1 // Copyright (C) 2019 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 <gtest/gtest.h>
16
17 #include <vector>
18
19 #include "flags/FlagProvider.h"
20 #include "src/StatsLogProcessor.h"
21 #include "src/state/StateTracker.h"
22 #include "src/stats_log_util.h"
23 #include "tests/statsd_test_util.h"
24
25 namespace android {
26 namespace os {
27 namespace statsd {
28
29 #ifdef __ANDROID__
30
31 // Setup for test fixture.
32 class EventMetricE2eTest : public ::testing::Test {
SetUp()33 void SetUp() override {
34 FlagProvider::getInstance().overrideFuncs(&isAtLeastSFuncTrue);
35 }
36
TearDown()37 void TearDown() override {
38 FlagProvider::getInstance().resetOverrides();
39 }
40
41 public:
42 void doTestRepeatedFieldsAndEmptyArrays();
43 void doTestMatchRepeatedFieldPositionFirst();
44 };
45
TEST_F(EventMetricE2eTest,TestEventMetricDataAggregated)46 TEST_F(EventMetricE2eTest, TestEventMetricDataAggregated) {
47 StatsdConfig config;
48
49 AtomMatcher wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
50 *config.add_atom_matcher() = wakelockAcquireMatcher;
51
52 EventMetric wakelockEventMetric =
53 createEventMetric("EventWakelockStateChanged", wakelockAcquireMatcher.id(), nullopt);
54 *config.add_event_metric() = wakelockEventMetric;
55
56 ConfigKey key(123, 987);
57 uint64_t bucketStartTimeNs = 10000000000; // 0:10
58 sp<StatsLogProcessor> processor =
59 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
60
61 // Initialize log events before update.
62 std::vector<std::unique_ptr<LogEvent>> events;
63
64 int app1Uid = 123;
65 vector<int> attributionUids = {app1Uid};
66 std::vector<string> attributionTags = {"App1"};
67
68 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
69 attributionUids, attributionTags, "wl1"));
70 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
71 attributionUids, attributionTags, "wl1"));
72 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 30 * NS_PER_SEC,
73 attributionUids, attributionTags, "wl2"));
74
75 // Send log events to StatsLogProcessor.
76 for (auto& event : events) {
77 processor->OnLogEvent(event.get());
78 }
79
80 uint64_t dumpTimeNs = bucketStartTimeNs + 100 * NS_PER_SEC;
81 ConfigMetricsReportList reports;
82 vector<uint8_t> buffer;
83 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
84 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
85 backfillStringInReport(&reports);
86 backfillStartEndTimestamp(&reports);
87 backfillAggregatedAtoms(&reports);
88 ASSERT_EQ(reports.reports_size(), 1);
89
90 ConfigMetricsReport report = reports.reports(0);
91 EXPECT_TRUE(report.has_estimated_data_bytes());
92 ASSERT_EQ(report.metrics_size(), 1);
93 StatsLogReport wakelockEventMetricReport = report.metrics(0);
94 EXPECT_TRUE(wakelockEventMetricReport.has_estimated_data_bytes());
95 EXPECT_EQ(wakelockEventMetricReport.metric_id(), wakelockEventMetric.id());
96 EXPECT_TRUE(wakelockEventMetricReport.has_event_metrics());
97 ASSERT_EQ(wakelockEventMetricReport.event_metrics().data_size(), 3);
98 auto data = wakelockEventMetricReport.event_metrics().data(0);
99 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 10 * NS_PER_SEC);
100 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl1");
101 data = wakelockEventMetricReport.event_metrics().data(1);
102 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 20 * NS_PER_SEC);
103 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl1");
104 data = wakelockEventMetricReport.event_metrics().data(2);
105 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 30 * NS_PER_SEC);
106 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl2");
107 }
108
TEST_F_GUARDED(EventMetricE2eTest,TestRepeatedFieldsAndEmptyArrays,__ANDROID_API_T__)109 TEST_F_GUARDED(EventMetricE2eTest, TestRepeatedFieldsAndEmptyArrays, __ANDROID_API_T__) {
110 StatsdConfig config;
111
112 AtomMatcher testAtomReportedAtomMatcher =
113 CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
114 *config.add_atom_matcher() = testAtomReportedAtomMatcher;
115
116 EventMetric testAtomReportedEventMetric =
117 createEventMetric("EventTestAtomReported", testAtomReportedAtomMatcher.id(), nullopt);
118 *config.add_event_metric() = testAtomReportedEventMetric;
119
120 ConfigKey key(123, 987);
121 uint64_t bucketStartTimeNs = 10000000000; // 0:10
122 sp<StatsLogProcessor> processor =
123 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
124
125 // Initialize log events before update.
126 std::vector<std::unique_ptr<LogEvent>> events;
127
128 vector<int> intArray = {3, 6};
129 vector<int64_t> longArray = {1000L, 10002L};
130 vector<float> floatArray = {0.3f, 0.09f};
131 vector<string> stringArray = {"str1", "str2"};
132 int boolArrayLength = 2;
133 bool boolArray[boolArrayLength];
134 boolArray[0] = 1;
135 boolArray[1] = 0;
136 vector<uint8_t> boolArrayVector = {1, 0};
137 vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF};
138
139 events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
140 bucketStartTimeNs + 10 * NS_PER_SEC, intArray, longArray, floatArray, stringArray,
141 boolArray, boolArrayLength, enumArray));
142 events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
143 bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
144 events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
145 bucketStartTimeNs + 30 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArray));
146
147 // Send log events to StatsLogProcessor.
148 for (auto& event : events) {
149 processor->OnLogEvent(event.get());
150 }
151
152 uint64_t dumpTimeNs = bucketStartTimeNs + 100 * NS_PER_SEC;
153 ConfigMetricsReportList reports;
154 vector<uint8_t> buffer;
155 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
156 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
157 backfillStringInReport(&reports);
158 backfillStartEndTimestamp(&reports);
159 backfillAggregatedAtoms(&reports);
160 ASSERT_EQ(reports.reports_size(), 1);
161
162 ConfigMetricsReport report = reports.reports(0);
163 ASSERT_EQ(report.metrics_size(), 1);
164 StatsLogReport testAtomEventMetricReport = report.metrics(0);
165 EXPECT_EQ(testAtomEventMetricReport.metric_id(), testAtomReportedEventMetric.id());
166 EXPECT_TRUE(testAtomEventMetricReport.has_event_metrics());
167 ASSERT_EQ(testAtomEventMetricReport.event_metrics().data_size(), 3);
168
169 EventMetricData data = testAtomEventMetricReport.event_metrics().data(0);
170 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 10 * NS_PER_SEC);
171 TestAtomReported atom = data.atom().test_atom_reported();
172 EXPECT_THAT(atom.repeated_int_field(), ElementsAreArray(intArray));
173 EXPECT_THAT(atom.repeated_long_field(), ElementsAreArray(longArray));
174 EXPECT_THAT(atom.repeated_float_field(), ElementsAreArray(floatArray));
175 EXPECT_THAT(atom.repeated_string_field(), ElementsAreArray(stringArray));
176 EXPECT_THAT(atom.repeated_boolean_field(), ElementsAreArray(boolArrayVector));
177 EXPECT_THAT(atom.repeated_enum_field(), ElementsAreArray(enumArray));
178
179 data = testAtomEventMetricReport.event_metrics().data(1);
180 atom = data.atom().test_atom_reported();
181 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 20 * NS_PER_SEC);
182 EXPECT_EQ(atom.repeated_int_field_size(), 0);
183 EXPECT_EQ(atom.repeated_long_field_size(), 0);
184 EXPECT_EQ(atom.repeated_float_field_size(), 0);
185 EXPECT_EQ(atom.repeated_string_field_size(), 0);
186 EXPECT_EQ(atom.repeated_boolean_field_size(), 0);
187 EXPECT_EQ(atom.repeated_enum_field_size(), 0);
188
189 data = testAtomEventMetricReport.event_metrics().data(2);
190 atom = data.atom().test_atom_reported();
191 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 30 * NS_PER_SEC);
192 EXPECT_EQ(atom.repeated_int_field_size(), 0);
193 EXPECT_EQ(atom.repeated_long_field_size(), 0);
194 EXPECT_EQ(atom.repeated_float_field_size(), 0);
195 EXPECT_EQ(atom.repeated_string_field_size(), 0);
196 EXPECT_EQ(atom.repeated_boolean_field_size(), 0);
197 EXPECT_THAT(atom.repeated_enum_field(), ElementsAreArray(enumArray));
198 }
199
TEST_F_GUARDED(EventMetricE2eTest,TestMatchRepeatedFieldPositionFirst,__ANDROID_API_T__)200 TEST_F_GUARDED(EventMetricE2eTest, TestMatchRepeatedFieldPositionFirst, __ANDROID_API_T__) {
201 StatsdConfig config;
202
203 AtomMatcher testAtomReportedStateFirstOnAtomMatcher =
204 CreateTestAtomRepeatedStateFirstOnAtomMatcher();
205 *config.add_atom_matcher() = testAtomReportedStateFirstOnAtomMatcher;
206
207 EventMetric testAtomReportedEventMetric = createEventMetric(
208 "EventTestAtomReported", testAtomReportedStateFirstOnAtomMatcher.id(), nullopt);
209 *config.add_event_metric() = testAtomReportedEventMetric;
210
211 ConfigKey key(123, 987);
212 uint64_t bucketStartTimeNs = 10000000000; // 0:10
213 sp<StatsLogProcessor> processor =
214 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
215
216 // Initialize log events before update.
217 std::vector<std::unique_ptr<LogEvent>> events;
218
219 vector<int> enumArrayNoMatch = {TestAtomReported::OFF, TestAtomReported::ON};
220 vector<int> enumArrayMatch = {TestAtomReported::ON, TestAtomReported::OFF};
221
222 events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
223 bucketStartTimeNs + 10 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayNoMatch));
224 events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
225 bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayMatch));
226 // No matching is done on an empty array.
227 events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
228 bucketStartTimeNs + 30 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
229
230 // Send log events to StatsLogProcessor.
231 for (auto& event : events) {
232 processor->OnLogEvent(event.get());
233 }
234
235 uint64_t dumpTimeNs = bucketStartTimeNs + 100 * NS_PER_SEC;
236 ConfigMetricsReportList reports;
237 vector<uint8_t> buffer;
238 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
239 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
240 backfillStringInReport(&reports);
241 backfillStartEndTimestamp(&reports);
242 backfillAggregatedAtoms(&reports);
243 ASSERT_EQ(reports.reports_size(), 1);
244
245 ConfigMetricsReport report = reports.reports(0);
246 ASSERT_EQ(report.metrics_size(), 1);
247 StatsLogReport testAtomEventMetricReport = report.metrics(0);
248 EXPECT_EQ(testAtomEventMetricReport.metric_id(), testAtomReportedEventMetric.id());
249 EXPECT_TRUE(testAtomEventMetricReport.has_event_metrics());
250 ASSERT_EQ(testAtomEventMetricReport.event_metrics().data_size(), 1);
251
252 EventMetricData data = testAtomEventMetricReport.event_metrics().data(0);
253 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 20 * NS_PER_SEC);
254 TestAtomReported atom = data.atom().test_atom_reported();
255 ASSERT_EQ(atom.repeated_int_field_size(), 0);
256 ASSERT_EQ(atom.repeated_long_field_size(), 0);
257 ASSERT_EQ(atom.repeated_float_field_size(), 0);
258 ASSERT_EQ(atom.repeated_string_field_size(), 0);
259 ASSERT_EQ(atom.repeated_boolean_field_size(), 0);
260 EXPECT_THAT(atom.repeated_enum_field(), ElementsAreArray(enumArrayMatch));
261 }
262
TEST_F(EventMetricE2eTest,TestDumpReportIncrementsReportNumber)263 TEST_F(EventMetricE2eTest, TestDumpReportIncrementsReportNumber) {
264 StatsdConfig config;
265
266 AtomMatcher testAtomReportedStateFirstOnAtomMatcher =
267 CreateTestAtomRepeatedStateFirstOnAtomMatcher();
268 *config.add_atom_matcher() = testAtomReportedStateFirstOnAtomMatcher;
269
270 EventMetric testAtomReportedEventMetric = createEventMetric(
271 "EventTestAtomReported", testAtomReportedStateFirstOnAtomMatcher.id(), nullopt);
272 *config.add_event_metric() = testAtomReportedEventMetric;
273
274 ConfigKey key(123, 987);
275 uint64_t configUpdateTime = 10000000000; // 0:10
276 sp<StatsLogProcessor> processor =
277 CreateStatsLogProcessor(configUpdateTime, configUpdateTime, config, key);
278
279 uint64_t dumpTimeNs = configUpdateTime + 100 * NS_PER_SEC;
280 ConfigMetricsReportList reports;
281 vector<uint8_t> buffer;
282 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
283 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
284 ASSERT_EQ(reports.reports_size(), 1);
285
286 EXPECT_EQ(reports.report_number(), 1);
287 EXPECT_EQ(reports.statsd_stats_id(), StatsdStats::getInstance().getStatsdStatsId());
288
289 buffer.clear();
290 processor->onDumpReport(key, dumpTimeNs + 100, true, true, ADB_DUMP, FAST, &buffer);
291 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
292 ASSERT_EQ(reports.reports_size(), 1);
293
294 EXPECT_EQ(reports.report_number(), 2);
295 EXPECT_EQ(reports.statsd_stats_id(), StatsdStats::getInstance().getStatsdStatsId());
296 }
297
TEST_F(EventMetricE2eTest,TestEventMetricSampling)298 TEST_F(EventMetricE2eTest, TestEventMetricSampling) {
299 // Set srand seed to make rand deterministic for testing.
300 srand(0);
301
302 StatsdConfig config;
303
304 AtomMatcher batterySaverOnMatcher = CreateBatterySaverModeStartAtomMatcher();
305 *config.add_atom_matcher() = batterySaverOnMatcher;
306
307 EventMetric batterySaverOnEventMetric =
308 createEventMetric("EventBatterySaverOn", batterySaverOnMatcher.id(), nullopt);
309 batterySaverOnEventMetric.set_sampling_percentage(50);
310 *config.add_event_metric() = batterySaverOnEventMetric;
311
312 ConfigKey key(123, 987);
313 uint64_t bucketStartTimeNs = 10000000000; // 0:10
314 sp<StatsLogProcessor> processor =
315 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
316
317 // Initialize log events before update.
318 std::vector<std::unique_ptr<LogEvent>> events;
319
320 for (int i = 0; i < 100; i++) {
321 events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + (10 + 10 * i) * NS_PER_SEC));
322 }
323
324 // Send log events to StatsLogProcessor.
325 for (auto& event : events) {
326 processor->OnLogEvent(event.get());
327 }
328
329 uint64_t dumpTimeNs = bucketStartTimeNs + 2000 * NS_PER_SEC;
330 ConfigMetricsReportList reports;
331 vector<uint8_t> buffer;
332 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
333 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
334 backfillStringInReport(&reports);
335 backfillStartEndTimestamp(&reports);
336 backfillAggregatedAtoms(&reports);
337 ASSERT_EQ(reports.reports_size(), 1);
338
339 ConfigMetricsReport report = reports.reports(0);
340 ASSERT_EQ(report.metrics_size(), 1);
341 StatsLogReport metricReport = report.metrics(0);
342 EXPECT_EQ(metricReport.metric_id(), batterySaverOnEventMetric.id());
343 EXPECT_TRUE(metricReport.has_event_metrics());
344 ASSERT_EQ(metricReport.event_metrics().data_size(), 46);
345 }
346
347 #else
348 GTEST_LOG_(INFO) << "This test does nothing.\n";
349 #endif
350
351 } // namespace statsd
352 } // namespace os
353 } // namespace android
354