• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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