blob: 087a612d19cedf698286e16247cff312010931a2 [file] [log] [blame]
Chenjie Yu6736c892017-11-09 10:50:09 -08001// Copyright (C) 2017 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Chenjie Yu6736c892017-11-09 10:50:09 -080015#include "src/metrics/ValueMetricProducer.h"
Yangster-macb8144812018-01-04 10:56:23 -080016#include "src/stats_log_util.h"
Yao Chenb3561512017-11-21 18:07:17 -080017#include "metrics_test_helper.h"
Yangster-mac94e197c2018-01-02 16:03:03 -080018#include "tests/statsd_test_util.h"
Chenjie Yu6736c892017-11-09 10:50:09 -080019
20#include <gmock/gmock.h>
21#include <gtest/gtest.h>
Bookatz6bf98252018-03-14 10:44:24 -070022#include <math.h>
Chenjie Yu6736c892017-11-09 10:50:09 -080023#include <stdio.h>
24#include <vector>
25
26using namespace testing;
27using android::sp;
Yao Chenb3561512017-11-21 18:07:17 -080028using std::make_shared;
Chenjie Yu6736c892017-11-09 10:50:09 -080029using std::set;
Yao Chenb3561512017-11-21 18:07:17 -080030using std::shared_ptr;
Chenjie Yu6736c892017-11-09 10:50:09 -080031using std::unordered_map;
32using std::vector;
Chenjie Yu6736c892017-11-09 10:50:09 -080033
34#ifdef __ANDROID__
35
36namespace android {
37namespace os {
38namespace statsd {
39
Yangster-mac94e197c2018-01-02 16:03:03 -080040const ConfigKey kConfigKey(0, 12345);
Chenjie Yua7259ab2017-12-10 08:31:05 -080041const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080042const int64_t metricId = 123;
Chenjie Yua7259ab2017-12-10 08:31:05 -080043const int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080044const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Chenjie Yua7259ab2017-12-10 08:31:05 -080045const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
46const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
47const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
Chenjie Yu6d370f42018-03-25 14:57:30 -070048const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
49const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
David Chen27785a82018-01-19 17:06:45 -080050const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
Chenjie Yua7259ab2017-12-10 08:31:05 -080051
Chenjie Yu6736c892017-11-09 10:50:09 -080052/*
53 * Tests pulled atoms with no conditions
54 */
55TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
Chenjie Yu6736c892017-11-09 10:50:09 -080056 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080057 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080058 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -080059 metric.mutable_value_field()->set_field(tagId);
60 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -080061
Chenjie Yu6736c892017-11-09 10:50:09 -080062 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.
Yao Chenb3561512017-11-21 18:07:17 -080065 shared_ptr<MockStatsPullerManager> pullerManager =
66 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -070067 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yu6736c892017-11-09 10:50:09 -080068 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
69
Yao Chenb3561512017-11-21 18:07:17 -080070 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -070071 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -080072 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yu6736c892017-11-09 10:50:09 -080073
74 vector<shared_ptr<LogEvent>> allData;
75 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080076 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
77 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -080078 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -080079 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;
yro59cc24d2018-02-13 20:17:32 -080086 valueProducer.setBucketSize(60 * NS_PER_SEC);
87
Chenjie Yua7259ab2017-12-10 08:31:05 -080088 // 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);
Chenjie Yuae63b0a2018-04-10 14:59:31 -070093 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6736c892017-11-09 10:50:09 -080094
95 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080096 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
97 event->write(tagId);
98 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -080099 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;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800105 // tartUpdated:false tainted:0 sum:12
106 EXPECT_EQ(true, curInterval.startUpdated);
107 EXPECT_EQ(0, curInterval.tainted);
108 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800109 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700110 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800111 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800112
113 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800114 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
115 event->write(tagId);
116 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800117 event->init();
118 allData.push_back(event);
119 valueProducer.onDataPulled(allData);
120 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
121 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800122 // startUpdated:false tainted:0 sum:12
123 EXPECT_EQ(true, curInterval.startUpdated);
124 EXPECT_EQ(0, curInterval.tainted);
125 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800126 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700127 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800128 EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800129}
130
131/*
132 * Test pulled event with non sliced condition.
133 */
134TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800135 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800136 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800137 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800138 metric.mutable_value_field()->set_field(tagId);
139 metric.mutable_value_field()->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800140 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800141
Chenjie Yu6736c892017-11-09 10:50:09 -0800142 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800143 shared_ptr<MockStatsPullerManager> pullerManager =
144 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700145 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yu6736c892017-11-09 10:50:09 -0800146 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
147
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700148 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
149 .WillOnce(Invoke([](int tagId, int64_t timeNs,
150 vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800151 data->clear();
152 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800153 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800154 event->write(100);
155 event->init();
156 data->push_back(event);
157 return true;
158 }))
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700159 .WillOnce(Invoke([](int tagId, int64_t timeNs,
160 vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800161 data->clear();
162 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800163 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800164 event->write(120);
165 event->init();
166 data->push_back(event);
167 return true;
168 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800169
Yao Chenb3561512017-11-21 18:07:17 -0800170 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700171 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800172 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800173 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800174
175 // has one slice
176 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
177 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800178 // startUpdated:false tainted:0 sum:0 start:100
179 EXPECT_EQ(100, curInterval.start);
180 EXPECT_EQ(true, curInterval.startUpdated);
181 EXPECT_EQ(0, curInterval.tainted);
182 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800183 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
184
185 vector<shared_ptr<LogEvent>> allData;
186 allData.clear();
187 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800188 event->write(1);
189 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800190 event->init();
191 allData.push_back(event);
192 valueProducer.onDataPulled(allData);
193
194 // has one slice
195 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
196 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800197 // startUpdated:false tainted:0 sum:0 start:110
198 EXPECT_EQ(110, curInterval.start);
Chenjie Yu6736c892017-11-09 10:50:09 -0800199 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
200 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
201 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
202
203 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
204
205 // has one slice
206 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
207 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800208 // startUpdated:false tainted:0 sum:0 start:110
209 EXPECT_EQ(10, curInterval.sum);
210 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yu6736c892017-11-09 10:50:09 -0800211}
212
David Chen27785a82018-01-19 17:06:45 -0800213TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
214 ValueMetric metric;
215 metric.set_id(metricId);
216 metric.set_bucket(ONE_MINUTE);
217 metric.mutable_value_field()->set_field(tagId);
218 metric.mutable_value_field()->add_child()->set_field(2);
219
220 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
221 shared_ptr<MockStatsPullerManager> pullerManager =
222 make_shared<StrictMock<MockStatsPullerManager>>();
223 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700224 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800225 valueProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800226
227 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
228 event1->write(1);
229 event1->write(10);
230 event1->init();
231 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
232 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
233
234 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
235 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700236 EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800237
238 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
239 event2->write(1);
240 event2->write(10);
241 event2->init();
242 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
243 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700244 EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800245
246 // Next value should create a new bucket.
247 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
248 event3->write(1);
249 event3->write(10);
250 event3->init();
251 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
252 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700253 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800254}
255
256TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
257 ValueMetric metric;
258 metric.set_id(metricId);
259 metric.set_bucket(ONE_MINUTE);
260 metric.mutable_value_field()->set_field(tagId);
261 metric.mutable_value_field()->add_child()->set_field(2);
262
263 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
264 shared_ptr<MockStatsPullerManager> pullerManager =
265 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700266 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
David Chen27785a82018-01-19 17:06:45 -0800267 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700268 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
269 .WillOnce(Invoke([](int tagId, int64_t timeNs,
270 vector<std::shared_ptr<LogEvent>>* data) {
David Chen27785a82018-01-19 17:06:45 -0800271 data->clear();
272 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
273 event->write(tagId);
274 event->write(120);
275 event->init();
276 data->push_back(event);
277 return true;
278 }));
279 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700280 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800281 valueProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800282
283 vector<shared_ptr<LogEvent>> allData;
284 allData.clear();
285 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
286 event->write(tagId);
287 event->write(100);
288 event->init();
289 allData.push_back(event);
290
291 valueProducer.onDataPulled(allData);
292 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
293
294 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
295 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700296 EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800297 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
298
299 allData.clear();
300 event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
301 event->write(tagId);
302 event->write(150);
303 event->init();
304 allData.push_back(event);
305 valueProducer.onDataPulled(allData);
306 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700307 EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800308 EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
309}
310
David Chen092a5a92018-05-15 17:50:32 -0700311TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
312 ValueMetric metric;
313 metric.set_id(metricId);
314 metric.set_bucket(ONE_MINUTE);
315 metric.mutable_value_field()->set_field(tagId);
316 metric.mutable_value_field()->add_child()->set_field(2);
317 metric.set_condition(StringToId("SCREEN_ON"));
318
319 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
320 shared_ptr<MockStatsPullerManager> pullerManager =
321 make_shared<StrictMock<MockStatsPullerManager>>();
322 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
323 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
324 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
325 .WillOnce(Invoke([](int tagId, int64_t timeNs,
326 vector<std::shared_ptr<LogEvent>>* data) {
327 data->clear();
328 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
329 event->write(tagId);
330 event->write(100);
331 event->init();
332 data->push_back(event);
333 return true;
334 }))
335 .WillOnce(Invoke([](int tagId, int64_t timeNs,
336 vector<std::shared_ptr<LogEvent>>* data) {
337 data->clear();
338 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
339 event->write(tagId);
340 event->write(120);
341 event->init();
342 data->push_back(event);
343 return true;
344 }));
345 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
346 bucketStartTimeNs, pullerManager);
347 valueProducer.setBucketSize(60 * NS_PER_SEC);
348 valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
349
350 valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
351 EXPECT_FALSE(valueProducer.mCondition);
352
353 valueProducer.notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
354 // Expect one full buckets already done and starting a partial bucket.
355 EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
356 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
357 EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
358 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
359 EXPECT_FALSE(valueProducer.mCondition);
360}
361
Chenjie Yu6736c892017-11-09 10:50:09 -0800362TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800363 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800364 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800365 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800366 metric.mutable_value_field()->set_field(tagId);
367 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800368
Chenjie Yu6736c892017-11-09 10:50:09 -0800369 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800370 shared_ptr<MockStatsPullerManager> pullerManager =
371 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800372
Yao Chenb3561512017-11-21 18:07:17 -0800373 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700374 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800375 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yu6736c892017-11-09 10:50:09 -0800376
377 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800378 event1->write(1);
379 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800380 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800381 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800382 event2->write(1);
383 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800384 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800385 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800386 // has one slice
387 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
388 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800389 EXPECT_EQ(10, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800390
Chenjie Yua7259ab2017-12-10 08:31:05 -0800391 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800392
393 // has one slice
394 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
395 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800396 EXPECT_EQ(30, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800397
Yangsterf2bee6f2017-11-29 12:01:05 -0800398 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800399 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
400 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
401 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
402}
403
Bookatzde1b55622017-12-14 18:38:27 -0800404TEST(ValueMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800405 sp<AlarmMonitor> alarmMonitor;
Bookatzde1b55622017-12-14 18:38:27 -0800406 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800407 alert.set_id(101);
408 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800409 alert.set_trigger_if_sum_gt(130);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800410 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800411 const int32_t refPeriodSec = 3;
412 alert.set_refractory_period_secs(refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800413
414 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800415 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800416 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800417 metric.mutable_value_field()->set_field(tagId);
418 metric.mutable_value_field()->add_child()->set_field(2);
Bookatzde1b55622017-12-14 18:38:27 -0800419
420 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
421 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700422 -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800423 valueProducer.setBucketSize(60 * NS_PER_SEC);
424
Yangster-mac932ecec2018-02-01 10:23:52 -0800425 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
Bookatzde1b55622017-12-14 18:38:27 -0800426
427
428 shared_ptr<LogEvent> event1
429 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
430 event1->write(161);
431 event1->write(10); // value of interest
432 event1->init();
433 shared_ptr<LogEvent> event2
434 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
435 event2->write(162);
436 event2->write(20); // value of interest
437 event2->init();
438 shared_ptr<LogEvent> event3
439 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
440 event3->write(163);
441 event3->write(130); // value of interest
442 event3->init();
443 shared_ptr<LogEvent> event4
444 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
445 event4->write(35);
446 event4->write(1); // value of interest
447 event4->init();
448 shared_ptr<LogEvent> event5
449 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
450 event5->write(45);
451 event5->write(150); // value of interest
452 event5->init();
453 shared_ptr<LogEvent> event6
454 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
455 event6->write(25);
456 event6->write(160); // value of interest
457 event6->init();
458
459 // Two events in bucket #0.
460 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
461 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz1bf94382018-01-04 11:43:20 -0800462 // Value sum == 30 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800463 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800464
465 // One event in bucket #2. No alarm as bucket #0 is trashed out.
466 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz1bf94382018-01-04 11:43:20 -0800467 // Value sum == 130 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800468 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800469
470 // Three events in bucket #3.
471 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
472 // Anomaly at event 4 since Value sum == 131 > 130!
Yangster-mac93694462018-01-22 20:49:31 -0800473 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700474 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800475 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
476 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Yangster-mac93694462018-01-22 20:49:31 -0800477 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700478 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800479
480 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
481 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Yangster-mac93694462018-01-22 20:49:31 -0800482 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700483 std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800484}
485
Chenjie Yu6d370f42018-03-25 14:57:30 -0700486// Test value metric no condition, the pull on bucket boundary come in time and too late
487TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
488 ValueMetric metric;
489 metric.set_id(metricId);
490 metric.set_bucket(ONE_MINUTE);
491 metric.mutable_value_field()->set_field(tagId);
492 metric.mutable_value_field()->add_child()->set_field(2);
493
494 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
495 shared_ptr<MockStatsPullerManager> pullerManager =
496 make_shared<StrictMock<MockStatsPullerManager>>();
497 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
498 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
499
500 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700501 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700502 valueProducer.setBucketSize(60 * NS_PER_SEC);
503
504 vector<shared_ptr<LogEvent>> allData;
505 // pull 1
506 allData.clear();
507 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
508 event->write(tagId);
509 event->write(11);
510 event->init();
511 allData.push_back(event);
512
513 valueProducer.onDataPulled(allData);
514 // has one slice
515 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
516 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yu6d370f42018-03-25 14:57:30 -0700517
518 // startUpdated:true tainted:0 sum:0 start:11
519 EXPECT_EQ(true, curInterval.startUpdated);
520 EXPECT_EQ(0, curInterval.tainted);
521 EXPECT_EQ(0, curInterval.sum);
522 EXPECT_EQ(11, curInterval.start);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700523 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700524
525 // pull 2 at correct time
526 allData.clear();
527 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
528 event->write(tagId);
529 event->write(23);
530 event->init();
531 allData.push_back(event);
532 valueProducer.onDataPulled(allData);
533 // has one slice
534 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
535 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
536 // tartUpdated:false tainted:0 sum:12
537 EXPECT_EQ(true, curInterval.startUpdated);
538 EXPECT_EQ(0, curInterval.tainted);
539 EXPECT_EQ(0, curInterval.sum);
540 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700541 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700542 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
543
544 // pull 3 come late.
545 // The previous bucket gets closed with error. (Has start value 23, no ending)
546 // Another bucket gets closed with error. (No start, but ending with 36)
547 // The new bucket is back to normal.
548 allData.clear();
549 event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
550 event->write(tagId);
551 event->write(36);
552 event->init();
553 allData.push_back(event);
554 valueProducer.onDataPulled(allData);
555 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
556 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
557 // startUpdated:false tainted:0 sum:12
558 EXPECT_EQ(true, curInterval.startUpdated);
559 EXPECT_EQ(0, curInterval.tainted);
560 EXPECT_EQ(36, curInterval.start);
561 EXPECT_EQ(0, curInterval.sum);
562 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700563 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
564 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700565}
566
567/*
568 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
569 * was delivered late.
570 */
571TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
572 ValueMetric metric;
573 metric.set_id(metricId);
574 metric.set_bucket(ONE_MINUTE);
575 metric.mutable_value_field()->set_field(tagId);
576 metric.mutable_value_field()->add_child()->set_field(2);
577 metric.set_condition(StringToId("SCREEN_ON"));
578
579 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
580 shared_ptr<MockStatsPullerManager> pullerManager =
581 make_shared<StrictMock<MockStatsPullerManager>>();
582 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
583 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
584
585 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
586 // condition becomes true
587 .WillOnce(Invoke([](int tagId, int64_t timeNs,
588 vector<std::shared_ptr<LogEvent>>* data) {
589 data->clear();
590 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
591 event->write(tagId);
592 event->write(100);
593 event->init();
594 data->push_back(event);
595 return true;
596 }))
597 // condition becomes false
598 .WillOnce(Invoke([](int tagId, int64_t timeNs,
599 vector<std::shared_ptr<LogEvent>>* data) {
600 data->clear();
601 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
602 event->write(tagId);
603 event->write(120);
604 event->init();
605 data->push_back(event);
606 return true;
607 }));
608
609 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700610 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700611 valueProducer.setBucketSize(60 * NS_PER_SEC);
612 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
613
614 // has one slice
615 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
616 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
617 // startUpdated:false tainted:0 sum:0 start:100
618 EXPECT_EQ(100, curInterval.start);
619 EXPECT_EQ(true, curInterval.startUpdated);
620 EXPECT_EQ(0, curInterval.tainted);
621 EXPECT_EQ(0, curInterval.sum);
622 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
623
624 // pull on bucket boundary come late, condition change happens before it
625 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
626 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
627 EXPECT_EQ(false, curInterval.startUpdated);
628 EXPECT_EQ(1, curInterval.tainted);
629 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700630 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700631
632 // Now the alarm is delivered.
633 // since the condition turned to off before this pull finish, it has no effect
634 vector<shared_ptr<LogEvent>> allData;
635 allData.clear();
636 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
637 event->write(1);
638 event->write(110);
639 event->init();
640 allData.push_back(event);
641 valueProducer.onDataPulled(allData);
642
643 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
644 EXPECT_EQ(false, curInterval.startUpdated);
645 EXPECT_EQ(1, curInterval.tainted);
646 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700647 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700648}
649
650/*
651 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
652 * change to false, and then true again. This is due to alarm delivered late.
653 */
654TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
655 ValueMetric metric;
656 metric.set_id(metricId);
657 metric.set_bucket(ONE_MINUTE);
658 metric.mutable_value_field()->set_field(tagId);
659 metric.mutable_value_field()->add_child()->set_field(2);
660 metric.set_condition(StringToId("SCREEN_ON"));
661
662 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
663 shared_ptr<MockStatsPullerManager> pullerManager =
664 make_shared<StrictMock<MockStatsPullerManager>>();
665 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
666 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
667
668 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
669 // condition becomes true
670 .WillOnce(Invoke([](int tagId, int64_t timeNs,
671 vector<std::shared_ptr<LogEvent>>* data) {
672 data->clear();
673 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
674 event->write(tagId);
675 event->write(100);
676 event->init();
677 data->push_back(event);
678 return true;
679 }))
680 // condition becomes false
681 .WillOnce(Invoke([](int tagId, int64_t timeNs,
682 vector<std::shared_ptr<LogEvent>>* data) {
683 data->clear();
684 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
685 event->write(tagId);
686 event->write(120);
687 event->init();
688 data->push_back(event);
689 return true;
690 }))
691 // condition becomes true again
692 .WillOnce(Invoke([](int tagId, int64_t timeNs,
693 vector<std::shared_ptr<LogEvent>>* data) {
694 data->clear();
695 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
696 event->write(tagId);
697 event->write(130);
698 event->init();
699 data->push_back(event);
700 return true;
701 }));
702
703 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700704 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700705 valueProducer.setBucketSize(60 * NS_PER_SEC);
706 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
707
708 // has one slice
709 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
710 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
711 // startUpdated:false tainted:0 sum:0 start:100
712 EXPECT_EQ(100, curInterval.start);
713 EXPECT_EQ(true, curInterval.startUpdated);
714 EXPECT_EQ(0, curInterval.tainted);
715 EXPECT_EQ(0, curInterval.sum);
716 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
717
718 // pull on bucket boundary come late, condition change happens before it
719 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
720 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
721 EXPECT_EQ(false, curInterval.startUpdated);
722 EXPECT_EQ(1, curInterval.tainted);
723 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700724 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700725
726 // condition changed to true again, before the pull alarm is delivered
727 valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
728 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
729 EXPECT_EQ(true, curInterval.startUpdated);
730 EXPECT_EQ(130, curInterval.start);
731 EXPECT_EQ(1, curInterval.tainted);
732 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700733 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700734
735 // Now the alarm is delivered, but it is considered late, it has no effect
736 vector<shared_ptr<LogEvent>> allData;
737 allData.clear();
738 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
739 event->write(1);
740 event->write(110);
741 event->init();
742 allData.push_back(event);
743 valueProducer.onDataPulled(allData);
744
745 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
746 EXPECT_EQ(true, curInterval.startUpdated);
747 EXPECT_EQ(130, curInterval.start);
748 EXPECT_EQ(1, curInterval.tainted);
749 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700750 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700751}
752
753/*
754 * Test pulled event with non sliced condition. The pull on boundary come late because the puller is
755 * very slow.
756 */
757TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3) {
758 ValueMetric metric;
759 metric.set_id(metricId);
760 metric.set_bucket(ONE_MINUTE);
761 metric.mutable_value_field()->set_field(tagId);
762 metric.mutable_value_field()->add_child()->set_field(2);
763 metric.set_condition(StringToId("SCREEN_ON"));
764
765 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
766 shared_ptr<MockStatsPullerManager> pullerManager =
767 make_shared<StrictMock<MockStatsPullerManager>>();
768 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
769 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
770
771 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
772 // condition becomes true
773 .WillOnce(Invoke([](int tagId, int64_t timeNs,
774 vector<std::shared_ptr<LogEvent>>* data) {
775 data->clear();
776 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
777 event->write(tagId);
778 event->write(100);
779 event->init();
780 data->push_back(event);
781 return true;
782 }))
783 // condition becomes false
784 .WillOnce(Invoke([](int tagId, int64_t timeNs,
785 vector<std::shared_ptr<LogEvent>>* data) {
786 data->clear();
787 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 20);
788 event->write(tagId);
789 event->write(120);
790 event->init();
791 data->push_back(event);
792 return true;
793 }));
794
795 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700796 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700797 valueProducer.setBucketSize(60 * NS_PER_SEC);
798 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
799
800 // has one slice
801 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
802 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
803 // startUpdated:false tainted:0 sum:0 start:100
804 EXPECT_EQ(100, curInterval.start);
805 EXPECT_EQ(true, curInterval.startUpdated);
806 EXPECT_EQ(0, curInterval.tainted);
807 EXPECT_EQ(0, curInterval.sum);
808 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
809
810 // pull on bucket boundary come late, condition change happens before it.
811 // But puller is very slow in this one, so the data come after bucket finish
812 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
813 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
814 EXPECT_EQ(false, curInterval.startUpdated);
815 EXPECT_EQ(1, curInterval.tainted);
816 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700817 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700818
819 // Alarm is delivered in time, but the pull is very slow, and pullers are called in order,
820 // so this one comes even later
821 vector<shared_ptr<LogEvent>> allData;
822 allData.clear();
823 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 30);
824 event->write(1);
825 event->write(110);
826 event->init();
827 allData.push_back(event);
828 valueProducer.onDataPulled(allData);
829
830 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
831 EXPECT_EQ(false, curInterval.startUpdated);
832 EXPECT_EQ(1, curInterval.tainted);
833 EXPECT_EQ(0, curInterval.sum);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700834 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700835}
836
Chenjie Yu6736c892017-11-09 10:50:09 -0800837} // namespace statsd
838} // namespace os
839} // namespace android
840#else
841GTEST_LOG_(INFO) << "This test does nothing.\n";
842#endif