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 "src/guardrail/StatsdStats.h"
16 #include "statslog.h"
17 #include "tests/statsd_test_util.h"
18 
19 #include <gtest/gtest.h>
20 #include <vector>
21 
22 #ifdef __ANDROID__
23 
24 namespace android {
25 namespace os {
26 namespace statsd {
27 
28 using std::vector;
29 
TEST(StatsdStatsTest,TestValidConfigAdd)30 TEST(StatsdStatsTest, TestValidConfigAdd) {
31     StatsdStats stats;
32     ConfigKey key(0, 12345);
33     const int metricsCount = 10;
34     const int conditionsCount = 20;
35     const int matchersCount = 30;
36     const int alertsCount = 10;
37     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
38                              true /*valid config*/);
39     vector<uint8_t> output;
40     stats.dumpStats(&output, false /*reset stats*/);
41 
42     StatsdStatsReport report;
43     bool good = report.ParseFromArray(&output[0], output.size());
44     EXPECT_TRUE(good);
45     EXPECT_EQ(1, report.config_stats_size());
46     const auto& configReport = report.config_stats(0);
47     EXPECT_EQ(0, configReport.uid());
48     EXPECT_EQ(12345, configReport.id());
49     EXPECT_EQ(metricsCount, configReport.metric_count());
50     EXPECT_EQ(conditionsCount, configReport.condition_count());
51     EXPECT_EQ(matchersCount, configReport.matcher_count());
52     EXPECT_EQ(alertsCount, configReport.alert_count());
53     EXPECT_EQ(true, configReport.is_valid());
54     EXPECT_FALSE(configReport.has_deletion_time_sec());
55 }
56 
TEST(StatsdStatsTest,TestInvalidConfigAdd)57 TEST(StatsdStatsTest, TestInvalidConfigAdd) {
58     StatsdStats stats;
59     ConfigKey key(0, 12345);
60     const int metricsCount = 10;
61     const int conditionsCount = 20;
62     const int matchersCount = 30;
63     const int alertsCount = 10;
64     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
65                              false /*bad config*/);
66     vector<uint8_t> output;
67     stats.dumpStats(&output, false);
68 
69     StatsdStatsReport report;
70     bool good = report.ParseFromArray(&output[0], output.size());
71     EXPECT_TRUE(good);
72     EXPECT_EQ(1, report.config_stats_size());
73     const auto& configReport = report.config_stats(0);
74     // The invalid config should be put into icebox with a deletion time.
75     EXPECT_TRUE(configReport.has_deletion_time_sec());
76 }
77 
TEST(StatsdStatsTest,TestConfigRemove)78 TEST(StatsdStatsTest, TestConfigRemove) {
79     StatsdStats stats;
80     ConfigKey key(0, 12345);
81     const int metricsCount = 10;
82     const int conditionsCount = 20;
83     const int matchersCount = 30;
84     const int alertsCount = 10;
85     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
86                              true);
87     vector<uint8_t> output;
88     stats.dumpStats(&output, false);
89     StatsdStatsReport report;
90     bool good = report.ParseFromArray(&output[0], output.size());
91     EXPECT_TRUE(good);
92     EXPECT_EQ(1, report.config_stats_size());
93     const auto& configReport = report.config_stats(0);
94     EXPECT_FALSE(configReport.has_deletion_time_sec());
95 
96     stats.noteConfigRemoved(key);
97     stats.dumpStats(&output, false);
98     good = report.ParseFromArray(&output[0], output.size());
99     EXPECT_TRUE(good);
100     EXPECT_EQ(1, report.config_stats_size());
101     const auto& configReport2 = report.config_stats(0);
102     EXPECT_TRUE(configReport2.has_deletion_time_sec());
103 }
104 
TEST(StatsdStatsTest,TestSubStats)105 TEST(StatsdStatsTest, TestSubStats) {
106     StatsdStats stats;
107     ConfigKey key(0, 12345);
108     stats.noteConfigReceived(key, 2, 3, 4, 5, {std::make_pair(123, 456)}, true);
109 
110     stats.noteMatcherMatched(key, StringToId("matcher1"));
111     stats.noteMatcherMatched(key, StringToId("matcher1"));
112     stats.noteMatcherMatched(key, StringToId("matcher2"));
113 
114     stats.noteConditionDimensionSize(key, StringToId("condition1"), 250);
115     stats.noteConditionDimensionSize(key, StringToId("condition1"), 240);
116 
117     stats.noteMetricDimensionSize(key, StringToId("metric1"), 201);
118     stats.noteMetricDimensionSize(key, StringToId("metric1"), 202);
119 
120     stats.noteAnomalyDeclared(key, StringToId("alert1"));
121     stats.noteAnomalyDeclared(key, StringToId("alert1"));
122     stats.noteAnomalyDeclared(key, StringToId("alert2"));
123 
124     // broadcast-> 2
125     stats.noteBroadcastSent(key);
126     stats.noteBroadcastSent(key);
127 
128     // data drop -> 1
129     stats.noteDataDropped(key);
130 
131     // dump report -> 3
132     stats.noteMetricsReportSent(key, 0);
133     stats.noteMetricsReportSent(key, 0);
134     stats.noteMetricsReportSent(key, 0);
135 
136     vector<uint8_t> output;
137     stats.dumpStats(&output, true);  // Dump and reset stats
138     StatsdStatsReport report;
139     bool good = report.ParseFromArray(&output[0], output.size());
140     EXPECT_TRUE(good);
141     EXPECT_EQ(1, report.config_stats_size());
142     const auto& configReport = report.config_stats(0);
143     EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
144     EXPECT_EQ(1, configReport.data_drop_time_sec_size());
145     EXPECT_EQ(3, configReport.dump_report_time_sec_size());
146     EXPECT_EQ(3, configReport.dump_report_data_size_size());
147     EXPECT_EQ(1, configReport.annotation_size());
148     EXPECT_EQ(123, configReport.annotation(0).field_int64());
149     EXPECT_EQ(456, configReport.annotation(0).field_int32());
150 
151     EXPECT_EQ(2, configReport.matcher_stats_size());
152     // matcher1 is the first in the list
153     if (configReport.matcher_stats(0).id() == StringToId("matcher1")) {
154         EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
155         EXPECT_EQ(1, configReport.matcher_stats(1).matched_times());
156         EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(1).id());
157     } else {
158         // matcher1 is the second in the list.
159         EXPECT_EQ(1, configReport.matcher_stats(0).matched_times());
160         EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(0).id());
161 
162         EXPECT_EQ(2, configReport.matcher_stats(1).matched_times());
163         EXPECT_EQ(StringToId("matcher1"), configReport.matcher_stats(1).id());
164     }
165 
166     EXPECT_EQ(2, configReport.alert_stats_size());
167     bool alert1first = configReport.alert_stats(0).id() == StringToId("alert1");
168     EXPECT_EQ(StringToId("alert1"), configReport.alert_stats(alert1first ? 0 : 1).id());
169     EXPECT_EQ(2, configReport.alert_stats(alert1first ? 0 : 1).alerted_times());
170     EXPECT_EQ(StringToId("alert2"), configReport.alert_stats(alert1first ? 1 : 0).id());
171     EXPECT_EQ(1, configReport.alert_stats(alert1first ? 1 : 0).alerted_times());
172 
173     EXPECT_EQ(1, configReport.condition_stats_size());
174     EXPECT_EQ(StringToId("condition1"), configReport.condition_stats(0).id());
175     EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
176 
177     EXPECT_EQ(1, configReport.metric_stats_size());
178     EXPECT_EQ(StringToId("metric1"), configReport.metric_stats(0).id());
179     EXPECT_EQ(202, configReport.metric_stats(0).max_tuple_counts());
180 
181     // after resetting the stats, some new events come
182     stats.noteMatcherMatched(key, StringToId("matcher99"));
183     stats.noteConditionDimensionSize(key, StringToId("condition99"), 300);
184     stats.noteMetricDimensionSize(key, StringToId("metric99tion99"), 270);
185     stats.noteAnomalyDeclared(key, StringToId("alert99"));
186 
187     // now the config stats should only contain the stats about the new event.
188     stats.dumpStats(&output, false);
189     good = report.ParseFromArray(&output[0], output.size());
190     EXPECT_TRUE(good);
191     EXPECT_EQ(1, report.config_stats_size());
192     const auto& configReport2 = report.config_stats(0);
193     EXPECT_EQ(1, configReport2.matcher_stats_size());
194     EXPECT_EQ(StringToId("matcher99"), configReport2.matcher_stats(0).id());
195     EXPECT_EQ(1, configReport2.matcher_stats(0).matched_times());
196 
197     EXPECT_EQ(1, configReport2.condition_stats_size());
198     EXPECT_EQ(StringToId("condition99"), configReport2.condition_stats(0).id());
199     EXPECT_EQ(300, configReport2.condition_stats(0).max_tuple_counts());
200 
201     EXPECT_EQ(1, configReport2.metric_stats_size());
202     EXPECT_EQ(StringToId("metric99tion99"), configReport2.metric_stats(0).id());
203     EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
204 
205     EXPECT_EQ(1, configReport2.alert_stats_size());
206     EXPECT_EQ(StringToId("alert99"), configReport2.alert_stats(0).id());
207     EXPECT_EQ(1, configReport2.alert_stats(0).alerted_times());
208 }
209 
TEST(StatsdStatsTest,TestAtomLog)210 TEST(StatsdStatsTest, TestAtomLog) {
211     StatsdStats stats;
212     time_t now = time(nullptr);
213     // old event, we get it from the stats buffer. should be ignored.
214     stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, 1000);
215 
216     stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 1);
217     stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 2);
218     stats.noteAtomLogged(android::util::APP_CRASH_OCCURRED, now + 3);
219     // pulled event, should ignore
220     stats.noteAtomLogged(android::util::WIFI_BYTES_TRANSFER, now + 4);
221 
222     vector<uint8_t> output;
223     stats.dumpStats(&output, false);
224     StatsdStatsReport report;
225     bool good = report.ParseFromArray(&output[0], output.size());
226     EXPECT_TRUE(good);
227 
228     EXPECT_EQ(2, report.atom_stats_size());
229     bool sensorAtomGood = false;
230     bool dropboxAtomGood = false;
231 
232     for (const auto& atomStats : report.atom_stats()) {
233         if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
234             sensorAtomGood = true;
235         }
236         if (atomStats.tag() == android::util::APP_CRASH_OCCURRED && atomStats.count() == 1) {
237             dropboxAtomGood = true;
238         }
239     }
240 
241     EXPECT_TRUE(dropboxAtomGood);
242     EXPECT_TRUE(sensorAtomGood);
243 }
244 
245 
TEST(StatsdStatsTest,TestAnomalyMonitor)246 TEST(StatsdStatsTest, TestAnomalyMonitor) {
247     StatsdStats stats;
248     stats.noteRegisteredAnomalyAlarmChanged();
249     stats.noteRegisteredAnomalyAlarmChanged();
250 
251     vector<uint8_t> output;
252     stats.dumpStats(&output, false);
253     StatsdStatsReport report;
254     bool good = report.ParseFromArray(&output[0], output.size());
255     EXPECT_TRUE(good);
256 
257     EXPECT_EQ(2, report.anomaly_alarm_stats().alarms_registered());
258 }
259 
TEST(StatsdStatsTest,TestTimestampThreshold)260 TEST(StatsdStatsTest, TestTimestampThreshold) {
261     StatsdStats stats;
262     vector<int32_t> timestamps;
263     for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
264         timestamps.push_back(i);
265     }
266     ConfigKey key(0, 12345);
267     stats.noteConfigReceived(key, 2, 3, 4, 5, {}, true);
268 
269     for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
270         stats.noteDataDropped(key, timestamps[i]);
271         stats.noteBroadcastSent(key, timestamps[i]);
272         stats.noteMetricsReportSent(key, 0, timestamps[i]);
273     }
274 
275     int32_t newTimestamp = 10000;
276 
277     // now it should trigger removing oldest timestamp
278     stats.noteDataDropped(key, 10000);
279     stats.noteBroadcastSent(key, 10000);
280     stats.noteMetricsReportSent(key, 0, 10000);
281 
282     EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
283     const auto& configStats = stats.mConfigStats[key];
284 
285     size_t maxCount = StatsdStats::kMaxTimestampCount;
286     EXPECT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
287     EXPECT_EQ(maxCount, configStats->data_drop_time_sec.size());
288     EXPECT_EQ(maxCount, configStats->dump_report_stats.size());
289 
290     // the oldest timestamp is the second timestamp in history
291     EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
292     EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
293     EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
294 
295     // the last timestamp is the newest timestamp.
296     EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
297     EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
298     EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
299 }
300 
TEST(StatsdStatsTest,TestSystemServerCrash)301 TEST(StatsdStatsTest, TestSystemServerCrash) {
302     StatsdStats stats;
303     vector<int32_t> timestamps;
304     for (int i = 0; i < StatsdStats::kMaxSystemServerRestarts; i++) {
305         timestamps.push_back(i);
306         stats.noteSystemServerRestart(timestamps[i]);
307     }
308     vector<uint8_t> output;
309     stats.dumpStats(&output, false);
310     StatsdStatsReport report;
311     EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
312     const int maxCount = StatsdStats::kMaxSystemServerRestarts;
313     EXPECT_EQ(maxCount, (int)report.system_restart_sec_size());
314 
315     stats.noteSystemServerRestart(StatsdStats::kMaxSystemServerRestarts + 1);
316     output.clear();
317     stats.dumpStats(&output, false);
318     EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
319     EXPECT_EQ(maxCount, (int)report.system_restart_sec_size());
320     EXPECT_EQ(StatsdStats::kMaxSystemServerRestarts + 1, report.system_restart_sec(maxCount - 1));
321 }
322 
323 }  // namespace statsd
324 }  // namespace os
325 }  // namespace android
326 #else
327 GTEST_LOG_(INFO) << "This test does nothing.\n";
328 #endif
329