1 // Copyright (C) 2017 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <gtest/gtest.h> 16 17 #include "src/condition/ConditionTracker.h" 18 #include "src/matchers/LogMatchingTracker.h" 19 #include "src/metrics/CountMetricProducer.h" 20 #include "src/metrics/GaugeMetricProducer.h" 21 #include "src/metrics/MetricProducer.h" 22 #include "src/metrics/ValueMetricProducer.h" 23 #include "src/metrics/metrics_manager_util.h" 24 #include "statsd_test_util.h" 25 26 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" 27 28 #include <stdio.h> 29 #include <set> 30 #include <unordered_map> 31 #include <vector> 32 33 using namespace android::os::statsd; 34 using android::sp; 35 using std::set; 36 using std::unordered_map; 37 using std::vector; 38 using android::os::statsd::Predicate; 39 40 #ifdef __ANDROID__ 41 42 // TODO: ADD MORE TEST CASES. 43 44 const ConfigKey kConfigKey(0, 12345); 45 46 const long timeBaseSec = 1000; 47 48 StatsdConfig buildGoodConfig() { 49 StatsdConfig config; 50 config.set_id(12345); 51 52 AtomMatcher* eventMatcher = config.add_atom_matcher(); 53 eventMatcher->set_id(StringToId("SCREEN_IS_ON")); 54 55 SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 56 simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); 57 simpleAtomMatcher->add_field_value_matcher()->set_field( 58 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); 59 simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 60 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); 61 62 eventMatcher = config.add_atom_matcher(); 63 eventMatcher->set_id(StringToId("SCREEN_IS_OFF")); 64 65 simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 66 simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); 67 simpleAtomMatcher->add_field_value_matcher()->set_field( 68 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); 69 simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 70 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/); 71 72 eventMatcher = config.add_atom_matcher(); 73 eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); 74 75 AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); 76 combination->set_operation(LogicalOperation::OR); 77 combination->add_matcher(StringToId("SCREEN_IS_ON")); 78 combination->add_matcher(StringToId("SCREEN_IS_OFF")); 79 80 CountMetric* metric = config.add_count_metric(); 81 metric->set_id(3); 82 metric->set_what(StringToId("SCREEN_IS_ON")); 83 metric->set_bucket(ONE_MINUTE); 84 metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); 85 metric->mutable_dimensions_in_what()->add_child()->set_field(1); 86 87 config.add_no_report_metric(3); 88 89 auto alert = config.add_alert(); 90 alert->set_id(3); 91 alert->set_metric_id(3); 92 alert->set_num_buckets(10); 93 alert->set_refractory_period_secs(100); 94 alert->set_trigger_if_sum_gt(100); 95 return config; 96 } 97 98 StatsdConfig buildCircleMatchers() { 99 StatsdConfig config; 100 config.set_id(12345); 101 102 AtomMatcher* eventMatcher = config.add_atom_matcher(); 103 eventMatcher->set_id(StringToId("SCREEN_IS_ON")); 104 105 SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 106 simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); 107 simpleAtomMatcher->add_field_value_matcher()->set_field( 108 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); 109 simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 110 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); 111 112 eventMatcher = config.add_atom_matcher(); 113 eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); 114 115 AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); 116 combination->set_operation(LogicalOperation::OR); 117 combination->add_matcher(StringToId("SCREEN_IS_ON")); 118 // Circle dependency 119 combination->add_matcher(StringToId("SCREEN_ON_OR_OFF")); 120 121 return config; 122 } 123 124 StatsdConfig buildAlertWithUnknownMetric() { 125 StatsdConfig config; 126 config.set_id(12345); 127 128 AtomMatcher* eventMatcher = config.add_atom_matcher(); 129 eventMatcher->set_id(StringToId("SCREEN_IS_ON")); 130 131 CountMetric* metric = config.add_count_metric(); 132 metric->set_id(3); 133 metric->set_what(StringToId("SCREEN_IS_ON")); 134 metric->set_bucket(ONE_MINUTE); 135 metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); 136 metric->mutable_dimensions_in_what()->add_child()->set_field(1); 137 138 auto alert = config.add_alert(); 139 alert->set_id(3); 140 alert->set_metric_id(2); 141 alert->set_num_buckets(10); 142 alert->set_refractory_period_secs(100); 143 alert->set_trigger_if_sum_gt(100); 144 return config; 145 } 146 147 StatsdConfig buildMissingMatchers() { 148 StatsdConfig config; 149 config.set_id(12345); 150 151 AtomMatcher* eventMatcher = config.add_atom_matcher(); 152 eventMatcher->set_id(StringToId("SCREEN_IS_ON")); 153 154 SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 155 simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); 156 simpleAtomMatcher->add_field_value_matcher()->set_field( 157 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); 158 simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 159 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); 160 161 eventMatcher = config.add_atom_matcher(); 162 eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); 163 164 AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); 165 combination->set_operation(LogicalOperation::OR); 166 combination->add_matcher(StringToId("SCREEN_IS_ON")); 167 // undefined matcher 168 combination->add_matcher(StringToId("ABC")); 169 170 return config; 171 } 172 173 StatsdConfig buildMissingPredicate() { 174 StatsdConfig config; 175 config.set_id(12345); 176 177 CountMetric* metric = config.add_count_metric(); 178 metric->set_id(3); 179 metric->set_what(StringToId("SCREEN_EVENT")); 180 metric->set_bucket(ONE_MINUTE); 181 metric->set_condition(StringToId("SOME_CONDITION")); 182 183 AtomMatcher* eventMatcher = config.add_atom_matcher(); 184 eventMatcher->set_id(StringToId("SCREEN_EVENT")); 185 186 SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 187 simpleAtomMatcher->set_atom_id(2); 188 189 return config; 190 } 191 192 StatsdConfig buildDimensionMetricsWithMultiTags() { 193 StatsdConfig config; 194 config.set_id(12345); 195 196 AtomMatcher* eventMatcher = config.add_atom_matcher(); 197 eventMatcher->set_id(StringToId("BATTERY_VERY_LOW")); 198 SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 199 simpleAtomMatcher->set_atom_id(2); 200 201 eventMatcher = config.add_atom_matcher(); 202 eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW")); 203 simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 204 simpleAtomMatcher->set_atom_id(3); 205 206 eventMatcher = config.add_atom_matcher(); 207 eventMatcher->set_id(StringToId("BATTERY_LOW")); 208 209 AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); 210 combination->set_operation(LogicalOperation::OR); 211 combination->add_matcher(StringToId("BATTERY_VERY_LOW")); 212 combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW")); 213 214 // Count process state changes, slice by uid, while SCREEN_IS_OFF 215 CountMetric* metric = config.add_count_metric(); 216 metric->set_id(3); 217 metric->set_what(StringToId("BATTERY_LOW")); 218 metric->set_bucket(ONE_MINUTE); 219 // This case is interesting. We want to dimension across two atoms. 220 metric->mutable_dimensions_in_what()->add_child()->set_field(1); 221 222 auto alert = config.add_alert(); 223 alert->set_id(103); 224 alert->set_metric_id(3); 225 alert->set_num_buckets(10); 226 alert->set_refractory_period_secs(100); 227 alert->set_trigger_if_sum_gt(100); 228 return config; 229 } 230 231 StatsdConfig buildCirclePredicates() { 232 StatsdConfig config; 233 config.set_id(12345); 234 235 AtomMatcher* eventMatcher = config.add_atom_matcher(); 236 eventMatcher->set_id(StringToId("SCREEN_IS_ON")); 237 238 SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 239 simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); 240 simpleAtomMatcher->add_field_value_matcher()->set_field( 241 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); 242 simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 243 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); 244 245 eventMatcher = config.add_atom_matcher(); 246 eventMatcher->set_id(StringToId("SCREEN_IS_OFF")); 247 248 simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); 249 simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); 250 simpleAtomMatcher->add_field_value_matcher()->set_field( 251 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); 252 simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 253 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/); 254 255 auto condition = config.add_predicate(); 256 condition->set_id(StringToId("SCREEN_IS_ON")); 257 SimplePredicate* simplePredicate = condition->mutable_simple_predicate(); 258 simplePredicate->set_start(StringToId("SCREEN_IS_ON")); 259 simplePredicate->set_stop(StringToId("SCREEN_IS_OFF")); 260 261 condition = config.add_predicate(); 262 condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF")); 263 264 Predicate_Combination* combination = condition->mutable_combination(); 265 combination->set_operation(LogicalOperation::OR); 266 combination->add_predicate(StringToId("SCREEN_IS_ON")); 267 combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF")); 268 269 return config; 270 } 271 272 TEST(MetricsManagerTest, TestGoodConfig) { 273 UidMap uidMap; 274 sp<AlarmMonitor> anomalyAlarmMonitor; 275 sp<AlarmMonitor> periodicAlarmMonitor; 276 StatsdConfig config = buildGoodConfig(); 277 set<int> allTagIds; 278 vector<sp<LogMatchingTracker>> allAtomMatchers; 279 vector<sp<ConditionTracker>> allConditionTrackers; 280 vector<sp<MetricProducer>> allMetricProducers; 281 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 282 std::vector<sp<AlarmTracker>> allAlarmTrackers; 283 unordered_map<int, std::vector<int>> conditionToMetricMap; 284 unordered_map<int, std::vector<int>> trackerToMetricMap; 285 unordered_map<int, std::vector<int>> trackerToConditionMap; 286 std::set<int64_t> noReportMetricIds; 287 288 EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, 289 anomalyAlarmMonitor, periodicAlarmMonitor, 290 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 291 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 292 allAlarmTrackers, 293 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 294 noReportMetricIds)); 295 EXPECT_EQ(1u, allMetricProducers.size()); 296 EXPECT_EQ(1u, allAnomalyTrackers.size()); 297 EXPECT_EQ(1u, noReportMetricIds.size()); 298 } 299 300 TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) { 301 UidMap uidMap; 302 sp<AlarmMonitor> anomalyAlarmMonitor; 303 sp<AlarmMonitor> periodicAlarmMonitor; 304 StatsdConfig config = buildDimensionMetricsWithMultiTags(); 305 set<int> allTagIds; 306 vector<sp<LogMatchingTracker>> allAtomMatchers; 307 vector<sp<ConditionTracker>> allConditionTrackers; 308 vector<sp<MetricProducer>> allMetricProducers; 309 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 310 std::vector<sp<AlarmTracker>> allAlarmTrackers; 311 unordered_map<int, std::vector<int>> conditionToMetricMap; 312 unordered_map<int, std::vector<int>> trackerToMetricMap; 313 unordered_map<int, std::vector<int>> trackerToConditionMap; 314 std::set<int64_t> noReportMetricIds; 315 316 EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, 317 anomalyAlarmMonitor, periodicAlarmMonitor, 318 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 319 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 320 allAlarmTrackers, 321 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 322 noReportMetricIds)); 323 } 324 325 TEST(MetricsManagerTest, TestCircleLogMatcherDependency) { 326 UidMap uidMap; 327 sp<AlarmMonitor> anomalyAlarmMonitor; 328 sp<AlarmMonitor> periodicAlarmMonitor; 329 StatsdConfig config = buildCircleMatchers(); 330 set<int> allTagIds; 331 vector<sp<LogMatchingTracker>> allAtomMatchers; 332 vector<sp<ConditionTracker>> allConditionTrackers; 333 vector<sp<MetricProducer>> allMetricProducers; 334 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 335 std::vector<sp<AlarmTracker>> allAlarmTrackers; 336 unordered_map<int, std::vector<int>> conditionToMetricMap; 337 unordered_map<int, std::vector<int>> trackerToMetricMap; 338 unordered_map<int, std::vector<int>> trackerToConditionMap; 339 std::set<int64_t> noReportMetricIds; 340 341 EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, 342 anomalyAlarmMonitor, periodicAlarmMonitor, 343 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 344 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 345 allAlarmTrackers, 346 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 347 noReportMetricIds)); 348 } 349 350 TEST(MetricsManagerTest, TestMissingMatchers) { 351 UidMap uidMap; 352 sp<AlarmMonitor> anomalyAlarmMonitor; 353 sp<AlarmMonitor> periodicAlarmMonitor; 354 StatsdConfig config = buildMissingMatchers(); 355 set<int> allTagIds; 356 vector<sp<LogMatchingTracker>> allAtomMatchers; 357 vector<sp<ConditionTracker>> allConditionTrackers; 358 vector<sp<MetricProducer>> allMetricProducers; 359 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 360 std::vector<sp<AlarmTracker>> allAlarmTrackers; 361 unordered_map<int, std::vector<int>> conditionToMetricMap; 362 unordered_map<int, std::vector<int>> trackerToMetricMap; 363 unordered_map<int, std::vector<int>> trackerToConditionMap; 364 std::set<int64_t> noReportMetricIds; 365 EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, 366 anomalyAlarmMonitor, periodicAlarmMonitor, 367 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 368 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 369 allAlarmTrackers, 370 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 371 noReportMetricIds)); 372 } 373 374 TEST(MetricsManagerTest, TestMissingPredicate) { 375 UidMap uidMap; 376 sp<AlarmMonitor> anomalyAlarmMonitor; 377 sp<AlarmMonitor> periodicAlarmMonitor; 378 StatsdConfig config = buildMissingPredicate(); 379 set<int> allTagIds; 380 vector<sp<LogMatchingTracker>> allAtomMatchers; 381 vector<sp<ConditionTracker>> allConditionTrackers; 382 vector<sp<MetricProducer>> allMetricProducers; 383 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 384 std::vector<sp<AlarmTracker>> allAlarmTrackers; 385 unordered_map<int, std::vector<int>> conditionToMetricMap; 386 unordered_map<int, std::vector<int>> trackerToMetricMap; 387 unordered_map<int, std::vector<int>> trackerToConditionMap; 388 std::set<int64_t> noReportMetricIds; 389 EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, 390 anomalyAlarmMonitor, periodicAlarmMonitor, 391 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 392 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 393 allAlarmTrackers, 394 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 395 noReportMetricIds)); 396 } 397 398 TEST(MetricsManagerTest, TestCirclePredicateDependency) { 399 UidMap uidMap; 400 sp<AlarmMonitor> anomalyAlarmMonitor; 401 sp<AlarmMonitor> periodicAlarmMonitor; 402 StatsdConfig config = buildCirclePredicates(); 403 set<int> allTagIds; 404 vector<sp<LogMatchingTracker>> allAtomMatchers; 405 vector<sp<ConditionTracker>> allConditionTrackers; 406 vector<sp<MetricProducer>> allMetricProducers; 407 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 408 std::vector<sp<AlarmTracker>> allAlarmTrackers; 409 unordered_map<int, std::vector<int>> conditionToMetricMap; 410 unordered_map<int, std::vector<int>> trackerToMetricMap; 411 unordered_map<int, std::vector<int>> trackerToConditionMap; 412 std::set<int64_t> noReportMetricIds; 413 414 EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, 415 anomalyAlarmMonitor, periodicAlarmMonitor, 416 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 417 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 418 allAlarmTrackers, 419 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 420 noReportMetricIds)); 421 } 422 423 TEST(MetricsManagerTest, testAlertWithUnknownMetric) { 424 UidMap uidMap; 425 sp<AlarmMonitor> anomalyAlarmMonitor; 426 sp<AlarmMonitor> periodicAlarmMonitor; 427 StatsdConfig config = buildAlertWithUnknownMetric(); 428 set<int> allTagIds; 429 vector<sp<LogMatchingTracker>> allAtomMatchers; 430 vector<sp<ConditionTracker>> allConditionTrackers; 431 vector<sp<MetricProducer>> allMetricProducers; 432 std::vector<sp<AnomalyTracker>> allAnomalyTrackers; 433 std::vector<sp<AlarmTracker>> allAlarmTrackers; 434 unordered_map<int, std::vector<int>> conditionToMetricMap; 435 unordered_map<int, std::vector<int>> trackerToMetricMap; 436 unordered_map<int, std::vector<int>> trackerToConditionMap; 437 std::set<int64_t> noReportMetricIds; 438 439 EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, 440 anomalyAlarmMonitor, periodicAlarmMonitor, 441 timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, 442 allConditionTrackers, allMetricProducers, allAnomalyTrackers, 443 allAlarmTrackers, 444 conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, 445 noReportMetricIds)); 446 } 447 448 #else 449 GTEST_LOG_(INFO) << "This test does nothing.\n"; 450 #endif 451