1 // 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 "src/metrics/ValueMetricProducer.h"
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <math.h>
20 #include <stdio.h>
21
22 #include <vector>
23
24 #include "metrics_test_helper.h"
25 #include "src/matchers/SimpleAtomMatchingTracker.h"
26 #include "src/metrics/MetricProducer.h"
27 #include "src/stats_log_util.h"
28 #include "tests/statsd_test_util.h"
29
30 using namespace testing;
31 using android::sp;
32 using std::make_shared;
33 using std::set;
34 using std::shared_ptr;
35 using std::unordered_map;
36 using std::vector;
37
38 #ifdef __ANDROID__
39
40 namespace android {
41 namespace os {
42 namespace statsd {
43
44 namespace {
45
46 const ConfigKey kConfigKey(0, 12345);
47 const int tagId = 1;
48 const int64_t metricId = 123;
49 const uint64_t protoHash = 0x1234567890;
50 const int logEventMatcherIndex = 0;
51 const int64_t bucketStartTimeNs = 10000000000;
52 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
53 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
54 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
55 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
56 const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
57 const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
58 double epsilon = 0.001;
59
assertPastBucketValuesSingleKey(const std::unordered_map<MetricDimensionKey,std::vector<PastValueBucket>> & mPastBuckets,const std::initializer_list<int> & expectedValuesList,const std::initializer_list<int64_t> & expectedDurationNsList,const std::initializer_list<int64_t> & expectedStartTimeNsList,const std::initializer_list<int64_t> & expectedEndTimeNsList)60 static void assertPastBucketValuesSingleKey(
61 const std::unordered_map<MetricDimensionKey, std::vector<PastValueBucket>>& mPastBuckets,
62 const std::initializer_list<int>& expectedValuesList,
63 const std::initializer_list<int64_t>& expectedDurationNsList,
64 const std::initializer_list<int64_t>& expectedStartTimeNsList,
65 const std::initializer_list<int64_t>& expectedEndTimeNsList) {
66 vector<int> expectedValues(expectedValuesList);
67 vector<int64_t> expectedDurationNs(expectedDurationNsList);
68 vector<int64_t> expectedStartTimeNs(expectedStartTimeNsList);
69 vector<int64_t> expectedEndTimeNs(expectedEndTimeNsList);
70
71 ASSERT_EQ(expectedValues.size(), expectedDurationNs.size());
72 ASSERT_EQ(expectedValues.size(), expectedStartTimeNs.size());
73 ASSERT_EQ(expectedValues.size(), expectedEndTimeNs.size());
74
75 if (expectedValues.size() == 0) {
76 ASSERT_EQ(0, mPastBuckets.size());
77 return;
78 }
79
80 ASSERT_EQ(1, mPastBuckets.size());
81 ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
82
83 const vector<PastValueBucket>& buckets = mPastBuckets.begin()->second;
84 for (int i = 0; i < expectedValues.size(); i++) {
85 EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
86 << "Values differ at index " << i;
87 EXPECT_EQ(expectedDurationNs[i], buckets[i].mConditionTrueNs)
88 << "Condition duration value differ at index " << i;
89 EXPECT_EQ(expectedStartTimeNs[i], buckets[i].mBucketStartNs)
90 << "Start time differs at index " << i;
91 EXPECT_EQ(expectedEndTimeNs[i], buckets[i].mBucketEndNs)
92 << "End time differs at index " << i;
93 }
94 }
95
assertConditionTimer(const ConditionTimer & conditionTimer,bool condition,int64_t timerNs,int64_t lastConditionTrueTimestampNs)96 static void assertConditionTimer(const ConditionTimer& conditionTimer, bool condition,
97 int64_t timerNs, int64_t lastConditionTrueTimestampNs) {
98 EXPECT_EQ(condition, conditionTimer.mCondition);
99 EXPECT_EQ(timerNs, conditionTimer.mTimerNs);
100 EXPECT_EQ(lastConditionTrueTimestampNs, conditionTimer.mLastConditionChangeTimestampNs);
101 }
102
103 } // anonymous namespace
104
105 class ValueMetricProducerTestHelper {
106 public:
createValueProducerNoConditions(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric)107 static sp<ValueMetricProducer> createValueProducerNoConditions(
108 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
109 sp<EventMatcherWizard> eventMatcherWizard =
110 createEventMatcherWizard(tagId, logEventMatcherIndex);
111 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
112 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
113 .WillOnce(Return());
114 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
115 .WillRepeatedly(Return());
116
117 sp<ValueMetricProducer> valueProducer =
118 new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
119 wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
120 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
121 valueProducer->prepareFirstBucket();
122 return valueProducer;
123 }
124
createValueProducerWithCondition(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric,ConditionState conditionAfterFirstBucketPrepared)125 static sp<ValueMetricProducer> createValueProducerWithCondition(
126 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
127 ConditionState conditionAfterFirstBucketPrepared) {
128 sp<EventMatcherWizard> eventMatcherWizard =
129 createEventMatcherWizard(tagId, logEventMatcherIndex);
130 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
131 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
132 .WillOnce(Return());
133 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
134 .WillRepeatedly(Return());
135
136 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
137 kConfigKey, metric, 0 /*condition index*/, {ConditionState::kUnknown}, wizard,
138 protoHash, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
139 bucketStartTimeNs, pullerManager);
140 valueProducer->prepareFirstBucket();
141 valueProducer->mCondition = conditionAfterFirstBucketPrepared;
142 return valueProducer;
143 }
144
createValueProducerWithState(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric,vector<int32_t> slicedStateAtoms,unordered_map<int,unordered_map<int,int64_t>> stateGroupMap)145 static sp<ValueMetricProducer> createValueProducerWithState(
146 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
147 vector<int32_t> slicedStateAtoms,
148 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
149 sp<EventMatcherWizard> eventMatcherWizard =
150 createEventMatcherWizard(tagId, logEventMatcherIndex);
151 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
152 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
153 .WillOnce(Return());
154 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
155 .WillRepeatedly(Return());
156
157 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
158 kConfigKey, metric, -1 /* no condition */, {}, wizard, protoHash,
159 logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
160 bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap);
161 valueProducer->prepareFirstBucket();
162 return valueProducer;
163 }
164
createValueProducerWithConditionAndState(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric,vector<int32_t> slicedStateAtoms,unordered_map<int,unordered_map<int,int64_t>> stateGroupMap,ConditionState conditionAfterFirstBucketPrepared)165 static sp<ValueMetricProducer> createValueProducerWithConditionAndState(
166 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
167 vector<int32_t> slicedStateAtoms,
168 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap,
169 ConditionState conditionAfterFirstBucketPrepared) {
170 sp<EventMatcherWizard> eventMatcherWizard =
171 createEventMatcherWizard(tagId, logEventMatcherIndex);
172 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
173 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
174 .WillOnce(Return());
175 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
176 .WillRepeatedly(Return());
177
178 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
179 kConfigKey, metric, 0 /* condition tracker index */, {ConditionState::kUnknown},
180 wizard, protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
181 bucketStartTimeNs, bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms,
182 stateGroupMap);
183 valueProducer->prepareFirstBucket();
184 valueProducer->mCondition = conditionAfterFirstBucketPrepared;
185 return valueProducer;
186 }
187
createMetric()188 static ValueMetric createMetric() {
189 ValueMetric metric;
190 metric.set_id(metricId);
191 metric.set_bucket(ONE_MINUTE);
192 metric.mutable_value_field()->set_field(tagId);
193 metric.mutable_value_field()->add_child()->set_field(2);
194 metric.set_max_pull_delay_sec(INT_MAX);
195 return metric;
196 }
197
createMetricWithCondition()198 static ValueMetric createMetricWithCondition() {
199 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
200 metric.set_condition(StringToId("SCREEN_ON"));
201 return metric;
202 }
203
createMetricWithState(string state)204 static ValueMetric createMetricWithState(string state) {
205 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
206 metric.add_slice_by_state(StringToId(state));
207 return metric;
208 }
209
createMetricWithConditionAndState(string state)210 static ValueMetric createMetricWithConditionAndState(string state) {
211 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
212 metric.set_condition(StringToId("SCREEN_ON"));
213 metric.add_slice_by_state(StringToId(state));
214 return metric;
215 }
216 };
217
218 // Setup for parameterized tests.
219 class ValueMetricProducerTest_PartialBucket : public TestWithParam<BucketSplitEvent> {};
220
221 INSTANTIATE_TEST_SUITE_P(ValueMetricProducerTest_PartialBucket,
222 ValueMetricProducerTest_PartialBucket,
223 testing::Values(APP_UPGRADE, BOOT_COMPLETE));
224
225 /*
226 * Tests that the first bucket works correctly
227 */
TEST(ValueMetricProducerTest,TestCalcPreviousBucketEndTime)228 TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
229 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
230
231 int64_t startTimeBase = 11;
232 sp<EventMatcherWizard> eventMatcherWizard =
233 createEventMatcherWizard(tagId, logEventMatcherIndex);
234 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
235 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
236
237 // statsd started long ago.
238 // The metric starts in the middle of the bucket
239 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
240 wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
241 -1, startTimeBase, 22, pullerManager);
242 valueProducer.prepareFirstBucket();
243
244 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
245 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
246 EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
247 valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
248 EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
249 valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
250 }
251
252 /*
253 * Tests that the first bucket works correctly
254 */
TEST(ValueMetricProducerTest,TestFirstBucket)255 TEST(ValueMetricProducerTest, TestFirstBucket) {
256 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
257
258 sp<EventMatcherWizard> eventMatcherWizard =
259 createEventMatcherWizard(tagId, logEventMatcherIndex);
260 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
261 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
262
263 // statsd started long ago.
264 // The metric starts in the middle of the bucket
265 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
266 wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
267 -1, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
268 valueProducer.prepareFirstBucket();
269
270 EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
271 EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
272 EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
273 }
274
275 /*
276 * Tests pulled atoms with no conditions
277 */
TEST(ValueMetricProducerTest,TestPulledEventsNoCondition)278 TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
279 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
280 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
281 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
282 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
283 vector<std::shared_ptr<LogEvent>>* data) {
284 data->clear();
285 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
286 return true;
287 }));
288
289 sp<ValueMetricProducer> valueProducer =
290 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
291
292 vector<shared_ptr<LogEvent>> allData;
293 allData.clear();
294 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
295
296 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
297 // has one slice
298 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
299 ValueMetricProducer::Interval curInterval =
300 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
301 ValueMetricProducer::BaseInfo curBaseInfo =
302 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
303
304 EXPECT_EQ(true, curBaseInfo.hasBase);
305 EXPECT_EQ(11, curBaseInfo.base.long_value);
306 EXPECT_EQ(false, curInterval.hasValue);
307 EXPECT_EQ(8, curInterval.value.long_value);
308 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
309 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
310 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
311
312 allData.clear();
313 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
314 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
315 // has one slice
316 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
317 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
318 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
319
320 EXPECT_EQ(true, curBaseInfo.hasBase);
321 EXPECT_EQ(23, curBaseInfo.base.long_value);
322 EXPECT_EQ(false, curInterval.hasValue);
323 EXPECT_EQ(12, curInterval.value.long_value);
324 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
325 ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
326 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
327 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
328 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
329 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
330
331 allData.clear();
332 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
333 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
334 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
335 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
336 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
337
338 EXPECT_EQ(true, curBaseInfo.hasBase);
339 EXPECT_EQ(36, curBaseInfo.base.long_value);
340 EXPECT_EQ(false, curInterval.hasValue);
341 EXPECT_EQ(13, curInterval.value.long_value);
342 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
343 ASSERT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
344 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
345 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
346 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
347 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
348 EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
349 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
350 }
351
TEST_P(ValueMetricProducerTest_PartialBucket,TestPartialBucketCreated)352 TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
353 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
354 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
355 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
356 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
357 // Initialize bucket.
358 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
359 vector<std::shared_ptr<LogEvent>>* data) {
360 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
361 data->clear();
362 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
363 return true;
364 }))
365 // Partial bucket.
366 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
367 const int64_t eventTimeNs,
368 vector<std::shared_ptr<LogEvent>>* data) {
369 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
370 data->clear();
371 data->push_back(
372 CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs + 8, 5));
373 return true;
374 }));
375
376 sp<ValueMetricProducer> valueProducer =
377 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
378
379 // First bucket ends.
380 vector<shared_ptr<LogEvent>> allData;
381 allData.clear();
382 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 2));
383 valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
384
385 // Partial buckets created in 2nd bucket.
386 switch (GetParam()) {
387 case APP_UPGRADE:
388 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
389 break;
390 case BOOT_COMPLETE:
391 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
392 break;
393 }
394 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
395 EXPECT_EQ(1, valueProducer->getCurrentBucketNum());
396
397 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1, 3},
398 {bucketSizeNs, partialBucketSplitTimeNs - bucket2StartTimeNs},
399 {bucketStartTimeNs, bucket2StartTimeNs},
400 {bucket2StartTimeNs, partialBucketSplitTimeNs});
401 }
402
403 /*
404 * Tests pulled atoms with filtering
405 */
TEST(ValueMetricProducerTest,TestPulledEventsWithFiltering)406 TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
407 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
408
409 FieldValueMatcher fvm;
410 fvm.set_field(1);
411 fvm.set_eq_int(3);
412 sp<EventMatcherWizard> eventMatcherWizard =
413 createEventMatcherWizard(tagId, logEventMatcherIndex, {fvm});
414 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
415 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
416 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
417 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
418 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
419 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
420 vector<std::shared_ptr<LogEvent>>* data) {
421 data->clear();
422 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
423 return true;
424 }));
425
426 sp<ValueMetricProducer> valueProducer =
427 new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard,
428 protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
429 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
430 valueProducer->prepareFirstBucket();
431
432 vector<shared_ptr<LogEvent>> allData;
433 allData.clear();
434 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 3, 11));
435
436 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
437 // has one slice
438 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
439 ValueMetricProducer::Interval curInterval =
440 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
441 ValueMetricProducer::BaseInfo curBaseInfo =
442 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
443
444 EXPECT_EQ(true, curBaseInfo.hasBase);
445 EXPECT_EQ(11, curBaseInfo.base.long_value);
446 EXPECT_EQ(false, curInterval.hasValue);
447 EXPECT_EQ(8, curInterval.value.long_value);
448 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
449 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
450 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
451
452 allData.clear();
453 allData.push_back(CreateTwoValueLogEvent(tagId, bucket3StartTimeNs + 1, 4, 23));
454 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
455 // No new data seen, so data has been cleared.
456 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
457
458 EXPECT_EQ(true, curBaseInfo.hasBase);
459 EXPECT_EQ(11, curBaseInfo.base.long_value);
460 EXPECT_EQ(false, curInterval.hasValue);
461 EXPECT_EQ(8, curInterval.value.long_value);
462 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
463 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
464 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
465
466 allData.clear();
467 allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
468 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
469 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
470 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
471 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
472
473 // the base was reset
474 EXPECT_EQ(true, curBaseInfo.hasBase);
475 EXPECT_EQ(36, curBaseInfo.base.long_value);
476 EXPECT_EQ(false, curInterval.hasValue);
477 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
478 ASSERT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
479 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
480 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
481 }
482
483 /*
484 * Tests pulled atoms with no conditions and take absolute value after reset
485 */
TEST(ValueMetricProducerTest,TestPulledEventsTakeAbsoluteValueOnReset)486 TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
487 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
488 metric.set_use_absolute_value_on_reset(true);
489
490 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
491 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
492 .WillOnce(Return(true));
493 sp<ValueMetricProducer> valueProducer =
494 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
495
496 vector<shared_ptr<LogEvent>> allData;
497 allData.clear();
498 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
499
500 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
501 // has one slice
502 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
503 ValueMetricProducer::Interval curInterval =
504 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
505 ValueMetricProducer::BaseInfo curBaseInfo =
506 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
507
508 EXPECT_EQ(true, curBaseInfo.hasBase);
509 EXPECT_EQ(11, curBaseInfo.base.long_value);
510 EXPECT_EQ(false, curInterval.hasValue);
511 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
512
513 allData.clear();
514 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
515 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
516 // has one slice
517 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
518 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
519 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
520 EXPECT_EQ(true, curBaseInfo.hasBase);
521 EXPECT_EQ(10, curBaseInfo.base.long_value);
522 EXPECT_EQ(false, curInterval.hasValue);
523 EXPECT_EQ(10, curInterval.value.long_value);
524 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
525 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
526 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
527
528 allData.clear();
529 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
530 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
531 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
532 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
533 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
534 EXPECT_EQ(true, curBaseInfo.hasBase);
535 EXPECT_EQ(36, curBaseInfo.base.long_value);
536 EXPECT_EQ(false, curInterval.hasValue);
537 EXPECT_EQ(26, curInterval.value.long_value);
538 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
539 ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
540 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
541 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
542 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
543 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
544 }
545
546 /*
547 * Tests pulled atoms with no conditions and take zero value after reset
548 */
TEST(ValueMetricProducerTest,TestPulledEventsTakeZeroOnReset)549 TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
550 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
551 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
552 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
553 .WillOnce(Return(false));
554 sp<ValueMetricProducer> valueProducer =
555 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
556
557 vector<shared_ptr<LogEvent>> allData;
558 allData.clear();
559 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
560
561 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
562 // has one slice
563 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
564 ValueMetricProducer::Interval curInterval =
565 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
566 ValueMetricProducer::BaseInfo curBaseInfo =
567 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
568
569 EXPECT_EQ(true, curBaseInfo.hasBase);
570 EXPECT_EQ(11, curBaseInfo.base.long_value);
571 EXPECT_EQ(false, curInterval.hasValue);
572 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
573
574 allData.clear();
575 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
576 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
577 // has one slice
578 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
579 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
580 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
581 EXPECT_EQ(true, curBaseInfo.hasBase);
582 EXPECT_EQ(10, curBaseInfo.base.long_value);
583 EXPECT_EQ(false, curInterval.hasValue);
584 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
585
586 allData.clear();
587 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
588 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
589 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
590 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
591 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
592 EXPECT_EQ(true, curBaseInfo.hasBase);
593 EXPECT_EQ(36, curBaseInfo.base.long_value);
594 EXPECT_EQ(false, curInterval.hasValue);
595 EXPECT_EQ(26, curInterval.value.long_value);
596 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
597 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
598 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
599 }
600
601 /*
602 * Test pulled event with non sliced condition.
603 */
TEST(ValueMetricProducerTest,TestEventsWithNonSlicedCondition)604 TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
605 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
606
607 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
608
609 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
610 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
611 vector<std::shared_ptr<LogEvent>>* data) {
612 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // First condition change.
613 data->clear();
614 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
615 return true;
616 }))
617 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
618 vector<std::shared_ptr<LogEvent>>* data) {
619 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); // Second condition change.
620 data->clear();
621 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
622 return true;
623 }))
624 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
625 vector<std::shared_ptr<LogEvent>>* data) {
626 EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 1); // Third condition change.
627 data->clear();
628 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
629 return true;
630 }));
631
632 sp<ValueMetricProducer> valueProducer =
633 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
634 ConditionState::kFalse);
635
636 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
637
638 // has one slice
639 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
640 ValueMetricProducer::Interval curInterval =
641 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
642 ValueMetricProducer::BaseInfo curBaseInfo =
643 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
644 // startUpdated:false sum:0 start:100
645 EXPECT_EQ(true, curBaseInfo.hasBase);
646 EXPECT_EQ(100, curBaseInfo.base.long_value);
647 EXPECT_EQ(false, curInterval.hasValue);
648 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
649
650 vector<shared_ptr<LogEvent>> allData;
651 allData.clear();
652 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
653 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
654 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8},
655 {bucketStartTimeNs}, {bucket2StartTimeNs});
656
657 // has one slice
658 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
659 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
660 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
661 EXPECT_EQ(true, curBaseInfo.hasBase);
662 EXPECT_EQ(110, curBaseInfo.base.long_value);
663 EXPECT_EQ(false, curInterval.hasValue);
664 EXPECT_EQ(10, curInterval.value.long_value);
665
666 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
667 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8},
668 {bucketStartTimeNs}, {bucket2StartTimeNs});
669
670 // has one slice
671 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
672 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
673 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
674 EXPECT_EQ(true, curInterval.hasValue);
675 EXPECT_EQ(20, curInterval.value.long_value);
676 EXPECT_EQ(false, curBaseInfo.hasBase);
677
678 valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
679 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1},
680 {bucketStartTimeNs, bucket2StartTimeNs},
681 {bucket2StartTimeNs, bucket3StartTimeNs});
682 }
683
TEST_P(ValueMetricProducerTest_PartialBucket,TestPushedEvents)684 TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
685 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
686
687 sp<EventMatcherWizard> eventMatcherWizard =
688 createEventMatcherWizard(tagId, logEventMatcherIndex);
689 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
690 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
691
692 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
693 logEventMatcherIndex, eventMatcherWizard, -1,
694 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
695 valueProducer.prepareFirstBucket();
696
697 LogEvent event1(/*uid=*/0, /*pid=*/0);
698 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
699 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
700 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
701
702 int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 150;
703 switch (GetParam()) {
704 case APP_UPGRADE:
705 valueProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
706 break;
707 case BOOT_COMPLETE:
708 valueProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
709 break;
710 }
711 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10},
712 {partialBucketSplitTimeNs - bucketStartTimeNs},
713 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
714 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
715 EXPECT_EQ(0, valueProducer.getCurrentBucketNum());
716
717 // Event arrives after the bucket split.
718 LogEvent event2(/*uid=*/0, /*pid=*/0);
719 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 59 * NS_PER_SEC, 20);
720 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
721
722 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10},
723 {partialBucketSplitTimeNs - bucketStartTimeNs},
724 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
725 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
726 EXPECT_EQ(0, valueProducer.getCurrentBucketNum());
727
728 // Next value should create a new bucket.
729 LogEvent event3(/*uid=*/0, /*pid=*/0);
730 CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 5 * NS_PER_SEC, 10);
731 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
732 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10, 20},
733 {partialBucketSplitTimeNs - bucketStartTimeNs,
734 bucket2StartTimeNs - partialBucketSplitTimeNs},
735 {bucketStartTimeNs, partialBucketSplitTimeNs},
736 {partialBucketSplitTimeNs, bucket2StartTimeNs});
737 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
738 EXPECT_EQ(1, valueProducer.getCurrentBucketNum());
739 }
740
TEST_P(ValueMetricProducerTest_PartialBucket,TestPulledValue)741 TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
742 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
743
744 sp<EventMatcherWizard> eventMatcherWizard =
745 createEventMatcherWizard(tagId, logEventMatcherIndex);
746 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
747 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
748 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
749 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
750 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
751 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
752 .WillOnce(Return(true))
753 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
754 const int64_t eventTimeNs,
755 vector<std::shared_ptr<LogEvent>>* data) {
756 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
757 data->clear();
758 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120));
759 return true;
760 }));
761
762 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
763 logEventMatcherIndex, eventMatcherWizard, tagId,
764 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
765 valueProducer.prepareFirstBucket();
766
767 vector<shared_ptr<LogEvent>> allData;
768 allData.clear();
769 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
770
771 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
772 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
773
774 switch (GetParam()) {
775 case APP_UPGRADE:
776 valueProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
777 break;
778 case BOOT_COMPLETE:
779 valueProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
780 break;
781 }
782 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
783 EXPECT_EQ(1, valueProducer.getCurrentBucketNum());
784 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150}, {bucket2StartTimeNs},
785 {partialBucketSplitTimeNs});
786
787 allData.clear();
788 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 150));
789 valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
790 EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
791 EXPECT_EQ(2, valueProducer.getCurrentBucketNum());
792 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30}, {150, bucketSizeNs - 150},
793 {bucket2StartTimeNs, partialBucketSplitTimeNs},
794 {partialBucketSplitTimeNs, bucket3StartTimeNs});
795 }
796
TEST(ValueMetricProducerTest,TestPulledWithAppUpgradeDisabled)797 TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
798 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
799 metric.set_split_bucket_for_app_upgrade(false);
800
801 sp<EventMatcherWizard> eventMatcherWizard =
802 createEventMatcherWizard(tagId, logEventMatcherIndex);
803 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
804 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
805 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
806 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
807 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
808 .WillOnce(Return(true));
809
810 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
811 logEventMatcherIndex, eventMatcherWizard, tagId,
812 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
813 valueProducer.prepareFirstBucket();
814
815 vector<shared_ptr<LogEvent>> allData;
816 allData.clear();
817 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
818
819 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
820 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
821
822 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150);
823 ASSERT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
824 EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
825 }
826
TEST_P(ValueMetricProducerTest_PartialBucket,TestPulledValueWhileConditionFalse)827 TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse) {
828 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
829
830 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
831 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
832 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
833 vector<std::shared_ptr<LogEvent>>* data) {
834 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to true time.
835 data->clear();
836 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
837 return true;
838 }))
839 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
840 vector<std::shared_ptr<LogEvent>>* data) {
841 EXPECT_EQ(eventTimeNs,
842 bucket2StartTimeNs - 100); // Condition change to false time.
843 data->clear();
844 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
845 return true;
846 }));
847 sp<ValueMetricProducer> valueProducer =
848 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
849 ConditionState::kFalse);
850
851 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
852
853 valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
854 EXPECT_FALSE(valueProducer->mCondition);
855
856 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs - 50;
857 switch (GetParam()) {
858 case APP_UPGRADE:
859 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
860 break;
861 case BOOT_COMPLETE:
862 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
863 break;
864 }
865 // Expect one full buckets already done and starting a partial bucket.
866 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
867 EXPECT_EQ(0, valueProducer->getCurrentBucketNum());
868 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
869 {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)},
870 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
871 EXPECT_FALSE(valueProducer->mCondition);
872 }
873
TEST(ValueMetricProducerTest,TestPushedEventsWithoutCondition)874 TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
875 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
876
877 sp<EventMatcherWizard> eventMatcherWizard =
878 createEventMatcherWizard(tagId, logEventMatcherIndex);
879 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
880 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
881
882 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
883 logEventMatcherIndex, eventMatcherWizard, -1,
884 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
885 valueProducer.prepareFirstBucket();
886
887 LogEvent event1(/*uid=*/0, /*pid=*/0);
888 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
889
890 LogEvent event2(/*uid=*/0, /*pid=*/0);
891 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
892
893 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
894 // has one slice
895 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
896 ValueMetricProducer::Interval curInterval =
897 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
898 ValueMetricProducer::BaseInfo curBaseInfo =
899 valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
900 EXPECT_EQ(10, curInterval.value.long_value);
901 EXPECT_EQ(true, curInterval.hasValue);
902
903 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
904
905 // has one slice
906 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
907 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
908 EXPECT_EQ(30, curInterval.value.long_value);
909
910 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
911 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs},
912 {bucketStartTimeNs}, {bucket2StartTimeNs});
913 }
914
TEST(ValueMetricProducerTest,TestPushedEventsWithCondition)915 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
916 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
917
918 sp<EventMatcherWizard> eventMatcherWizard =
919 createEventMatcherWizard(tagId, logEventMatcherIndex);
920 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
921 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
922
923 ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
924 protoHash, logEventMatcherIndex, eventMatcherWizard, -1,
925 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
926 valueProducer.prepareFirstBucket();
927 valueProducer.mCondition = ConditionState::kFalse;
928
929 LogEvent event1(/*uid=*/0, /*pid=*/0);
930 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
931 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
932 // has 1 slice
933 ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
934
935 valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
936
937 LogEvent event2(/*uid=*/0, /*pid=*/0);
938 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
939 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
940
941 // has one slice
942 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
943 ValueMetricProducer::Interval curInterval =
944 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
945 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
946 EXPECT_EQ(20, curInterval.value.long_value);
947
948 LogEvent event3(/*uid=*/0, /*pid=*/0);
949 CreateRepeatedValueLogEvent(&event3, tagId, bucketStartTimeNs + 30, 30);
950 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
951
952 // has one slice
953 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
954 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
955 EXPECT_EQ(50, curInterval.value.long_value);
956
957 valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
958
959 LogEvent event4(/*uid=*/0, /*pid=*/0);
960 CreateRepeatedValueLogEvent(&event4, tagId, bucketStartTimeNs + 40, 40);
961 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
962
963 // has one slice
964 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
965 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
966 EXPECT_EQ(50, curInterval.value.long_value);
967
968 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
969 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20}, {bucketStartTimeNs},
970 {bucket2StartTimeNs});
971 }
972
TEST(ValueMetricProducerTest,TestAnomalyDetection)973 TEST(ValueMetricProducerTest, TestAnomalyDetection) {
974 sp<AlarmMonitor> alarmMonitor;
975 Alert alert;
976 alert.set_id(101);
977 alert.set_metric_id(metricId);
978 alert.set_trigger_if_sum_gt(130);
979 alert.set_num_buckets(2);
980 const int32_t refPeriodSec = 3;
981 alert.set_refractory_period_secs(refPeriodSec);
982
983 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
984
985 sp<EventMatcherWizard> eventMatcherWizard =
986 createEventMatcherWizard(tagId, logEventMatcherIndex);
987 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
988 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
989
990 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
991 wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
992 -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
993 pullerManager);
994 valueProducer.prepareFirstBucket();
995
996 sp<AnomalyTracker> anomalyTracker =
997 valueProducer.addAnomalyTracker(alert, alarmMonitor, UPDATE_NEW, bucketStartTimeNs);
998
999 LogEvent event1(/*uid=*/0, /*pid=*/0);
1000 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 1 * NS_PER_SEC, 10);
1001
1002 LogEvent event2(/*uid=*/0, /*pid=*/0);
1003 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 2 + NS_PER_SEC, 20);
1004
1005 LogEvent event3(/*uid=*/0, /*pid=*/0);
1006 CreateRepeatedValueLogEvent(&event3, tagId,
1007 bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, 130);
1008
1009 LogEvent event4(/*uid=*/0, /*pid=*/0);
1010 CreateRepeatedValueLogEvent(&event4, tagId,
1011 bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC, 1);
1012
1013 LogEvent event5(/*uid=*/0, /*pid=*/0);
1014 CreateRepeatedValueLogEvent(&event5, tagId,
1015 bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC, 150);
1016
1017 LogEvent event6(/*uid=*/0, /*pid=*/0);
1018 CreateRepeatedValueLogEvent(&event6, tagId,
1019 bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC, 160);
1020
1021 // Two events in bucket #0.
1022 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1023 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1024 // Value sum == 30 <= 130.
1025 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1026
1027 // One event in bucket #2. No alarm as bucket #0 is trashed out.
1028 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1029 // Value sum == 130 <= 130.
1030 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1031
1032 // Three events in bucket #3.
1033 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1034 // Anomaly at event 4 since Value sum == 131 > 130!
1035 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1036 std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1037 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
1038 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
1039 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1040 std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1041
1042 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
1043 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
1044 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1045 std::ceil(1.0 * event6.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1046 }
1047
TEST(ValueMetricProducerTest,TestAnomalyDetectionMultipleBucketsSkipped)1048 TEST(ValueMetricProducerTest, TestAnomalyDetectionMultipleBucketsSkipped) {
1049 sp<AlarmMonitor> alarmMonitor;
1050 Alert alert;
1051 alert.set_id(101);
1052 alert.set_metric_id(metricId);
1053 alert.set_trigger_if_sum_gt(100);
1054 alert.set_num_buckets(1);
1055 const int32_t refPeriodSec = 3;
1056 alert.set_refractory_period_secs(refPeriodSec);
1057
1058 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1059
1060 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1061 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1062 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1063 vector<std::shared_ptr<LogEvent>>* data) {
1064 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to true time.
1065 data->clear();
1066 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 0));
1067 return true;
1068 }))
1069 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1070 vector<std::shared_ptr<LogEvent>>* data) {
1071 EXPECT_EQ(eventTimeNs,
1072 bucket3StartTimeNs + 100); // Condition changed to false time.
1073 data->clear();
1074 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 100, 120));
1075 return true;
1076 }));
1077 sp<ValueMetricProducer> valueProducer =
1078 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1079 ConditionState::kFalse);
1080 sp<AnomalyTracker> anomalyTracker =
1081 valueProducer->addAnomalyTracker(alert, alarmMonitor, UPDATE_NEW, bucketStartTimeNs);
1082
1083 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
1084
1085 // multiple buckets should be skipped here.
1086 valueProducer->onConditionChanged(false, bucket3StartTimeNs + 100);
1087
1088 // No alert is fired when multiple buckets are skipped.
1089 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1090 }
1091
1092 // Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest,TestBucketBoundaryNoCondition)1093 TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
1094 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1095 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1096 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1097 .WillOnce(Return(true));
1098 sp<ValueMetricProducer> valueProducer =
1099 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1100
1101 vector<shared_ptr<LogEvent>> allData;
1102 // pull 1
1103 allData.clear();
1104 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
1105
1106 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1107 // has one slice
1108 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1109 ValueMetricProducer::Interval curInterval =
1110 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1111 ValueMetricProducer::BaseInfo curBaseInfo =
1112 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1113
1114 // startUpdated:true sum:0 start:11
1115 EXPECT_EQ(true, curBaseInfo.hasBase);
1116 EXPECT_EQ(11, curBaseInfo.base.long_value);
1117 EXPECT_EQ(false, curInterval.hasValue);
1118 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1119
1120 // pull 2 at correct time
1121 allData.clear();
1122 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
1123 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1124 // has one slice
1125 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1126 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1127 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1128 // tartUpdated:false sum:12
1129 EXPECT_EQ(true, curBaseInfo.hasBase);
1130 EXPECT_EQ(23, curBaseInfo.base.long_value);
1131 EXPECT_EQ(false, curInterval.hasValue);
1132 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
1133 {bucket2StartTimeNs}, {bucket3StartTimeNs});
1134
1135 // pull 3 come late.
1136 // The previous bucket gets closed with error. (Has start value 23, no ending)
1137 // Another bucket gets closed with error. (No start, but ending with 36)
1138 // The new bucket is back to normal.
1139 allData.clear();
1140 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
1141 valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
1142 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1143 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1144 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1145 // startUpdated:false sum:12
1146 EXPECT_EQ(true, curBaseInfo.hasBase);
1147 EXPECT_EQ(36, curBaseInfo.base.long_value);
1148 EXPECT_EQ(false, curInterval.hasValue);
1149 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
1150 {bucket2StartTimeNs}, {bucket3StartTimeNs});
1151 // The 1st bucket is dropped because of no data
1152 // The 3rd bucket is dropped due to multiple buckets being skipped.
1153 ASSERT_EQ(2, valueProducer->mSkippedBuckets.size());
1154
1155 EXPECT_EQ(bucketStartTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
1156 EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
1157 ASSERT_EQ(1, valueProducer->mSkippedBuckets[0].dropEvents.size());
1158 EXPECT_EQ(NO_DATA, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
1159 EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].dropEvents[0].dropTimeNs);
1160
1161 EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[1].bucketStartTimeNs);
1162 EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[1].bucketEndTimeNs);
1163 ASSERT_EQ(1, valueProducer->mSkippedBuckets[1].dropEvents.size());
1164 EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[1].dropEvents[0].reason);
1165 EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[1].dropEvents[0].dropTimeNs);
1166 }
1167
1168 /*
1169 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
1170 * was delivered late.
1171 */
TEST(ValueMetricProducerTest,TestBucketBoundaryWithCondition)1172 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
1173 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1174
1175 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1176 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1177 // condition becomes true
1178 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1179 vector<std::shared_ptr<LogEvent>>* data) {
1180 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // First condition change.
1181 data->clear();
1182 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1183 return true;
1184 }))
1185 // condition becomes false
1186 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1187 vector<std::shared_ptr<LogEvent>>* data) {
1188 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); // Second condition change.
1189 data->clear();
1190 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
1191 return true;
1192 }));
1193 sp<ValueMetricProducer> valueProducer =
1194 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1195 ConditionState::kFalse);
1196
1197 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1198
1199 // has one slice
1200 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1201 ValueMetricProducer::Interval curInterval =
1202 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1203 ValueMetricProducer::BaseInfo curBaseInfo =
1204 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1205 EXPECT_EQ(true, curBaseInfo.hasBase);
1206 EXPECT_EQ(100, curBaseInfo.base.long_value);
1207 EXPECT_EQ(false, curInterval.hasValue);
1208 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1209
1210 // pull on bucket boundary come late, condition change happens before it
1211 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1212 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1213 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1214 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1215 {bucketStartTimeNs}, {bucket2StartTimeNs});
1216 EXPECT_EQ(false, curBaseInfo.hasBase);
1217
1218 // Now the alarm is delivered.
1219 // since the condition turned to off before this pull finish, it has no effect
1220 vector<shared_ptr<LogEvent>> allData;
1221 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
1222 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1223
1224 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1225 {bucketStartTimeNs}, {bucket2StartTimeNs});
1226 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1227 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1228 EXPECT_EQ(false, curBaseInfo.hasBase);
1229 EXPECT_EQ(false, curInterval.hasValue);
1230 }
1231
1232 /*
1233 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
1234 * change to false, and then true again. This is due to alarm delivered late.
1235 */
TEST(ValueMetricProducerTest,TestBucketBoundaryWithCondition2)1236 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
1237 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1238
1239 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1240 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1241 // condition becomes true
1242 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1243 vector<std::shared_ptr<LogEvent>>* data) {
1244 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
1245 data->clear();
1246 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1247 return true;
1248 }))
1249 // condition becomes false
1250 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1251 vector<std::shared_ptr<LogEvent>>* data) {
1252 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);
1253 data->clear();
1254 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
1255 return true;
1256 }))
1257 // condition becomes true again
1258 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1259 vector<std::shared_ptr<LogEvent>>* data) {
1260 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 25);
1261 data->clear();
1262 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
1263 return true;
1264 }));
1265
1266 sp<ValueMetricProducer> valueProducer =
1267 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1268 ConditionState::kFalse);
1269
1270 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1271
1272 // has one slice
1273 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1274 ValueMetricProducer::Interval curInterval =
1275 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1276 ValueMetricProducer::BaseInfo curBaseInfo =
1277 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1278 // startUpdated:false sum:0 start:100
1279 EXPECT_EQ(true, curBaseInfo.hasBase);
1280 EXPECT_EQ(100, curBaseInfo.base.long_value);
1281 EXPECT_EQ(false, curInterval.hasValue);
1282 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1283
1284 // pull on bucket boundary come late, condition change happens before it
1285 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1286 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1287 {bucketStartTimeNs}, {bucket2StartTimeNs});
1288 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1289 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1290 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1291 EXPECT_EQ(false, curBaseInfo.hasBase);
1292 EXPECT_EQ(false, curInterval.hasValue);
1293
1294 // condition changed to true again, before the pull alarm is delivered
1295 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
1296 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1297 {bucketStartTimeNs}, {bucket2StartTimeNs});
1298 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1299 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1300 EXPECT_EQ(true, curBaseInfo.hasBase);
1301 EXPECT_EQ(130, curBaseInfo.base.long_value);
1302 EXPECT_EQ(false, curInterval.hasValue);
1303
1304 // Now the alarm is delivered, but it is considered late, the data will be used
1305 // for the new bucket since it was just pulled.
1306 vector<shared_ptr<LogEvent>> allData;
1307 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
1308 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
1309
1310 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1311 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1312 EXPECT_EQ(true, curBaseInfo.hasBase);
1313 EXPECT_EQ(140, curBaseInfo.base.long_value);
1314 EXPECT_EQ(true, curInterval.hasValue);
1315 EXPECT_EQ(10, curInterval.value.long_value);
1316 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1317 {bucketStartTimeNs}, {bucket2StartTimeNs});
1318
1319 allData.clear();
1320 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 160));
1321 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1322 assertPastBucketValuesSingleKey(
1323 valueProducer->mPastBuckets, {20, 30}, {bucketSizeNs - 8, bucketSizeNs - 24},
1324 {bucketStartTimeNs, bucket2StartTimeNs}, {bucket2StartTimeNs, bucket3StartTimeNs});
1325 }
1326
TEST(ValueMetricProducerTest,TestPushedAggregateMin)1327 TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
1328 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1329 metric.set_aggregation_type(ValueMetric::MIN);
1330
1331 sp<EventMatcherWizard> eventMatcherWizard =
1332 createEventMatcherWizard(tagId, logEventMatcherIndex);
1333 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1334 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1335
1336 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1337 logEventMatcherIndex, eventMatcherWizard, -1,
1338 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1339 valueProducer.prepareFirstBucket();
1340
1341 LogEvent event1(/*uid=*/0, /*pid=*/0);
1342 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1343
1344 LogEvent event2(/*uid=*/0, /*pid=*/0);
1345 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
1346
1347 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1348 // has one slice
1349 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1350 ValueMetricProducer::Interval curInterval =
1351 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1352 EXPECT_EQ(10, curInterval.value.long_value);
1353 EXPECT_EQ(true, curInterval.hasValue);
1354
1355 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1356
1357 // has one slice
1358 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1359 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1360 EXPECT_EQ(10, curInterval.value.long_value);
1361
1362 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1363 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs},
1364 {bucketStartTimeNs}, {bucket2StartTimeNs});
1365 }
1366
TEST(ValueMetricProducerTest,TestPushedAggregateMax)1367 TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
1368 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1369 metric.set_aggregation_type(ValueMetric::MAX);
1370
1371 sp<EventMatcherWizard> eventMatcherWizard =
1372 createEventMatcherWizard(tagId, logEventMatcherIndex);
1373 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1374 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1375
1376 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1377 logEventMatcherIndex, eventMatcherWizard, -1,
1378 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1379 valueProducer.prepareFirstBucket();
1380
1381 LogEvent event1(/*uid=*/0, /*pid=*/0);
1382 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1383 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1384
1385 // has one slice
1386 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1387 ValueMetricProducer::Interval curInterval =
1388 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1389 EXPECT_EQ(10, curInterval.value.long_value);
1390 EXPECT_EQ(true, curInterval.hasValue);
1391
1392 LogEvent event2(/*uid=*/0, /*pid=*/0);
1393 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
1394 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1395
1396 // has one slice
1397 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1398 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1399 EXPECT_EQ(20, curInterval.value.long_value);
1400
1401 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1402 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {bucketSizeNs},
1403 {bucketStartTimeNs}, {bucket2StartTimeNs});
1404 }
1405
TEST(ValueMetricProducerTest,TestPushedAggregateAvg)1406 TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
1407 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1408 metric.set_aggregation_type(ValueMetric::AVG);
1409
1410 sp<EventMatcherWizard> eventMatcherWizard =
1411 createEventMatcherWizard(tagId, logEventMatcherIndex);
1412 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1413 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1414
1415 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1416 logEventMatcherIndex, eventMatcherWizard, -1,
1417 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1418 valueProducer.prepareFirstBucket();
1419
1420 LogEvent event1(/*uid=*/0, /*pid=*/0);
1421 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1422
1423 LogEvent event2(/*uid=*/0, /*pid=*/0);
1424 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
1425 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1426 // has one slice
1427 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1428 ValueMetricProducer::Interval curInterval;
1429 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1430 EXPECT_EQ(10, curInterval.value.long_value);
1431 EXPECT_EQ(true, curInterval.hasValue);
1432 EXPECT_EQ(1, curInterval.sampleSize);
1433
1434 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1435
1436 // has one slice
1437 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1438 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1439 EXPECT_EQ(25, curInterval.value.long_value);
1440 EXPECT_EQ(2, curInterval.sampleSize);
1441
1442 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1443 ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
1444 ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1445
1446 EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
1447 12.5) < epsilon);
1448 }
1449
TEST(ValueMetricProducerTest,TestPushedAggregateSum)1450 TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
1451 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1452 metric.set_aggregation_type(ValueMetric::SUM);
1453
1454 sp<EventMatcherWizard> eventMatcherWizard =
1455 createEventMatcherWizard(tagId, logEventMatcherIndex);
1456 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1457 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1458
1459 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1460 logEventMatcherIndex, eventMatcherWizard, -1,
1461 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1462 valueProducer.prepareFirstBucket();
1463
1464 LogEvent event1(/*uid=*/0, /*pid=*/0);
1465 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1466
1467 LogEvent event2(/*uid=*/0, /*pid=*/0);
1468 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
1469 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1470 // has one slice
1471 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1472 ValueMetricProducer::Interval curInterval =
1473 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1474 EXPECT_EQ(10, curInterval.value.long_value);
1475 EXPECT_EQ(true, curInterval.hasValue);
1476
1477 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1478
1479 // has one slice
1480 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1481 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1482 EXPECT_EQ(25, curInterval.value.long_value);
1483
1484 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1485 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs},
1486 {bucketStartTimeNs}, {bucket2StartTimeNs});
1487 }
1488
TEST(ValueMetricProducerTest,TestSkipZeroDiffOutput)1489 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
1490 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1491 metric.set_aggregation_type(ValueMetric::MIN);
1492 metric.set_use_diff(true);
1493
1494 sp<EventMatcherWizard> eventMatcherWizard =
1495 createEventMatcherWizard(tagId, logEventMatcherIndex);
1496 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1497 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1498
1499 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1500 logEventMatcherIndex, eventMatcherWizard, -1,
1501 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1502 valueProducer.prepareFirstBucket();
1503
1504 LogEvent event1(/*uid=*/0, /*pid=*/0);
1505 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1506 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1507
1508 // has one slice
1509 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1510 ValueMetricProducer::Interval curInterval =
1511 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1512 ValueMetricProducer::BaseInfo curBaseInfo =
1513 valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1514 EXPECT_EQ(true, curBaseInfo.hasBase);
1515 EXPECT_EQ(10, curBaseInfo.base.long_value);
1516 EXPECT_EQ(false, curInterval.hasValue);
1517
1518 LogEvent event2(/*uid=*/0, /*pid=*/0);
1519 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 15);
1520 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1521
1522 // has one slice
1523 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1524 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1525 EXPECT_EQ(true, curInterval.hasValue);
1526 EXPECT_EQ(5, curInterval.value.long_value);
1527
1528 // no change in data.
1529 LogEvent event3(/*uid=*/0, /*pid=*/0);
1530 CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 15);
1531 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1532
1533 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1534 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1535 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1536 EXPECT_EQ(true, curBaseInfo.hasBase);
1537 EXPECT_EQ(15, curBaseInfo.base.long_value);
1538 EXPECT_EQ(true, curInterval.hasValue);
1539 EXPECT_EQ(0, curInterval.value.long_value);
1540
1541 LogEvent event4(/*uid=*/0, /*pid=*/0);
1542 CreateRepeatedValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 15);
1543 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1544 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1545 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1546 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1547 EXPECT_EQ(true, curBaseInfo.hasBase);
1548 EXPECT_EQ(15, curBaseInfo.base.long_value);
1549 EXPECT_EQ(true, curInterval.hasValue);
1550 EXPECT_EQ(0, curInterval.value.long_value);
1551
1552 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1553 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs},
1554 {bucketStartTimeNs}, {bucket2StartTimeNs});
1555 }
1556
TEST(ValueMetricProducerTest,TestSkipZeroDiffOutputMultiValue)1557 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
1558 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1559 metric.mutable_value_field()->add_child()->set_field(3);
1560 metric.set_aggregation_type(ValueMetric::MIN);
1561 metric.set_use_diff(true);
1562
1563 sp<EventMatcherWizard> eventMatcherWizard =
1564 createEventMatcherWizard(tagId, logEventMatcherIndex);
1565 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1566 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1567
1568 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1569 logEventMatcherIndex, eventMatcherWizard, -1,
1570 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1571 valueProducer.prepareFirstBucket();
1572
1573 LogEvent event1(/*uid=*/0, /*pid=*/0);
1574 CreateThreeValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10, 20);
1575
1576 LogEvent event2(/*uid=*/0, /*pid=*/0);
1577 CreateThreeValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 1, 15, 22);
1578
1579 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1580 // has one slice
1581 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1582 ValueMetricProducer::Interval curInterval =
1583 valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1584 ValueMetricProducer::BaseInfo curBaseInfo =
1585 valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1586 EXPECT_EQ(true, curBaseInfo.hasBase);
1587 EXPECT_EQ(10, curBaseInfo.base.long_value);
1588 EXPECT_EQ(false, curInterval.hasValue);
1589 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1590 EXPECT_EQ(true, curBaseInfo.hasBase);
1591 EXPECT_EQ(20, curBaseInfo.base.long_value);
1592 EXPECT_EQ(false, curInterval.hasValue);
1593
1594 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1595
1596 // has one slice
1597 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1598 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1599 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1600 EXPECT_EQ(true, curInterval.hasValue);
1601 EXPECT_EQ(5, curInterval.value.long_value);
1602 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
1603 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1604 EXPECT_EQ(true, curInterval.hasValue);
1605 EXPECT_EQ(2, curInterval.value.long_value);
1606
1607 // no change in first value field
1608 LogEvent event3(/*uid=*/0, /*pid=*/0);
1609 CreateThreeValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 1, 15, 25);
1610
1611 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1612 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1613 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1614 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1615
1616 EXPECT_EQ(true, curBaseInfo.hasBase);
1617 EXPECT_EQ(15, curBaseInfo.base.long_value);
1618 EXPECT_EQ(true, curInterval.hasValue);
1619 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
1620 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1621 EXPECT_EQ(true, curBaseInfo.hasBase);
1622 EXPECT_EQ(25, curBaseInfo.base.long_value);
1623 EXPECT_EQ(true, curInterval.hasValue);
1624
1625 LogEvent event4(/*uid=*/0, /*pid=*/0);
1626 CreateThreeValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 1, 15, 29);
1627
1628 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1629 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1630 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1631 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1632 EXPECT_EQ(true, curBaseInfo.hasBase);
1633 EXPECT_EQ(15, curBaseInfo.base.long_value);
1634 EXPECT_EQ(true, curInterval.hasValue);
1635 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
1636 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1637 EXPECT_EQ(true, curBaseInfo.hasBase);
1638 EXPECT_EQ(29, curBaseInfo.base.long_value);
1639 EXPECT_EQ(true, curInterval.hasValue);
1640
1641 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1642
1643 ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
1644 ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
1645 ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
1646 ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
1647
1648 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
1649 EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
1650 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
1651 EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
1652 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
1653
1654 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
1655 EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
1656 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
1657 }
1658
1659 /*
1660 * Tests zero default base.
1661 */
TEST(ValueMetricProducerTest,TestUseZeroDefaultBase)1662 TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
1663 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1664 metric.mutable_dimensions_in_what()->set_field(tagId);
1665 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1666 metric.set_use_zero_default_base(true);
1667
1668 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1669 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1670 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1671 vector<std::shared_ptr<LogEvent>>* data) {
1672 data->clear();
1673 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1674 return true;
1675 }));
1676
1677 sp<ValueMetricProducer> valueProducer =
1678 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1679
1680 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1681 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1682 auto& interval1 = iter->second.intervals[0];
1683 auto iterBase = valueProducer->mCurrentBaseInfo.begin();
1684 auto& baseInfo1 = iterBase->second.baseInfos[0];
1685 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1686 EXPECT_EQ(true, baseInfo1.hasBase);
1687 EXPECT_EQ(3, baseInfo1.base.long_value);
1688 EXPECT_EQ(false, interval1.hasValue);
1689 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1690 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1691 vector<shared_ptr<LogEvent>> allData;
1692
1693 allData.clear();
1694 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1695 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1696
1697 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1698 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1699 EXPECT_EQ(true, baseInfo1.hasBase);
1700 EXPECT_EQ(11, baseInfo1.base.long_value);
1701 EXPECT_EQ(false, interval1.hasValue);
1702 EXPECT_EQ(8, interval1.value.long_value);
1703
1704 auto it = valueProducer->mCurrentSlicedBucket.begin();
1705 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1706 if (it != iter) {
1707 break;
1708 }
1709 }
1710 auto itBase = valueProducer->mCurrentBaseInfo.begin();
1711 for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
1712 if (itBase != iterBase) {
1713 break;
1714 }
1715 }
1716 EXPECT_TRUE(it != iter);
1717 EXPECT_TRUE(itBase != iterBase);
1718 auto& interval2 = it->second.intervals[0];
1719 auto& baseInfo2 = itBase->second.baseInfos[0];
1720 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1721 EXPECT_EQ(true, baseInfo2.hasBase);
1722 EXPECT_EQ(4, baseInfo2.base.long_value);
1723 EXPECT_EQ(false, interval2.hasValue);
1724 EXPECT_EQ(4, interval2.value.long_value);
1725
1726 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1727 auto iterator = valueProducer->mPastBuckets.begin();
1728 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1729 EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1730 iterator++;
1731 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1732 EXPECT_EQ(4, iterator->second[0].values[0].long_value);
1733 }
1734
1735 /*
1736 * Tests using zero default base with failed pull.
1737 */
TEST(ValueMetricProducerTest,TestUseZeroDefaultBaseWithPullFailures)1738 TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
1739 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1740 metric.mutable_dimensions_in_what()->set_field(tagId);
1741 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1742 metric.set_use_zero_default_base(true);
1743
1744 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1745 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1746 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1747 vector<std::shared_ptr<LogEvent>>* data) {
1748 data->clear();
1749 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1750 return true;
1751 }));
1752
1753 sp<ValueMetricProducer> valueProducer =
1754 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1755
1756 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1757 const auto& it = valueProducer->mCurrentSlicedBucket.begin();
1758 ValueMetricProducer::Interval& interval1 = it->second.intervals[0];
1759 ValueMetricProducer::BaseInfo& baseInfo1 =
1760 valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())
1761 ->second.baseInfos[0];
1762 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1763 EXPECT_EQ(true, baseInfo1.hasBase);
1764 EXPECT_EQ(3, baseInfo1.base.long_value);
1765 EXPECT_EQ(false, interval1.hasValue);
1766 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1767 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1768 vector<shared_ptr<LogEvent>> allData;
1769
1770 allData.clear();
1771 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1772 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1773
1774 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1775 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1776 EXPECT_EQ(true, baseInfo1.hasBase);
1777 EXPECT_EQ(11, baseInfo1.base.long_value);
1778 EXPECT_EQ(false, interval1.hasValue);
1779 EXPECT_EQ(8, interval1.value.long_value);
1780
1781 auto it2 = valueProducer->mCurrentSlicedBucket.begin();
1782 for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
1783 if (it2 != it) {
1784 break;
1785 }
1786 }
1787 EXPECT_TRUE(it2 != it);
1788 ValueMetricProducer::Interval& interval2 = it2->second.intervals[0];
1789 ValueMetricProducer::BaseInfo& baseInfo2 =
1790 valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())
1791 ->second.baseInfos[0];
1792 EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1793 EXPECT_EQ(true, baseInfo2.hasBase);
1794 EXPECT_EQ(4, baseInfo2.base.long_value);
1795 EXPECT_EQ(false, interval2.hasValue);
1796 EXPECT_EQ(4, interval2.value.long_value);
1797 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1798
1799 // next pull somehow did not happen, skip to end of bucket 3
1800 allData.clear();
1801 allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
1802 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1803
1804 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1805 EXPECT_EQ(true, baseInfo2.hasBase);
1806 EXPECT_EQ(5, baseInfo2.base.long_value);
1807 EXPECT_EQ(false, interval2.hasValue);
1808 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1809 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1810
1811 allData.clear();
1812 allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 13));
1813 allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 1, 5));
1814 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1815
1816 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1817 // Get new references now that entries have been deleted from the map
1818 const auto& it3 = valueProducer->mCurrentSlicedBucket.begin();
1819 const auto& it4 = std::next(valueProducer->mCurrentSlicedBucket.begin());
1820 ASSERT_EQ(it3->second.intervals.size(), 1);
1821 ASSERT_EQ(it4->second.intervals.size(), 1);
1822 ValueMetricProducer::Interval& interval3 = it3->second.intervals[0];
1823 ValueMetricProducer::Interval& interval4 = it4->second.intervals[0];
1824 ValueMetricProducer::BaseInfo& baseInfo3 =
1825 valueProducer->mCurrentBaseInfo.find(it3->first.getDimensionKeyInWhat())
1826 ->second.baseInfos[0];
1827 ValueMetricProducer::BaseInfo& baseInfo4 =
1828 valueProducer->mCurrentBaseInfo.find(it4->first.getDimensionKeyInWhat())
1829 ->second.baseInfos[0];
1830
1831 EXPECT_EQ(true, baseInfo3.hasBase);
1832 EXPECT_EQ(5, baseInfo3.base.long_value);
1833 EXPECT_EQ(false, interval3.hasValue);
1834 EXPECT_EQ(5, interval3.value.long_value);
1835 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1836
1837 EXPECT_EQ(true, baseInfo4.hasBase);
1838 EXPECT_EQ(13, baseInfo4.base.long_value);
1839 EXPECT_EQ(false, interval4.hasValue);
1840 EXPECT_EQ(8, interval4.value.long_value);
1841
1842 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1843 }
1844
1845 /*
1846 * Tests trim unused dimension key if no new data is seen in an entire bucket.
1847 */
TEST(ValueMetricProducerTest,TestTrimUnusedDimensionKey)1848 TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
1849 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1850 metric.mutable_dimensions_in_what()->set_field(tagId);
1851 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1852
1853 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1854 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1855 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1856 vector<std::shared_ptr<LogEvent>>* data) {
1857 data->clear();
1858 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1859 return true;
1860 }));
1861
1862 sp<ValueMetricProducer> valueProducer =
1863 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1864
1865 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1866 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1867 auto& interval1 = iter->second.intervals[0];
1868 auto iterBase = valueProducer->mCurrentBaseInfo.begin();
1869 auto& baseInfo1 = iterBase->second.baseInfos[0];
1870 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1871 EXPECT_EQ(true, baseInfo1.hasBase);
1872 EXPECT_EQ(3, baseInfo1.base.long_value);
1873 EXPECT_EQ(false, interval1.hasValue);
1874 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1875
1876 vector<shared_ptr<LogEvent>> allData;
1877 allData.clear();
1878 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1879 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1880 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1881
1882 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1883 EXPECT_EQ(true, baseInfo1.hasBase);
1884 EXPECT_EQ(11, baseInfo1.base.long_value);
1885 EXPECT_EQ(false, interval1.hasValue);
1886 EXPECT_EQ(8, interval1.value.long_value);
1887 EXPECT_FALSE(interval1.seenNewData);
1888 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs},
1889 {bucketStartTimeNs}, {bucket2StartTimeNs});
1890
1891 auto it = valueProducer->mCurrentSlicedBucket.begin();
1892 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1893 if (it != iter) {
1894 break;
1895 }
1896 }
1897 auto itBase = valueProducer->mCurrentBaseInfo.begin();
1898 for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
1899 if (itBase != iterBase) {
1900 break;
1901 }
1902 }
1903 EXPECT_TRUE(it != iter);
1904 EXPECT_TRUE(itBase != iterBase);
1905 auto interval2 = it->second.intervals[0];
1906 auto baseInfo2 = itBase->second.baseInfos[0];
1907 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1908 EXPECT_EQ(true, baseInfo2.hasBase);
1909 EXPECT_EQ(4, baseInfo2.base.long_value);
1910 EXPECT_EQ(false, interval2.hasValue);
1911 EXPECT_FALSE(interval2.seenNewData);
1912
1913 // next pull somehow did not happen, skip to end of bucket 3
1914 allData.clear();
1915 allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
1916 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1917 // Only one interval left. One was trimmed.
1918 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1919 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1920 baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1921 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1922 EXPECT_EQ(true, baseInfo2.hasBase);
1923 EXPECT_EQ(5, baseInfo2.base.long_value);
1924 EXPECT_EQ(false, interval2.hasValue);
1925 EXPECT_FALSE(interval2.seenNewData);
1926 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs},
1927 {bucketStartTimeNs}, {bucket2StartTimeNs});
1928
1929 allData.clear();
1930 allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 14));
1931 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1932
1933 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1934 baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1935 EXPECT_EQ(true, baseInfo2.hasBase);
1936 EXPECT_EQ(14, baseInfo2.base.long_value);
1937 EXPECT_EQ(false, interval2.hasValue);
1938 EXPECT_FALSE(interval2.seenNewData);
1939 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1940 auto iterator = valueProducer->mPastBuckets.begin();
1941 EXPECT_EQ(bucket4StartTimeNs, iterator->second[0].mBucketStartNs);
1942 EXPECT_EQ(bucket5StartTimeNs, iterator->second[0].mBucketEndNs);
1943 EXPECT_EQ(9, iterator->second[0].values[0].long_value);
1944 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1945 iterator++;
1946 EXPECT_EQ(bucketStartTimeNs, iterator->second[0].mBucketStartNs);
1947 EXPECT_EQ(bucket2StartTimeNs, iterator->second[0].mBucketEndNs);
1948 EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1949 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1950 }
1951
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailAfterConditionChange_EndOfBucket)1952 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
1953 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1954
1955 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1956 // Used by onConditionChanged.
1957 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _))
1958 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1959 vector<std::shared_ptr<LogEvent>>* data) {
1960 data->clear();
1961 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1962 return true;
1963 }));
1964
1965 sp<ValueMetricProducer> valueProducer =
1966 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1967 ConditionState::kFalse);
1968
1969 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1970 // has one slice
1971 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1972 ValueMetricProducer::Interval& curInterval =
1973 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1974 ValueMetricProducer::BaseInfo& curBaseInfo =
1975 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1976 EXPECT_EQ(true, curBaseInfo.hasBase);
1977 EXPECT_EQ(100, curBaseInfo.base.long_value);
1978 EXPECT_EQ(false, curInterval.hasValue);
1979
1980 vector<shared_ptr<LogEvent>> allData;
1981 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
1982 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1983 EXPECT_EQ(false, curBaseInfo.hasBase);
1984 EXPECT_EQ(false, curInterval.hasValue);
1985 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
1986 }
1987
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailAfterConditionChange)1988 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
1989 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1990
1991 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1992 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1993 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1994 vector<std::shared_ptr<LogEvent>>* data) {
1995 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // Condition change to true.
1996 data->clear();
1997 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1998 return true;
1999 }))
2000 .WillOnce(Return(false));
2001
2002 sp<ValueMetricProducer> valueProducer =
2003 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2004 ConditionState::kFalse);
2005
2006 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
2007
2008 // has one slice
2009 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2010 ValueMetricProducer::Interval& curInterval =
2011 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2012 ValueMetricProducer::BaseInfo& curBaseInfo =
2013 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2014 EXPECT_EQ(true, curBaseInfo.hasBase);
2015 EXPECT_EQ(100, curBaseInfo.base.long_value);
2016 EXPECT_EQ(false, curInterval.hasValue);
2017 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2018
2019 valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
2020
2021 // has one slice
2022 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2023 EXPECT_EQ(false, curInterval.hasValue);
2024 EXPECT_EQ(false, curBaseInfo.hasBase);
2025 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2026 }
2027
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailBeforeConditionChange)2028 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
2029 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2030
2031 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2032 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2033 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2034 vector<std::shared_ptr<LogEvent>>* data) {
2035 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
2036 data->clear();
2037 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
2038 return false;
2039 }))
2040 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2041 vector<std::shared_ptr<LogEvent>>* data) {
2042 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to false.
2043 data->clear();
2044 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
2045 return true;
2046 }));
2047
2048 sp<ValueMetricProducer> valueProducer =
2049 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2050 ConditionState::kFalse);
2051
2052 // Don't directly set mCondition; the real code never does that. Go through regular code path
2053 // to avoid unexpected behaviors.
2054 // valueProducer->mCondition = ConditionState::kTrue;
2055 valueProducer->onConditionChanged(true, bucketStartTimeNs);
2056
2057 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2058
2059 valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
2060 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2061 ValueMetricProducer::Interval& curInterval =
2062 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2063 ValueMetricProducer::BaseInfo curBaseInfo =
2064 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2065 EXPECT_EQ(false, curBaseInfo.hasBase);
2066 EXPECT_EQ(false, curInterval.hasValue);
2067 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2068 }
2069
TEST(ValueMetricProducerTest,TestResetBaseOnPullDelayExceeded)2070 TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
2071 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2072 metric.set_condition(StringToId("SCREEN_ON"));
2073 metric.set_max_pull_delay_sec(0);
2074
2075 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2076 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _))
2077 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2078 vector<std::shared_ptr<LogEvent>>* data) {
2079 data->clear();
2080 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
2081 return true;
2082 }));
2083
2084 sp<ValueMetricProducer> valueProducer =
2085 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2086 ConditionState::kFalse);
2087
2088 // Max delay is set to 0 so pull will exceed max delay.
2089 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2090 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2091 }
2092
TEST(ValueMetricProducerTest,TestResetBaseOnPullTooLate)2093 TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
2094 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2095
2096 sp<EventMatcherWizard> eventMatcherWizard =
2097 createEventMatcherWizard(tagId, logEventMatcherIndex);
2098 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2099 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2100 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2101 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
2102
2103 ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
2104 protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
2105 bucket2StartTimeNs, bucket2StartTimeNs, pullerManager);
2106 valueProducer.prepareFirstBucket();
2107 valueProducer.mCondition = ConditionState::kFalse;
2108
2109 // Event should be skipped since it is from previous bucket.
2110 // Pull should not be called.
2111 valueProducer.onConditionChanged(true, bucketStartTimeNs);
2112 ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
2113 }
2114
TEST(ValueMetricProducerTest,TestBaseSetOnConditionChange)2115 TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
2116 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2117
2118 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2119 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _))
2120 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2121 vector<std::shared_ptr<LogEvent>>* data) {
2122 data->clear();
2123 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
2124 return true;
2125 }));
2126
2127 sp<ValueMetricProducer> valueProducer =
2128 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2129 ConditionState::kFalse);
2130 valueProducer->mHasGlobalBase = false;
2131
2132 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2133 valueProducer->mHasGlobalBase = true;
2134 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2135 ValueMetricProducer::Interval& curInterval =
2136 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2137 ValueMetricProducer::BaseInfo curBaseInfo =
2138 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2139 EXPECT_EQ(true, curBaseInfo.hasBase);
2140 EXPECT_EQ(100, curBaseInfo.base.long_value);
2141 EXPECT_EQ(false, curInterval.hasValue);
2142 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2143 }
2144
2145 /*
2146 * Tests that a bucket is marked invalid when a condition change pull fails.
2147 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenOneConditionFailed)2148 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
2149 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2150
2151 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2152 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2153 // First onConditionChanged
2154 .WillOnce(Return(false))
2155 // Second onConditionChanged
2156 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2157 vector<std::shared_ptr<LogEvent>>* data) {
2158 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
2159 data->clear();
2160 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2161 return true;
2162 }));
2163
2164 sp<ValueMetricProducer> valueProducer =
2165 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2166 ConditionState::kTrue);
2167
2168 // Bucket start.
2169 vector<shared_ptr<LogEvent>> allData;
2170 allData.clear();
2171 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2172 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2173
2174 // This will fail and should invalidate the whole bucket since we do not have all the data
2175 // needed to compute the metric value when the screen was on.
2176 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2177 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2178
2179 // Bucket end.
2180 allData.clear();
2181 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2182 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2183
2184 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2185
2186 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2187 // Contains base from last pull which was successful.
2188 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2189 ValueMetricProducer::Interval& curInterval =
2190 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2191 ValueMetricProducer::BaseInfo curBaseInfo =
2192 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2193 EXPECT_EQ(true, curBaseInfo.hasBase);
2194 EXPECT_EQ(140, curBaseInfo.base.long_value);
2195 EXPECT_EQ(false, curInterval.hasValue);
2196 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2197
2198 // Check dump report.
2199 ProtoOutputStream output;
2200 std::set<string> strSet;
2201 valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
2202 FAST /* dumpLatency */, &strSet, &output);
2203
2204 StatsLogReport report = outputStreamToProto(&output);
2205 EXPECT_TRUE(report.has_value_metrics());
2206 ASSERT_EQ(0, report.value_metrics().data_size());
2207 ASSERT_EQ(1, report.value_metrics().skipped_size());
2208
2209 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2210 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2211 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2212 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2213 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2214
2215 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2216 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2217 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2218 }
2219
2220 /*
2221 * Tests that a bucket is marked invalid when the guardrail is hit.
2222 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenGuardRailHit)2223 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
2224 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2225 metric.mutable_dimensions_in_what()->set_field(tagId);
2226 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2227 metric.set_condition(StringToId("SCREEN_ON"));
2228
2229 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2230 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 2, _))
2231 // First onConditionChanged
2232 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2233 vector<std::shared_ptr<LogEvent>>* data) {
2234 for (int i = 0; i < 2000; i++) {
2235 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
2236 }
2237 return true;
2238 }));
2239
2240 sp<ValueMetricProducer> valueProducer =
2241 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2242 ConditionState::kFalse);
2243
2244 valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
2245 EXPECT_EQ(true, valueProducer->mCurrentBucketIsSkipped);
2246 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2247 ASSERT_EQ(0UL, valueProducer->mSkippedBuckets.size());
2248
2249 // Bucket 2 start.
2250 vector<shared_ptr<LogEvent>> allData;
2251 allData.clear();
2252 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 10));
2253 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2254
2255 // First bucket added to mSkippedBuckets after flush.
2256 ASSERT_EQ(1UL, valueProducer->mSkippedBuckets.size());
2257
2258 // Check dump report.
2259 ProtoOutputStream output;
2260 std::set<string> strSet;
2261 valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2262 true, FAST /* dumpLatency */, &strSet, &output);
2263
2264 StatsLogReport report = outputStreamToProto(&output);
2265 EXPECT_TRUE(report.has_value_metrics());
2266 ASSERT_EQ(0, report.value_metrics().data_size());
2267 ASSERT_EQ(1, report.value_metrics().skipped_size());
2268
2269 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2270 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2271 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2272 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2273 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2274
2275 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2276 EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
2277 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2278 }
2279
2280 /*
2281 * Tests that a bucket is marked invalid when the bucket's initial pull fails.
2282 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenInitialPullFailed)2283 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
2284 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2285
2286 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2287 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2288 // First onConditionChanged
2289 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2290 vector<std::shared_ptr<LogEvent>>* data) {
2291 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
2292 data->clear();
2293 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
2294 return true;
2295 }))
2296 // Second onConditionChanged
2297 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2298 vector<std::shared_ptr<LogEvent>>* data) {
2299 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
2300 data->clear();
2301 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2302 return true;
2303 }));
2304
2305 sp<ValueMetricProducer> valueProducer =
2306 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2307 ConditionState::kTrue);
2308
2309 // Bucket start.
2310 vector<shared_ptr<LogEvent>> allData;
2311 allData.clear();
2312 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2313 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
2314
2315 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2316 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2317
2318 // Bucket end.
2319 allData.clear();
2320 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2321 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2322
2323 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2324
2325 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2326 // Contains base from last pull which was successful.
2327 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2328 ValueMetricProducer::Interval& curInterval =
2329 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2330 ValueMetricProducer::BaseInfo curBaseInfo =
2331 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2332 EXPECT_EQ(true, curBaseInfo.hasBase);
2333 EXPECT_EQ(140, curBaseInfo.base.long_value);
2334 EXPECT_EQ(false, curInterval.hasValue);
2335 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2336
2337 // Check dump report.
2338 ProtoOutputStream output;
2339 std::set<string> strSet;
2340 valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2341 true, FAST /* dumpLatency */, &strSet, &output);
2342
2343 StatsLogReport report = outputStreamToProto(&output);
2344 EXPECT_TRUE(report.has_value_metrics());
2345 ASSERT_EQ(0, report.value_metrics().data_size());
2346 ASSERT_EQ(1, report.value_metrics().skipped_size());
2347
2348 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2349 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2350 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2351 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2352 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2353
2354 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2355 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2356 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2357 }
2358
2359 /*
2360 * Tests that a bucket is marked invalid when the bucket's final pull fails
2361 * (i.e. failed pull on bucket boundary).
2362 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenLastPullFailed)2363 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
2364 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2365
2366 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2367 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2368 // First onConditionChanged
2369 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2370 vector<std::shared_ptr<LogEvent>>* data) {
2371 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
2372 data->clear();
2373 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
2374 return true;
2375 }))
2376 // Second onConditionChanged
2377 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2378 vector<std::shared_ptr<LogEvent>>* data) {
2379 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
2380 data->clear();
2381 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2382 return true;
2383 }));
2384
2385 sp<ValueMetricProducer> valueProducer =
2386 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2387 ConditionState::kTrue);
2388
2389 // Bucket start.
2390 vector<shared_ptr<LogEvent>> allData;
2391 allData.clear();
2392 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2393 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2394
2395 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2396 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2397
2398 // Bucket end.
2399 allData.clear();
2400 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2401 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2402
2403 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2404
2405 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2406 // Last pull failed so base has been reset.
2407 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2408 ValueMetricProducer::Interval& curInterval =
2409 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2410 ValueMetricProducer::BaseInfo curBaseInfo =
2411 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2412 EXPECT_EQ(false, curBaseInfo.hasBase);
2413 EXPECT_EQ(false, curInterval.hasValue);
2414 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2415
2416 // Check dump report.
2417 ProtoOutputStream output;
2418 std::set<string> strSet;
2419 valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2420 true, FAST /* dumpLatency */, &strSet, &output);
2421
2422 StatsLogReport report = outputStreamToProto(&output);
2423 EXPECT_TRUE(report.has_value_metrics());
2424 ASSERT_EQ(0, report.value_metrics().data_size());
2425 ASSERT_EQ(1, report.value_metrics().skipped_size());
2426
2427 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2428 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2429 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2430 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2431 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2432
2433 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2434 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2435 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
2436 }
2437
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onDataPulled)2438 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
2439 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2440 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2441 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2442 // Start bucket.
2443 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2444 vector<std::shared_ptr<LogEvent>>* data) {
2445 data->clear();
2446 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2447 return true;
2448 }));
2449
2450 sp<ValueMetricProducer> valueProducer =
2451 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2452
2453 // Bucket 2 start.
2454 vector<shared_ptr<LogEvent>> allData;
2455 allData.clear();
2456 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
2457 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2458 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2459 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
2460
2461 // Bucket 3 empty.
2462 allData.clear();
2463 allData.push_back(CreateNoValuesLogEvent(tagId, bucket3StartTimeNs + 1));
2464 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
2465 // Data has been trimmed.
2466 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2467 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
2468 }
2469
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onConditionChanged)2470 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
2471 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2472
2473 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2474 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2475 // First onConditionChanged
2476 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2477 vector<std::shared_ptr<LogEvent>>* data) {
2478 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2479 data->clear();
2480 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2481 return true;
2482 }))
2483 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2484 vector<std::shared_ptr<LogEvent>>* data) {
2485 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2486 data->clear();
2487 return true;
2488 }));
2489
2490 sp<ValueMetricProducer> valueProducer =
2491 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2492 ConditionState::kFalse);
2493
2494 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2495 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2496 ValueMetricProducer::Interval& curInterval =
2497 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2498 ValueMetricProducer::BaseInfo curBaseInfo =
2499 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2500 EXPECT_EQ(true, curBaseInfo.hasBase);
2501 EXPECT_EQ(false, curInterval.hasValue);
2502 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2503
2504 // Empty pull.
2505 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2506 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2507 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2508 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2509 EXPECT_EQ(false, curBaseInfo.hasBase);
2510 EXPECT_EQ(false, curInterval.hasValue);
2511 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2512 }
2513
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onBucketBoundary)2514 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
2515 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2516
2517 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2518 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2519 // First onConditionChanged
2520 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2521 vector<std::shared_ptr<LogEvent>>* data) {
2522 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2523 data->clear();
2524 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2525 return true;
2526 }))
2527 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2528 vector<std::shared_ptr<LogEvent>>* data) {
2529 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 11);
2530 data->clear();
2531 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
2532 return true;
2533 }))
2534 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2535 vector<std::shared_ptr<LogEvent>>* data) {
2536 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 12);
2537 data->clear();
2538 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
2539 return true;
2540 }));
2541
2542 sp<ValueMetricProducer> valueProducer =
2543 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2544 ConditionState::kFalse);
2545
2546 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2547 valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
2548 valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
2549 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2550 ValueMetricProducer::Interval& curInterval =
2551 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2552 ValueMetricProducer::BaseInfo curBaseInfo =
2553 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2554 EXPECT_EQ(true, curBaseInfo.hasBase);
2555 EXPECT_EQ(true, curInterval.hasValue);
2556 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2557
2558 // End of bucket
2559 vector<shared_ptr<LogEvent>> allData;
2560 allData.clear();
2561 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2562 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2563 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2564 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2565 // Data is empty, base should be reset.
2566 EXPECT_EQ(false, curBaseInfo.hasBase);
2567 EXPECT_EQ(5, curBaseInfo.base.long_value);
2568 EXPECT_EQ(false, curInterval.hasValue);
2569 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2570
2571 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
2572 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1},
2573 {bucketStartTimeNs}, {bucket2StartTimeNs});
2574 }
2575
TEST(ValueMetricProducerTest,TestPartialResetOnBucketBoundaries)2576 TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
2577 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2578 metric.mutable_dimensions_in_what()->set_field(tagId);
2579 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2580 metric.set_condition(StringToId("SCREEN_ON"));
2581
2582 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2583 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _))
2584 // First onConditionChanged
2585 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2586 vector<std::shared_ptr<LogEvent>>* data) {
2587 data->clear();
2588 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2589 return true;
2590 }));
2591
2592 sp<ValueMetricProducer> valueProducer =
2593 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2594 ConditionState::kFalse);
2595
2596 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2597 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2598
2599 // End of bucket
2600 vector<shared_ptr<LogEvent>> allData;
2601 allData.clear();
2602 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 2));
2603 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2604
2605 // Key 1 should be reset since in not present in the most pull.
2606 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
2607 auto iterator = valueProducer->mCurrentSlicedBucket.begin();
2608 auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
2609 EXPECT_EQ(true, baseInfoIter->second.baseInfos[0].hasBase);
2610 EXPECT_EQ(2, baseInfoIter->second.baseInfos[0].base.long_value);
2611 EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
2612 iterator++;
2613 baseInfoIter++;
2614 EXPECT_EQ(false, baseInfoIter->second.baseInfos[0].hasBase);
2615 EXPECT_EQ(1, baseInfoIter->second.baseInfos[0].base.long_value);
2616 EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
2617
2618 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2619 }
2620
TEST_P(ValueMetricProducerTest_PartialBucket,TestFullBucketResetWhenLastBucketInvalid)2621 TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketInvalid) {
2622 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2623
2624 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2625 int64_t partialBucketSplitTimeNs = bucketStartTimeNs + bucketSizeNs / 2;
2626 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2627 // Initialization.
2628 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2629 vector<std::shared_ptr<LogEvent>>* data) {
2630 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
2631 data->clear();
2632 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2633 return true;
2634 }))
2635 // notifyAppUpgrade.
2636 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
2637 const int64_t eventTimeNs,
2638 vector<std::shared_ptr<LogEvent>>* data) {
2639 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
2640 data->clear();
2641 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
2642 return true;
2643 }));
2644 sp<ValueMetricProducer> valueProducer =
2645 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2646 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2647
2648 switch (GetParam()) {
2649 case APP_UPGRADE:
2650 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
2651 break;
2652 case BOOT_COMPLETE:
2653 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
2654 break;
2655 }
2656 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
2657 EXPECT_EQ(0, valueProducer->getCurrentBucketNum());
2658 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
2659 {partialBucketSplitTimeNs - bucketStartTimeNs},
2660 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
2661 ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
2662
2663 vector<shared_ptr<LogEvent>> allData;
2664 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 4));
2665 // Pull fails and arrives late.
2666 valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
2667 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
2668 {partialBucketSplitTimeNs - bucketStartTimeNs},
2669 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
2670 ASSERT_EQ(1, valueProducer->mSkippedBuckets.size());
2671 ASSERT_EQ(2, valueProducer->mSkippedBuckets[0].dropEvents.size());
2672 EXPECT_EQ(PULL_FAILED, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
2673 EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[0].dropEvents[1].reason);
2674 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
2675 EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
2676 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2677 }
2678
TEST(ValueMetricProducerTest,TestBucketBoundariesOnConditionChange)2679 TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
2680 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2681 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2682 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2683 // Second onConditionChanged.
2684 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2685 vector<std::shared_ptr<LogEvent>>* data) {
2686 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
2687 data->clear();
2688 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
2689 return true;
2690 }))
2691 // Third onConditionChanged.
2692 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2693 vector<std::shared_ptr<LogEvent>>* data) {
2694 EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 10);
2695 data->clear();
2696 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
2697 return true;
2698 }));
2699
2700 sp<ValueMetricProducer> valueProducer =
2701 ValueMetricProducerTestHelper::createValueProducerWithCondition(
2702 pullerManager, metric, ConditionState::kUnknown);
2703
2704 valueProducer->onConditionChanged(false, bucketStartTimeNs);
2705 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2706
2707 // End of first bucket
2708 vector<shared_ptr<LogEvent>> allData;
2709 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 4));
2710 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2711 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2712
2713 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2714 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2715 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2716 auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2717 EXPECT_EQ(true, curBaseInfo.hasBase);
2718 EXPECT_EQ(5, curBaseInfo.base.long_value);
2719 EXPECT_EQ(false, curInterval.hasValue);
2720
2721 valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
2722
2723 // Bucket should have been completed.
2724 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10},
2725 {bucket2StartTimeNs}, {bucket3StartTimeNs});
2726 }
2727
TEST(ValueMetricProducerTest,TestLateOnDataPulledWithoutDiff)2728 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
2729 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2730 metric.set_use_diff(false);
2731
2732 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2733 sp<ValueMetricProducer> valueProducer =
2734 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2735
2736 vector<shared_ptr<LogEvent>> allData;
2737 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2738 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2739
2740 allData.clear();
2741 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2742 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2743
2744 // Bucket should have been completed.
2745 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs},
2746 {bucketStartTimeNs}, {bucket2StartTimeNs});
2747 }
2748
TEST(ValueMetricProducerTest,TestLateOnDataPulledWithDiff)2749 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
2750 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2751
2752 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2753 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2754 // Initialization.
2755 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2756 vector<std::shared_ptr<LogEvent>>* data) {
2757 data->clear();
2758 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2759 return true;
2760 }));
2761
2762 sp<ValueMetricProducer> valueProducer =
2763 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2764
2765 vector<shared_ptr<LogEvent>> allData;
2766 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2767 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2768
2769 allData.clear();
2770 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2771 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2772
2773 // Bucket should have been completed.
2774 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs},
2775 {bucketStartTimeNs}, {bucket2StartTimeNs});
2776 }
2777
TEST_P(ValueMetricProducerTest_PartialBucket,TestBucketBoundariesOnPartialBucket)2778 TEST_P(ValueMetricProducerTest_PartialBucket, TestBucketBoundariesOnPartialBucket) {
2779 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2780
2781 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
2782 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2783 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2784 // Initialization.
2785 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2786 vector<std::shared_ptr<LogEvent>>* data) {
2787 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
2788 data->clear();
2789 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2790 return true;
2791 }))
2792 // notifyAppUpgrade.
2793 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
2794 const int64_t eventTimeNs,
2795 vector<std::shared_ptr<LogEvent>>* data) {
2796 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
2797 data->clear();
2798 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
2799 return true;
2800 }));
2801
2802 sp<ValueMetricProducer> valueProducer =
2803 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2804
2805 switch (GetParam()) {
2806 case APP_UPGRADE:
2807 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
2808 break;
2809 case BOOT_COMPLETE:
2810 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
2811 break;
2812 }
2813
2814 // Bucket should have been completed.
2815 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs},
2816 {bucketStartTimeNs}, {bucket2StartTimeNs});
2817 }
2818
TEST(ValueMetricProducerTest,TestDataIsNotUpdatedWhenNoConditionChanged)2819 TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
2820 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2821
2822 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2823 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2824 // First on condition changed.
2825 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2826 vector<std::shared_ptr<LogEvent>>* data) {
2827 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
2828 data->clear();
2829 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2830 return true;
2831 }))
2832 // Second on condition changed.
2833 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2834 vector<std::shared_ptr<LogEvent>>* data) {
2835 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2836 data->clear();
2837 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2838 return true;
2839 }));
2840
2841 sp<ValueMetricProducer> valueProducer =
2842 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2843 ConditionState::kFalse);
2844
2845 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
2846 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2847 valueProducer->onConditionChanged(false, bucketStartTimeNs + 12);
2848
2849 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2850 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2851 auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2852 EXPECT_EQ(true, curInterval.hasValue);
2853 EXPECT_EQ(2, curInterval.value.long_value);
2854
2855 vector<shared_ptr<LogEvent>> allData;
2856 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 10));
2857 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2858
2859 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2}, {bucketStartTimeNs},
2860 {bucket2StartTimeNs});
2861 }
2862
2863 // TODO: b/145705635 fix or delete this test
TEST(ValueMetricProducerTest,TestBucketInvalidIfGlobalBaseIsNotSet)2864 TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
2865 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2866
2867 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2868 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2869 // First condition change.
2870 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2871 vector<std::shared_ptr<LogEvent>>* data) {
2872 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
2873 data->clear();
2874 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2875 return true;
2876 }))
2877 // 2nd condition change.
2878 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2879 vector<std::shared_ptr<LogEvent>>* data) {
2880 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 8);
2881 data->clear();
2882 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
2883 return true;
2884 }))
2885 // 3rd condition change.
2886 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2887 vector<std::shared_ptr<LogEvent>>* data) {
2888 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
2889 data->clear();
2890 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
2891 return true;
2892 }));
2893
2894 sp<ValueMetricProducer> valueProducer =
2895 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2896 ConditionState::kFalse);
2897 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2898
2899 vector<shared_ptr<LogEvent>> allData;
2900 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 3, 10));
2901 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
2902
2903 allData.clear();
2904 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2905 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2906
2907 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
2908 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2909
2910 allData.clear();
2911 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 30));
2912 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2913
2914 // There was not global base available so all buckets are invalid.
2915 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
2916 }
2917
TEST(ValueMetricProducerTest,TestPullNeededFastDump)2918 TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
2919 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2920
2921 sp<EventMatcherWizard> eventMatcherWizard =
2922 createEventMatcherWizard(tagId, logEventMatcherIndex);
2923 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2924 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2925 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2926 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
2927
2928 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2929 // Initial pull.
2930 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2931 vector<std::shared_ptr<LogEvent>>* data) {
2932 data->clear();
2933 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2934 return true;
2935 }));
2936
2937 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
2938 logEventMatcherIndex, eventMatcherWizard, tagId,
2939 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
2940 valueProducer.prepareFirstBucket();
2941
2942 ProtoOutputStream output;
2943 std::set<string> strSet;
2944 valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
2945 FAST, &strSet, &output);
2946
2947 StatsLogReport report = outputStreamToProto(&output);
2948 // Bucket is invalid since we did not pull when dump report was called.
2949 ASSERT_EQ(0, report.value_metrics().data_size());
2950 }
2951
TEST(ValueMetricProducerTest,TestFastDumpWithoutCurrentBucket)2952 TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
2953 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2954
2955 sp<EventMatcherWizard> eventMatcherWizard =
2956 createEventMatcherWizard(tagId, logEventMatcherIndex);
2957 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2958 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2959 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2960 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
2961
2962 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2963 // Initial pull.
2964 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2965 vector<std::shared_ptr<LogEvent>>* data) {
2966 data->clear();
2967 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2968 return true;
2969 }));
2970
2971 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
2972 logEventMatcherIndex, eventMatcherWizard, tagId,
2973 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
2974 valueProducer.prepareFirstBucket();
2975
2976 vector<shared_ptr<LogEvent>> allData;
2977 allData.clear();
2978 allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, tagId, 2, 2));
2979 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2980
2981 ProtoOutputStream output;
2982 std::set<string> strSet;
2983 valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
2984 &strSet, &output);
2985
2986 StatsLogReport report = outputStreamToProto(&output);
2987 // Previous bucket is part of the report.
2988 ASSERT_EQ(1, report.value_metrics().data_size());
2989 EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
2990 }
2991
TEST(ValueMetricProducerTest,TestPullNeededNoTimeConstraints)2992 TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
2993 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2994
2995 sp<EventMatcherWizard> eventMatcherWizard =
2996 createEventMatcherWizard(tagId, logEventMatcherIndex);
2997 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2998 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2999 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
3000 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
3001
3002 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3003 // Initial pull.
3004 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3005 vector<std::shared_ptr<LogEvent>>* data) {
3006 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
3007 data->clear();
3008 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
3009 return true;
3010 }))
3011 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3012 vector<std::shared_ptr<LogEvent>>* data) {
3013 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3014 data->clear();
3015 data->push_back(
3016 CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
3017 return true;
3018 }));
3019
3020 ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
3021 logEventMatcherIndex, eventMatcherWizard, tagId,
3022 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
3023 valueProducer.prepareFirstBucket();
3024
3025 ProtoOutputStream output;
3026 std::set<string> strSet;
3027 valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
3028 NO_TIME_CONSTRAINTS, &strSet, &output);
3029
3030 StatsLogReport report = outputStreamToProto(&output);
3031 ASSERT_EQ(1, report.value_metrics().data_size());
3032 ASSERT_EQ(1, report.value_metrics().data(0).bucket_info_size());
3033 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
3034 }
3035
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withoutCondition)3036 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
3037 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
3038 metric.set_use_diff(false);
3039
3040 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3041 sp<ValueMetricProducer> valueProducer =
3042 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
3043
3044 vector<shared_ptr<LogEvent>> allData;
3045 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 10));
3046 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
3047
3048 // Bucket should have been completed.
3049 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs},
3050 {bucketStartTimeNs}, {bucket2StartTimeNs});
3051 }
3052
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withMultipleConditionChanges)3053 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
3054 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3055 metric.set_use_diff(false);
3056
3057 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3058 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3059 // condition becomes true
3060 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3061 vector<std::shared_ptr<LogEvent>>* data) {
3062 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
3063 data->clear();
3064 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3065 return true;
3066 }))
3067 // condition becomes false
3068 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3069 vector<std::shared_ptr<LogEvent>>* data) {
3070 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3071 data->clear();
3072 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
3073 return true;
3074 }));
3075 sp<ValueMetricProducer> valueProducer =
3076 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3077 ConditionState::kFalse);
3078
3079 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3080 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3081 // has one slice
3082 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
3083 ValueMetricProducer::Interval curInterval =
3084 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
3085 ValueMetricProducer::BaseInfo curBaseInfo =
3086 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
3087 EXPECT_EQ(false, curBaseInfo.hasBase);
3088 EXPECT_EQ(true, curInterval.hasValue);
3089 EXPECT_EQ(20, curInterval.value.long_value);
3090
3091 // Now the alarm is delivered. Condition is off though.
3092 vector<shared_ptr<LogEvent>> allData;
3093 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
3094 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3095
3096 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8},
3097 {bucketStartTimeNs}, {bucket2StartTimeNs});
3098 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
3099 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
3100 EXPECT_EQ(false, curBaseInfo.hasBase);
3101 EXPECT_EQ(false, curInterval.hasValue);
3102 }
3103
TEST(ValueMetricProducerTest,TestPulledData_noDiff_bucketBoundaryTrue)3104 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
3105 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3106 metric.set_use_diff(false);
3107
3108 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3109 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _))
3110 // condition becomes true
3111 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3112 vector<std::shared_ptr<LogEvent>>* data) {
3113 data->clear();
3114 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3115 return true;
3116 }));
3117 sp<ValueMetricProducer> valueProducer =
3118 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3119 ConditionState::kFalse);
3120
3121 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3122
3123 // Now the alarm is delivered. Condition is off though.
3124 vector<shared_ptr<LogEvent>> allData;
3125 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3126 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3127
3128 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8},
3129 {bucketStartTimeNs}, {bucket2StartTimeNs});
3130 ValueMetricProducer::Interval curInterval =
3131 valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
3132 ValueMetricProducer::BaseInfo curBaseInfo =
3133 valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
3134 EXPECT_EQ(false, curBaseInfo.hasBase);
3135 EXPECT_EQ(false, curInterval.hasValue);
3136 }
3137
TEST(ValueMetricProducerTest,TestPulledData_noDiff_bucketBoundaryFalse)3138 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
3139 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3140 metric.set_use_diff(false);
3141
3142 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3143 sp<ValueMetricProducer> valueProducer =
3144 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3145 ConditionState::kFalse);
3146
3147 // Now the alarm is delivered. Condition is off though.
3148 vector<shared_ptr<LogEvent>> allData;
3149 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3150 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3151
3152 // Condition was always false.
3153 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
3154 }
3155
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withFailure)3156 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
3157 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3158 metric.set_use_diff(false);
3159
3160 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3161 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3162 // condition becomes true
3163 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3164 vector<std::shared_ptr<LogEvent>>* data) {
3165 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
3166 data->clear();
3167 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3168 return true;
3169 }))
3170 .WillOnce(Return(false));
3171 sp<ValueMetricProducer> valueProducer =
3172 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3173 ConditionState::kFalse);
3174
3175 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3176 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3177
3178 // Now the alarm is delivered. Condition is off though.
3179 vector<shared_ptr<LogEvent>> allData;
3180 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3181 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3182
3183 // No buckets, we had a failure.
3184 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
3185 }
3186
3187 /*
3188 * Test that DUMP_REPORT_REQUESTED dump reason is logged.
3189 *
3190 * For the bucket to be marked invalid during a dump report requested,
3191 * three things must be true:
3192 * - we want to include the current partial bucket
3193 * - we need a pull (metric is pulled and condition is true)
3194 * - the dump latency must be FAST
3195 */
3196
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenDumpReportRequested)3197 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
3198 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3199
3200 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3201 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 20, _))
3202 // Condition change to true.
3203 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3204 vector<std::shared_ptr<LogEvent>>* data) {
3205 data->clear();
3206 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
3207 return true;
3208 }));
3209
3210 sp<ValueMetricProducer> valueProducer =
3211 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3212 ConditionState::kFalse);
3213
3214 // Condition change event.
3215 valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
3216
3217 // Check dump report.
3218 ProtoOutputStream output;
3219 std::set<string> strSet;
3220 valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
3221 FAST /* dumpLatency */, &strSet, &output);
3222
3223 StatsLogReport report = outputStreamToProto(&output);
3224 EXPECT_TRUE(report.has_value_metrics());
3225 ASSERT_EQ(0, report.value_metrics().data_size());
3226 ASSERT_EQ(1, report.value_metrics().skipped_size());
3227
3228 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3229 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3230 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
3231 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3232 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3233
3234 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3235 EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
3236 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
3237 }
3238
3239 /*
3240 * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
3241 * change event (i.e. the condition change occurs in the wrong bucket).
3242 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenConditionEventWrongBucket)3243 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
3244 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3245
3246 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3247 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 50, _))
3248 // Condition change to true.
3249 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3250 vector<std::shared_ptr<LogEvent>>* data) {
3251 data->clear();
3252 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3253 return true;
3254 }));
3255
3256 sp<ValueMetricProducer> valueProducer =
3257 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3258 ConditionState::kFalse);
3259
3260 // Condition change event.
3261 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3262
3263 // Bucket boundary pull.
3264 vector<shared_ptr<LogEvent>> allData;
3265 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
3266 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
3267
3268 // Late condition change event.
3269 valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
3270
3271 // Check dump report.
3272 ProtoOutputStream output;
3273 std::set<string> strSet;
3274 valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
3275 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3276
3277 StatsLogReport report = outputStreamToProto(&output);
3278 EXPECT_TRUE(report.has_value_metrics());
3279 ASSERT_EQ(1, report.value_metrics().data_size());
3280 ASSERT_EQ(1, report.value_metrics().skipped_size());
3281
3282 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3283 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3284 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
3285 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3286 ASSERT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
3287
3288 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3289 EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
3290 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
3291
3292 dropEvent = report.value_metrics().skipped(0).drop_event(1);
3293 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3294 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100), dropEvent.drop_time_millis());
3295 }
3296
3297 /*
3298 * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
3299 * event (i.e. the accumulate events call occurs in the wrong bucket).
3300 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenAccumulateEventWrongBucket)3301 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
3302 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3303
3304 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3305 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3306 // Condition change to true.
3307 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3308 vector<std::shared_ptr<LogEvent>>* data) {
3309 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3310 data->clear();
3311 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3312 return true;
3313 }))
3314 // Dump report requested.
3315 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3316 vector<std::shared_ptr<LogEvent>>* data) {
3317 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 100);
3318 data->clear();
3319 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
3320 return true;
3321 }));
3322
3323 sp<ValueMetricProducer> valueProducer =
3324 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3325 ConditionState::kFalse);
3326
3327 // Condition change event.
3328 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3329
3330 // Bucket boundary pull.
3331 vector<shared_ptr<LogEvent>> allData;
3332 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
3333 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
3334
3335 allData.clear();
3336 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 20));
3337
3338 // Late accumulateEvents event.
3339 valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
3340
3341 // Check dump report.
3342 ProtoOutputStream output;
3343 std::set<string> strSet;
3344 valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
3345 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3346
3347 StatsLogReport report = outputStreamToProto(&output);
3348 EXPECT_TRUE(report.has_value_metrics());
3349 ASSERT_EQ(1, report.value_metrics().data_size());
3350 ASSERT_EQ(1, report.value_metrics().skipped_size());
3351
3352 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3353 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3354 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
3355 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3356 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3357
3358 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3359 EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
3360 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
3361 }
3362
3363 /*
3364 * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
3365 * when a metric is initialized.
3366 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenConditionUnknown)3367 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
3368 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3369
3370 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3371 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3372 // Condition change to true.
3373 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3374 vector<std::shared_ptr<LogEvent>>* data) {
3375 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3376 data->clear();
3377 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3378 return true;
3379 }))
3380 // Dump report requested.
3381 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3382 vector<std::shared_ptr<LogEvent>>* data) {
3383 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10000);
3384 data->clear();
3385 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
3386 return true;
3387 }));
3388
3389 sp<ValueMetricProducer> valueProducer =
3390 ValueMetricProducerTestHelper::createValueProducerWithCondition(
3391 pullerManager, metric, ConditionState::kUnknown);
3392
3393 // Condition change event.
3394 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3395
3396 // Check dump report.
3397 ProtoOutputStream output;
3398 std::set<string> strSet;
3399 int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
3400 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3401 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3402
3403 StatsLogReport report = outputStreamToProto(&output);
3404 EXPECT_TRUE(report.has_value_metrics());
3405 ASSERT_EQ(0, report.value_metrics().data_size());
3406 ASSERT_EQ(1, report.value_metrics().skipped_size());
3407
3408 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3409 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3410 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3411 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3412 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3413
3414 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3415 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3416 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3417 }
3418
3419 /*
3420 * Test that PULL_FAILED dump reason is logged due to a pull failure in
3421 * #pullAndMatchEventsLocked.
3422 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenPullFailed)3423 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
3424 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3425
3426 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3427 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3428 // Condition change to true.
3429 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3430 vector<std::shared_ptr<LogEvent>>* data) {
3431 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3432 data->clear();
3433 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3434 return true;
3435 }))
3436 // Dump report requested, pull fails.
3437 .WillOnce(Return(false));
3438
3439 sp<ValueMetricProducer> valueProducer =
3440 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3441 ConditionState::kFalse);
3442
3443 // Condition change event.
3444 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3445
3446 // Check dump report.
3447 ProtoOutputStream output;
3448 std::set<string> strSet;
3449 int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
3450 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3451 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3452
3453 StatsLogReport report = outputStreamToProto(&output);
3454 EXPECT_TRUE(report.has_value_metrics());
3455 ASSERT_EQ(0, report.value_metrics().data_size());
3456 ASSERT_EQ(1, report.value_metrics().skipped_size());
3457
3458 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3459 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3460 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3461 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3462 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3463
3464 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3465 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3466 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3467 }
3468
3469 /*
3470 * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
3471 * skips over more than one bucket.
3472 */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenMultipleBucketsSkipped)3473 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
3474 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3475
3476 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3477 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3478 // Condition change to true.
3479 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3480 vector<std::shared_ptr<LogEvent>>* data) {
3481 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3482 data->clear();
3483 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3484 return true;
3485 }))
3486 // Dump report requested.
3487 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3488 vector<std::shared_ptr<LogEvent>>* data) {
3489 EXPECT_EQ(eventTimeNs, bucket4StartTimeNs + 10);
3490 data->clear();
3491 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
3492 return true;
3493 }));
3494
3495 sp<ValueMetricProducer> valueProducer =
3496 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3497 ConditionState::kFalse);
3498
3499 // Condition change event.
3500 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3501
3502 // Condition change event that skips forward by three buckets.
3503 valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
3504
3505 int64_t dumpTimeNs = bucket4StartTimeNs + 1000;
3506
3507 // Check dump report.
3508 ProtoOutputStream output;
3509 std::set<string> strSet;
3510 valueProducer->onDumpReport(dumpTimeNs, true /* include current buckets */, true,
3511 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3512
3513 StatsLogReport report = outputStreamToProto(&output);
3514 EXPECT_TRUE(report.has_value_metrics());
3515 ASSERT_EQ(0, report.value_metrics().data_size());
3516 ASSERT_EQ(2, report.value_metrics().skipped_size());
3517
3518 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3519 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3520 EXPECT_EQ(NanoToMillis(bucket4StartTimeNs),
3521 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3522 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3523
3524 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3525 EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
3526 EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
3527
3528 // This bucket is skipped because a dumpReport with include current buckets is called.
3529 // This creates a new bucket from bucket4StartTimeNs to dumpTimeNs in which we have no data
3530 // since the condition is false for the entire bucket interval.
3531 EXPECT_EQ(NanoToMillis(bucket4StartTimeNs),
3532 report.value_metrics().skipped(1).start_bucket_elapsed_millis());
3533 EXPECT_EQ(NanoToMillis(dumpTimeNs),
3534 report.value_metrics().skipped(1).end_bucket_elapsed_millis());
3535 ASSERT_EQ(1, report.value_metrics().skipped(1).drop_event_size());
3536
3537 dropEvent = report.value_metrics().skipped(1).drop_event(0);
3538 EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
3539 EXPECT_EQ(NanoToMillis(dumpTimeNs), dropEvent.drop_time_millis());
3540 }
3541
3542 /*
3543 * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
3544 * is smaller than the "min_bucket_size_nanos" specified in the metric config.
3545 */
TEST(ValueMetricProducerTest_BucketDrop,TestBucketDropWhenBucketTooSmall)3546 TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
3547 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3548 metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
3549
3550 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3551 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3552 // Condition change to true.
3553 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3554 vector<std::shared_ptr<LogEvent>>* data) {
3555 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3556 data->clear();
3557 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3558 return true;
3559 }))
3560 // Dump report requested.
3561 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3562 vector<std::shared_ptr<LogEvent>>* data) {
3563 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 9000000);
3564 data->clear();
3565 data->push_back(
3566 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15));
3567 return true;
3568 }));
3569
3570 sp<ValueMetricProducer> valueProducer =
3571 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3572 ConditionState::kFalse);
3573
3574 // Condition change event.
3575 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3576
3577 // Check dump report.
3578 ProtoOutputStream output;
3579 std::set<string> strSet;
3580 int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
3581 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3582 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3583
3584 StatsLogReport report = outputStreamToProto(&output);
3585 EXPECT_TRUE(report.has_value_metrics());
3586 ASSERT_EQ(0, report.value_metrics().data_size());
3587 ASSERT_EQ(1, report.value_metrics().skipped_size());
3588
3589 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3590 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3591 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3592 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3593 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3594
3595 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3596 EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
3597 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3598 }
3599
3600 /*
3601 * Test that NO_DATA dump reason is logged when a flushed bucket contains no data.
3602 */
TEST(ValueMetricProducerTest_BucketDrop,TestBucketDropWhenDataUnavailable)3603 TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenDataUnavailable) {
3604 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3605
3606 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3607
3608 sp<ValueMetricProducer> valueProducer =
3609 ValueMetricProducerTestHelper::createValueProducerWithCondition(
3610 pullerManager, metric, ConditionState::kFalse);
3611
3612 // Check dump report.
3613 ProtoOutputStream output;
3614 std::set<string> strSet;
3615 int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000; // 10 seconds
3616 valueProducer->onDumpReport(dumpReportTimeNs, true /* include current bucket */, true,
3617 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3618
3619 StatsLogReport report = outputStreamToProto(&output);
3620 EXPECT_TRUE(report.has_value_metrics());
3621 ASSERT_EQ(0, report.value_metrics().data_size());
3622 ASSERT_EQ(1, report.value_metrics().skipped_size());
3623
3624 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3625 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3626 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3627 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3628 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3629
3630 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3631 EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
3632 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3633 }
3634
3635 /*
3636 * Test that all buckets are dropped due to condition unknown until the first onConditionChanged.
3637 */
TEST(ValueMetricProducerTest_BucketDrop,TestConditionUnknownMultipleBuckets)3638 TEST(ValueMetricProducerTest_BucketDrop, TestConditionUnknownMultipleBuckets) {
3639 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3640
3641 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3642 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3643 // Condition change to true.
3644 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3645 vector<std::shared_ptr<LogEvent>>* data) {
3646 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10 * NS_PER_SEC);
3647 data->clear();
3648 data->push_back(CreateRepeatedValueLogEvent(
3649 tagId, bucket2StartTimeNs + 10 * NS_PER_SEC, 10));
3650 return true;
3651 }))
3652 // Dump report requested.
3653 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3654 vector<std::shared_ptr<LogEvent>>* data) {
3655 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 15 * NS_PER_SEC);
3656 data->clear();
3657 data->push_back(CreateRepeatedValueLogEvent(
3658 tagId, bucket2StartTimeNs + 15 * NS_PER_SEC, 15));
3659 return true;
3660 }));
3661
3662 sp<ValueMetricProducer> valueProducer =
3663 ValueMetricProducerTestHelper::createValueProducerWithCondition(
3664 pullerManager, metric, ConditionState::kUnknown);
3665
3666 // Bucket should be dropped because of condition unknown.
3667 int64_t appUpgradeTimeNs = bucketStartTimeNs + 5 * NS_PER_SEC;
3668 valueProducer->notifyAppUpgrade(appUpgradeTimeNs);
3669
3670 // Bucket also dropped due to condition unknown
3671 vector<shared_ptr<LogEvent>> allData;
3672 allData.clear();
3673 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 3));
3674 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3675
3676 // This bucket is also dropped due to condition unknown.
3677 int64_t conditionChangeTimeNs = bucket2StartTimeNs + 10 * NS_PER_SEC;
3678 valueProducer->onConditionChanged(true, conditionChangeTimeNs);
3679
3680 // Check dump report.
3681 ProtoOutputStream output;
3682 std::set<string> strSet;
3683 int64_t dumpReportTimeNs = bucket2StartTimeNs + 15 * NS_PER_SEC; // 15 seconds
3684 valueProducer->onDumpReport(dumpReportTimeNs, true /* include current bucket */, true,
3685 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3686
3687 StatsLogReport report = outputStreamToProto(&output);
3688 EXPECT_TRUE(report.has_value_metrics());
3689 ASSERT_EQ(0, report.value_metrics().data_size());
3690 ASSERT_EQ(3, report.value_metrics().skipped_size());
3691
3692 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3693 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3694 EXPECT_EQ(NanoToMillis(appUpgradeTimeNs),
3695 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3696 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3697
3698 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3699 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3700 EXPECT_EQ(NanoToMillis(appUpgradeTimeNs), dropEvent.drop_time_millis());
3701
3702 EXPECT_EQ(NanoToMillis(appUpgradeTimeNs),
3703 report.value_metrics().skipped(1).start_bucket_elapsed_millis());
3704 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3705 report.value_metrics().skipped(1).end_bucket_elapsed_millis());
3706 ASSERT_EQ(1, report.value_metrics().skipped(1).drop_event_size());
3707
3708 dropEvent = report.value_metrics().skipped(1).drop_event(0);
3709 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3710 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
3711
3712 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3713 report.value_metrics().skipped(2).start_bucket_elapsed_millis());
3714 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3715 report.value_metrics().skipped(2).end_bucket_elapsed_millis());
3716 ASSERT_EQ(1, report.value_metrics().skipped(2).drop_event_size());
3717
3718 dropEvent = report.value_metrics().skipped(2).drop_event(0);
3719 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3720 EXPECT_EQ(NanoToMillis(conditionChangeTimeNs), dropEvent.drop_time_millis());
3721 }
3722
3723 /*
3724 * Test that a skipped bucket is logged when a forced bucket split occurs when the previous bucket
3725 * was not flushed in time.
3726 */
TEST(ValueMetricProducerTest_BucketDrop,TestBucketDropWhenForceBucketSplitBeforeBucketFlush)3727 TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenForceBucketSplitBeforeBucketFlush) {
3728 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3729
3730 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3731 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3732 // Condition change to true.
3733 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3734 vector<std::shared_ptr<LogEvent>>* data) {
3735 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3736 data->clear();
3737 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3738 return true;
3739 }))
3740 // App Update.
3741 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3742 vector<std::shared_ptr<LogEvent>>* data) {
3743 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1000);
3744 data->clear();
3745 data->push_back(
3746 CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1000, 15));
3747 return true;
3748 }));
3749
3750 sp<ValueMetricProducer> valueProducer =
3751 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3752 ConditionState::kFalse);
3753
3754 // Condition changed event
3755 int64_t conditionChangeTimeNs = bucketStartTimeNs + 10;
3756 valueProducer->onConditionChanged(true, conditionChangeTimeNs);
3757
3758 // App update event.
3759 int64_t appUpdateTimeNs = bucket2StartTimeNs + 1000;
3760 valueProducer->notifyAppUpgrade(appUpdateTimeNs);
3761
3762 // Check dump report.
3763 ProtoOutputStream output;
3764 std::set<string> strSet;
3765 int64_t dumpReportTimeNs = bucket2StartTimeNs + 10000000000; // 10 seconds
3766 valueProducer->onDumpReport(dumpReportTimeNs, false /* include current buckets */, true,
3767 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3768
3769 StatsLogReport report = outputStreamToProto(&output);
3770 EXPECT_TRUE(report.has_value_metrics());
3771 ASSERT_EQ(1, report.value_metrics().data_size());
3772 ASSERT_EQ(1, report.value_metrics().skipped_size());
3773
3774 ASSERT_EQ(1, report.value_metrics().data(0).bucket_info_size());
3775 auto data = report.value_metrics().data(0);
3776 ASSERT_EQ(0, data.bucket_info(0).bucket_num());
3777 EXPECT_EQ(5, data.bucket_info(0).values(0).value_long());
3778
3779 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3780 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3781 EXPECT_EQ(NanoToMillis(appUpdateTimeNs),
3782 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3783 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3784
3785 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3786 EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
3787 EXPECT_EQ(NanoToMillis(appUpdateTimeNs), dropEvent.drop_time_millis());
3788 }
3789
3790 /*
3791 * Test multiple bucket drop events in the same bucket.
3792 */
TEST(ValueMetricProducerTest_BucketDrop,TestMultipleBucketDropEvents)3793 TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
3794 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3795
3796 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3797 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _))
3798 // Condition change to true.
3799 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3800 vector<std::shared_ptr<LogEvent>>* data) {
3801 data->clear();
3802 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3803 return true;
3804 }));
3805
3806 sp<ValueMetricProducer> valueProducer =
3807 ValueMetricProducerTestHelper::createValueProducerWithCondition(
3808 pullerManager, metric, ConditionState::kUnknown);
3809
3810 // Condition change event.
3811 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3812
3813 // Check dump report.
3814 ProtoOutputStream output;
3815 std::set<string> strSet;
3816 int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
3817 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3818 FAST /* dumpLatency */, &strSet, &output);
3819
3820 StatsLogReport report = outputStreamToProto(&output);
3821 EXPECT_TRUE(report.has_value_metrics());
3822 ASSERT_EQ(0, report.value_metrics().data_size());
3823 ASSERT_EQ(1, report.value_metrics().skipped_size());
3824
3825 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3826 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3827 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3828 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3829 ASSERT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
3830
3831 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3832 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3833 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
3834
3835 dropEvent = report.value_metrics().skipped(0).drop_event(1);
3836 EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
3837 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3838 }
3839
3840 /*
3841 * Test that the number of logged bucket drop events is capped at the maximum.
3842 * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
3843 */
TEST(ValueMetricProducerTest_BucketDrop,TestMaxBucketDropEvents)3844 TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
3845 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3846
3847 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3848 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3849 // First condition change event.
3850 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3851 vector<std::shared_ptr<LogEvent>>* data) {
3852 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3853 for (int i = 0; i < 2000; i++) {
3854 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
3855 }
3856 return true;
3857 }))
3858 .WillOnce(Return(false))
3859 .WillOnce(Return(false))
3860 .WillOnce(Return(false))
3861 .WillOnce(Return(false))
3862 .WillOnce(Return(false))
3863 .WillOnce(Return(false))
3864 .WillOnce(Return(false))
3865 .WillOnce(Return(false))
3866 .WillOnce(Return(false))
3867 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3868 vector<std::shared_ptr<LogEvent>>* data) {
3869 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 220);
3870 data->clear();
3871 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
3872 return true;
3873 }));
3874
3875 sp<ValueMetricProducer> valueProducer =
3876 ValueMetricProducerTestHelper::createValueProducerWithCondition(
3877 pullerManager, metric, ConditionState::kUnknown);
3878
3879 // First condition change event causes guardrail to be reached.
3880 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3881
3882 // 2-10 condition change events result in failed pulls.
3883 valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
3884 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3885 valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
3886 valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
3887 valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
3888 valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
3889 valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
3890 valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
3891 valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
3892
3893 // Condition change event 11
3894 valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
3895
3896 // Check dump report.
3897 ProtoOutputStream output;
3898 std::set<string> strSet;
3899 int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
3900 // Because we already have 10 dump events in the current bucket,
3901 // this case should not be added to the list of dump events.
3902 valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
3903 FAST /* dumpLatency */, &strSet, &output);
3904
3905 StatsLogReport report = outputStreamToProto(&output);
3906 EXPECT_TRUE(report.has_value_metrics());
3907 ASSERT_EQ(0, report.value_metrics().data_size());
3908 ASSERT_EQ(1, report.value_metrics().skipped_size());
3909
3910 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3911 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3912 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3913 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3914 ASSERT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
3915
3916 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3917 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3918 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
3919
3920 dropEvent = report.value_metrics().skipped(0).drop_event(1);
3921 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3922 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
3923
3924 dropEvent = report.value_metrics().skipped(0).drop_event(2);
3925 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3926 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
3927
3928 dropEvent = report.value_metrics().skipped(0).drop_event(3);
3929 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3930 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
3931
3932 dropEvent = report.value_metrics().skipped(0).drop_event(4);
3933 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3934 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
3935
3936 dropEvent = report.value_metrics().skipped(0).drop_event(5);
3937 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3938 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
3939
3940 dropEvent = report.value_metrics().skipped(0).drop_event(6);
3941 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3942 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
3943
3944 dropEvent = report.value_metrics().skipped(0).drop_event(7);
3945 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3946 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
3947
3948 dropEvent = report.value_metrics().skipped(0).drop_event(8);
3949 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3950 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
3951
3952 dropEvent = report.value_metrics().skipped(0).drop_event(9);
3953 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3954 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
3955 }
3956
3957 /*
3958 * Test metric with a simple sliced state
3959 * - Increasing values
3960 * - Using diff
3961 * - Second field is value field
3962 */
TEST(ValueMetricProducerTest,TestSlicedState)3963 TEST(ValueMetricProducerTest, TestSlicedState) {
3964 // Set up ValueMetricProducer.
3965 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
3966 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3967 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3968 // ValueMetricProducer initialized.
3969 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3970 vector<std::shared_ptr<LogEvent>>* data) {
3971 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
3972 data->clear();
3973 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
3974 return true;
3975 }))
3976 // Screen state change to ON.
3977 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3978 vector<std::shared_ptr<LogEvent>>* data) {
3979 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5 * NS_PER_SEC);
3980 data->clear();
3981 data->push_back(
3982 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5 * NS_PER_SEC, 5));
3983 return true;
3984 }))
3985 // Screen state change to OFF.
3986 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3987 vector<std::shared_ptr<LogEvent>>* data) {
3988 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
3989 data->clear();
3990 data->push_back(
3991 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 9));
3992 return true;
3993 }))
3994 // Screen state change to ON.
3995 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3996 vector<std::shared_ptr<LogEvent>>* data) {
3997 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15 * NS_PER_SEC);
3998 data->clear();
3999 data->push_back(CreateRepeatedValueLogEvent(
4000 tagId, bucketStartTimeNs + 15 * NS_PER_SEC, 21));
4001 return true;
4002 }))
4003 // Dump report requested.
4004 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4005 vector<std::shared_ptr<LogEvent>>* data) {
4006 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
4007 data->clear();
4008 data->push_back(CreateRepeatedValueLogEvent(
4009 tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 30));
4010 return true;
4011 }));
4012
4013 StateManager::getInstance().clear();
4014 sp<ValueMetricProducer> valueProducer =
4015 ValueMetricProducerTestHelper::createValueProducerWithState(
4016 pullerManager, metric, {util::SCREEN_STATE_CHANGED}, {});
4017 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
4018
4019 // Set up StateManager and check that StateTrackers are initialized.
4020 StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
4021 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4022 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
4023
4024 // Bucket status after metric initialized.
4025 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
4026 // Base for dimension key {}
4027 auto it = valueProducer->mCurrentSlicedBucket.begin();
4028 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4029 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4030 EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
4031 EXPECT_TRUE(itBase->second.hasCurrentState);
4032 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4033 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4034 itBase->second.currentState.getValues()[0].mValue.int_value);
4035 // Value for dimension, state key {{}, kStateUnknown}
4036 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4037 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4038 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4039 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4040 EXPECT_FALSE(it->second.intervals[0].hasValue);
4041 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4042
4043 // Bucket status after screen state change kStateUnknown->ON.
4044 auto screenEvent = CreateScreenStateChangedEvent(
4045 bucketStartTimeNs + 5 * NS_PER_SEC, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4046 StateManager::getInstance().onLogEvent(*screenEvent);
4047 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4048 // Base for dimension key {}
4049 it = valueProducer->mCurrentSlicedBucket.begin();
4050 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4051 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4052 EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4053 EXPECT_TRUE(itBase->second.hasCurrentState);
4054 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4055 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4056 itBase->second.currentState.getValues()[0].mValue.int_value);
4057 // Value for dimension, state key {{}, ON}
4058 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4059 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4060 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4061 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4062 EXPECT_EQ(0, it->second.intervals.size());
4063 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4064 // Value for dimension, state key {{}, kStateUnknown}
4065 it++;
4066 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4067 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4068 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4069 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4070 EXPECT_TRUE(it->second.intervals[0].hasValue);
4071 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4072 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4073 bucketStartTimeNs + 5 * NS_PER_SEC);
4074
4075 // Bucket status after screen state change ON->OFF.
4076 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
4077 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
4078 StateManager::getInstance().onLogEvent(*screenEvent);
4079 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4080 // Base for dimension key {}
4081 it = valueProducer->mCurrentSlicedBucket.begin();
4082 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4083 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4084 EXPECT_EQ(9, itBase->second.baseInfos[0].base.long_value);
4085 EXPECT_TRUE(itBase->second.hasCurrentState);
4086 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
4087 itBase->second.currentState.getValues()[0].mValue.int_value);
4088 // Value for dimension, state key {{}, OFF}
4089 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4090 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4091 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
4092 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4093 EXPECT_EQ(0, it->second.intervals.size());
4094 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
4095 // Value for dimension, state key {{}, ON}
4096 it++;
4097 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4098 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4099 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4100 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4101 EXPECT_TRUE(it->second.intervals[0].hasValue);
4102 EXPECT_EQ(4, it->second.intervals[0].value.long_value);
4103 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4104 bucketStartTimeNs + 10 * NS_PER_SEC);
4105 // Value for dimension, state key {{}, kStateUnknown}
4106 it++;
4107 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4108 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4109 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4110 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4111 EXPECT_TRUE(it->second.intervals[0].hasValue);
4112 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4113 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4114 bucketStartTimeNs + 5 * NS_PER_SEC);
4115
4116 // Bucket status after screen state change OFF->ON.
4117 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
4118 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4119 StateManager::getInstance().onLogEvent(*screenEvent);
4120 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4121 // Base for dimension key {}
4122 it = valueProducer->mCurrentSlicedBucket.begin();
4123 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4124 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4125 EXPECT_EQ(21, itBase->second.baseInfos[0].base.long_value);
4126 EXPECT_TRUE(itBase->second.hasCurrentState);
4127 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4128 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4129 itBase->second.currentState.getValues()[0].mValue.int_value);
4130 // Value for dimension, state key {{}, OFF}
4131 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4132 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4133 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
4134 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4135 EXPECT_TRUE(it->second.intervals[0].hasValue);
4136 EXPECT_EQ(12, it->second.intervals[0].value.long_value);
4137 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4138 bucketStartTimeNs + 15 * NS_PER_SEC);
4139 // Value for dimension, state key {{}, ON}
4140 it++;
4141 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4142 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4143 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4144 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4145 EXPECT_TRUE(it->second.intervals[0].hasValue);
4146 EXPECT_EQ(4, it->second.intervals[0].value.long_value);
4147 assertConditionTimer(it->second.conditionTimer, true, 5 * NS_PER_SEC,
4148 bucketStartTimeNs + 15 * NS_PER_SEC);
4149 // Value for dimension, state key {{}, kStateUnknown}
4150 it++;
4151 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4152 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4153 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4154 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4155 EXPECT_TRUE(it->second.intervals[0].hasValue);
4156 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4157 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4158 bucketStartTimeNs + 5 * NS_PER_SEC);
4159
4160 // Start dump report and check output.
4161 ProtoOutputStream output;
4162 std::set<string> strSet;
4163 valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
4164 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
4165 &strSet, &output);
4166
4167 StatsLogReport report = outputStreamToProto(&output);
4168 EXPECT_TRUE(report.has_value_metrics());
4169 ASSERT_EQ(3, report.value_metrics().data_size());
4170
4171 // {{}, kStateUnknown}
4172 auto data = report.value_metrics().data(0);
4173 ASSERT_EQ(1, data.bucket_info_size());
4174 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4175 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4176 EXPECT_TRUE(data.slice_by_state(0).has_value());
4177 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
4178 EXPECT_EQ(5 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4179
4180 // {{}, ON}
4181 data = report.value_metrics().data(1);
4182 ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
4183 EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
4184 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4185 EXPECT_TRUE(data.slice_by_state(0).has_value());
4186 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
4187 EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4188
4189 // {{}, OFF}
4190 data = report.value_metrics().data(2);
4191 ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
4192 EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
4193 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4194 EXPECT_TRUE(data.slice_by_state(0).has_value());
4195 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
4196 EXPECT_EQ(5 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4197 }
4198
4199 /*
4200 * Test metric with sliced state with map
4201 * - Increasing values
4202 * - Using diff
4203 * - Second field is value field
4204 */
TEST(ValueMetricProducerTest,TestSlicedStateWithMap)4205 TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
4206 // Set up ValueMetricProducer.
4207 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
4208 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
4209 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
4210 // ValueMetricProducer initialized.
4211 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4212 vector<std::shared_ptr<LogEvent>>* data) {
4213 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
4214 data->clear();
4215 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
4216 return true;
4217 }))
4218 // Screen state change to ON.
4219 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4220 vector<std::shared_ptr<LogEvent>>* data) {
4221 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5 * NS_PER_SEC);
4222 data->clear();
4223 data->push_back(
4224 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5 * NS_PER_SEC, 5));
4225 return true;
4226 }))
4227 // Screen state change to VR has no pull because it is in the same
4228 // state group as ON.
4229
4230 // Screen state change to ON has no pull because it is in the same
4231 // state group as VR.
4232
4233 // Screen state change to OFF.
4234 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4235 vector<std::shared_ptr<LogEvent>>* data) {
4236 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15 * NS_PER_SEC);
4237 data->clear();
4238 data->push_back(CreateRepeatedValueLogEvent(
4239 tagId, bucketStartTimeNs + 15 * NS_PER_SEC, 21));
4240 return true;
4241 }))
4242 // Dump report requested.
4243 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4244 vector<std::shared_ptr<LogEvent>>* data) {
4245 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
4246 data->clear();
4247 data->push_back(CreateRepeatedValueLogEvent(
4248 tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 30));
4249 return true;
4250 }));
4251
4252 const StateMap& stateMap =
4253 CreateScreenStateOnOffMap(/*screen on id=*/321, /*screen off id=*/123);
4254 const StateMap_StateGroup screenOnGroup = stateMap.group(0);
4255 const StateMap_StateGroup screenOffGroup = stateMap.group(1);
4256
4257 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
4258 for (auto group : stateMap.group()) {
4259 for (auto value : group.value()) {
4260 stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
4261 }
4262 }
4263
4264 StateManager::getInstance().clear();
4265 sp<ValueMetricProducer> valueProducer =
4266 ValueMetricProducerTestHelper::createValueProducerWithState(
4267 pullerManager, metric, {util::SCREEN_STATE_CHANGED}, stateGroupMap);
4268
4269 // Set up StateManager and check that StateTrackers are initialized.
4270 StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
4271 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4272 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
4273
4274 // Bucket status after metric initialized.
4275 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
4276 // Base for dimension key {}
4277 auto it = valueProducer->mCurrentSlicedBucket.begin();
4278 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4279 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4280 EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
4281 EXPECT_TRUE(itBase->second.hasCurrentState);
4282 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4283 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4284 itBase->second.currentState.getValues()[0].mValue.int_value);
4285 // Value for dimension, state key {{}, {kStateUnknown}}
4286 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4287 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4288 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4289 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4290 EXPECT_FALSE(it->second.intervals[0].hasValue);
4291 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4292
4293 // Bucket status after screen state change kStateUnknown->ON.
4294 auto screenEvent = CreateScreenStateChangedEvent(
4295 bucketStartTimeNs + 5 * NS_PER_SEC, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4296 StateManager::getInstance().onLogEvent(*screenEvent);
4297 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4298 // Base for dimension key {}
4299 it = valueProducer->mCurrentSlicedBucket.begin();
4300 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4301 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4302 EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4303 EXPECT_TRUE(itBase->second.hasCurrentState);
4304 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4305 EXPECT_EQ(screenOnGroup.group_id(),
4306 itBase->second.currentState.getValues()[0].mValue.long_value);
4307 // Value for dimension, state key {{}, ON GROUP}
4308 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4309 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4310 EXPECT_EQ(screenOnGroup.group_id(),
4311 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4312 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4313 // Value for dimension, state key {{}, kStateUnknown}
4314 it++;
4315 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4316 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4317 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4318 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4319 EXPECT_TRUE(it->second.intervals[0].hasValue);
4320 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4321 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4322 bucketStartTimeNs + 5 * NS_PER_SEC);
4323
4324 // Bucket status after screen state change ON->VR.
4325 // Both ON and VR are in the same state group, so the base should not change.
4326 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
4327 android::view::DisplayStateEnum::DISPLAY_STATE_VR);
4328 StateManager::getInstance().onLogEvent(*screenEvent);
4329 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4330 // Base for dimension key {}
4331 it = valueProducer->mCurrentSlicedBucket.begin();
4332 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4333 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4334 EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4335 EXPECT_TRUE(itBase->second.hasCurrentState);
4336 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4337 EXPECT_EQ(screenOnGroup.group_id(),
4338 itBase->second.currentState.getValues()[0].mValue.int_value);
4339 // Value for dimension, state key {{}, ON GROUP}
4340 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4341 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4342 EXPECT_EQ(screenOnGroup.group_id(),
4343 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4344 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4345 // Value for dimension, state key {{}, kStateUnknown}
4346 it++;
4347 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4348 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4349 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4350 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4351 EXPECT_TRUE(it->second.intervals[0].hasValue);
4352 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4353 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4354 bucketStartTimeNs + 5 * NS_PER_SEC);
4355
4356 // Bucket status after screen state change VR->ON.
4357 // Both ON and VR are in the same state group, so the base should not change.
4358 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 12 * NS_PER_SEC,
4359 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4360 StateManager::getInstance().onLogEvent(*screenEvent);
4361 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4362 // Base for dimension key {}
4363 it = valueProducer->mCurrentSlicedBucket.begin();
4364 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4365 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4366 EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4367 EXPECT_TRUE(itBase->second.hasCurrentState);
4368 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4369 EXPECT_EQ(screenOnGroup.group_id(),
4370 itBase->second.currentState.getValues()[0].mValue.int_value);
4371 // Value for dimension, state key {{}, ON GROUP}
4372 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4373 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4374 EXPECT_EQ(screenOnGroup.group_id(),
4375 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4376 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4377 // Value for dimension, state key {{}, kStateUnknown}
4378 it++;
4379 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4380 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4381 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4382 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4383 EXPECT_TRUE(it->second.intervals[0].hasValue);
4384 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4385 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4386 bucketStartTimeNs + 5 * NS_PER_SEC);
4387
4388 // Bucket status after screen state change VR->OFF.
4389 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
4390 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
4391 StateManager::getInstance().onLogEvent(*screenEvent);
4392 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4393 // Base for dimension key {}
4394 it = valueProducer->mCurrentSlicedBucket.begin();
4395 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4396 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4397 EXPECT_EQ(21, itBase->second.baseInfos[0].base.long_value);
4398 EXPECT_TRUE(itBase->second.hasCurrentState);
4399 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4400 EXPECT_EQ(screenOffGroup.group_id(),
4401 itBase->second.currentState.getValues()[0].mValue.int_value);
4402 // Value for dimension, state key {{}, OFF GROUP}
4403 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4404 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4405 EXPECT_EQ(screenOffGroup.group_id(),
4406 it->first.getStateValuesKey().getValues()[0].mValue.long_value);
4407 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 15 * NS_PER_SEC);
4408 // Value for dimension, state key {{}, ON GROUP}
4409 it++;
4410 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4411 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4412 EXPECT_EQ(screenOnGroup.group_id(),
4413 it->first.getStateValuesKey().getValues()[0].mValue.long_value);
4414 EXPECT_TRUE(it->second.intervals[0].hasValue);
4415 EXPECT_EQ(16, it->second.intervals[0].value.long_value);
4416 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
4417 bucketStartTimeNs + 15 * NS_PER_SEC);
4418 // Value for dimension, state key {{}, kStateUnknown}
4419 it++;
4420 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4421 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4422 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4423 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4424 EXPECT_TRUE(it->second.intervals[0].hasValue);
4425 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4426 assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4427 bucketStartTimeNs + 5 * NS_PER_SEC);
4428
4429 // Start dump report and check output.
4430 ProtoOutputStream output;
4431 std::set<string> strSet;
4432 valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
4433 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
4434 &strSet, &output);
4435
4436 StatsLogReport report = outputStreamToProto(&output);
4437 EXPECT_TRUE(report.has_value_metrics());
4438 ASSERT_EQ(3, report.value_metrics().data_size());
4439
4440 // {{}, kStateUnknown}
4441 auto data = report.value_metrics().data(0);
4442 ASSERT_EQ(1, data.bucket_info_size());
4443 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4444 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4445 EXPECT_TRUE(data.slice_by_state(0).has_value());
4446 EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value());
4447 EXPECT_EQ(5 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4448
4449 // {{}, ON GROUP}
4450 data = report.value_metrics().data(1);
4451 ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
4452 EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
4453 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4454 EXPECT_TRUE(data.slice_by_state(0).has_group_id());
4455 EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
4456 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4457
4458 // {{}, OFF GROUP}
4459 data = report.value_metrics().data(2);
4460 ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
4461 EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
4462 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4463 EXPECT_TRUE(data.slice_by_state(0).has_group_id());
4464 EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
4465 EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4466 }
4467
4468 /*
4469 * Test metric that slices by state with a primary field and has dimensions
4470 * - Increasing values
4471 * - Using diff
4472 * - Second field is value field
4473 */
TEST(ValueMetricProducerTest,TestSlicedStateWithPrimaryField_WithDimensions)4474 TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
4475 // Set up ValueMetricProducer.
4476 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
4477 metric.mutable_dimensions_in_what()->set_field(tagId);
4478 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
4479
4480 MetricStateLink* stateLink = metric.add_state_link();
4481 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
4482 auto fieldsInWhat = stateLink->mutable_fields_in_what();
4483 *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
4484 auto fieldsInState = stateLink->mutable_fields_in_state();
4485 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
4486
4487 /*
4488 NOTE: "1" denotes uid 1 and "2" denotes uid 2.
4489 bucket # 1 bucket # 2
4490 10 20 30 40 50 60 70 80 90 100 110 120 (seconds)
4491 |------------------------------------------|---------------------------------|--
4492
4493 (kStateUnknown)
4494 1
4495 |-------------|
4496 20
4497
4498 2
4499 |----------------------------|
4500 40
4501
4502 (FOREGROUND)
4503 1 1
4504 |----------------------------|-------------| |------|
4505 40 20 10
4506
4507
4508 (BACKGROUND)
4509 1
4510 |------------|
4511 20
4512 2
4513 |-------------|---------------------------------|
4514 20 50
4515 */
4516 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
4517 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
4518 // ValueMetricProducer initialized.
4519 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4520 vector<std::shared_ptr<LogEvent>>* data) {
4521 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
4522 data->clear();
4523 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
4524 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3));
4525 return true;
4526 }))
4527 // Uid 1 process state change from kStateUnknown -> Foreground
4528 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4529 vector<std::shared_ptr<LogEvent>>* data) {
4530 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
4531 data->clear();
4532 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
4533 1 /*uid*/, 6));
4534
4535 // This event should be skipped.
4536 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
4537 2 /*uid*/, 8));
4538 return true;
4539 }))
4540 // Uid 2 process state change from kStateUnknown -> Background
4541 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4542 vector<std::shared_ptr<LogEvent>>* data) {
4543 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
4544 data->clear();
4545 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
4546 2 /*uid*/, 9));
4547
4548 // This event should be skipped.
4549 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
4550 1 /*uid*/, 12));
4551 return true;
4552 }))
4553 // Uid 1 process state change from Foreground -> Background
4554 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4555 vector<std::shared_ptr<LogEvent>>* data) {
4556 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 20 * NS_PER_SEC);
4557 data->clear();
4558 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20 * NS_PER_SEC,
4559 1 /*uid*/, 13));
4560
4561 // This event should be skipped.
4562 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20 * NS_PER_SEC,
4563 2 /*uid*/, 11));
4564 return true;
4565 }))
4566 // Uid 1 process state change from Background -> Foreground
4567 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4568 vector<std::shared_ptr<LogEvent>>* data) {
4569 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 40 * NS_PER_SEC);
4570 data->clear();
4571 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40 * NS_PER_SEC,
4572 1 /*uid*/, 17));
4573
4574 // This event should be skipped.
4575 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40 * NS_PER_SEC,
4576 2 /*uid */, 15));
4577 return true;
4578 }))
4579 // Dump report pull.
4580 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4581 vector<std::shared_ptr<LogEvent>>* data) {
4582 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50 * NS_PER_SEC);
4583 data->clear();
4584 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50 * NS_PER_SEC,
4585 2 /*uid*/, 20));
4586 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50 * NS_PER_SEC,
4587 1 /*uid*/, 21));
4588 return true;
4589 }));
4590
4591 StateManager::getInstance().clear();
4592 sp<ValueMetricProducer> valueProducer =
4593 ValueMetricProducerTestHelper::createValueProducerWithState(
4594 pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
4595
4596 // Set up StateManager and check that StateTrackers are initialized.
4597 StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
4598 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4599 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
4600
4601 // Bucket status after metric initialized.
4602 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4603 // Base for dimension key {uid 1}.
4604 auto it = valueProducer->mCurrentSlicedBucket.begin();
4605 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4606 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4607 EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
4608 EXPECT_TRUE(itBase->second.hasCurrentState);
4609 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4610 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4611 itBase->second.currentState.getValues()[0].mValue.int_value);
4612 // Value for dimension, state key {{uid 1}, kStateUnknown}
4613 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4614 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4615 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4616 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4617 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4618 EXPECT_FALSE(it->second.intervals[0].hasValue);
4619 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4620 // Base for dimension key {uid 2}
4621 it++;
4622 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4623 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4624 EXPECT_EQ(7, itBase->second.baseInfos[0].base.long_value);
4625 EXPECT_TRUE(itBase->second.hasCurrentState);
4626 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4627 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4628 itBase->second.currentState.getValues()[0].mValue.int_value);
4629 // Value for dimension, state key {{uid 2}, kStateUnknown}
4630 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4631 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4632 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4633 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4634 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4635 EXPECT_FALSE(it->second.intervals[0].hasValue);
4636 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4637
4638 // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
4639 auto uidProcessEvent =
4640 CreateUidProcessStateChangedEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /* uid */,
4641 android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
4642 StateManager::getInstance().onLogEvent(*uidProcessEvent);
4643 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4644 // Base for dimension key {uid 1}.
4645 it = valueProducer->mCurrentSlicedBucket.begin();
4646 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4647 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4648 EXPECT_EQ(6, itBase->second.baseInfos[0].base.long_value);
4649 EXPECT_TRUE(itBase->second.hasCurrentState);
4650 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4651 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4652 itBase->second.currentState.getValues()[0].mValue.int_value);
4653 // Value for key {uid 1, kStateUnknown}.
4654 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4655 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4656 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4657 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4658 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4659 EXPECT_TRUE(it->second.intervals[0].hasValue);
4660 EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4661 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4662 bucketStartTimeNs + 20 * NS_PER_SEC);
4663 // Value for key {uid 1, FOREGROUND}.
4664 it++;
4665 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4666 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4667 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4668 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4669 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4670 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4671
4672 // Base for dimension key {uid 2}.
4673 it++;
4674 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4675 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4676 EXPECT_EQ(7, itBase->second.baseInfos[0].base.long_value);
4677 EXPECT_TRUE(itBase->second.hasCurrentState);
4678 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4679 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4680 itBase->second.currentState.getValues()[0].mValue.int_value);
4681 // Value for key {uid 2, kStateUnknown}.
4682 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4683 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4684 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4685 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4686 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4687 EXPECT_FALSE(it->second.intervals[0].hasValue);
4688 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4689
4690 // Bucket status after uid 2 process state change kStateUnknown -> Background.
4691 uidProcessEvent =
4692 CreateUidProcessStateChangedEvent(bucketStartTimeNs + 40 * NS_PER_SEC, 2 /* uid */,
4693 android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
4694 StateManager::getInstance().onLogEvent(*uidProcessEvent);
4695 ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
4696 // Base for dimension key {uid 2}.
4697 it = valueProducer->mCurrentSlicedBucket.begin();
4698 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4699 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4700 EXPECT_EQ(9, itBase->second.baseInfos[0].base.long_value);
4701 EXPECT_TRUE(itBase->second.hasCurrentState);
4702 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4703 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4704 itBase->second.currentState.getValues()[0].mValue.int_value);
4705 // Value for key {uid 2, BACKGROUND}.
4706 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4707 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4708 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4709 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4710 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4711 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4712
4713 // Base for dimension key {uid 1}.
4714 it++;
4715 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4716 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4717 EXPECT_EQ(6, itBase->second.baseInfos[0].base.long_value);
4718 EXPECT_TRUE(itBase->second.hasCurrentState);
4719 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4720 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4721 itBase->second.currentState.getValues()[0].mValue.int_value);
4722 // Value for key {uid 1, kStateUnknown}.
4723 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4724 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4725 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4726 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4727 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4728 EXPECT_TRUE(it->second.intervals[0].hasValue);
4729 EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4730 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4731 bucketStartTimeNs + 20 * NS_PER_SEC);
4732
4733 // Value for key {uid 1, FOREGROUND}.
4734 it++;
4735 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4736 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4737 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4738 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4739 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4740 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4741
4742 // Value for key {uid 2, kStateUnknown}
4743 it++;
4744 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4745 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4746 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4747 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4748 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4749 EXPECT_TRUE(it->second.intervals[0].hasValue);
4750 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4751 assertConditionTimer(it->second.conditionTimer, false, 40 * NS_PER_SEC,
4752 bucketStartTimeNs + 40 * NS_PER_SEC);
4753
4754 // Pull at end of first bucket.
4755 vector<shared_ptr<LogEvent>> allData;
4756 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 10));
4757 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 15));
4758 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
4759
4760 // Buckets flushed after end of first bucket.
4761 // None of the buckets should have a value.
4762 ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
4763 ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
4764 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
4765 // Base for dimension key {uid 2}.
4766 it = valueProducer->mCurrentSlicedBucket.begin();
4767 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4768 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4769 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4770 EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
4771 EXPECT_TRUE(itBase->second.hasCurrentState);
4772 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4773 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4774 itBase->second.currentState.getValues()[0].mValue.int_value);
4775 // Value for key {uid 2, BACKGROUND}.
4776 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4777 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4778 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4779 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4780 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4781 EXPECT_FALSE(it->second.intervals[0].hasValue);
4782 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4783 EXPECT_EQ(20 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4784
4785 // Base for dimension key {uid 1}
4786 it++;
4787 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4788 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4789 EXPECT_EQ(10, itBase->second.baseInfos[0].base.long_value);
4790 EXPECT_TRUE(itBase->second.hasCurrentState);
4791 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4792 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4793 itBase->second.currentState.getValues()[0].mValue.int_value);
4794 // Value for key {uid 1, kStateUnknown}
4795 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4796 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4797 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4798 EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
4799 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4800 EXPECT_FALSE(it->second.intervals[0].hasValue);
4801 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4802 EXPECT_EQ(20 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4803
4804 // Value for key {uid 1, FOREGROUND}
4805 it++;
4806 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4807 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4808 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4809 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4810 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4811 EXPECT_FALSE(it->second.intervals[0].hasValue);
4812 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4813 EXPECT_EQ(40 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4814
4815 // Value for key {uid 2, kStateUnknown}
4816 it++;
4817 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4818 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4819 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4820 EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
4821 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4822 EXPECT_FALSE(it->second.intervals[0].hasValue);
4823 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4824 EXPECT_EQ(40 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4825
4826 // Bucket status after uid 1 process state change from Foreground -> Background.
4827 uidProcessEvent =
4828 CreateUidProcessStateChangedEvent(bucket2StartTimeNs + 20 * NS_PER_SEC, 1 /* uid */,
4829 android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
4830 StateManager::getInstance().onLogEvent(*uidProcessEvent);
4831
4832 ASSERT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
4833 ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
4834 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
4835 // Base for dimension key {uid 2}.
4836 it = valueProducer->mCurrentSlicedBucket.begin();
4837 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4838 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4839 EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
4840 EXPECT_TRUE(itBase->second.hasCurrentState);
4841 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4842 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4843 itBase->second.currentState.getValues()[0].mValue.int_value);
4844 // Value for key {uid 2, BACKGROUND}.
4845 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4846 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4847 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4848 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4849 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4850 EXPECT_FALSE(it->second.intervals[0].hasValue);
4851 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4852
4853 // Base for dimension key {uid 1}
4854 it++;
4855 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4856 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4857 EXPECT_EQ(13, itBase->second.baseInfos[0].base.long_value);
4858 EXPECT_TRUE(itBase->second.hasCurrentState);
4859 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4860 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4861 itBase->second.currentState.getValues()[0].mValue.int_value);
4862 // Value for key {uid 1, kStateUnknown}
4863 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4864 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4865 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4866 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4867 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4868 EXPECT_FALSE(it->second.intervals[0].hasValue);
4869 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4870
4871 // Value for key {uid 1, BACKGROUND}
4872 it++;
4873 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4874 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4875 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4876 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4877 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4878 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs + 20 * NS_PER_SEC);
4879
4880 // Value for key {uid 1, FOREGROUND}
4881 it++;
4882 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4883 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4884 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4885 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4886 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4887 EXPECT_TRUE(it->second.intervals[0].hasValue);
4888 EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4889 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4890 bucket2StartTimeNs + 20 * NS_PER_SEC);
4891
4892 // Value for key {uid 2, kStateUnknown}
4893 it++;
4894 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4895 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4896 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4897 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4898 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4899 EXPECT_FALSE(it->second.intervals[0].hasValue);
4900 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4901
4902 // Bucket status after uid 1 process state change Background->Foreground.
4903 uidProcessEvent =
4904 CreateUidProcessStateChangedEvent(bucket2StartTimeNs + 40 * NS_PER_SEC, 1 /* uid */,
4905 android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
4906 StateManager::getInstance().onLogEvent(*uidProcessEvent);
4907
4908 ASSERT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
4909 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
4910 // Base for dimension key {uid 2}
4911 it = valueProducer->mCurrentSlicedBucket.begin();
4912 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4913 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4914 EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
4915 EXPECT_TRUE(itBase->second.hasCurrentState);
4916 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4917 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4918 itBase->second.currentState.getValues()[0].mValue.int_value);
4919 // Value for key {uid 2, BACKGROUND}
4920 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4921 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4922 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4923 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4924 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4925 EXPECT_FALSE(it->second.intervals[0].hasValue);
4926 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4927
4928 // Base for dimension key {uid 1}
4929 it++;
4930 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4931 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4932 EXPECT_EQ(17, itBase->second.baseInfos[0].base.long_value);
4933 EXPECT_TRUE(itBase->second.hasCurrentState);
4934 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4935 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4936 itBase->second.currentState.getValues()[0].mValue.int_value);
4937 // Value for key {uid 1, kStateUnknown}
4938 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4939 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4940 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4941 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4942 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4943 EXPECT_FALSE(it->second.intervals[0].hasValue);
4944 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4945
4946 // Value for key {uid 1, BACKGROUND}
4947 it++;
4948 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4949 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4950 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4951 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4952 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4953 EXPECT_TRUE(it->second.intervals[0].hasValue);
4954 EXPECT_EQ(4, it->second.intervals[0].value.long_value);
4955 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4956 bucket2StartTimeNs + 40 * NS_PER_SEC);
4957
4958 // Value for key {uid 1, FOREGROUND}
4959 it++;
4960 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4961 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4962 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4963 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4964 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4965 EXPECT_TRUE(it->second.intervals[0].hasValue);
4966 EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4967 assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
4968 bucket2StartTimeNs + 40 * NS_PER_SEC);
4969
4970 // Value for key {uid 2, kStateUnknown}
4971 it++;
4972 ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4973 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4974 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4975 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4976 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4977 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4978
4979 // Start dump report and check output.
4980 ProtoOutputStream output;
4981 std::set<string> strSet;
4982 valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
4983 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
4984 &strSet, &output);
4985
4986 StatsLogReport report = outputStreamToProto(&output);
4987 EXPECT_TRUE(report.has_value_metrics());
4988 ASSERT_EQ(5, report.value_metrics().data_size());
4989
4990 // {uid 1, BACKGROUND}
4991 auto data = report.value_metrics().data(0);
4992 ASSERT_EQ(1, data.bucket_info_size());
4993 EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4994 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4995 EXPECT_TRUE(data.slice_by_state(0).has_value());
4996 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
4997 data.slice_by_state(0).value());
4998 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4999
5000 // {uid 2, kStateUnknown}
5001 data = report.value_metrics().data(1);
5002 ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
5003 EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
5004 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5005 EXPECT_TRUE(data.slice_by_state(0).has_value());
5006 EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value());
5007 EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5008
5009 // {uid 1, FOREGROUND}
5010 data = report.value_metrics().data(2);
5011 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5012 EXPECT_TRUE(data.slice_by_state(0).has_value());
5013 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
5014 data.slice_by_state(0).value());
5015 ASSERT_EQ(2, report.value_metrics().data(2).bucket_info_size());
5016 EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
5017 EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
5018 EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5019 EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
5020
5021 // {uid 1, kStateUnknown}
5022 data = report.value_metrics().data(3);
5023 ASSERT_EQ(1, report.value_metrics().data(3).bucket_info_size());
5024 EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
5025 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5026 EXPECT_TRUE(data.slice_by_state(0).has_value());
5027 EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value());
5028 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5029
5030 // {uid 2, BACKGROUND}
5031 data = report.value_metrics().data(4);
5032 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5033 EXPECT_TRUE(data.slice_by_state(0).has_value());
5034 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
5035 data.slice_by_state(0).value());
5036 ASSERT_EQ(2, report.value_metrics().data(4).bucket_info_size());
5037 EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
5038 EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
5039 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5040 EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
5041 }
5042
5043 /*
5044 * Test slicing condition_true_nanos by state for metric that slices by state when data is not
5045 * present in pulled data during a state change.
5046 */
TEST(ValueMetricProducerTest,TestSlicedStateWithMissingDataInStateChange)5047 TEST(ValueMetricProducerTest, TestSlicedStateWithMissingDataInStateChange) {
5048 // Set up ValueMetricProducer.
5049 ValueMetric metric =
5050 ValueMetricProducerTestHelper::createMetricWithState("BATTERY_SAVER_MODE_STATE");
5051 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5052 /*
5053 NOTE: "-" means that the data was not present in the pulled data.
5054
5055 bucket # 1
5056 10 20 30 40 50 60 (seconds)
5057 |-------------------------------------------------------|--
5058 x (kStateUnknown)
5059 |-----------|
5060 10
5061
5062 x x (ON)
5063 |---------------------| |-----------|
5064 20 10
5065
5066 - (OFF)
5067 */
5068 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5069 // ValueMetricProducer initialized.
5070 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5071 vector<std::shared_ptr<LogEvent>>* data) {
5072 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
5073 data->clear();
5074 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
5075 return true;
5076 }))
5077 // Battery saver mode state changed to ON.
5078 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5079 vector<std::shared_ptr<LogEvent>>* data) {
5080 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5081 data->clear();
5082 data->push_back(
5083 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 5));
5084 return true;
5085 }))
5086 // Battery saver mode state changed to OFF but data for dimension key {} is not present
5087 // in the pulled data.
5088 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5089 vector<std::shared_ptr<LogEvent>>* data) {
5090 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
5091 data->clear();
5092 return true;
5093 }))
5094 // Battery saver mode state changed to ON.
5095 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5096 vector<std::shared_ptr<LogEvent>>* data) {
5097 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
5098 data->clear();
5099 data->push_back(
5100 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC, 7));
5101 return true;
5102 }))
5103 // Dump report pull.
5104 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5105 vector<std::shared_ptr<LogEvent>>* data) {
5106 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
5107 data->clear();
5108 data->push_back(CreateRepeatedValueLogEvent(
5109 tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 15));
5110 return true;
5111 }));
5112
5113 StateManager::getInstance().clear();
5114 sp<ValueMetricProducer> valueProducer =
5115 ValueMetricProducerTestHelper::createValueProducerWithState(
5116 pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {});
5117 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5118
5119 // Set up StateManager and check that StateTrackers are initialized.
5120 StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5121 valueProducer);
5122 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5123 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5124 util::BATTERY_SAVER_MODE_STATE_CHANGED));
5125
5126 // Bucket status after metric initialized.
5127 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
5128 // Base for dimension key {}
5129 auto it = valueProducer->mCurrentSlicedBucket.begin();
5130 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5131 EXPECT_TRUE(itBase->second.hasCurrentState);
5132 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5133 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5134 itBase->second.currentState.getValues()[0].mValue.int_value);
5135 // Value for dimension, state key {{}, kStateUnknown}
5136 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5137 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5138 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5139 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5140 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
5141
5142 // Bucket status after battery saver mode ON event.
5143 unique_ptr<LogEvent> batterySaverOnEvent =
5144 CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5145 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5146
5147 // Base for dimension key {}
5148
5149 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5150 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5151 it = valueProducer->mCurrentSlicedBucket.begin();
5152 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5153 EXPECT_TRUE(itBase->second.hasCurrentState);
5154 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5155 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5156 itBase->second.currentState.getValues()[0].mValue.int_value);
5157 // Value for key {{}, ON}
5158 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5159 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5160 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5161 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5162 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5163
5164 // Value for key {{}, -1}
5165 it++;
5166 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5167 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5168 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5169 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5170 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5171 bucketStartTimeNs + 10 * NS_PER_SEC);
5172
5173 // Bucket status after battery saver mode OFF event which is not present
5174 // in the pulled data.
5175 unique_ptr<LogEvent> batterySaverOffEvent =
5176 CreateBatterySaverOffEvent(/*timestamp=*/bucketStartTimeNs + 30 * NS_PER_SEC);
5177 StateManager::getInstance().onLogEvent(*batterySaverOffEvent);
5178
5179 // Base for dimension key {}
5180 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5181 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5182 it = valueProducer->mCurrentSlicedBucket.begin();
5183 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5184 EXPECT_FALSE(itBase->second.hasCurrentState);
5185 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5186 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5187 itBase->second.currentState.getValues()[0].mValue.int_value);
5188 // Value for key {{}, ON}
5189 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5190 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5191 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5192 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5193 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
5194 bucketStartTimeNs + 30 * NS_PER_SEC);
5195
5196 // Value for key {{}, -1}
5197 it++;
5198 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5199 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5200 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5201 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5202 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5203 bucketStartTimeNs + 10 * NS_PER_SEC);
5204
5205 // Bucket status after battery saver mode ON event.
5206 batterySaverOnEvent =
5207 CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 40 * NS_PER_SEC);
5208 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5209
5210 // Base for dimension key {}
5211 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5212 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5213 it = valueProducer->mCurrentSlicedBucket.begin();
5214 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5215 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5216 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5217 itBase->second.currentState.getValues()[0].mValue.int_value);
5218 // Value for key {{}, ON}
5219 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5220 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5221 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5222 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5223 assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
5224 bucketStartTimeNs + 40 * NS_PER_SEC);
5225
5226 // Value for key {{}, -1}
5227 it++;
5228 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5229 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5230 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5231 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5232 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5233 bucketStartTimeNs + 10 * NS_PER_SEC);
5234
5235 // Start dump report and check output.
5236 ProtoOutputStream output;
5237 std::set<string> strSet;
5238 valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
5239 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5240 &strSet, &output);
5241
5242 StatsLogReport report = outputStreamToProto(&output);
5243 EXPECT_TRUE(report.has_value_metrics());
5244 ASSERT_EQ(2, report.value_metrics().data_size());
5245
5246 // {{}, kStateUnknown}
5247 ValueMetricData data = report.value_metrics().data(0);
5248 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5249 EXPECT_EQ(-1 /*StateTracker::kUnknown*/, data.slice_by_state(0).value());
5250 ASSERT_EQ(1, data.bucket_info_size());
5251 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5252
5253 // {{}, ON}
5254 data = report.value_metrics().data(1);
5255 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5256 EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
5257 ASSERT_EQ(1, data.bucket_info_size());
5258 EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5259 }
5260
5261 /*
5262 * Test for metric that slices by state when data is not present in pulled data
5263 * during an event and then a flush occurs for the current bucket. With the new
5264 * condition timer behavior, a "new" MetricDimensionKey is inserted into
5265 * `mCurrentSlicedBucket` before intervals are closed/added to that new
5266 * MetricDimensionKey.
5267 */
TEST(ValueMetricProducerTest,TestSlicedStateWithMissingDataThenFlushBucket)5268 TEST(ValueMetricProducerTest, TestSlicedStateWithMissingDataThenFlushBucket) {
5269 // Set up ValueMetricProducer.
5270 ValueMetric metric =
5271 ValueMetricProducerTestHelper::createMetricWithState("BATTERY_SAVER_MODE_STATE");
5272 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5273 /*
5274 NOTE: "-" means that the data was not present in the pulled data.
5275
5276 bucket # 1
5277 10 20 30 40 50 60 (seconds)
5278 |-------------------------------------------------------|--
5279 - (kStateUnknown)
5280
5281 - (ON)
5282 */
5283 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5284 // ValueMetricProducer initialized but data for dimension key {} is not present
5285 // in the pulled data..
5286 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5287 vector<std::shared_ptr<LogEvent>>* data) {
5288 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
5289 data->clear();
5290 return true;
5291 }))
5292 // Battery saver mode state changed to ON but data for dimension key {} is not present
5293 // in the pulled data.
5294 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5295 vector<std::shared_ptr<LogEvent>>* data) {
5296 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5297 data->clear();
5298 return true;
5299 }))
5300 // Dump report pull.
5301 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5302 vector<std::shared_ptr<LogEvent>>* data) {
5303 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
5304 data->clear();
5305 data->push_back(CreateRepeatedValueLogEvent(
5306 tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 15));
5307 return true;
5308 }));
5309
5310 StateManager::getInstance().clear();
5311 sp<ValueMetricProducer> valueProducer =
5312 ValueMetricProducerTestHelper::createValueProducerWithState(
5313 pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {});
5314 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5315
5316 // Set up StateManager and check that StateTrackers are initialized.
5317 StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5318 valueProducer);
5319 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5320 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5321 util::BATTERY_SAVER_MODE_STATE_CHANGED));
5322
5323 // Bucket status after metric initialized.
5324 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
5325 ASSERT_EQ(0UL, valueProducer->mCurrentBaseInfo.size());
5326
5327 // Bucket status after battery saver mode ON event which is not present
5328 // in the pulled data.
5329 unique_ptr<LogEvent> batterySaverOnEvent =
5330 CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5331 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5332
5333 ASSERT_EQ(0UL, valueProducer->mCurrentBaseInfo.size());
5334 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
5335
5336 // Start dump report and check output.
5337 ProtoOutputStream output;
5338 std::set<string> strSet;
5339 valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
5340 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5341 &strSet, &output);
5342
5343 StatsLogReport report = outputStreamToProto(&output);
5344 EXPECT_TRUE(report.has_value_metrics());
5345 ASSERT_EQ(0, report.value_metrics().data_size());
5346 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5347 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5348 }
5349
TEST(ValueMetricProducerTest,TestSlicedStateWithNoPullOnBucketBoundary)5350 TEST(ValueMetricProducerTest, TestSlicedStateWithNoPullOnBucketBoundary) {
5351 // Set up ValueMetricProducer.
5352 ValueMetric metric =
5353 ValueMetricProducerTestHelper::createMetricWithState("BATTERY_SAVER_MODE_STATE");
5354 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5355 /*
5356 bucket # 1 bucket # 2
5357 10 20 30 40 50 60 70 80 90 100 110 120 (seconds)
5358 |------------------------------------|---------------------------|--
5359 x (kStateUnknown)
5360 |-----|
5361 10
5362 x x (ON)
5363 |-----| |-----------|
5364 10 20
5365 x (OFF)
5366 |------------------------|
5367 40
5368 */
5369 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5370 // ValueMetricProducer initialized.
5371 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5372 vector<std::shared_ptr<LogEvent>>* data) {
5373 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
5374 data->clear();
5375 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
5376 return true;
5377 }))
5378 // Battery saver mode state changed to ON.
5379 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5380 vector<std::shared_ptr<LogEvent>>* data) {
5381 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5382 data->clear();
5383 data->push_back(
5384 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 5));
5385 return true;
5386 }))
5387 // Battery saver mode state changed to OFF.
5388 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5389 vector<std::shared_ptr<LogEvent>>* data) {
5390 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
5391 data->clear();
5392 data->push_back(
5393 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC, 7));
5394 return true;
5395 }))
5396 // Battery saver mode state changed to ON.
5397 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5398 vector<std::shared_ptr<LogEvent>>* data) {
5399 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 30 * NS_PER_SEC);
5400 data->clear();
5401 data->push_back(CreateRepeatedValueLogEvent(
5402 tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 10));
5403 return true;
5404 }))
5405 // Dump report pull.
5406 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5407 vector<std::shared_ptr<LogEvent>>* data) {
5408 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50 * NS_PER_SEC);
5409 data->clear();
5410 data->push_back(CreateRepeatedValueLogEvent(
5411 tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 15));
5412 return true;
5413 }));
5414
5415 StateManager::getInstance().clear();
5416 sp<ValueMetricProducer> valueProducer =
5417 ValueMetricProducerTestHelper::createValueProducerWithState(
5418 pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {});
5419 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5420
5421 // Set up StateManager and check that StateTrackers are initialized.
5422 StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5423 valueProducer);
5424 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5425 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5426 util::BATTERY_SAVER_MODE_STATE_CHANGED));
5427
5428 // Bucket status after metric initialized.
5429 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
5430 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5431 auto it = valueProducer->mCurrentSlicedBucket.begin();
5432 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5433 EXPECT_TRUE(itBase->second.hasCurrentState);
5434 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5435 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5436 itBase->second.currentState.getValues()[0].mValue.int_value);
5437 // Value for dimension, state key {{}, kStateUnknown}
5438 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5439 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5440 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5441 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5442 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
5443
5444 // Bucket status after battery saver mode ON event.
5445 unique_ptr<LogEvent> batterySaverOnEvent =
5446 CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5447 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5448
5449 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5450 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5451 it = valueProducer->mCurrentSlicedBucket.begin();
5452 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5453 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5454 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5455 itBase->second.currentState.getValues()[0].mValue.int_value);
5456 // Value for key {{}, ON}
5457 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5458 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5459 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5460 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5461 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5462
5463 // Value for key {{}, -1}
5464 it++;
5465 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5466 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5467 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5468 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5469 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5470 bucketStartTimeNs + 10 * NS_PER_SEC);
5471
5472 // Bucket status after battery saver mode OFF event.
5473 unique_ptr<LogEvent> batterySaverOffEvent =
5474 CreateBatterySaverOffEvent(/*timestamp=*/bucketStartTimeNs + 20 * NS_PER_SEC);
5475 StateManager::getInstance().onLogEvent(*batterySaverOffEvent);
5476
5477 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5478 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
5479 it = valueProducer->mCurrentSlicedBucket.begin();
5480 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5481 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5482 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
5483 itBase->second.currentState.getValues()[0].mValue.int_value);
5484 // Value for key {{}, OFF}
5485 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5486 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5487 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
5488 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5489 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
5490
5491 // Value for key {{}, ON}
5492 it++;
5493 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5494 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5495 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5496 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5497 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5498 bucketStartTimeNs + 20 * NS_PER_SEC);
5499
5500 // Value for key {{}, -1}
5501 it++;
5502 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5503 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5504 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5505 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5506 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5507 bucketStartTimeNs + 10 * NS_PER_SEC);
5508
5509 // Bucket status after battery saver mode ON event.
5510 batterySaverOnEvent =
5511 CreateBatterySaverOnEvent(/*timestamp=*/bucket2StartTimeNs + 30 * NS_PER_SEC);
5512 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5513
5514 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5515 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
5516 it = valueProducer->mCurrentSlicedBucket.begin();
5517 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5518 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5519 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5520 itBase->second.currentState.getValues()[0].mValue.int_value);
5521 // Value for key {{}, OFF}
5522 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5523 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5524 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
5525 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5526 assertConditionTimer(it->second.conditionTimer, false, 30 * NS_PER_SEC,
5527 bucket2StartTimeNs + 30 * NS_PER_SEC);
5528
5529 // Value for key {{}, ON}
5530 it++;
5531 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5532 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5533 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5534 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5535 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs + 30 * NS_PER_SEC);
5536
5537 // Value for key {{}, -1}
5538 it++;
5539 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5540 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5541 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5542 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5543 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5544
5545 // Start dump report and check output.
5546 ProtoOutputStream output;
5547 std::set<string> strSet;
5548 valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
5549 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5550 &strSet, &output);
5551
5552 StatsLogReport report = outputStreamToProto(&output);
5553 EXPECT_TRUE(report.has_value_metrics());
5554 ASSERT_EQ(3, report.value_metrics().data_size());
5555
5556 // {{}, kStateUnknown}
5557 ValueMetricData data = report.value_metrics().data(0);
5558 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5559 EXPECT_EQ(-1 /*StateTracker::kUnknown*/, data.slice_by_state(0).value());
5560 ASSERT_EQ(1, data.bucket_info_size());
5561 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5562
5563 // {{}, ON}
5564 data = report.value_metrics().data(1);
5565 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5566 EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
5567 ASSERT_EQ(2, data.bucket_info_size());
5568 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5569 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
5570
5571 // {{}, OFF}
5572 data = report.value_metrics().data(2);
5573 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5574 EXPECT_EQ(BatterySaverModeStateChanged::OFF, data.slice_by_state(0).value());
5575 ASSERT_EQ(1, data.bucket_info_size());
5576 EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5577 }
5578
5579 /*
5580 * Test slicing condition_true_nanos by state for metric that slices by state when data is not
5581 * present in pulled data during a condition change.
5582 */
TEST(ValueMetricProducerTest,TestSlicedStateWithDataMissingInConditionChange)5583 TEST(ValueMetricProducerTest, TestSlicedStateWithDataMissingInConditionChange) {
5584 // Set up ValueMetricProducer.
5585 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithConditionAndState(
5586 "BATTERY_SAVER_MODE_STATE");
5587 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5588 /*
5589 NOTE: "-" means that the data was not present in the pulled data.
5590
5591 bucket # 1
5592 10 20 30 40 50 60 (seconds)
5593 |-------------------------------------------------------|--
5594
5595 T F T (Condition)
5596 x (ON)
5597 |----------------------| -
5598 20
5599 */
5600 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5601 // Battery saver mode state changed to ON.
5602 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5603 vector<std::shared_ptr<LogEvent>>* data) {
5604 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5605 data->clear();
5606 data->push_back(
5607 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 3));
5608 return true;
5609 }))
5610 // Condition changed to false.
5611 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5612 vector<std::shared_ptr<LogEvent>>* data) {
5613 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
5614 data->clear();
5615 data->push_back(
5616 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30 * NS_PER_SEC, 5));
5617 return true;
5618 }))
5619 // Condition changed to true but data for dimension key {} is not present in the
5620 // pulled data.
5621 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5622 vector<std::shared_ptr<LogEvent>>* data) {
5623 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
5624 data->clear();
5625 return true;
5626 }))
5627 // Dump report pull.
5628 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5629 vector<std::shared_ptr<LogEvent>>* data) {
5630 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
5631 data->clear();
5632 data->push_back(CreateRepeatedValueLogEvent(
5633 tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 20));
5634 return true;
5635 }));
5636
5637 StateManager::getInstance().clear();
5638 sp<ValueMetricProducer> valueProducer =
5639 ValueMetricProducerTestHelper::createValueProducerWithConditionAndState(
5640 pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {},
5641 ConditionState::kTrue);
5642 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5643
5644 // Set up StateManager and check that StateTrackers are initialized.
5645 StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5646 valueProducer);
5647 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5648 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5649 util::BATTERY_SAVER_MODE_STATE_CHANGED));
5650
5651 // Bucket status after battery saver mode ON event.
5652 unique_ptr<LogEvent> batterySaverOnEvent =
5653 CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5654 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5655 // Base for dimension key {}
5656 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5657 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5658 auto it = valueProducer->mCurrentSlicedBucket.begin();
5659 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5660 EXPECT_TRUE(itBase->second.hasCurrentState);
5661 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5662 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5663 itBase->second.currentState.getValues()[0].mValue.int_value);
5664 // Value for key {{}, ON}
5665 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5666 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5667 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5668 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5669 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5670
5671 // Value for key {{}, -1}
5672 it++;
5673 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5674 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5675 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5676 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5677 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5678
5679 // Bucket status after condition change to false.
5680 valueProducer->onConditionChanged(false, bucketStartTimeNs + 30 * NS_PER_SEC);
5681 // Base for dimension key {}
5682 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5683 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5684 it = valueProducer->mCurrentSlicedBucket.begin();
5685 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5686 EXPECT_TRUE(itBase->second.hasCurrentState);
5687 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5688 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5689 itBase->second.currentState.getValues()[0].mValue.int_value);
5690 // Value for key {{}, ON}
5691 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5692 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5693 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5694 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5695 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
5696 bucketStartTimeNs + 30 * NS_PER_SEC);
5697
5698 // Value for key {{}, -1}
5699 it++;
5700 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5701 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5702 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5703 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5704 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5705
5706 // Bucket status after condition change to true.
5707 valueProducer->onConditionChanged(true, bucketStartTimeNs + 40 * NS_PER_SEC);
5708 // Base for dimension key {}
5709 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5710 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5711 it = valueProducer->mCurrentSlicedBucket.begin();
5712 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5713 EXPECT_FALSE(itBase->second.hasCurrentState);
5714 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5715 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5716 itBase->second.currentState.getValues()[0].mValue.int_value);
5717 // Value for key {{}, ON}
5718 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5719 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5720 EXPECT_EQ(BatterySaverModeStateChanged::ON,
5721 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5722 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
5723 bucketStartTimeNs + 30 * NS_PER_SEC);
5724
5725 // Value for key {{}, -1}
5726 it++;
5727 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5728 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5729 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5730 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5731 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5732
5733 // Start dump report and check output.
5734 ProtoOutputStream output;
5735 std::set<string> strSet;
5736 valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
5737 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5738 &strSet, &output);
5739
5740 StatsLogReport report = outputStreamToProto(&output);
5741 EXPECT_TRUE(report.has_value_metrics());
5742 ASSERT_EQ(1, report.value_metrics().data_size());
5743
5744 // {{}, ON}
5745 ValueMetricData data = report.value_metrics().data(0);
5746 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5747 EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
5748 ASSERT_EQ(1, data.bucket_info_size());
5749 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5750 }
5751
5752 /*
5753 * Test slicing condition_true_nanos by state for metric that slices by state with a primary field,
5754 * condition, and has multiple dimensions.
5755 */
TEST(ValueMetricProducerTest,TestSlicedStateWithMultipleDimensions)5756 TEST(ValueMetricProducerTest, TestSlicedStateWithMultipleDimensions) {
5757 // Set up ValueMetricProducer.
5758 ValueMetric metric =
5759 ValueMetricProducerTestHelper::createMetricWithConditionAndState("UID_PROCESS_STATE");
5760 metric.mutable_dimensions_in_what()->set_field(tagId);
5761 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
5762 metric.mutable_dimensions_in_what()->add_child()->set_field(3);
5763
5764 MetricStateLink* stateLink = metric.add_state_link();
5765 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
5766 auto fieldsInWhat = stateLink->mutable_fields_in_what();
5767 *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
5768 auto fieldsInState = stateLink->mutable_fields_in_state();
5769 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
5770
5771 /*
5772 bucket # 1 bucket # 2
5773 10 20 30 40 50 60 70 80 90 100 110 120 (seconds)
5774 |------------------------------------------|---------------------------------|--
5775
5776 T F T (Condition)
5777 (FOREGROUND)
5778 x {1, 14}
5779 |------|
5780 10
5781
5782 x {1, 16}
5783 |------|
5784 10
5785 x {2, 8}
5786 |-------------|
5787 20
5788
5789 (BACKGROUND)
5790 x {1, 14}
5791 |-------------| |----------|---------------------------------|
5792 20 15 50
5793
5794 x {1, 16}
5795 |-------------| |----------|---------------------------------|
5796 20 15 50
5797
5798 x {2, 8}
5799 |----------| |----------|-------------------|
5800 15 15 30
5801 */
5802 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5803 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5804 // Uid 1 process state change from kStateUnknown -> Foreground
5805 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5806 vector<std::shared_ptr<LogEvent>>* data) {
5807 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5808 data->clear();
5809 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC,
5810 1 /*uid*/, 3, 14 /*tag*/));
5811 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC,
5812 1 /*uid*/, 3, 16 /*tag*/));
5813
5814 // This event should be skipped.
5815 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC,
5816 2 /*uid*/, 5, 8 /*tag*/));
5817 return true;
5818 }))
5819 // Uid 1 process state change from Foreground -> Background
5820 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5821 vector<std::shared_ptr<LogEvent>>* data) {
5822 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
5823 data->clear();
5824 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
5825 1 /*uid*/, 5, 14 /*tag*/));
5826 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
5827 1 /*uid*/, 5, 16 /*tag*/));
5828
5829 // This event should be skipped.
5830 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
5831 2 /*uid*/, 7, 8 /*tag*/));
5832
5833 return true;
5834 }))
5835 // Uid 2 process state change from kStateUnknown -> Background
5836 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5837 vector<std::shared_ptr<LogEvent>>* data) {
5838 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 25 * NS_PER_SEC);
5839 data->clear();
5840 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 25 * NS_PER_SEC,
5841 2 /*uid*/, 9, 8 /*tag*/));
5842
5843 // This event should be skipped.
5844 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 25 * NS_PER_SEC,
5845 1 /*uid*/, 9, 14 /* tag */));
5846
5847 // This event should be skipped.
5848 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 25 * NS_PER_SEC,
5849 1 /*uid*/, 9, 16 /* tag */));
5850
5851 return true;
5852 }))
5853 // Condition changed to false.
5854 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5855 vector<std::shared_ptr<LogEvent>>* data) {
5856 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
5857 data->clear();
5858 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
5859 1 /*uid*/, 11, 14 /* tag */));
5860 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
5861 1 /*uid*/, 11, 16 /* tag */));
5862 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
5863 2 /*uid*/, 11, 8 /*tag*/));
5864
5865 return true;
5866 }))
5867 // Condition changed to true.
5868 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5869 vector<std::shared_ptr<LogEvent>>* data) {
5870 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 45 * NS_PER_SEC);
5871 data->clear();
5872 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 45 * NS_PER_SEC,
5873 1 /*uid*/, 13, 14 /* tag */));
5874 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 45 * NS_PER_SEC,
5875 1 /*uid*/, 13, 16 /* tag */));
5876 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 45 * NS_PER_SEC,
5877 2 /*uid*/, 13, 8 /*tag*/));
5878 return true;
5879 }))
5880 // Uid 2 process state change from Background -> Foreground
5881 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5882 vector<std::shared_ptr<LogEvent>>* data) {
5883 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 30 * NS_PER_SEC);
5884 data->clear();
5885 data->push_back(CreateThreeValueLogEvent(
5886 tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 2 /*uid*/, 18, 8 /*tag*/));
5887
5888 // This event should be skipped.
5889 data->push_back(CreateThreeValueLogEvent(
5890 tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 1 /*uid*/, 18, 14 /* tag */));
5891 // This event should be skipped.
5892 data->push_back(CreateThreeValueLogEvent(
5893 tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 1 /*uid*/, 18, 16 /* tag */));
5894
5895 return true;
5896 }))
5897 // Dump report pull.
5898 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5899 vector<std::shared_ptr<LogEvent>>* data) {
5900 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50 * NS_PER_SEC);
5901 data->clear();
5902 data->push_back(CreateThreeValueLogEvent(
5903 tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 1 /*uid*/, 21, 14 /* tag */));
5904 data->push_back(CreateThreeValueLogEvent(
5905 tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 1 /*uid*/, 21, 16 /* tag */));
5906 data->push_back(CreateThreeValueLogEvent(
5907 tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 2 /*uid*/, 21, 8 /*tag*/));
5908 return true;
5909 }));
5910
5911 StateManager::getInstance().clear();
5912 sp<ValueMetricProducer> valueProducer =
5913 ValueMetricProducerTestHelper::createValueProducerWithConditionAndState(
5914 pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {}, ConditionState::kTrue);
5915 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5916
5917 // Set up StateManager and check that StateTrackers are initialized.
5918 StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
5919 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5920 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
5921
5922 // Condition is true.
5923 // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
5924 auto uidProcessEvent =
5925 CreateUidProcessStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC, 1 /* uid */,
5926 android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
5927 StateManager::getInstance().onLogEvent(*uidProcessEvent);
5928 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
5929 ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
5930 // Base for dimension {uid 1, tag 16}.
5931 auto it = valueProducer->mCurrentSlicedBucket.begin();
5932 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5933 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5934 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5935 itBase->second.currentState.getValues()[0].mValue.int_value);
5936 // Value for key {{uid 1, uid 16}, FOREGROUND}.
5937 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5938 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5939 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5940 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5941 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5942 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5943 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5944 // Value for key {{uid 1, tag 16}, kStateUnknown}.
5945 it++;
5946 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5947 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5948 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5949 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5950 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5951 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5952 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5953
5954 // Base for dimension key {uid 1, tag 14}.
5955 it++;
5956 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5957 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5958 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5959 itBase->second.currentState.getValues()[0].mValue.int_value);
5960 // Value for key {{uid 1, tag 14}, FOREGROUND}.
5961 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5962 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5963 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5964 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5965 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5966 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5967 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5968 // Value for key {{uid 1, tag 14}, kStateUnknown}.
5969 it++;
5970 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5971 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5972 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5973 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5974 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5975 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5976 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5977
5978 // Bucket status after uid 1 process state change Foreground -> Background.
5979 uidProcessEvent =
5980 CreateUidProcessStateChangedEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /* uid */,
5981 android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
5982 StateManager::getInstance().onLogEvent(*uidProcessEvent);
5983 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
5984 ASSERT_EQ(6UL, valueProducer->mCurrentSlicedBucket.size());
5985 // Base for dimension {uid 1, tag 16}.
5986 it = valueProducer->mCurrentSlicedBucket.begin();
5987 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5988 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5989 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
5990 itBase->second.currentState.getValues()[0].mValue.int_value);
5991 // Value for key {{uid 1, uid 16}, BACKGROUND}.
5992 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5993 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5994 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5995 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5996 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
5997 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5998 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
5999
6000 // Base for dimension key {uid 1, tag 14}.
6001 it++;
6002 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6003 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6004 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6005 itBase->second.currentState.getValues()[0].mValue.int_value);
6006 // Value for key {{uid 1, tag 14}, BACKGROUND}.
6007 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6008 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6009 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6010 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6011 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6012 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6013 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6014
6015 // Value for key {{uid 1, uid 16}, FOREGROUND}.
6016 it++;
6017 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6018 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6019 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6020 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6021 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6022 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6023 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6024 bucketStartTimeNs + 20 * NS_PER_SEC);
6025
6026 // Value for key {{uid 1, tag 16}, kStateUnknown}.
6027 it++;
6028 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6029 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6030 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6031 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6032 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6033 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6034 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6035
6036 // Value for key {{uid 1, tag 14}, FOREGROUND}.
6037 it++;
6038 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6039 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6040 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6041 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6042 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6043 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6044 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6045 bucketStartTimeNs + 20 * NS_PER_SEC);
6046
6047 // Value for key {{uid 1, tag 14}, kStateUnknown}.
6048 it++;
6049 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6050 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6051 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6052 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6053 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6054 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6055 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6056
6057 // Bucket status after uid 2 process state change kStateUnknown -> Background.
6058 uidProcessEvent =
6059 CreateUidProcessStateChangedEvent(bucketStartTimeNs + 25 * NS_PER_SEC, 2 /* uid */,
6060 android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
6061 StateManager::getInstance().onLogEvent(*uidProcessEvent);
6062 ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6063 ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6064 // Base for dimension {uid 2, tag 8}.
6065 it = valueProducer->mCurrentSlicedBucket.begin();
6066 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6067 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6068 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6069 itBase->second.currentState.getValues()[0].mValue.int_value);
6070 // Value for key {{uid 2, uid 8}, BACKGROUND}.
6071 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6072 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6073 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6074 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6075 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6076 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6077 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 25 * NS_PER_SEC);
6078
6079 // Value for key {{uid 2, uid 8}, kStateUnknown}.
6080 it++;
6081 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6082 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6083 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6084 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6085 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6086 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6087 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6088
6089 // Base for dimension {uid 1, tag 16}.
6090 it++;
6091 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6092 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6093 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6094 itBase->second.currentState.getValues()[0].mValue.int_value);
6095 // Value for key {{uid 1, uid 16}, BACKGROUND}.
6096 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6097 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6098 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6099 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6100 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6101 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6102 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6103
6104 // Base for dimension key {uid 1, tag 14}.
6105 it++;
6106 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6107 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6108 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6109 itBase->second.currentState.getValues()[0].mValue.int_value);
6110 // Value for key {{uid 1, tag 14}, BACKGROUND}.
6111 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6112 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6113 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6114 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6115 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6116 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6117 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6118
6119 // Value for key {{uid 1, uid 16}, FOREGROUND}.
6120 it++;
6121 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6122 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6123 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6124 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6125 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6126 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6127 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6128 bucketStartTimeNs + 20 * NS_PER_SEC);
6129
6130 // Value for key {{uid 1, tag 16}, kStateUnknown}.
6131 it++;
6132 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6133 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6134 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6135 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6136 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6137 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6138 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6139
6140 // Value for key {{uid 1, tag 14}, FOREGROUND}.
6141 it++;
6142 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6143 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6144 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6145 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6146 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6147 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6148 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6149 bucketStartTimeNs + 20 * NS_PER_SEC);
6150
6151 // Value for key {{uid 1, tag 14}, kStateUnknown}.
6152 it++;
6153 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6154 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6155 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6156 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6157 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6158 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6159 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6160
6161 // Bucket 1 status after condition change to false.
6162 // All condition timers should be turned off.
6163 valueProducer->onConditionChanged(false, bucketStartTimeNs + 40 * NS_PER_SEC);
6164 ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6165 ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6166 // Base for dimension {uid 2, tag 8}.
6167 it = valueProducer->mCurrentSlicedBucket.begin();
6168 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6169 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6170 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6171 itBase->second.currentState.getValues()[0].mValue.int_value);
6172 // Value for key {{uid 2, uid 8}, BACKGROUND}.
6173 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6174 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6175 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6176 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6177 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6178 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6179 assertConditionTimer(it->second.conditionTimer, false, 15 * NS_PER_SEC,
6180 bucketStartTimeNs + 40 * NS_PER_SEC);
6181
6182 // Value for key {{uid 2, uid 8}, kStateUnknown}.
6183 it++;
6184 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6185 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6186 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6187 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6188 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6189 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6190 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6191
6192 // Base for dimension {uid 1, tag 16}.
6193 it++;
6194 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6195 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6196 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6197 itBase->second.currentState.getValues()[0].mValue.int_value);
6198 // Value for key {{uid 1, uid 16}, BACKGROUND}.
6199 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6200 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6201 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6202 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6203 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6204 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6205 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
6206 bucketStartTimeNs + 40 * NS_PER_SEC);
6207
6208 // Base for dimension key {uid 1, tag 14}.
6209 it++;
6210 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6211 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6212 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6213 itBase->second.currentState.getValues()[0].mValue.int_value);
6214 // Value for key {{uid 1, tag 14}, BACKGROUND}.
6215 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6216 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6217 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6218 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6219 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6220 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6221 assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
6222 bucketStartTimeNs + 40 * NS_PER_SEC);
6223
6224 // Value for key {{uid 1, uid 16}, FOREGROUND}.
6225 it++;
6226 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6227 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6228 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6229 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6230 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6231 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6232 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6233 bucketStartTimeNs + 20 * NS_PER_SEC);
6234
6235 // Value for key {{uid 1, tag 16}, kStateUnknown}.
6236 it++;
6237 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6238 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6239 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6240 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6241 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6242 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6243 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6244
6245 // Value for key {{uid 1, tag 14}, FOREGROUND}.
6246 it++;
6247 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6248 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6249 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6250 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6251 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6252 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6253 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6254 bucketStartTimeNs + 20 * NS_PER_SEC);
6255
6256 // Value for key {{uid 1, tag 14}, kStateUnknown}.
6257 it++;
6258 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6259 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6260 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6261 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6262 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6263 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6264 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6265
6266 // Bucket 1 status after condition change to true.
6267 valueProducer->onConditionChanged(true, bucketStartTimeNs + 45 * NS_PER_SEC);
6268 ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6269 ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6270 // Base for dimension {uid 2, tag 8}.
6271 it = valueProducer->mCurrentSlicedBucket.begin();
6272 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6273 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6274 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6275 itBase->second.currentState.getValues()[0].mValue.int_value);
6276 // Value for key {{uid 2, uid 8}, BACKGROUND}.
6277 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6278 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6279 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6280 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6281 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6282 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6283 assertConditionTimer(it->second.conditionTimer, true, 15 * NS_PER_SEC,
6284 bucketStartTimeNs + 45 * NS_PER_SEC);
6285
6286 // Value for key {{uid 2, uid 8}, kStateUnknown}.
6287 it++;
6288 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6289 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6290 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6291 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6292 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6293 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6294 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6295
6296 // Base for dimension {uid 1, tag 16}.
6297 it++;
6298 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6299 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6300 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6301 itBase->second.currentState.getValues()[0].mValue.int_value);
6302 // Value for key {{uid 1, uid 16}, BACKGROUND}.
6303 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6304 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6305 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6306 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6307 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6308 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6309 assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
6310 bucketStartTimeNs + 45 * NS_PER_SEC);
6311
6312 // Base for dimension key {uid 1, tag 14}.
6313 it++;
6314 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6315 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6316 itBase->second.currentState.getValues()[0].mValue.int_value);
6317 // Value for key {{uid 1, tag 14}, BACKGROUND}.
6318 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6319 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6320 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6321 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6322 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6323 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6324 assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
6325 bucketStartTimeNs + 45 * NS_PER_SEC);
6326
6327 // Value for key {{uid 1, uid 16}, FOREGROUND}.
6328 it++;
6329 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6330 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6331 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6332 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6333 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6334 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6335 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6336 bucketStartTimeNs + 20 * NS_PER_SEC);
6337
6338 // Value for key {{uid 1, tag 16}, kStateUnknown}.
6339 it++;
6340 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6341 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6342 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6343 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6344 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6345 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6346 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6347
6348 // Value for key {{uid 1, tag 14}, FOREGROUND}.
6349 it++;
6350 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6351 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6352 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6353 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6354 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6355 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6356 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6357 bucketStartTimeNs + 20 * NS_PER_SEC);
6358
6359 // Value for key {{uid 1, tag 14}, kStateUnknown}.
6360 it++;
6361 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6362 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6363 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6364 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6365 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6366 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6367 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6368
6369 // Pull at end of first bucket.
6370 vector<shared_ptr<LogEvent>> allData;
6371 allData.push_back(
6372 CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 14 /* tag */));
6373 allData.push_back(
6374 CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 16 /* tag */));
6375 allData.push_back(
6376 CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 13, 8 /*tag*/));
6377 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
6378
6379 // Buckets flushed after end of first bucket.
6380 // All condition timers' behavior should rollover to bucket 2.
6381 ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6382 ASSERT_EQ(5UL, valueProducer->mPastBuckets.size());
6383 ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6384 // Base for dimension {uid 2, tag 8}.
6385 it = valueProducer->mCurrentSlicedBucket.begin();
6386 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6387 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6388 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6389 itBase->second.currentState.getValues()[0].mValue.int_value);
6390 // Value for key {{uid 2, uid 8}, BACKGROUND}.
6391 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6392 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6393 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6394 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6395 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6396 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6397 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6398 ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6399 EXPECT_EQ(30 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6400
6401 // Value for key {{uid 2, uid 8}, kStateUnknown}.
6402 it++;
6403 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6404 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6405 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6406 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6407 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6408 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6409 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6410
6411 // Base for dimension {uid 1, tag 16}.
6412 it++;
6413 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6414 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6415 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6416 itBase->second.currentState.getValues()[0].mValue.int_value);
6417 // Value for key {{uid 1, uid 16}, BACKGROUND}.
6418 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6419 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6420 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6421 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6422 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6423 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6424 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6425 ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6426 EXPECT_EQ(35 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6427
6428 // Base for dimension key {uid 1, tag 14}.
6429 it++;
6430 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6431 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6432 itBase->second.currentState.getValues()[0].mValue.int_value);
6433 // Value for key {{uid 1, tag 14}, BACKGROUND}.
6434 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6435 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6436 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6437 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6438 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6439 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6440 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6441 ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6442 EXPECT_EQ(35 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6443
6444 // Value for key {{uid 1, uid 16}, FOREGROUND}.
6445 it++;
6446 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6447 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6448 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6449 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6450 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6451 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6452 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6453 ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6454 EXPECT_EQ(10 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6455
6456 // Value for key {{uid 1, tag 16}, kStateUnknown}.
6457 it++;
6458 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6459 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6460 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6461 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6462 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6463 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6464 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6465
6466 // Value for key {{uid 1, tag 14}, FOREGROUND}.
6467 it++;
6468 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6469 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6470 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6471 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6472 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6473 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6474 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6475 ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6476 EXPECT_EQ(10 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6477
6478 // Value for key {{uid 1, tag 14}, kStateUnknown}.
6479 it++;
6480 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6481 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6482 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6483 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6484 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6485 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6486 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6487
6488 // Bucket 2 status after uid 2 process state change Background->Foreground.
6489 uidProcessEvent =
6490 CreateUidProcessStateChangedEvent(bucket2StartTimeNs + 30 * NS_PER_SEC, 2 /* uid */,
6491 android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
6492 StateManager::getInstance().onLogEvent(*uidProcessEvent);
6493
6494 ASSERT_EQ(9UL, valueProducer->mCurrentSlicedBucket.size());
6495 ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6496 // Base for dimension {uid 2, tag 8}.
6497 it = valueProducer->mCurrentSlicedBucket.begin();
6498 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6499 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6500 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6501 itBase->second.currentState.getValues()[0].mValue.int_value);
6502 // Value for key {{uid 2, uid 8}, FOREGROUND}.
6503 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6504 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6505 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6506 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6507 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6508 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6509 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs + 30 * NS_PER_SEC);
6510
6511 // Value for key {{uid 2, uid 8}, BACKGROUND}.
6512 it++;
6513 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6514 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6515 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6516 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6517 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6518 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6519 assertConditionTimer(it->second.conditionTimer, false, 30 * NS_PER_SEC,
6520 bucket2StartTimeNs + 30 * NS_PER_SEC);
6521
6522 // Value for key {{uid 2, uid 8}, kStateUnknown}.
6523 it++;
6524 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6525 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6526 EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6527 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6528 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6529 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6530 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6531
6532 // Base for dimension {uid 1, tag 16}.
6533 it++;
6534 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6535 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6536 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6537 itBase->second.currentState.getValues()[0].mValue.int_value);
6538 // Value for key {{uid 1, uid 16}, BACKGROUND}.
6539 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6540 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6541 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6542 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6543 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6544 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6545 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6546
6547 // Base for dimension key {uid 1, tag 14}.
6548 it++;
6549 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6550 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6551 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6552 itBase->second.currentState.getValues()[0].mValue.int_value);
6553 // Value for key {{uid 1, tag 14}, BACKGROUND}.
6554 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6555 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6556 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6557 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6558 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6559 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6560 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6561
6562 // Value for key {{uid 1, uid 16}, FOREGROUND}.
6563 it++;
6564 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6565 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6566 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6567 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6568 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6569 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6570 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6571
6572 // Value for key {{uid 1, tag 16}, kStateUnknown}.
6573 it++;
6574 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6575 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6576 EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6577 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6578 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6579 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6580 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6581
6582 // Value for key {{uid 1, tag 14}, FOREGROUND}.
6583 it++;
6584 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6585 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6586 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6587 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6588 EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6589 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6590 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6591
6592 // Value for key {{uid 1, tag 14}, kStateUnknown}.
6593 it++;
6594 ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6595 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6596 EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6597 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6598 EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6599 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6600 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6601
6602 // Start dump report and check output.
6603 ProtoOutputStream output;
6604 std::set<string> strSet;
6605 valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
6606 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
6607 &strSet, &output);
6608
6609 StatsLogReport report = outputStreamToProto(&output);
6610 EXPECT_TRUE(report.has_value_metrics());
6611 ASSERT_EQ(6, report.value_metrics().data_size());
6612
6613 // {{uid 1, tag 14}, FOREGROUND}.
6614 auto data = report.value_metrics().data(0);
6615 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6616 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
6617 data.slice_by_state(0).value());
6618 ASSERT_EQ(1, data.bucket_info_size());
6619 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6620
6621 // {{uid 1, tag 16}, BACKGROUND}.
6622 data = report.value_metrics().data(1);
6623 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6624 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
6625 data.slice_by_state(0).value());
6626 ASSERT_EQ(2, data.bucket_info_size());
6627 EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6628 EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6629
6630 // {{uid 1, tag 14}, BACKGROUND}.
6631 data = report.value_metrics().data(2);
6632 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6633 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
6634 data.slice_by_state(0).value());
6635 ASSERT_EQ(2, data.bucket_info_size());
6636 EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6637 EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6638
6639 // {{uid 1, tag 16}, FOREGROUND}.
6640 data = report.value_metrics().data(3);
6641 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6642 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
6643 data.slice_by_state(0).value());
6644 ASSERT_EQ(1, data.bucket_info_size());
6645 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6646
6647 // {{uid 2, tag 8}, FOREGROUND}.
6648 data = report.value_metrics().data(4);
6649 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6650 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
6651 data.slice_by_state(0).value());
6652 ASSERT_EQ(1, data.bucket_info_size());
6653 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6654
6655 // {{uid 2, tag 8}, BACKGROUND}.
6656 data = report.value_metrics().data(5);
6657 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6658 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
6659 data.slice_by_state(0).value());
6660 ASSERT_EQ(2, data.bucket_info_size());
6661 EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6662 EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6663 }
6664
TEST(ValueMetricProducerTest,TestSlicedStateWithCondition)6665 TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
6666 // Set up ValueMetricProducer.
6667 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithConditionAndState(
6668 "BATTERY_SAVER_MODE_STATE");
6669 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
6670 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
6671 // Condition changed to true.
6672 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6673 vector<std::shared_ptr<LogEvent>>* data) {
6674 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
6675 data->clear();
6676 data->push_back(
6677 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC, 3));
6678 return true;
6679 }))
6680 // Battery saver mode state changed to OFF.
6681 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6682 vector<std::shared_ptr<LogEvent>>* data) {
6683 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
6684 data->clear();
6685 data->push_back(
6686 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30 * NS_PER_SEC, 5));
6687 return true;
6688 }))
6689 // Condition changed to false.
6690 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6691 vector<std::shared_ptr<LogEvent>>* data) {
6692 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10 * NS_PER_SEC);
6693 data->clear();
6694 data->push_back(CreateRepeatedValueLogEvent(
6695 tagId, bucket2StartTimeNs + 10 * NS_PER_SEC, 15));
6696 return true;
6697 }));
6698
6699 StateManager::getInstance().clear();
6700 sp<ValueMetricProducer> valueProducer =
6701 ValueMetricProducerTestHelper::createValueProducerWithConditionAndState(
6702 pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {},
6703 ConditionState::kFalse);
6704 EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
6705
6706 // Set up StateManager and check that StateTrackers are initialized.
6707 StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
6708 valueProducer);
6709 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
6710 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
6711 util::BATTERY_SAVER_MODE_STATE_CHANGED));
6712
6713 // Bucket status after battery saver mode ON event.
6714 // Condition is false so we do nothing.
6715 unique_ptr<LogEvent> batterySaverOnEvent =
6716 CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
6717 StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
6718 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
6719 EXPECT_EQ(0UL, valueProducer->mCurrentBaseInfo.size());
6720
6721 // Bucket status after condition change to true.
6722 valueProducer->onConditionChanged(true, bucketStartTimeNs + 20 * NS_PER_SEC);
6723 // Base for dimension key {}
6724 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6725 std::unordered_map<HashableDimensionKey, ValueMetricProducer::DimensionsInWhatInfo>::iterator
6726 itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6727 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
6728 EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
6729 EXPECT_TRUE(itBase->second.hasCurrentState);
6730 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6731 EXPECT_EQ(BatterySaverModeStateChanged::ON,
6732 itBase->second.currentState.getValues()[0].mValue.int_value);
6733 // Value for key {{}, ON}
6734 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
6735 std::unordered_map<MetricDimensionKey, ValueMetricProducer::CurrentValueBucket>::iterator it =
6736 valueProducer->mCurrentSlicedBucket.begin();
6737 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6738 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6739 EXPECT_EQ(BatterySaverModeStateChanged::ON,
6740 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6741 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6742 // Value for key {{}, -1}
6743 it++;
6744 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6745 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6746 EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
6747 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6748 EXPECT_FALSE(it->second.intervals[0].hasValue);
6749 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6750
6751 // Bucket status after battery saver mode OFF event.
6752 unique_ptr<LogEvent> batterySaverOffEvent =
6753 CreateBatterySaverOffEvent(/*timestamp=*/bucketStartTimeNs + 30 * NS_PER_SEC);
6754 StateManager::getInstance().onLogEvent(*batterySaverOffEvent);
6755 // Base for dimension key {}
6756 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6757 itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6758 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
6759 EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
6760 EXPECT_TRUE(itBase->second.hasCurrentState);
6761 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6762 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6763 itBase->second.currentState.getValues()[0].mValue.int_value);
6764 // Value for key {{}, OFF}
6765 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
6766 it = valueProducer->mCurrentSlicedBucket.begin();
6767 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6768 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6769 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6770 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6771 assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 30 * NS_PER_SEC);
6772 // Value for key {{}, ON}
6773 it++;
6774 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6775 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6776 EXPECT_EQ(BatterySaverModeStateChanged::ON,
6777 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6778 EXPECT_TRUE(it->second.intervals[0].hasValue);
6779 EXPECT_EQ(2, it->second.intervals[0].value.long_value);
6780 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6781 bucketStartTimeNs + 30 * NS_PER_SEC);
6782 // Value for key {{}, -1}
6783 it++;
6784 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6785
6786 // Pull at end of first bucket.
6787 vector<shared_ptr<LogEvent>> allData;
6788 allData.clear();
6789 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 11));
6790 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
6791
6792 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
6793 EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
6794 // Base for dimension key {}
6795 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6796 itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6797 EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
6798 EXPECT_EQ(11, itBase->second.baseInfos[0].base.long_value);
6799 EXPECT_TRUE(itBase->second.hasCurrentState);
6800 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6801 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6802 itBase->second.currentState.getValues()[0].mValue.int_value);
6803 // Value for key {{}, OFF}
6804 it = valueProducer->mCurrentSlicedBucket.begin();
6805 assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6806 // Value for key {{}, ON}
6807 it++;
6808 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 30 * NS_PER_SEC);
6809 // Value for key {{}, -1}
6810 it++;
6811 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6812
6813 // Bucket 2 status after condition change to false.
6814 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 10 * NS_PER_SEC);
6815 // Base for dimension key {}
6816 ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6817 itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6818 EXPECT_FALSE(itBase->second.baseInfos[0].hasBase);
6819 EXPECT_TRUE(itBase->second.hasCurrentState);
6820 ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6821 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6822 itBase->second.currentState.getValues()[0].mValue.int_value);
6823 // Value for key {{}, OFF}
6824 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
6825 it = valueProducer->mCurrentSlicedBucket.begin();
6826 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6827 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6828 EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6829 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6830 EXPECT_TRUE(it->second.intervals[0].hasValue);
6831 EXPECT_EQ(4, it->second.intervals[0].value.long_value);
6832 assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6833 bucket2StartTimeNs + 10 * NS_PER_SEC);
6834 // Value for key {{}, ON}
6835 it++;
6836 EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6837 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6838 EXPECT_EQ(BatterySaverModeStateChanged::ON,
6839 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6840 EXPECT_FALSE(it->second.intervals[0].hasValue);
6841 assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 30 * NS_PER_SEC);
6842 // Value for key {{}, -1}
6843 it++;
6844 assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6845
6846 // Start dump report and check output.
6847 ProtoOutputStream output;
6848 std::set<string> strSet;
6849 valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
6850 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
6851 &strSet, &output);
6852
6853 StatsLogReport report = outputStreamToProto(&output);
6854 EXPECT_TRUE(report.has_value_metrics());
6855 ASSERT_EQ(2, report.value_metrics().data_size());
6856
6857 ValueMetricData data = report.value_metrics().data(0);
6858 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
6859 EXPECT_TRUE(data.slice_by_state(0).has_value());
6860 EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
6861 ASSERT_EQ(1, data.bucket_info_size());
6862 EXPECT_EQ(2, data.bucket_info(0).values(0).value_long());
6863 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6864
6865 data = report.value_metrics().data(1);
6866 EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
6867 EXPECT_TRUE(data.slice_by_state(0).has_value());
6868 EXPECT_EQ(BatterySaverModeStateChanged::OFF, data.slice_by_state(0).value());
6869 ASSERT_EQ(2, data.bucket_info_size());
6870 EXPECT_EQ(6, data.bucket_info(0).values(0).value_long());
6871 EXPECT_EQ(4, data.bucket_info(1).values(0).value_long());
6872 EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6873 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6874 }
6875
6876 /*
6877 * Test bucket splits when condition is unknown.
6878 */
TEST(ValueMetricProducerTest,TestForcedBucketSplitWhenConditionUnknownSkipsBucket)6879 TEST(ValueMetricProducerTest, TestForcedBucketSplitWhenConditionUnknownSkipsBucket) {
6880 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
6881
6882 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
6883
6884 sp<ValueMetricProducer> valueProducer =
6885 ValueMetricProducerTestHelper::createValueProducerWithCondition(
6886 pullerManager, metric,
6887 ConditionState::kUnknown);
6888
6889 // App update event.
6890 int64_t appUpdateTimeNs = bucketStartTimeNs + 1000;
6891 valueProducer->notifyAppUpgrade(appUpdateTimeNs);
6892
6893 // Check dump report.
6894 ProtoOutputStream output;
6895 std::set<string> strSet;
6896 int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000; // 10 seconds
6897 valueProducer->onDumpReport(dumpReportTimeNs, false /* include current buckets */, true,
6898 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
6899
6900 StatsLogReport report = outputStreamToProto(&output);
6901 EXPECT_TRUE(report.has_value_metrics());
6902 ASSERT_EQ(0, report.value_metrics().data_size());
6903 ASSERT_EQ(1, report.value_metrics().skipped_size());
6904
6905 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
6906 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
6907 EXPECT_EQ(NanoToMillis(appUpdateTimeNs),
6908 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
6909 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
6910
6911 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
6912 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
6913 EXPECT_EQ(NanoToMillis(appUpdateTimeNs), dropEvent.drop_time_millis());
6914 }
6915
TEST(ValueMetricProducerTest,TestUploadThreshold)6916 TEST(ValueMetricProducerTest, TestUploadThreshold) {
6917 // Create metric with upload threshold and two value fields.
6918 int64_t thresholdValue = 15;
6919 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
6920 metric.mutable_value_field()->add_child()->set_field(3);
6921 metric.mutable_threshold()->set_gt_int(thresholdValue);
6922 *metric.mutable_dimensions_in_what() = CreateDimensions(tagId, {1 /*uid*/});
6923
6924 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
6925
6926 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
6927 // First bucket pull.
6928 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6929 vector<std::shared_ptr<LogEvent>>* data) {
6930 data->clear();
6931 data->push_back(
6932 CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 1, 1 /*uid*/, 5, 5));
6933 data->push_back(
6934 CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 1, 2 /*uid*/, 5, 5));
6935 return true;
6936 }))
6937 // Dump report.
6938 .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6939 vector<std::shared_ptr<LogEvent>>* data) {
6940 data->clear();
6941 data->push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 10000000000,
6942 1 /*uid*/, 22, 21));
6943 data->push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 10000000000,
6944 2 /*uid*/, 30, 10));
6945 return true;
6946 }));
6947
6948 sp<ValueMetricProducer> valueProducer =
6949 ValueMetricProducerTestHelper::createValueProducerNoConditions(
6950 pullerManager, metric);
6951
6952 // Bucket 2 start.
6953 vector<shared_ptr<LogEvent>> allData;
6954 allData.clear();
6955 allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 1 /*uid*/, 21, 21));
6956 allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 2 /*uid*/, 20, 5));
6957 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
6958
6959 // Check dump report.
6960 ProtoOutputStream output;
6961 std::set<string> strSet;
6962 int64_t dumpReportTimeNs = bucket2StartTimeNs + 10000000000;
6963 valueProducer->onDumpReport(dumpReportTimeNs, true /* include current buckets */, true,
6964 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
6965
6966 StatsLogReport report = outputStreamToProto(&output);
6967 backfillDimensionPath(&report);
6968 backfillStartEndTimestamp(&report);
6969 EXPECT_TRUE(report.has_value_metrics());
6970 StatsLogReport::ValueMetricDataWrapper valueMetrics;
6971 sortMetricDataByDimensionsValue(report.value_metrics(), &valueMetrics);
6972 ASSERT_EQ(1, valueMetrics.data_size());
6973 ASSERT_EQ(1, report.value_metrics().skipped_size());
6974
6975 // Check data keyed to uid 1.
6976 ValueMetricData data = valueMetrics.data(0);
6977 ValidateUidDimension(data.dimensions_in_what(), tagId, 1);
6978 ASSERT_EQ(1, data.bucket_info_size());
6979 // First bucket.
6980 // Values pass threshold.
6981 ValidateValueBucket(data.bucket_info(0), bucketStartTimeNs, bucket2StartTimeNs, {16, 16}, -1);
6982 // Second bucket is dropped because values do not pass threshold.
6983
6984 // Check data keyed to uid 2.
6985 // First bucket and second bucket are dropped because values do not pass threshold.
6986
6987 // Check that second bucket has NO_DATA drop reason.
6988 EXPECT_EQ(bucket2StartTimeNs, report.value_metrics().skipped(0).start_bucket_elapsed_nanos());
6989 EXPECT_EQ(dumpReportTimeNs, report.value_metrics().skipped(0).end_bucket_elapsed_nanos());
6990 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
6991 EXPECT_EQ(BucketDropReason::NO_DATA,
6992 report.value_metrics().skipped(0).drop_event(0).drop_reason());
6993 }
6994
6995 } // namespace statsd
6996 } // namespace os
6997 } // namespace android
6998 #else
6999 GTEST_LOG_(INFO) << "This test does nothing.\n";
7000 #endif
7001