blob: 57aab971eaaa5b45f549356bcf555ec4146e6c59 [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/*
Chenjie Yue1361ed2018-07-23 17:33:09 -070053 * Tests that the first bucket works correctly
54 */
55TEST(ValueMetricProducerTest, TestFirstBucket) {
56 ValueMetric metric;
57 metric.set_id(metricId);
58 metric.set_bucket(ONE_MINUTE);
59 metric.mutable_value_field()->set_field(tagId);
60 metric.mutable_value_field()->add_child()->set_field(2);
61
62 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
63 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
64
65 // statsd started long ago.
66 // The metric starts in the middle of the bucket
67 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
68 -1, 5, 600 * NS_PER_SEC + NS_PER_SEC/2, pullerManager);
69
70 EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
71 EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
72 EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
73}
74
75/*
Chenjie Yu6736c892017-11-09 10:50:09 -080076 * Tests pulled atoms with no conditions
77 */
Chenjie Yue1361ed2018-07-23 17:33:09 -070078TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -080079 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080080 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080081 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -080082 metric.mutable_value_field()->set_field(tagId);
83 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -080084
Chenjie Yu6736c892017-11-09 10:50:09 -080085 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -070086 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -070087 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yu6736c892017-11-09 10:50:09 -080088 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yue1361ed2018-07-23 17:33:09 -070089 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
90 .WillOnce(Invoke([](int tagId, int64_t timeNs,
91 vector<std::shared_ptr<LogEvent>>* data) {
92 data->clear();
93 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
94 event->write(tagId);
95 event->write(3);
96 event->init();
97 data->push_back(event);
98 return true;
99 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800100
Yao Chenb3561512017-11-21 18:07:17 -0800101 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700102 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800103
104 vector<shared_ptr<LogEvent>> allData;
105 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800106 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
107 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -0800108 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -0800109 event->init();
110 allData.push_back(event);
111
112 valueProducer.onDataPulled(allData);
113 // has one slice
114 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
115 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
yro59cc24d2018-02-13 20:17:32 -0800116
Chenjie Yua0f02242018-07-06 16:14:34 -0700117 // startUpdated:true sum:0 start:11
Chenjie Yua7259ab2017-12-10 08:31:05 -0800118 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700119 EXPECT_EQ(false, curInterval.hasValue);
120 EXPECT_EQ(11, curInterval.start.long_value);
Chenjie Yue1361ed2018-07-23 17:33:09 -0700121 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
122 EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6736c892017-11-09 10:50:09 -0800123
124 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800125 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
126 event->write(tagId);
127 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -0800128 event->init();
129 allData.push_back(event);
130 valueProducer.onDataPulled(allData);
131 // has one slice
132 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
133 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700134 // tartUpdated:false sum:12
Chenjie Yua7259ab2017-12-10 08:31:05 -0800135 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yue1361ed2018-07-23 17:33:09 -0700136 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800137 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700138 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700139 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6736c892017-11-09 10:50:09 -0800140
141 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800142 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
143 event->write(tagId);
144 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800145 event->init();
146 allData.push_back(event);
147 valueProducer.onDataPulled(allData);
148 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
149 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700150 // startUpdated:false sum:12
Chenjie Yua7259ab2017-12-10 08:31:05 -0800151 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yue1361ed2018-07-23 17:33:09 -0700152 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800153 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700154 EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700155 EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6736c892017-11-09 10:50:09 -0800156}
157
158/*
Chenjie Yu021e2532018-05-16 12:23:07 -0700159 * Tests pulled atoms with no conditions and take absolute value after reset
160 */
161TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
162 ValueMetric metric;
163 metric.set_id(metricId);
164 metric.set_bucket(ONE_MINUTE);
165 metric.mutable_value_field()->set_field(tagId);
166 metric.mutable_value_field()->add_child()->set_field(2);
167 metric.set_use_absolute_value_on_reset(true);
168
169 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700170 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu021e2532018-05-16 12:23:07 -0700171 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
172 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700173 EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
Chenjie Yu021e2532018-05-16 12:23:07 -0700174
175 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
176 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu021e2532018-05-16 12:23:07 -0700177
178 vector<shared_ptr<LogEvent>> allData;
179 allData.clear();
180 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
181 event->write(tagId);
182 event->write(11);
183 event->init();
184 allData.push_back(event);
185
186 valueProducer.onDataPulled(allData);
187 // has one slice
188 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
189 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yu021e2532018-05-16 12:23:07 -0700190
191 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700192 EXPECT_EQ(false, curInterval.hasValue);
193 EXPECT_EQ(11, curInterval.start.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700194 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
195
196 allData.clear();
197 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
198 event->write(tagId);
199 event->write(10);
200 event->init();
201 allData.push_back(event);
202 valueProducer.onDataPulled(allData);
203 // has one slice
204 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
205 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
206 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700207 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700208 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
209 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700210 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu021e2532018-05-16 12:23:07 -0700211
212 allData.clear();
213 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
214 event->write(tagId);
215 event->write(36);
216 event->init();
217 allData.push_back(event);
218 valueProducer.onDataPulled(allData);
219 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
220 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
221 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700222 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700223 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
224 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700225 EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu021e2532018-05-16 12:23:07 -0700226}
227
228/*
229 * Tests pulled atoms with no conditions and take zero value after reset
230 */
231TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
232 ValueMetric metric;
233 metric.set_id(metricId);
234 metric.set_bucket(ONE_MINUTE);
235 metric.mutable_value_field()->set_field(tagId);
236 metric.mutable_value_field()->add_child()->set_field(2);
237
238 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700239 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu021e2532018-05-16 12:23:07 -0700240 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
241 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700242 EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
Chenjie Yu021e2532018-05-16 12:23:07 -0700243
244 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
245 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu021e2532018-05-16 12:23:07 -0700246
247 vector<shared_ptr<LogEvent>> allData;
248 allData.clear();
249 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
250 event->write(tagId);
251 event->write(11);
252 event->init();
253 allData.push_back(event);
254
255 valueProducer.onDataPulled(allData);
256 // has one slice
257 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
258 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yu021e2532018-05-16 12:23:07 -0700259
260 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700261 EXPECT_EQ(false, curInterval.hasValue);
262 EXPECT_EQ(11, curInterval.start.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700263 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
264
265 allData.clear();
266 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
267 event->write(tagId);
268 event->write(10);
269 event->init();
270 allData.push_back(event);
271 valueProducer.onDataPulled(allData);
272 // has one slice
273 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
274 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
275 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700276 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700277 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
278
279 allData.clear();
280 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
281 event->write(tagId);
282 event->write(36);
283 event->init();
284 allData.push_back(event);
285 valueProducer.onDataPulled(allData);
286 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
287 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
288 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700289 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu021e2532018-05-16 12:23:07 -0700290 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
291 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700292 EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu021e2532018-05-16 12:23:07 -0700293}
294
295/*
Chenjie Yu6736c892017-11-09 10:50:09 -0800296 * Test pulled event with non sliced condition.
297 */
298TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800299 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800300 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800301 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800302 metric.mutable_value_field()->set_field(tagId);
303 metric.mutable_value_field()->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800304 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800305
Chenjie Yu6736c892017-11-09 10:50:09 -0800306 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700307 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700308 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yu6736c892017-11-09 10:50:09 -0800309 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
310
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700311 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700312 // should not take effect
313 .WillOnce(Invoke([](int tagId, int64_t timeNs,
314 vector<std::shared_ptr<LogEvent>>* data) {
315 data->clear();
316 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
317 event->write(tagId);
318 event->write(3);
319 event->init();
320 data->push_back(event);
321 return true;
322 }))
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700323 .WillOnce(Invoke([](int tagId, int64_t timeNs,
324 vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800325 data->clear();
326 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800327 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800328 event->write(100);
329 event->init();
330 data->push_back(event);
331 return true;
332 }))
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700333 .WillOnce(Invoke([](int tagId, int64_t timeNs,
334 vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800335 data->clear();
336 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800337 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800338 event->write(120);
339 event->init();
340 data->push_back(event);
341 return true;
342 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800343
Yao Chenb3561512017-11-21 18:07:17 -0800344 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700345 bucketStartTimeNs, pullerManager);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800346 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800347
348 // has one slice
349 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
350 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700351 // startUpdated:false sum:0 start:100
352 EXPECT_EQ(100, curInterval.start.long_value);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800353 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700354 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800355 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
356
357 vector<shared_ptr<LogEvent>> allData;
358 allData.clear();
359 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800360 event->write(1);
361 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800362 event->init();
363 allData.push_back(event);
364 valueProducer.onDataPulled(allData);
365
366 // has one slice
367 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
368 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700369 // startUpdated:false sum:0 start:110
370 EXPECT_EQ(110, curInterval.start.long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800371 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
372 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700373 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6736c892017-11-09 10:50:09 -0800374
375 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
376
377 // has one slice
378 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
379 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700380 // startUpdated:false sum:0 start:110
381 EXPECT_EQ(10, curInterval.value.long_value);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800382 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yu6736c892017-11-09 10:50:09 -0800383}
384
David Chen27785a82018-01-19 17:06:45 -0800385TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
386 ValueMetric metric;
387 metric.set_id(metricId);
388 metric.set_bucket(ONE_MINUTE);
389 metric.mutable_value_field()->set_field(tagId);
390 metric.mutable_value_field()->add_child()->set_field(2);
391
392 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700393 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
David Chen27785a82018-01-19 17:06:45 -0800394 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700395 bucketStartTimeNs, pullerManager);
David Chen27785a82018-01-19 17:06:45 -0800396
397 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
398 event1->write(1);
399 event1->write(10);
400 event1->init();
401 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
402 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
403
404 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
405 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700406 EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800407
408 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
409 event2->write(1);
410 event2->write(10);
411 event2->init();
412 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
413 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700414 EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800415
416 // Next value should create a new bucket.
417 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
418 event3->write(1);
419 event3->write(10);
420 event3->init();
421 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
422 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700423 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
David Chen27785a82018-01-19 17:06:45 -0800424}
425
426TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
427 ValueMetric metric;
428 metric.set_id(metricId);
429 metric.set_bucket(ONE_MINUTE);
430 metric.mutable_value_field()->set_field(tagId);
431 metric.mutable_value_field()->add_child()->set_field(2);
432
433 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700434 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700435 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
David Chen27785a82018-01-19 17:06:45 -0800436 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700437 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700438 .WillOnce(Return(false))
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700439 .WillOnce(Invoke([](int tagId, int64_t timeNs,
440 vector<std::shared_ptr<LogEvent>>* data) {
David Chen27785a82018-01-19 17:06:45 -0800441 data->clear();
442 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
443 event->write(tagId);
444 event->write(120);
445 event->init();
446 data->push_back(event);
447 return true;
448 }));
449 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700450 bucketStartTimeNs, pullerManager);
David Chen27785a82018-01-19 17:06:45 -0800451
452 vector<shared_ptr<LogEvent>> allData;
453 allData.clear();
454 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
455 event->write(tagId);
456 event->write(100);
457 event->init();
458 allData.push_back(event);
459
460 valueProducer.onDataPulled(allData);
461 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
462
463 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
464 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700465 EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
Chenjie Yua0f02242018-07-06 16:14:34 -0700466 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
David Chen27785a82018-01-19 17:06:45 -0800467
468 allData.clear();
469 event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
470 event->write(tagId);
471 event->write(150);
472 event->init();
473 allData.push_back(event);
474 valueProducer.onDataPulled(allData);
475 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700476 EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
Chenjie Yua0f02242018-07-06 16:14:34 -0700477 EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValueLong);
David Chen27785a82018-01-19 17:06:45 -0800478}
479
David Chen092a5a92018-05-15 17:50:32 -0700480TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
481 ValueMetric metric;
482 metric.set_id(metricId);
483 metric.set_bucket(ONE_MINUTE);
484 metric.mutable_value_field()->set_field(tagId);
485 metric.mutable_value_field()->add_child()->set_field(2);
486 metric.set_condition(StringToId("SCREEN_ON"));
487
488 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700489 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
David Chen092a5a92018-05-15 17:50:32 -0700490 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
491 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
492 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700493 .WillOnce(Return(false))
David Chen092a5a92018-05-15 17:50:32 -0700494 .WillOnce(Invoke([](int tagId, int64_t timeNs,
495 vector<std::shared_ptr<LogEvent>>* data) {
496 data->clear();
497 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
498 event->write(tagId);
499 event->write(100);
500 event->init();
501 data->push_back(event);
502 return true;
503 }))
504 .WillOnce(Invoke([](int tagId, int64_t timeNs,
505 vector<std::shared_ptr<LogEvent>>* data) {
506 data->clear();
507 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
508 event->write(tagId);
509 event->write(120);
510 event->init();
511 data->push_back(event);
512 return true;
513 }));
514 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
515 bucketStartTimeNs, pullerManager);
David Chen092a5a92018-05-15 17:50:32 -0700516 valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
517
518 valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
519 EXPECT_FALSE(valueProducer.mCondition);
520
521 valueProducer.notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
522 // Expect one full buckets already done and starting a partial bucket.
523 EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
524 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
525 EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
Chenjie Yua0f02242018-07-06 16:14:34 -0700526 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
David Chen092a5a92018-05-15 17:50:32 -0700527 EXPECT_FALSE(valueProducer.mCondition);
528}
529
Chenjie Yu6736c892017-11-09 10:50:09 -0800530TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800531 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800532 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800533 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800534 metric.mutable_value_field()->set_field(tagId);
535 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800536
Chenjie Yu6736c892017-11-09 10:50:09 -0800537 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700538 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800539
Yao Chenb3561512017-11-21 18:07:17 -0800540 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700541 bucketStartTimeNs, pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800542
543 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800544 event1->write(1);
545 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800546 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800547 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800548 event2->write(1);
549 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800550 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800551 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800552 // has one slice
553 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
554 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700555 EXPECT_EQ(10, curInterval.value.long_value);
556 EXPECT_EQ(true, curInterval.hasValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800557
Chenjie Yua7259ab2017-12-10 08:31:05 -0800558 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800559
560 // has one slice
561 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
562 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700563 EXPECT_EQ(30, curInterval.value.long_value);
Chenjie Yu6736c892017-11-09 10:50:09 -0800564
Yangsterf2bee6f2017-11-29 12:01:05 -0800565 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800566 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
567 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700568 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6736c892017-11-09 10:50:09 -0800569}
570
Chenjie Yu021e2532018-05-16 12:23:07 -0700571TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
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
578 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700579 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu021e2532018-05-16 12:23:07 -0700580
581 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
582 bucketStartTimeNs, pullerManager);
Chenjie Yu021e2532018-05-16 12:23:07 -0700583
584 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
585 event1->write(1);
586 event1->write(10);
587 event1->init();
588 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
589 // has 1 slice
590 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
591 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
592 EXPECT_EQ(false, curInterval.hasValue);
593
594 valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
595 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
596 event2->write(1);
597 event2->write(20);
598 event2->init();
599 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
600
601 // has one slice
602 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
603 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700604 EXPECT_EQ(20, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700605
606 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
607 event3->write(1);
608 event3->write(30);
609 event3->init();
610 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
611
612 // has one slice
613 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
614 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700615 EXPECT_EQ(50, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700616
617 valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
618 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
619 event4->write(1);
620 event4->write(40);
621 event4->init();
622 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
623
624 // has one slice
625 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
626 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700627 EXPECT_EQ(50, curInterval.value.long_value);
Chenjie Yu021e2532018-05-16 12:23:07 -0700628
629 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
630 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
631 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700632 EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu021e2532018-05-16 12:23:07 -0700633}
634
Bookatzde1b55622017-12-14 18:38:27 -0800635TEST(ValueMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800636 sp<AlarmMonitor> alarmMonitor;
Bookatzde1b55622017-12-14 18:38:27 -0800637 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800638 alert.set_id(101);
639 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800640 alert.set_trigger_if_sum_gt(130);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800641 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800642 const int32_t refPeriodSec = 3;
643 alert.set_refractory_period_secs(refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800644
645 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800646 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800647 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800648 metric.mutable_value_field()->set_field(tagId);
649 metric.mutable_value_field()->add_child()->set_field(2);
Bookatzde1b55622017-12-14 18:38:27 -0800650
651 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700652 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Bookatzde1b55622017-12-14 18:38:27 -0800653 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Chenjie Yue2219202018-06-08 10:07:51 -0700654 -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
655 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800656
Yangster-mac932ecec2018-02-01 10:23:52 -0800657 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
Bookatzde1b55622017-12-14 18:38:27 -0800658
659
660 shared_ptr<LogEvent> event1
661 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
662 event1->write(161);
663 event1->write(10); // value of interest
664 event1->init();
665 shared_ptr<LogEvent> event2
666 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
667 event2->write(162);
668 event2->write(20); // value of interest
669 event2->init();
670 shared_ptr<LogEvent> event3
671 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
672 event3->write(163);
673 event3->write(130); // value of interest
674 event3->init();
675 shared_ptr<LogEvent> event4
676 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
677 event4->write(35);
678 event4->write(1); // value of interest
679 event4->init();
680 shared_ptr<LogEvent> event5
681 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
682 event5->write(45);
683 event5->write(150); // value of interest
684 event5->init();
685 shared_ptr<LogEvent> event6
686 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
687 event6->write(25);
688 event6->write(160); // value of interest
689 event6->init();
690
691 // Two events in bucket #0.
692 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
693 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz1bf94382018-01-04 11:43:20 -0800694 // Value sum == 30 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800695 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800696
697 // One event in bucket #2. No alarm as bucket #0 is trashed out.
698 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz1bf94382018-01-04 11:43:20 -0800699 // Value sum == 130 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800700 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800701
702 // Three events in bucket #3.
703 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
704 // Anomaly at event 4 since Value sum == 131 > 130!
Yangster-mac93694462018-01-22 20:49:31 -0800705 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700706 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800707 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
708 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Yangster-mac93694462018-01-22 20:49:31 -0800709 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700710 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800711
712 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
713 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Yangster-mac93694462018-01-22 20:49:31 -0800714 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700715 std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800716}
717
Chenjie Yu6d370f42018-03-25 14:57:30 -0700718// Test value metric no condition, the pull on bucket boundary come in time and too late
719TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
720 ValueMetric metric;
721 metric.set_id(metricId);
722 metric.set_bucket(ONE_MINUTE);
723 metric.mutable_value_field()->set_field(tagId);
724 metric.mutable_value_field()->add_child()->set_field(2);
725
726 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700727 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700728 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
729 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yue1361ed2018-07-23 17:33:09 -0700730 EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
Chenjie Yu6d370f42018-03-25 14:57:30 -0700731
732 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700733 tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700734
735 vector<shared_ptr<LogEvent>> allData;
736 // pull 1
737 allData.clear();
738 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
739 event->write(tagId);
740 event->write(11);
741 event->init();
742 allData.push_back(event);
743
744 valueProducer.onDataPulled(allData);
745 // has one slice
746 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
747 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yu6d370f42018-03-25 14:57:30 -0700748
Chenjie Yua0f02242018-07-06 16:14:34 -0700749 // startUpdated:true sum:0 start:11
Chenjie Yu6d370f42018-03-25 14:57:30 -0700750 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700751 EXPECT_EQ(false, curInterval.hasValue);
752 EXPECT_EQ(11, curInterval.start.long_value);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700753 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700754
755 // pull 2 at correct time
756 allData.clear();
757 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
758 event->write(tagId);
759 event->write(23);
760 event->init();
761 allData.push_back(event);
762 valueProducer.onDataPulled(allData);
763 // has one slice
764 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
765 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700766 // tartUpdated:false sum:12
Chenjie Yu6d370f42018-03-25 14:57:30 -0700767 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700768 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700769 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700770 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700771 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700772
773 // pull 3 come late.
774 // The previous bucket gets closed with error. (Has start value 23, no ending)
775 // Another bucket gets closed with error. (No start, but ending with 36)
776 // The new bucket is back to normal.
777 allData.clear();
778 event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
779 event->write(tagId);
780 event->write(36);
781 event->init();
782 allData.push_back(event);
783 valueProducer.onDataPulled(allData);
784 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
785 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700786 // startUpdated:false sum:12
Chenjie Yu6d370f42018-03-25 14:57:30 -0700787 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700788 EXPECT_EQ(36, curInterval.start.long_value);
789 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700790 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700791 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
Chenjie Yua0f02242018-07-06 16:14:34 -0700792 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700793}
794
795/*
796 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
797 * was delivered late.
798 */
799TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
800 ValueMetric metric;
801 metric.set_id(metricId);
802 metric.set_bucket(ONE_MINUTE);
803 metric.mutable_value_field()->set_field(tagId);
804 metric.mutable_value_field()->add_child()->set_field(2);
805 metric.set_condition(StringToId("SCREEN_ON"));
806
807 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700808 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700809 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
810 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
811
812 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700813 .WillOnce(Return(false))
Chenjie Yu6d370f42018-03-25 14:57:30 -0700814 // condition becomes true
815 .WillOnce(Invoke([](int tagId, int64_t timeNs,
816 vector<std::shared_ptr<LogEvent>>* data) {
817 data->clear();
818 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
819 event->write(tagId);
820 event->write(100);
821 event->init();
822 data->push_back(event);
823 return true;
824 }))
825 // condition becomes false
826 .WillOnce(Invoke([](int tagId, int64_t timeNs,
827 vector<std::shared_ptr<LogEvent>>* data) {
828 data->clear();
829 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
830 event->write(tagId);
831 event->write(120);
832 event->init();
833 data->push_back(event);
834 return true;
835 }));
836
837 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700838 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700839 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
840
841 // has one slice
842 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
843 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700844 // startUpdated:false sum:0 start:100
845 EXPECT_EQ(100, curInterval.start.long_value);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700846 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700847 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700848 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
849
850 // pull on bucket boundary come late, condition change happens before it
851 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
852 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
853 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700854 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700855 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700856
857 // Now the alarm is delivered.
858 // since the condition turned to off before this pull finish, it has no effect
859 vector<shared_ptr<LogEvent>> allData;
860 allData.clear();
861 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
862 event->write(1);
863 event->write(110);
864 event->init();
865 allData.push_back(event);
866 valueProducer.onDataPulled(allData);
867
868 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
869 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700870 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700871 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700872}
873
874/*
875 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
876 * change to false, and then true again. This is due to alarm delivered late.
877 */
878TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
879 ValueMetric metric;
880 metric.set_id(metricId);
881 metric.set_bucket(ONE_MINUTE);
882 metric.mutable_value_field()->set_field(tagId);
883 metric.mutable_value_field()->add_child()->set_field(2);
884 metric.set_condition(StringToId("SCREEN_ON"));
885
886 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700887 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700888 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
889 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
890
891 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700892 .WillOnce(Return(false))
Chenjie Yu6d370f42018-03-25 14:57:30 -0700893 // condition becomes true
894 .WillOnce(Invoke([](int tagId, int64_t timeNs,
895 vector<std::shared_ptr<LogEvent>>* data) {
896 data->clear();
897 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
898 event->write(tagId);
899 event->write(100);
900 event->init();
901 data->push_back(event);
902 return true;
903 }))
904 // condition becomes false
905 .WillOnce(Invoke([](int tagId, int64_t timeNs,
906 vector<std::shared_ptr<LogEvent>>* data) {
907 data->clear();
908 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
909 event->write(tagId);
910 event->write(120);
911 event->init();
912 data->push_back(event);
913 return true;
914 }))
915 // condition becomes true again
916 .WillOnce(Invoke([](int tagId, int64_t timeNs,
917 vector<std::shared_ptr<LogEvent>>* data) {
918 data->clear();
919 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
920 event->write(tagId);
921 event->write(130);
922 event->init();
923 data->push_back(event);
924 return true;
925 }));
926
927 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700928 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700929 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
930
931 // has one slice
932 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
933 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -0700934 // startUpdated:false sum:0 start:100
935 EXPECT_EQ(100, curInterval.start.long_value);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700936 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700937 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -0700938 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
939
940 // pull on bucket boundary come late, condition change happens before it
941 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
942 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
943 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700944 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700945 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700946
947 // condition changed to true again, before the pull alarm is delivered
948 valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
949 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
950 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700951 EXPECT_EQ(130, curInterval.start.long_value);
952 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700953 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700954
955 // Now the alarm is delivered, but it is considered late, it has no effect
956 vector<shared_ptr<LogEvent>> allData;
957 allData.clear();
958 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
959 event->write(1);
960 event->write(110);
961 event->init();
962 allData.push_back(event);
963 valueProducer.onDataPulled(allData);
964
965 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
966 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -0700967 EXPECT_EQ(130, curInterval.start.long_value);
968 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -0700969 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -0700970}
971
972/*
973 * Test pulled event with non sliced condition. The pull on boundary come late because the puller is
974 * very slow.
975 */
976TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3) {
977 ValueMetric metric;
978 metric.set_id(metricId);
979 metric.set_bucket(ONE_MINUTE);
980 metric.mutable_value_field()->set_field(tagId);
981 metric.mutable_value_field()->add_child()->set_field(2);
982 metric.set_condition(StringToId("SCREEN_ON"));
983
984 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Chenjie Yue2219202018-06-08 10:07:51 -0700985 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Chenjie Yu6d370f42018-03-25 14:57:30 -0700986 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
987 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
988
989 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
Chenjie Yue1361ed2018-07-23 17:33:09 -0700990 .WillOnce(Return(false))
Chenjie Yu6d370f42018-03-25 14:57:30 -0700991 // condition becomes true
992 .WillOnce(Invoke([](int tagId, int64_t timeNs,
993 vector<std::shared_ptr<LogEvent>>* data) {
994 data->clear();
995 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
996 event->write(tagId);
997 event->write(100);
998 event->init();
999 data->push_back(event);
1000 return true;
1001 }))
1002 // condition becomes false
1003 .WillOnce(Invoke([](int tagId, int64_t timeNs,
1004 vector<std::shared_ptr<LogEvent>>* data) {
1005 data->clear();
1006 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 20);
1007 event->write(tagId);
1008 event->write(120);
1009 event->init();
1010 data->push_back(event);
1011 return true;
1012 }));
1013
1014 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
Yangster-mac15f6bbc2018-04-08 11:52:26 -07001015 bucketStartTimeNs, pullerManager);
Chenjie Yu6d370f42018-03-25 14:57:30 -07001016 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
1017
1018 // has one slice
1019 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1020 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua0f02242018-07-06 16:14:34 -07001021 // startUpdated:false sum:0 start:100
1022 EXPECT_EQ(100, curInterval.start.long_value);
Chenjie Yu6d370f42018-03-25 14:57:30 -07001023 EXPECT_EQ(true, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -07001024 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yu6d370f42018-03-25 14:57:30 -07001025 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
1026
1027 // pull on bucket boundary come late, condition change happens before it.
1028 // But puller is very slow in this one, so the data come after bucket finish
1029 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
1030 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1031 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -07001032 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -07001033 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -07001034
1035 // Alarm is delivered in time, but the pull is very slow, and pullers are called in order,
1036 // so this one comes even later
1037 vector<shared_ptr<LogEvent>> allData;
1038 allData.clear();
1039 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 30);
1040 event->write(1);
1041 event->write(110);
1042 event->init();
1043 allData.push_back(event);
1044 valueProducer.onDataPulled(allData);
1045
1046 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1047 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yua0f02242018-07-06 16:14:34 -07001048 EXPECT_EQ(false, curInterval.hasValue);
Chenjie Yuae63b0a2018-04-10 14:59:31 -07001049 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
Chenjie Yu6d370f42018-03-25 14:57:30 -07001050}
1051
Chenjie Yua0f02242018-07-06 16:14:34 -07001052TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
1053 ValueMetric metric;
1054 metric.set_id(metricId);
1055 metric.set_bucket(ONE_MINUTE);
1056 metric.mutable_value_field()->set_field(tagId);
1057 metric.mutable_value_field()->add_child()->set_field(2);
1058 metric.set_aggregation_type(ValueMetric::MIN);
1059
1060 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1061 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1062
1063 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1064 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001065
1066 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1067 event1->write(1);
1068 event1->write(10);
1069 event1->init();
1070 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1071 event2->write(1);
1072 event2->write(20);
1073 event2->init();
1074 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1075 // has one slice
1076 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1077 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1078 EXPECT_EQ(10, curInterval.value.long_value);
1079 EXPECT_EQ(true, curInterval.hasValue);
1080
1081 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1082
1083 // has one slice
1084 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1085 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1086 EXPECT_EQ(10, curInterval.value.long_value);
1087
1088 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1089 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1090 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1091 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
1092}
1093
1094TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
1095 ValueMetric metric;
1096 metric.set_id(metricId);
1097 metric.set_bucket(ONE_MINUTE);
1098 metric.mutable_value_field()->set_field(tagId);
1099 metric.mutable_value_field()->add_child()->set_field(2);
1100 metric.set_aggregation_type(ValueMetric::MAX);
1101
1102 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1103 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1104
1105 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1106 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001107
1108 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1109 event1->write(1);
1110 event1->write(10);
1111 event1->init();
1112 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1113 event2->write(1);
1114 event2->write(20);
1115 event2->init();
1116 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1117 // has one slice
1118 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1119 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1120 EXPECT_EQ(10, curInterval.value.long_value);
1121 EXPECT_EQ(true, curInterval.hasValue);
1122
1123 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1124
1125 // has one slice
1126 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1127 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1128 EXPECT_EQ(20, curInterval.value.long_value);
1129
1130 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1131 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1132 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1133 EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
1134}
1135
1136TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
1137 ValueMetric metric;
1138 metric.set_id(metricId);
1139 metric.set_bucket(ONE_MINUTE);
1140 metric.mutable_value_field()->set_field(tagId);
1141 metric.mutable_value_field()->add_child()->set_field(2);
1142 metric.set_aggregation_type(ValueMetric::AVG);
1143
1144 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1145 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1146
1147 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1148 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001149
1150 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1151 event1->write(1);
1152 event1->write(10);
1153 event1->init();
1154 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1155 event2->write(1);
1156 event2->write(15);
1157 event2->init();
1158 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1159 // has one slice
1160 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1161 ValueMetricProducer::Interval curInterval;
1162 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1163 EXPECT_EQ(10, curInterval.value.long_value);
1164 EXPECT_EQ(true, curInterval.hasValue);
1165 EXPECT_EQ(1, curInterval.sampleSize);
1166
1167 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1168
1169 // has one slice
1170 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1171 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1172 EXPECT_EQ(25, curInterval.value.long_value);
1173 EXPECT_EQ(2, curInterval.sampleSize);
1174
1175 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1176 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1177 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1178 EXPECT_EQ(12.5, valueProducer.mPastBuckets.begin()->second.back().mValueDouble);
1179}
1180
1181TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
1182 ValueMetric metric;
1183 metric.set_id(metricId);
1184 metric.set_bucket(ONE_MINUTE);
1185 metric.mutable_value_field()->set_field(tagId);
1186 metric.mutable_value_field()->add_child()->set_field(2);
1187 metric.set_aggregation_type(ValueMetric::SUM);
1188
1189 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1190 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1191
1192 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
1193 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001194
1195 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
1196 event1->write(1);
1197 event1->write(10);
1198 event1->init();
1199 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
1200 event2->write(1);
1201 event2->write(15);
1202 event2->init();
1203 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
1204 // has one slice
1205 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1206 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1207 EXPECT_EQ(10, curInterval.value.long_value);
1208 EXPECT_EQ(true, curInterval.hasValue);
1209
1210 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
1211
1212 // has one slice
1213 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1214 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1215 EXPECT_EQ(25, curInterval.value.long_value);
1216
1217 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1218 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1219 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1220 EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
1221}
1222
1223TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced) {
1224 string slicedConditionName = "UID";
1225 const int conditionTagId = 2;
1226 ValueMetric metric;
1227 metric.set_id(metricId);
1228 metric.set_bucket(ONE_MINUTE);
1229 metric.mutable_value_field()->set_field(tagId);
1230 metric.mutable_value_field()->add_child()->set_field(1);
1231 metric.set_aggregation_type(ValueMetric::SUM);
1232
1233 metric.set_condition(StringToId(slicedConditionName));
1234 MetricConditionLink* link = metric.add_links();
1235 link->set_condition(StringToId(slicedConditionName));
1236 buildSimpleAtomFieldMatcher(tagId, 2, link->mutable_fields_in_what());
1237 buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
1238
1239 LogEvent event1(tagId, bucketStartTimeNs + 10);
1240 event1.write(10); // value
1241 event1.write("111"); // uid
1242 event1.init();
1243 ConditionKey key1;
1244 key1[StringToId(slicedConditionName)] =
1245 {getMockedDimensionKey(conditionTagId, 2, "111")};
1246
1247 LogEvent event2(tagId, bucketStartTimeNs + 20);
1248 event2.write(15);
1249 event2.write("222");
1250 event2.init();
1251 ConditionKey key2;
1252 key2[StringToId(slicedConditionName)] =
1253 {getMockedDimensionKey(conditionTagId, 2, "222")};
1254
1255 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1256 EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
Chenjie Yua0f02242018-07-06 16:14:34 -07001257 EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
1258
1259 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1260
1261 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
1262 bucketStartTimeNs, pullerManager);
Chenjie Yua0f02242018-07-06 16:14:34 -07001263
1264 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1265
1266 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1267 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1268 EXPECT_EQ(false, curInterval.hasValue);
1269
1270 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1271
1272 // has one slice
1273 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1274 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
1275 EXPECT_EQ(15, curInterval.value.long_value);
1276
1277 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1278 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
1279 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1280 EXPECT_EQ(15, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
1281}
1282
Chenjie Yu6736c892017-11-09 10:50:09 -08001283} // namespace statsd
1284} // namespace os
1285} // namespace android
1286#else
1287GTEST_LOG_(INFO) << "This test does nothing.\n";
1288#endif