diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index b3da32fc943f9..64d42bbd093d1 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -454,9 +454,9 @@ message Atom { BluetoothActivityInfo bluetooth_activity_info = 10007 [(module) = "framework"]; ProcessMemoryState process_memory_state = 10013 [(module) = "framework"]; SystemElapsedRealtime system_elapsed_realtime = 10014 [(module) = "framework"]; - SystemUptime system_uptime = 10015 [(module) = "framework", (module) = "statsdtest"]; + SystemUptime system_uptime = 10015 [(module) = "framework"]; CpuActiveTime cpu_active_time = 10016 [(module) = "framework", (module) = "statsdtest"]; - CpuClusterTime cpu_cluster_time = 10017 [(module) = "framework", (module) = "statsdtest"]; + CpuClusterTime cpu_cluster_time = 10017 [(module) = "framework"]; DiskSpace disk_space = 10018 [deprecated=true, (module) = "statsdtest"]; RemainingBatteryCapacity remaining_battery_capacity = 10019 [(module) = "framework"]; FullBatteryCapacity full_battery_capacity = 10020 [(module) = "framework"]; diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp index b809286da5f4e..e6144c52c4367 100644 --- a/cmds/statsd/tests/StatsLogProcessor_test.cpp +++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp @@ -1691,6 +1691,111 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { &buffer); } +TEST(StatsLogProcessorTest_mapIsolatedUidToHostUid, LogHostUid) { + int hostUid = 20; + int isolatedUid = 30; + uint64_t eventTimeNs = 12355; + int atomId = 89; + int field1 = 90; + int field2 = 28; + sp mockUidMap = makeMockUidMapForOneHost(hostUid, {isolatedUid}); + ConfigKey cfgKey; + StatsdConfig config = MakeConfig(false); + sp processor = + CreateStatsLogProcessor(1, 1, config, cfgKey, nullptr, 0, mockUidMap); + + shared_ptr logEvent = makeUidLogEvent(atomId, eventTimeNs, hostUid, field1, field2); + + processor->OnLogEvent(logEvent.get()); + + const vector* actualFieldValues = &logEvent->getValues(); + EXPECT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(field1, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(field2, actualFieldValues->at(2).mValue.int_value); +} + +TEST(StatsLogProcessorTest_mapIsolatedUidToHostUid, LogIsolatedUid) { + int hostUid = 20; + int isolatedUid = 30; + uint64_t eventTimeNs = 12355; + int atomId = 89; + int field1 = 90; + int field2 = 28; + sp mockUidMap = makeMockUidMapForOneHost(hostUid, {isolatedUid}); + ConfigKey cfgKey; + StatsdConfig config = MakeConfig(false); + sp processor = + CreateStatsLogProcessor(1, 1, config, cfgKey, nullptr, 0, mockUidMap); + + shared_ptr logEvent = + makeUidLogEvent(atomId, eventTimeNs, isolatedUid, field1, field2); + + processor->OnLogEvent(logEvent.get()); + + const vector* actualFieldValues = &logEvent->getValues(); + EXPECT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(field1, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(field2, actualFieldValues->at(2).mValue.int_value); +} + +TEST(StatsLogProcessorTest_mapIsolatedUidToHostUid, LogHostUidAttributionChain) { + int hostUid = 20; + int isolatedUid = 30; + uint64_t eventTimeNs = 12355; + int atomId = 89; + int field1 = 90; + int field2 = 28; + sp mockUidMap = makeMockUidMapForOneHost(hostUid, {isolatedUid}); + ConfigKey cfgKey; + StatsdConfig config = MakeConfig(false); + sp processor = + CreateStatsLogProcessor(1, 1, config, cfgKey, nullptr, 0, mockUidMap); + + shared_ptr logEvent = makeAttributionLogEvent(atomId, eventTimeNs, {hostUid, 200}, + {"tag1", "tag2"}, field1, field2); + + processor->OnLogEvent(logEvent.get()); + + const vector* actualFieldValues = &logEvent->getValues(); + EXPECT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(200, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(field1, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(field2, actualFieldValues->at(5).mValue.int_value); +} + +TEST(StatsLogProcessorTest_mapIsolatedUidToHostUid, LogIsolatedUidAttributionChain) { + int hostUid = 20; + int isolatedUid = 30; + uint64_t eventTimeNs = 12355; + int atomId = 89; + int field1 = 90; + int field2 = 28; + sp mockUidMap = makeMockUidMapForOneHost(hostUid, {isolatedUid}); + ConfigKey cfgKey; + StatsdConfig config = MakeConfig(false); + sp processor = + CreateStatsLogProcessor(1, 1, config, cfgKey, nullptr, 0, mockUidMap); + + shared_ptr logEvent = makeAttributionLogEvent(atomId, eventTimeNs, {isolatedUid, 200}, + {"tag1", "tag2"}, field1, field2); + + processor->OnLogEvent(logEvent.get()); + + const vector* actualFieldValues = &logEvent->getValues(); + EXPECT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(200, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(field1, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(field2, actualFieldValues->at(5).mValue.int_value); +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp index c10703c36b981..6bde79f52e33c 100644 --- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp +++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp @@ -13,13 +13,15 @@ // limitations under the License. #include "src/anomaly/AnomalyTracker.h" -#include "../metrics/metrics_test_helper.h" #include #include #include + #include +#include "tests/statsd_test_util.h" + using namespace testing; using android::sp; using std::set; diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp index c2cfb371d329e..a21dc8717776e 100644 --- a/cmds/statsd/tests/external/puller_util_test.cpp +++ b/cmds/statsd/tests/external/puller_util_test.cpp @@ -21,9 +21,9 @@ #include #include "../metrics/metrics_test_helper.h" +#include "FieldValue.h" #include "annotations.h" #include "stats_event.h" -#include "statslog_statsdtest.h" #include "tests/statsd_test_util.h" #ifdef __ANDROID__ @@ -33,207 +33,371 @@ namespace os { namespace statsd { using namespace testing; -using std::make_shared; using std::shared_ptr; using std::vector; -using testing::Contains; /* * Test merge isolated and host uid */ namespace { -int uidAtomTagId = util::CPU_CLUSTER_TIME; -const vector uidAdditiveFields = {3}; -int nonUidAtomTagId = util::SYSTEM_UPTIME; -int timestamp = 1234; -int isolatedUid = 30; -int isolatedAdditiveData = 31; -int isolatedNonAdditiveData = 32; -int hostUid = 20; -int hostAdditiveData = 21; -int hostNonAdditiveData = 22; +const int uidAtomTagId = 100; +const vector additiveFields = {3}; +const int nonUidAtomTagId = 200; +const int timestamp = 1234; +const int isolatedUid1 = 30; +const int isolatedUid2 = 40; +const int isolatedNonAdditiveData = 32; +const int isolatedAdditiveData = 31; +const int hostUid = 20; +const int hostNonAdditiveData = 22; +const int hostAdditiveData = 21; +const int attributionAtomTagId = 300; -void extractIntoVector(vector> events, - vector>& ret) { - ret.clear(); - status_t err; - for (const auto& event : events) { - vector vec; - vec.push_back(event->GetInt(1, &err)); - vec.push_back(event->GetInt(2, &err)); - vec.push_back(event->GetInt(3, &err)); - ret.push_back(vec); - } -} - -std::shared_ptr makeUidLogEvent(uint64_t timestampNs, int uid, int data1, int data2) { - AStatsEvent* statsEvent = AStatsEvent_obtain(); - AStatsEvent_setAtomId(statsEvent, uidAtomTagId); - AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); - - AStatsEvent_writeInt32(statsEvent, uid); - AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_IS_UID, true); - AStatsEvent_writeInt32(statsEvent, data1); - AStatsEvent_writeInt32(statsEvent, data2); - - std::shared_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); - parseStatsEventToLogEvent(statsEvent, logEvent.get()); - return logEvent; -} - -std::shared_ptr makeNonUidAtomLogEvent(uint64_t timestampNs, int data1) { - AStatsEvent* statsEvent = AStatsEvent_obtain(); - AStatsEvent_setAtomId(statsEvent, nonUidAtomTagId); - AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); - AStatsEvent_writeInt32(statsEvent, data1); - - std::shared_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); - parseStatsEventToLogEvent(statsEvent, logEvent.get()); - return logEvent; +sp makeMockUidMap() { + return makeMockUidMapForOneHost(hostUid, {isolatedUid1, isolatedUid2}); } } // anonymous namespace -TEST(puller_util, MergeNoDimension) { - vector> inputData; +TEST(PullerUtilTest, MergeNoDimension) { + vector> data = { + // 30->22->31 + makeUidLogEvent(uidAtomTagId, timestamp, isolatedUid1, hostNonAdditiveData, + isolatedAdditiveData), - // 30->22->31 - inputData.push_back( - makeUidLogEvent(timestamp, isolatedUid, hostNonAdditiveData, isolatedAdditiveData)); + // 20->22->21 + makeUidLogEvent(uidAtomTagId, timestamp, hostUid, hostNonAdditiveData, + hostAdditiveData), + }; - // 20->22->21 - inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData)); + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, uidAtomTagId, additiveFields); - sp uidMap = new NaggyMock(); - EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid)); - EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid))).WillRepeatedly(ReturnArg<0>()); - mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields); - - vector> actual; - extractIntoVector(inputData, actual); - vector expectedV1 = {20, 22, 52}; - EXPECT_EQ(1, (int)actual.size()); - EXPECT_THAT(actual, Contains(expectedV1)); + ASSERT_EQ(1, (int)data.size()); + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData + hostAdditiveData, actualFieldValues->at(2).mValue.int_value); } -TEST(puller_util, MergeWithDimension) { - vector> inputData; +TEST(PullerUtilTest, MergeWithDimension) { + vector> data = { + // 30->32->31 + makeUidLogEvent(uidAtomTagId, timestamp, isolatedUid1, isolatedNonAdditiveData, + isolatedAdditiveData), - // 30->32->31 - inputData.push_back( - makeUidLogEvent(timestamp, isolatedUid, isolatedNonAdditiveData, isolatedAdditiveData)); + // 20->32->21 + makeUidLogEvent(uidAtomTagId, timestamp, hostUid, isolatedNonAdditiveData, + hostAdditiveData), - // 20->32->21 - inputData.push_back( - makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, hostAdditiveData)); + // 20->22->21 + makeUidLogEvent(uidAtomTagId, timestamp, hostUid, hostNonAdditiveData, + hostAdditiveData), + }; - // 20->22->21 - inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData)); + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, uidAtomTagId, additiveFields); - sp uidMap = new NaggyMock(); - EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid)); - EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid))).WillRepeatedly(ReturnArg<0>()); - mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields); + ASSERT_EQ(2, (int)data.size()); - vector> actual; - extractIntoVector(inputData, actual); - vector expectedV1 = {20, 22, 21}; - vector expectedV2 = {20, 32, 52}; - EXPECT_EQ(2, (int)actual.size()); - EXPECT_THAT(actual, Contains(expectedV1)); - EXPECT_THAT(actual, Contains(expectedV2)); + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(2).mValue.int_value); + + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(hostAdditiveData + isolatedAdditiveData, actualFieldValues->at(2).mValue.int_value); } -TEST(puller_util, NoMergeHostUidOnly) { - vector> inputData; +TEST(PullerUtilTest, NoMergeHostUidOnly) { + vector> data = { + // 20->32->31 + makeUidLogEvent(uidAtomTagId, timestamp, hostUid, isolatedNonAdditiveData, + isolatedAdditiveData), + + // 20->22->21 + makeUidLogEvent(uidAtomTagId, timestamp, hostUid, hostNonAdditiveData, + hostAdditiveData), + }; + + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, uidAtomTagId, additiveFields); + + ASSERT_EQ(2, (int)data.size()); + + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(2).mValue.int_value); + + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData, actualFieldValues->at(2).mValue.int_value); +} + +TEST(PullerUtilTest, IsolatedUidOnly) { + vector> data = { + // 30->32->31 + makeUidLogEvent(uidAtomTagId, timestamp, isolatedUid1, isolatedNonAdditiveData, + isolatedAdditiveData), + + // 30->22->21 + makeUidLogEvent(uidAtomTagId, timestamp, isolatedUid1, hostNonAdditiveData, + hostAdditiveData), + }; + + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, uidAtomTagId, additiveFields); + + ASSERT_EQ(2, (int)data.size()); // 20->32->31 - inputData.push_back( - makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, isolatedAdditiveData)); + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(2).mValue.int_value); // 20->22->21 - inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData)); - - sp uidMap = new NaggyMock(); - EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid)); - EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid))).WillRepeatedly(ReturnArg<0>()); - mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields); - - // 20->32->31 - // 20->22->21 - vector> actual; - extractIntoVector(inputData, actual); - vector expectedV1 = {20, 32, 31}; - vector expectedV2 = {20, 22, 21}; - EXPECT_EQ(2, (int)actual.size()); - EXPECT_THAT(actual, Contains(expectedV1)); - EXPECT_THAT(actual, Contains(expectedV2)); + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData, actualFieldValues->at(2).mValue.int_value); } -TEST(puller_util, IsolatedUidOnly) { - vector> inputData; +TEST(PullerUtilTest, MultipleIsolatedUidToOneHostUid) { + vector> data = { + // 30->32->31 + makeUidLogEvent(uidAtomTagId, timestamp, isolatedUid1, isolatedNonAdditiveData, + isolatedAdditiveData), - // 30->32->31 - inputData.push_back( - makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, isolatedAdditiveData)); + // 31->32->21 + makeUidLogEvent(uidAtomTagId, timestamp, isolatedUid2, isolatedNonAdditiveData, + hostAdditiveData), - // 30->22->21 - inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData)); + // 20->32->21 + makeUidLogEvent(uidAtomTagId, timestamp, hostUid, isolatedNonAdditiveData, + hostAdditiveData), + }; - sp uidMap = new NaggyMock(); - EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid)); - EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid))).WillRepeatedly(ReturnArg<0>()); - mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields); + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, uidAtomTagId, additiveFields); - // 20->32->31 - // 20->22->21 - vector> actual; - extractIntoVector(inputData, actual); - vector expectedV1 = {20, 32, 31}; - vector expectedV2 = {20, 22, 21}; - EXPECT_EQ(2, (int)actual.size()); - EXPECT_THAT(actual, Contains(expectedV1)); - EXPECT_THAT(actual, Contains(expectedV2)); + ASSERT_EQ(1, (int)data.size()); + + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(3, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(1).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData + hostAdditiveData + hostAdditiveData, + actualFieldValues->at(2).mValue.int_value); } -TEST(puller_util, MultipleIsolatedUidToOneHostUid) { - vector> inputData; +TEST(PullerUtilTest, NoNeedToMerge) { + vector> data = { + // 32->31 + CreateTwoValueLogEvent(nonUidAtomTagId, timestamp, isolatedNonAdditiveData, + isolatedAdditiveData), - // 30->32->31 - inputData.push_back( - makeUidLogEvent(timestamp, isolatedUid, isolatedNonAdditiveData, isolatedAdditiveData)); + // 22->21 + CreateTwoValueLogEvent(nonUidAtomTagId, timestamp, hostNonAdditiveData, + hostAdditiveData), - // 31->32->21 - inputData.push_back( - makeUidLogEvent(timestamp, isolatedUid + 1, isolatedNonAdditiveData, hostAdditiveData)); + }; - // 20->32->21 - inputData.push_back( - makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, hostAdditiveData)); + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, nonUidAtomTagId, {} /*no additive fields*/); - sp uidMap = new NaggyMock(); - EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid)); - mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields); + ASSERT_EQ(2, (int)data.size()); - vector> actual; - extractIntoVector(inputData, actual); - vector expectedV1 = {20, 32, 73}; - EXPECT_EQ(1, (int)actual.size()); - EXPECT_THAT(actual, Contains(expectedV1)); + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(2, actualFieldValues->size()); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData, actualFieldValues->at(1).mValue.int_value); + + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(2, actualFieldValues->size()); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(1).mValue.int_value); } -TEST(puller_util, NoNeedToMerge) { - vector> inputData; +TEST(PullerUtilTest, MergeNoDimensionAttributionChain) { + vector> data = { + // 30->tag1->400->tag2->22->31 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {isolatedUid1, 400}, + {"tag1", "tag2"}, hostNonAdditiveData, isolatedAdditiveData), - // 32 - inputData.push_back(makeNonUidAtomLogEvent(timestamp, isolatedNonAdditiveData)); + // 20->tag1->400->tag2->22->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {hostUid, 400}, + {"tag1", "tag2"}, hostNonAdditiveData, hostAdditiveData), + }; - // 22 - inputData.push_back(makeNonUidAtomLogEvent(timestamp, hostNonAdditiveData)); + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, attributionAtomTagId, additiveFields); - sp uidMap = new NaggyMock(); - mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/); + ASSERT_EQ(1, (int)data.size()); + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(400, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData + hostAdditiveData, actualFieldValues->at(5).mValue.int_value); +} - EXPECT_EQ(2, (int)inputData.size()); +TEST(PullerUtilTest, MergeWithDimensionAttributionChain) { + vector> data = { + // 200->tag1->30->tag2->32->31 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {200, isolatedUid1}, + {"tag1", "tag2"}, isolatedNonAdditiveData, + isolatedAdditiveData), + + // 200->tag1->20->tag2->32->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {200, hostUid}, + {"tag1", "tag2"}, isolatedNonAdditiveData, hostAdditiveData), + + // 200->tag1->20->tag2->22->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {200, hostUid}, + {"tag1", "tag2"}, hostNonAdditiveData, hostAdditiveData), + }; + + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, attributionAtomTagId, additiveFields); + + ASSERT_EQ(2, (int)data.size()); + + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(200, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(hostUid, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(5).mValue.int_value); + + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(200, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(hostUid, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(hostAdditiveData + isolatedAdditiveData, actualFieldValues->at(5).mValue.int_value); +} + +TEST(PullerUtilTest, NoMergeHostUidOnlyAttributionChain) { + vector> data = { + // 20->tag1->400->tag2->32->31 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {hostUid, 400}, + {"tag1", "tag2"}, isolatedNonAdditiveData, + isolatedAdditiveData), + + // 20->tag1->400->tag2->22->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {hostUid, 400}, + {"tag1", "tag2"}, hostNonAdditiveData, hostAdditiveData), + }; + + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, attributionAtomTagId, additiveFields); + + ASSERT_EQ(2, (int)data.size()); + + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(400, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(5).mValue.int_value); + + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(400, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData, actualFieldValues->at(5).mValue.int_value); +} + +TEST(PullerUtilTest, IsolatedUidOnlyAttributionChain) { + vector> data = { + // 30->tag1->400->tag2->32->31 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {isolatedUid1, 400}, + {"tag1", "tag2"}, isolatedNonAdditiveData, + isolatedAdditiveData), + + // 30->tag1->400->tag2->22->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {isolatedUid1, 400}, + {"tag1", "tag2"}, hostNonAdditiveData, hostAdditiveData), + }; + + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, attributionAtomTagId, additiveFields); + + ASSERT_EQ(2, (int)data.size()); + + // 20->tag1->400->tag2->32->31 + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(400, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(hostNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(hostAdditiveData, actualFieldValues->at(5).mValue.int_value); + + // 20->tag1->400->tag2->22->21 + actualFieldValues = &data[1]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(400, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData, actualFieldValues->at(5).mValue.int_value); +} + +TEST(PullerUtilTest, MultipleIsolatedUidToOneHostUidAttributionChain) { + vector> data = { + // 30->tag1->400->tag2->32->31 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {isolatedUid1, 400}, + {"tag1", "tag2"}, isolatedNonAdditiveData, + isolatedAdditiveData), + + // 31->tag1->400->tag2->32->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {isolatedUid2, 400}, + {"tag1", "tag2"}, isolatedNonAdditiveData, hostAdditiveData), + + // 20->tag1->400->tag2->32->21 + makeAttributionLogEvent(attributionAtomTagId, timestamp, {hostUid, 400}, + {"tag1", "tag2"}, isolatedNonAdditiveData, hostAdditiveData), + }; + + sp uidMap = makeMockUidMap(); + mapAndMergeIsolatedUidsToHostUid(data, uidMap, attributionAtomTagId, additiveFields); + + ASSERT_EQ(1, (int)data.size()); + + const vector* actualFieldValues = &data[0]->getValues(); + ASSERT_EQ(6, actualFieldValues->size()); + EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value); + EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value); + EXPECT_EQ(400, actualFieldValues->at(2).mValue.int_value); + EXPECT_EQ("tag2", actualFieldValues->at(3).mValue.str_value); + EXPECT_EQ(isolatedNonAdditiveData, actualFieldValues->at(4).mValue.int_value); + EXPECT_EQ(isolatedAdditiveData + hostAdditiveData + hostAdditiveData, + actualFieldValues->at(5).mValue.int_value); } } // namespace statsd diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h index be410b10d43b2..46ef0f613bbea 100644 --- a/cmds/statsd/tests/metrics/metrics_test_helper.h +++ b/cmds/statsd/tests/metrics/metrics_test_helper.h @@ -48,12 +48,6 @@ public: void(const ConfigKey& configKey, wp provider)); }; -class MockUidMap : public UidMap { - public: - MOCK_CONST_METHOD1(getHostUidOrSelf, int(int uid)); - MOCK_CONST_METHOD1(getAppUid, std::set(const string& package)); -}; - HashableDimensionKey getMockedDimensionKey(int tagId, int key, std::string value); MetricDimensionKey getMockedMetricDimensionKey(int tagId, int key, std::string value); diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index 7216e1d8cc8e2..2315fd7243bc7 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -563,6 +563,48 @@ shared_ptr CreateNoValuesLogEvent(int atomId, int64_t eventTimeNs) { return logEvent; } +shared_ptr makeUidLogEvent(int atomId, int64_t eventTimeNs, int uid, int data1, + int data2) { + AStatsEvent* statsEvent = AStatsEvent_obtain(); + AStatsEvent_setAtomId(statsEvent, atomId); + AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); + + AStatsEvent_writeInt32(statsEvent, uid); + AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_IS_UID, true); + AStatsEvent_writeInt32(statsEvent, data1); + AStatsEvent_writeInt32(statsEvent, data2); + + shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); + parseStatsEventToLogEvent(statsEvent, logEvent.get()); + return logEvent; +} + +shared_ptr makeAttributionLogEvent(int atomId, int64_t eventTimeNs, + const vector& uids, const vector& tags, + int data1, int data2) { + AStatsEvent* statsEvent = AStatsEvent_obtain(); + AStatsEvent_setAtomId(statsEvent, atomId); + AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); + + writeAttribution(statsEvent, uids, tags); + AStatsEvent_writeInt32(statsEvent, data1); + AStatsEvent_writeInt32(statsEvent, data2); + + shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); + parseStatsEventToLogEvent(statsEvent, logEvent.get()); + return logEvent; +} + +sp makeMockUidMapForOneHost(int hostUid, const vector& isolatedUids) { + sp uidMap = new NaggyMock(); + EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(ReturnArg<0>()); + for (const int isolatedUid : isolatedUids) { + EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid)); + } + + return uidMap; +} + std::unique_ptr CreateScreenStateChangedEvent( uint64_t timestampNs, const android::view::DisplayStateEnum state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); @@ -878,8 +920,7 @@ std::unique_ptr CreateOverlayStateChangedEvent(int64_t timestampNs, co sp CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs, const StatsdConfig& config, const ConfigKey& key, const shared_ptr& puller, - const int32_t atomTag) { - sp uidMap = new UidMap(); + const int32_t atomTag, const sp uidMap) { sp pullerManager = new StatsPullerManager(); if (puller != nullptr) { pullerManager->RegisterPullAtomCallback(/*uid=*/0, atomTag, NS_PER_SEC, NS_PER_SEC * 10, {}, diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index 4d68ea2ecb792..dc012c5381ebe 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "frameworks/base/cmds/statsd/src/stats_log.pb.h" @@ -24,6 +25,7 @@ #include "src/StatsLogProcessor.h" #include "src/hash.h" #include "src/logd/LogEvent.h" +#include "src/packages/UidMap.h" #include "src/stats_log_util.h" #include "stats_event.h" #include "statslog_statsdtest.h" @@ -32,6 +34,7 @@ namespace android { namespace os { namespace statsd { +using namespace testing; using ::aidl::android::os::BnPullAtomCallback; using ::aidl::android::os::IPullAtomCallback; using ::aidl::android::os::IPullAtomResultReceiver; @@ -44,6 +47,12 @@ const int UID_PROCESS_STATE_ATOM_ID = util::UID_PROCESS_STATE_CHANGED; enum BucketSplitEvent { APP_UPGRADE, BOOT_COMPLETE }; +class MockUidMap : public UidMap { +public: + MOCK_METHOD(int, getHostUidOrSelf, (int uid), (const)); + MOCK_METHOD(std::set, getAppUid, (const string& package), (const)); +}; + // Converts a ProtoOutputStream to a StatsLogReport proto. StatsLogReport outputStreamToProto(ProtoOutputStream* proto); @@ -212,6 +221,15 @@ std::shared_ptr CreateNoValuesLogEvent(int atomId, int64_t eventTimeNs void CreateNoValuesLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs); +std::shared_ptr makeUidLogEvent(int atomId, int64_t eventTimeNs, int uid, int data1, + int data2); + +std::shared_ptr makeAttributionLogEvent(int atomId, int64_t eventTimeNs, + const vector& uids, + const vector& tags, int data1, int data2); + +sp makeMockUidMapForOneHost(int hostUid, const vector& isolatedUids); + // Create log event for screen state changed. std::unique_ptr CreateScreenStateChangedEvent( uint64_t timestampNs, const android::view::DisplayStateEnum state); @@ -293,7 +311,8 @@ std::unique_ptr CreateOverlayStateChangedEvent(int64_t timestampNs, co sp CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs, const StatsdConfig& config, const ConfigKey& key, const shared_ptr& puller = nullptr, - const int32_t atomTag = 0 /*for puller only*/); + const int32_t atomTag = 0 /*for puller only*/, + const sp = new UidMap()); // Util function to sort the log events by timestamp. void sortLogEventsByTimestamp(std::vector> *events);