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
buildGoodConfig()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
buildCircleMatchers()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
buildAlertWithUnknownMetric()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
buildMissingMatchers()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
buildMissingPredicate()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
buildDimensionMetricsWithMultiTags()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
buildCirclePredicates()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
TEST(MetricsManagerTest,TestGoodConfig)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
TEST(MetricsManagerTest,TestDimensionMetricsWithMultiTags)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
TEST(MetricsManagerTest,TestCircleLogMatcherDependency)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
TEST(MetricsManagerTest,TestMissingMatchers)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
TEST(MetricsManagerTest,TestMissingPredicate)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
TEST(MetricsManagerTest,TestCirclePredicateDependency)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
TEST(MetricsManagerTest,testAlertWithUnknownMetric)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