blob: 934b95101fed75f8bd6edb4679cebbb76239607a [file] [log] [blame]
Yangster13fb7e42018-03-07 17:30:49 -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"
18#include "src/stats_log_util.h"
19#include "tests/statsd_test_util.h"
20
21#include <vector>
22
23namespace android {
24namespace os {
25namespace statsd {
26
27#ifdef __ANDROID__
28
29namespace {
30
31StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
32 DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
33 StatsdConfig config;
David Chen8faaa012018-02-28 15:54:36 -080034 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
Yangster13fb7e42018-03-07 17:30:49 -080035 *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
36 *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
37 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
38 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
39 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
40 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
41
42 auto scheduledJobPredicate = CreateScheduledJobPredicate();
43 auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
44 dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
45 dimensions->add_child()->set_field(2); // job name field.
46
47 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
48
49 auto isSyncingPredicate = CreateIsSyncingPredicate();
50 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
51 *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
52 {Position::FIRST});
53 if (addExtraDimensionInCondition) {
54 syncDimension->add_child()->set_field(2 /* name field*/);
55 }
56
57 *config.add_predicate() = scheduledJobPredicate;
58 *config.add_predicate() = screenIsOffPredicate;
59 *config.add_predicate() = isSyncingPredicate;
60 auto combinationPredicate = config.add_predicate();
61 combinationPredicate->set_id(StringToId("CombinationPredicate"));
62 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
63 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
64 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
65
66 auto metric = config.add_duration_metric();
67 metric->set_bucket(FIVE_MINUTES);
68 metric->set_id(StringToId("scheduledJob"));
69 metric->set_what(scheduledJobPredicate.id());
70 metric->set_condition(combinationPredicate->id());
71 metric->set_aggregation_type(aggregationType);
72 auto dimensionWhat = metric->mutable_dimensions_in_what();
73 dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED);
74 dimensionWhat->add_child()->set_field(2); // job name field.
75 *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
76 android::util::SYNC_STATE_CHANGED, {Position::FIRST});
77 return config;
78}
79
80} // namespace
81
82TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition) {
83 for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : { true, false }) {
84 for (auto aggregationType : {DurationMetric::MAX_SPARSE, DurationMetric::SUM}) {
85 ConfigKey cfgKey;
86 auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition(
87 aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension);
88 int64_t bucketStartTimeNs = 10000000000;
89 int64_t bucketSizeNs =
90 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
91
92 auto processor = CreateStatsLogProcessor(
Yangster-mac15f6bbc2018-04-08 11:52:26 -070093 bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
Yangster13fb7e42018-03-07 17:30:49 -080094 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
95 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
96
97 std::vector<AttributionNodeInternal> attributions1 = {
98 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
99 CreateAttribution(222, "GMSCoreModule2")};
100
101 std::vector<AttributionNodeInternal> attributions2 = {
102 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
103 CreateAttribution(555, "GMSCoreModule2")};
104
105 std::vector<std::unique_ptr<LogEvent>> events;
106
107 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
108 bucketStartTimeNs + 11));
109 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
110 bucketStartTimeNs + 40));
111
112 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
113 bucketStartTimeNs + 102));
114 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
115 bucketStartTimeNs + 450));
116
117 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
118 bucketStartTimeNs + 650));
119 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
120 bucketStartTimeNs + bucketSizeNs + 100));
121
122 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
123 bucketStartTimeNs + bucketSizeNs + 640));
124 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
125 bucketStartTimeNs + bucketSizeNs + 650));
126
127 events.push_back(CreateStartScheduledJobEvent(
128 {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2));
129 events.push_back(CreateFinishScheduledJobEvent(
130 {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101));
131
132 events.push_back(CreateStartScheduledJobEvent(
133 {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201));
134 events.push_back(CreateFinishScheduledJobEvent(
135 {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500));
136
137 events.push_back(CreateStartScheduledJobEvent(
138 {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600));
139 events.push_back(CreateFinishScheduledJobEvent(
140 {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850));
141
142 events.push_back(CreateStartScheduledJobEvent(
143 {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600));
144 events.push_back(CreateFinishScheduledJobEvent(
145 {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900));
146
147 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
148 bucketStartTimeNs + 10));
149 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
150 bucketStartTimeNs + 50));
151
152 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
153 bucketStartTimeNs + 200));
154 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
155 bucketStartTimeNs + bucketSizeNs + 300));
156
157 events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc",
158 bucketStartTimeNs + 400));
159 events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
160 bucketStartTimeNs + bucketSizeNs - 1));
161
162 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
163 bucketStartTimeNs + 401));
164 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
165 bucketStartTimeNs + bucketSizeNs + 700));
166
167 sortLogEventsByTimestamp(&events);
168
169 for (const auto& event : events) {
170 processor->OnLogEvent(event.get());
171 }
172
173 ConfigMetricsReportList reports;
174 vector<uint8_t> buffer;
Chenjie Yue36018b2018-04-16 15:18:30 -0700175 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
176 ADB_DUMP, &buffer);
Yangster13fb7e42018-03-07 17:30:49 -0800177 EXPECT_TRUE(buffer.size() > 0);
178 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
179
180 EXPECT_EQ(reports.reports_size(), 1);
181 EXPECT_EQ(reports.reports(0).metrics_size(), 1);
182 StatsLogReport::DurationMetricDataWrapper metrics;
183 sortMetricDataByDimensionsValue(
184 reports.reports(0).metrics(0).duration_metrics(), &metrics);
185 if (aggregationType == DurationMetric::SUM) {
186 EXPECT_EQ(metrics.data_size(), 4);
187 auto data = metrics.data(0);
188 EXPECT_EQ(data.dimensions_in_what().field(),
189 android::util::SCHEDULED_JOB_STATE_CHANGED);
190 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
191 2); // job name field
192 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
193 "job0"); // job name
194 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
195 android::util::SYNC_STATE_CHANGED, 111, "App1");
196 EXPECT_EQ(data.bucket_info_size(), 1);
197 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11);
198 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
199 bucketStartTimeNs);
200 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
201 bucketStartTimeNs + bucketSizeNs);
202
203
204 data = metrics.data(1);
205 EXPECT_EQ(data.dimensions_in_what().field(),
206 android::util::SCHEDULED_JOB_STATE_CHANGED);
207 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
208 2); // job name field
209 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
210 "job1"); // job name
211 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
212 android::util::SYNC_STATE_CHANGED, 333, "App2");
213 EXPECT_EQ(data.bucket_info_size(), 1);
214 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10);
215 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
216 bucketStartTimeNs + bucketSizeNs);
217 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
218 bucketStartTimeNs + 2 * bucketSizeNs);
219
220 data = metrics.data(2);
221 EXPECT_EQ(data.dimensions_in_what().field(),
222 android::util::SCHEDULED_JOB_STATE_CHANGED);
223 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
224 2); // job name field
225 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
226 "job2"); // job name
227 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
228 android::util::SYNC_STATE_CHANGED, 111, "App1");
229 EXPECT_EQ(data.bucket_info_size(), 2);
230 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
231 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
232 bucketStartTimeNs + bucketSizeNs);
233 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 600);
234 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
235 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
236 bucketStartTimeNs + bucketSizeNs);
237 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
238 bucketStartTimeNs + 2 * bucketSizeNs);
239
240 data = metrics.data(3);
241 EXPECT_EQ(data.dimensions_in_what().field(),
242 android::util::SCHEDULED_JOB_STATE_CHANGED);
243 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
244 2); // job name field
245 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
246 "job2"); // job name
247 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
248 android::util::SYNC_STATE_CHANGED, 333, "App2");
249 EXPECT_EQ(data.bucket_info_size(), 2);
250 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 600);
251 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
252 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
253 bucketStartTimeNs + bucketSizeNs);
254 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100 + 650 - 640);
255 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
256 bucketStartTimeNs + bucketSizeNs);
257 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
258 bucketStartTimeNs + 2 * bucketSizeNs);
259 } else {
260 EXPECT_EQ(metrics.data_size(), 4);
261 auto data = metrics.data(0);
262 EXPECT_EQ(data.dimensions_in_what().field(),
263 android::util::SCHEDULED_JOB_STATE_CHANGED);
264 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
265 2); // job name field
266 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
267 "job0"); // job name
268 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
269 android::util::SYNC_STATE_CHANGED, 111, "App1");
270 EXPECT_EQ(data.bucket_info_size(), 1);
271 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11);
272 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
273 bucketStartTimeNs);
274 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
275 bucketStartTimeNs + bucketSizeNs);
276
277 data = metrics.data(1);
278 EXPECT_EQ(data.dimensions_in_what().field(),
279 android::util::SCHEDULED_JOB_STATE_CHANGED);
280 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
281 2); // job name field
282 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
283 "job1"); // job name
284 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
285 android::util::SYNC_STATE_CHANGED, 333, "App2");
286 EXPECT_EQ(data.bucket_info_size(), 1);
287 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10);
288 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
289 bucketStartTimeNs + bucketSizeNs);
290 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
291 bucketStartTimeNs + 2 * bucketSizeNs);
292
293 data = metrics.data(2);
294 EXPECT_EQ(data.dimensions_in_what().field(),
295 android::util::SCHEDULED_JOB_STATE_CHANGED);
296 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
297 2); // job name field
298 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
299 "job2"); // job name
300 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
301 android::util::SYNC_STATE_CHANGED, 111, "App1");
302 EXPECT_EQ(data.bucket_info_size(), 2);
303 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
304 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
305 bucketStartTimeNs + bucketSizeNs);
306 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201);
307 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
308 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
309 bucketStartTimeNs + bucketSizeNs);
310 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
311 bucketStartTimeNs + 2 * bucketSizeNs);
312
313 data = metrics.data(3);
314 EXPECT_EQ(data.dimensions_in_what().field(),
315 android::util::SCHEDULED_JOB_STATE_CHANGED);
316 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(),
317 2); // job name field
318 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
319 "job2"); // job name
320 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
321 android::util::SYNC_STATE_CHANGED, 333, "App2");
322 EXPECT_EQ(data.bucket_info_size(), 2);
323 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401);
324 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
325 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
326 bucketStartTimeNs + bucketSizeNs);
327 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 110);
328 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
329 bucketStartTimeNs + bucketSizeNs);
330 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
331 bucketStartTimeNs + 2 * bucketSizeNs);
332 }
333 }
334 }
335}
336
337namespace {
338
339StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition(
340 DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) {
341 StatsdConfig config;
David Chen8faaa012018-02-28 15:54:36 -0800342 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
Yangster13fb7e42018-03-07 17:30:49 -0800343 *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
344 *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
345 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
346 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
347 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
348 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
349
350 auto scheduledJobPredicate = CreateScheduledJobPredicate();
351 auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
352 *dimensions = CreateAttributionUidDimensions(
353 android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
354 dimensions->add_child()->set_field(2); // job name field.
355
356 auto isSyncingPredicate = CreateIsSyncingPredicate();
357 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
358 *syncDimension = CreateAttributionUidDimensions(
359 android::util::SYNC_STATE_CHANGED, {Position::FIRST});
360 if (addExtraDimensionInCondition) {
361 syncDimension->add_child()->set_field(2 /* name field*/);
362 }
363
364 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
365
366 *config.add_predicate() = scheduledJobPredicate;
367 *config.add_predicate() = screenIsOffPredicate;
368 *config.add_predicate() = isSyncingPredicate;
369 auto combinationPredicate = config.add_predicate();
370 combinationPredicate->set_id(StringToId("CombinationPredicate"));
371 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
372 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
373 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
374
375 auto metric = config.add_duration_metric();
376 metric->set_bucket(FIVE_MINUTES);
377 metric->set_id(StringToId("scheduledJob"));
378 metric->set_what(scheduledJobPredicate.id());
379 metric->set_condition(combinationPredicate->id());
380 metric->set_aggregation_type(aggregationType);
381 *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
382 android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
383
384 auto links = metric->add_links();
385 links->set_condition(isSyncingPredicate.id());
386 *links->mutable_fields_in_what() =
387 CreateAttributionUidDimensions(
388 android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
389 *links->mutable_fields_in_condition() =
390 CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
391 return config;
392}
393
394} // namespace
395
396TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition) {
397 for (bool isFullLink : {true, false}) {
398 for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
399 ConfigKey cfgKey;
400 auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition(
401 aggregationType, !isFullLink);
402 int64_t bucketStartTimeNs = 10000000000;
403 int64_t bucketSizeNs =
404 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
405
406 auto processor = CreateStatsLogProcessor(
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700407 bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
Yangster13fb7e42018-03-07 17:30:49 -0800408 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
409 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
410
411 std::vector<AttributionNodeInternal> attributions1 = {
412 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
413 CreateAttribution(222, "GMSCoreModule2")};
414
415 std::vector<AttributionNodeInternal> attributions2 = {
416 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
417 CreateAttribution(555, "GMSCoreModule2")};
418
419 std::vector<AttributionNodeInternal> attributions3 = {
420 CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
421 CreateAttribution(555, "GMSCoreModule2")};
422
423 std::vector<std::unique_ptr<LogEvent>> events;
424
425 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
426 bucketStartTimeNs + 55));
427 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
428 bucketStartTimeNs + 120));
429 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
430 bucketStartTimeNs + 121));
431 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
432 bucketStartTimeNs + 450));
433
434 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
435 bucketStartTimeNs + 501));
436 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
437 bucketStartTimeNs + bucketSizeNs + 100));
438
439 events.push_back(CreateStartScheduledJobEvent(
440 {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
441 events.push_back(CreateFinishScheduledJobEvent(
442 {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
443
444 events.push_back(CreateStartScheduledJobEvent(
445 {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
446 events.push_back(CreateFinishScheduledJobEvent(
447 {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
448 events.push_back(CreateStartScheduledJobEvent(
449 {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
450 events.push_back(CreateFinishScheduledJobEvent(
451 {CreateAttribution(333, "App2")}, "job2",
452 bucketStartTimeNs + bucketSizeNs + 850));
453
454 events.push_back(
455 CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
456 bucketStartTimeNs + bucketSizeNs - 2));
457 events.push_back(
458 CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
459 bucketStartTimeNs + bucketSizeNs + 900));
460
461 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
462 bucketStartTimeNs + 50));
463 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
464 bucketStartTimeNs + 110));
465
466 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
467 bucketStartTimeNs + 300));
468 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
469 bucketStartTimeNs + bucketSizeNs + 700));
470 events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
471 bucketStartTimeNs + 400));
472 events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
473 bucketStartTimeNs + bucketSizeNs - 1));
474
475 events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
476 bucketStartTimeNs + 550));
477 events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
478 bucketStartTimeNs + 800));
479 events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
480 bucketStartTimeNs + bucketSizeNs - 1));
481 events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
482 bucketStartTimeNs + bucketSizeNs + 700));
483
484 sortLogEventsByTimestamp(&events);
485
486 for (const auto& event : events) {
487 processor->OnLogEvent(event.get());
488 }
489
490 ConfigMetricsReportList reports;
491 vector<uint8_t> buffer;
Yangster-mace68f3a52018-04-04 00:01:43 -0700492 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
Chenjie Yue36018b2018-04-16 15:18:30 -0700493 ADB_DUMP, &buffer);
Yangster13fb7e42018-03-07 17:30:49 -0800494 EXPECT_TRUE(buffer.size() > 0);
495 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
496
497 EXPECT_EQ(reports.reports_size(), 1);
498 EXPECT_EQ(reports.reports(0).metrics_size(), 1);
499 StatsLogReport::DurationMetricDataWrapper metrics;
500 sortMetricDataByDimensionsValue(
501 reports.reports(0).metrics(0).duration_metrics(), &metrics);
502
503 if (aggregationType == DurationMetric::SUM) {
504 EXPECT_EQ(metrics.data_size(), 3);
505 auto data = metrics.data(0);
506 ValidateAttributionUidDimension(
507 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
508 EXPECT_EQ(data.bucket_info_size(), 1);
509 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
510 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
511 bucketStartTimeNs);
512 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
513 bucketStartTimeNs + bucketSizeNs);
514
515 data = metrics.data(1);
516 ValidateAttributionUidDimension(
517 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
518 EXPECT_EQ(data.bucket_info_size(), 2);
519 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
520 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
521 bucketStartTimeNs + bucketSizeNs);
522 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600);
523 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
524 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
525 bucketStartTimeNs + bucketSizeNs);
526 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
527 bucketStartTimeNs + 2 * bucketSizeNs);
528
529 data = metrics.data(2);
530 ValidateAttributionUidDimension(
531 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
532 EXPECT_EQ(data.bucket_info_size(), 2);
533 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1);
534 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
535 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
536 bucketStartTimeNs + bucketSizeNs);
537 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
538 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
539 bucketStartTimeNs + bucketSizeNs);
540 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
541 bucketStartTimeNs + 2 * bucketSizeNs);
542 } else {
543 EXPECT_EQ(metrics.data_size(), 3);
544 auto data = metrics.data(0);
545 ValidateAttributionUidDimension(
546 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
547 EXPECT_EQ(data.bucket_info_size(), 1);
548 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
549 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
550 bucketStartTimeNs);
551 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
552 bucketStartTimeNs + bucketSizeNs);
553
554 data = metrics.data(1);
555 ValidateAttributionUidDimension(
556 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
557 EXPECT_EQ(data.bucket_info_size(), 2);
558 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
559 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
560 bucketStartTimeNs + bucketSizeNs);
561 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300);
562 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
563 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
564 bucketStartTimeNs + bucketSizeNs);
565 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
566 bucketStartTimeNs + 2 * bucketSizeNs);
567
568 data = metrics.data(2);
569 ValidateAttributionUidDimension(
570 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
571 EXPECT_EQ(data.bucket_info_size(), 1);
572 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101);
573 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
574 bucketStartTimeNs + bucketSizeNs);
575 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
576 bucketStartTimeNs + 2 * bucketSizeNs);
577 }
578 }
579 }
580}
581
582namespace {
583
584StatsdConfig CreateDurationMetricConfig_PartialLink_AND_CombinationCondition(
585 DurationMetric::AggregationType aggregationType) {
586 StatsdConfig config;
David Chen8faaa012018-02-28 15:54:36 -0800587 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
Yangster13fb7e42018-03-07 17:30:49 -0800588 *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
589 *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
590 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
591 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
592 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
593 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
594
595 auto scheduledJobPredicate = CreateScheduledJobPredicate();
596 auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions();
597 *dimensions = CreateAttributionUidDimensions(
598 android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
599 dimensions->add_child()->set_field(2); // job name field.
600
601 auto isSyncingPredicate = CreateIsSyncingPredicate();
602 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
603 *syncDimension = CreateAttributionUidDimensions(
604 android::util::SYNC_STATE_CHANGED, {Position::FIRST});
605 syncDimension->add_child()->set_field(2 /* name field*/);
606
607 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
608
609 *config.add_predicate() = scheduledJobPredicate;
610 *config.add_predicate() = screenIsOffPredicate;
611 *config.add_predicate() = isSyncingPredicate;
612 auto combinationPredicate = config.add_predicate();
613 combinationPredicate->set_id(StringToId("CombinationPredicate"));
614 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
615 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
616 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
617
618 auto metric = config.add_duration_metric();
619 metric->set_bucket(FIVE_MINUTES);
620 metric->set_id(StringToId("scheduledJob"));
621 metric->set_what(scheduledJobPredicate.id());
622 metric->set_condition(combinationPredicate->id());
623 metric->set_aggregation_type(aggregationType);
624 *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
625 android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
626 *metric->mutable_dimensions_in_condition() = *syncDimension;
627
628
629 auto links = metric->add_links();
630 links->set_condition(isSyncingPredicate.id());
631 *links->mutable_fields_in_what() =
632 CreateAttributionUidDimensions(
633 android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
634 *links->mutable_fields_in_condition() =
635 CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
636 return config;
637}
638
639} // namespace
640
641TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition) {
642 for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
643 ConfigKey cfgKey;
644 auto config =
645 CreateDurationMetricConfig_PartialLink_AND_CombinationCondition(aggregationType);
646 int64_t bucketStartTimeNs = 10000000000;
647 int64_t bucketSizeNs =
648 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
649
650 auto processor = CreateStatsLogProcessor(
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700651 bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
Yangster13fb7e42018-03-07 17:30:49 -0800652 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
653 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
654
655 std::vector<AttributionNodeInternal> attributions1 = {
656 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
657 CreateAttribution(222, "GMSCoreModule2")};
658
659 std::vector<AttributionNodeInternal> attributions2 = {
660 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
661 CreateAttribution(555, "GMSCoreModule2")};
662
663 std::vector<AttributionNodeInternal> attributions3 = {
664 CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"),
665 CreateAttribution(555, "GMSCoreModule2")};
666
667 std::vector<std::unique_ptr<LogEvent>> events;
668
669 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
670 bucketStartTimeNs + 55));
671 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
672 bucketStartTimeNs + 120));
673 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
674 bucketStartTimeNs + 121));
675 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
676 bucketStartTimeNs + 450));
677
678 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
679 bucketStartTimeNs + 501));
680 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
681 bucketStartTimeNs + bucketSizeNs + 100));
682
683 events.push_back(CreateStartScheduledJobEvent(
684 {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1));
685 events.push_back(CreateFinishScheduledJobEvent(
686 {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101));
687
688 events.push_back(CreateStartScheduledJobEvent(
689 {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201));
690 events.push_back(CreateFinishScheduledJobEvent(
691 {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500));
692 events.push_back(CreateStartScheduledJobEvent(
693 {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600));
694 events.push_back(CreateFinishScheduledJobEvent(
695 {CreateAttribution(333, "App2")}, "job2",
696 bucketStartTimeNs + bucketSizeNs + 850));
697
698 events.push_back(
699 CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
700 bucketStartTimeNs + bucketSizeNs - 2));
701 events.push_back(
702 CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3",
703 bucketStartTimeNs + bucketSizeNs + 900));
704
705 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail",
706 bucketStartTimeNs + 50));
707 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
708 bucketStartTimeNs + 110));
709
710 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail",
711 bucketStartTimeNs + 300));
712 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
713 bucketStartTimeNs + bucketSizeNs + 700));
714 events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc",
715 bucketStartTimeNs + 400));
716 events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc",
717 bucketStartTimeNs + bucketSizeNs - 1));
718
719 events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
720 bucketStartTimeNs + 550));
721 events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
722 bucketStartTimeNs + 800));
723 events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc",
724 bucketStartTimeNs + bucketSizeNs - 1));
725 events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc",
726 bucketStartTimeNs + bucketSizeNs + 700));
727
728 sortLogEventsByTimestamp(&events);
729
730 for (const auto& event : events) {
731 processor->OnLogEvent(event.get());
732 }
733
734 ConfigMetricsReportList reports;
735 vector<uint8_t> buffer;
Chenjie Yue36018b2018-04-16 15:18:30 -0700736 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
737 &buffer);
Yangster13fb7e42018-03-07 17:30:49 -0800738 EXPECT_TRUE(buffer.size() > 0);
739 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
740
741 EXPECT_EQ(reports.reports_size(), 1);
742 EXPECT_EQ(reports.reports(0).metrics_size(), 1);
743 StatsLogReport::DurationMetricDataWrapper metrics;
744 sortMetricDataByDimensionsValue(
745 reports.reports(0).metrics(0).duration_metrics(), &metrics);
746 if (aggregationType == DurationMetric::SUM) {
747 EXPECT_EQ(metrics.data_size(), 4);
748 auto data = metrics.data(0);
749 ValidateAttributionUidDimension(
750 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
751 ValidateAttributionUidDimension(
752 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111);
753 EXPECT_EQ("ReadEmail",
754 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
755 EXPECT_EQ(data.bucket_info_size(), 1);
756 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
757 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
758 bucketStartTimeNs);
759 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
760 bucketStartTimeNs + bucketSizeNs);
761
762 data = metrics.data(1);
763 ValidateAttributionUidDimension(
764 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
765 ValidateAttributionUidDimension(
766 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
767 EXPECT_EQ("ReadDoc",
768 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
769 EXPECT_EQ(data.bucket_info_size(), 1);
770 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
771 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
772 bucketStartTimeNs + bucketSizeNs);
773 EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 600 + 50);
774
775 data = metrics.data(2);
776 ValidateAttributionUidDimension(
777 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
778 ValidateAttributionUidDimension(
779 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
780 EXPECT_EQ("ReadEmail",
781 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
782 EXPECT_EQ(data.bucket_info_size(), 2);
783 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
784 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
785 bucketStartTimeNs + bucketSizeNs);
786 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600);
787 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
788 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
789 bucketStartTimeNs + bucketSizeNs);
790 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
791 bucketStartTimeNs + 2 * bucketSizeNs);
792
793 data = metrics.data(3);
794 ValidateAttributionUidDimension(
795 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
796 ValidateAttributionUidDimension(
797 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444);
798 EXPECT_EQ("ReadDoc",
799 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
800 EXPECT_EQ(data.bucket_info_size(), 2);
801 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1);
802 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
803 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
804 bucketStartTimeNs + bucketSizeNs);
805 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
806 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
807 bucketStartTimeNs + bucketSizeNs);
808 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
809 bucketStartTimeNs + 2 * bucketSizeNs);
810 } else {
811 EXPECT_EQ(metrics.data_size(), 4);
812 auto data = metrics.data(0);
813 ValidateAttributionUidDimension(
814 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111);
815 ValidateAttributionUidDimension(
816 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111);
817 EXPECT_EQ("ReadEmail",
818 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
819 EXPECT_EQ(data.bucket_info_size(), 1);
820 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55);
821 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
822 bucketStartTimeNs);
823 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
824 bucketStartTimeNs + bucketSizeNs);
825
826 data = metrics.data(1);
827 ValidateAttributionUidDimension(
828 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
829 ValidateAttributionUidDimension(
830 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
831 EXPECT_EQ("ReadDoc",
832 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
833 EXPECT_EQ(data.bucket_info_size(), 2);
834 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
835 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
836 bucketStartTimeNs + bucketSizeNs);
837 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 50);
838 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600);
839 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
840 bucketStartTimeNs + bucketSizeNs);
841 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
842 bucketStartTimeNs + 2 * bucketSizeNs);
843
844 data = metrics.data(2);
845 ValidateAttributionUidDimension(
846 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333);
847 ValidateAttributionUidDimension(
848 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333);
849 EXPECT_EQ("ReadEmail",
850 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
851 EXPECT_EQ(data.bucket_info_size(), 2);
852 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
853 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
854 bucketStartTimeNs + bucketSizeNs);
855 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300);
856 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
857 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
858 bucketStartTimeNs + bucketSizeNs);
859 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
860 bucketStartTimeNs + 2 * bucketSizeNs);
861
862 data = metrics.data(3);
863 ValidateAttributionUidDimension(
864 data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444);
865 ValidateAttributionUidDimension(
866 data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444);
867 EXPECT_EQ("ReadDoc",
868 data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str());
869 EXPECT_EQ(data.bucket_info_size(), 1);
870 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101);
871 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
872 bucketStartTimeNs + bucketSizeNs);
873 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
874 bucketStartTimeNs + 2 * bucketSizeNs);
875 }
876 }
877}
878
879#else
880GTEST_LOG_(INFO) << "This test does nothing.\n";
881#endif
882
883} // namespace statsd
884} // namespace os
885} // namespace android