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 "gtest_matchers.h"
22 #include "src/metrics/parsing_utils/metrics_manager_util.h"
23 #include "src/shell/ShellSubscriber.h"
24 #include "src/stats_log.pb.h"
25 #include "statslog_statsdtest.h"
26 #include "tests/statsd_test_util.h"
27 
28 #ifdef __ANDROID__
29 
30 namespace std {
PrintTo(const tuple<int,size_t> & atomIdDimensionLimitTuple,ostream * os)31 void PrintTo(const tuple<int, size_t>& atomIdDimensionLimitTuple, ostream* os) {
32     *os << get<0>(atomIdDimensionLimitTuple) << "_" << get<1>(atomIdDimensionLimitTuple);
33 }
34 }  // namespace std
35 
36 namespace android {
37 namespace os {
38 namespace statsd {
39 namespace {
40 
41 using namespace testing;
42 using PerSubscriptionStats = StatsdStatsReport_SubscriptionStats_PerSubscriptionStats;
43 using std::tuple;
44 using std::unordered_map;
45 using std::vector;
46 
47 class StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap
48     : public TestWithParam<tuple<int, size_t>> {};
49 INSTANTIATE_TEST_SUITE_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap,
50                          StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap,
51                          Combine(Values(10022 /* BINDER_CALLS */, 10024 /* LOOPER_STATS */,
52                                         10010 /* CPU_TIME_PER_UID_FREQ */),
53                                  Values(-1, 0, 500, 800, 1000, 3000, 3300)),
54                          PrintToStringParamName());
55 
56 class StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap
57     : public StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap {};
58 
59 INSTANTIATE_TEST_SUITE_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap,
60                          StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap,
61                          Combine(Values(util::TEST_ATOM_REPORTED, util::SCREEN_STATE_CHANGED,
62                                         util::SUBSYSTEM_SLEEP_STATE),
63                                  Values(-1, 0, 500, 800, 1000, 3000, 3300)),
64                          PrintToStringParamName());
65 
66 }  // anonymous namespace
67 
TEST(StatsdStatsTest,TestValidConfigAdd)68 TEST(StatsdStatsTest, TestValidConfigAdd) {
69     StatsdStats stats;
70     ConfigKey key(0, 12345);
71     const int metricsCount = 10;
72     const int conditionsCount = 20;
73     const int matchersCount = 30;
74     const int alertsCount = 10;
75     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
76                              nullopt /*valid config*/);
77 
78     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
79     ASSERT_EQ(1, report.config_stats_size());
80     const auto& configReport = report.config_stats(0);
81     EXPECT_EQ(0, configReport.uid());
82     EXPECT_EQ(12345, configReport.id());
83     EXPECT_EQ(metricsCount, configReport.metric_count());
84     EXPECT_EQ(conditionsCount, configReport.condition_count());
85     EXPECT_EQ(matchersCount, configReport.matcher_count());
86     EXPECT_EQ(alertsCount, configReport.alert_count());
87     EXPECT_EQ(true, configReport.is_valid());
88     EXPECT_FALSE(configReport.has_invalid_config_reason());
89     EXPECT_FALSE(configReport.has_deletion_time_sec());
90 }
91 
TEST(StatsdStatsTest,TestConfigMetadataProviderPromotionFailed)92 TEST(StatsdStatsTest, TestConfigMetadataProviderPromotionFailed) {
93     StatsdStats stats;
94     ConfigKey key(0, 12345);
95     stats.noteConfigReceived(key, /*metricsCount=*/0, /*conditionsCount=*/0, /*matchersCount=*/0,
96                              /*alertCount=*/0, /*annotations=*/{}, nullopt /*valid config*/);
97 
98     stats.noteConfigMetadataProviderPromotionFailed(key);
99 
100     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
101     ASSERT_EQ(1, report.config_stats_size());
102     const auto& configReport = report.config_stats(0);
103     EXPECT_EQ(1, configReport.config_metadata_provider_promotion_failed());
104 }
105 
TEST(StatsdStatsTest,TestInvalidConfigAdd)106 TEST(StatsdStatsTest, TestInvalidConfigAdd) {
107     StatsdStats stats;
108     ConfigKey key(0, 12345);
109     const int metricsCount = 10;
110     const int conditionsCount = 20;
111     const int matchersCount = 30;
112     const int alertsCount = 10;
113     optional<InvalidConfigReason> invalidConfigReason =
114             InvalidConfigReason(INVALID_CONFIG_REASON_UNKNOWN, 1);
115     invalidConfigReason->stateId = 2;
116     invalidConfigReason->alertId = 3;
117     invalidConfigReason->alarmId = 4;
118     invalidConfigReason->subscriptionId = 5;
119     invalidConfigReason->matcherIds.push_back(6);
120     invalidConfigReason->matcherIds.push_back(7);
121     invalidConfigReason->conditionIds.push_back(8);
122     invalidConfigReason->conditionIds.push_back(9);
123     invalidConfigReason->conditionIds.push_back(10);
124     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
125                              invalidConfigReason /*bad config*/);
126 
127     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
128     ASSERT_EQ(1, report.config_stats_size());
129     const auto& configReport = report.config_stats(0);
130     // The invalid config should be put into icebox with a deletion time.
131     EXPECT_TRUE(configReport.has_deletion_time_sec());
132     EXPECT_TRUE(configReport.has_invalid_config_reason());
133     EXPECT_EQ(configReport.invalid_config_reason().reason(), INVALID_CONFIG_REASON_UNKNOWN);
134     EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
135     EXPECT_EQ(configReport.invalid_config_reason().state_id(), 2);
136     EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 3);
137     EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 4);
138     EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 5);
139     EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 2);
140     EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 6);
141     EXPECT_EQ(configReport.invalid_config_reason().matcher_id(1), 7);
142     EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 3);
143     EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 8);
144     EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 9);
145     EXPECT_EQ(configReport.invalid_config_reason().condition_id(2), 10);
146 }
147 
TEST(StatsdStatsTest,TestInvalidConfigMissingMetricId)148 TEST(StatsdStatsTest, TestInvalidConfigMissingMetricId) {
149     StatsdStats stats;
150     ConfigKey key(0, 12345);
151     const int metricsCount = 10;
152     const int conditionsCount = 20;
153     const int matchersCount = 30;
154     const int alertsCount = 10;
155     optional<InvalidConfigReason> invalidConfigReason =
156             InvalidConfigReason(INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
157     invalidConfigReason->stateId = 1;
158     invalidConfigReason->alertId = 2;
159     invalidConfigReason->alarmId = 3;
160     invalidConfigReason->subscriptionId = 4;
161     invalidConfigReason->matcherIds.push_back(5);
162     invalidConfigReason->conditionIds.push_back(6);
163     invalidConfigReason->conditionIds.push_back(7);
164     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
165                              invalidConfigReason /*bad config*/);
166 
167     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
168     ASSERT_EQ(1, report.config_stats_size());
169     const auto& configReport = report.config_stats(0);
170     // The invalid config should be put into icebox with a deletion time.
171     EXPECT_TRUE(configReport.has_deletion_time_sec());
172     EXPECT_TRUE(configReport.has_invalid_config_reason());
173     EXPECT_EQ(configReport.invalid_config_reason().reason(),
174               INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
175     EXPECT_FALSE(configReport.invalid_config_reason().has_metric_id());
176     EXPECT_EQ(configReport.invalid_config_reason().state_id(), 1);
177     EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 2);
178     EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 3);
179     EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 4);
180     EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 1);
181     EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 5);
182     EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 2);
183     EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 6);
184     EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 7);
185 }
186 
TEST(StatsdStatsTest,TestInvalidConfigOnlyMetricId)187 TEST(StatsdStatsTest, TestInvalidConfigOnlyMetricId) {
188     StatsdStats stats;
189     ConfigKey key(0, 12345);
190     const int metricsCount = 10;
191     const int conditionsCount = 20;
192     const int matchersCount = 30;
193     const int alertsCount = 10;
194     optional<InvalidConfigReason> invalidConfigReason =
195             InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG, 1);
196     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
197                              invalidConfigReason /*bad config*/);
198 
199     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
200     ASSERT_EQ(1, report.config_stats_size());
201     const auto& configReport = report.config_stats(0);
202     // The invalid config should be put into icebox with a deletion time.
203     EXPECT_TRUE(configReport.has_deletion_time_sec());
204     EXPECT_TRUE(configReport.has_invalid_config_reason());
205     EXPECT_EQ(configReport.invalid_config_reason().reason(),
206               INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG);
207     EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
208     EXPECT_FALSE(configReport.invalid_config_reason().has_state_id());
209     EXPECT_FALSE(configReport.invalid_config_reason().has_alert_id());
210     EXPECT_FALSE(configReport.invalid_config_reason().has_alarm_id());
211     EXPECT_FALSE(configReport.invalid_config_reason().has_subscription_id());
212     EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 0);
213     EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 0);
214 }
215 
TEST(StatsdStatsTest,TestConfigRemove)216 TEST(StatsdStatsTest, TestConfigRemove) {
217     StatsdStats stats;
218     ConfigKey key(0, 12345);
219     const int metricsCount = 10;
220     const int conditionsCount = 20;
221     const int matchersCount = 30;
222     const int alertsCount = 10;
223     stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
224                              nullopt);
225 
226     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
227     ASSERT_EQ(1, report.config_stats_size());
228     const auto& configReport = report.config_stats(0);
229     EXPECT_FALSE(configReport.has_deletion_time_sec());
230 
231     stats.noteConfigRemoved(key);
232 
233     report = getStatsdStatsReport(stats, /* reset stats */ false);
234     ASSERT_EQ(1, report.config_stats_size());
235     const auto& configReport2 = report.config_stats(0);
236     EXPECT_TRUE(configReport2.has_deletion_time_sec());
237 }
238 
TEST(StatsdStatsTest,TestSubStats)239 TEST(StatsdStatsTest, TestSubStats) {
240     StatsdStats stats;
241     ConfigKey key(0, 12345);
242     stats.noteConfigReceived(key, 2, 3, 4, 5, {std::make_pair(123, 456)}, nullopt);
243 
244     stats.noteMatcherMatched(key, StringToId("matcher1"));
245     stats.noteMatcherMatched(key, StringToId("matcher1"));
246     stats.noteMatcherMatched(key, StringToId("matcher2"));
247 
248     stats.noteConditionDimensionSize(key, StringToId("condition1"), 250);
249     stats.noteConditionDimensionSize(key, StringToId("condition1"), 240);
250 
251     stats.noteMetricDimensionSize(key, StringToId("metric1"), 201);
252     stats.noteMetricDimensionSize(key, StringToId("metric1"), 202);
253 
254     stats.noteAnomalyDeclared(key, StringToId("alert1"));
255     stats.noteAnomalyDeclared(key, StringToId("alert1"));
256     stats.noteAnomalyDeclared(key, StringToId("alert2"));
257 
258     // broadcast-> 2
259     stats.noteBroadcastSent(key);
260     stats.noteBroadcastSent(key);
261 
262     // data drop -> 1
263     stats.noteDataDropped(key, 123);
264 
265     // dump report -> 3
266     stats.noteMetricsReportSent(key, 0, 1);
267     stats.noteMetricsReportSent(key, 0, 2);
268     stats.noteMetricsReportSent(key, 0, 3);
269 
270     // activation_time_sec -> 2
271     stats.noteActiveStatusChanged(key, true);
272     stats.noteActiveStatusChanged(key, true);
273 
274     // deactivation_time_sec -> 1
275     stats.noteActiveStatusChanged(key, false);
276 
277     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true);
278     ASSERT_EQ(1, report.config_stats_size());
279     const auto& configReport = report.config_stats(0);
280     ASSERT_EQ(2, configReport.broadcast_sent_time_sec_size());
281     ASSERT_EQ(1, configReport.data_drop_time_sec_size());
282     ASSERT_EQ(1, configReport.data_drop_bytes_size());
283     EXPECT_EQ(123, configReport.data_drop_bytes(0));
284     ASSERT_EQ(3, configReport.dump_report_time_sec_size());
285     ASSERT_EQ(3, configReport.dump_report_data_size_size());
286     ASSERT_EQ(3, configReport.dump_report_number_size());
287     EXPECT_EQ(1, configReport.dump_report_number(0));
288     EXPECT_EQ(2, configReport.dump_report_number(1));
289     EXPECT_EQ(3, configReport.dump_report_number(2));
290     ASSERT_EQ(2, configReport.activation_time_sec_size());
291     ASSERT_EQ(1, configReport.deactivation_time_sec_size());
292     ASSERT_EQ(1, configReport.annotation_size());
293     EXPECT_EQ(123, configReport.annotation(0).field_int64());
294     EXPECT_EQ(456, configReport.annotation(0).field_int32());
295 
296     ASSERT_EQ(2, configReport.matcher_stats_size());
297     // matcher1 is the first in the list
298     if (configReport.matcher_stats(0).id() == StringToId("matcher1")) {
299         EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
300         EXPECT_EQ(1, configReport.matcher_stats(1).matched_times());
301         EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(1).id());
302     } else {
303         // matcher1 is the second in the list.
304         EXPECT_EQ(1, configReport.matcher_stats(0).matched_times());
305         EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(0).id());
306 
307         EXPECT_EQ(2, configReport.matcher_stats(1).matched_times());
308         EXPECT_EQ(StringToId("matcher1"), configReport.matcher_stats(1).id());
309     }
310 
311     ASSERT_EQ(2, configReport.alert_stats_size());
312     bool alert1first = configReport.alert_stats(0).id() == StringToId("alert1");
313     EXPECT_EQ(StringToId("alert1"), configReport.alert_stats(alert1first ? 0 : 1).id());
314     EXPECT_EQ(2, configReport.alert_stats(alert1first ? 0 : 1).alerted_times());
315     EXPECT_EQ(StringToId("alert2"), configReport.alert_stats(alert1first ? 1 : 0).id());
316     EXPECT_EQ(1, configReport.alert_stats(alert1first ? 1 : 0).alerted_times());
317 
318     ASSERT_EQ(1, configReport.condition_stats_size());
319     EXPECT_EQ(StringToId("condition1"), configReport.condition_stats(0).id());
320     EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
321 
322     ASSERT_EQ(1, configReport.metric_stats_size());
323     EXPECT_EQ(StringToId("metric1"), configReport.metric_stats(0).id());
324     EXPECT_EQ(202, configReport.metric_stats(0).max_tuple_counts());
325 
326     // after resetting the stats, some new events come
327     stats.noteMatcherMatched(key, StringToId("matcher99"));
328     stats.noteConditionDimensionSize(key, StringToId("condition99"), 300);
329     stats.noteMetricDimensionSize(key, StringToId("metric99tion99"), 270);
330     stats.noteAnomalyDeclared(key, StringToId("alert99"));
331 
332     // now the config stats should only contain the stats about the new event.
333     report = getStatsdStatsReport(stats, /* reset stats */ false);
334     ASSERT_EQ(1, report.config_stats_size());
335     const auto& configReport2 = report.config_stats(0);
336     ASSERT_EQ(1, configReport2.matcher_stats_size());
337     EXPECT_EQ(StringToId("matcher99"), configReport2.matcher_stats(0).id());
338     EXPECT_EQ(1, configReport2.matcher_stats(0).matched_times());
339 
340     ASSERT_EQ(1, configReport2.condition_stats_size());
341     EXPECT_EQ(StringToId("condition99"), configReport2.condition_stats(0).id());
342     EXPECT_EQ(300, configReport2.condition_stats(0).max_tuple_counts());
343 
344     ASSERT_EQ(1, configReport2.metric_stats_size());
345     EXPECT_EQ(StringToId("metric99tion99"), configReport2.metric_stats(0).id());
346     EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
347 
348     ASSERT_EQ(1, configReport2.alert_stats_size());
349     EXPECT_EQ(StringToId("alert99"), configReport2.alert_stats(0).id());
350     EXPECT_EQ(1, configReport2.alert_stats(0).alerted_times());
351 }
352 
TEST(StatsdStatsTest,TestAtomLog)353 TEST(StatsdStatsTest, TestAtomLog) {
354     StatsdStats stats;
355     time_t now = time(nullptr);
356     // old event, we get it from the stats buffer. should be ignored.
357     stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, 1000, false);
358 
359     stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 1, false);
360     stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 2, false);
361     stats.noteAtomLogged(util::APP_CRASH_OCCURRED, now + 3, false);
362 
363     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
364     ASSERT_EQ(2, report.atom_stats_size());
365     bool sensorAtomGood = false;
366     bool dropboxAtomGood = false;
367 
368     for (const auto& atomStats : report.atom_stats()) {
369         if (atomStats.tag() == util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
370             sensorAtomGood = true;
371         }
372         if (atomStats.tag() == util::APP_CRASH_OCCURRED && atomStats.count() == 1) {
373             dropboxAtomGood = true;
374         }
375         EXPECT_FALSE(atomStats.has_dropped_count());
376         EXPECT_FALSE(atomStats.has_skip_count());
377     }
378 
379     EXPECT_TRUE(dropboxAtomGood);
380     EXPECT_TRUE(sensorAtomGood);
381 }
382 
TEST(StatsdStatsTest,TestNonPlatformAtomLog)383 TEST(StatsdStatsTest, TestNonPlatformAtomLog) {
384     StatsdStats stats;
385     time_t now = time(nullptr);
386     int newAtom1 = StatsdStats::kMaxPushedAtomId + 1;
387     int newAtom2 = StatsdStats::kMaxPushedAtomId + 2;
388 
389     stats.noteAtomLogged(newAtom1, now + 1, false);
390     stats.noteAtomLogged(newAtom1, now + 2, false);
391     stats.noteAtomLogged(newAtom2, now + 3, false);
392 
393     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
394     ASSERT_EQ(2, report.atom_stats_size());
395     bool newAtom1Good = false;
396     bool newAtom2Good = false;
397 
398     for (const auto& atomStats : report.atom_stats()) {
399         if (atomStats.tag() == newAtom1 && atomStats.count() == 2) {
400             newAtom1Good = true;
401         }
402         if (atomStats.tag() == newAtom2 && atomStats.count() == 1) {
403             newAtom2Good = true;
404         }
405         EXPECT_FALSE(atomStats.has_dropped_count());
406         EXPECT_FALSE(atomStats.has_skip_count());
407     }
408 
409     EXPECT_TRUE(newAtom1Good);
410     EXPECT_TRUE(newAtom2Good);
411 }
412 
TEST(StatsdStatsTest,TestPullAtomStats)413 TEST(StatsdStatsTest, TestPullAtomStats) {
414     StatsdStats stats;
415 
416     stats.updateMinPullIntervalSec(util::DISK_SPACE, 3333L);
417     stats.updateMinPullIntervalSec(util::DISK_SPACE, 2222L);
418     stats.updateMinPullIntervalSec(util::DISK_SPACE, 4444L);
419 
420     stats.notePull(util::DISK_SPACE);
421     stats.notePullTime(util::DISK_SPACE, 1111L);
422     stats.notePullDelay(util::DISK_SPACE, 1111L);
423     stats.notePull(util::DISK_SPACE);
424     stats.notePullTime(util::DISK_SPACE, 3333L);
425     stats.notePullDelay(util::DISK_SPACE, 3335L);
426     stats.notePull(util::DISK_SPACE);
427     stats.notePullFromCache(util::DISK_SPACE);
428     stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
429     stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, false);
430     stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
431     stats.notePullBinderCallFailed(util::DISK_SPACE);
432     stats.notePullUidProviderNotFound(util::DISK_SPACE);
433     stats.notePullerNotFound(util::DISK_SPACE);
434     stats.notePullerNotFound(util::DISK_SPACE);
435     stats.notePullTimeout(util::DISK_SPACE, 3000L, 6000L);
436     stats.notePullTimeout(util::DISK_SPACE, 4000L, 7000L);
437 
438     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
439     ASSERT_EQ(1, report.pulled_atom_stats_size());
440 
441     EXPECT_EQ(util::DISK_SPACE, report.pulled_atom_stats(0).atom_id());
442     EXPECT_EQ(3, report.pulled_atom_stats(0).total_pull());
443     EXPECT_EQ(1, report.pulled_atom_stats(0).total_pull_from_cache());
444     EXPECT_EQ(2222L, report.pulled_atom_stats(0).min_pull_interval_sec());
445     EXPECT_EQ(2222L, report.pulled_atom_stats(0).average_pull_time_nanos());
446     EXPECT_EQ(3333L, report.pulled_atom_stats(0).max_pull_time_nanos());
447     EXPECT_EQ(2223L, report.pulled_atom_stats(0).average_pull_delay_nanos());
448     EXPECT_EQ(3335L, report.pulled_atom_stats(0).max_pull_delay_nanos());
449     EXPECT_EQ(2L, report.pulled_atom_stats(0).registered_count());
450     EXPECT_EQ(1L, report.pulled_atom_stats(0).unregistered_count());
451     EXPECT_EQ(1L, report.pulled_atom_stats(0).binder_call_failed());
452     EXPECT_EQ(1L, report.pulled_atom_stats(0).failed_uid_provider_not_found());
453     EXPECT_EQ(2L, report.pulled_atom_stats(0).puller_not_found());
454     ASSERT_EQ(2, report.pulled_atom_stats(0).pull_atom_metadata_size());
455     EXPECT_EQ(3000L, report.pulled_atom_stats(0).pull_atom_metadata(0).pull_timeout_uptime_millis());
456     EXPECT_EQ(4000L, report.pulled_atom_stats(0).pull_atom_metadata(1).pull_timeout_uptime_millis());
457     EXPECT_EQ(6000L, report.pulled_atom_stats(0).pull_atom_metadata(0)
458             .pull_timeout_elapsed_millis());
459     EXPECT_EQ(7000L, report.pulled_atom_stats(0).pull_atom_metadata(1)
460             .pull_timeout_elapsed_millis());
461 }
462 
TEST(StatsdStatsTest,TestAtomMetricsStats)463 TEST(StatsdStatsTest, TestAtomMetricsStats) {
464     StatsdStats stats;
465     time_t now = time(nullptr);
466     // old event, we get it from the stats buffer. should be ignored.
467     stats.noteBucketDropped(10000000000LL);
468 
469     stats.noteBucketBoundaryDelayNs(10000000000LL, -1L);
470     stats.noteBucketBoundaryDelayNs(10000000000LL, -10L);
471     stats.noteBucketBoundaryDelayNs(10000000000LL, 2L);
472 
473     stats.noteBucketBoundaryDelayNs(10000000001LL, 1L);
474 
475     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
476     ASSERT_EQ(2, report.atom_metric_stats().size());
477 
478     auto atomStats = report.atom_metric_stats(0);
479     EXPECT_EQ(10000000000LL, atomStats.metric_id());
480     EXPECT_EQ(1L, atomStats.bucket_dropped());
481     EXPECT_EQ(-10L, atomStats.min_bucket_boundary_delay_ns());
482     EXPECT_EQ(2L, atomStats.max_bucket_boundary_delay_ns());
483 
484     auto atomStats2 = report.atom_metric_stats(1);
485     EXPECT_EQ(10000000001LL, atomStats2.metric_id());
486     EXPECT_EQ(0L, atomStats2.bucket_dropped());
487     EXPECT_EQ(0L, atomStats2.min_bucket_boundary_delay_ns());
488     EXPECT_EQ(1L, atomStats2.max_bucket_boundary_delay_ns());
489 }
490 
TEST(StatsdStatsTest,TestRestrictedMetricsStats)491 TEST(StatsdStatsTest, TestRestrictedMetricsStats) {
492     StatsdStats stats;
493     const int64_t metricId = -1234556L;
494     ConfigKey key(0, 12345);
495     stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
496     stats.noteRestrictedMetricInsertError(key, metricId);
497     stats.noteRestrictedMetricTableCreationError(key, metricId);
498     stats.noteRestrictedMetricTableDeletionError(key, metricId);
499     stats.noteDeviceInfoTableCreationFailed(key);
500     stats.noteRestrictedMetricFlushLatency(key, metricId, 3000);
501     stats.noteRestrictedMetricFlushLatency(key, metricId, 3001);
502     stats.noteRestrictedMetricCategoryChanged(key, metricId);
503     stats.noteRestrictedConfigFlushLatency(key, 4000);
504     ConfigKey configKeyWithoutError(0, 666);
505     stats.noteConfigReceived(configKeyWithoutError, 2, 3, 4, 5, {}, nullopt);
506     stats.noteDbCorrupted(key);
507     stats.noteDbCorrupted(key);
508     stats.noteDbSizeExceeded(key);
509     stats.noteDbStatFailed(key);
510     stats.noteDbConfigInvalid(key);
511     stats.noteDbTooOld(key);
512     stats.noteDbDeletionConfigRemoved(key);
513     stats.noteDbDeletionConfigUpdated(key);
514     stats.noteRestrictedConfigDbSize(key, 999, 111);
515 
516     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
517     ASSERT_EQ(2, report.config_stats().size());
518     ASSERT_EQ(0, report.config_stats(0).restricted_metric_stats().size());
519     ASSERT_EQ(1, report.config_stats(1).restricted_metric_stats().size());
520     EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).insert_error());
521     EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).table_creation_error());
522     EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).table_deletion_error());
523     EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).category_changed_count());
524     ASSERT_EQ(2, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns().size());
525     EXPECT_EQ(3000, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns(0));
526     EXPECT_EQ(3001, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns(1));
527     ASSERT_EQ(1, report.config_stats(1).restricted_db_size_time_sec().size());
528     EXPECT_EQ(999, report.config_stats(1).restricted_db_size_time_sec(0));
529     ASSERT_EQ(1, report.config_stats(1).restricted_db_size_bytes().size());
530     EXPECT_EQ(111, report.config_stats(1).restricted_db_size_bytes(0));
531     ASSERT_EQ(1, report.config_stats(1).restricted_flush_latency().size());
532     EXPECT_EQ(4000, report.config_stats(1).restricted_flush_latency(0));
533     EXPECT_TRUE(report.config_stats(1).device_info_table_creation_failed());
534     EXPECT_EQ(metricId, report.config_stats(1).restricted_metric_stats(0).restricted_metric_id());
535     EXPECT_EQ(2, report.config_stats(1).restricted_db_corrupted_count());
536     EXPECT_EQ(1, report.config_stats(1).db_deletion_stat_failed());
537     EXPECT_EQ(1, report.config_stats(1).db_deletion_size_exceeded_limit());
538     EXPECT_EQ(1, report.config_stats(1).db_deletion_config_invalid());
539     EXPECT_EQ(1, report.config_stats(1).db_deletion_too_old());
540     EXPECT_EQ(1, report.config_stats(1).db_deletion_config_removed());
541     EXPECT_EQ(1, report.config_stats(1).db_deletion_config_updated());
542 }
543 
TEST(StatsdStatsTest,TestRestrictedMetricsQueryStats)544 TEST(StatsdStatsTest, TestRestrictedMetricsQueryStats) {
545     StatsdStats stats;
546     const int32_t callingUid = 100;
547     ConfigKey configKey(0, 12345);
548     const string configPackage = "com.google.android.gm";
549     int64_t beforeNoteMetricSucceed = getWallClockNs();
550     stats.noteQueryRestrictedMetricSucceed(configKey.GetId(), configPackage, configKey.GetUid(),
551                                            callingUid, /*queryLatencyNs=*/5 * NS_PER_SEC);
552     int64_t afterNoteMetricSucceed = getWallClockNs();
553 
554     const int64_t configIdWithError = 111;
555     stats.noteQueryRestrictedMetricFailed(configIdWithError, configPackage, std::nullopt,
556                                           callingUid, InvalidQueryReason(AMBIGUOUS_CONFIG_KEY));
557     stats.noteQueryRestrictedMetricFailed(configIdWithError, configPackage, std::nullopt,
558                                           callingUid, InvalidQueryReason(AMBIGUOUS_CONFIG_KEY),
559                                           "error_message");
560 
561     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
562     ASSERT_EQ(3, report.restricted_metric_query_stats().size());
563     EXPECT_EQ(configKey.GetId(), report.restricted_metric_query_stats(0).config_id());
564     EXPECT_EQ(configKey.GetUid(), report.restricted_metric_query_stats(0).config_uid());
565     EXPECT_EQ(callingUid, report.restricted_metric_query_stats(0).calling_uid());
566     EXPECT_EQ(configPackage, report.restricted_metric_query_stats(0).config_package());
567     EXPECT_FALSE(report.restricted_metric_query_stats(0).has_query_error());
568     EXPECT_LT(beforeNoteMetricSucceed,
569               report.restricted_metric_query_stats(0).query_wall_time_ns());
570     EXPECT_GT(afterNoteMetricSucceed, report.restricted_metric_query_stats(0).query_wall_time_ns());
571     EXPECT_EQ(5 * NS_PER_SEC, report.restricted_metric_query_stats(0).query_latency_ns());
572     EXPECT_EQ(configIdWithError, report.restricted_metric_query_stats(1).config_id());
573     EXPECT_EQ(AMBIGUOUS_CONFIG_KEY, report.restricted_metric_query_stats(1).invalid_query_reason());
574     EXPECT_EQ(false, report.restricted_metric_query_stats(1).has_config_uid());
575     EXPECT_FALSE(report.restricted_metric_query_stats(1).has_query_error());
576     EXPECT_FALSE(report.restricted_metric_query_stats(1).has_query_latency_ns());
577     EXPECT_EQ("error_message", report.restricted_metric_query_stats(2).query_error());
578     EXPECT_FALSE(report.restricted_metric_query_stats(2).has_query_latency_ns());
579     EXPECT_NE(report.restricted_metric_query_stats(1).query_wall_time_ns(),
580               report.restricted_metric_query_stats(0).query_wall_time_ns());
581 }
582 
TEST(StatsdStatsTest,TestAnomalyMonitor)583 TEST(StatsdStatsTest, TestAnomalyMonitor) {
584     StatsdStats stats;
585     stats.noteRegisteredAnomalyAlarmChanged();
586     stats.noteRegisteredAnomalyAlarmChanged();
587 
588     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
589     EXPECT_EQ(2, report.anomaly_alarm_stats().alarms_registered());
590 }
591 
TEST(StatsdStatsTest,TestTimestampThreshold)592 TEST(StatsdStatsTest, TestTimestampThreshold) {
593     StatsdStats stats;
594     vector<int32_t> timestamps;
595     for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
596         timestamps.push_back(i);
597     }
598     ConfigKey key(0, 12345);
599     stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
600 
601     for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
602         stats.noteDataDropped(key, timestamps[i]);
603         stats.noteBroadcastSent(key, timestamps[i]);
604         stats.noteMetricsReportSent(key, 0, timestamps[i], i + 1);
605         stats.noteActiveStatusChanged(key, true, timestamps[i]);
606         stats.noteActiveStatusChanged(key, false, timestamps[i]);
607     }
608 
609     int32_t newTimestamp = 10000;
610 
611     // now it should trigger removing oldest timestamp
612     stats.noteDataDropped(key, 123, 10000);
613     stats.noteBroadcastSent(key, 10000);
614     stats.noteMetricsReportSent(key, 0, 10000, 21);
615     stats.noteActiveStatusChanged(key, true, 10000);
616     stats.noteActiveStatusChanged(key, false, 10000);
617 
618     EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
619     const auto& configStats = stats.mConfigStats[key];
620 
621     size_t maxCount = StatsdStats::kMaxTimestampCount;
622     ASSERT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
623     ASSERT_EQ(maxCount, configStats->data_drop_time_sec.size());
624     ASSERT_EQ(maxCount, configStats->dump_report_stats.size());
625     ASSERT_EQ(maxCount, configStats->activation_time_sec.size());
626     ASSERT_EQ(maxCount, configStats->deactivation_time_sec.size());
627 
628     // the oldest timestamp is the second timestamp in history
629     EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
630     EXPECT_EQ(1, configStats->data_drop_bytes.front());
631     EXPECT_EQ(1, configStats->dump_report_stats.front().mDumpReportTimeSec);
632     EXPECT_EQ(1, configStats->activation_time_sec.front());
633     EXPECT_EQ(1, configStats->deactivation_time_sec.front());
634 
635     // the last timestamp is the newest timestamp.
636     EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
637     EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
638     EXPECT_EQ(123, configStats->data_drop_bytes.back());
639     EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().mDumpReportTimeSec);
640     EXPECT_EQ(newTimestamp, configStats->activation_time_sec.back());
641     EXPECT_EQ(newTimestamp, configStats->deactivation_time_sec.back());
642 }
643 
TEST(StatsdStatsTest,TestSystemServerCrash)644 TEST(StatsdStatsTest, TestSystemServerCrash) {
645     StatsdStats stats;
646     vector<int32_t> timestamps;
647     for (int i = 0; i < StatsdStats::kMaxSystemServerRestarts; i++) {
648         timestamps.push_back(i);
649         stats.noteSystemServerRestart(timestamps[i]);
650     }
651 
652     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
653     const int maxCount = StatsdStats::kMaxSystemServerRestarts;
654     ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
655 
656     stats.noteSystemServerRestart(StatsdStats::kMaxSystemServerRestarts + 1);
657 
658     report = getStatsdStatsReport(stats, /* reset stats */ false);
659     ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
660     EXPECT_EQ(StatsdStats::kMaxSystemServerRestarts + 1, report.system_restart_sec(maxCount - 1));
661 }
662 
TEST(StatsdStatsTest,TestActivationBroadcastGuardrailHit)663 TEST(StatsdStatsTest, TestActivationBroadcastGuardrailHit) {
664     StatsdStats stats;
665     int uid1 = 1;
666     int uid2 = 2;
667     stats.noteActivationBroadcastGuardrailHit(uid1, 10);
668     stats.noteActivationBroadcastGuardrailHit(uid1, 20);
669 
670     // Test that we only keep 20 timestamps.
671     for (int i = 0; i < 100; i++) {
672         stats.noteActivationBroadcastGuardrailHit(uid2, i);
673     }
674 
675     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
676     ASSERT_EQ(2, report.activation_guardrail_stats_size());
677     bool uid1Good = false;
678     bool uid2Good = false;
679     for (const auto& guardrailTimes : report.activation_guardrail_stats()) {
680         if (uid1 == guardrailTimes.uid()) {
681             uid1Good = true;
682             ASSERT_EQ(2, guardrailTimes.guardrail_met_sec_size());
683             EXPECT_EQ(10, guardrailTimes.guardrail_met_sec(0));
684             EXPECT_EQ(20, guardrailTimes.guardrail_met_sec(1));
685         } else if (uid2 == guardrailTimes.uid()) {
686             int maxCount = StatsdStats::kMaxTimestampCount;
687             uid2Good = true;
688             ASSERT_EQ(maxCount, guardrailTimes.guardrail_met_sec_size());
689             for (int i = 0; i < maxCount; i++) {
690                 EXPECT_EQ(100 - maxCount + i, guardrailTimes.guardrail_met_sec(i));
691             }
692         } else {
693             FAIL() << "Unexpected uid.";
694         }
695     }
696     EXPECT_TRUE(uid1Good);
697     EXPECT_TRUE(uid2Good);
698 }
699 
TEST(StatsdStatsTest,TestAtomErrorStats)700 TEST(StatsdStatsTest, TestAtomErrorStats) {
701     StatsdStats stats;
702 
703     int pushAtomTag = 100;
704     int pullAtomTag = 1000;
705     int numErrors = 10;
706 
707     for (int i = 0; i < numErrors; i++) {
708         // We must call noteAtomLogged as well because only those pushed atoms
709         // that have been logged will have stats printed about them in the
710         // proto.
711         stats.noteAtomLogged(pushAtomTag, /*timeSec=*/0, false);
712         stats.noteAtomError(pushAtomTag, /*pull=*/false);
713 
714         stats.noteAtomError(pullAtomTag, /*pull=*/true);
715     }
716 
717     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
718 
719     // Check error count = numErrors for push atom
720     ASSERT_EQ(1, report.atom_stats_size());
721     const auto& pushedAtomStats = report.atom_stats(0);
722     EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
723     EXPECT_EQ(numErrors, pushedAtomStats.error_count());
724     EXPECT_FALSE(pushedAtomStats.has_dropped_count());
725     EXPECT_FALSE(pushedAtomStats.has_skip_count());
726 
727     // Check error count = numErrors for pull atom
728     ASSERT_EQ(1, report.pulled_atom_stats_size());
729     const auto& pulledAtomStats = report.pulled_atom_stats(0);
730     EXPECT_EQ(pullAtomTag, pulledAtomStats.atom_id());
731     EXPECT_EQ(numErrors, pulledAtomStats.atom_error_count());
732 }
733 
TEST(StatsdStatsTest,TestAtomDroppedStats)734 TEST(StatsdStatsTest, TestAtomDroppedStats) {
735     StatsdStats stats;
736 
737     const int pushAtomTag = 100;
738     const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
739 
740     const int numDropped = 10;
741     for (int i = 0; i < numDropped; i++) {
742         stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, false);
743         stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, false);
744     }
745 
746     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true);
747 
748     ASSERT_EQ(0, stats.mPushedAtomDropsStats.size());
749 
750     // Check dropped_count = numDropped for push atoms
751     ASSERT_EQ(2, report.atom_stats_size());
752 
753     const auto& pushedAtomStats = report.atom_stats(0);
754     EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
755     EXPECT_EQ(numDropped, pushedAtomStats.count());
756     EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
757     EXPECT_FALSE(pushedAtomStats.has_error_count());
758     EXPECT_FALSE(pushedAtomStats.has_skip_count());
759 
760     const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
761     EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
762     EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.count());
763     EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
764     EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
765     EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count());
766 }
767 
TEST(StatsdStatsTest,TestQueueStats)768 TEST(StatsdStatsTest, TestQueueStats) {
769     StatsdStats stats;
770 
771     stats.noteEventQueueSize(100, 1000);
772     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true);
773 
774     ASSERT_EQ(100, report.event_queue_stats().max_size_observed());
775     ASSERT_EQ(1000, report.event_queue_stats().max_size_observed_elapsed_nanos());
776 }
777 
TEST(StatsdStatsTest,TestAtomLoggedAndDroppedStats)778 TEST(StatsdStatsTest, TestAtomLoggedAndDroppedStats) {
779     StatsdStats stats;
780 
781     const int pushAtomTag = 100;
782     const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
783 
784     const int numLogged = 10;
785     for (int i = 0; i < numLogged; i++) {
786         stats.noteAtomLogged(pushAtomTag, /*timeSec*/ 0, false);
787         stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec*/ 0, false);
788     }
789 
790     const int numDropped = 10;
791     for (int i = 0; i < numDropped; i++) {
792         stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, false);
793         stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, false);
794     }
795 
796     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
797 
798     // Check dropped_count = numDropped for push atoms
799     ASSERT_EQ(2, report.atom_stats_size());
800 
801     const auto& pushedAtomStats = report.atom_stats(0);
802     EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
803     EXPECT_EQ(numLogged + numDropped, pushedAtomStats.count());
804     EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
805     EXPECT_FALSE(pushedAtomStats.has_error_count());
806     EXPECT_FALSE(pushedAtomStats.has_skip_count());
807 
808     const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
809     EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
810     EXPECT_EQ(numLogged + numDropped, nonPlatformPushedAtomStats.count());
811     EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
812     EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
813     EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count());
814 }
815 
TEST(StatsdStatsTest,TestAtomSkippedStats)816 TEST(StatsdStatsTest, TestAtomSkippedStats) {
817     StatsdStats stats;
818 
819     const int pushAtomTag = 100;
820     const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
821     const int numSkipped = 10;
822 
823     for (int i = 0; i < numSkipped; i++) {
824         stats.noteAtomLogged(pushAtomTag, /*timeSec=*/0, /*isSkipped*/ true);
825         stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec=*/0, /*isSkipped*/ true);
826     }
827 
828     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
829 
830     // Check skip_count = numSkipped for push atoms
831     ASSERT_EQ(2, report.atom_stats_size());
832 
833     const auto& pushedAtomStats = report.atom_stats(0);
834     EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
835     EXPECT_EQ(numSkipped, pushedAtomStats.count());
836     EXPECT_EQ(numSkipped, pushedAtomStats.skip_count());
837     EXPECT_FALSE(pushedAtomStats.has_error_count());
838 
839     const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
840     EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
841     EXPECT_EQ(numSkipped, nonPlatformPushedAtomStats.count());
842     EXPECT_EQ(numSkipped, nonPlatformPushedAtomStats.skip_count());
843     EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
844 }
845 
TEST(StatsdStatsTest,TestAtomLoggedAndDroppedAndSkippedStats)846 TEST(StatsdStatsTest, TestAtomLoggedAndDroppedAndSkippedStats) {
847     StatsdStats stats;
848 
849     const int pushAtomTag = 100;
850     const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
851 
852     const int numLogged = 10;
853     for (int i = 0; i < numLogged; i++) {
854         stats.noteAtomLogged(pushAtomTag, /*timeSec*/ 0, false);
855         stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec*/ 0, false);
856     }
857 
858     const int numDropped = 10;
859     for (int i = 0; i < numDropped; i++) {
860         stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, true);
861         stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, true);
862     }
863 
864     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
865 
866     // Check dropped_count = numDropped for push atoms
867     ASSERT_EQ(2, report.atom_stats_size());
868 
869     const auto& pushedAtomStats = report.atom_stats(0);
870     EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
871     EXPECT_EQ(numLogged + numDropped, pushedAtomStats.count());
872     EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
873     EXPECT_EQ(numDropped, pushedAtomStats.skip_count());
874     EXPECT_FALSE(pushedAtomStats.has_error_count());
875 
876     const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
877     EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
878     EXPECT_EQ(numLogged + numDropped, nonPlatformPushedAtomStats.count());
879     EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
880     EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.skip_count());
881     EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
882 }
883 
TEST(StatsdStatsTest,TestShardOffsetProvider)884 TEST(StatsdStatsTest, TestShardOffsetProvider) {
885     StatsdStats stats;
886     ShardOffsetProvider::getInstance().setShardOffset(15);
887 
888     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
889     EXPECT_EQ(report.shard_offset(), 15);
890 }
891 
TEST(StatsdStatsTest,TestHasHitDimensionGuardrail)892 TEST(StatsdStatsTest, TestHasHitDimensionGuardrail) {
893     StatsdStats stats;
894     int metricId1 = 1;
895     int metricId2 = 2;
896     int metricId3 = 3;
897 
898     stats.noteBucketCount(metricId2);
899     stats.noteHardDimensionLimitReached(metricId3);
900 
901     // No AtomMetricStats.
902     EXPECT_FALSE(stats.hasHitDimensionGuardrail(metricId1));
903 
904     // Has AtomMetricStats but hasn't hit dimension guardrail.
905     EXPECT_FALSE(stats.hasHitDimensionGuardrail(metricId2));
906 
907     // Has hit dimension guardrail.
908     EXPECT_TRUE(stats.hasHitDimensionGuardrail(metricId3));
909 }
910 
TEST(StatsdStatsTest,TestSubscriptionStarted)911 TEST(StatsdStatsTest, TestSubscriptionStarted) {
912     StatsdStats stats;
913 
914     stats.noteSubscriptionStarted(/* id */ 1, /* pushedCount */ 3, /* pulledCount */ 1);
915 
916     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
917 
918     auto subscriptionStats = report.subscription_stats();
919     EXPECT_EQ(subscriptionStats.pull_thread_wakeup_count(), 0);
920     ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), 1);
921     auto perSubscriptionStats = subscriptionStats.per_subscription_stats(0);
922     EXPECT_EQ(perSubscriptionStats.pushed_atom_count(), 3);
923     EXPECT_EQ(perSubscriptionStats.pulled_atom_count(), 1);
924     EXPECT_GT(perSubscriptionStats.start_time_sec(), 0);
925     EXPECT_FALSE(perSubscriptionStats.has_end_time_sec());
926     EXPECT_EQ(perSubscriptionStats.flush_count(), 0);
927 }
928 
TEST(StatsdStatsTest,TestSubscriptionFlushed)929 TEST(StatsdStatsTest, TestSubscriptionFlushed) {
930     StatsdStats stats;
931 
932     stats.noteSubscriptionStarted(/* id */ 1, /* pushedCount */ 3, /* pulledCount */ 1);
933     stats.noteSubscriptionFlushed(/* id */ 1);
934 
935     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
936 
937     auto subscriptionStats = report.subscription_stats();
938     ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), 1);
939     auto perSubscriptionStats = subscriptionStats.per_subscription_stats(0);
940     EXPECT_EQ(perSubscriptionStats.flush_count(), 1);
941 }
942 
TEST(StatsdStatsTest,TestSubscriptionEnded)943 TEST(StatsdStatsTest, TestSubscriptionEnded) {
944     StatsdStats stats;
945 
946     stats.noteSubscriptionStarted(/* id */ 1, /* pushedCount */ 3, /* pulledCount */ 1);
947     stats.noteSubscriptionEnded(/* id */ 1);
948 
949     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
950 
951     auto subscriptionStats = report.subscription_stats();
952     ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), 1);
953     EXPECT_GT(subscriptionStats.per_subscription_stats(0).end_time_sec(), 0);
954 }
955 
TEST(StatsdStatsTest,TestSubscriptionAtomPulled)956 TEST(StatsdStatsTest, TestSubscriptionAtomPulled) {
957     StatsdStats stats;
958 
959     stats.noteSubscriptionAtomPulled(/* atomId */ 10'001);
960 
961     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
962 
963     ASSERT_EQ(report.pulled_atom_stats_size(), 1);
964     auto pulledAtomStats = report.pulled_atom_stats(0);
965     EXPECT_EQ(pulledAtomStats.subscription_pull_count(), 1);
966 }
967 
TEST(StatsdStatsTest,TestSubscriptionPullThreadWakeup)968 TEST(StatsdStatsTest, TestSubscriptionPullThreadWakeup) {
969     StatsdStats stats;
970 
971     stats.noteSubscriptionPullThreadWakeup();
972 
973     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
974 
975     auto subscriptionStats = report.subscription_stats();
976     EXPECT_EQ(subscriptionStats.pull_thread_wakeup_count(), 1);
977 }
978 
TEST(StatsdStatsTest,TestSubscriptionStartedMaxActiveSubscriptions)979 TEST(StatsdStatsTest, TestSubscriptionStartedMaxActiveSubscriptions) {
980     StatsdStats stats;
981 
982     const int maxSubs = ShellSubscriber::getMaxSubscriptions();
983 
984     // Start more than max # of allowed subscriptions.
985     // maxSub + 1th subscriptions should not have been added.
986     for (int id = 1; id <= maxSubs + 1; id++) {
987         stats.noteSubscriptionStarted(id, /* pushedCount */ 3, /* pulledCount */ 1);
988     }
989 
990     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
991 
992     auto subscriptionStats = report.subscription_stats();
993     ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), maxSubs);
994     EXPECT_THAT(subscriptionStats.per_subscription_stats(),
995                 Not(Contains(Property(&PerSubscriptionStats::id, Eq(maxSubs + 1)))));
996 }
997 
TEST(StatsdStatsTest,TestSubscriptionStartedRemoveFinishedSubscription)998 TEST(StatsdStatsTest, TestSubscriptionStartedRemoveFinishedSubscription) {
999     StatsdStats stats;
1000 
1001     const int maxSubs = ShellSubscriber::getMaxSubscriptions();
1002 
1003     // Start max # of allowed subscriptions
1004     for (int id = 1; id <= maxSubs; id++) {
1005         stats.noteSubscriptionStarted(id, /* pushedCount */ 3, /* pulledCount */ 1);
1006     }
1007 
1008     // End subscription with id 5.
1009     stats.noteSubscriptionEnded(/* id */ 5);
1010 
1011     // Add one more subscription after we've added max # of subscriptions.
1012     // Subscription wth id 5 should be removed and the new subscription added here should be
1013     // accepted.
1014     stats.noteSubscriptionStarted(maxSubs + 1, /* pushedCount */ 3, /* pulledCount */ 1);
1015 
1016     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1017 
1018     auto subscriptionStats = report.subscription_stats();
1019     ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), maxSubs);
1020     EXPECT_THAT(subscriptionStats.per_subscription_stats(),
1021                 Not(Contains(Property(&PerSubscriptionStats::id, Eq(5)))));
1022     EXPECT_THAT(subscriptionStats.per_subscription_stats(),
1023                 Contains(Property(&PerSubscriptionStats::id, Eq(maxSubs + 1))));
1024 }
1025 
TEST(StatsdStatsTest,TestEnforceDimensionKeySizeLimit)1026 TEST(StatsdStatsTest, TestEnforceDimensionKeySizeLimit) {
1027     EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(-1),
1028               StatsdStats::kDimensionKeySizeHardLimitMin);
1029     EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(0),
1030               StatsdStats::kDimensionKeySizeHardLimitMin);
1031     EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(500),
1032               StatsdStats::kDimensionKeySizeHardLimitMin);
1033     EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(1000), 1000);
1034     EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(3500),
1035               StatsdStats::kDimensionKeySizeHardLimitMax);
1036 }
1037 
TEST(StatsdStatsTest,TestSocketLossStats)1038 TEST(StatsdStatsTest, TestSocketLossStats) {
1039     StatsdStats stats;
1040 
1041     const int maxLossEvents = StatsdStats::kMaxSocketLossStatsSize;
1042 
1043     // Note maxLossEvents + 1
1044     for (int eventId = 0; eventId <= maxLossEvents; eventId++) {
1045         SocketLossInfo info;
1046 
1047         info.uid = eventId;
1048         info.firstLossTsNanos = 10 * eventId;
1049         info.lastLossTsNanos = 10 * eventId + 1;
1050 
1051         info.atomIds.push_back(eventId * 10);
1052         info.errors.push_back(eventId * 20);
1053         info.counts.push_back(eventId * 30);
1054 
1055         stats.noteAtomSocketLoss(info);
1056     }
1057 
1058     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1059 
1060     auto socketLossStats = report.socket_loss_stats();
1061     ASSERT_EQ(socketLossStats.loss_stats_per_uid().size(), maxLossEvents);
1062 
1063     for (int i = 0; i < socketLossStats.loss_stats_per_uid().size(); i++) {
1064         const auto& info = report.socket_loss_stats().loss_stats_per_uid(i);
1065 
1066         // due to the very first one with id 0 is popped out from the list ids (index) start from 1
1067         const int index = i + 1;
1068 
1069         ASSERT_EQ(info.uid(), index);
1070         ASSERT_EQ(info.first_timestamp_nanos(), 10 * index);
1071         ASSERT_EQ(info.last_timestamp_nanos(), 10 * index + 1);
1072 
1073         ASSERT_EQ(info.atom_id_loss_stats().size(), 1);
1074 
1075         ASSERT_EQ(info.atom_id_loss_stats(0).atom_id(), index * 10);
1076         ASSERT_EQ(info.atom_id_loss_stats(0).error(), index * 20);
1077         ASSERT_EQ(info.atom_id_loss_stats(0).count(), index * 30);
1078     }
1079 }
1080 
TEST(StatsdStatsTest,TestSocketLossStatsOverflowCounter)1081 TEST(StatsdStatsTest, TestSocketLossStatsOverflowCounter) {
1082     StatsdStats stats;
1083 
1084     const int uidsCount = 5;
1085     const int lossEventCount = 5;
1086 
1087     for (int uid = 0; uid < uidsCount; uid++) {
1088         for (int eventId = 0; eventId < lossEventCount; eventId++) {
1089             SocketLossInfo info;
1090 
1091             info.uid = uid;
1092             info.firstLossTsNanos = 10 * eventId;
1093             info.lastLossTsNanos = 10 * eventId + 1;
1094             // the counter value will be accumulated
1095             info.overflowCounter = 1;
1096 
1097             info.atomIds.push_back(eventId * 10);
1098             info.errors.push_back(eventId * 20);
1099             info.counts.push_back(eventId * 30);
1100 
1101             stats.noteAtomSocketLoss(info);
1102         }
1103     }
1104     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1105 
1106     auto socketLossStatsOverflowCounters =
1107             report.socket_loss_stats().loss_stats_overflow_counters();
1108     ASSERT_EQ(socketLossStatsOverflowCounters.size(), uidsCount);
1109 
1110     for (int i = 0; i < socketLossStatsOverflowCounters.size(); i++) {
1111         const auto& counters = report.socket_loss_stats().loss_stats_overflow_counters(i);
1112 
1113         ASSERT_EQ(counters.uid(), i);
1114         ASSERT_EQ(counters.count(), lossEventCount);
1115     }
1116 }
1117 
TEST(StatsdStatsTest,TestSocketBatchReadStats)1118 TEST(StatsdStatsTest, TestSocketBatchReadStats) {
1119     unordered_map<int32_t, int32_t> empty;
1120     unordered_map<int32_t, int32_t> m1199 = {{1, 1}, {2, 1190}, {3, 8}};  // only 2 should show up
1121     unordered_map<int32_t, int32_t> m1200 = {{1, 1}, {2, 4}, {3, 8}};     // none should show up
1122     unordered_map<int32_t, int32_t> m120000 = {{1, 1000}, {2, 2000}, {3, 800}};  // all show up
1123     StatsdStats stats;
1124     stats.noteBatchSocketRead(1, 0, 0, 0, 0, empty);                           // bin 1
1125     stats.noteBatchSocketRead(2, 0, 0, 0, 0, empty);                           // bin 2
1126     stats.noteBatchSocketRead(2, 0, 0, 0, 0, empty);                           // bin 2
1127     stats.noteBatchSocketRead(4, 0, 0, 0, 0, empty);                           // bin 4
1128     stats.noteBatchSocketRead(5, 0, 0, 0, 0, empty);                           // bin 5
1129     stats.noteBatchSocketRead(9, 0, 0, 0, 0, empty);                           // bin 5
1130     stats.noteBatchSocketRead(9, 0, 0, 0, 0, empty);                           // bin 5
1131     stats.noteBatchSocketRead(10, 0, 0, 0, 0, empty);                          // bin 6
1132     stats.noteBatchSocketRead(19, 0, 0, 0, 0, empty);                          // bin 6
1133     stats.noteBatchSocketRead(30, 0, 0, 0, 0, empty);                          // bin 8
1134     stats.noteBatchSocketRead(32, 0, 0, 0, 0, empty);                          // bin 8
1135     stats.noteBatchSocketRead(39, 0, 0, 0, 0, empty);                          // bin 8
1136     stats.noteBatchSocketRead(90, 0, 0, 0, 0, empty);                          // bin 14
1137     stats.noteBatchSocketRead(99, 0, 0, 0, 0, empty);                          // bin 14
1138     stats.noteBatchSocketRead(100, 0, 0, 0, 0, empty);                         // bin 15
1139     stats.noteBatchSocketRead(100, 0, 0, 0, 0, empty);                         // bin 15
1140     stats.noteBatchSocketRead(199, 0, 0, 0, 0, empty);                         // bin 15
1141     stats.noteBatchSocketRead(200, 0, 0, 0, 0, empty);                         // bin 16
1142     stats.noteBatchSocketRead(299, 0, 0, 0, 0, empty);                         // bin 16
1143     stats.noteBatchSocketRead(999, 0, 0, 0, 0, empty);                         // bin 23
1144     stats.noteBatchSocketRead(1000, 0, 0, 0, 0, empty);                        // bin 24
1145     stats.noteBatchSocketRead(1199, 1, 2, 3, 4, m1199);                        // bin 24
1146     stats.noteBatchSocketRead(1200, 5, 6, 7, 8, m1200);                        // bin 25
1147     stats.noteBatchSocketRead(1800, 0, 0, 0, 0, empty);                        // bin 28
1148     stats.noteBatchSocketRead(1999, 0, 0, 0, 0, empty);                        // bin 28
1149     stats.noteBatchSocketRead(2000, 0, 0, 0, 0, empty);                        // bin 29
1150     stats.noteBatchSocketRead(120000, 10, INT64_MAX, 50, INT64_MAX, m120000);  // bin 29
1151 
1152     StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1153     EXPECT_THAT(report.socket_read_stats().batched_read_size(),
1154                 ElementsAre(0, 1, 2, 0, 1, 3, 2, 0, 3, 0, 0, 0, 0, 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, 1,
1155                             2, 1, 0, 0, 2, 2));
1156 
1157     // Check the large batch stats
1158     ASSERT_EQ(report.socket_read_stats().large_batch_read_stats_size(), 7);
1159     auto largeBatchStats = report.socket_read_stats().large_batch_read_stats(1);  // 1199
1160     EXPECT_EQ(largeBatchStats.total_atoms_read(), 1199);
1161     EXPECT_EQ(largeBatchStats.last_read_time_elapsed_ns(), 1);
1162     EXPECT_EQ(largeBatchStats.curr_read_time_elapsed_ns(), 2);
1163     EXPECT_EQ(largeBatchStats.min_atom_time_elapsed_ns(), 3);
1164     EXPECT_EQ(largeBatchStats.max_atom_time_elapsed_ns(), 4);
1165     ASSERT_EQ(largeBatchStats.atom_stats_size(), 1);
1166     EXPECT_EQ(largeBatchStats.atom_stats(0).atom_id(), 2);
1167     EXPECT_EQ(largeBatchStats.atom_stats(0).count(), 1190);
1168 
1169     largeBatchStats = report.socket_read_stats().large_batch_read_stats(2);  // 1200
1170     EXPECT_EQ(largeBatchStats.total_atoms_read(), 1200);
1171     EXPECT_EQ(largeBatchStats.last_read_time_elapsed_ns(), 5);
1172     EXPECT_EQ(largeBatchStats.curr_read_time_elapsed_ns(), 6);
1173     EXPECT_EQ(largeBatchStats.min_atom_time_elapsed_ns(), 7);
1174     EXPECT_EQ(largeBatchStats.max_atom_time_elapsed_ns(), 8);
1175     ASSERT_EQ(largeBatchStats.atom_stats_size(), 0);
1176 
1177     largeBatchStats = report.socket_read_stats().large_batch_read_stats(6);  // 120000
1178     EXPECT_EQ(largeBatchStats.total_atoms_read(), 120000);
1179     EXPECT_EQ(largeBatchStats.last_read_time_elapsed_ns(), 10);
1180     EXPECT_EQ(largeBatchStats.curr_read_time_elapsed_ns(), INT64_MAX);
1181     EXPECT_EQ(largeBatchStats.min_atom_time_elapsed_ns(), 50);
1182     EXPECT_EQ(largeBatchStats.max_atom_time_elapsed_ns(), INT64_MAX);
1183     ASSERT_EQ(largeBatchStats.atom_stats_size(), 3);
1184     EXPECT_EQ(largeBatchStats.atom_stats(0).atom_id(), 3);
1185     EXPECT_EQ(largeBatchStats.atom_stats(0).count(), 800);
1186     EXPECT_EQ(largeBatchStats.atom_stats(1).atom_id(), 2);
1187     EXPECT_EQ(largeBatchStats.atom_stats(1).count(), 2000);
1188     EXPECT_EQ(largeBatchStats.atom_stats(2).atom_id(), 1);
1189     EXPECT_EQ(largeBatchStats.atom_stats(2).count(), 1000);
1190 
1191     stats.reset();
1192     report = getStatsdStatsReport(stats, /* reset stats */ false);
1193     EXPECT_THAT(report.socket_read_stats().batched_read_size(),
1194                 AllOf(SizeIs(StatsdStats::kNumBinsInSocketBatchReadHistogram), Each(0)));
1195     ASSERT_EQ(report.socket_read_stats().large_batch_read_stats_size(), 0);
1196 }
1197 
TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap,TestGetAtomDimensionKeySizeLimits)1198 TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap, TestGetAtomDimensionKeySizeLimits) {
1199     const auto& [atomId, defaultHardLimit] = GetParam();
1200     EXPECT_EQ(StatsdStats::getAtomDimensionKeySizeLimits(atomId, defaultHardLimit),
1201               StatsdStats::kAtomDimensionKeySizeLimitMap.at(atomId));
1202 }
1203 
TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap,TestGetAtomDimensionKeySizeLimits)1204 TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap, TestGetAtomDimensionKeySizeLimits) {
1205     const auto& [atomId, defaultHardLimit] = GetParam();
1206     EXPECT_EQ(
1207             StatsdStats::getAtomDimensionKeySizeLimits(atomId, defaultHardLimit),
1208             (std::pair<size_t, size_t>(StatsdStats::kDimensionKeySizeSoftLimit, defaultHardLimit)));
1209 }
1210 
1211 }  // namespace statsd
1212 }  // namespace os
1213 }  // namespace android
1214 #else
1215 GTEST_LOG_(INFO) << "This test does nothing.\n";
1216 #endif
1217