blob: 5e77ee0f0b0a119d429fed75f311c564a94e4fba [file] [log] [blame]
Yangster-mac20877162017-12-22 17:19:39 -08001// 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 <gtest/gtest.h>
16
17#include "src/StatsLogProcessor.h"
Yangster-macb8144812018-01-04 10:56:23 -080018#include "src/stats_log_util.h"
Yangster-mac20877162017-12-22 17:19:39 -080019#include "tests/statsd_test_util.h"
20
21#include <vector>
22
23namespace android {
24namespace os {
25namespace statsd {
26
27#ifdef __ANDROID__
Yangster-macb5bc7412018-01-06 23:17:45 -080028namespace {
Yangster-mac20877162017-12-22 17:19:39 -080029
30StatsdConfig CreateStatsdConfig() {
31 StatsdConfig config;
David Chen8faaa012018-02-28 15:54:36 -080032 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
33
Yangster-mac20877162017-12-22 17:19:39 -080034 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
35 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
36
37 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
38 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
39
40 *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
41 *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
42
43 auto appCrashMatcher = CreateProcessCrashAtomMatcher();
44 *config.add_atom_matcher() = appCrashMatcher;
45
46 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
47
48 auto isSyncingPredicate = CreateIsSyncingPredicate();
Yangster-mac93694462018-01-22 20:49:31 -080049 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
50 *syncDimension = CreateAttributionUidDimensions(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070051 util::SYNC_STATE_CHANGED, {Position::FIRST});
Yangster-mac93694462018-01-22 20:49:31 -080052 syncDimension->add_child()->set_field(2 /* name field*/);
Yangster-mac20877162017-12-22 17:19:39 -080053
54 auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
55 *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070056 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
Yangster-mac20877162017-12-22 17:19:39 -080057
58 *config.add_predicate() = screenIsOffPredicate;
59 *config.add_predicate() = isSyncingPredicate;
60 *config.add_predicate() = isInBackgroundPredicate;
61
62 auto combinationPredicate = config.add_predicate();
Yangster-mac94e197c2018-01-02 16:03:03 -080063 combinationPredicate->set_id(StringToId("combinationPredicate"));
Yangster-mac20877162017-12-22 17:19:39 -080064 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
65 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
66 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
67 addPredicateToPredicateCombination(isInBackgroundPredicate, combinationPredicate);
68
69 auto countMetric = config.add_count_metric();
Yangster-mac94e197c2018-01-02 16:03:03 -080070 countMetric->set_id(StringToId("AppCrashes"));
71 countMetric->set_what(appCrashMatcher.id());
72 countMetric->set_condition(combinationPredicate->id());
Yangster-mac20877162017-12-22 17:19:39 -080073 // The metric is dimensioning by uid only.
Yangster-mac468ff042018-01-17 12:26:34 -080074 *countMetric->mutable_dimensions_in_what() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070075 CreateDimensions(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
yro59cc24d2018-02-13 20:17:32 -080076 countMetric->set_bucket(FIVE_MINUTES);
Yangster-mac20877162017-12-22 17:19:39 -080077
78 // Links between crash atom and condition of app is in syncing.
79 auto links = countMetric->add_links();
Yangster-mac94e197c2018-01-02 16:03:03 -080080 links->set_condition(isSyncingPredicate.id());
Yangster-mac2c6dc472018-01-18 16:17:43 -080081 auto dimensionWhat = links->mutable_fields_in_what();
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070082 dimensionWhat->set_field(util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
Yangster-mac20877162017-12-22 17:19:39 -080083 dimensionWhat->add_child()->set_field(1); // uid field.
Yangster-mac93694462018-01-22 20:49:31 -080084 *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070085 util::SYNC_STATE_CHANGED, {Position::FIRST});
Yangster-mac20877162017-12-22 17:19:39 -080086
87 // Links between crash atom and condition of app is in background.
88 links = countMetric->add_links();
Yangster-mac94e197c2018-01-02 16:03:03 -080089 links->set_condition(isInBackgroundPredicate.id());
Yangster-mac2c6dc472018-01-18 16:17:43 -080090 dimensionWhat = links->mutable_fields_in_what();
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070091 dimensionWhat->set_field(util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
Yangster-mac20877162017-12-22 17:19:39 -080092 dimensionWhat->add_child()->set_field(1); // uid field.
Yangster-mac93694462018-01-22 20:49:31 -080093 auto dimensionCondition = links->mutable_fields_in_condition();
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070094 dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
Yangster-mac20877162017-12-22 17:19:39 -080095 dimensionCondition->add_child()->set_field(1); // uid field.
96 return config;
97}
Yangster-macb5bc7412018-01-06 23:17:45 -080098} // namespace
99
tsaichristine7747d372020-02-28 17:36:59 -0800100// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
101// we should use the real API which will clear the data after dump data is called.
102TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
103 auto config = CreateStatsdConfig();
104 uint64_t bucketStartTimeNs = 10000000000;
105 uint64_t bucketSizeNs =
106 TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
107
108 ConfigKey cfgKey;
109 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700110 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
tsaichristine7747d372020-02-28 17:36:59 -0800111 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
112
113 int appUid = 123;
114 auto crashEvent1 = CreateAppCrashEvent(bucketStartTimeNs + 1, appUid);
115 auto crashEvent2 = CreateAppCrashEvent(bucketStartTimeNs + 201, appUid);
116 auto crashEvent3 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 101, appUid);
117
118 auto crashEvent4 = CreateAppCrashEvent(bucketStartTimeNs + 51, appUid);
119 auto crashEvent5 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 299, appUid);
120 auto crashEvent6 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 2001, appUid);
121
122 auto crashEvent7 = CreateAppCrashEvent(bucketStartTimeNs + 16, appUid);
123 auto crashEvent8 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 249, appUid);
124
125 auto crashEvent9 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 351, appUid);
126 auto crashEvent10 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 2, appUid);
127
128 auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
129 bucketStartTimeNs + 2, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
130 auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
131 bucketStartTimeNs + 200, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
132 auto screenTurnedOnEvent2 =
133 CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
134 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
135
136 std::vector<int> attributionUids = {appUid, appUid + 1};
137 std::vector<string> attributionTags = {"App1", "GMSCoreModule1"};
138
139 auto syncOnEvent1 = CreateSyncStartEvent(bucketStartTimeNs + 50, attributionUids,
140 attributionTags, "ReadEmail");
141 auto syncOffEvent1 = CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 300, attributionUids,
142 attributionTags, "ReadEmail");
143 auto syncOnEvent2 = CreateSyncStartEvent(bucketStartTimeNs + bucketSizeNs + 2000,
144 attributionUids, attributionTags, "ReadDoc");
145
146 auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(bucketStartTimeNs + 15, appUid);
147 auto moveToForegroundEvent1 =
148 CreateMoveToForegroundEvent(bucketStartTimeNs + bucketSizeNs + 250, appUid);
149
150 auto moveToBackgroundEvent2 =
151 CreateMoveToBackgroundEvent(bucketStartTimeNs + bucketSizeNs + 350, appUid);
152 auto moveToForegroundEvent2 =
153 CreateMoveToForegroundEvent(bucketStartTimeNs + 2 * bucketSizeNs - 1, appUid);
154
155 /*
156 bucket #1 bucket #2
157
158
159 | | | | | | | | | | (crashEvents)
160 |-------------------------------------|-----------------------------------|---------
161
162 | | (MoveToBkground)
163
164 | | (MoveToForeground)
165
166 | | (SyncIsOn)
167 | (SyncIsOff)
168 | | (ScreenIsOn)
169 | (ScreenIsOff)
170 */
171 std::vector<std::unique_ptr<LogEvent>> events;
172 events.push_back(std::move(crashEvent1));
173 events.push_back(std::move(crashEvent2));
174 events.push_back(std::move(crashEvent3));
175 events.push_back(std::move(crashEvent4));
176 events.push_back(std::move(crashEvent5));
177 events.push_back(std::move(crashEvent6));
178 events.push_back(std::move(crashEvent7));
179 events.push_back(std::move(crashEvent8));
180 events.push_back(std::move(crashEvent9));
181 events.push_back(std::move(crashEvent10));
182 events.push_back(std::move(screenTurnedOnEvent));
183 events.push_back(std::move(screenTurnedOffEvent));
184 events.push_back(std::move(screenTurnedOnEvent2));
185 events.push_back(std::move(syncOnEvent1));
186 events.push_back(std::move(syncOffEvent1));
187 events.push_back(std::move(syncOnEvent2));
188 events.push_back(std::move(moveToBackgroundEvent1));
189 events.push_back(std::move(moveToForegroundEvent1));
190 events.push_back(std::move(moveToBackgroundEvent2));
191 events.push_back(std::move(moveToForegroundEvent2));
192
193 sortLogEventsByTimestamp(&events);
194
195 for (const auto& event : events) {
196 processor->OnLogEvent(event.get());
197 }
198 ConfigMetricsReportList reports;
199 vector<uint8_t> buffer;
200 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true, ADB_DUMP,
201 FAST, &buffer);
202 EXPECT_TRUE(buffer.size() > 0);
203 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
204 backfillDimensionPath(&reports);
205 backfillStringInReport(&reports);
206 backfillStartEndTimestamp(&reports);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700207 ASSERT_EQ(reports.reports_size(), 1);
208 ASSERT_EQ(reports.reports(0).metrics_size(), 1);
209 ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
210 ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
tsaichristine7747d372020-02-28 17:36:59 -0800211 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
212 auto data = reports.reports(0).metrics(0).count_metrics().data(0);
213 // Validate dimension value.
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700214 EXPECT_EQ(data.dimensions_in_what().field(), util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700215 ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
tsaichristine7747d372020-02-28 17:36:59 -0800216 // Uid field.
217 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
218 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
219}
220
221TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
222 auto config = CreateStatsdConfig();
223 uint64_t bucketStartTimeNs = 10000000000;
224 uint64_t bucketSizeNs =
225 TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
226
227 ConfigKey cfgKey;
228 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700229 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
tsaichristine7747d372020-02-28 17:36:59 -0800230 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
231
232 int appUid = 123;
233 auto crashEvent1 = CreateAppCrashEvent(bucketStartTimeNs + 1, appUid);
234 auto crashEvent2 = CreateAppCrashEvent(bucketStartTimeNs + 201, appUid);
235 auto crashEvent3 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 101, appUid);
236
237 auto crashEvent4 = CreateAppCrashEvent(bucketStartTimeNs + 51, appUid);
238 auto crashEvent5 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 299, appUid);
239 auto crashEvent6 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 2001, appUid);
240
241 auto crashEvent7 = CreateAppCrashEvent(bucketStartTimeNs + 16, appUid);
242 auto crashEvent8 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 249, appUid);
243
244 auto crashEvent9 = CreateAppCrashEvent(bucketStartTimeNs + bucketSizeNs + 351, appUid);
245 auto crashEvent10 = CreateAppCrashEvent(bucketStartTimeNs + 2 * bucketSizeNs - 2, appUid);
246
247 auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
248 bucketStartTimeNs + 2, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
249 auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
250 bucketStartTimeNs + 200, android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
251 auto screenTurnedOnEvent2 =
252 CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
253 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
254
255 std::vector<int> attributionUids = {appUid, appUid + 1};
256 std::vector<string> attributionTags = {"App1", "GMSCoreModule1"};
257
258 auto syncOnEvent1 = CreateSyncStartEvent(bucketStartTimeNs + 50, attributionUids,
259 attributionTags, "ReadEmail");
260 auto syncOffEvent1 = CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + 300, attributionUids,
261 attributionTags, "ReadEmail");
262 auto syncOnEvent2 = CreateSyncStartEvent(bucketStartTimeNs + bucketSizeNs + 2000,
263 attributionUids, attributionTags, "ReadDoc");
264
265 auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(bucketStartTimeNs + 15, appUid);
266 auto moveToForegroundEvent1 =
267 CreateMoveToForegroundEvent(bucketStartTimeNs + bucketSizeNs + 250, appUid);
268
269 auto moveToBackgroundEvent2 =
270 CreateMoveToBackgroundEvent(bucketStartTimeNs + bucketSizeNs + 350, appUid);
271 auto moveToForegroundEvent2 =
272 CreateMoveToForegroundEvent(bucketStartTimeNs + 2 * bucketSizeNs - 1, appUid);
273
274 /*
275 bucket #1 bucket #2
276
277
278 | | | | | | | | | | (crashEvents)
279 |-------------------------------------|-----------------------------------|---------
280
281 | | (MoveToBkground)
282
283 | | (MoveToForeground)
284
285 | | (SyncIsOn)
286 | (SyncIsOff)
287 | | (ScreenIsOn)
288 | (ScreenIsOff)
289 */
290 std::vector<std::unique_ptr<LogEvent>> events;
291 events.push_back(std::move(crashEvent1));
292 events.push_back(std::move(crashEvent2));
293 events.push_back(std::move(crashEvent3));
294 events.push_back(std::move(crashEvent4));
295 events.push_back(std::move(crashEvent5));
296 events.push_back(std::move(crashEvent6));
297 events.push_back(std::move(crashEvent7));
298 events.push_back(std::move(crashEvent8));
299 events.push_back(std::move(crashEvent9));
300 events.push_back(std::move(crashEvent10));
301 events.push_back(std::move(screenTurnedOnEvent));
302 events.push_back(std::move(screenTurnedOffEvent));
303 events.push_back(std::move(screenTurnedOnEvent2));
304 events.push_back(std::move(syncOnEvent1));
305 events.push_back(std::move(syncOffEvent1));
306 events.push_back(std::move(syncOnEvent2));
307 events.push_back(std::move(moveToBackgroundEvent1));
308 events.push_back(std::move(moveToForegroundEvent1));
309 events.push_back(std::move(moveToBackgroundEvent2));
310 events.push_back(std::move(moveToForegroundEvent2));
311
312 sortLogEventsByTimestamp(&events);
313
314 for (const auto& event : events) {
315 processor->OnLogEvent(event.get());
316 }
317 ConfigMetricsReportList reports;
318 vector<uint8_t> buffer;
319
320 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, ADB_DUMP,
321 FAST, &buffer);
322 EXPECT_TRUE(buffer.size() > 0);
323 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
324 backfillDimensionPath(&reports);
325 backfillStringInReport(&reports);
326 backfillStartEndTimestamp(&reports);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700327 ASSERT_EQ(reports.reports_size(), 1);
328 ASSERT_EQ(reports.reports(0).metrics_size(), 1);
329 ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
330 ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
tsaichristine7747d372020-02-28 17:36:59 -0800331 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
332 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
333 auto data = reports.reports(0).metrics(0).count_metrics().data(0);
334 // Validate dimension value.
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700335 EXPECT_EQ(data.dimensions_in_what().field(), util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700336 ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
tsaichristine7747d372020-02-28 17:36:59 -0800337 // Uid field.
338 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
339 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
340}
Yangster-mac20877162017-12-22 17:19:39 -0800341
342#else
343GTEST_LOG_(INFO) << "This test does nothing.\n";
344#endif
345
346} // namespace statsd
347} // namespace os
yro59cc24d2018-02-13 20:17:32 -0800348} // namespace android