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