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