Home | History | Annotate | Download | only in metrics
      1 // Copyright (C) 2017 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "src/metrics/ValueMetricProducer.h"
     16 #include "src/stats_log_util.h"
     17 #include "metrics_test_helper.h"
     18 #include "tests/statsd_test_util.h"
     19 
     20 #include <gmock/gmock.h>
     21 #include <gtest/gtest.h>
     22 #include <math.h>
     23 #include <stdio.h>
     24 #include <vector>
     25 
     26 using namespace testing;
     27 using android::sp;
     28 using std::make_shared;
     29 using std::set;
     30 using std::shared_ptr;
     31 using std::unordered_map;
     32 using std::vector;
     33 
     34 #ifdef __ANDROID__
     35 
     36 namespace android {
     37 namespace os {
     38 namespace statsd {
     39 
     40 const ConfigKey kConfigKey(0, 12345);
     41 const int tagId = 1;
     42 const int64_t metricId = 123;
     43 const int64_t bucketStartTimeNs = 10000000000;
     44 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
     45 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
     46 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
     47 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
     48 const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
     49 const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
     50 const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
     51 
     52 /*
     53  * Tests pulled atoms with no conditions
     54  */
     55 TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
     56     ValueMetric metric;
     57     metric.set_id(metricId);
     58     metric.set_bucket(ONE_MINUTE);
     59     metric.mutable_value_field()->set_field(tagId);
     60     metric.mutable_value_field()->add_child()->set_field(2);
     61 
     62     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     63     // TODO: pending refactor of StatsPullerManager
     64     // For now we still need this so that it doesn't do real pulling.
     65     shared_ptr<MockStatsPullerManager> pullerManager =
     66             make_shared<StrictMock<MockStatsPullerManager>>();
     67     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     68     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
     69 
     70     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
     71                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
     72     valueProducer.setBucketSize(60 * NS_PER_SEC);
     73 
     74     vector<shared_ptr<LogEvent>> allData;
     75     allData.clear();
     76     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
     77     event->write(tagId);
     78     event->write(11);
     79     event->init();
     80     allData.push_back(event);
     81 
     82     valueProducer.onDataPulled(allData);
     83     // has one slice
     84     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     85     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     86     valueProducer.setBucketSize(60 * NS_PER_SEC);
     87 
     88     // startUpdated:true tainted:0 sum:0 start:11
     89     EXPECT_EQ(true, curInterval.startUpdated);
     90     EXPECT_EQ(0, curInterval.tainted);
     91     EXPECT_EQ(0, curInterval.sum);
     92     EXPECT_EQ(11, curInterval.start);
     93     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
     94 
     95     allData.clear();
     96     event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
     97     event->write(tagId);
     98     event->write(23);
     99     event->init();
    100     allData.push_back(event);
    101     valueProducer.onDataPulled(allData);
    102     // has one slice
    103     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    104     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    105     // tartUpdated:false tainted:0 sum:12
    106     EXPECT_EQ(true, curInterval.startUpdated);
    107     EXPECT_EQ(0, curInterval.tainted);
    108     EXPECT_EQ(0, curInterval.sum);
    109     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    110     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    111     EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
    112 
    113     allData.clear();
    114     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
    115     event->write(tagId);
    116     event->write(36);
    117     event->init();
    118     allData.push_back(event);
    119     valueProducer.onDataPulled(allData);
    120     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    121     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    122     // startUpdated:false tainted:0 sum:12
    123     EXPECT_EQ(true, curInterval.startUpdated);
    124     EXPECT_EQ(0, curInterval.tainted);
    125     EXPECT_EQ(0, curInterval.sum);
    126     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    127     EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
    128     EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
    129 }
    130 
    131 /*
    132  * Tests pulled atoms with no conditions and take absolute value after reset
    133  */
    134 TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
    135     ValueMetric metric;
    136     metric.set_id(metricId);
    137     metric.set_bucket(ONE_MINUTE);
    138     metric.mutable_value_field()->set_field(tagId);
    139     metric.mutable_value_field()->add_child()->set_field(2);
    140     metric.set_use_absolute_value_on_reset(true);
    141 
    142     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    143     shared_ptr<MockStatsPullerManager> pullerManager =
    144             make_shared<StrictMock<MockStatsPullerManager>>();
    145     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    146     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    147 
    148     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    149                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
    150     valueProducer.setBucketSize(60 * NS_PER_SEC);
    151 
    152     vector<shared_ptr<LogEvent>> allData;
    153     allData.clear();
    154     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    155     event->write(tagId);
    156     event->write(11);
    157     event->init();
    158     allData.push_back(event);
    159 
    160     valueProducer.onDataPulled(allData);
    161     // has one slice
    162     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    163     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    164     valueProducer.setBucketSize(60 * NS_PER_SEC);
    165 
    166     EXPECT_EQ(true, curInterval.startUpdated);
    167     EXPECT_EQ(0, curInterval.tainted);
    168     EXPECT_EQ(0, curInterval.sum);
    169     EXPECT_EQ(11, curInterval.start);
    170     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    171 
    172     allData.clear();
    173     event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
    174     event->write(tagId);
    175     event->write(10);
    176     event->init();
    177     allData.push_back(event);
    178     valueProducer.onDataPulled(allData);
    179     // has one slice
    180     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    181     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    182     EXPECT_EQ(true, curInterval.startUpdated);
    183     EXPECT_EQ(0, curInterval.tainted);
    184     EXPECT_EQ(0, curInterval.sum);
    185     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    186     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    187     EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
    188 
    189     allData.clear();
    190     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
    191     event->write(tagId);
    192     event->write(36);
    193     event->init();
    194     allData.push_back(event);
    195     valueProducer.onDataPulled(allData);
    196     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    197     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    198     EXPECT_EQ(true, curInterval.startUpdated);
    199     EXPECT_EQ(0, curInterval.tainted);
    200     EXPECT_EQ(0, curInterval.sum);
    201     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    202     EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
    203     EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValue);
    204 }
    205 
    206 /*
    207  * Tests pulled atoms with no conditions and take zero value after reset
    208  */
    209 TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
    210     ValueMetric metric;
    211     metric.set_id(metricId);
    212     metric.set_bucket(ONE_MINUTE);
    213     metric.mutable_value_field()->set_field(tagId);
    214     metric.mutable_value_field()->add_child()->set_field(2);
    215 
    216     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    217     shared_ptr<MockStatsPullerManager> pullerManager =
    218             make_shared<StrictMock<MockStatsPullerManager>>();
    219     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    220     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    221 
    222     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    223                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
    224     valueProducer.setBucketSize(60 * NS_PER_SEC);
    225 
    226     vector<shared_ptr<LogEvent>> allData;
    227     allData.clear();
    228     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    229     event->write(tagId);
    230     event->write(11);
    231     event->init();
    232     allData.push_back(event);
    233 
    234     valueProducer.onDataPulled(allData);
    235     // has one slice
    236     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    237     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    238     valueProducer.setBucketSize(60 * NS_PER_SEC);
    239 
    240     EXPECT_EQ(true, curInterval.startUpdated);
    241     EXPECT_EQ(0, curInterval.tainted);
    242     EXPECT_EQ(0, curInterval.sum);
    243     EXPECT_EQ(11, curInterval.start);
    244     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    245 
    246     allData.clear();
    247     event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
    248     event->write(tagId);
    249     event->write(10);
    250     event->init();
    251     allData.push_back(event);
    252     valueProducer.onDataPulled(allData);
    253     // has one slice
    254     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    255     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    256     EXPECT_EQ(true, curInterval.startUpdated);
    257     EXPECT_EQ(0, curInterval.tainted);
    258     EXPECT_EQ(0, curInterval.sum);
    259     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    260 
    261     allData.clear();
    262     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
    263     event->write(tagId);
    264     event->write(36);
    265     event->init();
    266     allData.push_back(event);
    267     valueProducer.onDataPulled(allData);
    268     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    269     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    270     EXPECT_EQ(true, curInterval.startUpdated);
    271     EXPECT_EQ(0, curInterval.tainted);
    272     EXPECT_EQ(0, curInterval.sum);
    273     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    274     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    275     EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValue);
    276 }
    277 
    278 /*
    279  * Test pulled event with non sliced condition.
    280  */
    281 TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
    282     ValueMetric metric;
    283     metric.set_id(metricId);
    284     metric.set_bucket(ONE_MINUTE);
    285     metric.mutable_value_field()->set_field(tagId);
    286     metric.mutable_value_field()->add_child()->set_field(2);
    287     metric.set_condition(StringToId("SCREEN_ON"));
    288 
    289     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    290     shared_ptr<MockStatsPullerManager> pullerManager =
    291             make_shared<StrictMock<MockStatsPullerManager>>();
    292     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    293     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
    294 
    295     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
    296             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    297                                 vector<std::shared_ptr<LogEvent>>* data) {
    298                 data->clear();
    299                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    300                 event->write(tagId);
    301                 event->write(100);
    302                 event->init();
    303                 data->push_back(event);
    304                 return true;
    305             }))
    306             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    307                                 vector<std::shared_ptr<LogEvent>>* data) {
    308                 data->clear();
    309                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
    310                 event->write(tagId);
    311                 event->write(120);
    312                 event->init();
    313                 data->push_back(event);
    314                 return true;
    315             }));
    316 
    317     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
    318                                       bucketStartTimeNs, pullerManager);
    319     valueProducer.setBucketSize(60 * NS_PER_SEC);
    320     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
    321 
    322     // has one slice
    323     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    324     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    325     // startUpdated:false tainted:0 sum:0 start:100
    326     EXPECT_EQ(100, curInterval.start);
    327     EXPECT_EQ(true, curInterval.startUpdated);
    328     EXPECT_EQ(0, curInterval.tainted);
    329     EXPECT_EQ(0, curInterval.sum);
    330     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    331 
    332     vector<shared_ptr<LogEvent>> allData;
    333     allData.clear();
    334     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    335     event->write(1);
    336     event->write(110);
    337     event->init();
    338     allData.push_back(event);
    339     valueProducer.onDataPulled(allData);
    340 
    341     // has one slice
    342     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    343     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    344     // startUpdated:false tainted:0 sum:0 start:110
    345     EXPECT_EQ(110, curInterval.start);
    346     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    347     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    348     EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
    349 
    350     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
    351 
    352     // has one slice
    353     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    354     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    355     // startUpdated:false tainted:0 sum:0 start:110
    356     EXPECT_EQ(10, curInterval.sum);
    357     EXPECT_EQ(false, curInterval.startUpdated);
    358 }
    359 
    360 TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
    361     ValueMetric metric;
    362     metric.set_id(metricId);
    363     metric.set_bucket(ONE_MINUTE);
    364     metric.mutable_value_field()->set_field(tagId);
    365     metric.mutable_value_field()->add_child()->set_field(2);
    366 
    367     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    368     shared_ptr<MockStatsPullerManager> pullerManager =
    369             make_shared<StrictMock<MockStatsPullerManager>>();
    370     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
    371                                       bucketStartTimeNs, pullerManager);
    372     valueProducer.setBucketSize(60 * NS_PER_SEC);
    373 
    374     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    375     event1->write(1);
    376     event1->write(10);
    377     event1->init();
    378     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
    379     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    380 
    381     valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
    382     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    383     EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
    384 
    385     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
    386     event2->write(1);
    387     event2->write(10);
    388     event2->init();
    389     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
    390     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    391     EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
    392 
    393     // Next value should create a new bucket.
    394     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
    395     event3->write(1);
    396     event3->write(10);
    397     event3->init();
    398     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
    399     EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    400     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
    401 }
    402 
    403 TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
    404     ValueMetric metric;
    405     metric.set_id(metricId);
    406     metric.set_bucket(ONE_MINUTE);
    407     metric.mutable_value_field()->set_field(tagId);
    408     metric.mutable_value_field()->add_child()->set_field(2);
    409 
    410     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    411     shared_ptr<MockStatsPullerManager> pullerManager =
    412             make_shared<StrictMock<MockStatsPullerManager>>();
    413     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    414     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    415     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
    416             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    417                                 vector<std::shared_ptr<LogEvent>>* data) {
    418                 data->clear();
    419                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    420                 event->write(tagId);
    421                 event->write(120);
    422                 event->init();
    423                 data->push_back(event);
    424                 return true;
    425             }));
    426     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
    427                                       bucketStartTimeNs, pullerManager);
    428     valueProducer.setBucketSize(60 * NS_PER_SEC);
    429 
    430     vector<shared_ptr<LogEvent>> allData;
    431     allData.clear();
    432     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
    433     event->write(tagId);
    434     event->write(100);
    435     event->init();
    436     allData.push_back(event);
    437 
    438     valueProducer.onDataPulled(allData);
    439     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    440 
    441     valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
    442     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    443     EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
    444     EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
    445 
    446     allData.clear();
    447     event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    448     event->write(tagId);
    449     event->write(150);
    450     event->init();
    451     allData.push_back(event);
    452     valueProducer.onDataPulled(allData);
    453     EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    454     EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
    455     EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
    456 }
    457 
    458 TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
    459     ValueMetric metric;
    460     metric.set_id(metricId);
    461     metric.set_bucket(ONE_MINUTE);
    462     metric.mutable_value_field()->set_field(tagId);
    463     metric.mutable_value_field()->add_child()->set_field(2);
    464     metric.set_condition(StringToId("SCREEN_ON"));
    465 
    466     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    467     shared_ptr<MockStatsPullerManager> pullerManager =
    468             make_shared<StrictMock<MockStatsPullerManager>>();
    469     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    470     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    471     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
    472             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    473                                 vector<std::shared_ptr<LogEvent>>* data) {
    474                 data->clear();
    475                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    476                 event->write(tagId);
    477                 event->write(100);
    478                 event->init();
    479                 data->push_back(event);
    480                 return true;
    481             }))
    482             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    483                                 vector<std::shared_ptr<LogEvent>>* data) {
    484                 data->clear();
    485                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    486                 event->write(tagId);
    487                 event->write(120);
    488                 event->init();
    489                 data->push_back(event);
    490                 return true;
    491             }));
    492     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
    493                                       bucketStartTimeNs, pullerManager);
    494     valueProducer.setBucketSize(60 * NS_PER_SEC);
    495     valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
    496 
    497     valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
    498     EXPECT_FALSE(valueProducer.mCondition);
    499 
    500     valueProducer.notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
    501     // Expect one full buckets already done and starting a partial bucket.
    502     EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
    503     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    504     EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
    505     EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
    506     EXPECT_FALSE(valueProducer.mCondition);
    507 }
    508 
    509 TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
    510     ValueMetric metric;
    511     metric.set_id(metricId);
    512     metric.set_bucket(ONE_MINUTE);
    513     metric.mutable_value_field()->set_field(tagId);
    514     metric.mutable_value_field()->add_child()->set_field(2);
    515 
    516     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    517     shared_ptr<MockStatsPullerManager> pullerManager =
    518             make_shared<StrictMock<MockStatsPullerManager>>();
    519 
    520     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
    521                                       bucketStartTimeNs, pullerManager);
    522     valueProducer.setBucketSize(60 * NS_PER_SEC);
    523 
    524     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    525     event1->write(1);
    526     event1->write(10);
    527     event1->init();
    528     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
    529     event2->write(1);
    530     event2->write(20);
    531     event2->init();
    532     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
    533     // has one slice
    534     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    535     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    536     EXPECT_EQ(10, curInterval.sum);
    537 
    538     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
    539 
    540     // has one slice
    541     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    542     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    543     EXPECT_EQ(30, curInterval.sum);
    544 
    545     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
    546     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    547     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    548     EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
    549 }
    550 
    551 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
    552     ValueMetric metric;
    553     metric.set_id(metricId);
    554     metric.set_bucket(ONE_MINUTE);
    555     metric.mutable_value_field()->set_field(tagId);
    556     metric.mutable_value_field()->add_child()->set_field(2);
    557 
    558     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    559     shared_ptr<MockStatsPullerManager> pullerManager =
    560             make_shared<StrictMock<MockStatsPullerManager>>();
    561 
    562     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
    563                                       bucketStartTimeNs, pullerManager);
    564     valueProducer.setBucketSize(60 * NS_PER_SEC);
    565 
    566     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    567     event1->write(1);
    568     event1->write(10);
    569     event1->init();
    570     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
    571     // has 1 slice
    572     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    573     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    574     EXPECT_EQ(false, curInterval.hasValue);
    575 
    576     valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
    577     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
    578     event2->write(1);
    579     event2->write(20);
    580     event2->init();
    581     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
    582 
    583     // has one slice
    584     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    585     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    586     EXPECT_EQ(20, curInterval.sum);
    587 
    588     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
    589     event3->write(1);
    590     event3->write(30);
    591     event3->init();
    592     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
    593 
    594     // has one slice
    595     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    596     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    597     EXPECT_EQ(50, curInterval.sum);
    598 
    599     valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
    600     shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
    601     event4->write(1);
    602     event4->write(40);
    603     event4->init();
    604     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
    605 
    606     // has one slice
    607     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    608     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    609     EXPECT_EQ(50, curInterval.sum);
    610 
    611     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
    612     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    613     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    614     EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().mValue);
    615 }
    616 
    617 TEST(ValueMetricProducerTest, TestAnomalyDetection) {
    618     sp<AlarmMonitor> alarmMonitor;
    619     Alert alert;
    620     alert.set_id(101);
    621     alert.set_metric_id(metricId);
    622     alert.set_trigger_if_sum_gt(130);
    623     alert.set_num_buckets(2);
    624     const int32_t refPeriodSec = 3;
    625     alert.set_refractory_period_secs(refPeriodSec);
    626 
    627     ValueMetric metric;
    628     metric.set_id(metricId);
    629     metric.set_bucket(ONE_MINUTE);
    630     metric.mutable_value_field()->set_field(tagId);
    631     metric.mutable_value_field()->add_child()->set_field(2);
    632 
    633     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    634     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    635                                       -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs);
    636     valueProducer.setBucketSize(60 * NS_PER_SEC);
    637 
    638     sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
    639 
    640 
    641     shared_ptr<LogEvent> event1
    642             = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
    643     event1->write(161);
    644     event1->write(10); // value of interest
    645     event1->init();
    646     shared_ptr<LogEvent> event2
    647             = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
    648     event2->write(162);
    649     event2->write(20); // value of interest
    650     event2->init();
    651     shared_ptr<LogEvent> event3
    652             = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
    653     event3->write(163);
    654     event3->write(130); // value of interest
    655     event3->init();
    656     shared_ptr<LogEvent> event4
    657             = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
    658     event4->write(35);
    659     event4->write(1); // value of interest
    660     event4->init();
    661     shared_ptr<LogEvent> event5
    662             = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
    663     event5->write(45);
    664     event5->write(150); // value of interest
    665     event5->init();
    666     shared_ptr<LogEvent> event6
    667             = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
    668     event6->write(25);
    669     event6->write(160); // value of interest
    670     event6->init();
    671 
    672     // Two events in bucket #0.
    673     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
    674     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
    675     // Value sum == 30 <= 130.
    676     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
    677 
    678     // One event in bucket #2. No alarm as bucket #0 is trashed out.
    679     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
    680     // Value sum == 130 <= 130.
    681     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
    682 
    683     // Three events in bucket #3.
    684     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
    685     // Anomaly at event 4 since Value sum == 131 > 130!
    686     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
    687             std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
    688     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
    689     // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
    690     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
    691             std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
    692 
    693     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
    694     // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
    695     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
    696             std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
    697 }
    698 
    699 // Test value metric no condition, the pull on bucket boundary come in time and too late
    700 TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
    701     ValueMetric metric;
    702     metric.set_id(metricId);
    703     metric.set_bucket(ONE_MINUTE);
    704     metric.mutable_value_field()->set_field(tagId);
    705     metric.mutable_value_field()->add_child()->set_field(2);
    706 
    707     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    708     shared_ptr<MockStatsPullerManager> pullerManager =
    709             make_shared<StrictMock<MockStatsPullerManager>>();
    710     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    711     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    712 
    713     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    714                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
    715     valueProducer.setBucketSize(60 * NS_PER_SEC);
    716 
    717     vector<shared_ptr<LogEvent>> allData;
    718     // pull 1
    719     allData.clear();
    720     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    721     event->write(tagId);
    722     event->write(11);
    723     event->init();
    724     allData.push_back(event);
    725 
    726     valueProducer.onDataPulled(allData);
    727     // has one slice
    728     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    729     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    730 
    731     // startUpdated:true tainted:0 sum:0 start:11
    732     EXPECT_EQ(true, curInterval.startUpdated);
    733     EXPECT_EQ(0, curInterval.tainted);
    734     EXPECT_EQ(0, curInterval.sum);
    735     EXPECT_EQ(11, curInterval.start);
    736     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    737 
    738     // pull 2 at correct time
    739     allData.clear();
    740     event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
    741     event->write(tagId);
    742     event->write(23);
    743     event->init();
    744     allData.push_back(event);
    745     valueProducer.onDataPulled(allData);
    746     // has one slice
    747     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    748     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    749     // tartUpdated:false tainted:0 sum:12
    750     EXPECT_EQ(true, curInterval.startUpdated);
    751     EXPECT_EQ(0, curInterval.tainted);
    752     EXPECT_EQ(0, curInterval.sum);
    753     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    754     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    755     EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
    756 
    757     // pull 3 come late.
    758     // The previous bucket gets closed with error. (Has start value 23, no ending)
    759     // Another bucket gets closed with error. (No start, but ending with 36)
    760     // The new bucket is back to normal.
    761     allData.clear();
    762     event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
    763     event->write(tagId);
    764     event->write(36);
    765     event->init();
    766     allData.push_back(event);
    767     valueProducer.onDataPulled(allData);
    768     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    769     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    770     // startUpdated:false tainted:0 sum:12
    771     EXPECT_EQ(true, curInterval.startUpdated);
    772     EXPECT_EQ(0, curInterval.tainted);
    773     EXPECT_EQ(36, curInterval.start);
    774     EXPECT_EQ(0, curInterval.sum);
    775     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
    776     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
    777     EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
    778 }
    779 
    780 /*
    781  * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
    782  * was delivered late.
    783  */
    784 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
    785     ValueMetric metric;
    786     metric.set_id(metricId);
    787     metric.set_bucket(ONE_MINUTE);
    788     metric.mutable_value_field()->set_field(tagId);
    789     metric.mutable_value_field()->add_child()->set_field(2);
    790     metric.set_condition(StringToId("SCREEN_ON"));
    791 
    792     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    793     shared_ptr<MockStatsPullerManager> pullerManager =
    794             make_shared<StrictMock<MockStatsPullerManager>>();
    795     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    796     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
    797 
    798     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
    799             // condition becomes true
    800             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    801                                 vector<std::shared_ptr<LogEvent>>* data) {
    802                 data->clear();
    803                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    804                 event->write(tagId);
    805                 event->write(100);
    806                 event->init();
    807                 data->push_back(event);
    808                 return true;
    809             }))
    810             // condition becomes false
    811             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    812                                 vector<std::shared_ptr<LogEvent>>* data) {
    813                 data->clear();
    814                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
    815                 event->write(tagId);
    816                 event->write(120);
    817                 event->init();
    818                 data->push_back(event);
    819                 return true;
    820             }));
    821 
    822     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
    823                                       bucketStartTimeNs, pullerManager);
    824     valueProducer.setBucketSize(60 * NS_PER_SEC);
    825     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
    826 
    827     // has one slice
    828     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    829     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    830     // startUpdated:false tainted:0 sum:0 start:100
    831     EXPECT_EQ(100, curInterval.start);
    832     EXPECT_EQ(true, curInterval.startUpdated);
    833     EXPECT_EQ(0, curInterval.tainted);
    834     EXPECT_EQ(0, curInterval.sum);
    835     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    836 
    837     // pull on bucket boundary come late, condition change happens before it
    838     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
    839     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    840     EXPECT_EQ(false, curInterval.startUpdated);
    841     EXPECT_EQ(1, curInterval.tainted);
    842     EXPECT_EQ(0, curInterval.sum);
    843     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    844 
    845     // Now the alarm is delivered.
    846     // since the condition turned to off before this pull finish, it has no effect
    847     vector<shared_ptr<LogEvent>> allData;
    848     allData.clear();
    849     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
    850     event->write(1);
    851     event->write(110);
    852     event->init();
    853     allData.push_back(event);
    854     valueProducer.onDataPulled(allData);
    855 
    856     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    857     EXPECT_EQ(false, curInterval.startUpdated);
    858     EXPECT_EQ(1, curInterval.tainted);
    859     EXPECT_EQ(0, curInterval.sum);
    860     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    861 }
    862 
    863 /*
    864  * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
    865  * change to false, and then true again. This is due to alarm delivered late.
    866  */
    867 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
    868     ValueMetric metric;
    869     metric.set_id(metricId);
    870     metric.set_bucket(ONE_MINUTE);
    871     metric.mutable_value_field()->set_field(tagId);
    872     metric.mutable_value_field()->add_child()->set_field(2);
    873     metric.set_condition(StringToId("SCREEN_ON"));
    874 
    875     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    876     shared_ptr<MockStatsPullerManager> pullerManager =
    877             make_shared<StrictMock<MockStatsPullerManager>>();
    878     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
    879     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
    880 
    881     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
    882             // condition becomes true
    883             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    884                                 vector<std::shared_ptr<LogEvent>>* data) {
    885                 data->clear();
    886                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    887                 event->write(tagId);
    888                 event->write(100);
    889                 event->init();
    890                 data->push_back(event);
    891                 return true;
    892             }))
    893             // condition becomes false
    894             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    895                                 vector<std::shared_ptr<LogEvent>>* data) {
    896                 data->clear();
    897                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
    898                 event->write(tagId);
    899                 event->write(120);
    900                 event->init();
    901                 data->push_back(event);
    902                 return true;
    903             }))
    904             // condition becomes true again
    905             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    906                                 vector<std::shared_ptr<LogEvent>>* data) {
    907                 data->clear();
    908                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
    909                 event->write(tagId);
    910                 event->write(130);
    911                 event->init();
    912                 data->push_back(event);
    913                 return true;
    914             }));
    915 
    916     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
    917                                       bucketStartTimeNs, pullerManager);
    918     valueProducer.setBucketSize(60 * NS_PER_SEC);
    919     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
    920 
    921     // has one slice
    922     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
    923     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    924     // startUpdated:false tainted:0 sum:0 start:100
    925     EXPECT_EQ(100, curInterval.start);
    926     EXPECT_EQ(true, curInterval.startUpdated);
    927     EXPECT_EQ(0, curInterval.tainted);
    928     EXPECT_EQ(0, curInterval.sum);
    929     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    930 
    931     // pull on bucket boundary come late, condition change happens before it
    932     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
    933     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    934     EXPECT_EQ(false, curInterval.startUpdated);
    935     EXPECT_EQ(1, curInterval.tainted);
    936     EXPECT_EQ(0, curInterval.sum);
    937     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    938 
    939     // condition changed to true again, before the pull alarm is delivered
    940     valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
    941     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    942     EXPECT_EQ(true, curInterval.startUpdated);
    943     EXPECT_EQ(130, curInterval.start);
    944     EXPECT_EQ(1, curInterval.tainted);
    945     EXPECT_EQ(0, curInterval.sum);
    946     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    947 
    948     // Now the alarm is delivered, but it is considered late, it has no effect
    949     vector<shared_ptr<LogEvent>> allData;
    950     allData.clear();
    951     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
    952     event->write(1);
    953     event->write(110);
    954     event->init();
    955     allData.push_back(event);
    956     valueProducer.onDataPulled(allData);
    957 
    958     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
    959     EXPECT_EQ(true, curInterval.startUpdated);
    960     EXPECT_EQ(130, curInterval.start);
    961     EXPECT_EQ(1, curInterval.tainted);
    962     EXPECT_EQ(0, curInterval.sum);
    963     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
    964 }
    965 
    966 /*
    967  * Test pulled event with non sliced condition. The pull on boundary come late because the puller is
    968  * very slow.
    969  */
    970 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3) {
    971     ValueMetric metric;
    972     metric.set_id(metricId);
    973     metric.set_bucket(ONE_MINUTE);
    974     metric.mutable_value_field()->set_field(tagId);
    975     metric.mutable_value_field()->add_child()->set_field(2);
    976     metric.set_condition(StringToId("SCREEN_ON"));
    977 
    978     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    979     shared_ptr<MockStatsPullerManager> pullerManager =
    980             make_shared<StrictMock<MockStatsPullerManager>>();
    981     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    982     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
    983 
    984     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
    985             // condition becomes true
    986             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    987                                 vector<std::shared_ptr<LogEvent>>* data) {
    988                 data->clear();
    989                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    990                 event->write(tagId);
    991                 event->write(100);
    992                 event->init();
    993                 data->push_back(event);
    994                 return true;
    995             }))
    996             // condition becomes false
    997             .WillOnce(Invoke([](int tagId, int64_t timeNs,
    998                                 vector<std::shared_ptr<LogEvent>>* data) {
    999                 data->clear();
   1000                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 20);
   1001                 event->write(tagId);
   1002                 event->write(120);
   1003                 event->init();
   1004                 data->push_back(event);
   1005                 return true;
   1006             }));
   1007 
   1008     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
   1009                                       bucketStartTimeNs, pullerManager);
   1010     valueProducer.setBucketSize(60 * NS_PER_SEC);
   1011     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
   1012 
   1013     // has one slice
   1014     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
   1015     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
   1016     // startUpdated:false tainted:0 sum:0 start:100
   1017     EXPECT_EQ(100, curInterval.start);
   1018     EXPECT_EQ(true, curInterval.startUpdated);
   1019     EXPECT_EQ(0, curInterval.tainted);
   1020     EXPECT_EQ(0, curInterval.sum);
   1021     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
   1022 
   1023     // pull on bucket boundary come late, condition change happens before it.
   1024     // But puller is very slow in this one, so the data come after bucket finish
   1025     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
   1026     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
   1027     EXPECT_EQ(false, curInterval.startUpdated);
   1028     EXPECT_EQ(1, curInterval.tainted);
   1029     EXPECT_EQ(0, curInterval.sum);
   1030     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
   1031 
   1032     // Alarm is delivered in time, but the pull is very slow, and pullers are called in order,
   1033     // so this one comes even later
   1034     vector<shared_ptr<LogEvent>> allData;
   1035     allData.clear();
   1036     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 30);
   1037     event->write(1);
   1038     event->write(110);
   1039     event->init();
   1040     allData.push_back(event);
   1041     valueProducer.onDataPulled(allData);
   1042 
   1043     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
   1044     EXPECT_EQ(false, curInterval.startUpdated);
   1045     EXPECT_EQ(1, curInterval.tainted);
   1046     EXPECT_EQ(0, curInterval.sum);
   1047     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
   1048 }
   1049 
   1050 }  // namespace statsd
   1051 }  // namespace os
   1052 }  // namespace android
   1053 #else
   1054 GTEST_LOG_(INFO) << "This test does nothing.\n";
   1055 #endif
   1056