| // Copyright (C) 2020 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "src/metrics/parsing_utils/config_update_utils.h" |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <private/android_filesystem_config.h> |
| #include <stdio.h> |
| |
| #include <set> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "packages/modules/StatsD/bin/src/statsd_config.pb.h" |
| #include "src/condition/CombinationConditionTracker.h" |
| #include "src/condition/SimpleConditionTracker.h" |
| #include "src/matchers/CombinationAtomMatchingTracker.h" |
| #include "src/metrics/DurationMetricProducer.h" |
| #include "src/metrics/GaugeMetricProducer.h" |
| #include "src/metrics/ValueMetricProducer.h" |
| #include "src/metrics/parsing_utils/metrics_manager_util.h" |
| #include "tests/statsd_test_util.h" |
| |
| using namespace testing; |
| using android::sp; |
| using android::os::statsd::Predicate; |
| using std::map; |
| using std::nullopt; |
| using std::optional; |
| using std::set; |
| using std::unordered_map; |
| using std::vector; |
| |
| #ifdef __ANDROID__ |
| |
| namespace android { |
| namespace os { |
| namespace statsd { |
| |
| namespace { |
| |
| ConfigKey key(123, 456); |
| const int64_t timeBaseNs = 1000 * NS_PER_SEC; |
| |
| sp<UidMap> uidMap = new UidMap(); |
| sp<StatsPullerManager> pullerManager = new StatsPullerManager(); |
| sp<AlarmMonitor> anomalyAlarmMonitor; |
| sp<AlarmMonitor> periodicAlarmMonitor = new AlarmMonitor( |
| /*minDiffToUpdateRegisteredAlarmTimeSec=*/0, |
| [](const shared_ptr<IStatsCompanionService>&, int64_t) {}, |
| [](const shared_ptr<IStatsCompanionService>&) {}); |
| set<int> allTagIds; |
| vector<sp<AtomMatchingTracker>> oldAtomMatchingTrackers; |
| unordered_map<int64_t, int> oldAtomMatchingTrackerMap; |
| vector<sp<ConditionTracker>> oldConditionTrackers; |
| unordered_map<int64_t, int> oldConditionTrackerMap; |
| vector<sp<MetricProducer>> oldMetricProducers; |
| unordered_map<int64_t, int> oldMetricProducerMap; |
| std::vector<sp<AnomalyTracker>> oldAnomalyTrackers; |
| unordered_map<int64_t, int> oldAlertTrackerMap; |
| std::vector<sp<AlarmTracker>> oldAlarmTrackers; |
| unordered_map<int, std::vector<int>> tmpConditionToMetricMap; |
| unordered_map<int, std::vector<int>> tmpTrackerToMetricMap; |
| unordered_map<int, std::vector<int>> tmpTrackerToConditionMap; |
| unordered_map<int, std::vector<int>> tmpActivationAtomTrackerToMetricMap; |
| unordered_map<int, std::vector<int>> tmpDeactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| map<int64_t, uint64_t> oldStateHashes; |
| std::set<int64_t> noReportMetricIds; |
| |
| class ConfigUpdateTest : public ::testing::Test { |
| public: |
| ConfigUpdateTest() { |
| } |
| |
| void SetUp() override { |
| allTagIds.clear(); |
| oldAtomMatchingTrackers.clear(); |
| oldAtomMatchingTrackerMap.clear(); |
| oldConditionTrackers.clear(); |
| oldConditionTrackerMap.clear(); |
| oldMetricProducers.clear(); |
| oldMetricProducerMap.clear(); |
| oldAnomalyTrackers.clear(); |
| oldAlarmTrackers.clear(); |
| tmpConditionToMetricMap.clear(); |
| tmpTrackerToMetricMap.clear(); |
| tmpTrackerToConditionMap.clear(); |
| tmpActivationAtomTrackerToMetricMap.clear(); |
| tmpDeactivationAtomTrackerToMetricMap.clear(); |
| oldAlertTrackerMap.clear(); |
| metricsWithActivation.clear(); |
| oldStateHashes.clear(); |
| noReportMetricIds.clear(); |
| StateManager::getInstance().clear(); |
| } |
| }; |
| |
| bool initConfig(const StatsdConfig& config) { |
| return initStatsdConfig( |
| key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, |
| timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap, |
| oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldMetricProducerMap, |
| oldAnomalyTrackers, oldAlarmTrackers, tmpConditionToMetricMap, tmpTrackerToMetricMap, |
| tmpTrackerToConditionMap, tmpActivationAtomTrackerToMetricMap, |
| tmpDeactivationAtomTrackerToMetricMap, oldAlertTrackerMap, metricsWithActivation, |
| oldStateHashes, noReportMetricIds); |
| } |
| |
| EventMetric createEventMetric(string name, int64_t what, optional<int64_t> condition) { |
| EventMetric metric; |
| metric.set_id(StringToId(name)); |
| metric.set_what(what); |
| if (condition) { |
| metric.set_condition(condition.value()); |
| } |
| return metric; |
| } |
| |
| DurationMetric createDurationMetric(string name, int64_t what, optional<int64_t> condition, |
| vector<int64_t> states) { |
| DurationMetric metric; |
| metric.set_id(StringToId(name)); |
| metric.set_what(what); |
| metric.set_bucket(TEN_MINUTES); |
| if (condition) { |
| metric.set_condition(condition.value()); |
| } |
| for (const int64_t state : states) { |
| metric.add_slice_by_state(state); |
| } |
| return metric; |
| } |
| |
| ValueMetric createValueMetric(string name, const AtomMatcher& what, optional<int64_t> condition, |
| vector<int64_t> states) { |
| ValueMetric metric; |
| metric.set_id(StringToId(name)); |
| metric.set_what(what.id()); |
| metric.set_bucket(TEN_MINUTES); |
| metric.mutable_value_field()->set_field(what.simple_atom_matcher().atom_id()); |
| metric.mutable_value_field()->add_child()->set_field(2); |
| if (condition) { |
| metric.set_condition(condition.value()); |
| } |
| for (const int64_t state : states) { |
| metric.add_slice_by_state(state); |
| } |
| return metric; |
| } |
| |
| Alert createAlert(string name, int64_t metricId, int buckets, int64_t triggerSum) { |
| Alert alert; |
| alert.set_id(StringToId(name)); |
| alert.set_metric_id(metricId); |
| alert.set_num_buckets(buckets); |
| alert.set_trigger_if_sum_gt(triggerSum); |
| return alert; |
| } |
| |
| Subscription createSubscription(string name, Subscription_RuleType type, int64_t ruleId) { |
| Subscription subscription; |
| subscription.set_id(StringToId(name)); |
| subscription.set_rule_type(type); |
| subscription.set_rule_id(ruleId); |
| subscription.mutable_broadcast_subscriber_details(); |
| return subscription; |
| } |
| |
| Alarm createAlarm(string name, int64_t offsetMillis, int64_t periodMillis) { |
| Alarm alarm; |
| alarm.set_id(StringToId(name)); |
| alarm.set_offset_millis(offsetMillis); |
| alarm.set_period_millis(periodMillis); |
| return alarm; |
| } |
| } // anonymous namespace |
| |
| TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) { |
| StatsdConfig config; |
| AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10); |
| int64_t matcherId = matcher.id(); |
| *config.add_atom_matcher() = matcher; |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(1, false); |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| newAtomMatchingTrackerMap[matcherId] = 0; |
| EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldAtomMatchingTrackerMap, |
| oldAtomMatchingTrackers, newAtomMatchingTrackerMap, |
| matchersToUpdate, cycleTracker)); |
| EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) { |
| StatsdConfig config; |
| AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10); |
| *config.add_atom_matcher() = matcher; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| StatsdConfig newConfig; |
| // Same id, different atom, so should be replaced. |
| AtomMatcher newMatcher = CreateSimpleAtomMatcher("TEST", /*atom=*/11); |
| int64_t matcherId = newMatcher.id(); |
| EXPECT_EQ(matcherId, matcher.id()); |
| *newConfig.add_atom_matcher() = newMatcher; |
| |
| vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(1, false); |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| newAtomMatchingTrackerMap[matcherId] = 0; |
| EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap, |
| oldAtomMatchingTrackers, newAtomMatchingTrackerMap, |
| matchersToUpdate, cycleTracker)); |
| EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestSimpleMatcherNew) { |
| StatsdConfig config; |
| AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10); |
| *config.add_atom_matcher() = matcher; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| StatsdConfig newConfig; |
| // Different id, so should be a new matcher. |
| AtomMatcher newMatcher = CreateSimpleAtomMatcher("DIFFERENT_NAME", /*atom=*/10); |
| int64_t matcherId = newMatcher.id(); |
| EXPECT_NE(matcherId, matcher.id()); |
| *newConfig.add_atom_matcher() = newMatcher; |
| |
| vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(1, false); |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| newAtomMatchingTrackerMap[matcherId] = 0; |
| EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap, |
| oldAtomMatchingTrackers, newAtomMatchingTrackerMap, |
| matchersToUpdate, cycleTracker)); |
| EXPECT_EQ(matchersToUpdate[0], UPDATE_NEW); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) { |
| StatsdConfig config; |
| AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11); |
| *config.add_atom_matcher() = matcher2; |
| int64_t matcher2Id = matcher2.id(); |
| |
| AtomMatcher matcher3; |
| matcher3.set_id(StringToId("TEST3")); |
| AtomMatcher_Combination* combination = matcher3.mutable_combination(); |
| combination->set_operation(LogicalOperation::OR); |
| combination->add_matcher(matcher1Id); |
| combination->add_matcher(matcher2Id); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| StatsdConfig newConfig; |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| // Same matchers, different order, all should be preserved. |
| *newConfig.add_atom_matcher() = matcher2; |
| newAtomMatchingTrackerMap[matcher2Id] = 0; |
| *newConfig.add_atom_matcher() = matcher3; |
| newAtomMatchingTrackerMap[matcher3Id] = 1; |
| *newConfig.add_atom_matcher() = matcher1; |
| newAtomMatchingTrackerMap[matcher1Id] = 2; |
| |
| vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(3, false); |
| // Only update the combination. It should recurse the two child matchers and preserve all 3. |
| EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, |
| oldAtomMatchingTrackers, newAtomMatchingTrackerMap, |
| matchersToUpdate, cycleTracker)); |
| EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE); |
| EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE); |
| EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) { |
| StatsdConfig config; |
| AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11); |
| *config.add_atom_matcher() = matcher2; |
| int64_t matcher2Id = matcher2.id(); |
| |
| AtomMatcher matcher3; |
| matcher3.set_id(StringToId("TEST3")); |
| AtomMatcher_Combination* combination = matcher3.mutable_combination(); |
| combination->set_operation(LogicalOperation::OR); |
| combination->add_matcher(matcher1Id); |
| combination->add_matcher(matcher2Id); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change the logical operation of the combination matcher, causing a replacement. |
| matcher3.mutable_combination()->set_operation(LogicalOperation::AND); |
| |
| StatsdConfig newConfig; |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| *newConfig.add_atom_matcher() = matcher2; |
| newAtomMatchingTrackerMap[matcher2Id] = 0; |
| *newConfig.add_atom_matcher() = matcher3; |
| newAtomMatchingTrackerMap[matcher3Id] = 1; |
| *newConfig.add_atom_matcher() = matcher1; |
| newAtomMatchingTrackerMap[matcher1Id] = 2; |
| |
| vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(3, false); |
| // Only update the combination. The simple matchers should not be evaluated. |
| EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, |
| oldAtomMatchingTrackers, newAtomMatchingTrackerMap, |
| matchersToUpdate, cycleTracker)); |
| EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN); |
| EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE); |
| EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) { |
| StatsdConfig config; |
| AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11); |
| *config.add_atom_matcher() = matcher2; |
| int64_t matcher2Id = matcher2.id(); |
| |
| AtomMatcher matcher3; |
| matcher3.set_id(StringToId("TEST3")); |
| AtomMatcher_Combination* combination = matcher3.mutable_combination(); |
| combination->set_operation(LogicalOperation::OR); |
| combination->add_matcher(matcher1Id); |
| combination->add_matcher(matcher2Id); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change a dependency of matcher 3. |
| matcher2.mutable_simple_atom_matcher()->set_atom_id(12); |
| |
| StatsdConfig newConfig; |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| *newConfig.add_atom_matcher() = matcher2; |
| newAtomMatchingTrackerMap[matcher2Id] = 0; |
| *newConfig.add_atom_matcher() = matcher3; |
| newAtomMatchingTrackerMap[matcher3Id] = 1; |
| *newConfig.add_atom_matcher() = matcher1; |
| newAtomMatchingTrackerMap[matcher1Id] = 2; |
| |
| vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(3, false); |
| // Only update the combination. |
| EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, |
| oldAtomMatchingTrackers, newAtomMatchingTrackerMap, |
| matchersToUpdate, cycleTracker)); |
| // Matcher 2 and matcher3 must be reevaluated. Matcher 1 might, but does not need to be. |
| EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE); |
| EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateMatchers) { |
| StatsdConfig config; |
| // Will be preserved. |
| AtomMatcher simple1 = CreateSimpleAtomMatcher("SIMPLE1", /*atom=*/10); |
| int64_t simple1Id = simple1.id(); |
| *config.add_atom_matcher() = simple1; |
| |
| // Will be replaced. |
| AtomMatcher simple2 = CreateSimpleAtomMatcher("SIMPLE2", /*atom=*/11); |
| *config.add_atom_matcher() = simple2; |
| int64_t simple2Id = simple2.id(); |
| |
| // Will be removed. |
| AtomMatcher simple3 = CreateSimpleAtomMatcher("SIMPLE3", /*atom=*/12); |
| *config.add_atom_matcher() = simple3; |
| int64_t simple3Id = simple3.id(); |
| |
| // Will be preserved. |
| AtomMatcher combination1; |
| combination1.set_id(StringToId("combination1")); |
| AtomMatcher_Combination* combination = combination1.mutable_combination(); |
| combination->set_operation(LogicalOperation::NOT); |
| combination->add_matcher(simple1Id); |
| int64_t combination1Id = combination1.id(); |
| *config.add_atom_matcher() = combination1; |
| |
| // Will be replaced since it depends on simple2. |
| AtomMatcher combination2; |
| combination2.set_id(StringToId("combination2")); |
| combination = combination2.mutable_combination(); |
| combination->set_operation(LogicalOperation::AND); |
| combination->add_matcher(simple1Id); |
| combination->add_matcher(simple2Id); |
| int64_t combination2Id = combination2.id(); |
| *config.add_atom_matcher() = combination2; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change simple2, causing simple2 and combination2 to be replaced. |
| simple2.mutable_simple_atom_matcher()->set_atom_id(111); |
| |
| // 2 new matchers: simple4 and combination3: |
| AtomMatcher simple4 = CreateSimpleAtomMatcher("SIMPLE4", /*atom=*/13); |
| int64_t simple4Id = simple4.id(); |
| |
| AtomMatcher combination3; |
| combination3.set_id(StringToId("combination3")); |
| combination = combination3.mutable_combination(); |
| combination->set_operation(LogicalOperation::AND); |
| combination->add_matcher(simple4Id); |
| combination->add_matcher(simple2Id); |
| int64_t combination3Id = combination3.id(); |
| |
| StatsdConfig newConfig; |
| *newConfig.add_atom_matcher() = combination3; |
| *newConfig.add_atom_matcher() = simple2; |
| *newConfig.add_atom_matcher() = combination2; |
| *newConfig.add_atom_matcher() = simple1; |
| *newConfig.add_atom_matcher() = simple4; |
| *newConfig.add_atom_matcher() = combination1; |
| |
| set<int> newTagIds; |
| unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers; |
| set<int64_t> replacedMatchers; |
| EXPECT_TRUE(updateAtomMatchingTrackers( |
| newConfig, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newTagIds, |
| newAtomMatchingTrackerMap, newAtomMatchingTrackers, replacedMatchers)); |
| |
| ASSERT_EQ(newTagIds.size(), 3); |
| EXPECT_EQ(newTagIds.count(10), 1); |
| EXPECT_EQ(newTagIds.count(111), 1); |
| EXPECT_EQ(newTagIds.count(13), 1); |
| |
| ASSERT_EQ(newAtomMatchingTrackerMap.size(), 6); |
| EXPECT_EQ(newAtomMatchingTrackerMap.at(combination3Id), 0); |
| EXPECT_EQ(newAtomMatchingTrackerMap.at(simple2Id), 1); |
| EXPECT_EQ(newAtomMatchingTrackerMap.at(combination2Id), 2); |
| EXPECT_EQ(newAtomMatchingTrackerMap.at(simple1Id), 3); |
| EXPECT_EQ(newAtomMatchingTrackerMap.at(simple4Id), 4); |
| EXPECT_EQ(newAtomMatchingTrackerMap.at(combination1Id), 5); |
| |
| ASSERT_EQ(newAtomMatchingTrackers.size(), 6); |
| // Make sure all atom matchers are initialized: |
| for (const sp<AtomMatchingTracker>& tracker : newAtomMatchingTrackers) { |
| EXPECT_TRUE(tracker->mInitialized); |
| } |
| // Make sure preserved atom matchers are the same. |
| EXPECT_EQ(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(simple1Id)], |
| newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(simple1Id)]); |
| EXPECT_EQ(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination1Id)], |
| newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(combination1Id)]); |
| // Make sure replaced matchers are different. |
| EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(simple2Id)], |
| newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(simple2Id)]); |
| EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination2Id)], |
| newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(combination2Id)]); |
| |
| // Validation, make sure the matchers have the proper ids/indices. Could do more checks here. |
| EXPECT_EQ(newAtomMatchingTrackers[0]->getId(), combination3Id); |
| EXPECT_EQ(newAtomMatchingTrackers[0]->mIndex, 0); |
| EXPECT_EQ(newAtomMatchingTrackers[1]->getId(), simple2Id); |
| EXPECT_EQ(newAtomMatchingTrackers[1]->mIndex, 1); |
| EXPECT_EQ(newAtomMatchingTrackers[2]->getId(), combination2Id); |
| EXPECT_EQ(newAtomMatchingTrackers[2]->mIndex, 2); |
| EXPECT_EQ(newAtomMatchingTrackers[3]->getId(), simple1Id); |
| EXPECT_EQ(newAtomMatchingTrackers[3]->mIndex, 3); |
| EXPECT_EQ(newAtomMatchingTrackers[4]->getId(), simple4Id); |
| EXPECT_EQ(newAtomMatchingTrackers[4]->mIndex, 4); |
| EXPECT_EQ(newAtomMatchingTrackers[5]->getId(), combination1Id); |
| EXPECT_EQ(newAtomMatchingTrackers[5]->mIndex, 5); |
| |
| // Verify child indices of Combination Matchers are correct. |
| CombinationAtomMatchingTracker* combinationTracker1 = |
| static_cast<CombinationAtomMatchingTracker*>(newAtomMatchingTrackers[5].get()); |
| vector<int>* childMatchers = &combinationTracker1->mChildren; |
| EXPECT_EQ(childMatchers->size(), 1); |
| EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 3), childMatchers->end()); |
| |
| CombinationAtomMatchingTracker* combinationTracker2 = |
| static_cast<CombinationAtomMatchingTracker*>(newAtomMatchingTrackers[2].get()); |
| childMatchers = &combinationTracker2->mChildren; |
| EXPECT_EQ(childMatchers->size(), 2); |
| EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 1), childMatchers->end()); |
| EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 3), childMatchers->end()); |
| |
| CombinationAtomMatchingTracker* combinationTracker3 = |
| static_cast<CombinationAtomMatchingTracker*>(newAtomMatchingTrackers[0].get()); |
| childMatchers = &combinationTracker3->mChildren; |
| EXPECT_EQ(childMatchers->size(), 2); |
| EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 1), childMatchers->end()); |
| EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 4), childMatchers->end()); |
| |
| // Expect replacedMatchers to have simple2 and combination2 |
| ASSERT_EQ(replacedMatchers.size(), 2); |
| EXPECT_NE(replacedMatchers.find(simple2Id), replacedMatchers.end()); |
| EXPECT_NE(replacedMatchers.find(combination2Id), replacedMatchers.end()); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestSimpleConditionPreserve) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| set<int64_t> replacedMatchers; |
| vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(1, false); |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| newConditionTrackerMap[predicate.id()] = 0; |
| EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap, |
| oldConditionTrackers, newConditionTrackerMap, |
| replacedMatchers, conditionsToUpdate, cycleTracker)); |
| EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestSimpleConditionReplace) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Modify the predicate. |
| config.mutable_predicate(0)->mutable_simple_predicate()->set_count_nesting(true); |
| |
| set<int64_t> replacedMatchers; |
| vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(1, false); |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| newConditionTrackerMap[predicate.id()] = 0; |
| EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap, |
| oldConditionTrackers, newConditionTrackerMap, |
| replacedMatchers, conditionsToUpdate, cycleTracker)); |
| EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestSimpleConditionDepsChange) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| int64_t startMatcherId = startMatcher.id(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Start matcher was replaced. |
| set<int64_t> replacedMatchers; |
| replacedMatchers.insert(startMatcherId); |
| |
| vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(1, false); |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| newConditionTrackerMap[predicate.id()] = 0; |
| EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap, |
| oldConditionTrackers, newConditionTrackerMap, |
| replacedMatchers, conditionsToUpdate, cycleTracker)); |
| EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCombinationConditionPreserve) { |
| StatsdConfig config; |
| AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = screenOnMatcher; |
| AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = screenOffMatcher; |
| |
| Predicate simple1 = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = simple1; |
| Predicate simple2 = CreateScreenIsOffPredicate(); |
| *config.add_predicate() = simple2; |
| |
| Predicate combination1; |
| combination1.set_id(StringToId("COMBINATION1")); |
| Predicate_Combination* combinationInternal = combination1.mutable_combination(); |
| combinationInternal->set_operation(LogicalOperation::NAND); |
| combinationInternal->add_predicate(simple1.id()); |
| combinationInternal->add_predicate(simple2.id()); |
| *config.add_predicate() = combination1; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Same predicates, different order |
| StatsdConfig newConfig; |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| *newConfig.add_predicate() = combination1; |
| newConditionTrackerMap[combination1.id()] = 0; |
| *newConfig.add_predicate() = simple2; |
| newConditionTrackerMap[simple2.id()] = 1; |
| *newConfig.add_predicate() = simple1; |
| newConditionTrackerMap[simple1.id()] = 2; |
| |
| set<int64_t> replacedMatchers; |
| vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(3, false); |
| // Only update the combination. It should recurse the two child predicates and preserve all 3. |
| EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap, |
| oldConditionTrackers, newConditionTrackerMap, |
| replacedMatchers, conditionsToUpdate, cycleTracker)); |
| EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE); |
| EXPECT_EQ(conditionsToUpdate[1], UPDATE_PRESERVE); |
| EXPECT_EQ(conditionsToUpdate[2], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCombinationConditionReplace) { |
| StatsdConfig config; |
| AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = screenOnMatcher; |
| AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = screenOffMatcher; |
| |
| Predicate simple1 = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = simple1; |
| Predicate simple2 = CreateScreenIsOffPredicate(); |
| *config.add_predicate() = simple2; |
| |
| Predicate combination1; |
| combination1.set_id(StringToId("COMBINATION1")); |
| Predicate_Combination* combinationInternal = combination1.mutable_combination(); |
| combinationInternal->set_operation(LogicalOperation::NAND); |
| combinationInternal->add_predicate(simple1.id()); |
| combinationInternal->add_predicate(simple2.id()); |
| *config.add_predicate() = combination1; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Changing the logical operation changes the predicate definition, so it should be replaced. |
| combination1.mutable_combination()->set_operation(LogicalOperation::OR); |
| |
| StatsdConfig newConfig; |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| *newConfig.add_predicate() = combination1; |
| newConditionTrackerMap[combination1.id()] = 0; |
| *newConfig.add_predicate() = simple2; |
| newConditionTrackerMap[simple2.id()] = 1; |
| *newConfig.add_predicate() = simple1; |
| newConditionTrackerMap[simple1.id()] = 2; |
| |
| set<int64_t> replacedMatchers; |
| vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(3, false); |
| // Only update the combination. The simple conditions should not be evaluated. |
| EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap, |
| oldConditionTrackers, newConditionTrackerMap, |
| replacedMatchers, conditionsToUpdate, cycleTracker)); |
| EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE); |
| EXPECT_EQ(conditionsToUpdate[1], UPDATE_UNKNOWN); |
| EXPECT_EQ(conditionsToUpdate[2], UPDATE_UNKNOWN); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) { |
| StatsdConfig config; |
| AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = screenOnMatcher; |
| AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = screenOffMatcher; |
| |
| Predicate simple1 = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = simple1; |
| Predicate simple2 = CreateScreenIsOffPredicate(); |
| *config.add_predicate() = simple2; |
| |
| Predicate combination1; |
| combination1.set_id(StringToId("COMBINATION1")); |
| Predicate_Combination* combinationInternal = combination1.mutable_combination(); |
| combinationInternal->set_operation(LogicalOperation::NAND); |
| combinationInternal->add_predicate(simple1.id()); |
| combinationInternal->add_predicate(simple2.id()); |
| *config.add_predicate() = combination1; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| simple2.mutable_simple_predicate()->set_count_nesting(false); |
| |
| StatsdConfig newConfig; |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| *newConfig.add_predicate() = combination1; |
| newConditionTrackerMap[combination1.id()] = 0; |
| *newConfig.add_predicate() = simple2; |
| newConditionTrackerMap[simple2.id()] = 1; |
| *newConfig.add_predicate() = simple1; |
| newConditionTrackerMap[simple1.id()] = 2; |
| |
| set<int64_t> replacedMatchers; |
| vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN); |
| vector<bool> cycleTracker(3, false); |
| // Only update the combination. Simple2 and combination1 must be evaluated. |
| EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap, |
| oldConditionTrackers, newConditionTrackerMap, |
| replacedMatchers, conditionsToUpdate, cycleTracker)); |
| EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE); |
| EXPECT_EQ(conditionsToUpdate[1], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateConditions) { |
| StatsdConfig config; |
| // Add atom matchers. These are mostly needed for initStatsdConfig |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher(); |
| int64_t matcher5Id = matcher5.id(); |
| *config.add_atom_matcher() = matcher5; |
| |
| AtomMatcher matcher6 = CreateBatterySaverModeStopAtomMatcher(); |
| int64_t matcher6Id = matcher6.id(); |
| *config.add_atom_matcher() = matcher6; |
| |
| // Add the predicates. |
| // Will be preserved. |
| Predicate simple1 = CreateScreenIsOnPredicate(); |
| int64_t simple1Id = simple1.id(); |
| *config.add_predicate() = simple1; |
| |
| // Will be preserved. |
| Predicate simple2 = CreateScheduledJobPredicate(); |
| int64_t simple2Id = simple2.id(); |
| *config.add_predicate() = simple2; |
| |
| // Will be replaced. |
| Predicate simple3 = CreateBatterySaverModePredicate(); |
| int64_t simple3Id = simple3.id(); |
| *config.add_predicate() = simple3; |
| |
| // Will be preserved |
| Predicate combination1; |
| combination1.set_id(StringToId("COMBINATION1")); |
| combination1.mutable_combination()->set_operation(LogicalOperation::AND); |
| combination1.mutable_combination()->add_predicate(simple1Id); |
| combination1.mutable_combination()->add_predicate(simple2Id); |
| int64_t combination1Id = combination1.id(); |
| *config.add_predicate() = combination1; |
| |
| // Will be replaced since simple3 will be replaced. |
| Predicate combination2; |
| combination2.set_id(StringToId("COMBINATION2")); |
| combination2.mutable_combination()->set_operation(LogicalOperation::OR); |
| combination2.mutable_combination()->add_predicate(simple1Id); |
| combination2.mutable_combination()->add_predicate(simple3Id); |
| int64_t combination2Id = combination2.id(); |
| *config.add_predicate() = combination2; |
| |
| // Will be removed. |
| Predicate combination3; |
| combination3.set_id(StringToId("COMBINATION3")); |
| combination3.mutable_combination()->set_operation(LogicalOperation::NOT); |
| combination3.mutable_combination()->add_predicate(simple2Id); |
| int64_t combination3Id = combination3.id(); |
| *config.add_predicate() = combination3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Mark marcher 5 as replaced. Causes simple3, and therefore combination2 to be replaced. |
| set<int64_t> replacedMatchers; |
| replacedMatchers.insert(matcher6Id); |
| |
| // Change the condition of simple1 to false. |
| ASSERT_EQ(oldConditionTrackers[0]->getConditionId(), simple1Id); |
| LogEvent event(/*uid=*/0, /*pid=*/0); // Empty event is fine since there are no dimensions. |
| // Mark the stop matcher as matched, condition should be false. |
| vector<MatchingState> eventMatcherValues(6, MatchingState::kNotMatched); |
| eventMatcherValues[1] = MatchingState::kMatched; |
| vector<ConditionState> tmpConditionCache(6, ConditionState::kNotEvaluated); |
| vector<bool> conditionChangeCache(6, false); |
| oldConditionTrackers[0]->evaluateCondition(event, eventMatcherValues, oldConditionTrackers, |
| tmpConditionCache, conditionChangeCache); |
| EXPECT_EQ(tmpConditionCache[0], ConditionState::kFalse); |
| EXPECT_EQ(conditionChangeCache[0], true); |
| |
| // New combination predicate. Should have an initial condition of true since it is NOT(simple1). |
| Predicate combination4; |
| combination4.set_id(StringToId("COMBINATION4")); |
| combination4.mutable_combination()->set_operation(LogicalOperation::NOT); |
| combination4.mutable_combination()->add_predicate(simple1Id); |
| int64_t combination4Id = combination4.id(); |
| *config.add_predicate() = combination4; |
| |
| // Map the matchers in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher6Index = 0; |
| newAtomMatchingTrackerMap[matcher6Id] = 0; |
| const int matcher5Index = 1; |
| newAtomMatchingTrackerMap[matcher5Id] = 1; |
| const int matcher4Index = 2; |
| newAtomMatchingTrackerMap[matcher4Id] = 2; |
| const int matcher3Index = 3; |
| newAtomMatchingTrackerMap[matcher3Id] = 3; |
| const int matcher2Index = 4; |
| newAtomMatchingTrackerMap[matcher2Id] = 4; |
| const int matcher1Index = 5; |
| newAtomMatchingTrackerMap[matcher1Id] = 5; |
| |
| StatsdConfig newConfig; |
| *newConfig.add_predicate() = simple3; |
| const int simple3Index = 0; |
| *newConfig.add_predicate() = combination2; |
| const int combination2Index = 1; |
| *newConfig.add_predicate() = combination4; |
| const int combination4Index = 2; |
| *newConfig.add_predicate() = simple2; |
| const int simple2Index = 3; |
| *newConfig.add_predicate() = combination1; |
| const int combination1Index = 4; |
| *newConfig.add_predicate() = simple1; |
| const int simple1Index = 5; |
| |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| vector<sp<ConditionTracker>> newConditionTrackers; |
| unordered_map<int, vector<int>> trackerToConditionMap; |
| std::vector<ConditionState> conditionCache; |
| std::set<int64_t> replacedConditions; |
| EXPECT_TRUE(updateConditions(key, newConfig, newAtomMatchingTrackerMap, replacedMatchers, |
| oldConditionTrackerMap, oldConditionTrackers, |
| newConditionTrackerMap, newConditionTrackers, |
| trackerToConditionMap, conditionCache, replacedConditions)); |
| |
| unordered_map<int64_t, int> expectedConditionTrackerMap = { |
| {simple1Id, simple1Index}, {simple2Id, simple2Index}, |
| {simple3Id, simple3Index}, {combination1Id, combination1Index}, |
| {combination2Id, combination2Index}, {combination4Id, combination4Index}, |
| }; |
| EXPECT_THAT(newConditionTrackerMap, ContainerEq(expectedConditionTrackerMap)); |
| |
| ASSERT_EQ(newConditionTrackers.size(), 6); |
| // Make sure all conditions are initialized: |
| for (const sp<ConditionTracker>& tracker : newConditionTrackers) { |
| EXPECT_TRUE(tracker->mInitialized); |
| } |
| |
| // Make sure preserved conditions are the same. |
| EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple1Id)], |
| newConditionTrackers[newConditionTrackerMap.at(simple1Id)]); |
| EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple2Id)], |
| newConditionTrackers[newConditionTrackerMap.at(simple2Id)]); |
| EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(combination1Id)], |
| newConditionTrackers[newConditionTrackerMap.at(combination1Id)]); |
| |
| // Make sure replaced conditions are different and included in replacedConditions. |
| EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(simple3Id)], |
| newConditionTrackers[newConditionTrackerMap.at(simple3Id)]); |
| EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(combination2Id)], |
| newConditionTrackers[newConditionTrackerMap.at(combination2Id)]); |
| EXPECT_THAT(replacedConditions, ContainerEq(set({simple3Id, combination2Id}))); |
| |
| // Verify the trackerToConditionMap |
| ASSERT_EQ(trackerToConditionMap.size(), 6); |
| const vector<int>& matcher1Conditions = trackerToConditionMap[matcher1Index]; |
| EXPECT_THAT(matcher1Conditions, UnorderedElementsAre(simple1Index, combination1Index, |
| combination2Index, combination4Index)); |
| const vector<int>& matcher2Conditions = trackerToConditionMap[matcher2Index]; |
| EXPECT_THAT(matcher2Conditions, UnorderedElementsAre(simple1Index, combination1Index, |
| combination2Index, combination4Index)); |
| const vector<int>& matcher3Conditions = trackerToConditionMap[matcher3Index]; |
| EXPECT_THAT(matcher3Conditions, UnorderedElementsAre(simple2Index, combination1Index)); |
| const vector<int>& matcher4Conditions = trackerToConditionMap[matcher4Index]; |
| EXPECT_THAT(matcher4Conditions, UnorderedElementsAre(simple2Index, combination1Index)); |
| const vector<int>& matcher5Conditions = trackerToConditionMap[matcher5Index]; |
| EXPECT_THAT(matcher5Conditions, UnorderedElementsAre(simple3Index, combination2Index)); |
| const vector<int>& matcher6Conditions = trackerToConditionMap[matcher6Index]; |
| EXPECT_THAT(matcher6Conditions, UnorderedElementsAre(simple3Index, combination2Index)); |
| |
| // Verify the conditionCache. Specifically, simple1 is false and combination4 is true. |
| ASSERT_EQ(conditionCache.size(), 6); |
| EXPECT_EQ(conditionCache[simple1Index], ConditionState::kFalse); |
| EXPECT_EQ(conditionCache[simple2Index], ConditionState::kUnknown); |
| EXPECT_EQ(conditionCache[simple3Index], ConditionState::kUnknown); |
| EXPECT_EQ(conditionCache[combination1Index], ConditionState::kUnknown); |
| EXPECT_EQ(conditionCache[combination2Index], ConditionState::kUnknown); |
| EXPECT_EQ(conditionCache[combination4Index], ConditionState::kTrue); |
| |
| // Verify tracker indices/ids are correct. |
| EXPECT_EQ(newConditionTrackers[simple1Index]->getConditionId(), simple1Id); |
| EXPECT_EQ(newConditionTrackers[simple1Index]->mIndex, simple1Index); |
| EXPECT_TRUE(newConditionTrackers[simple1Index]->IsSimpleCondition()); |
| EXPECT_EQ(newConditionTrackers[simple2Index]->getConditionId(), simple2Id); |
| EXPECT_EQ(newConditionTrackers[simple2Index]->mIndex, simple2Index); |
| EXPECT_TRUE(newConditionTrackers[simple2Index]->IsSimpleCondition()); |
| EXPECT_EQ(newConditionTrackers[simple3Index]->getConditionId(), simple3Id); |
| EXPECT_EQ(newConditionTrackers[simple3Index]->mIndex, simple3Index); |
| EXPECT_TRUE(newConditionTrackers[simple3Index]->IsSimpleCondition()); |
| EXPECT_EQ(newConditionTrackers[combination1Index]->getConditionId(), combination1Id); |
| EXPECT_EQ(newConditionTrackers[combination1Index]->mIndex, combination1Index); |
| EXPECT_FALSE(newConditionTrackers[combination1Index]->IsSimpleCondition()); |
| EXPECT_EQ(newConditionTrackers[combination2Index]->getConditionId(), combination2Id); |
| EXPECT_EQ(newConditionTrackers[combination2Index]->mIndex, combination2Index); |
| EXPECT_FALSE(newConditionTrackers[combination2Index]->IsSimpleCondition()); |
| EXPECT_EQ(newConditionTrackers[combination4Index]->getConditionId(), combination4Id); |
| EXPECT_EQ(newConditionTrackers[combination4Index]->mIndex, combination4Index); |
| EXPECT_FALSE(newConditionTrackers[combination4Index]->IsSimpleCondition()); |
| |
| // Verify preserved trackers have indices updated. |
| SimpleConditionTracker* simpleTracker1 = |
| static_cast<SimpleConditionTracker*>(newConditionTrackers[simple1Index].get()); |
| EXPECT_EQ(simpleTracker1->mStartLogMatcherIndex, matcher1Index); |
| EXPECT_EQ(simpleTracker1->mStopLogMatcherIndex, matcher2Index); |
| EXPECT_EQ(simpleTracker1->mStopAllLogMatcherIndex, -1); |
| |
| SimpleConditionTracker* simpleTracker2 = |
| static_cast<SimpleConditionTracker*>(newConditionTrackers[simple2Index].get()); |
| EXPECT_EQ(simpleTracker2->mStartLogMatcherIndex, matcher3Index); |
| EXPECT_EQ(simpleTracker2->mStopLogMatcherIndex, matcher4Index); |
| EXPECT_EQ(simpleTracker2->mStopAllLogMatcherIndex, -1); |
| |
| CombinationConditionTracker* combinationTracker1 = static_cast<CombinationConditionTracker*>( |
| newConditionTrackers[combination1Index].get()); |
| EXPECT_THAT(combinationTracker1->mChildren, UnorderedElementsAre(simple1Index, simple2Index)); |
| EXPECT_THAT(combinationTracker1->mUnSlicedChildren, |
| UnorderedElementsAre(simple1Index, simple2Index)); |
| EXPECT_THAT(combinationTracker1->mSlicedChildren, IsEmpty()); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateStates) { |
| StatsdConfig config; |
| // Add states. |
| // Will be replaced because we add a state map. |
| State state1 = CreateScreenState(); |
| int64_t state1Id = state1.id(); |
| *config.add_state() = state1; |
| |
| // Will be preserved. |
| State state2 = CreateUidProcessState(); |
| int64_t state2Id = state2.id(); |
| *config.add_state() = state2; |
| |
| // Will be replaced since the atom changes from overlay to screen. |
| State state3 = CreateOverlayState(); |
| int64_t state3Id = state3.id(); |
| *config.add_state() = state3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change definitions of state1 and state3. |
| int64_t screenOnId = 0x4321, screenOffId = 0x1234; |
| *state1.mutable_map() = CreateScreenStateSimpleOnOffMap(screenOnId, screenOffId); |
| state3.set_atom_id(util::SCREEN_STATE_CHANGED); |
| |
| StatsdConfig newConfig; |
| *newConfig.add_state() = state3; |
| *newConfig.add_state() = state1; |
| *newConfig.add_state() = state2; |
| |
| unordered_map<int64_t, int> stateAtomIdMap; |
| unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps; |
| map<int64_t, uint64_t> newStateProtoHashes; |
| set<int64_t> replacedStates; |
| EXPECT_TRUE(updateStates(newConfig, oldStateHashes, stateAtomIdMap, allStateGroupMaps, |
| newStateProtoHashes, replacedStates)); |
| EXPECT_THAT(replacedStates, ContainerEq(set({state1Id, state3Id}))); |
| |
| unordered_map<int64_t, int> expectedStateAtomIdMap = { |
| {state1Id, util::SCREEN_STATE_CHANGED}, |
| {state2Id, util::UID_PROCESS_STATE_CHANGED}, |
| {state3Id, util::SCREEN_STATE_CHANGED}}; |
| EXPECT_THAT(stateAtomIdMap, ContainerEq(expectedStateAtomIdMap)); |
| |
| unordered_map<int64_t, unordered_map<int, int64_t>> expectedStateGroupMaps = { |
| {state1Id, |
| {{android::view::DisplayStateEnum::DISPLAY_STATE_OFF, screenOffId}, |
| {android::view::DisplayStateEnum::DISPLAY_STATE_ON, screenOnId}}}}; |
| EXPECT_THAT(allStateGroupMaps, ContainerEq(expectedStateGroupMaps)); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestEventMetricPreserve) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EventMetric* metric = config.add_event_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestEventMetricActivationAdded) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EventMetric* metric = config.add_event_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Add a metric activation, which should change the proto, causing replacement. |
| MetricActivation* activation = config.add_metric_activation(); |
| activation->set_metric_id(12345); |
| EventActivation* eventActivation = activation->add_event_activation(); |
| eventActivation->set_atom_matcher_id(startMatcher.id()); |
| eventActivation->set_ttl_seconds(5); |
| |
| unordered_map<int64_t, int> metricToActivationMap = {{12345, 0}}; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestEventMetricWhatChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EventMetric* metric = config.add_event_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestEventMetricConditionChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EventMetric* metric = config.add_event_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestMetricConditionLinkDepsChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| Predicate linkPredicate = CreateScreenIsOffPredicate(); |
| *config.add_predicate() = linkPredicate; |
| |
| EventMetric* metric = config.add_event_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| // Doesn't make sense as a real metric definition, but suffices as a separate predicate |
| // From the one in the condition. |
| MetricConditionLink* link = metric->add_links(); |
| link->set_condition(linkPredicate.id()); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{linkPredicate.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestEventMetricActivationDepsChange) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| EventMetric* metric = config.add_event_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| |
| MetricActivation* activation = config.add_metric_activation(); |
| activation->set_metric_id(12345); |
| EventActivation* eventActivation = activation->add_event_activation(); |
| eventActivation->set_atom_matcher_id(startMatcher.id()); |
| eventActivation->set_ttl_seconds(5); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap = {{12345, 0}}; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {startMatcher.id()}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCountMetricPreserve) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| State sliceState = CreateScreenState(); |
| *config.add_state() = sliceState; |
| |
| CountMetric* metric = config.add_count_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| metric->add_slice_by_state(sliceState.id()); |
| metric->set_bucket(ONE_HOUR); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCountMetricDefinitionChange) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| CountMetric* metric = config.add_count_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| metric->set_bucket(ONE_HOUR); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change bucket size, which should change the proto, causing replacement. |
| metric->set_bucket(TEN_MINUTES); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCountMetricWhatChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| CountMetric* metric = config.add_count_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| metric->set_bucket(ONE_HOUR); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCountMetricConditionChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| CountMetric* metric = config.add_count_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->set_condition(predicate.id()); |
| metric->set_bucket(ONE_HOUR); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestCountMetricStateChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| State sliceState = CreateScreenState(); |
| *config.add_state() = sliceState; |
| |
| CountMetric* metric = config.add_count_metric(); |
| metric->set_id(12345); |
| metric->set_what(whatMatcher.id()); |
| metric->add_slice_by_state(sliceState.id()); |
| metric->set_bucket(ONE_HOUR); |
| |
| // Create an initial config. |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{sliceState.id()}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestGaugeMetricPreserve) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| *config.add_gauge_metric() = createGaugeMetric( |
| "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, predicate.id(), nullopt); |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestGaugeMetricDefinitionChange) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_gauge_metric() = createGaugeMetric( |
| "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt); |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change split bucket on app upgrade, which should change the proto, causing replacement. |
| config.mutable_gauge_metric(0)->set_split_bucket_for_app_upgrade(false); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestGaugeMetricWhatChanged) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_gauge_metric() = createGaugeMetric( |
| "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt); |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestGaugeMetricConditionChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| *config.add_gauge_metric() = createGaugeMetric( |
| "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, predicate.id(), nullopt); |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestGaugeMetricTriggerEventChanged) { |
| StatsdConfig config; |
| AtomMatcher triggerEvent = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = triggerEvent; |
| AtomMatcher whatMatcher = CreateTemperatureAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_gauge_metric() = createGaugeMetric( |
| "GAUGE1", whatMatcher.id(), GaugeMetric::FIRST_N_SAMPLES, nullopt, triggerEvent.id()); |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {triggerEvent.id()}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestDurationMetricPreserve) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate what = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = what; |
| Predicate condition = CreateScreenIsOffPredicate(); |
| *config.add_predicate() = condition; |
| |
| State sliceState = CreateScreenState(); |
| *config.add_state() = sliceState; |
| |
| *config.add_duration_metric() = |
| createDurationMetric("DURATION1", what.id(), condition.id(), {sliceState.id()}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestDurationMetricDefinitionChange) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate what = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = what; |
| |
| *config.add_duration_metric() = createDurationMetric("DURATION1", what.id(), nullopt, {}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| config.mutable_duration_metric(0)->set_aggregation_type(DurationMetric::MAX_SPARSE); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, /*replacedMatchers*/ {}, |
| /*replacedConditions=*/{}, /*replacedStates=*/{}, |
| metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestDurationMetricWhatChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate what = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = what; |
| |
| *config.add_duration_metric() = createDurationMetric("DURATION1", what.id(), nullopt, {}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{what.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestDurationMetricConditionChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate what = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = what; |
| Predicate condition = CreateScreenIsOffPredicate(); |
| *config.add_predicate() = condition; |
| |
| *config.add_duration_metric() = createDurationMetric("DURATION", what.id(), condition.id(), {}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{condition.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestDurationMetricStateChange) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| |
| Predicate what = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = what; |
| |
| State sliceState = CreateScreenState(); |
| *config.add_state() = sliceState; |
| |
| *config.add_duration_metric() = |
| createDurationMetric("DURATION1", what.id(), nullopt, {sliceState.id()}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{sliceState.id()}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestValueMetricPreserve) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateTemperatureAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| State sliceState = CreateScreenState(); |
| *config.add_state() = sliceState; |
| |
| *config.add_value_metric() = |
| createValueMetric("VALUE1", whatMatcher, predicate.id(), {sliceState.id()}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestValueMetricDefinitionChange) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_value_metric() = createValueMetric("VALUE1", whatMatcher, nullopt, {}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change skip zero diff output, which should change the proto, causing replacement. |
| config.mutable_value_metric(0)->set_skip_zero_diff_output(true); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers, |
| metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestValueMetricWhatChanged) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateTemperatureAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_value_metric() = createValueMetric("VALUE1", whatMatcher, nullopt, {}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestValueMetricConditionChanged) { |
| StatsdConfig config; |
| AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = startMatcher; |
| AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_atom_matcher() = stopMatcher; |
| AtomMatcher whatMatcher = CreateTemperatureAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| Predicate predicate = CreateScreenIsOnPredicate(); |
| *config.add_predicate() = predicate; |
| |
| *config.add_value_metric() = createValueMetric("VALUE1", whatMatcher, predicate.id(), {}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()}, |
| /*replacedStates=*/{}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestValueMetricStateChanged) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| State sliceState = CreateScreenState(); |
| *config.add_state() = sliceState; |
| |
| *config.add_value_metric() = |
| createValueMetric("VALUE1", whatMatcher, nullopt, {sliceState.id()}); |
| EXPECT_TRUE(initConfig(config)); |
| |
| unordered_map<int64_t, int> metricToActivationMap; |
| vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN); |
| EXPECT_TRUE(determineAllMetricUpdateStatuses( |
| config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap, |
| /*replacedMatchers*/ {}, /*replacedConditions=*/{}, |
| /*replacedStates=*/{sliceState.id()}, metricsToUpdate)); |
| EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateEventMetrics) { |
| StatsdConfig config; |
| |
| // Add atom matchers/predicates. These are mostly needed for initStatsdConfig |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher(); |
| int64_t matcher5Id = matcher5.id(); |
| *config.add_atom_matcher() = matcher5; |
| |
| Predicate predicate1 = CreateScreenIsOnPredicate(); |
| int64_t predicate1Id = predicate1.id(); |
| *config.add_predicate() = predicate1; |
| |
| Predicate predicate2 = CreateScheduledJobPredicate(); |
| int64_t predicate2Id = predicate2.id(); |
| *config.add_predicate() = predicate2; |
| |
| // Add a few event metrics. |
| // Will be preserved. |
| EventMetric event1 = createEventMetric("EVENT1", matcher1Id, predicate2Id); |
| int64_t event1Id = event1.id(); |
| *config.add_event_metric() = event1; |
| |
| // Will be replaced. |
| EventMetric event2 = createEventMetric("EVENT2", matcher2Id, nullopt); |
| int64_t event2Id = event2.id(); |
| *config.add_event_metric() = event2; |
| |
| // Will be replaced. |
| EventMetric event3 = createEventMetric("EVENT3", matcher3Id, nullopt); |
| int64_t event3Id = event3.id(); |
| *config.add_event_metric() = event3; |
| |
| MetricActivation event3Activation; |
| event3Activation.set_metric_id(event3Id); |
| EventActivation* eventActivation = event3Activation.add_event_activation(); |
| eventActivation->set_atom_matcher_id(matcher5Id); |
| eventActivation->set_ttl_seconds(5); |
| *config.add_metric_activation() = event3Activation; |
| |
| // Will be replaced. |
| EventMetric event4 = createEventMetric("EVENT4", matcher4Id, predicate1Id); |
| int64_t event4Id = event4.id(); |
| *config.add_event_metric() = event4; |
| |
| // Will be deleted. |
| EventMetric event5 = createEventMetric("EVENT5", matcher5Id, nullopt); |
| int64_t event5Id = event5.id(); |
| *config.add_event_metric() = event5; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Used later to ensure the condition wizard is replaced. Get it before doing the update. |
| sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard; |
| EXPECT_EQ(oldConditionWizard->getStrongCount(), oldMetricProducers.size() + 1); |
| |
| // Add a condition to event2, causing it to be replaced. |
| event2.set_condition(predicate1Id); |
| |
| // Mark matcher 5 as replaced. Causes event3 to be replaced. |
| set<int64_t> replacedMatchers; |
| replacedMatchers.insert(matcher5Id); |
| |
| // Mark predicate 1 as replaced. Causes event4 to be replaced. |
| set<int64_t> replacedConditions; |
| replacedConditions.insert(predicate1Id); |
| |
| // Fake that predicate 2 is true. |
| ASSERT_EQ(oldMetricProducers[0]->getMetricId(), event1Id); |
| oldMetricProducers[0]->onConditionChanged(true, /*timestamp=*/0); |
| EXPECT_EQ(oldMetricProducers[0]->mCondition, ConditionState::kTrue); |
| |
| // New event metric. Should have an initial condition of true since it depends on predicate2. |
| EventMetric event6 = createEventMetric("EVENT6", matcher3Id, predicate2Id); |
| int64_t event6Id = event6.id(); |
| MetricActivation event6Activation; |
| event6Activation.set_metric_id(event6Id); |
| eventActivation = event6Activation.add_event_activation(); |
| eventActivation->set_atom_matcher_id(matcher5Id); |
| eventActivation->set_ttl_seconds(20); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher5Index = 0; |
| newAtomMatchingTrackerMap[matcher5Id] = 0; |
| const int matcher4Index = 1; |
| newAtomMatchingTrackerMap[matcher4Id] = 1; |
| const int matcher3Index = 2; |
| newAtomMatchingTrackerMap[matcher3Id] = 2; |
| const int matcher2Index = 3; |
| newAtomMatchingTrackerMap[matcher2Id] = 3; |
| const int matcher1Index = 4; |
| newAtomMatchingTrackerMap[matcher1Id] = 4; |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5); |
| std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| |
| std::unordered_map<int64_t, int> newConditionTrackerMap; |
| const int predicate2Index = 0; |
| newConditionTrackerMap[predicate2Id] = 0; |
| const int predicate1Index = 1; |
| newConditionTrackerMap[predicate1Id] = 1; |
| // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<ConditionTracker>> newConditionTrackers(2); |
| std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(), |
| newConditionTrackers.begin()); |
| // Fake that predicate2 is true. |
| vector<ConditionState> conditionCache = {ConditionState::kTrue, ConditionState::kUnknown}; |
| |
| StatsdConfig newConfig; |
| *newConfig.add_event_metric() = event6; |
| const int event6Index = 0; |
| *newConfig.add_event_metric() = event3; |
| const int event3Index = 1; |
| *newConfig.add_event_metric() = event1; |
| const int event1Index = 2; |
| *newConfig.add_event_metric() = event4; |
| const int event4Index = 3; |
| *newConfig.add_event_metric() = event2; |
| const int event2Index = 4; |
| *newConfig.add_metric_activation() = event3Activation; |
| *newConfig.add_metric_activation() = event6Activation; |
| |
| // Output data structures to validate. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers, |
| newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions, |
| newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{}, |
| /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, |
| newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| unordered_map<int64_t, int> expectedMetricProducerMap = { |
| {event1Id, event1Index}, {event2Id, event2Index}, {event3Id, event3Index}, |
| {event4Id, event4Index}, {event6Id, event6Index}, |
| }; |
| EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap)); |
| EXPECT_EQ(replacedMetrics, set<int64_t>({event2Id, event3Id, event4Id})); |
| |
| // Make sure preserved metrics are the same. |
| ASSERT_EQ(newMetricProducers.size(), 5); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(event1Id)], |
| newMetricProducers[newMetricProducerMap.at(event1Id)]); |
| |
| // Make sure replaced metrics are different. |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event2Id)], |
| newMetricProducers[newMetricProducerMap.at(event2Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event3Id)], |
| newMetricProducers[newMetricProducerMap.at(event3Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event4Id)], |
| newMetricProducers[newMetricProducerMap.at(event4Id)]); |
| |
| // Verify the conditionToMetricMap. |
| ASSERT_EQ(conditionToMetricMap.size(), 2); |
| const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index]; |
| EXPECT_THAT(condition1Metrics, UnorderedElementsAre(event2Index, event4Index)); |
| const vector<int>& condition2Metrics = conditionToMetricMap[predicate2Index]; |
| EXPECT_THAT(condition2Metrics, UnorderedElementsAre(event1Index, event6Index)); |
| |
| // Verify the trackerToMetricMap. |
| ASSERT_EQ(trackerToMetricMap.size(), 4); |
| const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index]; |
| EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(event1Index)); |
| const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index]; |
| EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(event2Index)); |
| const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index]; |
| EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(event3Index, event6Index)); |
| const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index]; |
| EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(event4Index)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 1); |
| EXPECT_THAT(activationAtomTrackerToMetricMap[matcher5Index], |
| UnorderedElementsAre(event3Index, event6Index)); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(metricsWithActivation.size(), 2); |
| EXPECT_THAT(metricsWithActivation, UnorderedElementsAre(event3Index, event6Index)); |
| |
| // Verify tracker indices/ids/conditions are correct. |
| EXPECT_EQ(newMetricProducers[event1Index]->getMetricId(), event1Id); |
| EXPECT_EQ(newMetricProducers[event1Index]->mConditionTrackerIndex, predicate2Index); |
| EXPECT_EQ(newMetricProducers[event1Index]->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(newMetricProducers[event2Index]->getMetricId(), event2Id); |
| EXPECT_EQ(newMetricProducers[event2Index]->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(newMetricProducers[event2Index]->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(newMetricProducers[event3Index]->getMetricId(), event3Id); |
| EXPECT_EQ(newMetricProducers[event3Index]->mConditionTrackerIndex, -1); |
| EXPECT_EQ(newMetricProducers[event3Index]->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(newMetricProducers[event4Index]->getMetricId(), event4Id); |
| EXPECT_EQ(newMetricProducers[event4Index]->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(newMetricProducers[event4Index]->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(newMetricProducers[event6Index]->getMetricId(), event6Id); |
| EXPECT_EQ(newMetricProducers[event6Index]->mConditionTrackerIndex, predicate2Index); |
| EXPECT_EQ(newMetricProducers[event6Index]->mCondition, ConditionState::kTrue); |
| |
| sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard; |
| EXPECT_NE(newConditionWizard, oldConditionWizard); |
| EXPECT_EQ(newConditionWizard->getStrongCount(), newMetricProducers.size() + 1); |
| oldMetricProducers.clear(); |
| // Only reference to the old wizard should be the one in the test. |
| EXPECT_EQ(oldConditionWizard->getStrongCount(), 1); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateCountMetrics) { |
| StatsdConfig config; |
| |
| // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig. |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher(); |
| int64_t matcher5Id = matcher5.id(); |
| *config.add_atom_matcher() = matcher5; |
| |
| Predicate predicate1 = CreateScreenIsOnPredicate(); |
| int64_t predicate1Id = predicate1.id(); |
| *config.add_predicate() = predicate1; |
| |
| State state1 = CreateScreenStateWithOnOffMap(0x123, 0x321); |
| int64_t state1Id = state1.id(); |
| *config.add_state() = state1; |
| |
| State state2 = CreateScreenState(); |
| int64_t state2Id = state2.id(); |
| *config.add_state() = state2; |
| |
| // Add a few count metrics. |
| // Will be preserved. |
| CountMetric count1 = createCountMetric("COUNT1", matcher1Id, predicate1Id, {state1Id}); |
| int64_t count1Id = count1.id(); |
| *config.add_count_metric() = count1; |
| |
| // Will be replaced. |
| CountMetric count2 = createCountMetric("COUNT2", matcher2Id, nullopt, {}); |
| int64_t count2Id = count2.id(); |
| *config.add_count_metric() = count2; |
| |
| // Will be replaced. |
| CountMetric count3 = createCountMetric("COUNT3", matcher3Id, nullopt, {}); |
| int64_t count3Id = count3.id(); |
| *config.add_count_metric() = count3; |
| |
| // Will be replaced. |
| CountMetric count4 = createCountMetric("COUNT4", matcher4Id, nullopt, {state2Id}); |
| int64_t count4Id = count4.id(); |
| *config.add_count_metric() = count4; |
| |
| // Will be deleted. |
| CountMetric count5 = createCountMetric("COUNT5", matcher5Id, nullopt, {}); |
| int64_t count5Id = count5.id(); |
| *config.add_count_metric() = count5; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Change bucket size of count2, causing it to be replaced. |
| count2.set_bucket(ONE_HOUR); |
| |
| // Mark matcher 3 as replaced. Causes count3 to be replaced. |
| set<int64_t> replacedMatchers; |
| replacedMatchers.insert(matcher3Id); |
| |
| // Mark state 2 as replaced and change the state to be about a different atom. |
| // Causes count4 to be replaced. |
| set<int64_t> replacedStates; |
| replacedStates.insert(state2Id); |
| state2.set_atom_id(util::BATTERY_SAVER_MODE_STATE_CHANGED); |
| |
| // Fake that predicate 1 is true for count metric 1. |
| ASSERT_EQ(oldMetricProducers[0]->getMetricId(), count1Id); |
| oldMetricProducers[0]->onConditionChanged(true, /*timestamp=*/0); |
| EXPECT_EQ(oldMetricProducers[0]->mCondition, ConditionState::kTrue); |
| |
| EXPECT_EQ(StateManager::getInstance().getStateTrackersCount(), 1); |
| // Tell the StateManager that the screen is on. |
| unique_ptr<LogEvent> event = |
| CreateScreenStateChangedEvent(0, android::view::DisplayStateEnum::DISPLAY_STATE_ON); |
| StateManager::getInstance().onLogEvent(*event); |
| |
| // New count metric. Should have an initial condition of true since it depends on predicate1. |
| CountMetric count6 = createCountMetric("EVENT6", matcher2Id, predicate1Id, {state1Id}); |
| int64_t count6Id = count6.id(); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher5Index = 0; |
| newAtomMatchingTrackerMap[matcher5Id] = 0; |
| const int matcher4Index = 1; |
| newAtomMatchingTrackerMap[matcher4Id] = 1; |
| const int matcher3Index = 2; |
| newAtomMatchingTrackerMap[matcher3Id] = 2; |
| const int matcher2Index = 3; |
| newAtomMatchingTrackerMap[matcher2Id] = 3; |
| const int matcher1Index = 4; |
| newAtomMatchingTrackerMap[matcher1Id] = 4; |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5); |
| std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| |
| std::unordered_map<int64_t, int> newConditionTrackerMap; |
| const int predicate1Index = 0; |
| newConditionTrackerMap[predicate1Id] = 0; |
| // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<ConditionTracker>> newConditionTrackers(1); |
| std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(), |
| newConditionTrackers.begin()); |
| // Fake that predicate1 is true for all new metrics. |
| vector<ConditionState> conditionCache = {ConditionState::kTrue}; |
| |
| StatsdConfig newConfig; |
| *newConfig.add_count_metric() = count6; |
| const int count6Index = 0; |
| *newConfig.add_count_metric() = count3; |
| const int count3Index = 1; |
| *newConfig.add_count_metric() = count1; |
| const int count1Index = 2; |
| *newConfig.add_count_metric() = count4; |
| const int count4Index = 3; |
| *newConfig.add_count_metric() = count2; |
| const int count2Index = 4; |
| |
| *newConfig.add_state() = state1; |
| *newConfig.add_state() = state2; |
| |
| unordered_map<int64_t, int> stateAtomIdMap; |
| unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps; |
| map<int64_t, uint64_t> stateProtoHashes; |
| EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes)); |
| EXPECT_EQ(stateAtomIdMap[state2Id], util::BATTERY_SAVER_MODE_STATE_CHANGED); |
| |
| // Output data structures to validate. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers, |
| newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{}, |
| newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates, |
| oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers, |
| conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| unordered_map<int64_t, int> expectedMetricProducerMap = { |
| {count1Id, count1Index}, {count2Id, count2Index}, {count3Id, count3Index}, |
| {count4Id, count4Index}, {count6Id, count6Index}, |
| }; |
| EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap)); |
| EXPECT_EQ(replacedMetrics, set<int64_t>({count2Id, count3Id, count4Id})); |
| |
| // Make sure preserved metrics are the same. |
| ASSERT_EQ(newMetricProducers.size(), 5); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(count1Id)], |
| newMetricProducers[newMetricProducerMap.at(count1Id)]); |
| |
| // Make sure replaced metrics are different. |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(count2Id)], |
| newMetricProducers[newMetricProducerMap.at(count2Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(count3Id)], |
| newMetricProducers[newMetricProducerMap.at(count3Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(count4Id)], |
| newMetricProducers[newMetricProducerMap.at(count4Id)]); |
| |
| // Verify the conditionToMetricMap. |
| ASSERT_EQ(conditionToMetricMap.size(), 1); |
| const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index]; |
| EXPECT_THAT(condition1Metrics, UnorderedElementsAre(count1Index, count6Index)); |
| |
| // Verify the trackerToMetricMap. |
| ASSERT_EQ(trackerToMetricMap.size(), 4); |
| const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index]; |
| EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(count1Index)); |
| const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index]; |
| EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(count2Index, count6Index)); |
| const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index]; |
| EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(count3Index)); |
| const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index]; |
| EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(count4Index)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(metricsWithActivation.size(), 0); |
| |
| // Verify tracker indices/ids/conditions/states are correct. |
| EXPECT_EQ(newMetricProducers[count1Index]->getMetricId(), count1Id); |
| EXPECT_EQ(newMetricProducers[count1Index]->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(newMetricProducers[count1Index]->mCondition, ConditionState::kTrue); |
| EXPECT_THAT(newMetricProducers[count1Index]->getSlicedStateAtoms(), |
| UnorderedElementsAre(util::SCREEN_STATE_CHANGED)); |
| EXPECT_EQ(newMetricProducers[count2Index]->getMetricId(), count2Id); |
| EXPECT_EQ(newMetricProducers[count2Index]->mConditionTrackerIndex, -1); |
| EXPECT_EQ(newMetricProducers[count2Index]->mCondition, ConditionState::kTrue); |
| EXPECT_TRUE(newMetricProducers[count2Index]->getSlicedStateAtoms().empty()); |
| EXPECT_EQ(newMetricProducers[count3Index]->getMetricId(), count3Id); |
| EXPECT_EQ(newMetricProducers[count3Index]->mConditionTrackerIndex, -1); |
| EXPECT_EQ(newMetricProducers[count3Index]->mCondition, ConditionState::kTrue); |
| EXPECT_TRUE(newMetricProducers[count3Index]->getSlicedStateAtoms().empty()); |
| EXPECT_EQ(newMetricProducers[count4Index]->getMetricId(), count4Id); |
| EXPECT_EQ(newMetricProducers[count4Index]->mConditionTrackerIndex, -1); |
| EXPECT_EQ(newMetricProducers[count4Index]->mCondition, ConditionState::kTrue); |
| EXPECT_THAT(newMetricProducers[count4Index]->getSlicedStateAtoms(), |
| UnorderedElementsAre(util::BATTERY_SAVER_MODE_STATE_CHANGED)); |
| EXPECT_EQ(newMetricProducers[count6Index]->getMetricId(), count6Id); |
| EXPECT_EQ(newMetricProducers[count6Index]->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(newMetricProducers[count6Index]->mCondition, ConditionState::kTrue); |
| EXPECT_THAT(newMetricProducers[count6Index]->getSlicedStateAtoms(), |
| UnorderedElementsAre(util::SCREEN_STATE_CHANGED)); |
| |
| oldMetricProducers.clear(); |
| // Ensure that the screen state StateTracker did not get deleted and replaced. |
| EXPECT_EQ(StateManager::getInstance().getStateTrackersCount(), 2); |
| FieldValue screenState; |
| StateManager::getInstance().getStateValue(util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY, |
| &screenState); |
| EXPECT_EQ(screenState.mValue.int_value, android::view::DisplayStateEnum::DISPLAY_STATE_ON); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateGaugeMetrics) { |
| StatsdConfig config; |
| |
| // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig. |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateTemperatureAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| AtomMatcher matcher5 = CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE); |
| int64_t matcher5Id = matcher5.id(); |
| *config.add_atom_matcher() = matcher5; |
| |
| Predicate predicate1 = CreateScreenIsOnPredicate(); |
| int64_t predicate1Id = predicate1.id(); |
| *config.add_predicate() = predicate1; |
| |
| // Add a few gauge metrics. |
| // Will be preserved. |
| GaugeMetric gauge1 = createGaugeMetric("GAUGE1", matcher4Id, GaugeMetric::FIRST_N_SAMPLES, |
| predicate1Id, matcher1Id); |
| int64_t gauge1Id = gauge1.id(); |
| *config.add_gauge_metric() = gauge1; |
| |
| // Will be replaced. |
| GaugeMetric gauge2 = |
| createGaugeMetric("GAUGE2", matcher1Id, GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt); |
| int64_t gauge2Id = gauge2.id(); |
| *config.add_gauge_metric() = gauge2; |
| |
| // Will be replaced. |
| GaugeMetric gauge3 = createGaugeMetric("GAUGE3", matcher5Id, GaugeMetric::FIRST_N_SAMPLES, |
| nullopt, matcher3Id); |
| int64_t gauge3Id = gauge3.id(); |
| *config.add_gauge_metric() = gauge3; |
| |
| // Will be replaced. |
| GaugeMetric gauge4 = createGaugeMetric("GAUGE4", matcher3Id, GaugeMetric::RANDOM_ONE_SAMPLE, |
| predicate1Id, nullopt); |
| int64_t gauge4Id = gauge4.id(); |
| *config.add_gauge_metric() = gauge4; |
| |
| // Will be deleted. |
| GaugeMetric gauge5 = |
| createGaugeMetric("GAUGE5", matcher2Id, GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, {}); |
| int64_t gauge5Id = gauge5.id(); |
| *config.add_gauge_metric() = gauge5; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Used later to ensure the condition wizard is replaced. Get it before doing the update. |
| sp<EventMatcherWizard> oldMatcherWizard = |
| static_cast<GaugeMetricProducer*>(oldMetricProducers[0].get())->mEventMatcherWizard; |
| EXPECT_EQ(oldMatcherWizard->getStrongCount(), 6); |
| |
| // Change gauge2, causing it to be replaced. |
| gauge2.set_max_num_gauge_atoms_per_bucket(50); |
| |
| // Mark matcher 3 as replaced. Causes gauge3 and gauge4 to be replaced. |
| set<int64_t> replacedMatchers = {matcher3Id}; |
| |
| // New gauge metric. |
| GaugeMetric gauge6 = createGaugeMetric("GAUGE6", matcher5Id, GaugeMetric::FIRST_N_SAMPLES, |
| predicate1Id, matcher3Id); |
| int64_t gauge6Id = gauge6.id(); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher5Index = 0; |
| newAtomMatchingTrackerMap[matcher5Id] = 0; |
| const int matcher4Index = 1; |
| newAtomMatchingTrackerMap[matcher4Id] = 1; |
| const int matcher3Index = 2; |
| newAtomMatchingTrackerMap[matcher3Id] = 2; |
| const int matcher2Index = 3; |
| newAtomMatchingTrackerMap[matcher2Id] = 3; |
| const int matcher1Index = 4; |
| newAtomMatchingTrackerMap[matcher1Id] = 4; |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5); |
| std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| |
| std::unordered_map<int64_t, int> newConditionTrackerMap; |
| const int predicate1Index = 0; |
| newConditionTrackerMap[predicate1Id] = 0; |
| // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<ConditionTracker>> newConditionTrackers(1); |
| std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(), |
| newConditionTrackers.begin()); |
| // Say that predicate1 is unknown since the initial condition never changed. |
| vector<ConditionState> conditionCache = {ConditionState::kUnknown}; |
| |
| StatsdConfig newConfig; |
| *newConfig.add_gauge_metric() = gauge6; |
| const int gauge6Index = 0; |
| *newConfig.add_gauge_metric() = gauge3; |
| const int gauge3Index = 1; |
| *newConfig.add_gauge_metric() = gauge1; |
| const int gauge1Index = 2; |
| *newConfig.add_gauge_metric() = gauge4; |
| const int gauge4Index = 3; |
| *newConfig.add_gauge_metric() = gauge2; |
| const int gauge2Index = 4; |
| |
| // Output data structures to validate. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers, |
| newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{}, |
| newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{}, |
| /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, |
| newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| unordered_map<int64_t, int> expectedMetricProducerMap = { |
| {gauge1Id, gauge1Index}, {gauge2Id, gauge2Index}, {gauge3Id, gauge3Index}, |
| {gauge4Id, gauge4Index}, {gauge6Id, gauge6Index}, |
| }; |
| EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap)); |
| EXPECT_EQ(replacedMetrics, set<int64_t>({gauge2Id, gauge3Id, gauge4Id})); |
| |
| // Make sure preserved metrics are the same. |
| ASSERT_EQ(newMetricProducers.size(), 5); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(gauge1Id)], |
| newMetricProducers[newMetricProducerMap.at(gauge1Id)]); |
| |
| // Make sure replaced metrics are different. |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gauge2Id)], |
| newMetricProducers[newMetricProducerMap.at(gauge2Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gauge3Id)], |
| newMetricProducers[newMetricProducerMap.at(gauge3Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gauge4Id)], |
| newMetricProducers[newMetricProducerMap.at(gauge4Id)]); |
| |
| // Verify the conditionToMetricMap. |
| ASSERT_EQ(conditionToMetricMap.size(), 1); |
| const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index]; |
| EXPECT_THAT(condition1Metrics, UnorderedElementsAre(gauge1Index, gauge4Index, gauge6Index)); |
| |
| // Verify the trackerToMetricMap. |
| ASSERT_EQ(trackerToMetricMap.size(), 4); |
| const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index]; |
| EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(gauge1Index, gauge2Index)); |
| const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index]; |
| EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(gauge3Index, gauge4Index, gauge6Index)); |
| const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index]; |
| EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(gauge1Index)); |
| const vector<int>& matcher5Metrics = trackerToMetricMap[matcher5Index]; |
| EXPECT_THAT(matcher5Metrics, UnorderedElementsAre(gauge3Index, gauge6Index)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(metricsWithActivation.size(), 0); |
| |
| // Verify tracker indices/ids/conditions/states are correct. |
| GaugeMetricProducer* gaugeProducer1 = |
| static_cast<GaugeMetricProducer*>(newMetricProducers[gauge1Index].get()); |
| EXPECT_EQ(gaugeProducer1->getMetricId(), gauge1Id); |
| EXPECT_EQ(gaugeProducer1->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(gaugeProducer1->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(gaugeProducer1->mWhatMatcherIndex, matcher4Index); |
| GaugeMetricProducer* gaugeProducer2 = |
| static_cast<GaugeMetricProducer*>(newMetricProducers[gauge2Index].get()); |
| EXPECT_EQ(gaugeProducer2->getMetricId(), gauge2Id); |
| EXPECT_EQ(gaugeProducer2->mConditionTrackerIndex, -1); |
| EXPECT_EQ(gaugeProducer2->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(gaugeProducer2->mWhatMatcherIndex, matcher1Index); |
| GaugeMetricProducer* gaugeProducer3 = |
| static_cast<GaugeMetricProducer*>(newMetricProducers[gauge3Index].get()); |
| EXPECT_EQ(gaugeProducer3->getMetricId(), gauge3Id); |
| EXPECT_EQ(gaugeProducer3->mConditionTrackerIndex, -1); |
| EXPECT_EQ(gaugeProducer3->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(gaugeProducer3->mWhatMatcherIndex, matcher5Index); |
| GaugeMetricProducer* gaugeProducer4 = |
| static_cast<GaugeMetricProducer*>(newMetricProducers[gauge4Index].get()); |
| EXPECT_EQ(gaugeProducer4->getMetricId(), gauge4Id); |
| EXPECT_EQ(gaugeProducer4->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(gaugeProducer4->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(gaugeProducer4->mWhatMatcherIndex, matcher3Index); |
| GaugeMetricProducer* gaugeProducer6 = |
| static_cast<GaugeMetricProducer*>(newMetricProducers[gauge6Index].get()); |
| EXPECT_EQ(gaugeProducer6->getMetricId(), gauge6Id); |
| EXPECT_EQ(gaugeProducer6->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(gaugeProducer6->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(gaugeProducer6->mWhatMatcherIndex, matcher5Index); |
| |
| sp<EventMatcherWizard> newMatcherWizard = gaugeProducer1->mEventMatcherWizard; |
| EXPECT_NE(newMatcherWizard, oldMatcherWizard); |
| EXPECT_EQ(newMatcherWizard->getStrongCount(), 6); |
| oldMetricProducers.clear(); |
| // Only reference to the old wizard should be the one in the test. |
| EXPECT_EQ(oldMatcherWizard->getStrongCount(), 1); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) { |
| StatsdConfig config; |
| // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig. |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateAcquireWakelockAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateReleaseWakelockAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| AtomMatcher matcher5 = CreateMoveToForegroundAtomMatcher(); |
| int64_t matcher5Id = matcher5.id(); |
| *config.add_atom_matcher() = matcher5; |
| |
| AtomMatcher matcher6 = CreateMoveToBackgroundAtomMatcher(); |
| int64_t matcher6Id = matcher6.id(); |
| *config.add_atom_matcher() = matcher6; |
| |
| AtomMatcher matcher7 = CreateBatteryStateNoneMatcher(); |
| int64_t matcher7Id = matcher7.id(); |
| *config.add_atom_matcher() = matcher7; |
| |
| AtomMatcher matcher8 = CreateBatteryStateUsbMatcher(); |
| int64_t matcher8Id = matcher8.id(); |
| *config.add_atom_matcher() = matcher8; |
| |
| Predicate predicate1 = CreateScreenIsOnPredicate(); |
| int64_t predicate1Id = predicate1.id(); |
| *config.add_predicate() = predicate1; |
| |
| Predicate predicate2 = CreateScreenIsOffPredicate(); |
| int64_t predicate2Id = predicate2.id(); |
| *config.add_predicate() = predicate2; |
| |
| Predicate predicate3 = CreateDeviceUnpluggedPredicate(); |
| int64_t predicate3Id = predicate3.id(); |
| *config.add_predicate() = predicate3; |
| |
| Predicate predicate4 = CreateIsInBackgroundPredicate(); |
| *predicate4.mutable_simple_predicate()->mutable_dimensions() = |
| CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1}); |
| int64_t predicate4Id = predicate4.id(); |
| *config.add_predicate() = predicate4; |
| |
| Predicate predicate5 = CreateHoldingWakelockPredicate(); |
| *predicate5.mutable_simple_predicate()->mutable_dimensions() = |
| CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); |
| predicate5.mutable_simple_predicate()->set_stop_all(matcher7Id); |
| int64_t predicate5Id = predicate5.id(); |
| *config.add_predicate() = predicate5; |
| |
| State state1 = CreateScreenStateWithOnOffMap(0x123, 0x321); |
| int64_t state1Id = state1.id(); |
| *config.add_state() = state1; |
| |
| State state2 = CreateScreenState(); |
| int64_t state2Id = state2.id(); |
| *config.add_state() = state2; |
| |
| // Add a few duration metrics. |
| // Will be preserved. |
| DurationMetric duration1 = |
| createDurationMetric("DURATION1", predicate5Id, predicate4Id, {state2Id}); |
| *duration1.mutable_dimensions_in_what() = |
| CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); |
| MetricConditionLink* link = duration1.add_links(); |
| link->set_condition(predicate4Id); |
| *link->mutable_fields_in_what() = |
| CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); |
| *link->mutable_fields_in_condition() = |
| CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/); |
| int64_t duration1Id = duration1.id(); |
| *config.add_duration_metric() = duration1; |
| |
| // Will be replaced. |
| DurationMetric duration2 = createDurationMetric("DURATION2", predicate1Id, nullopt, {}); |
| int64_t duration2Id = duration2.id(); |
| *config.add_duration_metric() = duration2; |
| |
| // Will be replaced. |
| DurationMetric duration3 = createDurationMetric("DURATION3", predicate3Id, nullopt, {state1Id}); |
| int64_t duration3Id = duration3.id(); |
| *config.add_duration_metric() = duration3; |
| |
| // Will be replaced. |
| DurationMetric duration4 = createDurationMetric("DURATION4", predicate3Id, predicate2Id, {}); |
| int64_t duration4Id = duration4.id(); |
| *config.add_duration_metric() = duration4; |
| |
| // Will be deleted. |
| DurationMetric duration5 = createDurationMetric("DURATION5", predicate2Id, nullopt, {}); |
| int64_t duration5Id = duration5.id(); |
| *config.add_duration_metric() = duration5; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Make some sliced conditions true. |
| int uid1 = 10; |
| int uid2 = 11; |
| vector<MatchingState> matchingStates(8, MatchingState::kNotMatched); |
| matchingStates[2] = kMatched; |
| vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated); |
| vector<bool> changedCache(5, false); |
| unique_ptr<LogEvent> event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid1}, {"tag"}, "wl1"); |
| oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers, |
| conditionCache, changedCache); |
| EXPECT_TRUE(oldConditionTrackers[4]->isSliced()); |
| EXPECT_TRUE(changedCache[4]); |
| EXPECT_EQ(conditionCache[4], ConditionState::kTrue); |
| oldMetricProducers[0]->onMatchedLogEvent(2, *event.get()); |
| |
| fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated); |
| fill(changedCache.begin(), changedCache.end(), false); |
| event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid2}, {"tag"}, "wl2"); |
| oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers, |
| conditionCache, changedCache); |
| EXPECT_TRUE(changedCache[4]); |
| EXPECT_EQ(conditionCache[4], ConditionState::kTrue); |
| oldMetricProducers[0]->onMatchedLogEvent(2, *event.get()); |
| |
| // Used later to ensure the condition wizard is replaced. Get it before doing the update. |
| // The duration trackers have a pointer to the wizard, and 2 trackers were created above. |
| sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard; |
| EXPECT_EQ(oldConditionWizard->getStrongCount(), 8); |
| |
| // Replace predicate1, predicate3, and state1. Causes duration2/3/4 to be replaced. |
| set<int64_t> replacedConditions({predicate1Id, predicate2Id}); |
| set<int64_t> replacedStates({state1Id}); |
| |
| // New duration metric. |
| DurationMetric duration6 = createDurationMetric("DURATION6", predicate4Id, predicate5Id, {}); |
| *duration6.mutable_dimensions_in_what() = |
| CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/); |
| link = duration6.add_links(); |
| link->set_condition(predicate5Id); |
| *link->mutable_fields_in_what() = |
| CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/); |
| *link->mutable_fields_in_condition() = |
| CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); |
| int64_t duration6Id = duration6.id(); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| const int matcher8Index = 0, matcher7Index = 1, matcher6Index = 2, matcher5Index = 3, |
| matcher4Index = 4, matcher3Index = 5, matcher2Index = 6, matcher1Index = 7; |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap({{matcher8Id, matcher8Index}, |
| {matcher7Id, matcher7Index}, |
| {matcher6Id, matcher6Index}, |
| {matcher5Id, matcher5Index}, |
| {matcher4Id, matcher4Index}, |
| {matcher3Id, matcher3Index}, |
| {matcher2Id, matcher2Index}, |
| {matcher1Id, matcher1Index}}); |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(8); |
| reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| |
| const int predicate5Index = 0, predicate4Index = 1, predicate3Index = 2, predicate2Index = 3, |
| predicate1Index = 4; |
| std::unordered_map<int64_t, int> newConditionTrackerMap({ |
| {predicate5Id, predicate5Index}, |
| {predicate4Id, predicate4Index}, |
| {predicate3Id, predicate3Index}, |
| {predicate2Id, predicate2Index}, |
| {predicate1Id, predicate1Index}, |
| }); |
| // Use the existing conditionTrackers and reinitialize them to get the initial condition cache. |
| vector<sp<ConditionTracker>> newConditionTrackers(5); |
| reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(), |
| newConditionTrackers.begin()); |
| vector<Predicate> conditionProtos(5); |
| reverse_copy(config.predicate().begin(), config.predicate().end(), conditionProtos.begin()); |
| for (int i = 0; i < newConditionTrackers.size(); i++) { |
| EXPECT_TRUE(newConditionTrackers[i]->onConfigUpdated( |
| conditionProtos, i, newConditionTrackers, newAtomMatchingTrackerMap, |
| newConditionTrackerMap)); |
| } |
| vector<bool> cycleTracker(5, false); |
| fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated); |
| for (int i = 0; i < newConditionTrackers.size(); i++) { |
| EXPECT_TRUE(newConditionTrackers[i]->init(conditionProtos, newConditionTrackers, |
| newConditionTrackerMap, cycleTracker, |
| conditionCache)); |
| } |
| // Predicate5 should be true since 2 uids have wakelocks |
| EXPECT_EQ(conditionCache, vector({kTrue, kUnknown, kUnknown, kUnknown, kUnknown})); |
| |
| StatsdConfig newConfig; |
| *newConfig.add_duration_metric() = duration6; |
| const int duration6Index = 0; |
| *newConfig.add_duration_metric() = duration3; |
| const int duration3Index = 1; |
| *newConfig.add_duration_metric() = duration1; |
| const int duration1Index = 2; |
| *newConfig.add_duration_metric() = duration4; |
| const int duration4Index = 3; |
| *newConfig.add_duration_metric() = duration2; |
| const int duration2Index = 4; |
| |
| for (const Predicate& predicate : conditionProtos) { |
| *newConfig.add_predicate() = predicate; |
| } |
| *newConfig.add_state() = state1; |
| *newConfig.add_state() = state2; |
| unordered_map<int64_t, int> stateAtomIdMap; |
| unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps; |
| map<int64_t, uint64_t> stateProtoHashes; |
| EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes)); |
| |
| // Output data structures to validate. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{}, |
| newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions, |
| newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates, |
| oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers, |
| conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| unordered_map<int64_t, int> expectedMetricProducerMap = { |
| {duration1Id, duration1Index}, {duration2Id, duration2Index}, |
| {duration3Id, duration3Index}, {duration4Id, duration4Index}, |
| {duration6Id, duration6Index}, |
| }; |
| EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap)); |
| EXPECT_EQ(replacedMetrics, set<int64_t>({duration2Id, duration3Id, duration4Id})); |
| // Make sure preserved metrics are the same. |
| ASSERT_EQ(newMetricProducers.size(), 5); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(duration1Id)], |
| newMetricProducers[newMetricProducerMap.at(duration1Id)]); |
| |
| // Make sure replaced metrics are different. |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration2Id)], |
| newMetricProducers[newMetricProducerMap.at(duration2Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration3Id)], |
| newMetricProducers[newMetricProducerMap.at(duration3Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration4Id)], |
| newMetricProducers[newMetricProducerMap.at(duration4Id)]); |
| |
| // Verify the conditionToMetricMap. Note that the "what" is not in this map. |
| ASSERT_EQ(conditionToMetricMap.size(), 3); |
| const vector<int>& condition2Metrics = conditionToMetricMap[predicate2Index]; |
| EXPECT_THAT(condition2Metrics, UnorderedElementsAre(duration4Index)); |
| const vector<int>& condition4Metrics = conditionToMetricMap[predicate4Index]; |
| EXPECT_THAT(condition4Metrics, UnorderedElementsAre(duration1Index)); |
| const vector<int>& condition5Metrics = conditionToMetricMap[predicate5Index]; |
| EXPECT_THAT(condition5Metrics, UnorderedElementsAre(duration6Index)); |
| |
| // Verify the trackerToMetricMap. The start/stop/stopall indices from the "what" should be here. |
| ASSERT_EQ(trackerToMetricMap.size(), 8); |
| const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index]; |
| EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(duration2Index)); |
| const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index]; |
| EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(duration2Index)); |
| const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index]; |
| EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(duration1Index)); |
| const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index]; |
| EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(duration1Index)); |
| const vector<int>& matcher5Metrics = trackerToMetricMap[matcher5Index]; |
| EXPECT_THAT(matcher5Metrics, UnorderedElementsAre(duration6Index)); |
| const vector<int>& matcher6Metrics = trackerToMetricMap[matcher6Index]; |
| EXPECT_THAT(matcher6Metrics, UnorderedElementsAre(duration6Index)); |
| const vector<int>& matcher7Metrics = trackerToMetricMap[matcher7Index]; |
| EXPECT_THAT(matcher7Metrics, |
| UnorderedElementsAre(duration1Index, duration3Index, duration4Index)); |
| const vector<int>& matcher8Metrics = trackerToMetricMap[matcher8Index]; |
| EXPECT_THAT(matcher8Metrics, UnorderedElementsAre(duration3Index, duration4Index)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(metricsWithActivation.size(), 0); |
| |
| // Verify tracker indices/ids/conditions are correct. |
| DurationMetricProducer* durationProducer1 = |
| static_cast<DurationMetricProducer*>(newMetricProducers[duration1Index].get()); |
| EXPECT_EQ(durationProducer1->getMetricId(), duration1Id); |
| EXPECT_EQ(durationProducer1->mConditionTrackerIndex, predicate4Index); |
| EXPECT_EQ(durationProducer1->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(durationProducer1->mStartIndex, matcher3Index); |
| EXPECT_EQ(durationProducer1->mStopIndex, matcher4Index); |
| EXPECT_EQ(durationProducer1->mStopAllIndex, matcher7Index); |
| EXPECT_EQ(durationProducer1->mCurrentSlicedDurationTrackerMap.size(), 2); |
| for (const auto& durationTrackerIt : durationProducer1->mCurrentSlicedDurationTrackerMap) { |
| EXPECT_EQ(durationTrackerIt.second->mConditionTrackerIndex, predicate4Index); |
| } |
| DurationMetricProducer* durationProducer2 = |
| static_cast<DurationMetricProducer*>(newMetricProducers[duration2Index].get()); |
| EXPECT_EQ(durationProducer2->getMetricId(), duration2Id); |
| EXPECT_EQ(durationProducer2->mConditionTrackerIndex, -1); |
| EXPECT_EQ(durationProducer2->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(durationProducer2->mStartIndex, matcher1Index); |
| EXPECT_EQ(durationProducer2->mStopIndex, matcher2Index); |
| EXPECT_EQ(durationProducer2->mStopAllIndex, -1); |
| DurationMetricProducer* durationProducer3 = |
| static_cast<DurationMetricProducer*>(newMetricProducers[duration3Index].get()); |
| EXPECT_EQ(durationProducer3->getMetricId(), duration3Id); |
| EXPECT_EQ(durationProducer3->mConditionTrackerIndex, -1); |
| EXPECT_EQ(durationProducer3->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(durationProducer3->mStartIndex, matcher7Index); |
| EXPECT_EQ(durationProducer3->mStopIndex, matcher8Index); |
| EXPECT_EQ(durationProducer3->mStopAllIndex, -1); |
| DurationMetricProducer* durationProducer4 = |
| static_cast<DurationMetricProducer*>(newMetricProducers[duration4Index].get()); |
| EXPECT_EQ(durationProducer4->getMetricId(), duration4Id); |
| EXPECT_EQ(durationProducer4->mConditionTrackerIndex, predicate2Index); |
| EXPECT_EQ(durationProducer4->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(durationProducer4->mStartIndex, matcher7Index); |
| EXPECT_EQ(durationProducer4->mStopIndex, matcher8Index); |
| EXPECT_EQ(durationProducer4->mStopAllIndex, -1); |
| DurationMetricProducer* durationProducer6 = |
| static_cast<DurationMetricProducer*>(newMetricProducers[duration6Index].get()); |
| EXPECT_EQ(durationProducer6->getMetricId(), duration6Id); |
| EXPECT_EQ(durationProducer6->mConditionTrackerIndex, predicate5Index); |
| // TODO(b/167491517): should this be unknown since the condition is sliced? |
| EXPECT_EQ(durationProducer6->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(durationProducer6->mStartIndex, matcher6Index); |
| EXPECT_EQ(durationProducer6->mStopIndex, matcher5Index); |
| EXPECT_EQ(durationProducer6->mStopAllIndex, -1); |
| |
| sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard; |
| EXPECT_NE(newConditionWizard, oldConditionWizard); |
| EXPECT_EQ(newConditionWizard->getStrongCount(), 8); |
| oldMetricProducers.clear(); |
| // Only reference to the old wizard should be the one in the test. |
| EXPECT_EQ(oldConditionWizard->getStrongCount(), 1); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateValueMetrics) { |
| StatsdConfig config; |
| |
| // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig. |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateTemperatureAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| AtomMatcher matcher5 = CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE); |
| int64_t matcher5Id = matcher5.id(); |
| *config.add_atom_matcher() = matcher5; |
| |
| Predicate predicate1 = CreateScreenIsOnPredicate(); |
| int64_t predicate1Id = predicate1.id(); |
| *config.add_predicate() = predicate1; |
| |
| Predicate predicate2 = CreateScreenIsOffPredicate(); |
| int64_t predicate2Id = predicate2.id(); |
| *config.add_predicate() = predicate2; |
| |
| State state1 = CreateScreenStateWithOnOffMap(0x123, 0x321); |
| int64_t state1Id = state1.id(); |
| *config.add_state() = state1; |
| |
| State state2 = CreateScreenState(); |
| int64_t state2Id = state2.id(); |
| *config.add_state() = state2; |
| |
| // Add a few value metrics. |
| // Note that these will not work as "real" metrics since the value field is always 2. |
| // Will be preserved. |
| ValueMetric value1 = createValueMetric("VALUE1", matcher4, predicate1Id, {state1Id}); |
| int64_t value1Id = value1.id(); |
| *config.add_value_metric() = value1; |
| |
| // Will be replaced - definition change. |
| ValueMetric value2 = createValueMetric("VALUE2", matcher1, nullopt, {}); |
| int64_t value2Id = value2.id(); |
| *config.add_value_metric() = value2; |
| |
| // Will be replaced - condition change. |
| ValueMetric value3 = createValueMetric("VALUE3", matcher5, predicate2Id, {}); |
| int64_t value3Id = value3.id(); |
| *config.add_value_metric() = value3; |
| |
| // Will be replaced - state change. |
| ValueMetric value4 = createValueMetric("VALUE4", matcher3, nullopt, {state2Id}); |
| int64_t value4Id = value4.id(); |
| *config.add_value_metric() = value4; |
| |
| // Will be deleted. |
| ValueMetric value5 = createValueMetric("VALUE5", matcher2, nullopt, {}); |
| int64_t value5Id = value5.id(); |
| *config.add_value_metric() = value5; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Used later to ensure the condition wizard is replaced. Get it before doing the update. |
| sp<EventMatcherWizard> oldMatcherWizard = |
| static_cast<ValueMetricProducer*>(oldMetricProducers[0].get())->mEventMatcherWizard; |
| EXPECT_EQ(oldMatcherWizard->getStrongCount(), 6); |
| |
| // Change value2, causing it to be replaced. |
| value2.set_aggregation_type(ValueMetric::AVG); |
| |
| // Mark predicate 2 as replaced. Causes value3 to be replaced. |
| set<int64_t> replacedConditions = {predicate2Id}; |
| |
| // Mark state 2 as replaced. Causes value4 to be replaced. |
| set<int64_t> replacedStates = {state2Id}; |
| |
| // New value metric. |
| ValueMetric value6 = createValueMetric("VALUE6", matcher5, predicate1Id, {state1Id}); |
| int64_t value6Id = value6.id(); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher5Index = 0; |
| newAtomMatchingTrackerMap[matcher5Id] = 0; |
| const int matcher4Index = 1; |
| newAtomMatchingTrackerMap[matcher4Id] = 1; |
| const int matcher3Index = 2; |
| newAtomMatchingTrackerMap[matcher3Id] = 2; |
| const int matcher2Index = 3; |
| newAtomMatchingTrackerMap[matcher2Id] = 3; |
| const int matcher1Index = 4; |
| newAtomMatchingTrackerMap[matcher1Id] = 4; |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5); |
| std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| |
| std::unordered_map<int64_t, int> newConditionTrackerMap; |
| const int predicate2Index = 0; |
| newConditionTrackerMap[predicate2Id] = 0; |
| const int predicate1Index = 1; |
| newConditionTrackerMap[predicate1Id] = 1; |
| // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<ConditionTracker>> newConditionTrackers(2); |
| std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(), |
| newConditionTrackers.begin()); |
| // Say that predicate1 & predicate2 is unknown since the initial condition never changed. |
| vector<ConditionState> conditionCache = {ConditionState::kUnknown, ConditionState::kUnknown}; |
| |
| StatsdConfig newConfig; |
| *newConfig.add_value_metric() = value6; |
| const int value6Index = 0; |
| *newConfig.add_value_metric() = value3; |
| const int value3Index = 1; |
| *newConfig.add_value_metric() = value1; |
| const int value1Index = 2; |
| *newConfig.add_value_metric() = value4; |
| const int value4Index = 3; |
| *newConfig.add_value_metric() = value2; |
| const int value2Index = 4; |
| |
| *newConfig.add_state() = state1; |
| *newConfig.add_state() = state2; |
| |
| unordered_map<int64_t, int> stateAtomIdMap; |
| unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps; |
| map<int64_t, uint64_t> stateProtoHashes; |
| EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes)); |
| |
| // Output data structures to validate. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{}, |
| newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions, |
| newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates, |
| oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers, |
| conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| unordered_map<int64_t, int> expectedMetricProducerMap = { |
| {value1Id, value1Index}, {value2Id, value2Index}, {value3Id, value3Index}, |
| {value4Id, value4Index}, {value6Id, value6Index}, |
| }; |
| EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap)); |
| EXPECT_EQ(replacedMetrics, set<int64_t>({value2Id, value3Id, value4Id})); |
| |
| // Make sure preserved metrics are the same. |
| ASSERT_EQ(newMetricProducers.size(), 5); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(value1Id)], |
| newMetricProducers[newMetricProducerMap.at(value1Id)]); |
| |
| // Make sure replaced metrics are different. |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(value2Id)], |
| newMetricProducers[newMetricProducerMap.at(value2Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(value3Id)], |
| newMetricProducers[newMetricProducerMap.at(value3Id)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(value4Id)], |
| newMetricProducers[newMetricProducerMap.at(value4Id)]); |
| |
| // Verify the conditionToMetricMap. |
| ASSERT_EQ(conditionToMetricMap.size(), 2); |
| const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index]; |
| EXPECT_THAT(condition1Metrics, UnorderedElementsAre(value1Index, value6Index)); |
| const vector<int>& condition2Metrics = conditionToMetricMap[predicate2Index]; |
| EXPECT_THAT(condition2Metrics, UnorderedElementsAre(value3Index)); |
| |
| // Verify the trackerToMetricMap. |
| ASSERT_EQ(trackerToMetricMap.size(), 4); |
| const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index]; |
| EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(value2Index)); |
| const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index]; |
| EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(value4Index)); |
| const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index]; |
| EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(value1Index)); |
| const vector<int>& matcher5Metrics = trackerToMetricMap[matcher5Index]; |
| EXPECT_THAT(matcher5Metrics, UnorderedElementsAre(value3Index, value6Index)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(metricsWithActivation.size(), 0); |
| |
| // Verify tracker indices/ids/conditions/states are correct. |
| ValueMetricProducer* valueProducer1 = |
| static_cast<ValueMetricProducer*>(newMetricProducers[value1Index].get()); |
| EXPECT_EQ(valueProducer1->getMetricId(), value1Id); |
| EXPECT_EQ(valueProducer1->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(valueProducer1->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(valueProducer1->mWhatMatcherIndex, matcher4Index); |
| ValueMetricProducer* valueProducer2 = |
| static_cast<ValueMetricProducer*>(newMetricProducers[value2Index].get()); |
| EXPECT_EQ(valueProducer2->getMetricId(), value2Id); |
| EXPECT_EQ(valueProducer2->mConditionTrackerIndex, -1); |
| EXPECT_EQ(valueProducer2->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(valueProducer2->mWhatMatcherIndex, matcher1Index); |
| ValueMetricProducer* valueProducer3 = |
| static_cast<ValueMetricProducer*>(newMetricProducers[value3Index].get()); |
| EXPECT_EQ(valueProducer3->getMetricId(), value3Id); |
| EXPECT_EQ(valueProducer3->mConditionTrackerIndex, predicate2Index); |
| EXPECT_EQ(valueProducer3->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(valueProducer3->mWhatMatcherIndex, matcher5Index); |
| ValueMetricProducer* valueProducer4 = |
| static_cast<ValueMetricProducer*>(newMetricProducers[value4Index].get()); |
| EXPECT_EQ(valueProducer4->getMetricId(), value4Id); |
| EXPECT_EQ(valueProducer4->mConditionTrackerIndex, -1); |
| EXPECT_EQ(valueProducer4->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(valueProducer4->mWhatMatcherIndex, matcher3Index); |
| ValueMetricProducer* valueProducer6 = |
| static_cast<ValueMetricProducer*>(newMetricProducers[value6Index].get()); |
| EXPECT_EQ(valueProducer6->getMetricId(), value6Id); |
| EXPECT_EQ(valueProducer6->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(valueProducer6->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(valueProducer6->mWhatMatcherIndex, matcher5Index); |
| |
| sp<EventMatcherWizard> newMatcherWizard = valueProducer1->mEventMatcherWizard; |
| EXPECT_NE(newMatcherWizard, oldMatcherWizard); |
| EXPECT_EQ(newMatcherWizard->getStrongCount(), 6); |
| oldMetricProducers.clear(); |
| // Only reference to the old wizard should be the one in the test. |
| EXPECT_EQ(oldMatcherWizard->getStrongCount(), 1); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) { |
| StatsdConfig config; |
| // Add atom matchers |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher(); |
| int64_t matcher4Id = matcher4.id(); |
| *config.add_atom_matcher() = matcher4; |
| |
| // Add an event metric with multiple activations. |
| EventMetric event1 = createEventMetric("EVENT1", matcher1Id, nullopt); |
| int64_t event1Id = event1.id(); |
| *config.add_event_metric() = event1; |
| |
| int64_t matcher2TtlSec = 2, matcher3TtlSec = 3, matcher4TtlSec = 4; |
| MetricActivation metricActivation; |
| metricActivation.set_metric_id(event1Id); |
| EventActivation* activation = metricActivation.add_event_activation(); |
| activation->set_atom_matcher_id(matcher2Id); |
| activation->set_ttl_seconds(matcher2TtlSec); |
| activation->set_activation_type(ACTIVATE_IMMEDIATELY); |
| activation->set_deactivation_atom_matcher_id(matcher1Id); |
| activation = metricActivation.add_event_activation(); |
| activation->set_atom_matcher_id(matcher3Id); |
| activation->set_ttl_seconds(matcher3TtlSec); |
| activation->set_activation_type(ACTIVATE_ON_BOOT); |
| activation->set_deactivation_atom_matcher_id(matcher1Id); |
| activation = metricActivation.add_event_activation(); |
| activation->set_atom_matcher_id(matcher4Id); |
| activation->set_ttl_seconds(matcher4TtlSec); |
| activation->set_activation_type(ACTIVATE_IMMEDIATELY); |
| activation->set_deactivation_atom_matcher_id(matcher2Id); |
| *config.add_metric_activation() = metricActivation; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Activate some of the event activations. |
| ASSERT_EQ(oldMetricProducers[0]->getMetricId(), event1Id); |
| int64_t matcher2StartNs = 12345; |
| oldMetricProducers[0]->activate(oldAtomMatchingTrackerMap[matcher2Id], matcher2StartNs); |
| int64_t matcher3StartNs = 23456; |
| oldMetricProducers[0]->activate(oldAtomMatchingTrackerMap[matcher3Id], matcher3StartNs); |
| EXPECT_TRUE(oldMetricProducers[0]->isActive()); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher4Index = 0; |
| newAtomMatchingTrackerMap[matcher4Id] = 0; |
| const int matcher3Index = 1; |
| newAtomMatchingTrackerMap[matcher3Id] = 1; |
| const int matcher2Index = 2; |
| newAtomMatchingTrackerMap[matcher2Id] = 2; |
| const int matcher1Index = 3; |
| newAtomMatchingTrackerMap[matcher1Id] = 3; |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(4); |
| std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| set<int64_t> replacedMatchers; |
| |
| unordered_map<int64_t, int> newConditionTrackerMap; |
| vector<sp<ConditionTracker>> newConditionTrackers; |
| set<int64_t> replacedConditions; |
| vector<ConditionState> conditionCache; |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers, |
| newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions, |
| newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{}, |
| /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, |
| newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 3); |
| EXPECT_THAT(activationAtomTrackerToMetricMap[matcher2Index], UnorderedElementsAre(0)); |
| EXPECT_THAT(activationAtomTrackerToMetricMap[matcher3Index], UnorderedElementsAre(0)); |
| EXPECT_THAT(activationAtomTrackerToMetricMap[matcher4Index], UnorderedElementsAre(0)); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 2); |
| EXPECT_THAT(deactivationAtomTrackerToMetricMap[matcher1Index], UnorderedElementsAre(0, 0)); |
| EXPECT_THAT(deactivationAtomTrackerToMetricMap[matcher2Index], UnorderedElementsAre(0)); |
| ASSERT_EQ(metricsWithActivation.size(), 1); |
| EXPECT_THAT(metricsWithActivation, UnorderedElementsAre(0)); |
| |
| // Verify mEventActivation and mEventDeactivation map of the producer. |
| sp<MetricProducer> producer = newMetricProducers[0]; |
| EXPECT_TRUE(producer->isActive()); |
| ASSERT_EQ(producer->mEventActivationMap.size(), 3); |
| shared_ptr<Activation> matcher2Activation = producer->mEventActivationMap[matcher2Index]; |
| EXPECT_EQ(matcher2Activation->ttl_ns, matcher2TtlSec * NS_PER_SEC); |
| EXPECT_EQ(matcher2Activation->activationType, ACTIVATE_IMMEDIATELY); |
| EXPECT_EQ(matcher2Activation->state, kActive); |
| EXPECT_EQ(matcher2Activation->start_ns, matcher2StartNs); |
| shared_ptr<Activation> matcher3Activation = producer->mEventActivationMap[matcher3Index]; |
| EXPECT_EQ(matcher3Activation->ttl_ns, matcher3TtlSec * NS_PER_SEC); |
| EXPECT_EQ(matcher3Activation->activationType, ACTIVATE_ON_BOOT); |
| EXPECT_EQ(matcher3Activation->state, kActiveOnBoot); |
| shared_ptr<Activation> matcher4Activation = producer->mEventActivationMap[matcher4Index]; |
| EXPECT_EQ(matcher4Activation->ttl_ns, matcher4TtlSec * NS_PER_SEC); |
| EXPECT_EQ(matcher4Activation->activationType, ACTIVATE_IMMEDIATELY); |
| EXPECT_EQ(matcher4Activation->state, kNotActive); |
| |
| ASSERT_EQ(producer->mEventDeactivationMap.size(), 2); |
| EXPECT_THAT(producer->mEventDeactivationMap[matcher1Index], |
| UnorderedElementsAre(matcher2Activation, matcher3Activation)); |
| EXPECT_THAT(producer->mEventDeactivationMap[matcher2Index], |
| UnorderedElementsAre(matcher4Activation)); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) { |
| StatsdConfig config; |
| // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig |
| AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher(); |
| int64_t matcher1Id = matcher1.id(); |
| *config.add_atom_matcher() = matcher1; |
| |
| AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher(); |
| int64_t matcher2Id = matcher2.id(); |
| *config.add_atom_matcher() = matcher2; |
| |
| AtomMatcher matcher3 = CreateTemperatureAtomMatcher(); |
| int64_t matcher3Id = matcher3.id(); |
| *config.add_atom_matcher() = matcher3; |
| |
| Predicate predicate1 = CreateScreenIsOnPredicate(); |
| int64_t predicate1Id = predicate1.id(); |
| *config.add_predicate() = predicate1; |
| |
| // Add a few count metrics. |
| // Will be preserved. |
| CountMetric countMetric = createCountMetric("COUNT1", matcher1Id, predicate1Id, {}); |
| int64_t countMetricId = countMetric.id(); |
| *config.add_count_metric() = countMetric; |
| |
| // Will be replaced since matcher2 is replaced. |
| EventMetric eventMetric = createEventMetric("EVENT1", matcher2Id, nullopt); |
| int64_t eventMetricId = eventMetric.id(); |
| *config.add_event_metric() = eventMetric; |
| |
| // Will be replaced because the definition changes - a predicate is added. |
| GaugeMetric gaugeMetric = createGaugeMetric("GAUGE1", matcher3Id, |
| GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt); |
| int64_t gaugeMetricId = gaugeMetric.id(); |
| *config.add_gauge_metric() = gaugeMetric; |
| |
| // Preserved. |
| ValueMetric valueMetric = createValueMetric("VALUE1", matcher3, predicate1Id, {}); |
| int64_t valueMetricId = valueMetric.id(); |
| *config.add_value_metric() = valueMetric; |
| |
| // Preserved. |
| DurationMetric durationMetric = createDurationMetric("DURATION1", predicate1Id, nullopt, {}); |
| int64_t durationMetricId = durationMetric.id(); |
| *config.add_duration_metric() = durationMetric; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Used later to ensure the condition wizard is replaced. Get it before doing the update. |
| sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard; |
| EXPECT_EQ(oldConditionWizard->getStrongCount(), 6); |
| |
| // Mark matcher 2 as replaced. Causes eventMetric to be replaced. |
| set<int64_t> replacedMatchers; |
| replacedMatchers.insert(matcher2Id); |
| |
| // Add predicate1 as a predicate on gaugeMetric, causing it to be replaced. |
| gaugeMetric.set_condition(predicate1Id); |
| |
| // Map the matchers and predicates in reverse order to force the indices to change. |
| std::unordered_map<int64_t, int> newAtomMatchingTrackerMap; |
| const int matcher3Index = 0; |
| newAtomMatchingTrackerMap[matcher3Id] = 0; |
| const int matcher2Index = 1; |
| newAtomMatchingTrackerMap[matcher2Id] = 1; |
| const int matcher1Index = 2; |
| newAtomMatchingTrackerMap[matcher1Id] = 2; |
| // Use the existing matchers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(3); |
| std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(), |
| newAtomMatchingTrackers.begin()); |
| |
| std::unordered_map<int64_t, int> newConditionTrackerMap; |
| const int predicate1Index = 0; |
| newConditionTrackerMap[predicate1Id] = 0; |
| // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them. |
| vector<sp<ConditionTracker>> newConditionTrackers(1); |
| std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(), |
| newConditionTrackers.begin()); |
| vector<ConditionState> conditionCache = {ConditionState::kUnknown}; |
| |
| // The order matters. we parse in the order of: count, duration, event, value, gauge. |
| StatsdConfig newConfig; |
| *newConfig.add_count_metric() = countMetric; |
| const int countMetricIndex = 0; |
| *newConfig.add_duration_metric() = durationMetric; |
| const int durationMetricIndex = 1; |
| *newConfig.add_event_metric() = eventMetric; |
| const int eventMetricIndex = 2; |
| *newConfig.add_value_metric() = valueMetric; |
| const int valueMetricIndex = 3; |
| *newConfig.add_gauge_metric() = gaugeMetric; |
| const int gaugeMetricIndex = 4; |
| |
| // Add the predicate since duration metric needs it. |
| *newConfig.add_predicate() = predicate1; |
| |
| // Output data structures to validate. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers, |
| newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{}, |
| newConditionTrackers, conditionCache, /*stateAtomIdMap*/ {}, /*allStateGroupMaps=*/{}, |
| /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, |
| newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| unordered_map<int64_t, int> expectedMetricProducerMap = { |
| {countMetricId, countMetricIndex}, {durationMetricId, durationMetricIndex}, |
| {eventMetricId, eventMetricIndex}, {valueMetricId, valueMetricIndex}, |
| {gaugeMetricId, gaugeMetricIndex}, |
| }; |
| EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap)); |
| |
| EXPECT_EQ(replacedMetrics, set<int64_t>({eventMetricId, gaugeMetricId})); |
| |
| // Make sure preserved metrics are the same. |
| ASSERT_EQ(newMetricProducers.size(), 5); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(countMetricId)], |
| newMetricProducers[newMetricProducerMap.at(countMetricId)]); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(durationMetricId)], |
| newMetricProducers[newMetricProducerMap.at(durationMetricId)]); |
| EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(valueMetricId)], |
| newMetricProducers[newMetricProducerMap.at(valueMetricId)]); |
| |
| // Make sure replaced metrics are different. |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(eventMetricId)], |
| newMetricProducers[newMetricProducerMap.at(eventMetricId)]); |
| EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gaugeMetricId)], |
| newMetricProducers[newMetricProducerMap.at(gaugeMetricId)]); |
| |
| // Verify the conditionToMetricMap. |
| ASSERT_EQ(conditionToMetricMap.size(), 1); |
| const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index]; |
| EXPECT_THAT(condition1Metrics, |
| UnorderedElementsAre(countMetricIndex, gaugeMetricIndex, valueMetricIndex)); |
| |
| // Verify the trackerToMetricMap. |
| ASSERT_EQ(trackerToMetricMap.size(), 3); |
| const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index]; |
| EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex, durationMetricIndex)); |
| const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index]; |
| EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex, durationMetricIndex)); |
| const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index]; |
| EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(gaugeMetricIndex, valueMetricIndex)); |
| |
| // Verify event activation/deactivation maps. |
| ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0); |
| ASSERT_EQ(metricsWithActivation.size(), 0); |
| |
| // Verify tracker indices/ids/conditions are correct. |
| EXPECT_EQ(newMetricProducers[countMetricIndex]->getMetricId(), countMetricId); |
| EXPECT_EQ(newMetricProducers[countMetricIndex]->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(newMetricProducers[countMetricIndex]->mCondition, ConditionState::kUnknown); |
| EXPECT_EQ(newMetricProducers[durationMetricIndex]->getMetricId(), durationMetricId); |
| EXPECT_EQ(newMetricProducers[durationMetricIndex]->mConditionTrackerIndex, -1); |
| EXPECT_EQ(newMetricProducers[durationMetricIndex]->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(newMetricProducers[eventMetricIndex]->getMetricId(), eventMetricId); |
| EXPECT_EQ(newMetricProducers[eventMetricIndex]->mConditionTrackerIndex, -1); |
| EXPECT_EQ(newMetricProducers[eventMetricIndex]->mCondition, ConditionState::kTrue); |
| EXPECT_EQ(newMetricProducers[gaugeMetricIndex]->getMetricId(), gaugeMetricId); |
| EXPECT_EQ(newMetricProducers[gaugeMetricIndex]->mConditionTrackerIndex, predicate1Index); |
| EXPECT_EQ(newMetricProducers[gaugeMetricIndex]->mCondition, ConditionState::kUnknown); |
| |
| sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard; |
| EXPECT_NE(newConditionWizard, oldConditionWizard); |
| EXPECT_EQ(newConditionWizard->getStrongCount(), 6); |
| oldMetricProducers.clear(); |
| // Only reference to the old wizard should be the one in the test. |
| EXPECT_EQ(oldConditionWizard->getStrongCount(), 1); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestAlertPreserve) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_count_metric() = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {}); |
| |
| Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1); |
| *config.add_alert() = alert; |
| EXPECT_TRUE(initConfig(config)); |
| |
| UpdateStatus updateStatus = UPDATE_UNKNOWN; |
| EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers, |
| /*replacedMetrics*/ {}, updateStatus)); |
| EXPECT_EQ(updateStatus, UPDATE_PRESERVE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestAlertMetricChanged) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| CountMetric metric = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {}); |
| *config.add_count_metric() = metric; |
| |
| Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1); |
| *config.add_alert() = alert; |
| EXPECT_TRUE(initConfig(config)); |
| |
| UpdateStatus updateStatus = UPDATE_UNKNOWN; |
| EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers, |
| /*replacedMetrics*/ {metric.id()}, updateStatus)); |
| EXPECT_EQ(updateStatus, UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestAlertDefinitionChanged) { |
| StatsdConfig config; |
| AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher(); |
| *config.add_atom_matcher() = whatMatcher; |
| |
| *config.add_count_metric() = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {}); |
| |
| Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1); |
| *config.add_alert() = alert; |
| EXPECT_TRUE(initConfig(config)); |
| |
| alert.set_num_buckets(2); |
| |
| UpdateStatus updateStatus = UPDATE_UNKNOWN; |
| EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers, |
| /*replacedMetrics*/ {}, updateStatus)); |
| EXPECT_EQ(updateStatus, UPDATE_REPLACE); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateAlerts) { |
| StatsdConfig config; |
| // Add atom matchers/predicates/metrics. These are mostly needed for initStatsdConfig |
| *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); |
| *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); |
| *config.add_predicate() = CreateScreenIsOnPredicate(); |
| |
| CountMetric countMetric = createCountMetric("COUNT1", config.atom_matcher(0).id(), nullopt, {}); |
| int64_t countMetricId = countMetric.id(); |
| *config.add_count_metric() = countMetric; |
| |
| DurationMetric durationMetric = |
| createDurationMetric("DURATION1", config.predicate(0).id(), nullopt, {}); |
| int64_t durationMetricId = durationMetric.id(); |
| *config.add_duration_metric() = durationMetric; |
| |
| // Add alerts. |
| // Preserved. |
| Alert alert1 = createAlert("Alert1", durationMetricId, /*buckets*/ 1, /*triggerSum*/ 5000); |
| int64_t alert1Id = alert1.id(); |
| *config.add_alert() = alert1; |
| |
| // Replaced. |
| Alert alert2 = createAlert("Alert2", countMetricId, /*buckets*/ 1, /*triggerSum*/ 2); |
| int64_t alert2Id = alert2.id(); |
| *config.add_alert() = alert2; |
| |
| // Replaced. |
| Alert alert3 = createAlert("Alert3", durationMetricId, /*buckets*/ 3, /*triggerSum*/ 5000); |
| int64_t alert3Id = alert3.id(); |
| *config.add_alert() = alert3; |
| |
| // Add Subscriptions. |
| Subscription subscription1 = createSubscription("S1", Subscription::ALERT, alert1Id); |
| *config.add_subscription() = subscription1; |
| Subscription subscription2 = createSubscription("S2", Subscription::ALERT, alert1Id); |
| *config.add_subscription() = subscription2; |
| Subscription subscription3 = createSubscription("S3", Subscription::ALERT, alert2Id); |
| *config.add_subscription() = subscription3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| // Add a duration tracker to the duration metric to ensure durationTrackers are updated |
| // with the proper anomalyTrackers. |
| unique_ptr<LogEvent> event = CreateScreenStateChangedEvent( |
| timeBaseNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_ON); |
| oldMetricProducers[1]->onMatchedLogEvent(0, *event.get()); |
| |
| // Change the count metric. Causes alert2 to be replaced. |
| config.mutable_count_metric(0)->set_bucket(ONE_DAY); |
| // Change num buckets on alert3, causing replacement. |
| alert3.set_num_buckets(5); |
| |
| // New alert. |
| Alert alert4 = createAlert("Alert4", durationMetricId, /*buckets*/ 3, /*triggerSum*/ 10000); |
| int64_t alert4Id = alert4.id(); |
| |
| // Move subscription2 to be on alert2 and make a new subscription. |
| subscription2.set_rule_id(alert2Id); |
| Subscription subscription4 = createSubscription("S4", Subscription::ALERT, alert2Id); |
| |
| // Create the new config. Modify the old one to avoid adding the matchers/predicates. |
| // Add alerts in different order so the map is changed. |
| config.clear_alert(); |
| *config.add_alert() = alert4; |
| const int alert4Index = 0; |
| *config.add_alert() = alert3; |
| const int alert3Index = 1; |
| *config.add_alert() = alert1; |
| const int alert1Index = 2; |
| *config.add_alert() = alert2; |
| const int alert2Index = 3; |
| |
| // Subscription3 is removed. |
| config.clear_subscription(); |
| *config.add_subscription() = subscription4; |
| *config.add_subscription() = subscription2; |
| *config.add_subscription() = subscription1; |
| |
| // Output data structures from update metrics. Don't care about the outputs besides |
| // replacedMetrics, but need to do this so that the metrics clear their anomaly trackers. |
| unordered_map<int64_t, int> newMetricProducerMap; |
| vector<sp<MetricProducer>> newMetricProducers; |
| unordered_map<int, vector<int>> conditionToMetricMap; |
| unordered_map<int, vector<int>> trackerToMetricMap; |
| set<int64_t> noReportMetricIds; |
| unordered_map<int, vector<int>> activationAtomTrackerToMetricMap; |
| unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap; |
| vector<int> metricsWithActivation; |
| set<int64_t> replacedMetrics; |
| EXPECT_TRUE(updateMetrics( |
| key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(), |
| oldAtomMatchingTrackerMap, oldAtomMatchingTrackerMap, /*replacedMatchers*/ {}, |
| oldAtomMatchingTrackers, oldConditionTrackerMap, /*replacedConditions=*/{}, |
| oldConditionTrackers, {ConditionState::kUnknown}, /*stateAtomIdMap*/ {}, |
| /*allStateGroupMaps=*/{}, |
| /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, |
| newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds, |
| activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, |
| metricsWithActivation, replacedMetrics)); |
| |
| EXPECT_EQ(replacedMetrics, set<int64_t>({countMetricId})); |
| |
| unordered_map<int64_t, int> newAlertTrackerMap; |
| vector<sp<AnomalyTracker>> newAnomalyTrackers; |
| EXPECT_TRUE(updateAlerts(config, newMetricProducerMap, replacedMetrics, oldAlertTrackerMap, |
| oldAnomalyTrackers, anomalyAlarmMonitor, newMetricProducers, |
| newAlertTrackerMap, newAnomalyTrackers)); |
| |
| unordered_map<int64_t, int> expectedAlertMap = { |
| {alert1Id, alert1Index}, |
| {alert2Id, alert2Index}, |
| {alert3Id, alert3Index}, |
| {alert4Id, alert4Index}, |
| }; |
| EXPECT_THAT(newAlertTrackerMap, ContainerEq(expectedAlertMap)); |
| |
| // Make sure preserved alerts are the same. |
| ASSERT_EQ(newAnomalyTrackers.size(), 4); |
| EXPECT_EQ(oldAnomalyTrackers[oldAlertTrackerMap.at(alert1Id)], |
| newAnomalyTrackers[newAlertTrackerMap.at(alert1Id)]); |
| |
| // Make sure replaced alerts are different. |
| EXPECT_NE(oldAnomalyTrackers[oldAlertTrackerMap.at(alert2Id)], |
| newAnomalyTrackers[newAlertTrackerMap.at(alert2Id)]); |
| EXPECT_NE(oldAnomalyTrackers[oldAlertTrackerMap.at(alert3Id)], |
| newAnomalyTrackers[newAlertTrackerMap.at(alert3Id)]); |
| |
| // Verify the alerts have the correct anomaly trackers. |
| ASSERT_EQ(newMetricProducers.size(), 2); |
| EXPECT_THAT(newMetricProducers[0]->mAnomalyTrackers, |
| UnorderedElementsAre(newAnomalyTrackers[alert2Index])); |
| // For durationMetric, make sure the duration trackers get the updated anomalyTrackers. |
| DurationMetricProducer* durationProducer = |
| static_cast<DurationMetricProducer*>(newMetricProducers[1].get()); |
| EXPECT_THAT( |
| durationProducer->mAnomalyTrackers, |
| UnorderedElementsAre(newAnomalyTrackers[alert1Index], newAnomalyTrackers[alert3Index], |
| newAnomalyTrackers[alert4Index])); |
| ASSERT_EQ(durationProducer->mCurrentSlicedDurationTrackerMap.size(), 1); |
| for (const auto& durationTrackerIt : durationProducer->mCurrentSlicedDurationTrackerMap) { |
| EXPECT_EQ(durationTrackerIt.second->mAnomalyTrackers, durationProducer->mAnomalyTrackers); |
| } |
| |
| // Verify alerts have the correct subscriptions. Use subscription id as proxy for equivalency. |
| vector<int64_t> alert1Subscriptions; |
| for (const Subscription& subscription : newAnomalyTrackers[alert1Index]->mSubscriptions) { |
| alert1Subscriptions.push_back(subscription.id()); |
| } |
| EXPECT_THAT(alert1Subscriptions, UnorderedElementsAre(subscription1.id())); |
| vector<int64_t> alert2Subscriptions; |
| for (const Subscription& subscription : newAnomalyTrackers[alert2Index]->mSubscriptions) { |
| alert2Subscriptions.push_back(subscription.id()); |
| } |
| EXPECT_THAT(alert2Subscriptions, UnorderedElementsAre(subscription2.id(), subscription4.id())); |
| EXPECT_THAT(newAnomalyTrackers[alert3Index]->mSubscriptions, IsEmpty()); |
| EXPECT_THAT(newAnomalyTrackers[alert4Index]->mSubscriptions, IsEmpty()); |
| } |
| |
| TEST_F(ConfigUpdateTest, TestUpdateAlarms) { |
| StatsdConfig config; |
| // Add alarms. |
| Alarm alarm1 = createAlarm("Alarm1", /*offset*/ 1 * MS_PER_SEC, /*period*/ 50 * MS_PER_SEC); |
| int64_t alarm1Id = alarm1.id(); |
| *config.add_alarm() = alarm1; |
| |
| Alarm alarm2 = createAlarm("Alarm2", /*offset*/ 1 * MS_PER_SEC, /*period*/ 2000 * MS_PER_SEC); |
| int64_t alarm2Id = alarm2.id(); |
| *config.add_alarm() = alarm2; |
| |
| Alarm alarm3 = createAlarm("Alarm3", /*offset*/ 10 * MS_PER_SEC, /*period*/ 5000 * MS_PER_SEC); |
| int64_t alarm3Id = alarm3.id(); |
| *config.add_alarm() = alarm3; |
| |
| // Add Subscriptions. |
| Subscription subscription1 = createSubscription("S1", Subscription::ALARM, alarm1Id); |
| *config.add_subscription() = subscription1; |
| Subscription subscription2 = createSubscription("S2", Subscription::ALARM, alarm1Id); |
| *config.add_subscription() = subscription2; |
| Subscription subscription3 = createSubscription("S3", Subscription::ALARM, alarm2Id); |
| *config.add_subscription() = subscription3; |
| |
| EXPECT_TRUE(initConfig(config)); |
| |
| ASSERT_EQ(oldAlarmTrackers.size(), 3); |
| // Config is created at statsd start time, so just add the offsets. |
| EXPECT_EQ(oldAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1); |
| EXPECT_EQ(oldAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1); |
| EXPECT_EQ(oldAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10); |
| |
| // Change alarm2/alarm3. |
| config.mutable_alarm(1)->set_offset_millis(5 * MS_PER_SEC); |
| config.mutable_alarm(2)->set_period_millis(10000 * MS_PER_SEC); |
| |
| // Move subscription2 to be on alarm2 and make a new subscription. |
| config.mutable_subscription(1)->set_rule_id(alarm2Id); |
| Subscription subscription4 = createSubscription("S4", Subscription::ALARM, alarm1Id); |
| *config.add_subscription() = subscription4; |
| |
| // Update time is 2 seconds after the base time. |
| int64_t currentTimeNs = timeBaseNs + 2 * NS_PER_SEC; |
| vector<sp<AlarmTracker>> newAlarmTrackers; |
| EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs, |
| newAlarmTrackers)); |
| |
| ASSERT_EQ(newAlarmTrackers.size(), 3); |
| // Config is updated 2 seconds after statsd start |
| // The offset has passed for alarm1, but not for alarms 2/3. |
| EXPECT_EQ(newAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1 + 50); |
| EXPECT_EQ(newAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 5); |
| EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10); |
| |
| // Verify alarms have the correct subscriptions. Use subscription id as proxy for equivalency. |
| vector<int64_t> alarm1Subscriptions; |
| for (const Subscription& subscription : newAlarmTrackers[0]->mSubscriptions) { |
| alarm1Subscriptions.push_back(subscription.id()); |
| } |
| EXPECT_THAT(alarm1Subscriptions, UnorderedElementsAre(subscription1.id(), subscription4.id())); |
| vector<int64_t> alarm2Subscriptions; |
| for (const Subscription& subscription : newAlarmTrackers[1]->mSubscriptions) { |
| alarm2Subscriptions.push_back(subscription.id()); |
| } |
| EXPECT_THAT(alarm2Subscriptions, UnorderedElementsAre(subscription2.id(), subscription3.id())); |
| EXPECT_THAT(newAlarmTrackers[2]->mSubscriptions, IsEmpty()); |
| |
| // Verify the alarm monitor is updated accordingly once the old alarms are removed. |
| // Alarm2 fires the earliest. |
| oldAlarmTrackers.clear(); |
| EXPECT_EQ(periodicAlarmMonitor->getRegisteredAlarmTimeSec(), timeBaseNs / NS_PER_SEC + 5); |
| |
| // Do another update 60 seconds after config creation time, after the offsets of each alarm. |
| currentTimeNs = timeBaseNs + 60 * NS_PER_SEC; |
| newAlarmTrackers.clear(); |
| EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs, |
| newAlarmTrackers)); |
| |
| ASSERT_EQ(newAlarmTrackers.size(), 3); |
| // Config is updated one minute after statsd start. |
| // Two periods have passed for alarm 1, one has passed for alarms2/3. |
| EXPECT_EQ(newAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1 + 2 * 50); |
| EXPECT_EQ(newAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 5 + 2000); |
| EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10 + 10000); |
| } |
| |
| } // namespace statsd |
| } // namespace os |
| } // namespace android |
| |
| #else |
| GTEST_LOG_(INFO) << "This test does nothing.\n"; |
| #endif |