blob: ee225dfc3b86faee7fd59cfffa68faecdfc54e12 [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;
Chenjie Yuc715b9e2018-10-19 07:52:12 -070050double epsilon = 0.001;
51
52/*
53 * Tests that the first bucket works correctly
54 */
55TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
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 int64_t startTimeBase = 11;
63
64 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
65 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
66
67 // statsd started long ago.
68 // The metric starts in the middle of the bucket
69 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
70 -1, startTimeBase, 22, pullerManager);
71
72 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
73 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
74 EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
75 valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
76 EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
77 valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
78}
Chenjie Yua7259ab2017-12-10 08:31:05 -080079
Chenjie Yu6736c892017-11-09 10:50:09 -080080/*
Chenjie Yue1361ed2018-07-23 17:33:09 -070081 * Tests that the first bucket works correctly
82 */
83TEST(ValueMetricProducerTest, TestFirstBucket) {
84 ValueMetric metric;
85 metric.set_id(metricId);
86 metric.set_bucket(ONE_MINUTE);
87 metric.mutable_value_field()->set_field(tagId);
88 metric.mutable_value_field()->add_child()->set_field(2);
89
90 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
91 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
92
93 // statsd started long ago.
94 // The metric starts in the middle of the bucket
95 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
96 -1, 5, 600 * NS_PER_SEC + NS_PER_SEC/2, pullerManager);
97
98 EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
99 EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
100 EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
101}
102
103/*
Chenjie Yu6736c892017-11-09 10:50:09 -0800104 * Tests pulled atoms with no conditions
105 */
Chenjie Yue1361ed2018-07-23 17:33:09 -0700106TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800107 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800108 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800109 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800110 metric.mutable_value_field()->set_field(tagId);
111 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800112
Chenjie Yu6736c892017-11-09 10:50:09 -0800113 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700114 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700115 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yu6736c892017-11-09 10:50:09 -0800116 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700117 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
118 .WillOnce(Invoke([](int tagId, int64_t timeNs,
119 vector<std::shared_ptr<LogEvent>>* data) {
120 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700121 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
Chenjie Yue1361ed2018-07-23 17:33:09 -0700122 event->write(tagId);
123 event->write(3);
124 event->init();
125 data->push_back(event);
126 return true;
127 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800128
Yao Chenb3561512017-11-21 18:07:17 -0800129 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700130 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800131
132 vector<shared_ptr<LogEvent>> allData;
133 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800134 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
135 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -0800136 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -0800137 event->init();
138 allData.push_back(event);
139
140 valueProducer.onDataPulled(allData);
141 // has one slice
142 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700143 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
yro59cc24d2018-02-13 20:17:32 -0800144
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700145 EXPECT_EQ(true, curInterval.hasBase);
146 EXPECT_EQ(11, curInterval.base.long_value);
147 EXPECT_EQ(true, curInterval.hasValue);
148 EXPECT_EQ(8, curInterval.value.long_value);
149 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6736c892017-11-09 10:50:09 -0800150
151 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800152 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
153 event->write(tagId);
154 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -0800155 event->init();
156 allData.push_back(event);
157 valueProducer.onDataPulled(allData);
158 // has one slice
159 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700160 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700161
162 EXPECT_EQ(true, curInterval.hasBase);
163 EXPECT_EQ(23, curInterval.base.long_value);
164 EXPECT_EQ(true, curInterval.hasValue);
165 EXPECT_EQ(12, curInterval.value.long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800166 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700167 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700168 EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800169
170 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800171 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
172 event->write(tagId);
173 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800174 event->init();
175 allData.push_back(event);
176 valueProducer.onDataPulled(allData);
177 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700178 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700179
180 EXPECT_EQ(true, curInterval.hasBase);
181 EXPECT_EQ(36, curInterval.base.long_value);
182 EXPECT_EQ(true, curInterval.hasValue);
183 EXPECT_EQ(13, curInterval.value.long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800184 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700185 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700186 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800187}
188
189/*
Chenjie Yu021e2532018-05-16 12:23:07 -0700190 * Tests pulled atoms with no conditions and take absolute value after reset
191 */
192TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
193 ValueMetric metric;
194 metric.set_id(metricId);
195 metric.set_bucket(ONE_MINUTE);
196 metric.mutable_value_field()->set_field(tagId);
197 metric.mutable_value_field()->add_child()->set_field(2);
198 metric.set_use_absolute_value_on_reset(true);
199
200 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700201 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu021e2532018-05-16 12:23:07 -0700202 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
203 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700204 EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(true));
Chenjie Yu021e2532018-05-16 12:23:07 -0700205
206 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
207 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu021e2532018-05-16 12:23:07 -0700208
209 vector<shared_ptr<LogEvent>> allData;
210 allData.clear();
211 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
212 event->write(tagId);
213 event->write(11);
214 event->init();
215 allData.push_back(event);
216
217 valueProducer.onDataPulled(allData);
218 // has one slice
219 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700220 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yu021e2532018-05-16 12:23:07 -0700221
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700222 EXPECT_EQ(true, curInterval.hasBase);
223 EXPECT_EQ(11, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700224 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700225 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
226
227 allData.clear();
228 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
229 event->write(tagId);
230 event->write(10);
231 event->init();
232 allData.push_back(event);
233 valueProducer.onDataPulled(allData);
234 // has one slice
235 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700236 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700237 EXPECT_EQ(true, curInterval.hasBase);
238 EXPECT_EQ(10, curInterval.base.long_value);
239 EXPECT_EQ(true, curInterval.hasValue);
240 EXPECT_EQ(10, curInterval.value.long_value);
241 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu021e2532018-05-16 12:23:07 -0700242
243 allData.clear();
244 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
245 event->write(tagId);
246 event->write(36);
247 event->init();
248 allData.push_back(event);
249 valueProducer.onDataPulled(allData);
250 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700251 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700252 EXPECT_EQ(true, curInterval.hasBase);
253 EXPECT_EQ(36, curInterval.base.long_value);
254 EXPECT_EQ(true, curInterval.hasValue);
255 EXPECT_EQ(26, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700256 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700257 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700258 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700259}
260
261/*
262 * Tests pulled atoms with no conditions and take zero value after reset
263 */
264TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
265 ValueMetric metric;
266 metric.set_id(metricId);
267 metric.set_bucket(ONE_MINUTE);
268 metric.mutable_value_field()->set_field(tagId);
269 metric.mutable_value_field()->add_child()->set_field(2);
270
271 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700272 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu021e2532018-05-16 12:23:07 -0700273 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
274 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700275 EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
Chenjie Yu021e2532018-05-16 12:23:07 -0700276
277 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
278 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu021e2532018-05-16 12:23:07 -0700279
280 vector<shared_ptr<LogEvent>> allData;
281 allData.clear();
282 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
283 event->write(tagId);
284 event->write(11);
285 event->init();
286 allData.push_back(event);
287
288 valueProducer.onDataPulled(allData);
289 // has one slice
290 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700291 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yu021e2532018-05-16 12:23:07 -0700292
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700293 EXPECT_EQ(true, curInterval.hasBase);
294 EXPECT_EQ(11, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700295 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700296 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
297
298 allData.clear();
299 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
300 event->write(tagId);
301 event->write(10);
302 event->init();
303 allData.push_back(event);
304 valueProducer.onDataPulled(allData);
305 // has one slice
306 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700307 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700308 EXPECT_EQ(true, curInterval.hasBase);
309 EXPECT_EQ(10, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700310 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700311 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
312
313 allData.clear();
314 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
315 event->write(tagId);
316 event->write(36);
317 event->init();
318 allData.push_back(event);
319 valueProducer.onDataPulled(allData);
320 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700321 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700322 EXPECT_EQ(true, curInterval.hasBase);
323 EXPECT_EQ(36, curInterval.base.long_value);
324 EXPECT_EQ(true, curInterval.hasValue);
325 EXPECT_EQ(26, curInterval.value.long_value);
326 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu021e2532018-05-16 12:23:07 -0700327}
328
329/*
Chenjie Yu6736c892017-11-09 10:50:09 -0800330 * Test pulled event with non sliced condition.
331 */
332TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800333 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800334 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800335 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800336 metric.mutable_value_field()->set_field(tagId);
337 metric.mutable_value_field()->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800338 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800339
Chenjie Yu6736c892017-11-09 10:50:09 -0800340 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700341 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700342 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yu6736c892017-11-09 10:50:09 -0800343 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
344
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700345 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700346 .WillOnce(Invoke([](int tagId, int64_t timeNs,
347 vector<std::shared_ptr<LogEvent>>* data) {
348 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700349 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800350 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800351 event->write(100);
352 event->init();
353 data->push_back(event);
354 return true;
355 }))
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700356 .WillOnce(Invoke([](int tagId, int64_t timeNs,
357 vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800358 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700359 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800360 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800361 event->write(120);
362 event->init();
363 data->push_back(event);
364 return true;
365 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800366
Yao Chenb3561512017-11-21 18:07:17 -0800367 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700368 bucketStartTimeNs, pullerManager);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800369 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800370
371 // has one slice
372 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700373 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700374 // startUpdated:false sum:0 start:100
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700375 EXPECT_EQ(true, curInterval.hasBase);
376 EXPECT_EQ(100, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700377 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800378 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
379
380 vector<shared_ptr<LogEvent>> allData;
381 allData.clear();
382 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800383 event->write(1);
384 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800385 event->init();
386 allData.push_back(event);
387 valueProducer.onDataPulled(allData);
388
389 // has one slice
390 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700391 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700392 EXPECT_EQ(true, curInterval.hasBase);
393 EXPECT_EQ(110, curInterval.base.long_value);
394 EXPECT_EQ(true, curInterval.hasValue);
395 EXPECT_EQ(10, curInterval.value.long_value);
396 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6736c892017-11-09 10:50:09 -0800397
398 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
399
400 // has one slice
401 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700402 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700403 EXPECT_EQ(true, curInterval.hasValue);
Chenjie Yua0f02242018-07-06 16:14:34 -0700404 EXPECT_EQ(10, curInterval.value.long_value);
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700405 EXPECT_EQ(false, curInterval.hasBase);
Chenjie Yu6736c892017-11-09 10:50:09 -0800406}
407
David Chen27785a82018-01-19 17:06:45 -0800408TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
409 ValueMetric metric;
410 metric.set_id(metricId);
411 metric.set_bucket(ONE_MINUTE);
412 metric.mutable_value_field()->set_field(tagId);
413 metric.mutable_value_field()->add_child()->set_field(2);
414
415 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700416 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
David Chen27785a82018-01-19 17:06:45 -0800417 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700418 bucketStartTimeNs, pullerManager);
David Chen27785a82018-01-19 17:06:45 -0800419
420 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
421 event1->write(1);
422 event1->write(10);
423 event1->init();
424 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
425 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
426
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700427 valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
David Chen27785a82018-01-19 17:06:45 -0800428 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700429 EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800430
431 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
432 event2->write(1);
433 event2->write(10);
434 event2->init();
435 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
436 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700437 EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800438
439 // Next value should create a new bucket.
440 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
441 event3->write(1);
442 event3->write(10);
443 event3->init();
444 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
445 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700446 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800447}
448
449TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
450 ValueMetric metric;
451 metric.set_id(metricId);
452 metric.set_bucket(ONE_MINUTE);
453 metric.mutable_value_field()->set_field(tagId);
454 metric.mutable_value_field()->add_child()->set_field(2);
455
456 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700457 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700458 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
David Chen27785a82018-01-19 17:06:45 -0800459 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700460 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700461 .WillOnce(Return(true))
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700462 .WillOnce(Invoke([](int tagId, int64_t timeNs,
463 vector<std::shared_ptr<LogEvent>>* data) {
David Chen27785a82018-01-19 17:06:45 -0800464 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700465 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
David Chen27785a82018-01-19 17:06:45 -0800466 event->write(tagId);
467 event->write(120);
468 event->init();
469 data->push_back(event);
470 return true;
471 }));
472 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700473 bucketStartTimeNs, pullerManager);
David Chen27785a82018-01-19 17:06:45 -0800474
475 vector<shared_ptr<LogEvent>> allData;
476 allData.clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700477 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
David Chen27785a82018-01-19 17:06:45 -0800478 event->write(tagId);
479 event->write(100);
480 event->init();
481 allData.push_back(event);
482
483 valueProducer.onDataPulled(allData);
484 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
485
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700486 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
David Chen27785a82018-01-19 17:06:45 -0800487 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700488 EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
Chenjie Yu32717c32018-10-20 23:54:48 -0700489 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
David Chen27785a82018-01-19 17:06:45 -0800490
491 allData.clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700492 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
David Chen27785a82018-01-19 17:06:45 -0800493 event->write(tagId);
494 event->write(150);
495 event->init();
496 allData.push_back(event);
497 valueProducer.onDataPulled(allData);
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700498 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
499 EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
Chenjie Yu32717c32018-10-20 23:54:48 -0700500 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
David Chen27785a82018-01-19 17:06:45 -0800501}
502
David Chen092a5a92018-05-15 17:50:32 -0700503TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
504 ValueMetric metric;
505 metric.set_id(metricId);
506 metric.set_bucket(ONE_MINUTE);
507 metric.mutable_value_field()->set_field(tagId);
508 metric.mutable_value_field()->add_child()->set_field(2);
509 metric.set_condition(StringToId("SCREEN_ON"));
510
511 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700512 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
David Chen092a5a92018-05-15 17:50:32 -0700513 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
514 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
515 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
516 .WillOnce(Invoke([](int tagId, int64_t timeNs,
517 vector<std::shared_ptr<LogEvent>>* data) {
518 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700519 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
David Chen092a5a92018-05-15 17:50:32 -0700520 event->write(tagId);
521 event->write(100);
522 event->init();
523 data->push_back(event);
524 return true;
525 }))
526 .WillOnce(Invoke([](int tagId, int64_t timeNs,
527 vector<std::shared_ptr<LogEvent>>* data) {
528 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700529 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
David Chen092a5a92018-05-15 17:50:32 -0700530 event->write(tagId);
531 event->write(120);
532 event->init();
533 data->push_back(event);
534 return true;
535 }));
536 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
537 bucketStartTimeNs, pullerManager);
David Chen092a5a92018-05-15 17:50:32 -0700538 valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
539
540 valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
541 EXPECT_FALSE(valueProducer.mCondition);
542
543 valueProducer.notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
544 // Expect one full buckets already done and starting a partial bucket.
545 EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
546 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
547 EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
Chenjie Yu32717c32018-10-20 23:54:48 -0700548 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
David Chen092a5a92018-05-15 17:50:32 -0700549 EXPECT_FALSE(valueProducer.mCondition);
550}
551
Chenjie Yu6736c892017-11-09 10:50:09 -0800552TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800553 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800554 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800555 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800556 metric.mutable_value_field()->set_field(tagId);
557 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800558
Chenjie Yu6736c892017-11-09 10:50:09 -0800559 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700560 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800561
Yao Chenb3561512017-11-21 18:07:17 -0800562 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700563 bucketStartTimeNs, pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800564
565 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800566 event1->write(1);
567 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800568 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800569 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800570 event2->write(1);
571 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800572 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800573 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800574 // has one slice
575 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700576 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700577 EXPECT_EQ(10, curInterval.value.long_value);
578 EXPECT_EQ(true, curInterval.hasValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800579
Chenjie Yua7259ab2017-12-10 08:31:05 -0800580 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800581
582 // has one slice
583 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700584 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700585 EXPECT_EQ(30, curInterval.value.long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800586
Yangsterf2bee6f2017-11-29 12:01:05 -0800587 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800588 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
589 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700590 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800591}
592
Chenjie Yu021e2532018-05-16 12:23:07 -0700593TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
594 ValueMetric metric;
595 metric.set_id(metricId);
596 metric.set_bucket(ONE_MINUTE);
597 metric.mutable_value_field()->set_field(tagId);
598 metric.mutable_value_field()->add_child()->set_field(2);
599
600 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700601 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu021e2532018-05-16 12:23:07 -0700602
603 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
604 bucketStartTimeNs, pullerManager);
Chenjie Yu021e2532018-05-16 12:23:07 -0700605
606 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
607 event1->write(1);
608 event1->write(10);
609 event1->init();
610 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
611 // has 1 slice
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700612 EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu021e2532018-05-16 12:23:07 -0700613
614 valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
615 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
616 event2->write(1);
617 event2->write(20);
618 event2->init();
619 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
620
621 // has one slice
622 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700623 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
624 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700625 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700626
627 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
628 event3->write(1);
629 event3->write(30);
630 event3->init();
631 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
632
633 // has one slice
634 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700635 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700636 EXPECT_EQ(50, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700637
638 valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
639 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
640 event4->write(1);
641 event4->write(40);
642 event4->init();
643 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
644
645 // has one slice
646 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700647 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700648 EXPECT_EQ(50, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700649
650 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
651 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
652 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700653 EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700654}
655
Bookatzde1b55622017-12-14 18:38:27 -0800656TEST(ValueMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800657 sp<AlarmMonitor> alarmMonitor;
Bookatzde1b55622017-12-14 18:38:27 -0800658 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800659 alert.set_id(101);
660 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800661 alert.set_trigger_if_sum_gt(130);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800662 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800663 const int32_t refPeriodSec = 3;
664 alert.set_refractory_period_secs(refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800665
666 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800667 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800668 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800669 metric.mutable_value_field()->set_field(tagId);
670 metric.mutable_value_field()->add_child()->set_field(2);
Bookatzde1b55622017-12-14 18:38:27 -0800671
672 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700673 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Bookatzde1b55622017-12-14 18:38:27 -0800674 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Chenjie Yue2219202018-06-08 10:07:51 -0700675 -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
676 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800677
Yangster-mac932ecec2018-02-01 10:23:52 -0800678 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
Bookatzde1b55622017-12-14 18:38:27 -0800679
680
681 shared_ptr<LogEvent> event1
682 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
683 event1->write(161);
684 event1->write(10); // value of interest
685 event1->init();
686 shared_ptr<LogEvent> event2
687 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
688 event2->write(162);
689 event2->write(20); // value of interest
690 event2->init();
691 shared_ptr<LogEvent> event3
692 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
693 event3->write(163);
694 event3->write(130); // value of interest
695 event3->init();
696 shared_ptr<LogEvent> event4
697 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
698 event4->write(35);
699 event4->write(1); // value of interest
700 event4->init();
701 shared_ptr<LogEvent> event5
702 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
703 event5->write(45);
704 event5->write(150); // value of interest
705 event5->init();
706 shared_ptr<LogEvent> event6
707 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
708 event6->write(25);
709 event6->write(160); // value of interest
710 event6->init();
711
712 // Two events in bucket #0.
713 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
714 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz1bf94382018-01-04 11:43:20 -0800715 // Value sum == 30 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800716 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800717
718 // One event in bucket #2. No alarm as bucket #0 is trashed out.
719 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz1bf94382018-01-04 11:43:20 -0800720 // Value sum == 130 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800721 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800722
723 // Three events in bucket #3.
724 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
725 // Anomaly at event 4 since Value sum == 131 > 130!
Yangster-mac93694462018-01-22 20:49:31 -0800726 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700727 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800728 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
729 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Yangster-mac93694462018-01-22 20:49:31 -0800730 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700731 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800732
733 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
734 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Yangster-mac93694462018-01-22 20:49:31 -0800735 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700736 std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800737}
738
Chenjie Yu6d370f42018-03-25 14:57:30 -0700739// Test value metric no condition, the pull on bucket boundary come in time and too late
740TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
741 ValueMetric metric;
742 metric.set_id(metricId);
743 metric.set_bucket(ONE_MINUTE);
744 metric.mutable_value_field()->set_field(tagId);
745 metric.mutable_value_field()->add_child()->set_field(2);
746
747 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700748 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700749 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
750 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700751 EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(true));
Chenjie Yu6d370f42018-03-25 14:57:30 -0700752
753 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700754 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700755
756 vector<shared_ptr<LogEvent>> allData;
757 // pull 1
758 allData.clear();
759 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
760 event->write(tagId);
761 event->write(11);
762 event->init();
763 allData.push_back(event);
764
765 valueProducer.onDataPulled(allData);
766 // has one slice
767 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700768 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yu6d370f42018-03-25 14:57:30 -0700769
Chenjie Yua0f02242018-07-06 16:14:34 -0700770 // startUpdated:true sum:0 start:11
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700771 EXPECT_EQ(true, curInterval.hasBase);
772 EXPECT_EQ(11, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700773 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700774 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700775
776 // pull 2 at correct time
777 allData.clear();
778 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
779 event->write(tagId);
780 event->write(23);
781 event->init();
782 allData.push_back(event);
783 valueProducer.onDataPulled(allData);
784 // has one slice
785 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700786 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700787 // tartUpdated:false sum:12
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700788 EXPECT_EQ(true, curInterval.hasBase);
789 EXPECT_EQ(23, curInterval.base.long_value);
790 EXPECT_EQ(true, curInterval.hasValue);
791 EXPECT_EQ(12, curInterval.value.long_value);
792 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700793
794 // pull 3 come late.
795 // The previous bucket gets closed with error. (Has start value 23, no ending)
796 // Another bucket gets closed with error. (No start, but ending with 36)
797 // The new bucket is back to normal.
798 allData.clear();
799 event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
800 event->write(tagId);
801 event->write(36);
802 event->init();
803 allData.push_back(event);
804 valueProducer.onDataPulled(allData);
805 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700806 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700807 // startUpdated:false sum:12
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700808 EXPECT_EQ(true, curInterval.hasBase);
809 EXPECT_EQ(36, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700810 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700811 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700812 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700813 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700814}
815
816/*
817 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
818 * was delivered late.
819 */
820TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
821 ValueMetric metric;
822 metric.set_id(metricId);
823 metric.set_bucket(ONE_MINUTE);
824 metric.mutable_value_field()->set_field(tagId);
825 metric.mutable_value_field()->add_child()->set_field(2);
826 metric.set_condition(StringToId("SCREEN_ON"));
827
828 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700829 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700830 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
831 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
832
833 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
834 // condition becomes true
835 .WillOnce(Invoke([](int tagId, int64_t timeNs,
836 vector<std::shared_ptr<LogEvent>>* data) {
837 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700838 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700839 event->write(tagId);
840 event->write(100);
841 event->init();
842 data->push_back(event);
843 return true;
844 }))
845 // condition becomes false
846 .WillOnce(Invoke([](int tagId, int64_t timeNs,
847 vector<std::shared_ptr<LogEvent>>* data) {
848 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700849 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700850 event->write(tagId);
851 event->write(120);
852 event->init();
853 data->push_back(event);
854 return true;
855 }));
856
857 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700858 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700859 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
860
861 // has one slice
862 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700863 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700864 EXPECT_EQ(true, curInterval.hasBase);
865 EXPECT_EQ(100, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700866 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700867 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
868
869 // pull on bucket boundary come late, condition change happens before it
870 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
Chenjie Yu32717c32018-10-20 23:54:48 -0700871 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700872 EXPECT_EQ(false, curInterval.hasBase);
873 EXPECT_EQ(true, curInterval.hasValue);
874 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700875 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700876
877 // Now the alarm is delivered.
878 // since the condition turned to off before this pull finish, it has no effect
879 vector<shared_ptr<LogEvent>> allData;
880 allData.clear();
881 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
882 event->write(1);
883 event->write(110);
884 event->init();
885 allData.push_back(event);
886 valueProducer.onDataPulled(allData);
887
Chenjie Yu32717c32018-10-20 23:54:48 -0700888 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700889 EXPECT_EQ(false, curInterval.hasBase);
890 EXPECT_EQ(true, curInterval.hasValue);
891 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700892 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700893}
894
895/*
896 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
897 * change to false, and then true again. This is due to alarm delivered late.
898 */
899TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
900 ValueMetric metric;
901 metric.set_id(metricId);
902 metric.set_bucket(ONE_MINUTE);
903 metric.mutable_value_field()->set_field(tagId);
904 metric.mutable_value_field()->add_child()->set_field(2);
905 metric.set_condition(StringToId("SCREEN_ON"));
906
907 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700908 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700909 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
910 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
911
912 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
913 // condition becomes true
914 .WillOnce(Invoke([](int tagId, int64_t timeNs,
915 vector<std::shared_ptr<LogEvent>>* data) {
916 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700917 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700918 event->write(tagId);
919 event->write(100);
920 event->init();
921 data->push_back(event);
922 return true;
923 }))
924 // condition becomes false
925 .WillOnce(Invoke([](int tagId, int64_t timeNs,
926 vector<std::shared_ptr<LogEvent>>* data) {
927 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700928 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700929 event->write(tagId);
930 event->write(120);
931 event->init();
932 data->push_back(event);
933 return true;
934 }))
935 // condition becomes true again
936 .WillOnce(Invoke([](int tagId, int64_t timeNs,
937 vector<std::shared_ptr<LogEvent>>* data) {
938 data->clear();
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700939 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700940 event->write(tagId);
941 event->write(130);
942 event->init();
943 data->push_back(event);
944 return true;
945 }));
946
947 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700948 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700949 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
950
951 // has one slice
952 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -0700953 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -0700954 // startUpdated:false sum:0 start:100
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700955 EXPECT_EQ(true, curInterval.hasBase);
956 EXPECT_EQ(100, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -0700957 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700958 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
959
960 // pull on bucket boundary come late, condition change happens before it
961 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
Chenjie Yu32717c32018-10-20 23:54:48 -0700962 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700963 EXPECT_EQ(false, curInterval.hasBase);
964 EXPECT_EQ(true, curInterval.hasValue);
965 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700966 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700967
968 // condition changed to true again, before the pull alarm is delivered
969 valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
Chenjie Yu32717c32018-10-20 23:54:48 -0700970 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700971 EXPECT_EQ(true, curInterval.hasBase);
972 EXPECT_EQ(130, curInterval.base.long_value);
973 EXPECT_EQ(true, curInterval.hasValue);
974 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700975 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700976
977 // Now the alarm is delivered, but it is considered late, it has no effect
978 vector<shared_ptr<LogEvent>> allData;
979 allData.clear();
980 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
981 event->write(1);
982 event->write(110);
983 event->init();
984 allData.push_back(event);
985 valueProducer.onDataPulled(allData);
986
Chenjie Yu32717c32018-10-20 23:54:48 -0700987 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700988 EXPECT_EQ(true, curInterval.hasBase);
989 EXPECT_EQ(130, curInterval.base.long_value);
990 EXPECT_EQ(true, curInterval.hasValue);
991 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700992 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700993}
994
Chenjie Yua0f02242018-07-06 16:14:34 -0700995TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
996 ValueMetric metric;
997 metric.set_id(metricId);
998 metric.set_bucket(ONE_MINUTE);
999 metric.mutable_value_field()->set_field(tagId);
1000 metric.mutable_value_field()->add_child()->set_field(2);
1001 metric.set_aggregation_type(ValueMetric::MIN);
1002
1003 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1004 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1005
1006 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1007 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001008
1009 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1010 event1->write(1);
1011 event1->write(10);
1012 event1->init();
1013 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1014 event2->write(1);
1015 event2->write(20);
1016 event2->init();
1017 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1018 // has one slice
1019 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001020 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001021 EXPECT_EQ(10, curInterval.value.long_value);
1022 EXPECT_EQ(true, curInterval.hasValue);
1023
1024 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1025
1026 // has one slice
1027 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001028 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001029 EXPECT_EQ(10, curInterval.value.long_value);
1030
1031 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1032 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1033 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001034 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -07001035}
1036
1037TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
1038 ValueMetric metric;
1039 metric.set_id(metricId);
1040 metric.set_bucket(ONE_MINUTE);
1041 metric.mutable_value_field()->set_field(tagId);
1042 metric.mutable_value_field()->add_child()->set_field(2);
1043 metric.set_aggregation_type(ValueMetric::MAX);
1044
1045 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1046 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1047
1048 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1049 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001050
1051 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1052 event1->write(1);
1053 event1->write(10);
1054 event1->init();
1055 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1056 event2->write(1);
1057 event2->write(20);
1058 event2->init();
1059 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1060 // has one slice
1061 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001062 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001063 EXPECT_EQ(10, curInterval.value.long_value);
1064 EXPECT_EQ(true, curInterval.hasValue);
1065
1066 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1067
1068 // has one slice
1069 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001070 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001071 EXPECT_EQ(20, curInterval.value.long_value);
1072
1073 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1074 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1075 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001076 EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -07001077}
1078
1079TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
1080 ValueMetric metric;
1081 metric.set_id(metricId);
1082 metric.set_bucket(ONE_MINUTE);
1083 metric.mutable_value_field()->set_field(tagId);
1084 metric.mutable_value_field()->add_child()->set_field(2);
1085 metric.set_aggregation_type(ValueMetric::AVG);
1086
1087 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1088 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1089
1090 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1091 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001092
1093 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1094 event1->write(1);
1095 event1->write(10);
1096 event1->init();
1097 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1098 event2->write(1);
1099 event2->write(15);
1100 event2->init();
1101 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1102 // has one slice
1103 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1104 ValueMetricProducer::Interval curInterval;
Chenjie Yu32717c32018-10-20 23:54:48 -07001105 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001106 EXPECT_EQ(10, curInterval.value.long_value);
1107 EXPECT_EQ(true, curInterval.hasValue);
1108 EXPECT_EQ(1, curInterval.sampleSize);
1109
1110 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1111
1112 // has one slice
1113 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001114 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001115 EXPECT_EQ(25, curInterval.value.long_value);
1116 EXPECT_EQ(2, curInterval.sampleSize);
1117
1118 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1119 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1120 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001121 EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value - 12.5) < epsilon);
Chenjie Yua0f02242018-07-06 16:14:34 -07001122}
1123
1124TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
1125 ValueMetric metric;
1126 metric.set_id(metricId);
1127 metric.set_bucket(ONE_MINUTE);
1128 metric.mutable_value_field()->set_field(tagId);
1129 metric.mutable_value_field()->add_child()->set_field(2);
1130 metric.set_aggregation_type(ValueMetric::SUM);
1131
1132 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1133 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1134
1135 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1136 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001137
1138 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1139 event1->write(1);
1140 event1->write(10);
1141 event1->init();
1142 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1143 event2->write(1);
1144 event2->write(15);
1145 event2->init();
1146 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1147 // has one slice
1148 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001149 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001150 EXPECT_EQ(10, curInterval.value.long_value);
1151 EXPECT_EQ(true, curInterval.hasValue);
1152
1153 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1154
1155 // has one slice
1156 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001157 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yua0f02242018-07-06 16:14:34 -07001158 EXPECT_EQ(25, curInterval.value.long_value);
1159
1160 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1161 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1162 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001163 EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -07001164}
1165
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001166TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
Chenjie Yua0f02242018-07-06 16:14:34 -07001167 ValueMetric metric;
1168 metric.set_id(metricId);
1169 metric.set_bucket(ONE_MINUTE);
1170 metric.mutable_value_field()->set_field(tagId);
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001171 metric.mutable_value_field()->add_child()->set_field(2);
1172 metric.set_aggregation_type(ValueMetric::MIN);
1173 metric.set_use_diff(true);
Chenjie Yua0f02242018-07-06 16:14:34 -07001174
1175 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yua0f02242018-07-06 16:14:34 -07001176 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1177
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001178 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Chenjie Yua0f02242018-07-06 16:14:34 -07001179 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001180
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001181 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1182 event1->write(1);
1183 event1->write(10);
1184 event1->init();
1185 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
1186 event2->write(1);
1187 event2->write(15);
1188 event2->init();
1189 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1190 // has one slice
Chenjie Yua0f02242018-07-06 16:14:34 -07001191 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001192 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001193 EXPECT_EQ(true, curInterval.hasBase);
1194 EXPECT_EQ(10, curInterval.base.long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -07001195 EXPECT_EQ(false, curInterval.hasValue);
1196
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001197 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yua0f02242018-07-06 16:14:34 -07001198
1199 // has one slice
1200 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001201 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001202 EXPECT_EQ(true, curInterval.hasValue);
1203 EXPECT_EQ(5, curInterval.value.long_value);
1204
1205 // no change in data.
1206 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
1207 event3->write(1);
1208 event3->write(15);
1209 event3->init();
1210 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
1211 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001212 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001213 EXPECT_EQ(true, curInterval.hasBase);
1214 EXPECT_EQ(15, curInterval.base.long_value);
1215 EXPECT_EQ(true, curInterval.hasValue);
1216
1217 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
1218 event4->write(1);
1219 event4->write(15);
1220 event4->init();
1221 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
1222 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001223 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
Chenjie Yuc715b9e2018-10-19 07:52:12 -07001224 EXPECT_EQ(true, curInterval.hasBase);
1225 EXPECT_EQ(15, curInterval.base.long_value);
1226 EXPECT_EQ(true, curInterval.hasValue);
Chenjie Yua0f02242018-07-06 16:14:34 -07001227
1228 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1229 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1230 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yu32717c32018-10-20 23:54:48 -07001231 EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
Chenjie Yua0f02242018-07-06 16:14:34 -07001232}
1233
Chenjie Yu6736c892017-11-09 10:50:09 -08001234} // namespace statsd
1235} // namespace os
1236} // namespace android
1237#else
1238GTEST_LOG_(INFO) << "This test does nothing.\n";
1239#endif