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