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/matchers/SimpleLogMatchingTracker.h"
16 #include "src/metrics/ValueMetricProducer.h"
17 #include "src/stats_log_util.h"
18 #include "metrics_test_helper.h"
19 #include "tests/statsd_test_util.h"
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include <vector>
26
27 using namespace testing;
28 using android::sp;
29 using android::util::ProtoReader;
30 using std::make_shared;
31 using std::set;
32 using std::shared_ptr;
33 using std::unordered_map;
34 using std::vector;
35
36 #ifdef __ANDROID__
37
38 namespace android {
39 namespace os {
40 namespace statsd {
41
42 const ConfigKey kConfigKey(0, 12345);
43 const int tagId = 1;
44 const int64_t metricId = 123;
45 const int64_t atomMatcherId = 678;
46 const int logEventMatcherIndex = 0;
47 const int64_t bucketStartTimeNs = 10000000000;
48 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
49 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
50 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
51 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
52 const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
53 const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
54 double epsilon = 0.001;
55
assertPastBucketValuesSingleKey(const std::unordered_map<MetricDimensionKey,std::vector<ValueBucket>> & mPastBuckets,const std::initializer_list<int> & expectedValuesList,const std::initializer_list<int64_t> & expectedDurationNsList)56 static void assertPastBucketValuesSingleKey(
57 const std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>>& mPastBuckets,
58 const std::initializer_list<int>& expectedValuesList,
59 const std::initializer_list<int64_t>& expectedDurationNsList) {
60 std::vector<int> expectedValues(expectedValuesList);
61 std::vector<int64_t> expectedDurationNs(expectedDurationNsList);
62 ASSERT_EQ(expectedValues.size(), expectedDurationNs.size());
63 if (expectedValues.size() == 0) {
64 ASSERT_EQ(0, mPastBuckets.size());
65 return;
66 }
67
68 ASSERT_EQ(1, mPastBuckets.size());
69 ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
70
71 auto buckets = mPastBuckets.begin()->second;
72 for (int i = 0; i < expectedValues.size(); i++) {
73 EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
74 << "Values differ at index " << i;
75 EXPECT_EQ(expectedDurationNs[i], buckets[i].mConditionTrueNs)
76 << "Condition duration value differ at index " << i;
77 }
78 }
79
80 class ValueMetricProducerTestHelper {
81
82 public:
createEvent(int64_t eventTimeNs,int64_t value)83 static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
84 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
85 event->write(tagId);
86 event->write(value);
87 event->write(value);
88 event->init();
89 return event;
90 }
91
createValueProducerNoConditions(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric)92 static sp<ValueMetricProducer> createValueProducerNoConditions(
93 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
94 UidMap uidMap;
95 SimpleAtomMatcher atomMatcher;
96 atomMatcher.set_atom_id(tagId);
97 sp<EventMatcherWizard> eventMatcherWizard =
98 new EventMatcherWizard({new SimpleLogMatchingTracker(
99 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
100 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
101 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
102 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
103
104 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
105 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
106 logEventMatcherIndex, eventMatcherWizard, tagId,
107 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
108 valueProducer->prepareFirstBucket();
109 return valueProducer;
110 }
111
createValueProducerWithCondition(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric)112 static sp<ValueMetricProducer> createValueProducerWithCondition(
113 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
114 UidMap uidMap;
115 SimpleAtomMatcher atomMatcher;
116 atomMatcher.set_atom_id(tagId);
117 sp<EventMatcherWizard> eventMatcherWizard =
118 new EventMatcherWizard({new SimpleLogMatchingTracker(
119 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
120 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
121 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
122 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
123
124 sp<ValueMetricProducer> valueProducer =
125 new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
126 eventMatcherWizard, tagId, bucketStartTimeNs,
127 bucketStartTimeNs, pullerManager);
128 valueProducer->prepareFirstBucket();
129 valueProducer->mCondition = ConditionState::kFalse;
130 return valueProducer;
131 }
132
createMetric()133 static ValueMetric createMetric() {
134 ValueMetric metric;
135 metric.set_id(metricId);
136 metric.set_bucket(ONE_MINUTE);
137 metric.mutable_value_field()->set_field(tagId);
138 metric.mutable_value_field()->add_child()->set_field(2);
139 metric.set_max_pull_delay_sec(INT_MAX);
140 return metric;
141 }
142
createMetricWithCondition()143 static ValueMetric createMetricWithCondition() {
144 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
145 metric.set_condition(StringToId("SCREEN_ON"));
146 return metric;
147 }
148 };
149
150
151 /*
152 * Tests that the first bucket works correctly
153 */
TEST(ValueMetricProducerTest,TestCalcPreviousBucketEndTime)154 TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
155 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
156
157 int64_t startTimeBase = 11;
158 UidMap uidMap;
159 SimpleAtomMatcher atomMatcher;
160 atomMatcher.set_atom_id(tagId);
161 sp<EventMatcherWizard> eventMatcherWizard =
162 new EventMatcherWizard({new SimpleLogMatchingTracker(
163 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
164 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
165 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
166
167 // statsd started long ago.
168 // The metric starts in the middle of the bucket
169 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
170 logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
171 22, pullerManager);
172 valueProducer.prepareFirstBucket();
173
174 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
175 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
176 EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
177 valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
178 EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
179 valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
180 }
181
182 /*
183 * Tests that the first bucket works correctly
184 */
TEST(ValueMetricProducerTest,TestFirstBucket)185 TEST(ValueMetricProducerTest, TestFirstBucket) {
186 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
187
188 UidMap uidMap;
189 SimpleAtomMatcher atomMatcher;
190 atomMatcher.set_atom_id(tagId);
191 sp<EventMatcherWizard> eventMatcherWizard =
192 new EventMatcherWizard({new SimpleLogMatchingTracker(
193 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
194 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
195 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
196
197 // statsd started long ago.
198 // The metric starts in the middle of the bucket
199 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
200 logEventMatcherIndex, eventMatcherWizard, -1, 5,
201 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
202 valueProducer.prepareFirstBucket();
203
204 EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
205 EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
206 EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
207 }
208
209 /*
210 * Tests pulled atoms with no conditions
211 */
TEST(ValueMetricProducerTest,TestPulledEventsNoCondition)212 TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
213 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
214 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
215 EXPECT_CALL(*pullerManager, Pull(tagId, _))
216 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
217 data->clear();
218 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
219 event->write(tagId);
220 event->write(3);
221 event->init();
222 data->push_back(event);
223 return true;
224 }));
225
226 sp<ValueMetricProducer> valueProducer =
227 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
228
229 vector<shared_ptr<LogEvent>> allData;
230 allData.clear();
231 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
232 event->write(tagId);
233 event->write(11);
234 event->init();
235 allData.push_back(event);
236
237 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
238 // has one slice
239 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
240 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
241
242 EXPECT_EQ(true, curInterval.hasBase);
243 EXPECT_EQ(11, curInterval.base.long_value);
244 EXPECT_EQ(false, curInterval.hasValue);
245 EXPECT_EQ(8, curInterval.value.long_value);
246 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
247 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
248 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
249
250 allData.clear();
251 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
252 event->write(tagId);
253 event->write(23);
254 event->init();
255 allData.push_back(event);
256 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
257 // has one slice
258 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
259 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
260
261 EXPECT_EQ(true, curInterval.hasBase);
262 EXPECT_EQ(23, curInterval.base.long_value);
263 EXPECT_EQ(false, curInterval.hasValue);
264 EXPECT_EQ(12, curInterval.value.long_value);
265 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
266 EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
267 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
268 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
269 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
270 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
271
272 allData.clear();
273 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
274 event->write(tagId);
275 event->write(36);
276 event->init();
277 allData.push_back(event);
278 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
279 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
280 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
281
282 EXPECT_EQ(true, curInterval.hasBase);
283 EXPECT_EQ(36, curInterval.base.long_value);
284 EXPECT_EQ(false, curInterval.hasValue);
285 EXPECT_EQ(13, curInterval.value.long_value);
286 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
287 EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
288 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
289 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
290 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
291 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
292 EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
293 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
294 }
295
TEST(ValueMetricProducerTest,TestPartialBucketCreated)296 TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
297 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
298 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
299 EXPECT_CALL(*pullerManager, Pull(tagId, _))
300 // Initialize bucket.
301 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
302 data->clear();
303 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
304 event->write(tagId);
305 event->write(1);
306 event->init();
307 data->push_back(event);
308 return true;
309 }))
310 // Partial bucket.
311 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
312 data->clear();
313 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
314 event->write(tagId);
315 event->write(5);
316 event->init();
317 data->push_back(event);
318 return true;
319 }));
320
321 sp<ValueMetricProducer> valueProducer =
322 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
323
324 // First bucket ends.
325 vector<shared_ptr<LogEvent>> allData;
326 allData.clear();
327 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
328 event->write(tagId);
329 event->write(2);
330 event->init();
331 allData.push_back(event);
332 valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
333
334 // Partial buckets created in 2nd bucket.
335 valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
336
337 // One full bucket and one partial bucket.
338 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
339 vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
340 EXPECT_EQ(2UL, buckets.size());
341 // Full bucket (2 - 1)
342 EXPECT_EQ(1, buckets[0].values[0].long_value);
343 EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
344 // Full bucket (5 - 3)
345 EXPECT_EQ(3, buckets[1].values[0].long_value);
346 // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
347 EXPECT_EQ(2, buckets[1].mConditionTrueNs);
348 }
349
350 /*
351 * Tests pulled atoms with filtering
352 */
TEST(ValueMetricProducerTest,TestPulledEventsWithFiltering)353 TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
354 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
355
356 UidMap uidMap;
357 SimpleAtomMatcher atomMatcher;
358 atomMatcher.set_atom_id(tagId);
359 auto keyValue = atomMatcher.add_field_value_matcher();
360 keyValue->set_field(1);
361 keyValue->set_eq_int(3);
362 sp<EventMatcherWizard> eventMatcherWizard =
363 new EventMatcherWizard({new SimpleLogMatchingTracker(
364 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
365 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
366 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
367 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
368 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
369 EXPECT_CALL(*pullerManager, Pull(tagId, _))
370 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
371 data->clear();
372 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
373 event->write(3);
374 event->write(3);
375 event->init();
376 data->push_back(event);
377 return true;
378 }));
379
380 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
381 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
382 logEventMatcherIndex, eventMatcherWizard, tagId,
383 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
384 valueProducer->prepareFirstBucket();
385
386 vector<shared_ptr<LogEvent>> allData;
387 allData.clear();
388 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
389 event->write(3);
390 event->write(11);
391 event->init();
392 allData.push_back(event);
393
394 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
395 // has one slice
396 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
397 ValueMetricProducer::Interval curInterval =
398 valueProducer->mCurrentSlicedBucket.begin()->second[0];
399
400 EXPECT_EQ(true, curInterval.hasBase);
401 EXPECT_EQ(11, curInterval.base.long_value);
402 EXPECT_EQ(false, curInterval.hasValue);
403 EXPECT_EQ(8, curInterval.value.long_value);
404 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
405 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
406 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
407
408 allData.clear();
409 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
410 event->write(4);
411 event->write(23);
412 event->init();
413 allData.push_back(event);
414 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
415 // No new data seen, so data has been cleared.
416 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
417
418 EXPECT_EQ(true, curInterval.hasBase);
419 EXPECT_EQ(11, curInterval.base.long_value);
420 EXPECT_EQ(false, curInterval.hasValue);
421 EXPECT_EQ(8, curInterval.value.long_value);
422 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
423 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
424 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
425
426 allData.clear();
427 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
428 event->write(3);
429 event->write(36);
430 event->init();
431 allData.push_back(event);
432 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
433 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
434 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
435
436 // the base was reset
437 EXPECT_EQ(true, curInterval.hasBase);
438 EXPECT_EQ(36, curInterval.base.long_value);
439 EXPECT_EQ(false, curInterval.hasValue);
440 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
441 EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
442 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
443 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
444 }
445
446 /*
447 * Tests pulled atoms with no conditions and take absolute value after reset
448 */
TEST(ValueMetricProducerTest,TestPulledEventsTakeAbsoluteValueOnReset)449 TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
450 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
451 metric.set_use_absolute_value_on_reset(true);
452
453 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
454 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
455 sp<ValueMetricProducer> valueProducer =
456 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
457
458 vector<shared_ptr<LogEvent>> allData;
459 allData.clear();
460 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
461 event->write(tagId);
462 event->write(11);
463 event->init();
464 allData.push_back(event);
465
466 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
467 // has one slice
468 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
469 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
470
471 EXPECT_EQ(true, curInterval.hasBase);
472 EXPECT_EQ(11, curInterval.base.long_value);
473 EXPECT_EQ(false, curInterval.hasValue);
474 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
475
476 allData.clear();
477 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
478 event->write(tagId);
479 event->write(10);
480 event->init();
481 allData.push_back(event);
482 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
483 // has one slice
484 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
485 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
486 EXPECT_EQ(true, curInterval.hasBase);
487 EXPECT_EQ(10, curInterval.base.long_value);
488 EXPECT_EQ(false, curInterval.hasValue);
489 EXPECT_EQ(10, curInterval.value.long_value);
490 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
491 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
492 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
493
494 allData.clear();
495 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
496 event->write(tagId);
497 event->write(36);
498 event->init();
499 allData.push_back(event);
500 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
501 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
502 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
503 EXPECT_EQ(true, curInterval.hasBase);
504 EXPECT_EQ(36, curInterval.base.long_value);
505 EXPECT_EQ(false, curInterval.hasValue);
506 EXPECT_EQ(26, curInterval.value.long_value);
507 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
508 EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
509 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
510 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
511 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
512 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
513 }
514
515 /*
516 * Tests pulled atoms with no conditions and take zero value after reset
517 */
TEST(ValueMetricProducerTest,TestPulledEventsTakeZeroOnReset)518 TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
519 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
520 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
521 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
522 sp<ValueMetricProducer> valueProducer =
523 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
524
525 vector<shared_ptr<LogEvent>> allData;
526 allData.clear();
527 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
528 event->write(tagId);
529 event->write(11);
530 event->init();
531 allData.push_back(event);
532
533 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
534 // has one slice
535 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
536 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
537
538 EXPECT_EQ(true, curInterval.hasBase);
539 EXPECT_EQ(11, curInterval.base.long_value);
540 EXPECT_EQ(false, curInterval.hasValue);
541 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
542
543 allData.clear();
544 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
545 event->write(tagId);
546 event->write(10);
547 event->init();
548 allData.push_back(event);
549 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
550 // has one slice
551 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
552 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
553 EXPECT_EQ(true, curInterval.hasBase);
554 EXPECT_EQ(10, curInterval.base.long_value);
555 EXPECT_EQ(false, curInterval.hasValue);
556 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
557
558 allData.clear();
559 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
560 event->write(tagId);
561 event->write(36);
562 event->init();
563 allData.push_back(event);
564 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
565 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
566 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
567 EXPECT_EQ(true, curInterval.hasBase);
568 EXPECT_EQ(36, curInterval.base.long_value);
569 EXPECT_EQ(false, curInterval.hasValue);
570 EXPECT_EQ(26, curInterval.value.long_value);
571 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
572 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
573 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
574 }
575
576 /*
577 * Test pulled event with non sliced condition.
578 */
TEST(ValueMetricProducerTest,TestEventsWithNonSlicedCondition)579 TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
580 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
581
582 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
583
584 EXPECT_CALL(*pullerManager, Pull(tagId, _))
585 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
586 data->clear();
587 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
588 event->write(tagId);
589 event->write(100);
590 event->init();
591 data->push_back(event);
592 return true;
593 }))
594 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
595 data->clear();
596 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
597 event->write(tagId);
598 event->write(130);
599 event->init();
600 data->push_back(event);
601 return true;
602 }))
603 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
604 data->clear();
605 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
606 event->write(tagId);
607 event->write(180);
608 event->init();
609 data->push_back(event);
610 return true;
611 }));
612
613 sp<ValueMetricProducer> valueProducer =
614 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
615
616 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
617
618 // has one slice
619 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
620 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
621 // startUpdated:false sum:0 start:100
622 EXPECT_EQ(true, curInterval.hasBase);
623 EXPECT_EQ(100, curInterval.base.long_value);
624 EXPECT_EQ(false, curInterval.hasValue);
625 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
626
627 vector<shared_ptr<LogEvent>> allData;
628 allData.clear();
629 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
630 event->write(1);
631 event->write(110);
632 event->init();
633 allData.push_back(event);
634 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
635 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
636
637 // has one slice
638 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
639 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
640 EXPECT_EQ(true, curInterval.hasBase);
641 EXPECT_EQ(110, curInterval.base.long_value);
642 EXPECT_EQ(false, curInterval.hasValue);
643 EXPECT_EQ(10, curInterval.value.long_value);
644
645 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
646 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
647
648 // has one slice
649 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
650 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
651 EXPECT_EQ(true, curInterval.hasValue);
652 EXPECT_EQ(20, curInterval.value.long_value);
653 EXPECT_EQ(false, curInterval.hasBase);
654
655 valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
656 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
657 }
658
TEST(ValueMetricProducerTest,TestPushedEventsWithUpgrade)659 TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
660 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
661
662 UidMap uidMap;
663 SimpleAtomMatcher atomMatcher;
664 atomMatcher.set_atom_id(tagId);
665 sp<EventMatcherWizard> eventMatcherWizard =
666 new EventMatcherWizard({new SimpleLogMatchingTracker(
667 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
668 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
669 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
670 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
671 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
672 pullerManager);
673 valueProducer.prepareFirstBucket();
674
675 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
676 event1->write(1);
677 event1->write(10);
678 event1->init();
679 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
680 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
681
682 valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
683 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
684 EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
685
686 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
687 event2->write(1);
688 event2->write(10);
689 event2->init();
690 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
691 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
692 EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
693
694 // Next value should create a new bucket.
695 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
696 event3->write(1);
697 event3->write(10);
698 event3->init();
699 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
700 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
701 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
702 }
703
TEST(ValueMetricProducerTest,TestPulledValueWithUpgrade)704 TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
705 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
706
707 UidMap uidMap;
708 SimpleAtomMatcher atomMatcher;
709 atomMatcher.set_atom_id(tagId);
710 sp<EventMatcherWizard> eventMatcherWizard =
711 new EventMatcherWizard({new SimpleLogMatchingTracker(
712 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
713 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
714 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
715 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
716 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
717 EXPECT_CALL(*pullerManager, Pull(tagId, _))
718 .WillOnce(Return(true))
719 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
720 data->clear();
721 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
722 event->write(tagId);
723 event->write(120);
724 event->init();
725 data->push_back(event);
726 return true;
727 }));
728 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
729 eventMatcherWizard, tagId, bucketStartTimeNs,
730 bucketStartTimeNs, pullerManager);
731 valueProducer.prepareFirstBucket();
732
733 vector<shared_ptr<LogEvent>> allData;
734 allData.clear();
735 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
736 event->write(tagId);
737 event->write(100);
738 event->init();
739 allData.push_back(event);
740
741 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
742 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
743
744 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
745 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
746 EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
747 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
748
749 allData.clear();
750 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
751 event->write(tagId);
752 event->write(150);
753 event->init();
754 allData.push_back(event);
755 valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
756 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
757 EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
758 EXPECT_EQ(20L,
759 valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
760 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
761 {150, bucketSizeNs - 150});
762 }
763
TEST(ValueMetricProducerTest,TestPulledWithAppUpgradeDisabled)764 TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
765 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
766 metric.set_split_bucket_for_app_upgrade(false);
767
768 UidMap uidMap;
769 SimpleAtomMatcher atomMatcher;
770 atomMatcher.set_atom_id(tagId);
771 sp<EventMatcherWizard> eventMatcherWizard =
772 new EventMatcherWizard({new SimpleLogMatchingTracker(
773 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
774 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
775 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
776 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
777 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
778 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
779 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
780 eventMatcherWizard, tagId, bucketStartTimeNs,
781 bucketStartTimeNs, pullerManager);
782 valueProducer.prepareFirstBucket();
783
784 vector<shared_ptr<LogEvent>> allData;
785 allData.clear();
786 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
787 event->write(tagId);
788 event->write(100);
789 event->init();
790 allData.push_back(event);
791
792 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
793 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
794
795 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
796 EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
797 EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
798 }
799
TEST(ValueMetricProducerTest,TestPulledValueWithUpgradeWhileConditionFalse)800 TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
801 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
802
803 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
804 EXPECT_CALL(*pullerManager, Pull(tagId, _))
805 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
806 data->clear();
807 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
808 event->write(tagId);
809 event->write(100);
810 event->init();
811 data->push_back(event);
812 return true;
813 }))
814 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
815 data->clear();
816 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
817 event->write(tagId);
818 event->write(120);
819 event->init();
820 data->push_back(event);
821 return true;
822 }));
823 sp<ValueMetricProducer> valueProducer =
824 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
825
826 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
827
828 valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
829 EXPECT_FALSE(valueProducer->mCondition);
830
831 valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
832 // Expect one full buckets already done and starting a partial bucket.
833 EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
834 EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
835 EXPECT_EQ(bucketStartTimeNs,
836 valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
837 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
838 {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
839 EXPECT_FALSE(valueProducer->mCondition);
840 }
841
TEST(ValueMetricProducerTest,TestPushedEventsWithoutCondition)842 TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
843 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
844
845 UidMap uidMap;
846 SimpleAtomMatcher atomMatcher;
847 atomMatcher.set_atom_id(tagId);
848 sp<EventMatcherWizard> eventMatcherWizard =
849 new EventMatcherWizard({new SimpleLogMatchingTracker(
850 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
851 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
852 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
853
854 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
855 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
856 pullerManager);
857 valueProducer.prepareFirstBucket();
858
859 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
860 event1->write(1);
861 event1->write(10);
862 event1->init();
863 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
864 event2->write(1);
865 event2->write(20);
866 event2->init();
867 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
868 // has one slice
869 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
870 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
871 EXPECT_EQ(10, curInterval.value.long_value);
872 EXPECT_EQ(true, curInterval.hasValue);
873
874 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
875
876 // has one slice
877 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
878 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
879 EXPECT_EQ(30, curInterval.value.long_value);
880
881 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
882 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
883 }
884
TEST(ValueMetricProducerTest,TestPushedEventsWithCondition)885 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
886 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
887
888 UidMap uidMap;
889 SimpleAtomMatcher atomMatcher;
890 atomMatcher.set_atom_id(tagId);
891 sp<EventMatcherWizard> eventMatcherWizard =
892 new EventMatcherWizard({new SimpleLogMatchingTracker(
893 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
894 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
895 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
896
897 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
898 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
899 pullerManager);
900 valueProducer.prepareFirstBucket();
901 valueProducer.mCondition = ConditionState::kFalse;
902
903 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
904 event1->write(1);
905 event1->write(10);
906 event1->init();
907 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
908 // has 1 slice
909 EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
910
911 valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
912 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
913 event2->write(1);
914 event2->write(20);
915 event2->init();
916 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
917
918 // has one slice
919 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
920 ValueMetricProducer::Interval curInterval =
921 valueProducer.mCurrentSlicedBucket.begin()->second[0];
922 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
923 EXPECT_EQ(20, curInterval.value.long_value);
924
925 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
926 event3->write(1);
927 event3->write(30);
928 event3->init();
929 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
930
931 // has one slice
932 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
933 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
934 EXPECT_EQ(50, curInterval.value.long_value);
935
936 valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
937 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
938 event4->write(1);
939 event4->write(40);
940 event4->init();
941 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
942
943 // has one slice
944 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
945 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
946 EXPECT_EQ(50, curInterval.value.long_value);
947
948 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
949 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
950 }
951
TEST(ValueMetricProducerTest,TestAnomalyDetection)952 TEST(ValueMetricProducerTest, TestAnomalyDetection) {
953 sp<AlarmMonitor> alarmMonitor;
954 Alert alert;
955 alert.set_id(101);
956 alert.set_metric_id(metricId);
957 alert.set_trigger_if_sum_gt(130);
958 alert.set_num_buckets(2);
959 const int32_t refPeriodSec = 3;
960 alert.set_refractory_period_secs(refPeriodSec);
961
962 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
963
964 UidMap uidMap;
965 SimpleAtomMatcher atomMatcher;
966 atomMatcher.set_atom_id(tagId);
967 sp<EventMatcherWizard> eventMatcherWizard =
968 new EventMatcherWizard({new SimpleLogMatchingTracker(
969 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
970 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
971 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
972 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
973 logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
974 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
975 valueProducer.prepareFirstBucket();
976
977 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
978
979
980 shared_ptr<LogEvent> event1
981 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
982 event1->write(161);
983 event1->write(10); // value of interest
984 event1->init();
985 shared_ptr<LogEvent> event2
986 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
987 event2->write(162);
988 event2->write(20); // value of interest
989 event2->init();
990 shared_ptr<LogEvent> event3
991 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
992 event3->write(163);
993 event3->write(130); // value of interest
994 event3->init();
995 shared_ptr<LogEvent> event4
996 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
997 event4->write(35);
998 event4->write(1); // value of interest
999 event4->init();
1000 shared_ptr<LogEvent> event5
1001 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
1002 event5->write(45);
1003 event5->write(150); // value of interest
1004 event5->init();
1005 shared_ptr<LogEvent> event6
1006 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
1007 event6->write(25);
1008 event6->write(160); // value of interest
1009 event6->init();
1010
1011 // Two events in bucket #0.
1012 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1013 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1014 // Value sum == 30 <= 130.
1015 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1016
1017 // One event in bucket #2. No alarm as bucket #0 is trashed out.
1018 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
1019 // Value sum == 130 <= 130.
1020 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1021
1022 // Three events in bucket #3.
1023 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
1024 // Anomaly at event 4 since Value sum == 131 > 130!
1025 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1026 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1027 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
1028 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
1029 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1030 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1031
1032 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
1033 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
1034 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1035 std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1036 }
1037
1038 // Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest,TestBucketBoundaryNoCondition)1039 TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
1040 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1041 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1042 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
1043 sp<ValueMetricProducer> valueProducer =
1044 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1045
1046 vector<shared_ptr<LogEvent>> allData;
1047 // pull 1
1048 allData.clear();
1049 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1050 event->write(tagId);
1051 event->write(11);
1052 event->init();
1053 allData.push_back(event);
1054
1055 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1056 // has one slice
1057 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1058 ValueMetricProducer::Interval curInterval =
1059 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1060
1061 // startUpdated:true sum:0 start:11
1062 EXPECT_EQ(true, curInterval.hasBase);
1063 EXPECT_EQ(11, curInterval.base.long_value);
1064 EXPECT_EQ(false, curInterval.hasValue);
1065 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1066
1067 // pull 2 at correct time
1068 allData.clear();
1069 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
1070 event->write(tagId);
1071 event->write(23);
1072 event->init();
1073 allData.push_back(event);
1074 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1075 // has one slice
1076 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1077 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1078 // tartUpdated:false sum:12
1079 EXPECT_EQ(true, curInterval.hasBase);
1080 EXPECT_EQ(23, curInterval.base.long_value);
1081 EXPECT_EQ(false, curInterval.hasValue);
1082 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
1083
1084 // pull 3 come late.
1085 // The previous bucket gets closed with error. (Has start value 23, no ending)
1086 // Another bucket gets closed with error. (No start, but ending with 36)
1087 // The new bucket is back to normal.
1088 allData.clear();
1089 event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
1090 event->write(tagId);
1091 event->write(36);
1092 event->init();
1093 allData.push_back(event);
1094 valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
1095 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1096 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1097 // startUpdated:false sum:12
1098 EXPECT_EQ(true, curInterval.hasBase);
1099 EXPECT_EQ(36, curInterval.base.long_value);
1100 EXPECT_EQ(false, curInterval.hasValue);
1101 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
1102 }
1103
1104 /*
1105 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
1106 * was delivered late.
1107 */
TEST(ValueMetricProducerTest,TestBucketBoundaryWithCondition)1108 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
1109 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1110
1111 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1112 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1113 // condition becomes true
1114 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1115 data->clear();
1116 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
1117 event->write(tagId);
1118 event->write(100);
1119 event->init();
1120 data->push_back(event);
1121 return true;
1122 }))
1123 // condition becomes false
1124 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1125 data->clear();
1126 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1127 event->write(tagId);
1128 event->write(120);
1129 event->init();
1130 data->push_back(event);
1131 return true;
1132 }));
1133 sp<ValueMetricProducer> valueProducer =
1134 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1135
1136 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1137
1138 // has one slice
1139 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1140 ValueMetricProducer::Interval curInterval =
1141 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1142 EXPECT_EQ(true, curInterval.hasBase);
1143 EXPECT_EQ(100, curInterval.base.long_value);
1144 EXPECT_EQ(false, curInterval.hasValue);
1145 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1146
1147 // pull on bucket boundary come late, condition change happens before it
1148 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1149 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1150 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
1151 EXPECT_EQ(false, curInterval.hasBase);
1152
1153 // Now the alarm is delivered.
1154 // since the condition turned to off before this pull finish, it has no effect
1155 vector<shared_ptr<LogEvent>> allData;
1156 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
1157 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1158
1159 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
1160 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1161 EXPECT_EQ(false, curInterval.hasBase);
1162 EXPECT_EQ(false, curInterval.hasValue);
1163 }
1164
1165 /*
1166 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
1167 * change to false, and then true again. This is due to alarm delivered late.
1168 */
TEST(ValueMetricProducerTest,TestBucketBoundaryWithCondition2)1169 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
1170 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1171
1172 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1173 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1174 // condition becomes true
1175 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1176 data->clear();
1177 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
1178 event->write(tagId);
1179 event->write(100);
1180 event->init();
1181 data->push_back(event);
1182 return true;
1183 }))
1184 // condition becomes false
1185 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1186 data->clear();
1187 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1188 event->write(tagId);
1189 event->write(120);
1190 event->init();
1191 data->push_back(event);
1192 return true;
1193 }))
1194 // condition becomes true again
1195 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1196 data->clear();
1197 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
1198 event->write(tagId);
1199 event->write(130);
1200 event->init();
1201 data->push_back(event);
1202 return true;
1203 }));
1204
1205 sp<ValueMetricProducer> valueProducer =
1206 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1207
1208 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1209
1210 // has one slice
1211 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1212 ValueMetricProducer::Interval curInterval =
1213 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1214 // startUpdated:false sum:0 start:100
1215 EXPECT_EQ(true, curInterval.hasBase);
1216 EXPECT_EQ(100, curInterval.base.long_value);
1217 EXPECT_EQ(false, curInterval.hasValue);
1218 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1219
1220 // pull on bucket boundary come late, condition change happens before it
1221 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1222 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
1223 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1224 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1225 EXPECT_EQ(false, curInterval.hasBase);
1226 EXPECT_EQ(false, curInterval.hasValue);
1227
1228 // condition changed to true again, before the pull alarm is delivered
1229 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
1230 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
1231 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1232 EXPECT_EQ(true, curInterval.hasBase);
1233 EXPECT_EQ(130, curInterval.base.long_value);
1234 EXPECT_EQ(false, curInterval.hasValue);
1235
1236 // Now the alarm is delivered, but it is considered late, the data will be used
1237 // for the new bucket since it was just pulled.
1238 vector<shared_ptr<LogEvent>> allData;
1239 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
1240 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
1241
1242 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1243 EXPECT_EQ(true, curInterval.hasBase);
1244 EXPECT_EQ(140, curInterval.base.long_value);
1245 EXPECT_EQ(true, curInterval.hasValue);
1246 EXPECT_EQ(10, curInterval.value.long_value);
1247 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
1248
1249 allData.clear();
1250 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
1251 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1252 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
1253 {bucketSizeNs - 8, bucketSizeNs - 24});
1254 }
1255
TEST(ValueMetricProducerTest,TestPushedAggregateMin)1256 TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
1257 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1258 metric.set_aggregation_type(ValueMetric::MIN);
1259
1260 UidMap uidMap;
1261 SimpleAtomMatcher atomMatcher;
1262 atomMatcher.set_atom_id(tagId);
1263 sp<EventMatcherWizard> eventMatcherWizard =
1264 new EventMatcherWizard({new SimpleLogMatchingTracker(
1265 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1266 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1267 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1268
1269 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1270 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1271 pullerManager);
1272 valueProducer.prepareFirstBucket();
1273
1274 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1275 event1->write(1);
1276 event1->write(10);
1277 event1->init();
1278 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1279 event2->write(1);
1280 event2->write(20);
1281 event2->init();
1282 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1283 // has one slice
1284 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1285 ValueMetricProducer::Interval curInterval =
1286 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1287 EXPECT_EQ(10, curInterval.value.long_value);
1288 EXPECT_EQ(true, curInterval.hasValue);
1289
1290 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1291
1292 // has one slice
1293 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1294 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1295 EXPECT_EQ(10, curInterval.value.long_value);
1296
1297 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1298 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
1299 }
1300
TEST(ValueMetricProducerTest,TestPushedAggregateMax)1301 TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
1302 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1303 metric.set_aggregation_type(ValueMetric::MAX);
1304
1305 UidMap uidMap;
1306 SimpleAtomMatcher atomMatcher;
1307 atomMatcher.set_atom_id(tagId);
1308 sp<EventMatcherWizard> eventMatcherWizard =
1309 new EventMatcherWizard({new SimpleLogMatchingTracker(
1310 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1311 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1312 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1313
1314 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1315 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1316 pullerManager);
1317 valueProducer.prepareFirstBucket();
1318
1319 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1320 event1->write(1);
1321 event1->write(10);
1322 event1->init();
1323 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1324 event2->write(1);
1325 event2->write(20);
1326 event2->init();
1327 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1328 // has one slice
1329 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1330 ValueMetricProducer::Interval curInterval =
1331 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1332 EXPECT_EQ(10, curInterval.value.long_value);
1333 EXPECT_EQ(true, curInterval.hasValue);
1334
1335 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1336
1337 // has one slice
1338 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1339 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1340 EXPECT_EQ(20, curInterval.value.long_value);
1341
1342 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1343 /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
1344 /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
1345 /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
1346 }
1347
TEST(ValueMetricProducerTest,TestPushedAggregateAvg)1348 TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
1349 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1350 metric.set_aggregation_type(ValueMetric::AVG);
1351
1352 UidMap uidMap;
1353 SimpleAtomMatcher atomMatcher;
1354 atomMatcher.set_atom_id(tagId);
1355 sp<EventMatcherWizard> eventMatcherWizard =
1356 new EventMatcherWizard({new SimpleLogMatchingTracker(
1357 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1358 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1359 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1360
1361 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1362 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1363 pullerManager);
1364 valueProducer.prepareFirstBucket();
1365
1366 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1367 event1->write(1);
1368 event1->write(10);
1369 event1->init();
1370 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1371 event2->write(1);
1372 event2->write(15);
1373 event2->init();
1374 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1375 // has one slice
1376 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1377 ValueMetricProducer::Interval curInterval;
1378 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1379 EXPECT_EQ(10, curInterval.value.long_value);
1380 EXPECT_EQ(true, curInterval.hasValue);
1381 EXPECT_EQ(1, curInterval.sampleSize);
1382
1383 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1384
1385 // has one slice
1386 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1387 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1388 EXPECT_EQ(25, curInterval.value.long_value);
1389 EXPECT_EQ(2, curInterval.sampleSize);
1390
1391 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1392 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1393 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1394
1395 EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
1396 12.5) < epsilon);
1397 }
1398
TEST(ValueMetricProducerTest,TestPushedAggregateSum)1399 TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
1400 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1401 metric.set_aggregation_type(ValueMetric::SUM);
1402
1403 UidMap uidMap;
1404 SimpleAtomMatcher atomMatcher;
1405 atomMatcher.set_atom_id(tagId);
1406 sp<EventMatcherWizard> eventMatcherWizard =
1407 new EventMatcherWizard({new SimpleLogMatchingTracker(
1408 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1409 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1410 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1411
1412 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1413 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1414 pullerManager);
1415 valueProducer.prepareFirstBucket();
1416
1417 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1418 event1->write(1);
1419 event1->write(10);
1420 event1->init();
1421 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1422 event2->write(1);
1423 event2->write(15);
1424 event2->init();
1425 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1426 // has one slice
1427 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1428 ValueMetricProducer::Interval curInterval =
1429 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1430 EXPECT_EQ(10, curInterval.value.long_value);
1431 EXPECT_EQ(true, curInterval.hasValue);
1432
1433 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1434
1435 // has one slice
1436 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1437 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1438 EXPECT_EQ(25, curInterval.value.long_value);
1439
1440 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1441 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
1442 }
1443
TEST(ValueMetricProducerTest,TestSkipZeroDiffOutput)1444 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
1445 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1446 metric.set_aggregation_type(ValueMetric::MIN);
1447 metric.set_use_diff(true);
1448
1449 UidMap uidMap;
1450 SimpleAtomMatcher atomMatcher;
1451 atomMatcher.set_atom_id(tagId);
1452 sp<EventMatcherWizard> eventMatcherWizard =
1453 new EventMatcherWizard({new SimpleLogMatchingTracker(
1454 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1455 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1456 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1457
1458 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1459 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1460 pullerManager);
1461 valueProducer.prepareFirstBucket();
1462
1463 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1464 event1->write(1);
1465 event1->write(10);
1466 event1->init();
1467 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
1468 event2->write(1);
1469 event2->write(15);
1470 event2->init();
1471 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1472 // has one slice
1473 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1474 ValueMetricProducer::Interval curInterval =
1475 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1476 EXPECT_EQ(true, curInterval.hasBase);
1477 EXPECT_EQ(10, curInterval.base.long_value);
1478 EXPECT_EQ(false, curInterval.hasValue);
1479
1480 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1481
1482 // has one slice
1483 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1484 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1485 EXPECT_EQ(true, curInterval.hasValue);
1486 EXPECT_EQ(5, curInterval.value.long_value);
1487
1488 // no change in data.
1489 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
1490 event3->write(1);
1491 event3->write(15);
1492 event3->init();
1493 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
1494 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1495 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1496 EXPECT_EQ(true, curInterval.hasBase);
1497 EXPECT_EQ(15, curInterval.base.long_value);
1498 EXPECT_EQ(true, curInterval.hasValue);
1499
1500 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
1501 event4->write(1);
1502 event4->write(15);
1503 event4->init();
1504 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
1505 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1506 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1507 EXPECT_EQ(true, curInterval.hasBase);
1508 EXPECT_EQ(15, curInterval.base.long_value);
1509 EXPECT_EQ(true, curInterval.hasValue);
1510
1511 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1512 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1513 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1514 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
1515 }
1516
TEST(ValueMetricProducerTest,TestSkipZeroDiffOutputMultiValue)1517 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
1518 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1519 metric.mutable_value_field()->add_child()->set_field(3);
1520 metric.set_aggregation_type(ValueMetric::MIN);
1521 metric.set_use_diff(true);
1522
1523 UidMap uidMap;
1524 SimpleAtomMatcher atomMatcher;
1525 atomMatcher.set_atom_id(tagId);
1526 sp<EventMatcherWizard> eventMatcherWizard =
1527 new EventMatcherWizard({new SimpleLogMatchingTracker(
1528 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1529 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1530 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1531
1532 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1533 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1534 pullerManager);
1535 valueProducer.prepareFirstBucket();
1536
1537 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1538 event1->write(1);
1539 event1->write(10);
1540 event1->write(20);
1541 event1->init();
1542 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
1543 event2->write(1);
1544 event2->write(15);
1545 event2->write(22);
1546 event2->init();
1547 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1548 // has one slice
1549 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1550 ValueMetricProducer::Interval curInterval0 =
1551 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1552 ValueMetricProducer::Interval curInterval1 =
1553 valueProducer.mCurrentSlicedBucket.begin()->second[1];
1554 EXPECT_EQ(true, curInterval0.hasBase);
1555 EXPECT_EQ(10, curInterval0.base.long_value);
1556 EXPECT_EQ(false, curInterval0.hasValue);
1557 EXPECT_EQ(true, curInterval1.hasBase);
1558 EXPECT_EQ(20, curInterval1.base.long_value);
1559 EXPECT_EQ(false, curInterval1.hasValue);
1560
1561 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1562
1563 // has one slice
1564 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1565 curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1566 curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
1567 EXPECT_EQ(true, curInterval0.hasValue);
1568 EXPECT_EQ(5, curInterval0.value.long_value);
1569 EXPECT_EQ(true, curInterval1.hasValue);
1570 EXPECT_EQ(2, curInterval1.value.long_value);
1571
1572 // no change in first value field
1573 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
1574 event3->write(1);
1575 event3->write(15);
1576 event3->write(25);
1577 event3->init();
1578 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
1579 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1580 curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1581 curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
1582 EXPECT_EQ(true, curInterval0.hasBase);
1583 EXPECT_EQ(15, curInterval0.base.long_value);
1584 EXPECT_EQ(true, curInterval0.hasValue);
1585 EXPECT_EQ(true, curInterval1.hasBase);
1586 EXPECT_EQ(25, curInterval1.base.long_value);
1587 EXPECT_EQ(true, curInterval1.hasValue);
1588
1589 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
1590 event4->write(1);
1591 event4->write(15);
1592 event4->write(29);
1593 event4->init();
1594 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
1595 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1596 curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1597 curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
1598 EXPECT_EQ(true, curInterval0.hasBase);
1599 EXPECT_EQ(15, curInterval0.base.long_value);
1600 EXPECT_EQ(true, curInterval0.hasValue);
1601 EXPECT_EQ(true, curInterval1.hasBase);
1602 EXPECT_EQ(29, curInterval1.base.long_value);
1603 EXPECT_EQ(true, curInterval1.hasValue);
1604
1605 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1606
1607 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1608 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
1609 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
1610 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
1611
1612 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
1613 EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
1614 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
1615 EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
1616 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
1617
1618 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
1619 EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
1620 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
1621 }
1622
1623 /*
1624 * Tests zero default base.
1625 */
TEST(ValueMetricProducerTest,TestUseZeroDefaultBase)1626 TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
1627 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1628 metric.mutable_dimensions_in_what()->set_field(tagId);
1629 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1630 metric.set_use_zero_default_base(true);
1631
1632 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1633 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1634 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1635 data->clear();
1636 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
1637 event->write(1);
1638 event->write(3);
1639 event->init();
1640 data->push_back(event);
1641 return true;
1642 }));
1643
1644 sp<ValueMetricProducer> valueProducer =
1645 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1646
1647 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1648 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1649 auto& interval1 = iter->second[0];
1650 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1651 EXPECT_EQ(true, interval1.hasBase);
1652 EXPECT_EQ(3, interval1.base.long_value);
1653 EXPECT_EQ(false, interval1.hasValue);
1654 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1655 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1656 vector<shared_ptr<LogEvent>> allData;
1657
1658 allData.clear();
1659 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1660 event1->write(2);
1661 event1->write(4);
1662 event1->init();
1663 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1664 event2->write(1);
1665 event2->write(11);
1666 event2->init();
1667 allData.push_back(event1);
1668 allData.push_back(event2);
1669
1670 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1671 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1672 EXPECT_EQ(true, interval1.hasBase);
1673 EXPECT_EQ(11, interval1.base.long_value);
1674 EXPECT_EQ(false, interval1.hasValue);
1675 EXPECT_EQ(8, interval1.value.long_value);
1676
1677 auto it = valueProducer->mCurrentSlicedBucket.begin();
1678 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1679 if (it != iter) {
1680 break;
1681 }
1682 }
1683 EXPECT_TRUE(it != iter);
1684 auto& interval2 = it->second[0];
1685 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1686 EXPECT_EQ(true, interval2.hasBase);
1687 EXPECT_EQ(4, interval2.base.long_value);
1688 EXPECT_EQ(false, interval2.hasValue);
1689 EXPECT_EQ(4, interval2.value.long_value);
1690
1691 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
1692 auto iterator = valueProducer->mPastBuckets.begin();
1693 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1694 EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1695 iterator++;
1696 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1697 EXPECT_EQ(4, iterator->second[0].values[0].long_value);
1698 }
1699
1700 /*
1701 * Tests using zero default base with failed pull.
1702 */
TEST(ValueMetricProducerTest,TestUseZeroDefaultBaseWithPullFailures)1703 TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
1704 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1705 metric.mutable_dimensions_in_what()->set_field(tagId);
1706 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1707 metric.set_use_zero_default_base(true);
1708
1709 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1710 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1711 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1712 data->clear();
1713 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
1714 event->write(1);
1715 event->write(3);
1716 event->init();
1717 data->push_back(event);
1718 return true;
1719 }));
1720
1721 sp<ValueMetricProducer> valueProducer =
1722 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1723
1724 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1725 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1726 auto& interval1 = iter->second[0];
1727 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1728 EXPECT_EQ(true, interval1.hasBase);
1729 EXPECT_EQ(3, interval1.base.long_value);
1730 EXPECT_EQ(false, interval1.hasValue);
1731 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1732 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1733 vector<shared_ptr<LogEvent>> allData;
1734
1735 allData.clear();
1736 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1737 event1->write(2);
1738 event1->write(4);
1739 event1->init();
1740 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1741 event2->write(1);
1742 event2->write(11);
1743 event2->init();
1744 allData.push_back(event1);
1745 allData.push_back(event2);
1746
1747 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1748 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1749 EXPECT_EQ(true, interval1.hasBase);
1750 EXPECT_EQ(11, interval1.base.long_value);
1751 EXPECT_EQ(false, interval1.hasValue);
1752 EXPECT_EQ(8, interval1.value.long_value);
1753
1754 auto it = valueProducer->mCurrentSlicedBucket.begin();
1755 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1756 if (it != iter) {
1757 break;
1758 }
1759 }
1760 EXPECT_TRUE(it != iter);
1761 auto& interval2 = it->second[0];
1762 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1763 EXPECT_EQ(true, interval2.hasBase);
1764 EXPECT_EQ(4, interval2.base.long_value);
1765 EXPECT_EQ(false, interval2.hasValue);
1766 EXPECT_EQ(4, interval2.value.long_value);
1767 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
1768
1769 // next pull somehow did not happen, skip to end of bucket 3
1770 allData.clear();
1771 event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
1772 event1->write(2);
1773 event1->write(5);
1774 event1->init();
1775 allData.push_back(event1);
1776 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1777
1778 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1779 EXPECT_EQ(true, interval2.hasBase);
1780 EXPECT_EQ(5, interval2.base.long_value);
1781 EXPECT_EQ(false, interval2.hasValue);
1782 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1783 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
1784
1785 allData.clear();
1786 event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
1787 event1->write(2);
1788 event1->write(13);
1789 event1->init();
1790 allData.push_back(event1);
1791 event2 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
1792 event2->write(1);
1793 event2->write(5);
1794 event2->init();
1795 allData.push_back(event2);
1796 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1797
1798 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1799 auto it1 = std::next(valueProducer->mCurrentSlicedBucket.begin())->second[0];
1800 EXPECT_EQ(true, it1.hasBase);
1801 EXPECT_EQ(13, it1.base.long_value);
1802 EXPECT_EQ(false, it1.hasValue);
1803 EXPECT_EQ(8, it1.value.long_value);
1804 auto it2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1805 EXPECT_EQ(true, it2.hasBase);
1806 EXPECT_EQ(5, it2.base.long_value);
1807 EXPECT_EQ(false, it2.hasValue);
1808 EXPECT_EQ(5, it2.value.long_value);
1809 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1810 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
1811 }
1812
1813 /*
1814 * Tests trim unused dimension key if no new data is seen in an entire bucket.
1815 */
TEST(ValueMetricProducerTest,TestTrimUnusedDimensionKey)1816 TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
1817 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1818 metric.mutable_dimensions_in_what()->set_field(tagId);
1819 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1820
1821 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1822 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1823 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1824 data->clear();
1825 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
1826 event->write(1);
1827 event->write(3);
1828 event->init();
1829 data->push_back(event);
1830 return true;
1831 }));
1832
1833 sp<ValueMetricProducer> valueProducer =
1834 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1835
1836 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1837 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1838 auto& interval1 = iter->second[0];
1839 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1840 EXPECT_EQ(true, interval1.hasBase);
1841 EXPECT_EQ(3, interval1.base.long_value);
1842 EXPECT_EQ(false, interval1.hasValue);
1843 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1844 vector<shared_ptr<LogEvent>> allData;
1845
1846 allData.clear();
1847 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1848 event1->write(2);
1849 event1->write(4);
1850 event1->init();
1851 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
1852 event2->write(1);
1853 event2->write(11);
1854 event2->init();
1855 allData.push_back(event1);
1856 allData.push_back(event2);
1857
1858 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1859 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1860 EXPECT_EQ(true, interval1.hasBase);
1861 EXPECT_EQ(11, interval1.base.long_value);
1862 EXPECT_EQ(false, interval1.hasValue);
1863 EXPECT_EQ(8, interval1.value.long_value);
1864 EXPECT_FALSE(interval1.seenNewData);
1865 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
1866
1867 auto it = valueProducer->mCurrentSlicedBucket.begin();
1868 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1869 if (it != iter) {
1870 break;
1871 }
1872 }
1873 EXPECT_TRUE(it != iter);
1874 auto& interval2 = it->second[0];
1875 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1876 EXPECT_EQ(true, interval2.hasBase);
1877 EXPECT_EQ(4, interval2.base.long_value);
1878 EXPECT_EQ(false, interval2.hasValue);
1879 EXPECT_FALSE(interval2.seenNewData);
1880 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
1881
1882 // next pull somehow did not happen, skip to end of bucket 3
1883 allData.clear();
1884 event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
1885 event1->write(2);
1886 event1->write(5);
1887 event1->init();
1888 allData.push_back(event1);
1889 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1890 // Only one interval left. One was trimmed.
1891 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1892 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1893 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1894 EXPECT_EQ(true, interval2.hasBase);
1895 EXPECT_EQ(5, interval2.base.long_value);
1896 EXPECT_EQ(false, interval2.hasValue);
1897 EXPECT_FALSE(interval2.seenNewData);
1898 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
1899
1900 allData.clear();
1901 event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
1902 event1->write(2);
1903 event1->write(14);
1904 event1->init();
1905 allData.push_back(event1);
1906 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1907
1908 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1909 EXPECT_EQ(true, interval2.hasBase);
1910 EXPECT_EQ(14, interval2.base.long_value);
1911 EXPECT_EQ(false, interval2.hasValue);
1912 EXPECT_FALSE(interval2.seenNewData);
1913 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1914 auto iterator = valueProducer->mPastBuckets.begin();
1915 EXPECT_EQ(9, iterator->second[0].values[0].long_value);
1916 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1917 iterator++;
1918 EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1919 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1920 }
1921
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailAfterConditionChange_EndOfBucket)1922 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
1923 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1924
1925 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1926 // Used by onConditionChanged.
1927 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1928 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1929 data->clear();
1930 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
1931 event->write(tagId);
1932 event->write(100);
1933 event->init();
1934 data->push_back(event);
1935 return true;
1936 }));
1937
1938 sp<ValueMetricProducer> valueProducer =
1939 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1940
1941 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1942 // has one slice
1943 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1944 ValueMetricProducer::Interval& curInterval =
1945 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1946 EXPECT_EQ(true, curInterval.hasBase);
1947 EXPECT_EQ(100, curInterval.base.long_value);
1948 EXPECT_EQ(false, curInterval.hasValue);
1949
1950 vector<shared_ptr<LogEvent>> allData;
1951 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
1952 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1953 EXPECT_EQ(false, curInterval.hasBase);
1954 EXPECT_EQ(false, curInterval.hasValue);
1955 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
1956 }
1957
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailAfterConditionChange)1958 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
1959 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1960
1961 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1962 EXPECT_CALL(*pullerManager, Pull(tagId, _))
1963 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
1964 data->clear();
1965 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
1966 event->write(tagId);
1967 event->write(100);
1968 event->init();
1969 data->push_back(event);
1970 return true;
1971 }))
1972 .WillOnce(Return(false));
1973
1974 sp<ValueMetricProducer> valueProducer =
1975 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1976
1977 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1978
1979 // has one slice
1980 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1981 ValueMetricProducer::Interval& curInterval =
1982 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1983 EXPECT_EQ(true, curInterval.hasBase);
1984 EXPECT_EQ(100, curInterval.base.long_value);
1985 EXPECT_EQ(false, curInterval.hasValue);
1986 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
1987
1988 valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
1989
1990 // has one slice
1991 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1992 EXPECT_EQ(false, curInterval.hasValue);
1993 EXPECT_EQ(false, curInterval.hasBase);
1994 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
1995 }
1996
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailBeforeConditionChange)1997 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
1998 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1999
2000 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2001 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2002 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2003 data->clear();
2004 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2005 event->write(tagId);
2006 event->write(50);
2007 event->init();
2008 data->push_back(event);
2009 return false;
2010 }))
2011 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2012 data->clear();
2013 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
2014 event->write(tagId);
2015 event->write(100);
2016 event->init();
2017 data->push_back(event);
2018 return true;
2019 }));
2020
2021 sp<ValueMetricProducer> valueProducer =
2022 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2023
2024 // Don't directly set mCondition; the real code never does that. Go through regular code path
2025 // to avoid unexpected behaviors.
2026 // valueProducer->mCondition = ConditionState::kTrue;
2027 valueProducer->onConditionChanged(true, bucketStartTimeNs);
2028
2029 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2030
2031 valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
2032 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2033 ValueMetricProducer::Interval& curInterval =
2034 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2035 EXPECT_EQ(false, curInterval.hasBase);
2036 EXPECT_EQ(false, curInterval.hasValue);
2037 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2038 }
2039
TEST(ValueMetricProducerTest,TestResetBaseOnPullDelayExceeded)2040 TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
2041 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2042 metric.set_condition(StringToId("SCREEN_ON"));
2043 metric.set_max_pull_delay_sec(0);
2044
2045 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2046 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2047 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2048 data->clear();
2049 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
2050 event->write(tagId);
2051 event->write(120);
2052 event->init();
2053 data->push_back(event);
2054 return true;
2055 }));
2056
2057 sp<ValueMetricProducer> valueProducer =
2058 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2059
2060 valueProducer->mCondition = ConditionState::kFalse;
2061
2062 // Max delay is set to 0 so pull will exceed max delay.
2063 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2064 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2065 }
2066
TEST(ValueMetricProducerTest,TestResetBaseOnPullTooLate)2067 TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
2068 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2069
2070 UidMap uidMap;
2071 SimpleAtomMatcher atomMatcher;
2072 atomMatcher.set_atom_id(tagId);
2073 sp<EventMatcherWizard> eventMatcherWizard =
2074 new EventMatcherWizard({new SimpleLogMatchingTracker(
2075 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2076 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2077 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2078 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
2079 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
2080
2081 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
2082 eventMatcherWizard, tagId, bucket2StartTimeNs,
2083 bucket2StartTimeNs, pullerManager);
2084 valueProducer.prepareFirstBucket();
2085 valueProducer.mCondition = ConditionState::kFalse;
2086
2087 // Event should be skipped since it is from previous bucket.
2088 // Pull should not be called.
2089 valueProducer.onConditionChanged(true, bucketStartTimeNs);
2090 EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
2091 }
2092
TEST(ValueMetricProducerTest,TestBaseSetOnConditionChange)2093 TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
2094 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2095
2096 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2097 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2098 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2099 data->clear();
2100 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
2101 event->write(tagId);
2102 event->write(100);
2103 event->init();
2104 data->push_back(event);
2105 return true;
2106 }));
2107
2108 sp<ValueMetricProducer> valueProducer =
2109 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2110
2111 valueProducer->mCondition = ConditionState::kFalse;
2112 valueProducer->mHasGlobalBase = false;
2113
2114 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2115 valueProducer->mHasGlobalBase = true;
2116 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2117 ValueMetricProducer::Interval& curInterval =
2118 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2119 EXPECT_EQ(true, curInterval.hasBase);
2120 EXPECT_EQ(100, curInterval.base.long_value);
2121 EXPECT_EQ(false, curInterval.hasValue);
2122 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2123 }
2124
TEST(ValueMetricProducerTest,TestInvalidBucketWhenOneConditionFailed)2125 TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
2126 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2127
2128 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2129 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2130 // First onConditionChanged
2131 .WillOnce(Return(false))
2132 // Second onConditionChanged
2133 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2134 data->clear();
2135 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
2136 event->write(tagId);
2137 event->write(130);
2138 event->init();
2139 data->push_back(event);
2140 return true;
2141 }));
2142
2143 sp<ValueMetricProducer> valueProducer =
2144 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2145
2146 valueProducer->mCondition = ConditionState::kTrue;
2147
2148 // Bucket start.
2149 vector<shared_ptr<LogEvent>> allData;
2150 allData.clear();
2151 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
2152 event->write(1);
2153 event->write(110);
2154 event->init();
2155 allData.push_back(event);
2156 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2157
2158 // This will fail and should invalidate the whole bucket since we do not have all the data
2159 // needed to compute the metric value when the screen was on.
2160 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2161 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2162
2163 // Bucket end.
2164 allData.clear();
2165 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2166 event2->write(1);
2167 event2->write(140);
2168 event2->init();
2169 allData.push_back(event2);
2170 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2171
2172 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2173
2174 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
2175 // Contains base from last pull which was successful.
2176 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2177 ValueMetricProducer::Interval& curInterval =
2178 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2179 EXPECT_EQ(true, curInterval.hasBase);
2180 EXPECT_EQ(140, curInterval.base.long_value);
2181 EXPECT_EQ(false, curInterval.hasValue);
2182 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2183 }
2184
TEST(ValueMetricProducerTest,TestInvalidBucketWhenGuardRailHit)2185 TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
2186 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2187 metric.mutable_dimensions_in_what()->set_field(tagId);
2188 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2189 metric.set_condition(StringToId("SCREEN_ON"));
2190
2191 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2192 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2193 // First onConditionChanged
2194 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2195 for (int i = 0; i < 2000; i++) {
2196 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
2197 event->write(i);
2198 event->write(i);
2199 event->init();
2200 data->push_back(event);
2201 }
2202 return true;
2203 }));
2204
2205 sp<ValueMetricProducer> valueProducer =
2206 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2207 valueProducer->mCondition = ConditionState::kFalse;
2208
2209 valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
2210 EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
2211 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2212 }
2213
TEST(ValueMetricProducerTest,TestInvalidBucketWhenInitialPullFailed)2214 TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
2215 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2216
2217 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2218 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2219 // First onConditionChanged
2220 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2221 data->clear();
2222 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
2223 event->write(tagId);
2224 event->write(120);
2225 event->init();
2226 data->push_back(event);
2227 return true;
2228 }))
2229 // Second onConditionChanged
2230 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2231 data->clear();
2232 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
2233 event->write(tagId);
2234 event->write(130);
2235 event->init();
2236 data->push_back(event);
2237 return true;
2238 }));
2239
2240 sp<ValueMetricProducer> valueProducer =
2241 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2242
2243 valueProducer->mCondition = ConditionState::kTrue;
2244
2245 // Bucket start.
2246 vector<shared_ptr<LogEvent>> allData;
2247 allData.clear();
2248 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
2249 event->write(1);
2250 event->write(110);
2251 event->init();
2252 allData.push_back(event);
2253 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
2254
2255 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2256 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2257
2258 // Bucket end.
2259 allData.clear();
2260 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2261 event2->write(1);
2262 event2->write(140);
2263 event2->init();
2264 allData.push_back(event2);
2265 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2266
2267 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2268
2269 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
2270 // Contains base from last pull which was successful.
2271 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2272 ValueMetricProducer::Interval& curInterval =
2273 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2274 EXPECT_EQ(true, curInterval.hasBase);
2275 EXPECT_EQ(140, curInterval.base.long_value);
2276 EXPECT_EQ(false, curInterval.hasValue);
2277 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2278 }
2279
TEST(ValueMetricProducerTest,TestInvalidBucketWhenLastPullFailed)2280 TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
2281 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2282
2283 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2284 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2285 // First onConditionChanged
2286 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2287 data->clear();
2288 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
2289 event->write(tagId);
2290 event->write(120);
2291 event->init();
2292 data->push_back(event);
2293 return true;
2294 }))
2295 // Second onConditionChanged
2296 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2297 data->clear();
2298 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
2299 event->write(tagId);
2300 event->write(130);
2301 event->init();
2302 data->push_back(event);
2303 return true;
2304 }));
2305
2306 sp<ValueMetricProducer> valueProducer =
2307 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2308
2309 valueProducer->mCondition = ConditionState::kTrue;
2310
2311 // Bucket start.
2312 vector<shared_ptr<LogEvent>> allData;
2313 allData.clear();
2314 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
2315 event->write(1);
2316 event->write(110);
2317 event->init();
2318 allData.push_back(event);
2319 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2320
2321 // This will fail and should invalidate the whole bucket since we do not have all the data
2322 // needed to compute the metric value when the screen was on.
2323 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2324 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2325
2326 // Bucket end.
2327 allData.clear();
2328 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2329 event2->write(1);
2330 event2->write(140);
2331 event2->init();
2332 allData.push_back(event2);
2333 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2334
2335 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2336
2337 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
2338 // Last pull failed so based has been reset.
2339 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2340 ValueMetricProducer::Interval& curInterval =
2341 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2342 EXPECT_EQ(false, curInterval.hasBase);
2343 EXPECT_EQ(false, curInterval.hasValue);
2344 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2345 }
2346
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onDataPulled)2347 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
2348 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2349 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2350 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2351 // Start bucket.
2352 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2353 data->clear();
2354 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2355 event->write(tagId);
2356 event->write(3);
2357 event->init();
2358 data->push_back(event);
2359 return true;
2360 }));
2361
2362 sp<ValueMetricProducer> valueProducer =
2363 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2364
2365 // Bucket 2 start.
2366 vector<shared_ptr<LogEvent>> allData;
2367 allData.clear();
2368 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2369 event->write(tagId);
2370 event->write(110);
2371 event->init();
2372 allData.push_back(event);
2373 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2374 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2375 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
2376
2377 // Bucket 3 empty.
2378 allData.clear();
2379 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
2380 event2->init();
2381 allData.push_back(event2);
2382 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
2383 // Data has been trimmed.
2384 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2385 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
2386 }
2387
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onConditionChanged)2388 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
2389 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2390
2391 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2392 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2393 // First onConditionChanged
2394 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2395 data->clear();
2396 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2397 event->write(tagId);
2398 event->write(3);
2399 event->init();
2400 data->push_back(event);
2401 return true;
2402 }))
2403 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2404 data->clear();
2405 return true;
2406 }));
2407
2408 sp<ValueMetricProducer> valueProducer =
2409 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2410
2411 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2412 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2413 ValueMetricProducer::Interval& curInterval =
2414 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2415 EXPECT_EQ(true, curInterval.hasBase);
2416 EXPECT_EQ(false, curInterval.hasValue);
2417 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2418
2419 // Empty pull.
2420 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2421 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2422 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2423 EXPECT_EQ(false, curInterval.hasBase);
2424 EXPECT_EQ(false, curInterval.hasValue);
2425 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2426 }
2427
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onBucketBoundary)2428 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
2429 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2430
2431 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2432 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2433 // First onConditionChanged
2434 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2435 data->clear();
2436 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2437 event->write(tagId);
2438 event->write(1);
2439 event->init();
2440 data->push_back(event);
2441 return true;
2442 }))
2443 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2444 data->clear();
2445 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2446 event->write(tagId);
2447 event->write(2);
2448 event->init();
2449 data->push_back(event);
2450 return true;
2451 }))
2452 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2453 data->clear();
2454 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2455 event->write(tagId);
2456 event->write(5);
2457 event->init();
2458 data->push_back(event);
2459 return true;
2460 }));
2461
2462 sp<ValueMetricProducer> valueProducer =
2463 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2464
2465 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2466 valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
2467 valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
2468 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2469 ValueMetricProducer::Interval& curInterval =
2470 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2471 EXPECT_EQ(true, curInterval.hasBase);
2472 EXPECT_EQ(true, curInterval.hasValue);
2473 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2474
2475 // End of bucket
2476 vector<shared_ptr<LogEvent>> allData;
2477 allData.clear();
2478 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2479 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2480 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2481 // Data is empty, base should be reset.
2482 EXPECT_EQ(false, curInterval.hasBase);
2483 EXPECT_EQ(5, curInterval.base.long_value);
2484 EXPECT_EQ(false, curInterval.hasValue);
2485 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2486
2487 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
2488 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
2489 }
2490
TEST(ValueMetricProducerTest,TestPartialResetOnBucketBoundaries)2491 TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
2492 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2493 metric.mutable_dimensions_in_what()->set_field(tagId);
2494 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2495 metric.set_condition(StringToId("SCREEN_ON"));
2496
2497 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2498 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2499 // First onConditionChanged
2500 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2501 data->clear();
2502 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2503 event->write(tagId);
2504 event->write(1);
2505 event->write(1);
2506 event->init();
2507 data->push_back(event);
2508 return true;
2509 }));
2510
2511 sp<ValueMetricProducer> valueProducer =
2512 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2513
2514 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2515 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2516
2517 // End of bucket
2518 vector<shared_ptr<LogEvent>> allData;
2519 allData.clear();
2520 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2521 event->write(2);
2522 event->write(2);
2523 event->init();
2524 allData.push_back(event);
2525 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2526
2527 // Key 1 should be reset since in not present in the most pull.
2528 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
2529 auto iterator = valueProducer->mCurrentSlicedBucket.begin();
2530 EXPECT_EQ(true, iterator->second[0].hasBase);
2531 EXPECT_EQ(2, iterator->second[0].base.long_value);
2532 EXPECT_EQ(false, iterator->second[0].hasValue);
2533 iterator++;
2534 EXPECT_EQ(false, iterator->second[0].hasBase);
2535 EXPECT_EQ(1, iterator->second[0].base.long_value);
2536 EXPECT_EQ(false, iterator->second[0].hasValue);
2537
2538 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2539 }
2540
TEST(ValueMetricProducerTest,TestBucketIncludingUnknownConditionIsInvalid)2541 TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid) {
2542 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2543 metric.mutable_dimensions_in_what()->set_field(tagId);
2544 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2545 metric.set_condition(StringToId("SCREEN_ON"));
2546
2547 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2548 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2549 // Second onConditionChanged.
2550 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2551 data->clear();
2552 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2553 event->write(tagId);
2554 event->write(2);
2555 event->write(2);
2556 event->init();
2557 data->push_back(event);
2558 return true;
2559 }));
2560
2561 sp<ValueMetricProducer> valueProducer =
2562 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2563 valueProducer->mCondition = ConditionState::kUnknown;
2564
2565 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2566 valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
2567
2568 // End of bucket
2569 vector<shared_ptr<LogEvent>> allData;
2570 allData.clear();
2571 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2572 event->write(4);
2573 event->write(4);
2574 event->init();
2575 allData.push_back(event);
2576 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2577
2578 // Bucket is incomplete so it is mark as invalid, however the base is fine since the last pull
2579 // succeeded.
2580 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
2581 }
2582
TEST(ValueMetricProducerTest,TestFullBucketResetWhenLastBucketInvalid)2583 TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
2584 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2585
2586 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2587 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2588 // Initialization.
2589 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2590 data->clear();
2591 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
2592 return true;
2593 }))
2594 // notifyAppUpgrade.
2595 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2596 data->clear();
2597 data->push_back(ValueMetricProducerTestHelper::createEvent(
2598 bucketStartTimeNs + bucketSizeNs / 2, 10));
2599 return true;
2600 }));
2601 sp<ValueMetricProducer> valueProducer =
2602 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2603 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2604
2605 valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
2606 ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
2607
2608 vector<shared_ptr<LogEvent>> allData;
2609 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
2610 valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
2611 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2612 }
2613
TEST(ValueMetricProducerTest,TestBucketBoundariesOnConditionChange)2614 TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
2615 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2616 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2617 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2618 // Second onConditionChanged.
2619 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2620 data->clear();
2621 data->push_back(
2622 ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
2623 return true;
2624 }))
2625 // Third onConditionChanged.
2626 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2627 data->clear();
2628 data->push_back(
2629 ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
2630 return true;
2631 }));
2632
2633 sp<ValueMetricProducer> valueProducer =
2634 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2635 valueProducer->mCondition = ConditionState::kUnknown;
2636
2637 valueProducer->onConditionChanged(false, bucketStartTimeNs);
2638 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2639
2640 // End of first bucket
2641 vector<shared_ptr<LogEvent>> allData;
2642 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
2643 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2644 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2645
2646 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2647 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2648 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2649 EXPECT_EQ(true, curInterval.hasBase);
2650 EXPECT_EQ(5, curInterval.base.long_value);
2651 EXPECT_EQ(false, curInterval.hasValue);
2652
2653 valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
2654
2655 // Bucket should have been completed.
2656 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
2657 }
2658
TEST(ValueMetricProducerTest,TestLateOnDataPulledWithoutDiff)2659 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
2660 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2661 metric.set_use_diff(false);
2662
2663 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2664 sp<ValueMetricProducer> valueProducer =
2665 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2666
2667 vector<shared_ptr<LogEvent>> allData;
2668 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
2669 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2670
2671 allData.clear();
2672 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
2673 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2674
2675 // Bucket should have been completed.
2676 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
2677 }
2678
TEST(ValueMetricProducerTest,TestLateOnDataPulledWithDiff)2679 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
2680 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2681
2682 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2683 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2684 // Initialization.
2685 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2686 data->clear();
2687 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
2688 return true;
2689 }));
2690
2691 sp<ValueMetricProducer> valueProducer =
2692 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2693
2694 vector<shared_ptr<LogEvent>> allData;
2695 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
2696 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2697
2698 allData.clear();
2699 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
2700 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2701
2702 // Bucket should have been completed.
2703 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
2704 }
2705
TEST(ValueMetricProducerTest,TestBucketBoundariesOnAppUpgrade)2706 TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
2707 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2708
2709 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2710 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2711 // Initialization.
2712 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2713 data->clear();
2714 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
2715 return true;
2716 }))
2717 // notifyAppUpgrade.
2718 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2719 data->clear();
2720 data->push_back(
2721 ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
2722 return true;
2723 }));
2724
2725 sp<ValueMetricProducer> valueProducer =
2726 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2727
2728 valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
2729
2730 // Bucket should have been completed.
2731 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
2732 }
2733
TEST(ValueMetricProducerTest,TestDataIsNotUpdatedWhenNoConditionChanged)2734 TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
2735 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2736
2737 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2738 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2739 // First on condition changed.
2740 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2741 data->clear();
2742 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
2743 return true;
2744 }))
2745 // Second on condition changed.
2746 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2747 data->clear();
2748 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
2749 return true;
2750 }));
2751
2752 sp<ValueMetricProducer> valueProducer =
2753 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2754
2755 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
2756 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2757 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2758
2759 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2760 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2761 EXPECT_EQ(true, curInterval.hasValue);
2762 EXPECT_EQ(2, curInterval.value.long_value);
2763
2764 vector<shared_ptr<LogEvent>> allData;
2765 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10));
2766 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2767
2768 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
2769 }
2770
TEST(ValueMetricProducerTest,TestBucketInvalidIfGlobalBaseIsNotSet)2771 TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
2772 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2773
2774 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2775 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2776 // First condition change.
2777 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2778 data->clear();
2779 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
2780 return true;
2781 }))
2782 // 2nd condition change.
2783 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2784 data->clear();
2785 data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
2786 return true;
2787 }))
2788 // 3rd condition change.
2789 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2790 data->clear();
2791 data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
2792 return true;
2793 }));
2794
2795 sp<ValueMetricProducer> valueProducer =
2796 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2797 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2798
2799 vector<shared_ptr<LogEvent>> allData;
2800 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
2801 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
2802
2803 allData.clear();
2804 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
2805 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2806
2807 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
2808 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2809
2810 allData.clear();
2811 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
2812 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2813
2814 // There was not global base available so all buckets are invalid.
2815 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
2816 }
2817
outputStreamToProto(ProtoOutputStream * proto)2818 static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
2819 vector<uint8_t> bytes;
2820 bytes.resize(proto->size());
2821 size_t pos = 0;
2822 sp<ProtoReader> reader = proto->data();
2823 while (reader->readBuffer() != NULL) {
2824 size_t toRead = reader->currentToRead();
2825 std::memcpy(&((bytes)[pos]), reader->readBuffer(), toRead);
2826 pos += toRead;
2827 reader->move(toRead);
2828 }
2829
2830 StatsLogReport report;
2831 report.ParseFromArray(bytes.data(), bytes.size());
2832 return report;
2833 }
2834
TEST(ValueMetricProducerTest,TestPullNeededFastDump)2835 TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
2836 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2837
2838 UidMap uidMap;
2839 SimpleAtomMatcher atomMatcher;
2840 atomMatcher.set_atom_id(tagId);
2841 sp<EventMatcherWizard> eventMatcherWizard =
2842 new EventMatcherWizard({new SimpleLogMatchingTracker(
2843 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2844 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2845 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2846 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
2847 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
2848
2849 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2850 // Initial pull.
2851 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2852 data->clear();
2853 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2854 event->write(tagId);
2855 event->write(1);
2856 event->write(1);
2857 event->init();
2858 data->push_back(event);
2859 return true;
2860 }));
2861
2862 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
2863 eventMatcherWizard, tagId, bucketStartTimeNs,
2864 bucketStartTimeNs, pullerManager);
2865 valueProducer.prepareFirstBucket();
2866
2867 ProtoOutputStream output;
2868 std::set<string> strSet;
2869 valueProducer.onDumpReport(bucketStartTimeNs + 10,
2870 true /* include recent buckets */, true,
2871 FAST, &strSet, &output);
2872
2873 StatsLogReport report = outputStreamToProto(&output);
2874 // Bucket is invalid since we did not pull when dump report was called.
2875 EXPECT_EQ(0, report.value_metrics().data_size());
2876 }
2877
TEST(ValueMetricProducerTest,TestFastDumpWithoutCurrentBucket)2878 TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
2879 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2880
2881 UidMap uidMap;
2882 SimpleAtomMatcher atomMatcher;
2883 atomMatcher.set_atom_id(tagId);
2884 sp<EventMatcherWizard> eventMatcherWizard =
2885 new EventMatcherWizard({new SimpleLogMatchingTracker(
2886 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2887 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2888 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2889 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
2890 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
2891
2892 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2893 // Initial pull.
2894 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2895 data->clear();
2896 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2897 event->write(tagId);
2898 event->write(1);
2899 event->write(1);
2900 event->init();
2901 data->push_back(event);
2902 return true;
2903 }));
2904
2905 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
2906 eventMatcherWizard, tagId, bucketStartTimeNs,
2907 bucketStartTimeNs, pullerManager);
2908 valueProducer.prepareFirstBucket();
2909
2910 vector<shared_ptr<LogEvent>> allData;
2911 allData.clear();
2912 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
2913 event->write(tagId);
2914 event->write(2);
2915 event->write(2);
2916 event->init();
2917 allData.push_back(event);
2918 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2919
2920 ProtoOutputStream output;
2921 std::set<string> strSet;
2922 valueProducer.onDumpReport(bucket4StartTimeNs,
2923 false /* include recent buckets */, true,
2924 FAST, &strSet, &output);
2925
2926 StatsLogReport report = outputStreamToProto(&output);
2927 // Previous bucket is part of the report.
2928 EXPECT_EQ(1, report.value_metrics().data_size());
2929 EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
2930 }
2931
TEST(ValueMetricProducerTest,TestPullNeededNoTimeConstraints)2932 TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
2933 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2934
2935 UidMap uidMap;
2936 SimpleAtomMatcher atomMatcher;
2937 atomMatcher.set_atom_id(tagId);
2938 sp<EventMatcherWizard> eventMatcherWizard =
2939 new EventMatcherWizard({new SimpleLogMatchingTracker(
2940 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2941 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2942 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2943 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
2944 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
2945
2946 EXPECT_CALL(*pullerManager, Pull(tagId, _))
2947 // Initial pull.
2948 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2949 data->clear();
2950 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
2951 event->write(tagId);
2952 event->write(1);
2953 event->write(1);
2954 event->init();
2955 data->push_back(event);
2956 return true;
2957 }))
2958 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
2959 data->clear();
2960 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
2961 event->write(tagId);
2962 event->write(3);
2963 event->write(3);
2964 event->init();
2965 data->push_back(event);
2966 return true;
2967 }));
2968
2969 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
2970 eventMatcherWizard, tagId, bucketStartTimeNs,
2971 bucketStartTimeNs, pullerManager);
2972 valueProducer.prepareFirstBucket();
2973
2974 ProtoOutputStream output;
2975 std::set<string> strSet;
2976 valueProducer.onDumpReport(bucketStartTimeNs + 10,
2977 true /* include recent buckets */, true,
2978 NO_TIME_CONSTRAINTS, &strSet, &output);
2979
2980 StatsLogReport report = outputStreamToProto(&output);
2981 EXPECT_EQ(1, report.value_metrics().data_size());
2982 EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
2983 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
2984 }
2985
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withoutCondition)2986 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
2987 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2988 metric.set_use_diff(false);
2989
2990 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2991 sp<ValueMetricProducer> valueProducer =
2992 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2993
2994 vector<shared_ptr<LogEvent>> allData;
2995 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10));
2996 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
2997
2998 // Bucket should have been completed.
2999 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
3000 }
3001
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withMultipleConditionChanges)3002 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
3003 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3004 metric.set_use_diff(false);
3005
3006 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3007 EXPECT_CALL(*pullerManager, Pull(tagId, _))
3008 // condition becomes true
3009 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
3010 data->clear();
3011 data->push_back(ValueMetricProducerTestHelper::createEvent(
3012 bucketStartTimeNs + 30, 10));
3013 return true;
3014 }))
3015 // condition becomes false
3016 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
3017 data->clear();
3018 data->push_back(ValueMetricProducerTestHelper::createEvent(
3019 bucketStartTimeNs + 50, 20));
3020 return true;
3021 }));
3022 sp<ValueMetricProducer> valueProducer =
3023 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3024 valueProducer->mCondition = ConditionState::kFalse;
3025
3026 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3027 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3028 // has one slice
3029 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
3030 ValueMetricProducer::Interval curInterval =
3031 valueProducer->mCurrentSlicedBucket.begin()->second[0];
3032 EXPECT_EQ(false, curInterval.hasBase);
3033 EXPECT_EQ(true, curInterval.hasValue);
3034 EXPECT_EQ(20, curInterval.value.long_value);
3035
3036
3037 // Now the alarm is delivered. Condition is off though.
3038 vector<shared_ptr<LogEvent>> allData;
3039 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
3040 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3041
3042 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
3043 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
3044 EXPECT_EQ(false, curInterval.hasBase);
3045 EXPECT_EQ(false, curInterval.hasValue);
3046 }
3047
TEST(ValueMetricProducerTest,TestPulledData_noDiff_bucketBoundaryTrue)3048 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
3049 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3050 metric.set_use_diff(false);
3051
3052 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3053 EXPECT_CALL(*pullerManager, Pull(tagId, _))
3054 // condition becomes true
3055 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
3056 data->clear();
3057 data->push_back(ValueMetricProducerTestHelper::createEvent(
3058 bucketStartTimeNs + 30, 10));
3059 return true;
3060 }));
3061 sp<ValueMetricProducer> valueProducer =
3062 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3063 valueProducer->mCondition = ConditionState::kFalse;
3064
3065 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3066
3067 // Now the alarm is delivered. Condition is off though.
3068 vector<shared_ptr<LogEvent>> allData;
3069 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
3070 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3071
3072 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
3073 ValueMetricProducer::Interval curInterval =
3074 valueProducer->mCurrentSlicedBucket.begin()->second[0];
3075 EXPECT_EQ(false, curInterval.hasBase);
3076 EXPECT_EQ(false, curInterval.hasValue);
3077 }
3078
TEST(ValueMetricProducerTest,TestPulledData_noDiff_bucketBoundaryFalse)3079 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
3080 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3081 metric.set_use_diff(false);
3082
3083 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3084 sp<ValueMetricProducer> valueProducer =
3085 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3086 valueProducer->mCondition = ConditionState::kFalse;
3087
3088 // Now the alarm is delivered. Condition is off though.
3089 vector<shared_ptr<LogEvent>> allData;
3090 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
3091 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3092
3093 // Condition was always false.
3094 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
3095 }
3096
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withFailure)3097 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
3098 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3099 metric.set_use_diff(false);
3100
3101 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3102 EXPECT_CALL(*pullerManager, Pull(tagId, _))
3103 // condition becomes true
3104 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
3105 data->clear();
3106 data->push_back(ValueMetricProducerTestHelper::createEvent(
3107 bucketStartTimeNs + 30, 10));
3108 return true;
3109 }))
3110 .WillOnce(Return(false));
3111 sp<ValueMetricProducer> valueProducer =
3112 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3113 valueProducer->mCondition = ConditionState::kFalse;
3114
3115 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3116 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3117
3118 // Now the alarm is delivered. Condition is off though.
3119 vector<shared_ptr<LogEvent>> allData;
3120 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
3121 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3122
3123 // No buckets, we had a failure.
3124 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
3125 }
3126
3127 } // namespace statsd
3128 } // namespace os
3129 } // namespace android
3130 #else
3131 GTEST_LOG_(INFO) << "This test does nothing.\n";
3132 #endif
3133