1 // Copyright (C) 2020 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "src/external/StatsPullerManager.h" 16 17 #include <aidl/android/os/IPullAtomResultReceiver.h> 18 #include <aidl/android/util/StatsEventParcel.h> 19 #include <gmock/gmock.h> 20 #include <gtest/gtest.h> 21 22 #include "stats_event.h" 23 #include "tests/statsd_test_util.h" 24 25 using aidl::android::util::StatsEventParcel; 26 using ::ndk::SharedRefBase; 27 using std::make_shared; 28 using std::shared_ptr; 29 using std::vector; 30 31 namespace android { 32 namespace os { 33 namespace statsd { 34 35 namespace { 36 37 int pullTagId1 = 10101; 38 int pullTagId2 = 10102; 39 int uid1 = 9999; 40 int uid2 = 8888; 41 ConfigKey configKey(50, 12345); 42 ConfigKey badConfigKey(60, 54321); 43 int unregisteredUid = 98765; 44 int64_t coolDownNs = NS_PER_SEC; 45 int64_t timeoutNs = NS_PER_SEC / 2; 46 47 AStatsEvent* createSimpleEvent(int32_t atomId, int32_t value) { 48 AStatsEvent* event = AStatsEvent_obtain(); 49 AStatsEvent_setAtomId(event, atomId); 50 AStatsEvent_writeInt32(event, value); 51 AStatsEvent_build(event); 52 return event; 53 } 54 55 class FakePullAtomCallback : public BnPullAtomCallback { 56 public: 57 FakePullAtomCallback(int32_t uid) : mUid(uid){}; 58 Status onPullAtom(int atomTag, 59 const shared_ptr<IPullAtomResultReceiver>& resultReceiver) override { 60 vector<StatsEventParcel> parcels; 61 AStatsEvent* event = createSimpleEvent(atomTag, mUid); 62 size_t size; 63 uint8_t* buffer = AStatsEvent_getBuffer(event, &size); 64 65 StatsEventParcel p; 66 // vector.assign() creates a copy, but this is inevitable unless 67 // stats_event.h/c uses a vector as opposed to a buffer. 68 p.buffer.assign(buffer, buffer + size); 69 parcels.push_back(std::move(p)); 70 AStatsEvent_release(event); 71 resultReceiver->pullFinished(atomTag, /*success*/ true, parcels); 72 return Status::ok(); 73 } 74 int32_t mUid; 75 }; 76 77 class FakePullUidProvider : public PullUidProvider { 78 public: 79 vector<int32_t> getPullAtomUids(int atomId) override { 80 if (atomId == pullTagId1) { 81 return {uid2, uid1}; 82 } else if (atomId == pullTagId2) { 83 return {uid2}; 84 } 85 return {}; 86 } 87 }; 88 89 sp<StatsPullerManager> createPullerManagerAndRegister() { 90 sp<StatsPullerManager> pullerManager = new StatsPullerManager(); 91 shared_ptr<FakePullAtomCallback> cb1 = SharedRefBase::make<FakePullAtomCallback>(uid1); 92 pullerManager->RegisterPullAtomCallback(uid1, pullTagId1, coolDownNs, timeoutNs, {}, cb1); 93 shared_ptr<FakePullAtomCallback> cb2 = SharedRefBase::make<FakePullAtomCallback>(uid2); 94 pullerManager->RegisterPullAtomCallback(uid2, pullTagId1, coolDownNs, timeoutNs, {}, cb2); 95 pullerManager->RegisterPullAtomCallback(uid1, pullTagId2, coolDownNs, timeoutNs, {}, cb1); 96 return pullerManager; 97 } 98 } // anonymous namespace 99 100 TEST(StatsPullerManagerTest, TestPullInvalidUid) { 101 sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); 102 103 vector<shared_ptr<LogEvent>> data; 104 EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, /*timestamp =*/1, &data)); 105 } 106 107 TEST(StatsPullerManagerTest, TestPullChoosesCorrectUid) { 108 sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); 109 110 vector<shared_ptr<LogEvent>> data; 111 EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, /*timestamp =*/1, &data)); 112 ASSERT_EQ(data.size(), 1); 113 EXPECT_EQ(data[0]->GetTagId(), pullTagId1); 114 ASSERT_EQ(data[0]->getValues().size(), 1); 115 EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid1); 116 } 117 118 TEST(StatsPullerManagerTest, TestPullInvalidConfigKey) { 119 sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); 120 sp<FakePullUidProvider> uidProvider = new FakePullUidProvider(); 121 pullerManager->RegisterPullUidProvider(configKey, uidProvider); 122 123 vector<shared_ptr<LogEvent>> data; 124 EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, /*timestamp =*/1, &data)); 125 } 126 127 TEST(StatsPullerManagerTest, TestPullConfigKeyGood) { 128 sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); 129 sp<FakePullUidProvider> uidProvider = new FakePullUidProvider(); 130 pullerManager->RegisterPullUidProvider(configKey, uidProvider); 131 132 vector<shared_ptr<LogEvent>> data; 133 EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, /*timestamp =*/1, &data)); 134 EXPECT_EQ(data[0]->GetTagId(), pullTagId1); 135 ASSERT_EQ(data[0]->getValues().size(), 1); 136 EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid2); 137 } 138 139 TEST(StatsPullerManagerTest, TestPullConfigKeyNoPullerWithUid) { 140 sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); 141 sp<FakePullUidProvider> uidProvider = new FakePullUidProvider(); 142 pullerManager->RegisterPullUidProvider(configKey, uidProvider); 143 144 vector<shared_ptr<LogEvent>> data; 145 EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, /*timestamp =*/1, &data)); 146 } 147 148 } // namespace statsd 149 } // namespace os 150 } // namespace android