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