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