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/metrics/EventMetricProducer.h"
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <stdio.h>
20 
21 #include <vector>
22 
23 #include "metrics_test_helper.h"
24 #include "stats_event.h"
25 #include "tests/statsd_test_util.h"
26 
27 using namespace testing;
28 using android::sp;
29 using std::set;
30 using std::unordered_map;
31 using std::vector;
32 
33 #ifdef __ANDROID__
34 
35 namespace android {
36 namespace os {
37 namespace statsd {
38 
39 namespace {
40 const ConfigKey kConfigKey(0, 12345);
41 const uint64_t protoHash = 0x1234567890;
42 
makeLogEvent(LogEvent * logEvent,int32_t atomId,int64_t timestampNs,string str,vector<uint8_t> * bytesField=nullptr)43 void makeLogEvent(LogEvent* logEvent, int32_t atomId, int64_t timestampNs, string str,
44                   vector<uint8_t>* bytesField = nullptr) {
45     AStatsEvent* statsEvent = AStatsEvent_obtain();
46     AStatsEvent_setAtomId(statsEvent, atomId);
47     AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
48     AStatsEvent_writeString(statsEvent, str.c_str());
49     if (bytesField != nullptr) {
50         AStatsEvent_writeByteArray(statsEvent, bytesField->data(), bytesField->size());
51     }
52 
53     parseStatsEventToLogEvent(statsEvent, logEvent);
54 }
55 
56 }  // anonymous namespace
57 
58 class EventMetricProducerTest : public ::testing::Test {
SetUp()59     void SetUp() override {
60         FlagProvider::getInstance().overrideFuncs(&isAtLeastSFuncTrue);
61     }
62 
TearDown()63     void TearDown() override {
64         FlagProvider::getInstance().resetOverrides();
65     }
66 };
67 
TEST_F(EventMetricProducerTest,TestNoCondition)68 TEST_F(EventMetricProducerTest, TestNoCondition) {
69     int64_t bucketStartTimeNs = 10000000000;
70     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
71     int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
72 
73     EventMetric metric;
74     metric.set_id(1);
75 
76     LogEvent event1(/*uid=*/0, /*pid=*/0);
77     CreateNoValuesLogEvent(&event1, 1 /*tagId*/, bucketStartTimeNs + 1);
78 
79     LogEvent event2(/*uid=*/0, /*pid=*/0);
80     CreateNoValuesLogEvent(&event2, 1 /*tagId*/, bucketStartTimeNs + 2);
81 
82     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
83     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
84 
85     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
86                                       wizard, protoHash, bucketStartTimeNs, provider);
87 
88     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
89     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
90 
91     // Check dump report content.
92     ProtoOutputStream output;
93     std::set<string> strSet;
94     eventProducer.onDumpReport(bucketStartTimeNs + 20, true /*include current partial bucket*/,
95                                true /*erase data*/, FAST, &strSet, &output);
96 
97     StatsLogReport report = outputStreamToProto(&output);
98     backfillAggregatedAtoms(&report);
99     EXPECT_TRUE(report.has_event_metrics());
100     ASSERT_EQ(2, report.event_metrics().data_size());
101     EXPECT_EQ(bucketStartTimeNs + 1, report.event_metrics().data(0).elapsed_timestamp_nanos());
102     EXPECT_EQ(bucketStartTimeNs + 2, report.event_metrics().data(1).elapsed_timestamp_nanos());
103 }
104 
TEST_F(EventMetricProducerTest,TestEventsWithNonSlicedCondition)105 TEST_F(EventMetricProducerTest, TestEventsWithNonSlicedCondition) {
106     int64_t bucketStartTimeNs = 10000000000;
107     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
108     int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
109 
110     EventMetric metric;
111     metric.set_id(1);
112     metric.set_condition(StringToId("SCREEN_ON"));
113 
114     LogEvent event1(/*uid=*/0, /*pid=*/0);
115     CreateNoValuesLogEvent(&event1, 1 /*tagId*/, bucketStartTimeNs + 1);
116 
117     LogEvent event2(/*uid=*/0, /*pid=*/0);
118     CreateNoValuesLogEvent(&event2, 1 /*tagId*/, bucketStartTimeNs + 10);
119 
120     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
121     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
122 
123     EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/,
124                                       {ConditionState::kUnknown}, wizard, protoHash,
125                                       bucketStartTimeNs, provider);
126 
127     eventProducer.onConditionChanged(true /*condition*/, bucketStartTimeNs);
128     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
129 
130     eventProducer.onConditionChanged(false /*condition*/, bucketStartTimeNs + 2);
131 
132     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
133 
134     // Check dump report content.
135     ProtoOutputStream output;
136     std::set<string> strSet;
137     eventProducer.onDumpReport(bucketStartTimeNs + 20, true /*include current partial bucket*/,
138                                true /*erase data*/, FAST, &strSet, &output);
139 
140     StatsLogReport report = outputStreamToProto(&output);
141     EXPECT_TRUE(report.has_event_metrics());
142     backfillAggregatedAtoms(&report);
143     ASSERT_EQ(1, report.event_metrics().data_size());
144     EXPECT_EQ(bucketStartTimeNs + 1, report.event_metrics().data(0).elapsed_timestamp_nanos());
145 }
146 
TEST_F(EventMetricProducerTest,TestEventsWithSlicedCondition)147 TEST_F(EventMetricProducerTest, TestEventsWithSlicedCondition) {
148     int64_t bucketStartTimeNs = 10000000000;
149     int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
150 
151     int tagId = 1;
152     int conditionTagId = 2;
153 
154     EventMetric metric;
155     metric.set_id(1);
156     metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
157     MetricConditionLink* link = metric.add_links();
158     link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
159     buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
160     buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
161 
162     LogEvent event1(/*uid=*/0, /*pid=*/0);
163     makeLogEvent(&event1, 1 /*tagId*/, bucketStartTimeNs + 1, "111");
164     ConditionKey key1;
165     key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {
166             getMockedDimensionKey(conditionTagId, 2, "111")};
167 
168     LogEvent event2(/*uid=*/0, /*pid=*/0);
169     makeLogEvent(&event2, 1 /*tagId*/, bucketStartTimeNs + 10, "222");
170     ConditionKey key2;
171     key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {
172             getMockedDimensionKey(conditionTagId, 2, "222")};
173 
174     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
175     // Condition is false for first event.
176     EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
177     // Condition is true for second event.
178     EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
179     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
180 
181     EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/,
182                                       {ConditionState::kUnknown}, wizard, protoHash,
183                                       bucketStartTimeNs, provider);
184 
185     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
186     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
187 
188     // Check dump report content.
189     ProtoOutputStream output;
190     std::set<string> strSet;
191     eventProducer.onDumpReport(bucketStartTimeNs + 20, true /*include current partial bucket*/,
192                                true /*erase data*/, FAST, &strSet, &output);
193 
194     StatsLogReport report = outputStreamToProto(&output);
195     backfillAggregatedAtoms(&report);
196     EXPECT_TRUE(report.has_event_metrics());
197     ASSERT_EQ(1, report.event_metrics().data_size());
198     EXPECT_EQ(bucketStartTimeNs + 10, report.event_metrics().data(0).elapsed_timestamp_nanos());
199 }
200 
TEST_F(EventMetricProducerTest,TestOneAtomTagAggregatedEvents)201 TEST_F(EventMetricProducerTest, TestOneAtomTagAggregatedEvents) {
202     int64_t bucketStartTimeNs = 10000000000;
203     int tagId = 1;
204 
205     EventMetric metric;
206     metric.set_id(1);
207 
208     LogEvent event1(/*uid=*/0, /*pid=*/0);
209     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111");
210     LogEvent event2(/*uid=*/0, /*pid=*/0);
211     makeLogEvent(&event2, tagId, bucketStartTimeNs + 20, "111");
212     LogEvent event3(/*uid=*/0, /*pid=*/0);
213     makeLogEvent(&event3, tagId, bucketStartTimeNs + 30, "111");
214 
215     LogEvent event4(/*uid=*/0, /*pid=*/0);
216     makeLogEvent(&event4, tagId, bucketStartTimeNs + 40, "222");
217 
218     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
219     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
220     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
221                                       wizard, protoHash, bucketStartTimeNs, provider);
222 
223     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
224     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
225     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event3);
226     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event4);
227 
228     // Check dump report content.
229     ProtoOutputStream output;
230     std::set<string> strSet;
231     eventProducer.onDumpReport(bucketStartTimeNs + 50, true /*include current partial bucket*/,
232                                true /*erase data*/, FAST, &strSet, &output);
233 
234     StatsLogReport report = outputStreamToProto(&output);
235     EXPECT_TRUE(report.has_event_metrics());
236     ASSERT_EQ(2, report.event_metrics().data_size());
237 
238     for (EventMetricData metricData : report.event_metrics().data()) {
239         AggregatedAtomInfo atomInfo = metricData.aggregated_atom_info();
240         if (atomInfo.elapsed_timestamp_nanos_size() == 1) {
241             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 40);
242         } else if (atomInfo.elapsed_timestamp_nanos_size() == 3) {
243             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 10);
244             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(1), bucketStartTimeNs + 20);
245             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(2), bucketStartTimeNs + 30);
246         } else {
247             FAIL();
248         }
249     }
250 }
251 
TEST_F(EventMetricProducerTest,TestBytesFieldAggregatedEvents)252 TEST_F(EventMetricProducerTest, TestBytesFieldAggregatedEvents) {
253     int64_t bucketStartTimeNs = 10000000000;
254     int tagId = 1;
255 
256     EventMetric metric;
257     metric.set_id(1);
258 
259     vector<uint8_t> bytesField1{10, 20, 30};
260     vector<uint8_t> bytesField2{10, 20, 30, 40};
261     LogEvent event1(/*uid=*/0, /*pid=*/0);
262     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111", &bytesField1);
263     LogEvent event2(/*uid=*/0, /*pid=*/0);
264     makeLogEvent(&event2, tagId, bucketStartTimeNs + 20, "111", &bytesField1);
265     LogEvent event3(/*uid=*/0, /*pid=*/0);
266     makeLogEvent(&event3, tagId, bucketStartTimeNs + 30, "111", &bytesField1);
267 
268     LogEvent event4(/*uid=*/0, /*pid=*/0);
269     makeLogEvent(&event4, tagId, bucketStartTimeNs + 40, "111", &bytesField2);
270 
271     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
272     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
273     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
274                                       wizard, protoHash, bucketStartTimeNs, provider);
275 
276     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
277     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
278     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event3);
279     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event4);
280 
281     // Check dump report content.
282     ProtoOutputStream output;
283     std::set<string> strSet;
284     eventProducer.onDumpReport(bucketStartTimeNs + 50, true /*include current partial bucket*/,
285                                true /*erase data*/, FAST, &strSet, &output);
286 
287     StatsLogReport report = outputStreamToProto(&output);
288     EXPECT_TRUE(report.has_event_metrics());
289     ASSERT_EQ(2, report.event_metrics().data_size());
290 
291     for (EventMetricData metricData : report.event_metrics().data()) {
292         AggregatedAtomInfo atomInfo = metricData.aggregated_atom_info();
293         if (atomInfo.elapsed_timestamp_nanos_size() == 1) {
294             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 40);
295         } else if (atomInfo.elapsed_timestamp_nanos_size() == 3) {
296             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 10);
297             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(1), bucketStartTimeNs + 20);
298             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(2), bucketStartTimeNs + 30);
299         } else {
300             FAIL();
301         }
302     }
303 }
304 
TEST_F(EventMetricProducerTest,TestTwoAtomTagAggregatedEvents)305 TEST_F(EventMetricProducerTest, TestTwoAtomTagAggregatedEvents) {
306     int64_t bucketStartTimeNs = 10000000000;
307     int tagId = 1;
308     int tagId2 = 0;
309 
310     EventMetric metric;
311     metric.set_id(1);
312 
313     LogEvent event1(/*uid=*/0, /*pid=*/0);
314     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111");
315     LogEvent event2(/*uid=*/0, /*pid=*/0);
316     makeLogEvent(&event2, tagId, bucketStartTimeNs + 20, "111");
317 
318     LogEvent event3(/*uid=*/0, /*pid=*/0);
319     makeLogEvent(&event3, tagId2, bucketStartTimeNs + 40, "222");
320 
321     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
322     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
323     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
324                                       wizard, protoHash, bucketStartTimeNs, provider);
325 
326     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
327     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
328     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event3);
329 
330     // Check dump report content.
331     ProtoOutputStream output;
332     std::set<string> strSet;
333     eventProducer.onDumpReport(bucketStartTimeNs + 50, true /*include current partial bucket*/,
334                                true /*erase data*/, FAST, &strSet, &output);
335 
336     StatsLogReport report = outputStreamToProto(&output);
337     EXPECT_TRUE(report.has_event_metrics());
338     ASSERT_EQ(2, report.event_metrics().data_size());
339 
340     for (EventMetricData metricData : report.event_metrics().data()) {
341         AggregatedAtomInfo atomInfo = metricData.aggregated_atom_info();
342         if (atomInfo.elapsed_timestamp_nanos_size() == 1) {
343             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 40);
344         } else if (atomInfo.elapsed_timestamp_nanos_size() == 2) {
345             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 10);
346             EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(1), bucketStartTimeNs + 20);
347         } else {
348             FAIL();
349         }
350     }
351 }
352 
TEST_F(EventMetricProducerTest,TestCorruptedDataReason_OnDumpReport)353 TEST_F(EventMetricProducerTest, TestCorruptedDataReason_OnDumpReport) {
354     int64_t bucketStartTimeNs = 10000000000;
355     int tagId = 1;
356 
357     EventMetric metric;
358     metric.set_id(1);
359 
360     LogEvent event1(/*uid=*/0, /*pid=*/0);
361     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111");
362 
363     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
364     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
365                                       nullptr, protoHash, bucketStartTimeNs, provider);
366 
367     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
368     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
369               MetricProducer::DataCorruptionSeverity::kNone);
370     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
371               MetricProducer::DataCorruptionSeverity::kNone);
372     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
373                                         MetricProducer::LostAtomType::kWhat);
374     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
375               MetricProducer::DataCorruptionSeverity::kResetOnDump);
376     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
377               MetricProducer::DataCorruptionSeverity::kNone);
378 
379     {
380         // Check dump report content.
381         ProtoOutputStream output;
382         eventProducer.onDumpReport(bucketStartTimeNs + 50, true /*include current partial bucket*/,
383                                    true /*erase data*/, FAST, nullptr, &output);
384 
385         StatsLogReport report = outputStreamToProto(&output);
386         EXPECT_TRUE(report.has_event_metrics());
387         EXPECT_EQ(1, report.event_metrics().data_size());
388         ASSERT_EQ(1, report.data_corrupted_reason_size());
389         ASSERT_EQ(DATA_CORRUPTED_SOCKET_LOSS, report.data_corrupted_reason()[0]);
390         EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
391                   MetricProducer::DataCorruptionSeverity::kNone);
392         EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
393                   MetricProducer::DataCorruptionSeverity::kNone);
394     }
395 
396     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
397     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
398               MetricProducer::DataCorruptionSeverity::kNone);
399     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
400               MetricProducer::DataCorruptionSeverity::kNone);
401     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
402                                         MetricProducer::LostAtomType::kWhat);
403     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
404               MetricProducer::DataCorruptionSeverity::kNone);
405     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
406               MetricProducer::DataCorruptionSeverity::kResetOnDump);
407 
408     {
409         // Check dump report content.
410         ProtoOutputStream output;
411         std::set<string> strSet;
412         eventProducer.onDumpReport(bucketStartTimeNs + 150, true /*include current partial bucket*/,
413                                    true /*erase data*/, FAST, &strSet, &output);
414 
415         StatsLogReport report = outputStreamToProto(&output);
416         EXPECT_TRUE(report.has_event_metrics());
417         EXPECT_EQ(1, report.event_metrics().data_size());
418         ASSERT_EQ(1, report.data_corrupted_reason_size());
419         ASSERT_EQ(DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW, report.data_corrupted_reason()[0]);
420         EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
421                   MetricProducer::DataCorruptionSeverity::kNone);
422         EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
423                   MetricProducer::DataCorruptionSeverity::kNone);
424     }
425 
426     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
427     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
428               MetricProducer::DataCorruptionSeverity::kNone);
429     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
430               MetricProducer::DataCorruptionSeverity::kNone);
431     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
432                                         MetricProducer::LostAtomType::kWhat);
433     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
434                                         MetricProducer::LostAtomType::kWhat);
435     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
436               MetricProducer::DataCorruptionSeverity::kResetOnDump);
437     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
438               MetricProducer::DataCorruptionSeverity::kResetOnDump);
439 
440     {
441         // Check dump report content.
442         ProtoOutputStream output;
443         std::set<string> strSet;
444         eventProducer.onDumpReport(bucketStartTimeNs + 250, true /*include current partial bucket*/,
445                                    true /*erase data*/, FAST, &strSet, &output);
446 
447         StatsLogReport report = outputStreamToProto(&output);
448         EXPECT_TRUE(report.has_event_metrics());
449         EXPECT_EQ(1, report.event_metrics().data_size());
450         EXPECT_EQ(2, report.data_corrupted_reason_size());
451         EXPECT_THAT(report.data_corrupted_reason(),
452                     ElementsAre(DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW, DATA_CORRUPTED_SOCKET_LOSS));
453         EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
454                   MetricProducer::DataCorruptionSeverity::kNone);
455         EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
456                   MetricProducer::DataCorruptionSeverity::kNone);
457     }
458 }
459 
TEST_F(EventMetricProducerTest,TestCorruptedDataReason_OnDropData)460 TEST_F(EventMetricProducerTest, TestCorruptedDataReason_OnDropData) {
461     int64_t bucketStartTimeNs = 10000000000;
462     int tagId = 1;
463 
464     EventMetric metric;
465     metric.set_id(1);
466 
467     LogEvent event1(/*uid=*/0, /*pid=*/0);
468     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111");
469 
470     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
471     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
472                                       nullptr, protoHash, bucketStartTimeNs, provider);
473     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
474 
475     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
476               MetricProducer::DataCorruptionSeverity::kNone);
477     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
478               MetricProducer::DataCorruptionSeverity::kNone);
479 
480     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
481                                         MetricProducer::LostAtomType::kWhat);
482 
483     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
484               MetricProducer::DataCorruptionSeverity::kResetOnDump);
485     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
486               MetricProducer::DataCorruptionSeverity::kNone);
487 
488     eventProducer.dropData(bucketStartTimeNs + 100);
489 
490     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
491               MetricProducer::DataCorruptionSeverity::kNone);
492     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
493               MetricProducer::DataCorruptionSeverity::kNone);
494 
495     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
496                                         MetricProducer::LostAtomType::kWhat);
497 
498     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
499               MetricProducer::DataCorruptionSeverity::kNone);
500     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
501               MetricProducer::DataCorruptionSeverity::kResetOnDump);
502 
503     eventProducer.dropData(bucketStartTimeNs + 200);
504 
505     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
506               MetricProducer::DataCorruptionSeverity::kNone);
507     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
508               MetricProducer::DataCorruptionSeverity::kNone);
509 
510     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
511                                         MetricProducer::LostAtomType::kWhat);
512     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
513                                         MetricProducer::LostAtomType::kWhat);
514 
515     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
516               MetricProducer::DataCorruptionSeverity::kResetOnDump);
517     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
518               MetricProducer::DataCorruptionSeverity::kResetOnDump);
519 
520     eventProducer.dropData(bucketStartTimeNs + 300);
521 
522     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
523               MetricProducer::DataCorruptionSeverity::kNone);
524     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
525               MetricProducer::DataCorruptionSeverity::kNone);
526 
527     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
528                                         MetricProducer::LostAtomType::kCondition);
529 
530     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
531               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
532     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
533               MetricProducer::DataCorruptionSeverity::kNone);
534 
535     eventProducer.dropData(bucketStartTimeNs + 400);
536 
537     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
538               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
539     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
540               MetricProducer::DataCorruptionSeverity::kNone);
541 
542     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
543                                         MetricProducer::LostAtomType::kCondition);
544 
545     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
546               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
547     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
548               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
549 
550     eventProducer.dropData(bucketStartTimeNs + 500);
551 
552     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
553               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
554     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
555               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
556 }
557 
TEST_F(EventMetricProducerTest,TestCorruptedDataReason_OnClearPastBuckets)558 TEST_F(EventMetricProducerTest, TestCorruptedDataReason_OnClearPastBuckets) {
559     int64_t bucketStartTimeNs = 10000000000;
560     int tagId = 1;
561 
562     EventMetric metric;
563     metric.set_id(1);
564 
565     LogEvent event1(/*uid=*/0, /*pid=*/0);
566     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111");
567 
568     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
569     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
570                                       nullptr, protoHash, bucketStartTimeNs, provider);
571     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
572 
573     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
574               MetricProducer::DataCorruptionSeverity::kNone);
575     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
576               MetricProducer::DataCorruptionSeverity::kNone);
577 
578     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
579                                         MetricProducer::LostAtomType::kWhat);
580 
581     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
582               MetricProducer::DataCorruptionSeverity::kResetOnDump);
583     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
584               MetricProducer::DataCorruptionSeverity::kNone);
585 
586     eventProducer.clearPastBuckets(bucketStartTimeNs + 100);
587 
588     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
589               MetricProducer::DataCorruptionSeverity::kNone);
590     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
591               MetricProducer::DataCorruptionSeverity::kNone);
592 
593     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
594                                         MetricProducer::LostAtomType::kWhat);
595 
596     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
597               MetricProducer::DataCorruptionSeverity::kNone);
598     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
599               MetricProducer::DataCorruptionSeverity::kResetOnDump);
600 
601     eventProducer.clearPastBuckets(bucketStartTimeNs + 200);
602 
603     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
604               MetricProducer::DataCorruptionSeverity::kNone);
605     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
606               MetricProducer::DataCorruptionSeverity::kNone);
607 
608     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
609                                         MetricProducer::LostAtomType::kWhat);
610     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
611                                         MetricProducer::LostAtomType::kWhat);
612 
613     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
614               MetricProducer::DataCorruptionSeverity::kResetOnDump);
615     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
616               MetricProducer::DataCorruptionSeverity::kResetOnDump);
617 
618     eventProducer.clearPastBuckets(bucketStartTimeNs + 300);
619 
620     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
621               MetricProducer::DataCorruptionSeverity::kNone);
622     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
623               MetricProducer::DataCorruptionSeverity::kNone);
624 
625     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
626                                         MetricProducer::LostAtomType::kCondition);
627 
628     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
629               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
630     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
631               MetricProducer::DataCorruptionSeverity::kNone);
632 
633     eventProducer.clearPastBuckets(bucketStartTimeNs + 400);
634 
635     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
636               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
637     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
638               MetricProducer::DataCorruptionSeverity::kNone);
639 
640     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
641                                         MetricProducer::LostAtomType::kCondition);
642 
643     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
644               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
645     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
646               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
647 
648     eventProducer.clearPastBuckets(bucketStartTimeNs + 500);
649 
650     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
651               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
652     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
653               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
654 }
655 
TEST_F(EventMetricProducerTest,TestCorruptedDataReason_UnrecoverableLossOfCondition)656 TEST_F(EventMetricProducerTest, TestCorruptedDataReason_UnrecoverableLossOfCondition) {
657     const int64_t bucketStartTimeNs = 10000000000;
658     const int tagId = 1;
659 
660     EventMetric metric;
661     metric.set_id(1);
662 
663     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
664     EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
665                                       nullptr, protoHash, bucketStartTimeNs, provider);
666 
667     LogEvent event1(/*uid=*/0, /*pid=*/0);
668     makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111");
669     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
670     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
671               MetricProducer::DataCorruptionSeverity::kNone);
672     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
673               MetricProducer::DataCorruptionSeverity::kNone);
674 
675     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_SOCKET_LOSS,
676                                         MetricProducer::LostAtomType::kCondition);
677     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
678               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
679     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
680               MetricProducer::DataCorruptionSeverity::kNone);
681 
682     {
683         // Check dump report content.
684         ProtoOutputStream output;
685         eventProducer.onDumpReport(bucketStartTimeNs + 50, true /*include current partial bucket*/,
686                                    true /*erase data*/, FAST, nullptr, &output);
687 
688         StatsLogReport report = outputStreamToProto(&output);
689         EXPECT_TRUE(report.has_event_metrics());
690         ASSERT_EQ(1, report.event_metrics().data_size());
691         EXPECT_EQ(1, report.data_corrupted_reason_size());
692         EXPECT_THAT(report.data_corrupted_reason(), ElementsAre(DATA_CORRUPTED_SOCKET_LOSS));
693         // confirm that unrecoverable loss status persist after dumpReport
694         EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
695                   MetricProducer::DataCorruptionSeverity::kUnrecoverable);
696         EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
697                   MetricProducer::DataCorruptionSeverity::kNone);
698     }
699 
700     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
701     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
702               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
703     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
704               MetricProducer::DataCorruptionSeverity::kNone);
705     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
706                                         MetricProducer::LostAtomType::kWhat);
707     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
708               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
709     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
710               MetricProducer::DataCorruptionSeverity::kResetOnDump);
711 
712     {
713         // Check dump report content.
714         ProtoOutputStream output;
715         eventProducer.onDumpReport(bucketStartTimeNs + 150, true /*include current partial bucket*/,
716                                    true /*erase data*/, FAST, nullptr, &output);
717 
718         StatsLogReport report = outputStreamToProto(&output);
719         EXPECT_TRUE(report.has_event_metrics());
720         EXPECT_EQ(1, report.event_metrics().data_size());
721         EXPECT_EQ(2, report.data_corrupted_reason_size());
722         EXPECT_THAT(report.data_corrupted_reason(),
723                     ElementsAre(DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW, DATA_CORRUPTED_SOCKET_LOSS));
724         // confirm that unrecoverable loss status persist after dumpReport
725         EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
726                   MetricProducer::DataCorruptionSeverity::kUnrecoverable);
727         // confirm that kResetOnDump loss status is reset after dumpReport
728         EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
729                   MetricProducer::DataCorruptionSeverity::kNone);
730     }
731 
732     eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
733     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
734               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
735     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
736               MetricProducer::DataCorruptionSeverity::kNone);
737     eventProducer.onMatchedLogEventLost(tagId, DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW,
738                                         MetricProducer::LostAtomType::kCondition);
739     EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
740               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
741     EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
742               MetricProducer::DataCorruptionSeverity::kUnrecoverable);
743 
744     {
745         // Check dump report content.
746         ProtoOutputStream output;
747         eventProducer.onDumpReport(bucketStartTimeNs + 150, true /*include current partial bucket*/,
748                                    true /*erase data*/, FAST, nullptr, &output);
749 
750         StatsLogReport report = outputStreamToProto(&output);
751         EXPECT_TRUE(report.has_event_metrics());
752         EXPECT_EQ(1, report.event_metrics().data_size());
753         EXPECT_EQ(2, report.data_corrupted_reason_size());
754         EXPECT_THAT(report.data_corrupted_reason(),
755                     ElementsAre(DATA_CORRUPTED_EVENT_QUEUE_OVERFLOW, DATA_CORRUPTED_SOCKET_LOSS));
756         // confirm that unrecoverable loss status persist after dumpReport
757         EXPECT_EQ(eventProducer.mDataCorruptedDueToSocketLoss,
758                   MetricProducer::DataCorruptionSeverity::kUnrecoverable);
759         EXPECT_EQ(eventProducer.mDataCorruptedDueToQueueOverflow,
760                   MetricProducer::DataCorruptionSeverity::kUnrecoverable);
761     }
762 }
763 
764 }  // namespace statsd
765 }  // namespace os
766 }  // namespace android
767 #else
768 GTEST_LOG_(INFO) << "This test does nothing.\n";
769 #endif
770