blob: a8193dd92e8c1cffb5a8beec5f537ae2bef7e33f [file] [log] [blame]
Yao Chenb3561512017-11-21 18:07:17 -08001// 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"
Yao Chen69f1baf2017-11-27 17:25:36 -080016#include "statslog.h"
Yao Chenb3561512017-11-21 18:07:17 -080017
18#include <gtest/gtest.h>
Yao Chen69f1baf2017-11-27 17:25:36 -080019#include <vector>
Yao Chenb3561512017-11-21 18:07:17 -080020
21#ifdef __ANDROID__
22
23namespace android {
24namespace os {
25namespace statsd {
26
Yao Chen69f1baf2017-11-27 17:25:36 -080027using std::vector;
28
29TEST(StatsdStatsTest, TestValidConfigAdd) {
30 StatsdStats stats;
31 string name = "StatsdTest";
32 ConfigKey key(0, name);
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(name, configReport.name());
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
57TEST(StatsdStatsTest, TestInvalidConfigAdd) {
58 StatsdStats stats;
59 string name = "StatsdTest";
60 ConfigKey key(0, name);
61 const int metricsCount = 10;
62 const int conditionsCount = 20;
63 const int matchersCount = 30;
64 const int alertsCount = 10;
65 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount,
66 false /*bad config*/);
67 vector<uint8_t> output;
68 stats.dumpStats(&output, false);
69
70 StatsdStatsReport report;
71 bool good = report.ParseFromArray(&output[0], output.size());
72 EXPECT_TRUE(good);
73 EXPECT_EQ(1, report.config_stats_size());
74 const auto& configReport = report.config_stats(0);
75 // The invalid config should be put into icebox with a deletion time.
76 EXPECT_TRUE(configReport.has_deletion_time_sec());
Yao Chenb3561512017-11-21 18:07:17 -080077}
78
79TEST(StatsdStatsTest, TestConfigRemove) {
Yao Chen69f1baf2017-11-27 17:25:36 -080080 StatsdStats stats;
81 string name = "StatsdTest";
82 ConfigKey key(0, name);
83 const int metricsCount = 10;
84 const int conditionsCount = 20;
85 const int matchersCount = 30;
86 const int alertsCount = 10;
87 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, true);
88 vector<uint8_t> output;
89 stats.dumpStats(&output, false);
90 StatsdStatsReport report;
91 bool good = report.ParseFromArray(&output[0], output.size());
92 EXPECT_TRUE(good);
93 EXPECT_EQ(1, report.config_stats_size());
94 const auto& configReport = report.config_stats(0);
95 EXPECT_FALSE(configReport.has_deletion_time_sec());
96
97 stats.noteConfigRemoved(key);
98 stats.dumpStats(&output, false);
99 good = report.ParseFromArray(&output[0], output.size());
100 EXPECT_TRUE(good);
101 EXPECT_EQ(1, report.config_stats_size());
102 const auto& configReport2 = report.config_stats(0);
103 EXPECT_TRUE(configReport2.has_deletion_time_sec());
Yao Chenb3561512017-11-21 18:07:17 -0800104}
105
Yao Chen69f1baf2017-11-27 17:25:36 -0800106TEST(StatsdStatsTest, TestSubStats) {
107 StatsdStats stats;
108 ConfigKey key(0, "test");
109 stats.noteConfigReceived(key, 2, 3, 4, 5, true);
Yao Chenb3561512017-11-21 18:07:17 -0800110
Yao Chen69f1baf2017-11-27 17:25:36 -0800111 stats.noteMatcherMatched(key, "matcher1");
112 stats.noteMatcherMatched(key, "matcher1");
113 stats.noteMatcherMatched(key, "matcher2");
114
115 stats.noteConditionDimensionSize(key, "condition1", 250);
116 stats.noteConditionDimensionSize(key, "condition1", 240);
117
118 stats.noteMetricDimensionSize(key, "metric1", 201);
119 stats.noteMetricDimensionSize(key, "metric1", 202);
120
121 // broadcast-> 2
122 stats.noteBroadcastSent(key);
123 stats.noteBroadcastSent(key);
124
125 // data drop -> 1
126 stats.noteDataDropped(key);
127
128 // dump report -> 3
129 stats.noteMetricsReportSent(key);
130 stats.noteMetricsReportSent(key);
131 stats.noteMetricsReportSent(key);
132
133 vector<uint8_t> output;
134 stats.dumpStats(&output, true); // Dump and reset stats
135 StatsdStatsReport report;
136 bool good = report.ParseFromArray(&output[0], output.size());
137 EXPECT_TRUE(good);
138 EXPECT_EQ(1, report.config_stats_size());
139 const auto& configReport = report.config_stats(0);
140 EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
141 EXPECT_EQ(1, configReport.data_drop_time_sec_size());
142 EXPECT_EQ(3, configReport.dump_report_time_sec_size());
143
144 EXPECT_EQ(2, configReport.matcher_stats_size());
145
146 // matcher1 is the first in the list
147 if (!configReport.matcher_stats(0).name().compare("matcher1")) {
148 EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
149 EXPECT_EQ(1, configReport.matcher_stats(1).matched_times());
150 EXPECT_EQ("matcher2", configReport.matcher_stats(1).name());
151 } else {
152 // matcher1 is the second in the list.
153 EXPECT_EQ(1, configReport.matcher_stats(0).matched_times());
154 EXPECT_EQ("matcher2", configReport.matcher_stats(0).name());
155
156 EXPECT_EQ(2, configReport.matcher_stats(1).matched_times());
157 EXPECT_EQ("matcher1", configReport.matcher_stats(1).name());
158 }
159
160 EXPECT_EQ(1, configReport.condition_stats_size());
161 EXPECT_EQ("condition1", configReport.condition_stats(0).name());
162 EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
163
164 EXPECT_EQ(1, configReport.metric_stats_size());
165 EXPECT_EQ("metric1", configReport.metric_stats(0).name());
166 EXPECT_EQ(202, configReport.metric_stats(0).max_tuple_counts());
167
168 // after resetting the stats, some new events come
169 stats.noteMatcherMatched(key, "matcher99");
170 stats.noteConditionDimensionSize(key, "condition99", 300);
171 stats.noteMetricDimensionSize(key, "metric99", 270);
172
173 // now the config stats should only contain the stats about the new event.
174 stats.dumpStats(&output, false);
175 good = report.ParseFromArray(&output[0], output.size());
176 EXPECT_TRUE(good);
177 EXPECT_EQ(1, report.config_stats_size());
178 const auto& configReport2 = report.config_stats(0);
179 EXPECT_EQ(1, configReport2.matcher_stats_size());
180 EXPECT_EQ("matcher99", configReport2.matcher_stats(0).name());
181 EXPECT_EQ(1, configReport2.matcher_stats(0).matched_times());
182
183 EXPECT_EQ(1, configReport2.condition_stats_size());
184 EXPECT_EQ("condition99", configReport2.condition_stats(0).name());
185 EXPECT_EQ(300, configReport2.condition_stats(0).max_tuple_counts());
186
187 EXPECT_EQ(1, configReport2.metric_stats_size());
188 EXPECT_EQ("metric99", configReport2.metric_stats(0).name());
189 EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
Yao Chenb3561512017-11-21 18:07:17 -0800190}
191
192TEST(StatsdStatsTest, TestAtomLog) {
Yao Chen69f1baf2017-11-27 17:25:36 -0800193 StatsdStats stats;
194 time_t now = time(nullptr);
195 // old event, we get it from the stats buffer. should be ignored.
196 stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, 1000);
197
198 stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 1);
199 stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 2);
200 stats.noteAtomLogged(android::util::DROPBOX_ERROR_CHANGED, now + 3);
201 // pulled event, should ignore
202 stats.noteAtomLogged(android::util::WIFI_BYTES_TRANSFERRED, now + 4);
203
204 vector<uint8_t> output;
205 stats.dumpStats(&output, false);
206 StatsdStatsReport report;
207 bool good = report.ParseFromArray(&output[0], output.size());
208 EXPECT_TRUE(good);
209
210 EXPECT_EQ(2, report.atom_stats_size());
211 bool sensorAtomGood = false;
212 bool dropboxAtomGood = false;
213
214 for (const auto& atomStats : report.atom_stats()) {
215 if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 2) {
216 sensorAtomGood = true;
217 }
218 if (atomStats.tag() == android::util::DROPBOX_ERROR_CHANGED && atomStats.count() == 1) {
219 dropboxAtomGood = true;
220 }
221 }
222
223 EXPECT_TRUE(dropboxAtomGood);
224 EXPECT_TRUE(sensorAtomGood);
Yao Chenb3561512017-11-21 18:07:17 -0800225}
226
Yao Chen0fac5b12017-11-28 16:07:02 -0800227TEST(StatsdStatsTest, TestTimestampThreshold) {
228 StatsdStats stats;
229 vector<int32_t> timestamps;
230 for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
231 timestamps.push_back(i);
232 }
233 ConfigKey key(0, "test");
234 stats.noteConfigReceived(key, 2, 3, 4, 5, true);
235
236 for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
237 stats.noteDataDropped(key, timestamps[i]);
238 stats.noteBroadcastSent(key, timestamps[i]);
239 stats.noteMetricsReportSent(key, timestamps[i]);
240 }
241
242 int32_t newTimestamp = 10000;
243
244 // now it should trigger removing oldest timestamp
245 stats.noteDataDropped(key, 10000);
246 stats.noteBroadcastSent(key, 10000);
247 stats.noteMetricsReportSent(key, 10000);
248
249 EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
250 const auto& configStats = stats.mConfigStats[key];
251
252 int maxCount = StatsdStats::kMaxTimestampCount;
253 EXPECT_EQ(maxCount, configStats.broadcast_sent_time_sec_size());
254 EXPECT_EQ(maxCount, configStats.data_drop_time_sec_size());
255 EXPECT_EQ(maxCount, configStats.dump_report_time_sec_size());
256
257 // the oldest timestamp is the second timestamp in history
258 EXPECT_EQ(1, configStats.broadcast_sent_time_sec(0));
259 EXPECT_EQ(1, configStats.broadcast_sent_time_sec(0));
260 EXPECT_EQ(1, configStats.broadcast_sent_time_sec(0));
261
262 // the last timestamp is the newest timestamp.
263 EXPECT_EQ(newTimestamp,
264 configStats.broadcast_sent_time_sec(StatsdStats::kMaxTimestampCount - 1));
265 EXPECT_EQ(newTimestamp, configStats.data_drop_time_sec(StatsdStats::kMaxTimestampCount - 1));
266 EXPECT_EQ(newTimestamp, configStats.dump_report_time_sec(StatsdStats::kMaxTimestampCount - 1));
267}
268
Yao Chenb3561512017-11-21 18:07:17 -0800269} // namespace statsd
270} // namespace os
271} // namespace android
272#else
273GTEST_LOG_(INFO) << "This test does nothing.\n";
274#endif