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