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
17 #include <gtest/gtest.h>
18
19 #include <vector>
20
21 #include "src/metrics/parsing_utils/metrics_manager_util.h"
22 #include "statslog_statsdtest.h"
23 #include "tests/statsd_test_util.h"
24
25 #ifdef __ANDROID__
26
27 namespace android {
28 namespace os {
29 namespace statsd {
30
31 using std::vector;
32
TEST(StatsdStatsTest,TestValidConfigAdd)33 TEST(StatsdStatsTest, TestValidConfigAdd) {
34 StatsdStats stats;
35 ConfigKey key(0, 12345);
36 const int metricsCount = 10;
37 const int conditionsCount = 20;
38 const int matchersCount = 30;
39 const int alertsCount = 10;
40 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
41 nullopt /*valid config*/);
42 vector<uint8_t> output;
43 stats.dumpStats(&output, false /*reset stats*/);
44
45 StatsdStatsReport report;
46 bool good = report.ParseFromArray(&output[0], output.size());
47 EXPECT_TRUE(good);
48 ASSERT_EQ(1, report.config_stats_size());
49 const auto& configReport = report.config_stats(0);
50 EXPECT_EQ(0, configReport.uid());
51 EXPECT_EQ(12345, configReport.id());
52 EXPECT_EQ(metricsCount, configReport.metric_count());
53 EXPECT_EQ(conditionsCount, configReport.condition_count());
54 EXPECT_EQ(matchersCount, configReport.matcher_count());
55 EXPECT_EQ(alertsCount, configReport.alert_count());
56 EXPECT_EQ(true, configReport.is_valid());
57 EXPECT_FALSE(configReport.has_invalid_config_reason());
58 EXPECT_FALSE(configReport.has_deletion_time_sec());
59 }
60
TEST(StatsdStatsTest,TestInvalidConfigAdd)61 TEST(StatsdStatsTest, TestInvalidConfigAdd) {
62 StatsdStats stats;
63 ConfigKey key(0, 12345);
64 const int metricsCount = 10;
65 const int conditionsCount = 20;
66 const int matchersCount = 30;
67 const int alertsCount = 10;
68 optional<InvalidConfigReason> invalidConfigReason =
69 InvalidConfigReason(INVALID_CONFIG_REASON_UNKNOWN, 1);
70 invalidConfigReason->stateId = 2;
71 invalidConfigReason->alertId = 3;
72 invalidConfigReason->alarmId = 4;
73 invalidConfigReason->subscriptionId = 5;
74 invalidConfigReason->matcherIds.push_back(6);
75 invalidConfigReason->matcherIds.push_back(7);
76 invalidConfigReason->conditionIds.push_back(8);
77 invalidConfigReason->conditionIds.push_back(9);
78 invalidConfigReason->conditionIds.push_back(10);
79 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
80 invalidConfigReason /*bad config*/);
81 vector<uint8_t> output;
82 stats.dumpStats(&output, false);
83
84 StatsdStatsReport report;
85 bool good = report.ParseFromArray(&output[0], output.size());
86 EXPECT_TRUE(good);
87 ASSERT_EQ(1, report.config_stats_size());
88 const auto& configReport = report.config_stats(0);
89 // The invalid config should be put into icebox with a deletion time.
90 EXPECT_TRUE(configReport.has_deletion_time_sec());
91 EXPECT_TRUE(configReport.has_invalid_config_reason());
92 EXPECT_EQ(configReport.invalid_config_reason().reason(), INVALID_CONFIG_REASON_UNKNOWN);
93 EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
94 EXPECT_EQ(configReport.invalid_config_reason().state_id(), 2);
95 EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 3);
96 EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 4);
97 EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 5);
98 EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 2);
99 EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 6);
100 EXPECT_EQ(configReport.invalid_config_reason().matcher_id(1), 7);
101 EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 3);
102 EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 8);
103 EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 9);
104 EXPECT_EQ(configReport.invalid_config_reason().condition_id(2), 10);
105 }
106
TEST(StatsdStatsTest,TestInvalidConfigMissingMetricId)107 TEST(StatsdStatsTest, TestInvalidConfigMissingMetricId) {
108 StatsdStats stats;
109 ConfigKey key(0, 12345);
110 const int metricsCount = 10;
111 const int conditionsCount = 20;
112 const int matchersCount = 30;
113 const int alertsCount = 10;
114 optional<InvalidConfigReason> invalidConfigReason =
115 InvalidConfigReason(INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
116 invalidConfigReason->stateId = 1;
117 invalidConfigReason->alertId = 2;
118 invalidConfigReason->alarmId = 3;
119 invalidConfigReason->subscriptionId = 4;
120 invalidConfigReason->matcherIds.push_back(5);
121 invalidConfigReason->conditionIds.push_back(6);
122 invalidConfigReason->conditionIds.push_back(7);
123 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
124 invalidConfigReason /*bad config*/);
125 vector<uint8_t> output;
126 stats.dumpStats(&output, false);
127
128 StatsdStatsReport report;
129 bool good = report.ParseFromArray(&output[0], output.size());
130 EXPECT_TRUE(good);
131 ASSERT_EQ(1, report.config_stats_size());
132 const auto& configReport = report.config_stats(0);
133 // The invalid config should be put into icebox with a deletion time.
134 EXPECT_TRUE(configReport.has_deletion_time_sec());
135 EXPECT_TRUE(configReport.has_invalid_config_reason());
136 EXPECT_EQ(configReport.invalid_config_reason().reason(),
137 INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
138 EXPECT_FALSE(configReport.invalid_config_reason().has_metric_id());
139 EXPECT_EQ(configReport.invalid_config_reason().state_id(), 1);
140 EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 2);
141 EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 3);
142 EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 4);
143 EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 1);
144 EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 5);
145 EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 2);
146 EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 6);
147 EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 7);
148 }
149
TEST(StatsdStatsTest,TestInvalidConfigOnlyMetricId)150 TEST(StatsdStatsTest, TestInvalidConfigOnlyMetricId) {
151 StatsdStats stats;
152 ConfigKey key(0, 12345);
153 const int metricsCount = 10;
154 const int conditionsCount = 20;
155 const int matchersCount = 30;
156 const int alertsCount = 10;
157 optional<InvalidConfigReason> invalidConfigReason =
158 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG, 1);
159 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
160 invalidConfigReason /*bad config*/);
161 vector<uint8_t> output;
162 stats.dumpStats(&output, false);
163
164 StatsdStatsReport report;
165 bool good = report.ParseFromArray(&output[0], output.size());
166 EXPECT_TRUE(good);
167 ASSERT_EQ(1, report.config_stats_size());
168 const auto& configReport = report.config_stats(0);
169 // The invalid config should be put into icebox with a deletion time.
170 EXPECT_TRUE(configReport.has_deletion_time_sec());
171 EXPECT_TRUE(configReport.has_invalid_config_reason());
172 EXPECT_EQ(configReport.invalid_config_reason().reason(),
173 INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG);
174 EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
175 EXPECT_FALSE(configReport.invalid_config_reason().has_state_id());
176 EXPECT_FALSE(configReport.invalid_config_reason().has_alert_id());
177 EXPECT_FALSE(configReport.invalid_config_reason().has_alarm_id());
178 EXPECT_FALSE(configReport.invalid_config_reason().has_subscription_id());
179 EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 0);
180 EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 0);
181 }
182
TEST(StatsdStatsTest,TestConfigRemove)183 TEST(StatsdStatsTest, TestConfigRemove) {
184 StatsdStats stats;
185 ConfigKey key(0, 12345);
186 const int metricsCount = 10;
187 const int conditionsCount = 20;
188 const int matchersCount = 30;
189 const int alertsCount = 10;
190 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
191 nullopt);
192 vector<uint8_t> output;
193 stats.dumpStats(&output, false);
194 StatsdStatsReport report;
195 bool good = report.ParseFromArray(&output[0], output.size());
196 EXPECT_TRUE(good);
197 ASSERT_EQ(1, report.config_stats_size());
198 const auto& configReport = report.config_stats(0);
199 EXPECT_FALSE(configReport.has_deletion_time_sec());
200
201 stats.noteConfigRemoved(key);
202 stats.dumpStats(&output, false);
203 good = report.ParseFromArray(&output[0], output.size());
204 EXPECT_TRUE(good);
205 ASSERT_EQ(1, report.config_stats_size());
206 const auto& configReport2 = report.config_stats(0);
207 EXPECT_TRUE(configReport2.has_deletion_time_sec());
208 }
209
TEST(StatsdStatsTest,TestSubStats)210 TEST(StatsdStatsTest, TestSubStats) {
211 StatsdStats stats;
212 ConfigKey key(0, 12345);
213 stats.noteConfigReceived(key, 2, 3, 4, 5, {std::make_pair(123, 456)}, nullopt);
214
215 stats.noteMatcherMatched(key, StringToId("matcher1"));
216 stats.noteMatcherMatched(key, StringToId("matcher1"));
217 stats.noteMatcherMatched(key, StringToId("matcher2"));
218
219 stats.noteConditionDimensionSize(key, StringToId("condition1"), 250);
220 stats.noteConditionDimensionSize(key, StringToId("condition1"), 240);
221
222 stats.noteMetricDimensionSize(key, StringToId("metric1"), 201);
223 stats.noteMetricDimensionSize(key, StringToId("metric1"), 202);
224
225 stats.noteAnomalyDeclared(key, StringToId("alert1"));
226 stats.noteAnomalyDeclared(key, StringToId("alert1"));
227 stats.noteAnomalyDeclared(key, StringToId("alert2"));
228
229 // broadcast-> 2
230 stats.noteBroadcastSent(key);
231 stats.noteBroadcastSent(key);
232
233 // data drop -> 1
234 stats.noteDataDropped(key, 123);
235
236 // dump report -> 3
237 stats.noteMetricsReportSent(key, 0);
238 stats.noteMetricsReportSent(key, 0);
239 stats.noteMetricsReportSent(key, 0);
240
241 // activation_time_sec -> 2
242 stats.noteActiveStatusChanged(key, true);
243 stats.noteActiveStatusChanged(key, true);
244
245 // deactivation_time_sec -> 1
246 stats.noteActiveStatusChanged(key, false);
247
248 vector<uint8_t> output;
249 stats.dumpStats(&output, true); // Dump and reset stats
250 StatsdStatsReport report;
251 bool good = report.ParseFromArray(&output[0], output.size());
252 EXPECT_TRUE(good);
253 ASSERT_EQ(1, report.config_stats_size());
254 const auto& configReport = report.config_stats(0);
255 ASSERT_EQ(2, configReport.broadcast_sent_time_sec_size());
256 ASSERT_EQ(1, configReport.data_drop_time_sec_size());
257 ASSERT_EQ(1, configReport.data_drop_bytes_size());
258 EXPECT_EQ(123, configReport.data_drop_bytes(0));
259 ASSERT_EQ(3, configReport.dump_report_time_sec_size());
260 ASSERT_EQ(3, configReport.dump_report_data_size_size());
261 ASSERT_EQ(2, configReport.activation_time_sec_size());
262 ASSERT_EQ(1, configReport.deactivation_time_sec_size());
263 ASSERT_EQ(1, configReport.annotation_size());
264 EXPECT_EQ(123, configReport.annotation(0).field_int64());
265 EXPECT_EQ(456, configReport.annotation(0).field_int32());
266
267 ASSERT_EQ(2, configReport.matcher_stats_size());
268 // matcher1 is the first in the list
269 if (configReport.matcher_stats(0).id() == StringToId("matcher1")) {
270 EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
271 EXPECT_EQ(1, configReport.matcher_stats(1).matched_times());
272 EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(1).id());
273 } else {
274 // matcher1 is the second in the list.
275 EXPECT_EQ(1, configReport.matcher_stats(0).matched_times());
276 EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(0).id());
277
278 EXPECT_EQ(2, configReport.matcher_stats(1).matched_times());
279 EXPECT_EQ(StringToId("matcher1"), configReport.matcher_stats(1).id());
280 }
281
282 ASSERT_EQ(2, configReport.alert_stats_size());
283 bool alert1first = configReport.alert_stats(0).id() == StringToId("alert1");
284 EXPECT_EQ(StringToId("alert1"), configReport.alert_stats(alert1first ? 0 : 1).id());
285 EXPECT_EQ(2, configReport.alert_stats(alert1first ? 0 : 1).alerted_times());
286 EXPECT_EQ(StringToId("alert2"), configReport.alert_stats(alert1first ? 1 : 0).id());
287 EXPECT_EQ(1, configReport.alert_stats(alert1first ? 1 : 0).alerted_times());
288
289 ASSERT_EQ(1, configReport.condition_stats_size());
290 EXPECT_EQ(StringToId("condition1"), configReport.condition_stats(0).id());
291 EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
292
293 ASSERT_EQ(1, configReport.metric_stats_size());
294 EXPECT_EQ(StringToId("metric1"), configReport.metric_stats(0).id());
295 EXPECT_EQ(202, configReport.metric_stats(0).max_tuple_counts());
296
297 // after resetting the stats, some new events come
298 stats.noteMatcherMatched(key, StringToId("matcher99"));
299 stats.noteConditionDimensionSize(key, StringToId("condition99"), 300);
300 stats.noteMetricDimensionSize(key, StringToId("metric99tion99"), 270);
301 stats.noteAnomalyDeclared(key, StringToId("alert99"));
302
303 // now the config stats should only contain the stats about the new event.
304 stats.dumpStats(&output, false);
305 good = report.ParseFromArray(&output[0], output.size());
306 EXPECT_TRUE(good);
307 ASSERT_EQ(1, report.config_stats_size());
308 const auto& configReport2 = report.config_stats(0);
309 ASSERT_EQ(1, configReport2.matcher_stats_size());
310 EXPECT_EQ(StringToId("matcher99"), configReport2.matcher_stats(0).id());
311 EXPECT_EQ(1, configReport2.matcher_stats(0).matched_times());
312
313 ASSERT_EQ(1, configReport2.condition_stats_size());
314 EXPECT_EQ(StringToId("condition99"), configReport2.condition_stats(0).id());
315 EXPECT_EQ(300, configReport2.condition_stats(0).max_tuple_counts());
316
317 ASSERT_EQ(1, configReport2.metric_stats_size());
318 EXPECT_EQ(StringToId("metric99tion99"), configReport2.metric_stats(0).id());
319 EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
320
321 ASSERT_EQ(1, configReport2.alert_stats_size());
322 EXPECT_EQ(StringToId("alert99"), configReport2.alert_stats(0).id());
323 EXPECT_EQ(1, configReport2.alert_stats(0).alerted_times());
324 }
325
TEST(StatsdStatsTest,TestAtomLog)326 TEST(StatsdStatsTest, TestAtomLog) {
327 StatsdStats stats;
328 time_t now = time(nullptr);
329 // old event, we get it from the stats buffer. should be ignored.
330 stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, 1000, false);
331
332 stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 1, false);
333 stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 2, false);
334 stats.noteAtomLogged(util::APP_CRASH_OCCURRED, now + 3, false);
335
336 vector<uint8_t> output;
337 stats.dumpStats(&output, false);
338 StatsdStatsReport report;
339 bool good = report.ParseFromArray(&output[0], output.size());
340 EXPECT_TRUE(good);
341
342 ASSERT_EQ(2, report.atom_stats_size());
343 bool sensorAtomGood = false;
344 bool dropboxAtomGood = false;
345
346 for (const auto& atomStats : report.atom_stats()) {
347 if (atomStats.tag() == util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
348 sensorAtomGood = true;
349 }
350 if (atomStats.tag() == util::APP_CRASH_OCCURRED && atomStats.count() == 1) {
351 dropboxAtomGood = true;
352 }
353 EXPECT_FALSE(atomStats.has_dropped_count());
354 EXPECT_FALSE(atomStats.has_skip_count());
355 }
356
357 EXPECT_TRUE(dropboxAtomGood);
358 EXPECT_TRUE(sensorAtomGood);
359 }
360
TEST(StatsdStatsTest,TestNonPlatformAtomLog)361 TEST(StatsdStatsTest, TestNonPlatformAtomLog) {
362 StatsdStats stats;
363 time_t now = time(nullptr);
364 int newAtom1 = StatsdStats::kMaxPushedAtomId + 1;
365 int newAtom2 = StatsdStats::kMaxPushedAtomId + 2;
366
367 stats.noteAtomLogged(newAtom1, now + 1, false);
368 stats.noteAtomLogged(newAtom1, now + 2, false);
369 stats.noteAtomLogged(newAtom2, now + 3, false);
370
371 vector<uint8_t> output;
372 stats.dumpStats(&output, false);
373 StatsdStatsReport report;
374 bool good = report.ParseFromArray(&output[0], output.size());
375 EXPECT_TRUE(good);
376
377 ASSERT_EQ(2, report.atom_stats_size());
378 bool newAtom1Good = false;
379 bool newAtom2Good = false;
380
381 for (const auto& atomStats : report.atom_stats()) {
382 if (atomStats.tag() == newAtom1 && atomStats.count() == 2) {
383 newAtom1Good = true;
384 }
385 if (atomStats.tag() == newAtom2 && atomStats.count() == 1) {
386 newAtom2Good = true;
387 }
388 EXPECT_FALSE(atomStats.has_dropped_count());
389 EXPECT_FALSE(atomStats.has_skip_count());
390 }
391
392 EXPECT_TRUE(newAtom1Good);
393 EXPECT_TRUE(newAtom2Good);
394 }
395
TEST(StatsdStatsTest,TestPullAtomStats)396 TEST(StatsdStatsTest, TestPullAtomStats) {
397 StatsdStats stats;
398
399 stats.updateMinPullIntervalSec(util::DISK_SPACE, 3333L);
400 stats.updateMinPullIntervalSec(util::DISK_SPACE, 2222L);
401 stats.updateMinPullIntervalSec(util::DISK_SPACE, 4444L);
402
403 stats.notePull(util::DISK_SPACE);
404 stats.notePullTime(util::DISK_SPACE, 1111L);
405 stats.notePullDelay(util::DISK_SPACE, 1111L);
406 stats.notePull(util::DISK_SPACE);
407 stats.notePullTime(util::DISK_SPACE, 3333L);
408 stats.notePullDelay(util::DISK_SPACE, 3335L);
409 stats.notePull(util::DISK_SPACE);
410 stats.notePullFromCache(util::DISK_SPACE);
411 stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
412 stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, false);
413 stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
414 stats.notePullBinderCallFailed(util::DISK_SPACE);
415 stats.notePullUidProviderNotFound(util::DISK_SPACE);
416 stats.notePullerNotFound(util::DISK_SPACE);
417 stats.notePullerNotFound(util::DISK_SPACE);
418 stats.notePullTimeout(util::DISK_SPACE, 3000L, 6000L);
419 stats.notePullTimeout(util::DISK_SPACE, 4000L, 7000L);
420
421 vector<uint8_t> output;
422 stats.dumpStats(&output, false);
423 StatsdStatsReport report;
424 bool good = report.ParseFromArray(&output[0], output.size());
425 EXPECT_TRUE(good);
426
427 ASSERT_EQ(1, report.pulled_atom_stats_size());
428
429 EXPECT_EQ(util::DISK_SPACE, report.pulled_atom_stats(0).atom_id());
430 EXPECT_EQ(3, report.pulled_atom_stats(0).total_pull());
431 EXPECT_EQ(1, report.pulled_atom_stats(0).total_pull_from_cache());
432 EXPECT_EQ(2222L, report.pulled_atom_stats(0).min_pull_interval_sec());
433 EXPECT_EQ(2222L, report.pulled_atom_stats(0).average_pull_time_nanos());
434 EXPECT_EQ(3333L, report.pulled_atom_stats(0).max_pull_time_nanos());
435 EXPECT_EQ(2223L, report.pulled_atom_stats(0).average_pull_delay_nanos());
436 EXPECT_EQ(3335L, report.pulled_atom_stats(0).max_pull_delay_nanos());
437 EXPECT_EQ(2L, report.pulled_atom_stats(0).registered_count());
438 EXPECT_EQ(1L, report.pulled_atom_stats(0).unregistered_count());
439 EXPECT_EQ(1L, report.pulled_atom_stats(0).binder_call_failed());
440 EXPECT_EQ(1L, report.pulled_atom_stats(0).failed_uid_provider_not_found());
441 EXPECT_EQ(2L, report.pulled_atom_stats(0).puller_not_found());
442 ASSERT_EQ(2, report.pulled_atom_stats(0).pull_atom_metadata_size());
443 EXPECT_EQ(3000L, report.pulled_atom_stats(0).pull_atom_metadata(0).pull_timeout_uptime_millis());
444 EXPECT_EQ(4000L, report.pulled_atom_stats(0).pull_atom_metadata(1).pull_timeout_uptime_millis());
445 EXPECT_EQ(6000L, report.pulled_atom_stats(0).pull_atom_metadata(0)
446 .pull_timeout_elapsed_millis());
447 EXPECT_EQ(7000L, report.pulled_atom_stats(0).pull_atom_metadata(1)
448 .pull_timeout_elapsed_millis());
449 }
450
TEST(StatsdStatsTest,TestAtomMetricsStats)451 TEST(StatsdStatsTest, TestAtomMetricsStats) {
452 StatsdStats stats;
453 time_t now = time(nullptr);
454 // old event, we get it from the stats buffer. should be ignored.
455 stats.noteBucketDropped(10000000000LL);
456
457 stats.noteBucketBoundaryDelayNs(10000000000LL, -1L);
458 stats.noteBucketBoundaryDelayNs(10000000000LL, -10L);
459 stats.noteBucketBoundaryDelayNs(10000000000LL, 2L);
460
461 stats.noteBucketBoundaryDelayNs(10000000001LL, 1L);
462
463 vector<uint8_t> output;
464 stats.dumpStats(&output, false);
465 StatsdStatsReport report;
466 bool good = report.ParseFromArray(&output[0], output.size());
467 EXPECT_TRUE(good);
468
469 ASSERT_EQ(2, report.atom_metric_stats().size());
470
471 auto atomStats = report.atom_metric_stats(0);
472 EXPECT_EQ(10000000000LL, atomStats.metric_id());
473 EXPECT_EQ(1L, atomStats.bucket_dropped());
474 EXPECT_EQ(-10L, atomStats.min_bucket_boundary_delay_ns());
475 EXPECT_EQ(2L, atomStats.max_bucket_boundary_delay_ns());
476
477 auto atomStats2 = report.atom_metric_stats(1);
478 EXPECT_EQ(10000000001LL, atomStats2.metric_id());
479 EXPECT_EQ(0L, atomStats2.bucket_dropped());
480 EXPECT_EQ(0L, atomStats2.min_bucket_boundary_delay_ns());
481 EXPECT_EQ(1L, atomStats2.max_bucket_boundary_delay_ns());
482 }
483
TEST(StatsdStatsTest,TestRestrictedMetricsStats)484 TEST(StatsdStatsTest, TestRestrictedMetricsStats) {
485 StatsdStats stats;
486 const int64_t metricId = -1234556L;
487 ConfigKey key(0, 12345);
488 stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
489 stats.noteRestrictedMetricInsertError(key, metricId);
490 stats.noteRestrictedMetricTableCreationError(key, metricId);
491 stats.noteRestrictedMetricTableDeletionError(key, metricId);
492 stats.noteDeviceInfoTableCreationFailed(key);
493 stats.noteRestrictedMetricFlushLatency(key, metricId, 3000);
494 stats.noteRestrictedMetricFlushLatency(key, metricId, 3001);
495 stats.noteRestrictedMetricCategoryChanged(key, metricId);
496 stats.noteRestrictedConfigFlushLatency(key, 4000);
497 ConfigKey configKeyWithoutError(0, 666);
498 stats.noteConfigReceived(configKeyWithoutError, 2, 3, 4, 5, {}, nullopt);
499 stats.noteDbCorrupted(key);
500 stats.noteDbCorrupted(key);
501 stats.noteRestrictedConfigDbSize(key, 999, 111);
502
503 vector<uint8_t> output;
504 stats.dumpStats(&output, false);
505 StatsdStatsReport report;
506 bool good = report.ParseFromArray(&output[0], output.size());
507 EXPECT_TRUE(good);
508
509 ASSERT_EQ(2, report.config_stats().size());
510 ASSERT_EQ(0, report.config_stats(0).restricted_metric_stats().size());
511 ASSERT_EQ(1, report.config_stats(1).restricted_metric_stats().size());
512 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).insert_error());
513 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).table_creation_error());
514 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).table_deletion_error());
515 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).category_changed_count());
516 ASSERT_EQ(2, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns().size());
517 EXPECT_EQ(3000, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns(0));
518 EXPECT_EQ(3001, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns(1));
519 ASSERT_EQ(1, report.config_stats(1).restricted_db_size_time_sec().size());
520 EXPECT_EQ(999, report.config_stats(1).restricted_db_size_time_sec(0));
521 ASSERT_EQ(1, report.config_stats(1).restricted_db_size_bytes().size());
522 EXPECT_EQ(111, report.config_stats(1).restricted_db_size_bytes(0));
523 ASSERT_EQ(1, report.config_stats(1).restricted_flush_latency().size());
524 EXPECT_EQ(4000, report.config_stats(1).restricted_flush_latency(0));
525 EXPECT_TRUE(report.config_stats(1).device_info_table_creation_failed());
526 EXPECT_EQ(metricId, report.config_stats(1).restricted_metric_stats(0).restricted_metric_id());
527 EXPECT_EQ(2, report.config_stats(1).restricted_db_corrupted_count());
528 }
529
TEST(StatsdStatsTest,TestRestrictedMetricsQueryStats)530 TEST(StatsdStatsTest, TestRestrictedMetricsQueryStats) {
531 StatsdStats stats;
532 const int32_t callingUid = 100;
533 ConfigKey configKey(0, 12345);
534 const string configPackage = "com.google.android.gm";
535 int64_t beforeNoteMetricSucceed = getWallClockNs();
536 stats.noteQueryRestrictedMetricSucceed(configKey.GetId(), configPackage, configKey.GetUid(),
537 callingUid, /*queryLatencyNs=*/5 * NS_PER_SEC);
538 int64_t afterNoteMetricSucceed = getWallClockNs();
539
540 const int64_t configIdWithError = 111;
541 stats.noteQueryRestrictedMetricFailed(configIdWithError, configPackage, std::nullopt,
542 callingUid, InvalidQueryReason(AMBIGUOUS_CONFIG_KEY));
543 stats.noteQueryRestrictedMetricFailed(configIdWithError, configPackage, std::nullopt,
544 callingUid, InvalidQueryReason(AMBIGUOUS_CONFIG_KEY),
545 "error_message");
546
547 vector<uint8_t> output;
548 stats.dumpStats(&output, false);
549 StatsdStatsReport report;
550 bool good = report.ParseFromArray(&output[0], output.size());
551 EXPECT_TRUE(good);
552
553 ASSERT_EQ(3, report.restricted_metric_query_stats().size());
554 EXPECT_EQ(configKey.GetId(), report.restricted_metric_query_stats(0).config_id());
555 EXPECT_EQ(configKey.GetUid(), report.restricted_metric_query_stats(0).config_uid());
556 EXPECT_EQ(callingUid, report.restricted_metric_query_stats(0).calling_uid());
557 EXPECT_EQ(configPackage, report.restricted_metric_query_stats(0).config_package());
558 EXPECT_FALSE(report.restricted_metric_query_stats(0).has_query_error());
559 EXPECT_LT(beforeNoteMetricSucceed,
560 report.restricted_metric_query_stats(0).query_wall_time_ns());
561 EXPECT_GT(afterNoteMetricSucceed, report.restricted_metric_query_stats(0).query_wall_time_ns());
562 EXPECT_EQ(5 * NS_PER_SEC, report.restricted_metric_query_stats(0).query_latency_ns());
563 EXPECT_EQ(configIdWithError, report.restricted_metric_query_stats(1).config_id());
564 EXPECT_EQ(AMBIGUOUS_CONFIG_KEY, report.restricted_metric_query_stats(1).invalid_query_reason());
565 EXPECT_EQ(false, report.restricted_metric_query_stats(1).has_config_uid());
566 EXPECT_FALSE(report.restricted_metric_query_stats(1).has_query_error());
567 EXPECT_FALSE(report.restricted_metric_query_stats(1).has_query_latency_ns());
568 EXPECT_EQ("error_message", report.restricted_metric_query_stats(2).query_error());
569 EXPECT_FALSE(report.restricted_metric_query_stats(2).has_query_latency_ns());
570 EXPECT_NE(report.restricted_metric_query_stats(1).query_wall_time_ns(),
571 report.restricted_metric_query_stats(0).query_wall_time_ns());
572 }
573
TEST(StatsdStatsTest,TestAnomalyMonitor)574 TEST(StatsdStatsTest, TestAnomalyMonitor) {
575 StatsdStats stats;
576 stats.noteRegisteredAnomalyAlarmChanged();
577 stats.noteRegisteredAnomalyAlarmChanged();
578
579 vector<uint8_t> output;
580 stats.dumpStats(&output, false);
581 StatsdStatsReport report;
582 bool good = report.ParseFromArray(&output[0], output.size());
583 EXPECT_TRUE(good);
584
585 EXPECT_EQ(2, report.anomaly_alarm_stats().alarms_registered());
586 }
587
TEST(StatsdStatsTest,TestTimestampThreshold)588 TEST(StatsdStatsTest, TestTimestampThreshold) {
589 StatsdStats stats;
590 vector<int32_t> timestamps;
591 for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
592 timestamps.push_back(i);
593 }
594 ConfigKey key(0, 12345);
595 stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
596
597 for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
598 stats.noteDataDropped(key, timestamps[i]);
599 stats.noteBroadcastSent(key, timestamps[i]);
600 stats.noteMetricsReportSent(key, 0, timestamps[i]);
601 stats.noteActiveStatusChanged(key, true, timestamps[i]);
602 stats.noteActiveStatusChanged(key, false, timestamps[i]);
603 }
604
605 int32_t newTimestamp = 10000;
606
607 // now it should trigger removing oldest timestamp
608 stats.noteDataDropped(key, 123, 10000);
609 stats.noteBroadcastSent(key, 10000);
610 stats.noteMetricsReportSent(key, 0, 10000);
611 stats.noteActiveStatusChanged(key, true, 10000);
612 stats.noteActiveStatusChanged(key, false, 10000);
613
614 EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
615 const auto& configStats = stats.mConfigStats[key];
616
617 size_t maxCount = StatsdStats::kMaxTimestampCount;
618 ASSERT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
619 ASSERT_EQ(maxCount, configStats->data_drop_time_sec.size());
620 ASSERT_EQ(maxCount, configStats->dump_report_stats.size());
621 ASSERT_EQ(maxCount, configStats->activation_time_sec.size());
622 ASSERT_EQ(maxCount, configStats->deactivation_time_sec.size());
623
624 // the oldest timestamp is the second timestamp in history
625 EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
626 EXPECT_EQ(1, configStats->data_drop_bytes.front());
627 EXPECT_EQ(1, configStats->dump_report_stats.front().first);
628 EXPECT_EQ(1, configStats->activation_time_sec.front());
629 EXPECT_EQ(1, configStats->deactivation_time_sec.front());
630
631 // the last timestamp is the newest timestamp.
632 EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
633 EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
634 EXPECT_EQ(123, configStats->data_drop_bytes.back());
635 EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
636 EXPECT_EQ(newTimestamp, configStats->activation_time_sec.back());
637 EXPECT_EQ(newTimestamp, configStats->deactivation_time_sec.back());
638 }
639
TEST(StatsdStatsTest,TestSystemServerCrash)640 TEST(StatsdStatsTest, TestSystemServerCrash) {
641 StatsdStats stats;
642 vector<int32_t> timestamps;
643 for (int i = 0; i < StatsdStats::kMaxSystemServerRestarts; i++) {
644 timestamps.push_back(i);
645 stats.noteSystemServerRestart(timestamps[i]);
646 }
647 vector<uint8_t> output;
648 stats.dumpStats(&output, false);
649 StatsdStatsReport report;
650 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
651 const int maxCount = StatsdStats::kMaxSystemServerRestarts;
652 ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
653
654 stats.noteSystemServerRestart(StatsdStats::kMaxSystemServerRestarts + 1);
655 output.clear();
656 stats.dumpStats(&output, false);
657 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
658 ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
659 EXPECT_EQ(StatsdStats::kMaxSystemServerRestarts + 1, report.system_restart_sec(maxCount - 1));
660 }
661
TEST(StatsdStatsTest,TestActivationBroadcastGuardrailHit)662 TEST(StatsdStatsTest, TestActivationBroadcastGuardrailHit) {
663 StatsdStats stats;
664 int uid1 = 1;
665 int uid2 = 2;
666 stats.noteActivationBroadcastGuardrailHit(uid1, 10);
667 stats.noteActivationBroadcastGuardrailHit(uid1, 20);
668
669 // Test that we only keep 20 timestamps.
670 for (int i = 0; i < 100; i++) {
671 stats.noteActivationBroadcastGuardrailHit(uid2, i);
672 }
673
674 vector<uint8_t> output;
675 stats.dumpStats(&output, false);
676 StatsdStatsReport report;
677 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
678
679 ASSERT_EQ(2, report.activation_guardrail_stats_size());
680 bool uid1Good = false;
681 bool uid2Good = false;
682 for (const auto& guardrailTimes : report.activation_guardrail_stats()) {
683 if (uid1 == guardrailTimes.uid()) {
684 uid1Good = true;
685 ASSERT_EQ(2, guardrailTimes.guardrail_met_sec_size());
686 EXPECT_EQ(10, guardrailTimes.guardrail_met_sec(0));
687 EXPECT_EQ(20, guardrailTimes.guardrail_met_sec(1));
688 } else if (uid2 == guardrailTimes.uid()) {
689 int maxCount = StatsdStats::kMaxTimestampCount;
690 uid2Good = true;
691 ASSERT_EQ(maxCount, guardrailTimes.guardrail_met_sec_size());
692 for (int i = 0; i < maxCount; i++) {
693 EXPECT_EQ(100 - maxCount + i, guardrailTimes.guardrail_met_sec(i));
694 }
695 } else {
696 FAIL() << "Unexpected uid.";
697 }
698 }
699 EXPECT_TRUE(uid1Good);
700 EXPECT_TRUE(uid2Good);
701 }
702
TEST(StatsdStatsTest,TestAtomErrorStats)703 TEST(StatsdStatsTest, TestAtomErrorStats) {
704 StatsdStats stats;
705
706 int pushAtomTag = 100;
707 int pullAtomTag = 1000;
708 int numErrors = 10;
709
710 for (int i = 0; i < numErrors; i++) {
711 // We must call noteAtomLogged as well because only those pushed atoms
712 // that have been logged will have stats printed about them in the
713 // proto.
714 stats.noteAtomLogged(pushAtomTag, /*timeSec=*/0, false);
715 stats.noteAtomError(pushAtomTag, /*pull=*/false);
716
717 stats.noteAtomError(pullAtomTag, /*pull=*/true);
718 }
719
720 vector<uint8_t> output;
721 stats.dumpStats(&output, false);
722 StatsdStatsReport report;
723 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
724
725 // Check error count = numErrors for push atom
726 ASSERT_EQ(1, report.atom_stats_size());
727 const auto& pushedAtomStats = report.atom_stats(0);
728 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
729 EXPECT_EQ(numErrors, pushedAtomStats.error_count());
730 EXPECT_FALSE(pushedAtomStats.has_dropped_count());
731 EXPECT_FALSE(pushedAtomStats.has_skip_count());
732
733 // Check error count = numErrors for pull atom
734 ASSERT_EQ(1, report.pulled_atom_stats_size());
735 const auto& pulledAtomStats = report.pulled_atom_stats(0);
736 EXPECT_EQ(pullAtomTag, pulledAtomStats.atom_id());
737 EXPECT_EQ(numErrors, pulledAtomStats.atom_error_count());
738 }
739
TEST(StatsdStatsTest,TestAtomDroppedStats)740 TEST(StatsdStatsTest, TestAtomDroppedStats) {
741 StatsdStats stats;
742
743 const int pushAtomTag = 100;
744 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
745
746 const int numDropped = 10;
747 for (int i = 0; i < numDropped; i++) {
748 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, false);
749 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, false);
750 }
751
752 vector<uint8_t> output;
753 stats.dumpStats(&output, true);
754 ASSERT_EQ(0, stats.mPushedAtomDropsStats.size());
755
756 StatsdStatsReport report;
757 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
758
759 // Check dropped_count = numDropped for push atoms
760 ASSERT_EQ(2, report.atom_stats_size());
761
762 const auto& pushedAtomStats = report.atom_stats(0);
763 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
764 EXPECT_EQ(numDropped, pushedAtomStats.count());
765 EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
766 EXPECT_FALSE(pushedAtomStats.has_error_count());
767 EXPECT_FALSE(pushedAtomStats.has_skip_count());
768
769 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
770 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
771 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.count());
772 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
773 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
774 EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count());
775 }
776
TEST(StatsdStatsTest,TestAtomLoggedAndDroppedStats)777 TEST(StatsdStatsTest, TestAtomLoggedAndDroppedStats) {
778 StatsdStats stats;
779
780 const int pushAtomTag = 100;
781 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
782
783 const int numLogged = 10;
784 for (int i = 0; i < numLogged; i++) {
785 stats.noteAtomLogged(pushAtomTag, /*timeSec*/ 0, false);
786 stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec*/ 0, false);
787 }
788
789 const int numDropped = 10;
790 for (int i = 0; i < numDropped; i++) {
791 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, false);
792 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, false);
793 }
794
795 vector<uint8_t> output;
796 stats.dumpStats(&output, false);
797 StatsdStatsReport report;
798 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
799
800 // Check dropped_count = numDropped for push atoms
801 ASSERT_EQ(2, report.atom_stats_size());
802
803 const auto& pushedAtomStats = report.atom_stats(0);
804 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
805 EXPECT_EQ(numLogged + numDropped, pushedAtomStats.count());
806 EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
807 EXPECT_FALSE(pushedAtomStats.has_error_count());
808 EXPECT_FALSE(pushedAtomStats.has_skip_count());
809
810 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
811 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
812 EXPECT_EQ(numLogged + numDropped, nonPlatformPushedAtomStats.count());
813 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
814 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
815 EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count());
816 }
817
TEST(StatsdStatsTest,TestAtomSkippedStats)818 TEST(StatsdStatsTest, TestAtomSkippedStats) {
819 StatsdStats stats;
820
821 const int pushAtomTag = 100;
822 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
823 const int numSkipped = 10;
824
825 for (int i = 0; i < numSkipped; i++) {
826 stats.noteAtomLogged(pushAtomTag, /*timeSec=*/0, /*isSkipped*/ true);
827 stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec=*/0, /*isSkipped*/ true);
828 }
829
830 vector<uint8_t> output;
831 stats.dumpStats(&output, false);
832 StatsdStatsReport report;
833 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
834
835 // Check skip_count = numSkipped for push atoms
836 ASSERT_EQ(2, report.atom_stats_size());
837
838 const auto& pushedAtomStats = report.atom_stats(0);
839 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
840 EXPECT_EQ(numSkipped, pushedAtomStats.count());
841 EXPECT_EQ(numSkipped, pushedAtomStats.skip_count());
842 EXPECT_FALSE(pushedAtomStats.has_error_count());
843
844 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
845 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
846 EXPECT_EQ(numSkipped, nonPlatformPushedAtomStats.count());
847 EXPECT_EQ(numSkipped, nonPlatformPushedAtomStats.skip_count());
848 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
849 }
850
TEST(StatsdStatsTest,TestAtomLoggedAndDroppedAndSkippedStats)851 TEST(StatsdStatsTest, TestAtomLoggedAndDroppedAndSkippedStats) {
852 StatsdStats stats;
853
854 const int pushAtomTag = 100;
855 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
856
857 const int numLogged = 10;
858 for (int i = 0; i < numLogged; i++) {
859 stats.noteAtomLogged(pushAtomTag, /*timeSec*/ 0, false);
860 stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec*/ 0, false);
861 }
862
863 const int numDropped = 10;
864 for (int i = 0; i < numDropped; i++) {
865 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, true);
866 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, true);
867 }
868
869 vector<uint8_t> output;
870 stats.dumpStats(&output, false);
871 StatsdStatsReport report;
872 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
873
874 // Check dropped_count = numDropped for push atoms
875 ASSERT_EQ(2, report.atom_stats_size());
876
877 const auto& pushedAtomStats = report.atom_stats(0);
878 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
879 EXPECT_EQ(numLogged + numDropped, pushedAtomStats.count());
880 EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
881 EXPECT_EQ(numDropped, pushedAtomStats.skip_count());
882 EXPECT_FALSE(pushedAtomStats.has_error_count());
883
884 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
885 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
886 EXPECT_EQ(numLogged + numDropped, nonPlatformPushedAtomStats.count());
887 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
888 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.skip_count());
889 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
890 }
891
TEST(StatsdStatsTest,TestShardOffsetProvider)892 TEST(StatsdStatsTest, TestShardOffsetProvider) {
893 StatsdStats stats;
894 ShardOffsetProvider::getInstance().setShardOffset(15);
895 vector<uint8_t> output;
896 stats.dumpStats(&output, false);
897
898 StatsdStatsReport report;
899 EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
900 EXPECT_EQ(report.shard_offset(), 15);
901 }
902
903 } // namespace statsd
904 } // namespace os
905 } // namespace android
906 #else
907 GTEST_LOG_(INFO) << "This test does nothing.\n";
908 #endif
909