Merge "(Part 1) Use new socket schema with statsd tests" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-03-11 07:05:51 +00:00
committed by Android (Google) Code Review
22 changed files with 7290 additions and 7172 deletions

View File

@@ -328,4 +328,3 @@ void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, std::v
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -137,7 +137,9 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
simplePredicate, trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// This event is not accessed in this test besides dimensions which is why this is okay.
// This is technically an invalid LogEvent because we do not call parseBuffer.
LogEvent event(/*uid=*/0, /*pid=*/0);
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kNotMatched);
@@ -222,7 +224,9 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// This event is not accessed in this test besides dimensions which is why this is okay.
// This is technically an invalid LogEvent because we do not call parseBuffer.
LogEvent event(/*uid=*/0, /*pid=*/0);
// one matched start
vector<MatchingState> matcherState;
@@ -296,8 +300,8 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
std::vector<int> uids = {111, 222, 333};
LogEvent event(/*uid=*/-1, /*pid=*/-1);
makeWakeLockEvent(&event, /*atomId=*/1, /*timestamp=*/0, uids, "wl1", /*acquire=*/1);
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event1, /*atomId=*/1, /*timestamp=*/0, uids, "wl1", /*acquire=*/1);
// one matched start
vector<MatchingState> matcherState;
@@ -308,7 +312,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
changedCache);
if (position == Position::FIRST || position == Position::LAST) {
@@ -333,7 +337,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// another wake lock acquired by this uid
LogEvent event2(/*uid=*/-1, /*pid=*/-1);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event2, /*atomId=*/1, /*timestamp=*/0, uids, "wl2", /*acquire=*/1);
matcherState.clear();
matcherState.push_back(MatchingState::kMatched);
@@ -353,7 +357,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
// wake lock 1 release
LogEvent event3(/*uid=*/-1, /*pid=*/-1);
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids, "wl1", /*acquire=*/0);
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
@@ -372,7 +376,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
LogEvent event4(/*uid=*/-1, /*pid=*/-1);
LogEvent event4(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event4, /*atomId=*/1, /*timestamp=*/0, uids, "wl2", /*acquire=*/0);
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
@@ -399,246 +403,235 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
}
//TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
// std::vector<sp<ConditionTracker>> allConditions;
//
// SimplePredicate simplePredicate = getWakeLockHeldCondition(
// true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
// Position::ANY /* position */);
// string conditionName = "WL_HELD";
//
// unordered_map<int64_t, int> trackerNameIndexMap;
// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
//
// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
// 0 /*condition tracker index*/, simplePredicate,
// trackerNameIndexMap);
//
// EXPECT_FALSE(conditionTracker.isSliced());
//
// std::vector<int> uid_list1 = {111, 1111, 11111};
// string uid1_wl1 = "wl1_1";
// std::vector<int> uid_list2 = {222, 2222, 22222};
// string uid2_wl1 = "wl2_1";
//
// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
//
// // one matched start for uid1
// vector<MatchingState> matcherState;
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// vector<sp<ConditionTracker>> allPredicates;
// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
// vector<bool> changedCache(1, false);
//
// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
// changedCache);
//
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// EXPECT_TRUE(changedCache[0]);
//
// // Now test query
// ConditionKey queryKey;
// conditionCache[0] = ConditionState::kNotEvaluated;
//
// conditionTracker.isConditionMet(queryKey, allPredicates,
// true,
// conditionCache);
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
// // another wake lock acquired by this uid
// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
// matcherState.clear();
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_FALSE(changedCache[0]);
//
// // uid1 wake lock 1 release
// LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0); // now release it.
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
// changedCache);
// // nothing changes, because uid2 is still holding wl.
// EXPECT_FALSE(changedCache[0]);
//
// LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0); // now release it.
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
// EXPECT_TRUE(changedCache[0]);
//
// // query again
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// true,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
//}
//
//TEST(SimpleConditionTrackerTest, TestStopAll) {
// std::vector<sp<ConditionTracker>> allConditions;
// for (Position position :
// { Position::FIRST, Position::LAST }) {
// SimplePredicate simplePredicate = getWakeLockHeldCondition(
// true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
// position);
// string conditionName = "WL_HELD_BY_UID3";
//
// unordered_map<int64_t, int> trackerNameIndexMap;
// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
//
// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
// 0 /*condition tracker index*/, simplePredicate,
// trackerNameIndexMap);
//
// std::vector<int> uid_list1 = {111, 1111, 11111};
// std::vector<int> uid_list2 = {222, 2222, 22222};
//
// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event, uid_list1, "wl1", 1);
//
// // one matched start
// vector<MatchingState> matcherState;
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// vector<sp<ConditionTracker>> allPredicates;
// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
// vector<bool> changedCache(1, false);
//
// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
// changedCache);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(changedCache[0]);
// {
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// }
// }
//
// // Now test query
// const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
//
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
// // another wake lock acquired by uid2
// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
// matcherState.clear();
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
// changedCache);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uid_list1.size() + uid_list2.size(),
// conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(changedCache[0]);
// {
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// }
// }
//
//
// // TEST QUERY
// const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
//
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
//
// // stop all event
// LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
//
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_TRUE(changedCache[0]);
// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
// {
// if (position == Position::FIRST || position == Position::LAST) {
// EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(uid_list1.size() + uid_list2.size(),
// conditionTracker.getChangedToFalseDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// }
// }
//
// // TEST QUERY
// const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
//
// // TEST QUERY
// const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
// }
//}
TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
std::vector<sp<ConditionTracker>> allConditions;
SimplePredicate simplePredicate =
getWakeLockHeldCondition(true /*nesting*/, true /*default to false*/,
false /*slice output by uid*/, Position::ANY /* position */);
string conditionName = "WL_HELD";
unordered_map<int64_t, int> trackerNameIndexMap;
trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
std::vector<int> uids1 = {111, 1111, 11111};
string uid1_wl1 = "wl1_1";
std::vector<int> uids2 = {222, 2222, 22222};
string uid2_wl1 = "wl2_1";
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event1, /*atomId=*/1, /*timestamp=*/0, uids1, uid1_wl1, /*acquire=*/1);
// one matched start for uid1
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
vector<sp<ConditionTracker>> allPredicates;
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
EXPECT_TRUE(changedCache[0]);
// Now test query
ConditionKey queryKey;
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, true, conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// another wake lock acquired by this uid
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event2, /*atomId=*/1, /*timestamp=*/0, uids2, uid2_wl1, /*acquire=*/1);
matcherState.clear();
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_FALSE(changedCache[0]);
// uid1 wake lock 1 release
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids1, uid1_wl1,
/*release=*/0); // now release it.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
changedCache);
// nothing changes, because uid2 is still holding wl.
EXPECT_FALSE(changedCache[0]);
LogEvent event4(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event4, /*atomId=*/1, /*timestamp=*/0, uids2, uid2_wl1,
/*acquire=*/0); // now release it.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
EXPECT_TRUE(changedCache[0]);
// query again
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, true, conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
TEST(SimpleConditionTrackerTest, TestStopAll) {
std::vector<sp<ConditionTracker>> allConditions;
for (Position position : {Position::FIRST, Position::LAST}) {
SimplePredicate simplePredicate =
getWakeLockHeldCondition(true /*nesting*/, true /*default to false*/,
true /*output slice by uid*/, position);
string conditionName = "WL_HELD_BY_UID3";
unordered_map<int64_t, int> trackerNameIndexMap;
trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
std::vector<int> uids1 = {111, 1111, 11111};
std::vector<int> uids2 = {222, 2222, 22222};
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event1, /*atomId=*/1, /*timestamp=*/0, uids1, "wl1", /*acquire=*/1);
// one matched start
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
vector<sp<ConditionTracker>> allPredicates;
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
changedCache);
if (position == Position::FIRST || position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uids1.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
{
if (position == Position::FIRST || position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
} else {
EXPECT_EQ(uids1.size(),
conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
}
}
// Now test query
const auto queryKey = getWakeLockQueryKey(position, uids1, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// another wake lock acquired by uid2
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event2, /*atomId=*/1, /*timestamp=*/0, uids2, "wl2", /*acquire=*/1);
matcherState.clear();
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
changedCache);
if (position == Position::FIRST || position == Position::LAST) {
EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uids1.size() + uids2.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
{
if (position == Position::FIRST || position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
} else {
EXPECT_EQ(uids2.size(),
conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
}
}
// TEST QUERY
const auto queryKey2 = getWakeLockQueryKey(position, uids2, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// stop all event
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids2, "wl2", /*acquire=*/1);
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_TRUE(changedCache[0]);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
{
if (position == Position::FIRST || position == Position::LAST) {
EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
} else {
EXPECT_EQ(uids1.size() + uids2.size(),
conditionTracker.getChangedToFalseDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
}
}
// TEST QUERY
const auto queryKey3 = getWakeLockQueryKey(position, uids1, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
// TEST QUERY
const auto queryKey4 = getWakeLockQueryKey(position, uids2, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
}
} // namespace statsd
} // namespace os

View File

@@ -53,185 +53,192 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) {
} // namespace
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
// const int num_buckets = 1;
// const int threshold = 3;
// auto config = CreateStatsdConfig(num_buckets, threshold);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
// std::vector<AttributionNodeInternal> attributions2 = {
// CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
// std::vector<AttributionNodeInternal> attributions3 = {
// CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions4 = {
// CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions5 = {
// CreateAttribution(222, "GMSCoreModule1") };
//
// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)111));
// HashableDimensionKey whatKey1({fieldValue1});
// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
//
// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)222));
// HashableDimensionKey whatKey2({fieldValue2});
// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
//
// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// // Fired alarm and refractory period end timestamp updated.
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//}
//
//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
// const int num_buckets = 3;
// const int threshold = 3;
// auto config = CreateStatsdConfig(num_buckets, threshold);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
// std::vector<AttributionNodeInternal> attributions2 = {
// CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
// std::vector<AttributionNodeInternal> attributions3 = {
// CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions4 = {
// CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions5 = {
// CreateAttribution(222, "GMSCoreModule1") };
//
// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)111));
// HashableDimensionKey whatKey1({fieldValue1});
// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
//
// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)222));
// HashableDimensionKey whatKey2({fieldValue2});
// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
//
// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// // Fired alarm and refractory period end timestamp updated.
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//}
TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
const int num_buckets = 1;
const int threshold = 3;
auto config = CreateStatsdConfig(num_buckets, threshold);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
std::vector<int> attributionUids1 = {111};
std::vector<string> attributionTags1 = {"App1"};
std::vector<int> attributionUids2 = {111, 222};
std::vector<string> attributionTags2 = {"App1", "GMSCoreModule1"};
std::vector<int> attributionUids3 = {111, 333};
std::vector<string> attributionTags3 = {"App1", "App3"};
std::vector<int> attributionUids4 = {222, 333};
std::vector<string> attributionTags4 = {"GMSCoreModule1", "App3"};
std::vector<int> attributionUids5 = {222};
std::vector<string> attributionTags5 = {"GMSCoreModule1"};
FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids4, attributionTags4,
"wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 3, attributionUids2, attributionTags2,
"wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 3, attributionUids5, attributionTags5,
"wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 4, attributionUids3, attributionTags3,
"wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 4, attributionUids5, attributionTags5,
"wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Fired alarm and refractory period end timestamp updated.
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 5, attributionUids1, attributionTags1,
"wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 100, attributionUids1, attributionTags1,
"wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1, attributionUids4,
attributionTags4, "wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2, attributionUids5,
attributionTags5, "wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 3, attributionUids5,
attributionTags5, "wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 4, attributionUids5,
attributionTags5, "wl2");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
}
TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
const int num_buckets = 3;
const int threshold = 3;
auto config = CreateStatsdConfig(num_buckets, threshold);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
std::vector<int> attributionUids1 = {111};
std::vector<string> attributionTags1 = {"App1"};
std::vector<int> attributionUids2 = {111, 222};
std::vector<string> attributionTags2 = {"App1", "GMSCoreModule1"};
FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 3, attributionUids2, attributionTags2,
"wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Fired alarm and refractory period end timestamp updated.
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 4, attributionUids1, attributionTags1,
"wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2, attributionUids2,
attributionTags2, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs + 1, attributionUids2,
attributionTags2, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs + 2, attributionUids2,
attributionTags2, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -69,414 +69,432 @@ StatsdConfig CreateStatsdConfig(int num_buckets,
return config;
}
} // namespace
std::vector<int> attributionUids1 = {111, 222};
std::vector<string> attributionTags1 = {"App1", "GMSCoreModule1"};
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1")};
std::vector<int> attributionUids2 = {111, 222};
std::vector<string> attributionTags2 = {"App2", "GMSCoreModule1"};
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App2"),
CreateAttribution(222, "GMSCoreModule1")};
std::vector<int> attributionUids3 = {222};
std::vector<string> attributionTags3 = {"GMSCoreModule1"};
std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1")};
MetricDimensionKey dimensionKey(
HashableDimensionKey({FieldValue(Field(android::util::WAKELOCK_STATE_CHANGED,
(int32_t)0x02010101), Value((int32_t)111))}),
DEFAULT_DIMENSION_KEY);
MetricDimensionKey dimensionKey1(
HashableDimensionKey({FieldValue(Field(android::util::WAKELOCK_STATE_CHANGED,
(int32_t)0x02010101),
Value((int32_t)111))}),
DEFAULT_DIMENSION_KEY);
MetricDimensionKey dimensionKey2(
HashableDimensionKey({FieldValue(Field(android::util::WAKELOCK_STATE_CHANGED,
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
// const int num_buckets = 1;
// const uint64_t threshold_ns = NS_PER_SEC;
// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// auto screen_on_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
// auto screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
// processor->OnLogEvent(screen_on_event.get());
// processor->OnLogEvent(screen_off_event.get());
//
// // Acquire wakelock wl1.
// auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
// auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock wl1 within bucket #0.
// acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock wl1. One anomaly detected.
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock wl1.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
// processor->OnLogEvent(acquire_event.get());
// // Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
// // end of the refractory period.
// const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
// (uint32_t)alarmFiredTimestampSec0);
//
// // Anomaly alarm fired.
// auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
// static_cast<uint32_t>(alarmFiredTimestampSec0));
// EXPECT_EQ(1u, alarmSet.size());
// processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock wl1.
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Within refractory period. No more anomaly detected.
// EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock wl1.
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11);
// processor->OnLogEvent(acquire_event.get());
// const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
// (uint64_t)alarmFiredTimestampSec1);
//
// // Release wakelock wl1.
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
// static_cast<uint32_t>(alarmFiredTimestampSec1));
// EXPECT_EQ(0u, alarmSet.size());
//
// // Acquire wakelock wl1 near the end of bucket #0.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// // Release the event at early bucket #1.
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Anomaly detected when stopping the alarm. The refractory period does not change.
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Condition changes to false.
// screen_on_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs + 20);
// processor->OnLogEvent(screen_on_event.get());
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
// processor->OnLogEvent(acquire_event.get());
// // The condition is false. Do not start the alarm.
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Condition turns true.
// screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
// processor->OnLogEvent(screen_off_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// // Condition turns to false.
// screen_on_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
// processor->OnLogEvent(screen_on_event.get());
// // Condition turns to false. Cancelled the alarm.
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Detected one anomaly.
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Condition turns to true again.
// screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
// processor->OnLogEvent(screen_off_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
//}
//
//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
// const int num_buckets = 3;
// const uint64_t threshold_ns = NS_PER_SEC;
// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// auto screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
// processor->OnLogEvent(screen_off_event.get());
//
// // Acquire wakelock "wc1" in bucket #0.
// auto acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock "wc1" in bucket #0.
// auto release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock "wc1" in bucket #1.
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock "wc2" in bucket #2.
// acquire_event = CreateAcquireWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
// anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// // Release wakelock "wc2" in bucket #2.
// release_event = CreateReleaseWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// // Acquire wakelock "wc1" in bucket #2.
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock "wc1" in bucket #2.
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec +
// (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
// processor->OnLogEvent(acquire_event.get());
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey2));
//
// release_event = CreateReleaseWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
// processor->OnLogEvent(release_event.get());
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// // The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
// EXPECT_EQ(refractory_period_sec +
// (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//}
//
//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
// const int num_buckets = 2;
// const uint64_t threshold_ns = 3 * NS_PER_SEC;
// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
// int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
//
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
// config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// auto screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
// processor->OnLogEvent(screen_off_event.get());
//
// // Acquire wakelock "wc1" in bucket #0.
// auto acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire the wakelock "wc1" again.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
// processor->OnLogEvent(acquire_event.get());
// // The alarm does not change.
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Anomaly alarm fired late.
// const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
// auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
// static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
// EXPECT_EQ(1u, alarmSet.size());
// processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// auto release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Within the refractory period. No anomaly.
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // A new wakelock, but still within refractory period.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
// // Still in the refractory period. No anomaly.
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//}
} // namespace
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const int num_buckets = 1;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
auto screen_on_event = CreateScreenStateChangedEvent(
bucketStartTimeNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
auto screen_off_event = CreateScreenStateChangedEvent(
bucketStartTimeNs + 10, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_on_event.get());
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock wl1.
auto acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 11, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 101, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock wl1 within bucket #0.
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 110, attributionUids2,
attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock wl1. One anomaly detected.
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + NS_PER_SEC + 109,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock wl1.
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + NS_PER_SEC + 112,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
// Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
// end of the refractory period.
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
(uint32_t)alarmFiredTimestampSec0);
// Anomaly alarm fired.
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec0));
EXPECT_EQ(1u, alarmSet.size());
processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock wl1.
release_event =
CreateReleaseWakelockEvent(alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Within refractory period. No more anomaly detected.
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock wl1.
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
(uint64_t)alarmFiredTimestampSec1);
// Release wakelock wl1.
release_event =
CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec1));
EXPECT_EQ(0u, alarmSet.size());
// Acquire wakelock wl1 near the end of bucket #0.
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 2,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Release the event at early bucket #1.
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Anomaly detected when stopping the alarm. The refractory period does not change.
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Condition changes to false.
screen_on_event =
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 20,
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
processor->OnLogEvent(screen_on_event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 30,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
// The condition is false. Do not start the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Condition turns true.
screen_off_event =
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Condition turns to false.
screen_on_event =
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1,
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
processor->OnLogEvent(screen_on_event.get());
// Condition turns to false. Cancelled the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Detected one anomaly.
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Condition turns to true again.
screen_off_event =
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
release_event =
CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
const int num_buckets = 3;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
auto screen_off_event = CreateScreenStateChangedEvent(
bucketStartTimeNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #0.
auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc1" in bucket #1.
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + 100,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc2" in bucket #2.
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Release wakelock "wc2" in bucket #2.
release_event =
CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Acquire wakelock "wc1" in bucket #2.
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #2.
release_event =
CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec +
(int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) /
NS_PER_SEC +
1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4,
attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 2,
attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(release_event.get());
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 6,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
EXPECT_EQ(refractory_period_sec + (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC +
1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const int num_buckets = 2;
const uint64_t threshold_ns = 3 * NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
auto screen_off_event = CreateScreenStateChangedEvent(
bucketStartTimeNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire the wakelock "wc1" again.
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
// The alarm does not change.
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Anomaly alarm fired late.
const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
EXPECT_EQ(1u, alarmSet.size());
processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Within the refractory period. No anomaly.
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// A new wakelock, but still within refractory period.
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
attributionUids1, attributionTags1, "wl1");
// Still in the refractory period. No anomaly.
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
release_event =
CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
acquire_event =
CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -53,367 +53,318 @@ StatsdConfig CreateStatsdConfig(const Position position) {
return config;
}
// GMS core node is in the middle.
std::vector<int> attributionUids1 = {111, 222, 333};
std::vector<string> attributionTags1 = {"App1", "GMSCoreModule1", "App3"};
// GMS core node is the last one.
std::vector<int> attributionUids2 = {111, 333, 222};
std::vector<string> attributionTags2 = {"App1", "App3", "GMSCoreModule1"};
// GMS core node is the first one.
std::vector<int> attributionUids3 = {222, 333};
std::vector<string> attributionTags3 = {"GMSCoreModule1", "App3"};
// Single GMS core node.
std::vector<int> attributionUids4 = {222};
std::vector<string> attributionTags4 = {"GMSCoreModule1"};
// GMS core has another uid.
std::vector<int> attributionUids5 = {111, 444, 333};
std::vector<string> attributionTags5 = {"App1", "GMSCoreModule2", "App3"};
// Multiple GMS core nodes.
std::vector<int> attributionUids6 = {444, 222};
std::vector<string> attributionTags6 = {"GMSCoreModule2", "GMSCoreModule1"};
// No GMS core nodes
std::vector<int> attributionUids7 = {111, 333};
std::vector<string> attributionTags7 = {"App1", "App3"};
std::vector<int> attributionUids8 = {111};
std::vector<string> attributionTags8 = {"App1"};
// GMS core node with isolated uid.
const int isolatedUid = 666;
std::vector<int> attributionUids9 = {isolatedUid};
std::vector<string> attributionTags9 = {"GMSCoreModule3"};
std::vector<int> attributionUids10 = {isolatedUid};
std::vector<string> attributionTags10 = {"GMSCoreModule1"};
} // namespace
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
// auto config = CreateStatsdConfig(Position::FIRST);
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// // Here it assumes that GMS core has two uids.
// processor->getUidMap()->updateMap(
// 1, {222, 444, 111, 333}, {1, 1, 2, 2},
// {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
// {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
// String16("APP3")},
// {String16(""), String16(""), String16(""), String16("")});
//
// // GMS core node is in the middle.
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
// CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // GMS core node is the last one.
// std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core node is the first one.
// std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // Single GMS core node.
// std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core has another uid.
// std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
// CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(333, "App3")};
//
// // Multiple GMS core nodes.
// std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // No GMS core nodes.
// std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
//
// // GMS core node with isolated uid.
// const int isolatedUid = 666;
// std::vector<AttributionNodeInternal> attributions9 = {
// CreateAttribution(isolatedUid, "GMSCoreModule3")};
//
// std::vector<std::unique_ptr<LogEvent>> events;
// // Events 1~4 are in the 1st bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 200));
// events.push_back(CreateAcquireWakelockEvent(
// attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
//
// // Events 5~8 are in the 3rd bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateAcquireWakelockEvent(
// attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
//
// StatsLogReport::CountMetricDataWrapper countMetrics;
// sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
// EXPECT_EQ(countMetrics.data_size(), 4);
//
// auto data = countMetrics.data(0);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
// "App1");
// EXPECT_EQ(data.bucket_info_size(), 2);
// EXPECT_EQ(data.bucket_info(0).count(), 2);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).count(), 1);
// EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
//
// data = countMetrics.data(1);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
// "GMSCoreModule1");
// EXPECT_EQ(data.bucket_info_size(), 2);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).count(), 1);
// EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
//
// data = countMetrics.data(2);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
// "GMSCoreModule3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
//
// data = countMetrics.data(3);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
// "GMSCoreModule2");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
//}
//
//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
// auto config = CreateStatsdConfig(Position::ALL);
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// // Here it assumes that GMS core has two uids.
// processor->getUidMap()->updateMap(
// 1, {222, 444, 111, 333}, {1, 1, 2, 2},
// {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
// {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
// String16("APP3")},
// {String16(""), String16(""), String16(""), String16("")});
//
// // GMS core node is in the middle.
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
// CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // GMS core node is the last one.
// std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core node is the first one.
// std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // Single GMS core node.
// std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core has another uid.
// std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
// CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(333, "App3")};
//
// // Multiple GMS core nodes.
// std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // No GMS core nodes.
// std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
//
// // GMS core node with isolated uid.
// const int isolatedUid = 666;
// std::vector<AttributionNodeInternal> attributions9 = {
// CreateAttribution(isolatedUid, "GMSCoreModule1")};
//
// std::vector<std::unique_ptr<LogEvent>> events;
// // Events 1~4 are in the 1st bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 200));
// events.push_back(CreateAcquireWakelockEvent(
// attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
//
// // Events 5~8 are in the 3rd bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateAcquireWakelockEvent(
// attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
//
// StatsLogReport::CountMetricDataWrapper countMetrics;
// sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
// EXPECT_EQ(countMetrics.data_size(), 6);
//
// auto data = countMetrics.data(0);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// EXPECT_EQ(2, data.bucket_info_size());
// EXPECT_EQ(1, data.bucket_info(0).count());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(1).count());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
// data.bucket_info(1).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(1);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
//
// data = countMetrics.data(2);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(3);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// ValidateUidDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(4);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// ValidateUidDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(5);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
// ValidateUidDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//}
TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
auto config = CreateStatsdConfig(Position::FIRST);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")},
{String16(""), String16(""), String16(""), String16("")});
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1,
attributionTags1, "wl1"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 200, attributionUids2,
attributionTags2, "wl1"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
attributionUids3, attributionTags3, "wl1"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs, attributionUids4,
attributionTags4, "wl1"));
// Events 5~8 are in the 3rd bucket.
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
attributionUids5, attributionTags5, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 100,
attributionUids6, attributionTags6, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - 2,
attributionUids7, attributionTags7, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs,
attributionUids8, attributionTags8, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs + 1,
attributionUids9, attributionTags9, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs + 100,
attributionUids9, attributionTags9, "wl2"));
events.push_back(CreateIsolatedUidChangedEvent(bucketStartTimeNs + 3 * bucketSizeNs - 1, 222,
isolatedUid, true /*is_create*/));
events.push_back(CreateIsolatedUidChangedEvent(bucketStartTimeNs + 3 * bucketSizeNs + 10, 222,
isolatedUid, false /*is_create*/));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
StatsLogReport::CountMetricDataWrapper countMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
EXPECT_EQ(countMetrics.data_size(), 4);
auto data = countMetrics.data(0);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
EXPECT_EQ(data.bucket_info_size(), 2);
EXPECT_EQ(data.bucket_info(0).count(), 2);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).count(), 1);
EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
data = countMetrics.data(1);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 2);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).count(), 1);
EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
data = countMetrics.data(2);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
bucketStartTimeNs + 3 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
data = countMetrics.data(3);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
}
TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
auto config = CreateStatsdConfig(Position::ALL);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")},
{String16(""), String16(""), String16(""), String16("")});
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1,
attributionTags1, "wl1"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 200, attributionUids2,
attributionTags2, "wl1"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
attributionUids3, attributionTags3, "wl1"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs, attributionUids4,
attributionTags4, "wl1"));
// Events 5~8 are in the 3rd bucket.
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
attributionUids5, attributionTags5, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 100,
attributionUids6, attributionTags6, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - 2,
attributionUids7, attributionTags7, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs,
attributionUids8, attributionTags8, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs + 1,
attributionUids10, attributionTags10, "wl2"));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs + 100,
attributionUids10, attributionTags10, "wl2"));
events.push_back(CreateIsolatedUidChangedEvent(bucketStartTimeNs + 3 * bucketSizeNs - 1, 222,
isolatedUid, true /*is_create*/));
events.push_back(CreateIsolatedUidChangedEvent(bucketStartTimeNs + 3 * bucketSizeNs + 10, 222,
isolatedUid, false /*is_create*/));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
StatsLogReport::CountMetricDataWrapper countMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
EXPECT_EQ(countMetrics.data_size(), 6);
auto data = countMetrics.data(0);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(2, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(1).count());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
data = countMetrics.data(2);
ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
android::util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
ValidateUidDimension(data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
ValidateUidDimension(data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(5);
ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
android::util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
ValidateUidDimension(data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -56,54 +56,54 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) {
} // namespace
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(ConfigTtlE2eTest, TestCountMetric) {
// const int num_buckets = 1;
// const int threshold = 3;
// auto config = CreateStatsdConfig(num_buckets, threshold);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
//
// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)111));
// HashableDimensionKey whatKey1({fieldValue1});
// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
//
// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)222));
// HashableDimensionKey whatKey2({fieldValue2});
// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
//
// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
//
// event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
//
// event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
//
// EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
// processor->mMetricsManagers.begin()->second->getTtlEndNs());
//
// // Clear the data stored on disk as a result of the ttl.
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
// ADB_DUMP, FAST, &buffer);
//}
TEST(ConfigTtlE2eTest, TestCountMetric) {
const int num_buckets = 1;
const int threshold = 3;
auto config = CreateStatsdConfig(num_buckets, threshold);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
std::vector<int> attributionUids1 = {111};
std::vector<string> attributionTags1 = {"App1"};
FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2, attributionUids1,
attributionTags1, "wl2");
processor->OnLogEvent(event.get());
event = CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * bucketSizeNs + 2, attributionUids1,
attributionTags1, "wl1");
processor->OnLogEvent(event.get());
EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
processor->mMetricsManagers.begin()->second->getTtlEndNs());
// Clear the data stored on disk as a result of the ttl.
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
ADB_DUMP, FAST, &buffer);
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -65,482 +65,465 @@ StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,
} // namespaces
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the gauge metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& nextPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// processor->informPullAlarmFired(nextPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + bucketSizeNs + 10);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + bucketSizeNs + 100);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(nextPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
// nextPullTimeNs);
//
// processor->informPullAlarmFired(nextPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
//
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 3 * bucketSizeNs + 2);
// processor->OnLogEvent(screenOnEvent.get());
//
// processor->informPullAlarmFired(nextPullTimeNs + 3);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 5 * bucketSizeNs + 1);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(nextPullTimeNs + 2);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
//
// processor->informPullAlarmFired(nextPullTimeNs + 2);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(6, data.bucket_info_size());
//
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
// data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(2).atom_size());
// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
// data.bucket_info(2).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(3).atom_size());
// EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
// data.bucket_info(3).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(4).atom_size());
// EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
// data.bucket_info(4).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(5).atom_size());
// EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
// data.bucket_info(5).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
//}
//
//TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
// auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + bucketSizeNs + 10);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + bucketSizeNs + 100);
// processor->OnLogEvent(screenOffEvent.get());
//
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 3 * bucketSizeNs + 2);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 5 * bucketSizeNs + 1);
// processor->OnLogEvent(screenOffEvent.get());
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 5 * bucketSizeNs + 3);
// processor->OnLogEvent(screenOnEvent.get());
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 5 * bucketSizeNs + 10);
// processor->OnLogEvent(screenOffEvent.get());
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
// data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(2, data.bucket_info(2).atom_size());
// EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
// data.bucket_info(2).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
// data.bucket_info(2).elapsed_timestamp_nanos(1));
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
// EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
//}
//
//
//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the gauge metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& nextPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + bucketSizeNs + 10);
// processor->OnLogEvent(screenOnEvent.get());
//
// // Pulling alarm arrives one bucket size late.
// processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 3 * bucketSizeNs + 11);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives more than one bucket size late.
// processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
// data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(2).atom_size());
// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
// data.bucket_info(2).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
//}
//
//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
//
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
// *config.add_atom_matcher() = batterySaverStartMatcher;
// const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
// auto metric_activation = config.add_metric_activation();
// metric_activation->set_metric_id(metricId);
// metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
// auto event_activation = metric_activation->add_event_activation();
// event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
// event_activation->set_ttl_seconds(ttlNs / 1000000000);
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // When creating the config, the gauge metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& nextPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// // Event should not be kept.
// processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // Activate the metric. A pull occurs upon activation.
// const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
// auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
// processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // This event should be kept. 2 total.
// processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
// nextPullTimeNs);
//
// // This event should be kept. 3 total.
// processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
//
// // Create random event to deactivate metric.
// auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
// processor->OnLogEvent(deactivationEvent.get());
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // Event should not be kept. 3 total.
// processor->informPullAlarmFired(nextPullTimeNs + 3);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
//
// processor->informPullAlarmFired(nextPullTimeNs + 2);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 0);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// auto bucketInfo = data.bucket_info(0);
// EXPECT_EQ(1, bucketInfo.atom_size());
// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
// EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
//
// bucketInfo = data.bucket_info(1);
// EXPECT_EQ(1, bucketInfo.atom_size());
// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
//
// bucketInfo = data.bucket_info(2);
// EXPECT_EQ(1, bucketInfo.atom_size());
// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
// EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
// bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
// bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
//}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor =
CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the gauge metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& nextPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
auto screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives on time and reset the sequential pulling alarm.
processor->informPullAlarmFired(nextPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
auto screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 100,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(nextPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
processor->informPullAlarmFired(nextPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 2,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
processor->informPullAlarmFired(nextPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 1,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(nextPullTimeNs + 2);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
processor->informPullAlarmFired(nextPullTimeNs + 2);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(6, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(2).atom_size());
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, data.bucket_info(2).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(3).atom_size());
EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1, data.bucket_info(3).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(4).atom_size());
EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1, data.bucket_info(4).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(5).atom_size());
EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2, data.bucket_info(5).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor =
CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
auto screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 100,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 2,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 1,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 3,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 10,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100, data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(2, data.bucket_info(2).atom_size());
EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1, data.bucket_info(2).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10, data.bucket_info(2).elapsed_timestamp_nanos(1));
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor =
CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the gauge metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& nextPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
auto screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
// Pulling alarm arrives one bucket size late.
processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 11,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives more than one bucket size late.
processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(2).atom_size());
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12, data.bucket_info(2).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
*config.add_atom_matcher() = batterySaverStartMatcher;
const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
auto metric_activation = config.add_metric_activation();
metric_activation->set_metric_id(metricId);
metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
auto event_activation = metric_activation->add_event_activation();
event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
event_activation->set_ttl_seconds(ttlNs / 1000000000);
ConfigKey cfgKey;
auto processor =
CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// When creating the config, the gauge metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& nextPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
// Pulling alarm arrives on time and reset the sequential pulling alarm.
// Event should not be kept.
processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// Activate the metric. A pull occurs upon activation.
const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// This event should be kept. 2 total.
processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
// This event should be kept. 3 total.
processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
// Create random event to deactivate metric.
auto deactivationEvent = CreateScreenBrightnessChangedEvent(activationNs + ttlNs + 1, 50);
processor->OnLogEvent(deactivationEvent.get());
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// Event should not be kept. 3 total.
processor->informPullAlarmFired(nextPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
processor->informPullAlarmFired(nextPullTimeNs + 2);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 0);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
auto bucketInfo = data.bucket_info(0);
EXPECT_EQ(1, bucketInfo.atom_size());
EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
bucketInfo = data.bucket_info(1);
EXPECT_EQ(1, bucketInfo.atom_size());
EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
bucketInfo = data.bucket_info(2);
EXPECT_EQ(1, bucketInfo.atom_size());
EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
bucketInfo.end_bucket_elapsed_nanos());
EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);

View File

@@ -14,12 +14,13 @@
#include <gtest/gtest.h>
#include <vector>
#include "src/StatsLogProcessor.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
#include "tests/statsd_test_util.h"
#include <vector>
namespace android {
namespace os {
namespace statsd {
@@ -68,221 +69,227 @@ StatsdConfig CreateStatsdConfigForPushedEvent(const GaugeMetric::SamplingType sa
return config;
}
// TODO(b/149590301): Update this helper to use new socket schema.
//std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
// const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
// const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
// int64_t activity_start_msec, uint64_t timestampNs) {
// auto logEvent = std::make_unique<LogEvent>(
// android::util::APP_START_OCCURRED, timestampNs);
// logEvent->write(uid);
// logEvent->write(pkg_name);
// logEvent->write(type);
// logEvent->write(activity_name);
// logEvent->write(calling_pkg_name);
// logEvent->write(is_instant_app);
// logEvent->write(activity_start_msec);
// logEvent->init();
// return logEvent;
//}
std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
uint64_t timestampNs, const int uid, const string& pkg_name,
AppStartOccurred::TransitionType type, const string& activity_name,
const string& calling_pkg_name, const bool is_instant_app, int64_t activity_start_msec) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::APP_START_OCCURRED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
AStatsEvent_writeString(statsEvent, pkg_name.c_str());
AStatsEvent_writeInt32(statsEvent, type);
AStatsEvent_writeString(statsEvent, activity_name.c_str());
AStatsEvent_writeString(statsEvent, calling_pkg_name.c_str());
AStatsEvent_writeInt32(statsEvent, is_instant_app);
AStatsEvent_writeInt32(statsEvent, activity_start_msec);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
} // namespace
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
// for (const auto& sampling_type :
// { GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
// auto config = CreateStatsdConfigForPushedEvent(sampling_type);
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(
// bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// int appUid1 = 123;
// int appUid2 = 456;
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
// events.push_back(CreateMoveToForegroundEvent(
// appUid1, bucketStartTimeNs + bucketSizeNs + 250));
// events.push_back(CreateMoveToBackgroundEvent(
// appUid1, bucketStartTimeNs + bucketSizeNs + 350));
// events.push_back(CreateMoveToForegroundEvent(
// appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
//
//
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
// true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
// true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
// true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
// true /*is_instant_app*/, 104 /*activity_start_msec*/,
// bucketStartTimeNs + bucketSizeNs + 30));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
// true /*is_instant_app*/, 105 /*activity_start_msec*/,
// bucketStartTimeNs + 2 * bucketSizeNs));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
// false /*is_instant_app*/, 106 /*activity_start_msec*/,
// bucketStartTimeNs + 2 * bucketSizeNs + 10));
//
// events.push_back(CreateMoveToBackgroundEvent(
// appUid2, bucketStartTimeNs + bucketSizeNs + 10));
// events.push_back(CreateAppStartOccurredEvent(
// appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
// true /*is_instant_app*/, 201 /*activity_start_msec*/,
// bucketStartTimeNs + 2 * bucketSizeNs + 10));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_EQ(2, gaugeMetrics.data_size());
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* uid field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
// EXPECT_EQ(3, data.bucket_info_size());
// if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
// EXPECT_EQ(2, data.bucket_info(0).atom_size());
// EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::HOT,
// data.bucket_info(0).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name2",
// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(102L,
// data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
// EXPECT_EQ(AppStartOccurred::COLD,
// data.bucket_info(0).atom(1).app_start_occurred().type());
// EXPECT_EQ("activity_name3",
// data.bucket_info(0).atom(1).app_start_occurred().activity_name());
// EXPECT_EQ(103L,
// data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::WARM,
// data.bucket_info(1).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name4",
// data.bucket_info(1).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(104L,
// data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(2, data.bucket_info(2).atom_size());
// EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::COLD,
// data.bucket_info(2).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name5",
// data.bucket_info(2).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(105L,
// data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
// EXPECT_EQ(AppStartOccurred::HOT,
// data.bucket_info(2).atom(1).app_start_occurred().type());
// EXPECT_EQ("activity_name6",
// data.bucket_info(2).atom(1).app_start_occurred().activity_name());
// EXPECT_EQ(106L,
// data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
// } else {
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::HOT,
// data.bucket_info(0).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name2",
// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(102L,
// data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::WARM,
// data.bucket_info(1).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name4",
// data.bucket_info(1).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(104L,
// data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(1, data.bucket_info(2).atom_size());
// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::COLD,
// data.bucket_info(2).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name5",
// data.bucket_info(2).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(105L,
// data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
// }
//
// data = gaugeMetrics.data(1);
//
// EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// EXPECT_EQ(1 /* uid field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
// EXPECT_EQ(1, data.bucket_info_size());
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name7",
// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
// }
//}
TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
for (const auto& sampling_type :
{GaugeMetric::FIRST_N_SAMPLES, GaugeMetric::RANDOM_ONE_SAMPLE}) {
auto config = CreateStatsdConfigForPushedEvent(sampling_type);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor =
CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
int appUid1 = 123;
int appUid2 = 456;
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(CreateMoveToBackgroundEvent(bucketStartTimeNs + 15, appUid1));
events.push_back(
CreateMoveToForegroundEvent(bucketStartTimeNs + bucketSizeNs + 250, appUid1));
events.push_back(
CreateMoveToBackgroundEvent(bucketStartTimeNs + bucketSizeNs + 350, appUid1));
events.push_back(
CreateMoveToForegroundEvent(bucketStartTimeNs + 2 * bucketSizeNs + 100, appUid1));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + 10, appUid1, "app1", AppStartOccurred::WARM, "activity_name1",
"calling_pkg_name1", true /*is_instant_app*/, 101 /*activity_start_msec*/));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + 20, appUid1, "app1", AppStartOccurred::HOT, "activity_name2",
"calling_pkg_name2", true /*is_instant_app*/, 102 /*activity_start_msec*/));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + 30, appUid1, "app1", AppStartOccurred::COLD, "activity_name3",
"calling_pkg_name3", true /*is_instant_app*/, 103 /*activity_start_msec*/));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + bucketSizeNs + 30, appUid1, "app1", AppStartOccurred::WARM,
"activity_name4", "calling_pkg_name4", true /*is_instant_app*/,
104 /*activity_start_msec*/));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + 2 * bucketSizeNs, appUid1, "app1", AppStartOccurred::COLD,
"activity_name5", "calling_pkg_name5", true /*is_instant_app*/,
105 /*activity_start_msec*/));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + 2 * bucketSizeNs + 10, appUid1, "app1", AppStartOccurred::HOT,
"activity_name6", "calling_pkg_name6", false /*is_instant_app*/,
106 /*activity_start_msec*/));
events.push_back(
CreateMoveToBackgroundEvent(bucketStartTimeNs + bucketSizeNs + 10, appUid2));
events.push_back(CreateAppStartOccurredEvent(
bucketStartTimeNs + 2 * bucketSizeNs + 10, appUid2, "app2", AppStartOccurred::COLD,
"activity_name7", "calling_pkg_name7", true /*is_instant_app*/,
201 /*activity_start_msec*/));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(),
&gaugeMetrics);
EXPECT_EQ(2, gaugeMetrics.data_size());
auto data = gaugeMetrics.data(0);
EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
EXPECT_EQ(3, data.bucket_info_size());
if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
EXPECT_EQ(2, data.bucket_info(0).atom_size());
EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::HOT,
data.bucket_info(0).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name2",
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(102L,
data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(AppStartOccurred::COLD,
data.bucket_info(0).atom(1).app_start_occurred().type());
EXPECT_EQ("activity_name3",
data.bucket_info(0).atom(1).app_start_occurred().activity_name());
EXPECT_EQ(103L,
data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::WARM,
data.bucket_info(1).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name4",
data.bucket_info(1).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(104L,
data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(2, data.bucket_info(2).atom_size());
EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::COLD,
data.bucket_info(2).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name5",
data.bucket_info(2).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(105L,
data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(AppStartOccurred::HOT,
data.bucket_info(2).atom(1).app_start_occurred().type());
EXPECT_EQ("activity_name6",
data.bucket_info(2).atom(1).app_start_occurred().activity_name());
EXPECT_EQ(106L,
data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
} else {
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::HOT,
data.bucket_info(0).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name2",
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(102L,
data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::WARM,
data.bucket_info(1).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name4",
data.bucket_info(1).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(104L,
data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(1, data.bucket_info(2).atom_size());
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::COLD,
data.bucket_info(2).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name5",
data.bucket_info(2).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(105L,
data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
}
data = gaugeMetrics.data(1);
EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
EXPECT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name7",
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
}
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

File diff suppressed because it is too large Load Diff

View File

@@ -97,250 +97,247 @@ StatsdConfig CreateStatsdConfig() {
}
} // namespace
// TODO(b/149590301): Update these tests to use new socket schema.
//// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
//// we should use the real API which will clear the data after dump data is called.
//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
// auto config = CreateStatsdConfig();
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// int appUid = 123;
// auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
// auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
// auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
//
// auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
// auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
// auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
//
// auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
// auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
//
// auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
// auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
//
// auto screenTurnedOnEvent =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2);
// auto screenTurnedOffEvent =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 200);
// auto screenTurnedOnEvent2 =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs - 100);
//
// std::vector<AttributionNodeInternal> attributions = {
// CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
// auto syncOnEvent1 =
// CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
// auto syncOffEvent1 =
// CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
// auto syncOnEvent2 =
// CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
//
// auto moveToBackgroundEvent1 =
// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
// auto moveToForegroundEvent1 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
//
// auto moveToBackgroundEvent2 =
// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
// auto moveToForegroundEvent2 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
//
// /*
// bucket #1 bucket #2
//
//
// | | | | | | | | | | (crashEvents)
// |-------------------------------------|-----------------------------------|---------
//
// | | (MoveToBkground)
//
// | | (MoveToForeground)
//
// | | (SyncIsOn)
// | (SyncIsOff)
// | | (ScreenIsOn)
// | (ScreenIsOff)
// */
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(std::move(crashEvent1));
// events.push_back(std::move(crashEvent2));
// events.push_back(std::move(crashEvent3));
// events.push_back(std::move(crashEvent4));
// events.push_back(std::move(crashEvent5));
// events.push_back(std::move(crashEvent6));
// events.push_back(std::move(crashEvent7));
// events.push_back(std::move(crashEvent8));
// events.push_back(std::move(crashEvent9));
// events.push_back(std::move(crashEvent10));
// events.push_back(std::move(screenTurnedOnEvent));
// events.push_back(std::move(screenTurnedOffEvent));
// events.push_back(std::move(screenTurnedOnEvent2));
// events.push_back(std::move(syncOnEvent1));
// events.push_back(std::move(syncOffEvent1));
// events.push_back(std::move(syncOnEvent2));
// events.push_back(std::move(moveToBackgroundEvent1));
// events.push_back(std::move(moveToForegroundEvent1));
// events.push_back(std::move(moveToBackgroundEvent2));
// events.push_back(std::move(moveToForegroundEvent2));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// // Validate dimension value.
// EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// // Uid field.
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
//}
//
//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
// auto config = CreateStatsdConfig();
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(
// bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// int appUid = 123;
// auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
// auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
// auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
//
// auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
// auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
// auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
//
// auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
// auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
//
// auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
// auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
//
// auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
// auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
// auto screenTurnedOnEvent2 =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs - 100);
//
// std::vector<AttributionNodeInternal> attributions = {
// CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
// auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
// auto syncOffEvent1 =
// CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
// auto syncOnEvent2 =
// CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
//
// auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
// auto moveToForegroundEvent1 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
//
// auto moveToBackgroundEvent2 =
// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
// auto moveToForegroundEvent2 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
//
// /*
// bucket #1 bucket #2
//
//
// | | | | | | | | | | (crashEvents)
// |-------------------------------------|-----------------------------------|---------
//
// | | (MoveToBkground)
//
// | | (MoveToForeground)
//
// | | (SyncIsOn)
// | (SyncIsOff)
// | | (ScreenIsOn)
// | (ScreenIsOff)
// */
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(std::move(crashEvent1));
// events.push_back(std::move(crashEvent2));
// events.push_back(std::move(crashEvent3));
// events.push_back(std::move(crashEvent4));
// events.push_back(std::move(crashEvent5));
// events.push_back(std::move(crashEvent6));
// events.push_back(std::move(crashEvent7));
// events.push_back(std::move(crashEvent8));
// events.push_back(std::move(crashEvent9));
// events.push_back(std::move(crashEvent10));
// events.push_back(std::move(screenTurnedOnEvent));
// events.push_back(std::move(screenTurnedOffEvent));
// events.push_back(std::move(screenTurnedOnEvent2));
// events.push_back(std::move(syncOnEvent1));
// events.push_back(std::move(syncOffEvent1));
// events.push_back(std::move(syncOnEvent2));
// events.push_back(std::move(moveToBackgroundEvent1));
// events.push_back(std::move(moveToForegroundEvent1));
// events.push_back(std::move(moveToBackgroundEvent2));
// events.push_back(std::move(moveToForegroundEvent2));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
//
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// // Validate dimension value.
// EXPECT_EQ(data.dimensions_in_what().field(),
// android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// // Uid field.
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
//}
// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
// we should use the real API which will clear the data after dump data is called.
TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
auto config = CreateStatsdConfig();
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
int appUid = 123;
auto crashEvent1 = CreateAppCrashEvent(bucketStartTimeNs + 1, appUid);
auto crashEvent2 = CreateAppCrashEvent(bucketStartTimeNs + 201, appUid);
auto crashEvent3 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 101, appUid);
auto crashEvent4 = CreateAppCrashEvent(bucketStartTimeNs + 51, appUid);
auto crashEvent5 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 299, appUid);
auto crashEvent6 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 2001, appUid);
auto crashEvent7 = CreateAppCrashEvent(bucketStartTimeNs + 16, appUid);
auto crashEvent8 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 249, appUid);
auto crashEvent9 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 351, appUid);
auto crashEvent10 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 2, appUid);
auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
bucketStartTimeNs + 2, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
bucketStartTimeNs + 200, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
auto screenTurnedOnEvent2 =
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
std::vector<int> attributionUids = {appUid, appUid + 1};
std::vector<string> attributionTags = {"App1", "GMSCoreModule1"};
auto syncOnEvent1 = CreateSyncStartEvent(bucketStartTimeNs + 50, attributionUids,
attributionTags, "ReadEmail");
auto syncOffEvent1 = CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 300, attributionUids,
attributionTags, "ReadEmail");
auto syncOnEvent2 = CreateSyncStartEvent(bucketStartTimeNs + bucketSizeNs + 2000,
attributionUids, attributionTags, "ReadDoc");
auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(bucketStartTimeNs + 15, appUid);
auto moveToForegroundEvent1 =
CreateMoveToForegroundEvent(bucketStartTimeNs + bucketSizeNs + 250, appUid);
auto moveToBackgroundEvent2 =
CreateMoveToBackgroundEvent(bucketStartTimeNs + bucketSizeNs + 350, appUid);
auto moveToForegroundEvent2 =
CreateMoveToForegroundEvent(bucketStartTimeNs + 2 * bucketSizeNs - 1, appUid);
/*
bucket #1 bucket #2
| | | | | | | | | | (crashEvents)
|-------------------------------------|-----------------------------------|---------
| | (MoveToBkground)
| | (MoveToForeground)
| | (SyncIsOn)
| (SyncIsOff)
| | (ScreenIsOn)
| (ScreenIsOff)
*/
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(std::move(crashEvent1));
events.push_back(std::move(crashEvent2));
events.push_back(std::move(crashEvent3));
events.push_back(std::move(crashEvent4));
events.push_back(std::move(crashEvent5));
events.push_back(std::move(crashEvent6));
events.push_back(std::move(crashEvent7));
events.push_back(std::move(crashEvent8));
events.push_back(std::move(crashEvent9));
events.push_back(std::move(crashEvent10));
events.push_back(std::move(screenTurnedOnEvent));
events.push_back(std::move(screenTurnedOffEvent));
events.push_back(std::move(screenTurnedOnEvent2));
events.push_back(std::move(syncOnEvent1));
events.push_back(std::move(syncOffEvent1));
events.push_back(std::move(syncOnEvent2));
events.push_back(std::move(moveToBackgroundEvent1));
events.push_back(std::move(moveToForegroundEvent1));
events.push_back(std::move(moveToBackgroundEvent2));
events.push_back(std::move(moveToForegroundEvent2));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// Validate dimension value.
EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// Uid field.
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
}
TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
auto config = CreateStatsdConfig();
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
int appUid = 123;
auto crashEvent1 = CreateAppCrashEvent(bucketStartTimeNs + 1, appUid);
auto crashEvent2 = CreateAppCrashEvent(bucketStartTimeNs + 201, appUid);
auto crashEvent3 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 101, appUid);
auto crashEvent4 = CreateAppCrashEvent(bucketStartTimeNs + 51, appUid);
auto crashEvent5 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 299, appUid);
auto crashEvent6 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 2001, appUid);
auto crashEvent7 = CreateAppCrashEvent(bucketStartTimeNs + 16, appUid);
auto crashEvent8 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 249, appUid);
auto crashEvent9 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 351, appUid);
auto crashEvent10 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 2, appUid);
auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
bucketStartTimeNs + 2, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
bucketStartTimeNs + 200, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
auto screenTurnedOnEvent2 =
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
std::vector<int> attributionUids = {appUid, appUid + 1};
std::vector<string> attributionTags = {"App1", "GMSCoreModule1"};
auto syncOnEvent1 = CreateSyncStartEvent(bucketStartTimeNs + 50, attributionUids,
attributionTags, "ReadEmail");
auto syncOffEvent1 = CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 300, attributionUids,
attributionTags, "ReadEmail");
auto syncOnEvent2 = CreateSyncStartEvent(bucketStartTimeNs + bucketSizeNs + 2000,
attributionUids, attributionTags, "ReadDoc");
auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(bucketStartTimeNs + 15, appUid);
auto moveToForegroundEvent1 =
CreateMoveToForegroundEvent(bucketStartTimeNs + bucketSizeNs + 250, appUid);
auto moveToBackgroundEvent2 =
CreateMoveToBackgroundEvent(bucketStartTimeNs + bucketSizeNs + 350, appUid);
auto moveToForegroundEvent2 =
CreateMoveToForegroundEvent(bucketStartTimeNs + 2 * bucketSizeNs - 1, appUid);
/*
bucket #1 bucket #2
| | | | | | | | | | (crashEvents)
|-------------------------------------|-----------------------------------|---------
| | (MoveToBkground)
| | (MoveToForeground)
| | (SyncIsOn)
| (SyncIsOff)
| | (ScreenIsOn)
| (ScreenIsOff)
*/
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(std::move(crashEvent1));
events.push_back(std::move(crashEvent2));
events.push_back(std::move(crashEvent3));
events.push_back(std::move(crashEvent4));
events.push_back(std::move(crashEvent5));
events.push_back(std::move(crashEvent6));
events.push_back(std::move(crashEvent7));
events.push_back(std::move(crashEvent8));
events.push_back(std::move(crashEvent9));
events.push_back(std::move(crashEvent10));
events.push_back(std::move(screenTurnedOnEvent));
events.push_back(std::move(screenTurnedOffEvent));
events.push_back(std::move(screenTurnedOnEvent2));
events.push_back(std::move(syncOnEvent1));
events.push_back(std::move(syncOffEvent1));
events.push_back(std::move(syncOnEvent2));
events.push_back(std::move(moveToBackgroundEvent1));
events.push_back(std::move(moveToForegroundEvent1));
events.push_back(std::move(moveToBackgroundEvent2));
events.push_back(std::move(moveToForegroundEvent2));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// Validate dimension value.
EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// Uid field.
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -113,96 +113,107 @@ StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
}
} // anonymous namespace
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
//
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
// // Expect no metrics since the bucket has not finished yet.
// EXPECT_EQ(1, report.metrics_size());
// EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
//}
//
//TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
//
// // Force the uidmap to update at timestamp 2.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// // This is a new installation, so there shouldn't be a split (should be same as the without
// // split case).
// service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
// String16(""));
// // Goes into the second bucket.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
// EXPECT_EQ(1, report.metrics_size());
// EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
//}
//
//TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
// service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
// {String16("")});
//
// // Force the uidmap to update at timestamp 2.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
// String16(""));
// // Goes into the second bucket.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
// backfillStartEndTimestamp(&report);
//
// ASSERT_EQ(1, report.metrics_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_start_bucket_elapsed_nanos());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_end_bucket_elapsed_nanos());
// EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
//}
//
//TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
// service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
// {String16("")});
//
// // Force the uidmap to update at timestamp 2.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
// // Goes into the second bucket.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
// backfillStartEndTimestamp(&report);
//
// ASSERT_EQ(1, report.metrics_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_start_bucket_elapsed_nanos());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_end_bucket_elapsed_nanos());
// EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
//}
TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
// Expect no metrics since the bucket has not finished yet.
EXPECT_EQ(1, report.metrics_size());
EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
}
TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
// This is a new installation, so there shouldn't be a split (should be same as the without
// split case).
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
EXPECT_EQ(1, report.metrics_size());
EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
}
TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
{String16("")});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
EXPECT_TRUE(report.metrics(0)
.count_metrics()
.data(0)
.bucket_info(0)
.has_start_bucket_elapsed_nanos());
EXPECT_TRUE(report.metrics(0)
.count_metrics()
.data(0)
.bucket_info(0)
.has_end_bucket_elapsed_nanos());
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
{String16("")});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
EXPECT_TRUE(report.metrics(0)
.count_metrics()
.data(0)
.bucket_info(0)
.has_start_bucket_elapsed_nanos());
EXPECT_TRUE(report.metrics(0)
.count_metrics()
.data(0)
.bucket_info(0)
.has_end_bucket_elapsed_nanos());
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);

View File

@@ -64,317 +64,313 @@ StatsdConfig CreateStatsdConfig(bool useCondition = true) {
} // namespace
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(ValueMetricE2eTest, TestPulledEvents) {
// auto config = CreateStatsdConfig();
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// android::util::SUBSYSTEM_SLEEP_STATE);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the value metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& expectedPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 65);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 75);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 2 * bucketSizeNs + 15);
// processor->OnLogEvent(screenOnEvent.get());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 4 * bucketSizeNs + 11);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::ValueMetricDataWrapper valueMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
// EXPECT_GT((int)valueMetrics.data_size(), 1);
//
// auto data = valueMetrics.data(0);
// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// // We have 4 buckets, the first one was incomplete since the condition was unknown.
// EXPECT_EQ(4, data.bucket_info_size());
//
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(0).values_size());
//
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(1).values_size());
//
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(2).values_size());
//
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(3).values_size());
//}
//
//TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
// auto config = CreateStatsdConfig();
// int64_t baseTimeNs = getElapsedRealtimeNs();
// // 10 mins == 2 bucket durations.
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// android::util::SUBSYSTEM_SLEEP_STATE);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the value metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& expectedPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
//
// // Screen off/on/off events.
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 65);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 75);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
// // future, data will be skipped.
// processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
//
// // This screen state change will start a new bucket.
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 4 * bucketSizeNs + 65);
// processor->OnLogEvent(screenOnEvent.get());
//
// // The alarm is delayed but we already created a bucket thanks to the screen state condition.
// // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
// processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 6 * bucketSizeNs + 31);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::ValueMetricDataWrapper valueMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
// EXPECT_GT((int)valueMetrics.data_size(), 1);
//
// auto data = valueMetrics.data(0);
// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(0).values_size());
//
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(1).values_size());
//
// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(2).values_size());
//}
//
//TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
// auto config = CreateStatsdConfig(false);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
//
// auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
// *config.add_atom_matcher() = batterySaverStartMatcher;
// const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
// auto metric_activation = config.add_metric_activation();
// metric_activation->set_metric_id(metricId);
// metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
// auto event_activation = metric_activation->add_event_activation();
// event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
// event_activation->set_ttl_seconds(ttlNs / 1000000000);
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// android::util::SUBSYSTEM_SLEEP_STATE);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // When creating the config, the value metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& expectedPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // Activate the metric. A pull occurs here
// const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
// auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
// processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
//
// // Create random event to deactivate metric.
// auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
// processor->OnLogEvent(deactivationEvent.get());
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 3);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 4);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::ValueMetricDataWrapper valueMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
// EXPECT_GT((int)valueMetrics.data_size(), 0);
//
// auto data = valueMetrics.data(0);
// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// // We have 2 full buckets, the two surrounding the activation are dropped.
// EXPECT_EQ(2, data.bucket_info_size());
//
// auto bucketInfo = data.bucket_info(0);
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_EQ(1, bucketInfo.values_size());
//
// bucketInfo = data.bucket_info(1);
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_EQ(1, bucketInfo.values_size());
//}
TEST(ValueMetricE2eTest, TestPulledEvents) {
auto config = CreateStatsdConfig();
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
android::util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the value metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& expectedPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
auto screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 65, android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 75, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives on time and reset the sequential pulling alarm.
processor->informPullAlarmFired(expectedPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 2 * bucketSizeNs + 15,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
processor->informPullAlarmFired(expectedPullTimeNs + 1);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 4 * bucketSizeNs + 11,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(expectedPullTimeNs + 1);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::ValueMetricDataWrapper valueMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
EXPECT_GT((int)valueMetrics.data_size(), 1);
auto data = valueMetrics.data(0);
EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// We have 4 buckets, the first one was incomplete since the condition was unknown.
EXPECT_EQ(4, data.bucket_info_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(0).values_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(1).values_size());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(2).values_size());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(3).values_size());
}
TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
auto config = CreateStatsdConfig();
int64_t baseTimeNs = getElapsedRealtimeNs();
// 10 mins == 2 bucket durations.
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
android::util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the value metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& expectedPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
// Screen off/on/off events.
auto screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 65, android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent =
CreateScreenStateChangedEvent(configAddedTimeNs + 75, android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
// future, data will be skipped.
processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
// This screen state change will start a new bucket.
screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 4 * bucketSizeNs + 65,
android::view::DISPLAY_STATE_ON);
processor->OnLogEvent(screenOnEvent.get());
// The alarm is delayed but we already created a bucket thanks to the screen state condition.
// This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 6 * bucketSizeNs + 31,
android::view::DISPLAY_STATE_OFF);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::ValueMetricDataWrapper valueMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
EXPECT_GT((int)valueMetrics.data_size(), 1);
auto data = valueMetrics.data(0);
EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(0).values_size());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(1).values_size());
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(2).values_size());
}
TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
auto config = CreateStatsdConfig(false);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
*config.add_atom_matcher() = batterySaverStartMatcher;
const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
auto metric_activation = config.add_metric_activation();
metric_activation->set_metric_id(metricId);
metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
auto event_activation = metric_activation->add_event_activation();
event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
event_activation->set_ttl_seconds(ttlNs / 1000000000);
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
android::util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()
->second->mAllMetricProducers[0]
->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// When creating the config, the value metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& expectedPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
// Pulling alarm arrives on time and reset the sequential pulling alarm.
processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// Activate the metric. A pull occurs here
const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
// Create random event to deactivate metric.
auto deactivationEvent = CreateScreenBrightnessChangedEvent(activationNs + ttlNs + 1, 50);
processor->OnLogEvent(deactivationEvent.get());
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
processor->informPullAlarmFired(expectedPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 4);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::ValueMetricDataWrapper valueMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
EXPECT_GT((int)valueMetrics.data_size(), 0);
auto data = valueMetrics.data(0);
EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// We have 2 full buckets, the two surrounding the activation are dropped.
EXPECT_EQ(2, data.bucket_info_size());
auto bucketInfo = data.bucket_info(0);
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_EQ(1, bucketInfo.values_size());
bucketInfo = data.bucket_info(1);
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_EQ(1, bucketInfo.values_size());
}
/**
* Test initialization of a simple value metric that is sliced by a state.

View File

@@ -61,292 +61,290 @@ StatsdConfig CreateStatsdConfig(DurationMetric::AggregationType aggregationType)
return config;
}
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<int> attributionUids1 = {111, 222, 222};
std::vector<string> attributionTags1 = {"App1", "GMSCoreModule1", "GMSCoreModule2"};
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<int> attributionUids2 = {111, 222, 222};
std::vector<string> attributionTags2 = {"App2", "GMSCoreModule1", "GMSCoreModule2"};
// TODO(b/149590301): Update this helper to use new socket schema.
///*
//Events:
//Screen off is met from (200ns,1 min+500ns].
//Acquire event for wl1 from 2ns to 1min+2ns
//Acquire event for wl2 from 1min-10ns to 2min-15ns
//*/
//void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
//
// auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
// auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
// auto screenTurnedOnEvent2 =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + bucketSizeNs + 500);
//
// auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// auto releaseEvent1 =
// CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
// auto acquireEvent2 =
// CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
// auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
// bucketStartTimeNs + 2 * bucketSizeNs - 15);
//
// std::vector<std::unique_ptr<LogEvent>> events;
//
// events.push_back(std::move(screenTurnedOnEvent));
// events.push_back(std::move(screenTurnedOffEvent));
// events.push_back(std::move(screenTurnedOnEvent2));
// events.push_back(std::move(acquireEvent1));
// events.push_back(std::move(acquireEvent2));
// events.push_back(std::move(releaseEvent1));
// events.push_back(std::move(releaseEvent2));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
//}
/*
Events:
Screen off is met from (200ns,1 min+500ns].
Acquire event for wl1 from 2ns to 1min+2ns
Acquire event for wl2 from 1min-10ns to 2min-15ns
*/
void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
bucketStartTimeNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
bucketStartTimeNs + 200, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
auto screenTurnedOnEvent2 =
CreateScreenStateChangedEvent(bucketStartTimeNs + bucketSizeNs + 500,
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
auto acquireEvent1 = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1,
attributionTags1, "wl1");
auto releaseEvent1 = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2,
attributionUids1, attributionTags1, "wl1");
auto acquireEvent2 = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 10,
attributionUids2, attributionTags2, "wl2");
auto releaseEvent2 = CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs - 15,
attributionUids2, attributionTags2, "wl2");
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(std::move(screenTurnedOnEvent));
events.push_back(std::move(screenTurnedOffEvent));
events.push_back(std::move(screenTurnedOnEvent2));
events.push_back(std::move(acquireEvent1));
events.push_back(std::move(acquireEvent2));
events.push_back(std::move(releaseEvent1));
events.push_back(std::move(releaseEvent2));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
}
} // namespace
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::SUM);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// vector<uint8_t> buffer;
// ConfigMetricsReportList reports;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
//
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
//
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // Validate dimension value.
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // Validate bucket info.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
// data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // The wakelock holding interval starts from the screen off event and to the end of the 1st
// // bucket.
// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::SUM);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// vector<uint8_t> buffer;
// ConfigMetricsReportList reports;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// // Dump the report after the end of 2nd bucket.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // Validate dimension value.
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // Two output buckets.
// // The wakelock holding interval in the 1st bucket starts from the screen off event and to
// // the end of the 1st bucket.
// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
// bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
// // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
// // ends at the second screen on event.
// EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
//}
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::SUM);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// vector<uint8_t> buffer;
// ConfigMetricsReportList reports;
//
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + 90));
// events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 5 * bucketSizeNs + 100));
// sortLogEventsByTimestamp(&events);
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
//
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // The last wakelock holding spans 4 buckets.
// EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
// EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
//
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
//
// EXPECT_EQ(reports.reports_size(), 1);
//
// // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
// // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
// // itself.
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// // Dump the report after the end of 2nd bucket. One dimension with one bucket.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // Validate dimension value.
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // The max is acquire event for wl1 to screen off start.
// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
//
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + 90));
// events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 5 * bucketSizeNs + 100));
// sortLogEventsByTimestamp(&events);
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
//
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // The last wakelock holding spans 4 buckets.
// EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
// bucketStartTimeNs + 5 * bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
// bucketStartTimeNs + 6 * bucketSizeNs);
//}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::SUM);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// Only 1 dimension output. The tag dimension in the predicate has been aggregated.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// Validate bucket info.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
data = reports.reports(0).metrics(0).duration_metrics().data(0);
// The wakelock holding interval starts from the screen off event and to the end of the 1st
// bucket.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::SUM);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// Dump the report after the end of 2nd bucket.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// Two output buckets.
// The wakelock holding interval in the 1st bucket starts from the screen off event and to
// the end of the 1st bucket.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
// The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
// ends at the second screen on event.
EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::SUM);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 90,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 100,
attributionUids1, attributionTags1, "wl3"));
events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs + 100,
attributionUids1, attributionTags1, "wl3"));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// The last wakelock holding spans 4 buckets.
EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
// When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
// one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
// itself.
EXPECT_EQ(1, reports.reports(0).metrics_size());
EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// Dump the report after the end of 2nd bucket. One dimension with one bucket.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// The max is acquire event for wl1 to screen off start.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 90,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 100,
attributionUids1, attributionTags1, "wl3"));
events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs + 100,
attributionUids1, attributionTags1, "wl3"));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true, ADB_DUMP,
FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// The last wakelock holding spans 4 buckets.
EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
bucketStartTimeNs + 5 * bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
bucketStartTimeNs + 6 * bucketSizeNs);
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -15,11 +15,14 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <chrono>
#include <thread>
#include <vector>
#include "../metrics/metrics_test_helper.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
#include "tests/statsd_test_util.h"
#ifdef __ANDROID__
@@ -57,13 +60,22 @@ private:
FakePuller puller;
// TODO(b/149590301): Update this helper to use new socket schema.
//shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
// shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
// event->write(value);
// event->init();
// return event;
//}
std::unique_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, pullTagId);
AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
AStatsEvent_writeInt64(statsEvent, value);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
class StatsPullerTest : public ::testing::Test {
public:
@@ -80,149 +92,148 @@ public:
} // Anonymous namespace.
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST_F(StatsPullerTest, PullSuccess) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//
// sleep_for(std::chrono::seconds(1));
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
//
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
//}
//
//TEST_F(StatsPullerTest, PullFailAfterSuccess) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//
// sleep_for(std::chrono::seconds(1));
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = false;
// dataHolder.clear();
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//
// pullSuccess = true;
// dataHolder.clear();
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
//TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
// pullData.push_back(createSimpleEvent(1111L, 33));
// pullSuccess = true;
// // timeout is 0.5
// pullDelayNs = (long)(0.8 * NS_PER_SEC);
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
// dataHolder.clear();
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//TEST_F(StatsPullerTest, PullFail) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = false;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//TEST_F(StatsPullerTest, PullTakeTooLong) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
// pullDelayNs = NS_PER_SEC;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//TEST_F(StatsPullerTest, PullTooFast) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
//
// dataHolder.clear();
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//}
//
//TEST_F(StatsPullerTest, PullFailsAndTooFast) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = false;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
//
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
TEST_F(StatsPullerTest, PullSuccess) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
sleep_for(std::chrono::seconds(1));
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
}
TEST_F(StatsPullerTest, PullFailAfterSuccess) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
sleep_for(std::chrono::seconds(1));
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = false;
dataHolder.clear();
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
pullSuccess = true;
dataHolder.clear();
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
// timeout is 0.5
pullDelayNs = (long)(0.8 * NS_PER_SEC);
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
dataHolder.clear();
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
TEST_F(StatsPullerTest, PullFail) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = false;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
TEST_F(StatsPullerTest, PullTakeTooLong) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
pullDelayNs = NS_PER_SEC;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
TEST_F(StatsPullerTest, PullTooFast) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
dataHolder.clear();
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
}
TEST_F(StatsPullerTest, PullFailsAndTooFast) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = false;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
} // namespace statsd
} // namespace os

View File

@@ -13,12 +13,16 @@
// limitations under the License.
#include "external/puller_util.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <vector>
#include "statslog.h"
#include "../metrics/metrics_test_helper.h"
#include "stats_event.h"
#include "statslog.h"
#ifdef __ANDROID__
@@ -58,212 +62,187 @@ void extractIntoVector(vector<shared_ptr<LogEvent>> events,
ret.push_back(vec);
}
}
std::shared_ptr<LogEvent> 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_writeInt32(statsEvent, data1);
AStatsEvent_writeInt32(statsEvent, data2);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::shared_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::shared_ptr<LogEvent> makeNonUidAtomLogEvent(uint64_t timestampNs, int data1) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, nonUidAtomTagId);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, data1);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::shared_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
} // anonymous namespace
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(puller_util, MergeNoDimension) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->22->31
// event->write(isolatedUid);
// event->write(hostNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
// .WillRepeatedly(Return(hostUid));
// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
// .WillRepeatedly(ReturnArg<0>());
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 22, 52};
// EXPECT_EQ(1, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
//}
//
//TEST(puller_util, MergeWithDimension) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->32->31
// event->write(isolatedUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->32->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
// .WillRepeatedly(Return(hostUid));
// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
// .WillRepeatedly(ReturnArg<0>());
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 22, 21};
// vector<int> expectedV2 = {20, 32, 52};
// EXPECT_EQ(2, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
// EXPECT_THAT(actual, Contains(expectedV2));
//}
//
//TEST(puller_util, NoMergeHostUidOnly) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 20->32->31
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// 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<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 32, 31};
// vector<int> expectedV2 = {20, 22, 21};
// EXPECT_EQ(2, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
// EXPECT_THAT(actual, Contains(expectedV2));
//}
//
//TEST(puller_util, IsolatedUidOnly) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->32->31
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 30->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// 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<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 32, 31};
// vector<int> expectedV2 = {20, 22, 21};
// EXPECT_EQ(2, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
// EXPECT_THAT(actual, Contains(expectedV2));
//}
//
//TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->32->31
// event->write(isolatedUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 31->32->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(isolatedUid + 1);
// event->write(isolatedNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->32->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 32, 73};
// EXPECT_EQ(1, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
//}
//
//TEST(puller_util, NoNeedToMerge) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event =
// make_shared<LogEvent>(nonUidAtomTagId, timestamp);
// // 32
// event->write(isolatedNonAdditiveData);
// event->init();
// inputData.push_back(event);
//
// event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
// // 22
// event->write(hostNonAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
//
// EXPECT_EQ(2, (int)inputData.size());
//}
TEST(puller_util, MergeNoDimension) {
vector<shared_ptr<LogEvent>> inputData;
// 30->22->31
inputData.push_back(
makeUidLogEvent(timestamp, isolatedUid, hostNonAdditiveData, isolatedAdditiveData));
// 20->22->21
inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData));
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid))).WillRepeatedly(ReturnArg<0>());
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 22, 52};
EXPECT_EQ(1, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
}
TEST(puller_util, MergeWithDimension) {
vector<shared_ptr<LogEvent>> inputData;
// 30->32->31
inputData.push_back(
makeUidLogEvent(timestamp, isolatedUid, isolatedNonAdditiveData, isolatedAdditiveData));
// 20->32->21
inputData.push_back(
makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, hostAdditiveData));
// 20->22->21
inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData));
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid))).WillRepeatedly(ReturnArg<0>());
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 22, 21};
vector<int> expectedV2 = {20, 32, 52};
EXPECT_EQ(2, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
EXPECT_THAT(actual, Contains(expectedV2));
}
TEST(puller_util, NoMergeHostUidOnly) {
vector<shared_ptr<LogEvent>> inputData;
// 20->32->31
inputData.push_back(
makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, isolatedAdditiveData));
// 20->22->21
inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData));
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
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<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 32, 31};
vector<int> expectedV2 = {20, 22, 21};
EXPECT_EQ(2, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
EXPECT_THAT(actual, Contains(expectedV2));
}
TEST(puller_util, IsolatedUidOnly) {
vector<shared_ptr<LogEvent>> inputData;
// 30->32->31
inputData.push_back(
makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, isolatedAdditiveData));
// 30->22->21
inputData.push_back(makeUidLogEvent(timestamp, hostUid, hostNonAdditiveData, hostAdditiveData));
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
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<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 32, 31};
vector<int> expectedV2 = {20, 22, 21};
EXPECT_EQ(2, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
EXPECT_THAT(actual, Contains(expectedV2));
}
TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
vector<shared_ptr<LogEvent>> inputData;
// 30->32->31
inputData.push_back(
makeUidLogEvent(timestamp, isolatedUid, isolatedNonAdditiveData, isolatedAdditiveData));
// 31->32->21
inputData.push_back(
makeUidLogEvent(timestamp, isolatedUid + 1, isolatedNonAdditiveData, hostAdditiveData));
// 20->32->21
inputData.push_back(
makeUidLogEvent(timestamp, hostUid, isolatedNonAdditiveData, hostAdditiveData));
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 32, 73};
EXPECT_EQ(1, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
}
TEST(puller_util, NoNeedToMerge) {
vector<shared_ptr<LogEvent>> inputData;
// 32
inputData.push_back(makeNonUidAtomLogEvent(timestamp, isolatedNonAdditiveData));
// 22
inputData.push_back(makeNonUidAtomLogEvent(timestamp, hostNonAdditiveData));
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
EXPECT_EQ(2, (int)inputData.size());
}
} // namespace statsd
} // namespace os

View File

@@ -42,7 +42,7 @@ std::unique_ptr<LogEvent> makeLogEvent(uint64_t timestampNs) {
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/-1, /*pid=*/-1);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;

View File

@@ -13,16 +13,19 @@
// limitations under the License.
#include "src/metrics/CountMetricProducer.h"
#include "src/stats_log_util.h"
#include "metrics_test_helper.h"
#include "tests/statsd_test_util.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <math.h>
#include <stdio.h>
#include <vector>
#include "metrics_test_helper.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
#include "tests/statsd_test_util.h"
using namespace testing;
using android::sp;
using std::set;
@@ -37,366 +40,392 @@ namespace statsd {
const ConfigKey kConfigKey(0, 12345);
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(CountMetricProducerTest, TestFirstBucket) {
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
//
// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
// 600 * NS_PER_SEC + NS_PER_SEC / 2);
// EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
// EXPECT_EQ(10, countProducer.mCurrentBucketNum);
// EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
//}
//
//TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
// int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
// int tagId = 1;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
//
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
//
// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// // 2 events in bucket 1.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
//
// // Flushes at event #2.
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// // Flushes.
// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(2LL, buckets[0].mCount);
//
// // 1 matched event happens in bucket 2.
// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
// event3.init();
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
// EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
// EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
// EXPECT_EQ(1LL, bucketInfo2.mCount);
//
// // nothing happens in bucket 3. we should not record anything for bucket 3.
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(2UL, buckets3.size());
//}
//
//TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_condition(StringToId("SCREEN_ON"));
//
// LogEvent event1(1, bucketStartTimeNs + 1);
// event1.init();
//
// LogEvent event2(1, bucketStartTimeNs + 10);
// event2.init();
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
//
// CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
// bucketStartTimeNs);
//
// countProducer.onConditionChanged(true, bucketStartTimeNs);
// countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
// // Upon this match event, the matched event1 is flushed.
// countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// {
// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// const auto& bucketInfo = buckets[0];
// EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
// EXPECT_EQ(1LL, bucketInfo.mCount);
// }
//}
//
//TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
// MetricConditionLink* link = metric.add_links();
// link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
// buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
// buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
//
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.write("111"); // uid
// event1.init();
// ConditionKey key1;
// key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
// {getMockedDimensionKey(conditionTagId, 2, "111")};
//
// LogEvent event2(tagId, bucketStartTimeNs + 10);
// event2.write("222"); // uid
// event2.init();
// ConditionKey key2;
// key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
// {getMockedDimensionKey(conditionTagId, 2, "222")};
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
//
// EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
//
// CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// const auto& bucketInfo = buckets[0];
// EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
// EXPECT_EQ(1LL, bucketInfo.mCount);
//}
//
//TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
// sp<AlarmMonitor> alarmMonitor;
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// Alert alert;
// alert.set_num_buckets(3);
// alert.set_trigger_if_sum_gt(2);
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
// EXPECT_TRUE(anomalyTracker != nullptr);
//
// // Bucket is flushed yet.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//
// // App upgrade forces bucket flush.
// // Check that there's a past bucket and the bucket end is not adjusted.
// countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ((long long)bucketStartTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
// EXPECT_EQ((long long)eventUpgradeTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// // Anomaly tracker only contains full buckets.
// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//
// int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
// // Next event occurs in same bucket as partial bucket created.
// LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
// event2.write("222"); // uid
// event2.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//
// // Third event in following bucket.
// LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
// event3.write("333"); // uid
// event3.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
// EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//}
//
//TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// // Bucket is flushed yet.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// // App upgrade forces bucket flush.
// // Check that there's a past bucket and the bucket end is not adjusted.
// countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ((int64_t)bucketStartTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
//
// // Next event occurs in same bucket as partial bucket created.
// LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
// event2.write("222"); // uid
// event2.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
//
// // Third event in following bucket.
// LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
// event3.write("333"); // uid
// event3.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ((int64_t)eventUpgradeTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
//}
//
//TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
// sp<AlarmMonitor> alarmMonitor;
// Alert alert;
// alert.set_id(11);
// alert.set_metric_id(1);
// alert.set_trigger_if_sum_gt(2);
// alert.set_num_buckets(2);
// const int32_t refPeriodSec = 1;
// alert.set_refractory_period_secs(refPeriodSec);
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
// int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
// LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
// event3.init();
// LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
// event4.init();
// LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
// event5.init();
// LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
// event6.init();
// LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
// event7.init();
//
// // Two events in bucket #0.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
//
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
//
// // One event in bucket #2. No alarm as bucket #0 is trashed out.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
//
// // Two events in bucket #3.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
// // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
// std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
// std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
//}
namespace {
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
}
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId, string uid) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeString(statsEvent, uid.c_str());
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
}
} // namespace
TEST(CountMetricProducerTest, TestFirstBucket) {
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
600 * NS_PER_SEC + NS_PER_SEC / 2);
EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, countProducer.mCurrentBucketNum);
EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
}
TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
int tagId = 1;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
bucketStartTimeNs, bucketStartTimeNs);
// 2 events in bucket 1.
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 2, tagId);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// Flushes at event #2.
countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
// Flushes.
countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(2LL, buckets[0].mCount);
// 1 matched event happens in bucket 2.
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event3, bucketStartTimeNs + bucketSizeNs + 2, tagId);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
EXPECT_EQ(1LL, bucketInfo2.mCount);
// nothing happens in bucket 3. we should not record anything for bucket 3.
countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(2UL, buckets3.size());
}
TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
bucketStartTimeNs);
countProducer.onConditionChanged(true, bucketStartTimeNs);
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, /*atomId=*/1);
countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
// Upon this match event, the matched event1 is flushed.
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 10, /*atomId=*/1);
countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
const auto& bucketInfo = buckets[0];
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
EXPECT_EQ(1LL, bucketInfo.mCount);
}
TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int tagId = 1;
int conditionTagId = 2;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
MetricConditionLink* link = metric.add_links();
link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId, /*uid=*/"111");
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 10, tagId, /*uid=*/"222");
ConditionKey key1;
key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {
getMockedDimensionKey(conditionTagId, 2, "111")};
ConditionKey key2;
key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {
getMockedDimensionKey(conditionTagId, 2, "222")};
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
bucketStartTimeNs, bucketStartTimeNs);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
const auto& bucketInfo = buckets[0];
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
EXPECT_EQ(1LL, bucketInfo.mCount);
}
TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
sp<AlarmMonitor> alarmMonitor;
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int tagId = 1;
int conditionTagId = 2;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
Alert alert;
alert.set_num_buckets(3);
alert.set_trigger_if_sum_gt(2);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
// Bucket is flushed yet.
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId, /*uid=*/"111");
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
// App upgrade forces bucket flush.
// Check that there's a past bucket and the bucket end is not adjusted.
countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ((long long)bucketStartTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
EXPECT_EQ((long long)eventUpgradeTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// Anomaly tracker only contains full buckets.
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
// Next event occurs in same bucket as partial bucket created.
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 59 * NS_PER_SEC + 10, tagId, /*uid=*/"222");
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
// Third event in following bucket.
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event3, bucketStartTimeNs + 62 * NS_PER_SEC + 10, tagId, /*uid=*/"333");
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
}
TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int tagId = 1;
int conditionTagId = 2;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
bucketStartTimeNs, bucketStartTimeNs);
// Bucket is flushed yet.
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId, /*uid=*/"111");
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
// App upgrade forces bucket flush.
// Check that there's a past bucket and the bucket end is not adjusted.
countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ((int64_t)bucketStartTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// Next event occurs in same bucket as partial bucket created.
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 70 * NS_PER_SEC + 10, tagId, /*uid=*/"222");
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// Third event in following bucket.
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event3, bucketStartTimeNs + 121 * NS_PER_SEC + 10, tagId, /*uid=*/"333");
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ((int64_t)eventUpgradeTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
}
TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
sp<AlarmMonitor> alarmMonitor;
Alert alert;
alert.set_id(11);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(2);
alert.set_num_buckets(2);
const int32_t refPeriodSec = 1;
alert.set_refractory_period_secs(refPeriodSec);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 2, tagId);
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event3, bucketStartTimeNs + 2 * bucketSizeNs + 1, tagId);
LogEvent event4(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event4, bucketStartTimeNs + 3 * bucketSizeNs + 1, tagId);
LogEvent event5(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event5, bucketStartTimeNs + 3 * bucketSizeNs + 2, tagId);
LogEvent event6(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event6, bucketStartTimeNs + 3 * bucketSizeNs + 3, tagId);
LogEvent event7(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event7, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC, tagId);
// Two events in bucket #0.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
// One event in bucket #2. No alarm as bucket #0 is trashed out.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
// Two events in bucket #3.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
// Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
}
TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
CountMetric metric;

View File

@@ -13,17 +13,20 @@
// limitations under the License.
#include "src/metrics/DurationMetricProducer.h"
#include "src/stats_log_util.h"
#include "metrics_test_helper.h"
#include "src/condition/ConditionWizard.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <set>
#include <unordered_map>
#include <vector>
#include "metrics_test_helper.h"
#include "src/condition/ConditionWizard.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
using namespace android::os::statsd;
using namespace testing;
using android::sp;
@@ -39,6 +42,22 @@ namespace statsd {
const ConfigKey kConfigKey(0, 12345);
namespace {
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
}
} // namespace
TEST(DurationMetricTrackerTest, TestFirstBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
DurationMetric metric;
@@ -56,383 +75,386 @@ TEST(DurationMetricTrackerTest, TestFirstBucket) {
EXPECT_EQ(660000000005, durationProducer.getCurrentBucketEndTimeNs());
}
// TODO(b/149590301): Update these to use new socket schema.
//TEST(DurationMetricTrackerTest, TestNoCondition) {
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
// event2.init();
//
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
// EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// durationProducer.mPastBuckets.end());
// const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(2UL, buckets.size());
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
// EXPECT_EQ(2LL, buckets[1].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
// event3.init();
// LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
// event4.init();
//
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
// durationProducer.mCondition = ConditionState::kFalse;
//
// EXPECT_FALSE(durationProducer.mCondition);
// EXPECT_FALSE(durationProducer.isConditionSliced());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
// durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
// EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// durationProducer.mPastBuckets.end());
// const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets2.size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
// EXPECT_EQ(1LL, buckets2[0].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
// event3.init();
// LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
// event4.init();
//
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
// EXPECT_FALSE(durationProducer.isConditionSliced());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
// durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
// const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets2.size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
// EXPECT_EQ(1LL, buckets2[0].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
// /**
// * The duration starts from the first bucket, through the two partial buckets (10-70sec),
// * another bucket, and ends at the beginning of the next full bucket.
// * Expected buckets:
// * - [10,25]: 14 secs
// * - [25,70]: All 45 secs
// * - [70,130]: All 60 secs
// * - [130, 210]: Only 5 secs (event ended at 135sec)
// */
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(3UL, buckets.size());
// EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
// EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
// /**
// * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
// * - [10,70]: 59 secs
// * - [70,75]: 5 sec
// * - [75,130]: 55 secs
// */
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
// EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(3UL, buckets.size());
// EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
// sp<AlarmMonitor> alarmMonitor;
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1;
// int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
//
// int tagId = 1;
//
// // Setup metric with alert.
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
// Alert alert;
// alert.set_num_buckets(3);
// alert.set_trigger_if_sum_gt(2);
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
// EXPECT_TRUE(anomalyTracker != nullptr);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
//
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
// anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//}
//
//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1;
// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
// LogEvent event1(tagId, startTimeNs);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
//
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1;
// int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
// LogEvent event1(tagId, startTimeNs);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // Stop occurs in the same partial bucket as created for the app upgrade.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
//}
TEST(DurationMetricTrackerTest, TestNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + bucketSizeNs + 2, tagId);
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
durationProducer.mPastBuckets.end());
const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(2UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
EXPECT_EQ(2LL, buckets[1].mDuration);
}
TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 2, tagId);
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event3, bucketStartTimeNs + bucketSizeNs + 1, tagId);
LogEvent event4(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event4, bucketStartTimeNs + bucketSizeNs + 3, tagId);
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, 0 /* condition index */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.mCondition = ConditionState::kFalse;
EXPECT_FALSE(durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
durationProducer.mPastBuckets.end());
const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets2.size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
EXPECT_EQ(1LL, buckets2[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, bucketStartTimeNs + 1, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, bucketStartTimeNs + 2, tagId);
LogEvent event3(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event3, bucketStartTimeNs + bucketSizeNs + 1, tagId);
LogEvent event4(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event4, bucketStartTimeNs + bucketSizeNs + 3, tagId);
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, 0 /* condition index */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets2.size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
EXPECT_EQ(1LL, buckets2[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
/**
* The duration starts from the first bucket, through the two partial buckets (10-70sec),
* another bucket, and ends at the beginning of the next full bucket.
* Expected buckets:
* - [10,25]: 14 secs
* - [25,70]: All 45 secs
* - [70,130]: All 60 secs
* - [130, 210]: Only 5 secs (event ended at 135sec)
*/
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, startTimeNs, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, endTimeNs, tagId);
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(3UL, buckets.size());
EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
/**
* Expected buckets (start at 11s, upgrade at 75s, end at 135s):
* - [10,70]: 59 secs
* - [70,75]: 5 sec
* - [75,130]: 55 secs
*/
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, startTimeNs, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, endTimeNs, tagId);
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(3UL, buckets.size());
EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
sp<AlarmMonitor> alarmMonitor;
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1;
int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, startTimeNs, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, endTimeNs, tagId);
// Setup metric with alert.
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
Alert alert;
alert.set_num_buckets(3);
alert.set_trigger_if_sum_gt(2);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
}
TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1;
int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, startTimeNs, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, endTimeNs, tagId);
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1;
int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
int tagId = 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event1, startTimeNs, tagId);
LogEvent event2(/*uid=*/0, /*pid=*/0);
makeLogEvent(&event2, endTimeNs, tagId);
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */,
1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard,
dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// Stop occurs in the same partial bucket as created for the app upgrade.
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
}
} // namespace statsd
} // namespace os

View File

@@ -410,40 +410,75 @@ FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields)
return dimensions;
}
// TODO(b/149590301): Update these helpers to use new socket schema.
//std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
// const android::view::DisplayStateEnum state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(state));
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(
// android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(
// android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
// int level, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(level));
// event->init();
// return event;
//
//}
//
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
uint64_t timestampNs, const android::view::DisplayStateEnum state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::SCREEN_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, state);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::BATTERY_SAVER_MODE_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, BatterySaverModeStateChanged::ON);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::BATTERY_SAVER_MODE_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, BatterySaverModeStateChanged::OFF);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(uint64_t timestampNs, int level) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::SCREEN_BRIGHTNESS_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, level);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
//std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
// const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
@@ -470,121 +505,212 @@ FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields)
// attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
// const WakelockStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
// event->write(attributions);
// event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
// event->write(wakelockName);
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
// uint64_t timestampNs) {
// return CreateWakelockStateChangedEvent(
// attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
// uint64_t timestampNs) {
// return CreateWakelockStateChangedEvent(
// attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
// const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(
// android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
// event->write(uid);
// event->write("pkg_name");
// event->write("class_name");
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
// return CreateActivityForegroundStateChangedEvent(
// uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
// return CreateActivityForegroundStateChangedEvent(
// uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& name,
// const SyncStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
// event->write(attributions);
// event->write(name);
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateSyncStartEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& name,
// uint64_t timestampNs) {
// return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateSyncEndEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& name,
// uint64_t timestampNs) {
// return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
// const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
// auto logEvent = std::make_unique<LogEvent>(
// android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
// logEvent->write(uid);
// logEvent->write("");
// logEvent->write(state);
// logEvent->init();
// return logEvent;
//}
//
//std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
// return CreateProcessLifeCycleStateChangedEvent(
// uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
// event->write(uid);
// event->write("eventType");
// event->write("processName");
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
// int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
// auto logEvent = std::make_unique<LogEvent>(
// android::util::ISOLATED_UID_CHANGED, timestampNs);
// logEvent->write(hostUid);
// logEvent->write(isolatedUid);
// logEvent->write(is_create);
// logEvent->init();
// return logEvent;
//}
//
//std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
// int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
// event->write(uid);
// event->write(state);
// event->init();
// return event;
//}
std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(uint64_t timestampNs,
const vector<int>& attributionUids,
const vector<string>& attributionTags,
const string& wakelockName,
const WakelockStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::WAKELOCK_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
vector<const char*> cTags(attributionTags.size());
for (int i = 0; i < cTags.size(); i++) {
cTags[i] = attributionTags[i].c_str();
}
AStatsEvent_writeAttributionChain(statsEvent,
reinterpret_cast<const uint32_t*>(attributionUids.data()),
cTags.data(), attributionUids.size());
AStatsEvent_writeInt32(statsEvent, android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
AStatsEvent_writeString(statsEvent, wakelockName.c_str());
AStatsEvent_writeInt32(statsEvent, state);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(uint64_t timestampNs,
const vector<int>& attributionUids,
const vector<string>& attributionTags,
const string& wakelockName) {
return CreateWakelockStateChangedEvent(timestampNs, attributionUids, attributionTags,
wakelockName, WakelockStateChanged::ACQUIRE);
}
std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(uint64_t timestampNs,
const vector<int>& attributionUids,
const vector<string>& attributionTags,
const string& wakelockName) {
return CreateWakelockStateChangedEvent(timestampNs, attributionUids, attributionTags,
wakelockName, WakelockStateChanged::RELEASE);
}
std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
uint64_t timestampNs, const int uid, const ActivityForegroundStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
AStatsEvent_writeString(statsEvent, "pkg_name");
AStatsEvent_writeString(statsEvent, "class_name");
AStatsEvent_writeInt32(statsEvent, state);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid) {
return CreateActivityForegroundStateChangedEvent(timestampNs, uid,
ActivityForegroundStateChanged::BACKGROUND);
}
std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid) {
return CreateActivityForegroundStateChangedEvent(timestampNs, uid,
ActivityForegroundStateChanged::FOREGROUND);
}
std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(uint64_t timestampNs,
const vector<int>& attributionUids,
const vector<string>& attributionTags,
const string& name,
const SyncStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::SYNC_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
vector<const char*> cTags(attributionTags.size());
for (int i = 0; i < cTags.size(); i++) {
cTags[i] = attributionTags[i].c_str();
}
AStatsEvent_writeAttributionChain(statsEvent,
reinterpret_cast<const uint32_t*>(attributionUids.data()),
cTags.data(), attributionUids.size());
AStatsEvent_writeString(statsEvent, name.c_str());
AStatsEvent_writeInt32(statsEvent, state);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateSyncStartEvent(uint64_t timestampNs,
const vector<int>& attributionUids,
const vector<string>& attributionTags,
const string& name) {
return CreateSyncStateChangedEvent(timestampNs, attributionUids, attributionTags, name,
SyncStateChanged::ON);
}
std::unique_ptr<LogEvent> CreateSyncEndEvent(uint64_t timestampNs,
const vector<int>& attributionUids,
const vector<string>& attributionTags,
const string& name) {
return CreateSyncStateChangedEvent(timestampNs, attributionUids, attributionTags, name,
SyncStateChanged::OFF);
}
std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
uint64_t timestampNs, const int uid, const ProcessLifeCycleStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
AStatsEvent_writeString(statsEvent, "");
AStatsEvent_writeInt32(statsEvent, state);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateAppCrashEvent(uint64_t timestampNs, const int uid) {
return CreateProcessLifeCycleStateChangedEvent(timestampNs, uid,
ProcessLifeCycleStateChanged::CRASHED);
}
std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(uint64_t timestampNs, const int uid) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::APP_CRASH_OCCURRED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
AStatsEvent_writeString(statsEvent, "eventType");
AStatsEvent_writeString(statsEvent, "processName");
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(uint64_t timestampNs, int hostUid,
int isolatedUid, bool is_create) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::ISOLATED_UID_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, hostUid);
AStatsEvent_writeInt32(statsEvent, isolatedUid);
AStatsEvent_writeInt32(statsEvent, is_create);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
uint64_t timestampNs, int uid, const android::app::ProcessStateEnum state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, android::util::UID_PROCESS_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
AStatsEvent_writeInt32(statsEvent, state);
AStatsEvent_build(statsEvent);
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
logEvent->parseBuffer(buf, size);
AStatsEvent_release(statsEvent);
return logEvent;
}
sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
const StatsdConfig& config, const ConfigKey& key,

View File

@@ -166,11 +166,10 @@ FieldMatcher CreateAttributionUidDimensions(const int atomId,
// Create log event for screen state changed.
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
const android::view::DisplayStateEnum state, uint64_t timestampNs);
uint64_t timestampNs, const android::view::DisplayStateEnum state);
// Create log event for screen brightness state changed.
std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
int level, uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(uint64_t timestampNs, int level);
// Create log event when scheduled job starts.
std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
@@ -188,45 +187,42 @@ std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs);
// Create log event for app moving to background.
std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid);
// Create log event for app moving to foreground.
std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid);
// Create log event when the app sync starts.
std::unique_ptr<LogEvent> CreateSyncStartEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateSyncStartEvent(uint64_t timestampNs, const vector<int>& uids,
const vector<string>& tags, const string& name);
// Create log event when the app sync ends.
std::unique_ptr<LogEvent> CreateSyncEndEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateSyncEndEvent(uint64_t timestampNs, const vector<int>& uids,
const vector<string>& tags, const string& name);
// Create log event when the app sync ends.
std::unique_ptr<LogEvent> CreateAppCrashEvent(
const int uid, uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateAppCrashEvent(uint64_t timestampNs, const int uid);
// Create log event for an app crash.
std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(uint64_t timestampNs, const int uid);
// Create log event for acquiring wakelock.
std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(uint64_t timestampNs, const vector<int>& uids,
const vector<string>& tags,
const string& wakelockName);
// Create log event for releasing wakelock.
std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(uint64_t timestampNs, const vector<int>& uids,
const vector<string>& tags,
const string& wakelockName);
// Create log event for releasing wakelock.
std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs);
std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(uint64_t timestampNs, int isolatedUid,
int hostUid, bool is_create);
// Create log event for uid process state change.
std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs);
uint64_t timestampNs, int uid, const android::app::ProcessStateEnum state);
// Helper function to create an AttributionNodeInternal proto.
AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);