blob: be1b9ebb557c806457eacec70980e155fa1e99e2 [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"
16
17#include <gmock/gmock.h>
18#include <gtest/gtest.h>
Bookatz6bf98252018-03-14 10:44:24 -070019#include <math.h>
Chenjie Yu6736c892017-11-09 10:50:09 -080020#include <stdio.h>
tsaichristineb87ca152019-12-09 15:19:41 -080021
Chenjie Yu6736c892017-11-09 10:50:09 -080022#include <vector>
23
tsaichristineb87ca152019-12-09 15:19:41 -080024#include "metrics_test_helper.h"
25#include "src/matchers/SimpleLogMatchingTracker.h"
26#include "src/metrics/MetricProducer.h"
27#include "src/stats_log_util.h"
28#include "tests/statsd_test_util.h"
29
Chenjie Yu6736c892017-11-09 10:50:09 -080030using namespace testing;
31using android::sp;
Yao Chenb3561512017-11-21 18:07:17 -080032using std::make_shared;
Chenjie Yu6736c892017-11-09 10:50:09 -080033using std::set;
Yao Chenb3561512017-11-21 18:07:17 -080034using std::shared_ptr;
Chenjie Yu6736c892017-11-09 10:50:09 -080035using std::unordered_map;
36using std::vector;
Chenjie Yu6736c892017-11-09 10:50:09 -080037
38#ifdef __ANDROID__
39
40namespace android {
41namespace os {
42namespace statsd {
43
Tej Singhe678cb72020-04-14 16:23:30 -070044namespace {
45
Yangster-mac94e197c2018-01-02 16:03:03 -080046const ConfigKey kConfigKey(0, 12345);
Chenjie Yua7259ab2017-12-10 08:31:05 -080047const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080048const int64_t metricId = 123;
Chenjie Yu054ce9c2018-11-12 15:27:29 -080049const int64_t atomMatcherId = 678;
50const int logEventMatcherIndex = 0;
Chenjie Yua7259ab2017-12-10 08:31:05 -080051const int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080052const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Chenjie Yua7259ab2017-12-10 08:31:05 -080053const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
54const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
55const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
Chenjie Yu6d370f42018-03-25 14:57:30 -070056const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
57const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
Chenjie Yuc715b9e2018-10-19 07:52:12 -070058double epsilon = 0.001;
59
Olivier Gaillard47a9efc2019-02-22 15:43:31 +000060static void assertPastBucketValuesSingleKey(
61 const std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>>& mPastBuckets,
Yao Chene6cfb142019-04-08 12:00:01 -070062 const std::initializer_list<int>& expectedValuesList,
Tej Singhe678cb72020-04-14 16:23:30 -070063 const std::initializer_list<int64_t>& expectedDurationNsList,
64 const std::initializer_list<int64_t>& expectedStartTimeNsList,
65 const std::initializer_list<int64_t>& expectedEndTimeNsList) {
66 vector<int> expectedValues(expectedValuesList);
67 vector<int64_t> expectedDurationNs(expectedDurationNsList);
68 vector<int64_t> expectedStartTimeNs(expectedStartTimeNsList);
69 vector<int64_t> expectedEndTimeNs(expectedEndTimeNsList);
70
Yao Chene6cfb142019-04-08 12:00:01 -070071 ASSERT_EQ(expectedValues.size(), expectedDurationNs.size());
Tej Singhe678cb72020-04-14 16:23:30 -070072 ASSERT_EQ(expectedValues.size(), expectedStartTimeNs.size());
73 ASSERT_EQ(expectedValues.size(), expectedEndTimeNs.size());
74
Olivier Gaillarda8b70112019-02-25 11:24:23 +000075 if (expectedValues.size() == 0) {
76 ASSERT_EQ(0, mPastBuckets.size());
77 return;
78 }
79
Olivier Gaillard47a9efc2019-02-22 15:43:31 +000080 ASSERT_EQ(1, mPastBuckets.size());
81 ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
82
Tej Singhe678cb72020-04-14 16:23:30 -070083 const vector<ValueBucket>& buckets = mPastBuckets.begin()->second;
Olivier Gaillard47a9efc2019-02-22 15:43:31 +000084 for (int i = 0; i < expectedValues.size(); i++) {
85 EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
86 << "Values differ at index " << i;
Yao Chene6cfb142019-04-08 12:00:01 -070087 EXPECT_EQ(expectedDurationNs[i], buckets[i].mConditionTrueNs)
88 << "Condition duration value differ at index " << i;
Tej Singhe678cb72020-04-14 16:23:30 -070089 EXPECT_EQ(expectedStartTimeNs[i], buckets[i].mBucketStartNs)
90 << "Start time differs at index " << i;
91 EXPECT_EQ(expectedEndTimeNs[i], buckets[i].mBucketEndNs)
92 << "End time differs at index " << i;
Olivier Gaillard47a9efc2019-02-22 15:43:31 +000093 }
94}
95
Tej Singhe678cb72020-04-14 16:23:30 -070096} // anonymous namespace
97
tsaichristinebb33b802020-03-16 09:46:41 -070098class ValueMetricProducerTestHelper {
99public:
100 static sp<ValueMetricProducer> createValueProducerNoConditions(
101 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
102 UidMap uidMap;
103 SimpleAtomMatcher atomMatcher;
104 atomMatcher.set_atom_id(tagId);
105 sp<EventMatcherWizard> eventMatcherWizard =
106 new EventMatcherWizard({new SimpleLogMatchingTracker(
107 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
108 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Tej Singh3be093b2020-03-04 20:08:38 -0800109 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
110 .WillOnce(Return());
111 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
112 .WillRepeatedly(Return());
tsaichristinebb33b802020-03-16 09:46:41 -0700113
114 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
115 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
116 eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800117 valueProducer->prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700118 return valueProducer;
119 }
120
121 static sp<ValueMetricProducer> createValueProducerWithCondition(
122 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
123 UidMap uidMap;
124 SimpleAtomMatcher atomMatcher;
125 atomMatcher.set_atom_id(tagId);
126 sp<EventMatcherWizard> eventMatcherWizard =
127 new EventMatcherWizard({new SimpleLogMatchingTracker(
128 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
129 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Tej Singh3be093b2020-03-04 20:08:38 -0800130 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
131 .WillOnce(Return());
132 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
133 .WillRepeatedly(Return());
tsaichristinebb33b802020-03-16 09:46:41 -0700134
135 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
136 kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
137 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800138 valueProducer->prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700139 valueProducer->mCondition = ConditionState::kFalse;
140 return valueProducer;
141 }
142
143 static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
144 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
145 UidMap uidMap;
146 SimpleAtomMatcher atomMatcher;
147 atomMatcher.set_atom_id(tagId);
148 sp<EventMatcherWizard> eventMatcherWizard =
149 new EventMatcherWizard({new SimpleLogMatchingTracker(
150 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
151 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Tej Singh3be093b2020-03-04 20:08:38 -0800152 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
153 .WillOnce(Return());
154 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
155 .WillRepeatedly(Return());
tsaichristinebb33b802020-03-16 09:46:41 -0700156
157 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
158 kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
159 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800160 valueProducer->prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700161 return valueProducer;
162 }
163
164 static sp<ValueMetricProducer> createValueProducerWithState(
165 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
166 vector<int32_t> slicedStateAtoms,
167 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
168 UidMap uidMap;
169 SimpleAtomMatcher atomMatcher;
170 atomMatcher.set_atom_id(tagId);
171 sp<EventMatcherWizard> eventMatcherWizard =
172 new EventMatcherWizard({new SimpleLogMatchingTracker(
173 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
174 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Tej Singh3be093b2020-03-04 20:08:38 -0800175 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
176 .WillOnce(Return());
177 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
178 .WillRepeatedly(Return());
tsaichristinebb33b802020-03-16 09:46:41 -0700179 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
180 kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
181 eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
182 {}, slicedStateAtoms, stateGroupMap);
Tej Singh3be093b2020-03-04 20:08:38 -0800183 valueProducer->prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700184 return valueProducer;
185 }
186
187 static ValueMetric createMetric() {
188 ValueMetric metric;
189 metric.set_id(metricId);
190 metric.set_bucket(ONE_MINUTE);
191 metric.mutable_value_field()->set_field(tagId);
192 metric.mutable_value_field()->add_child()->set_field(2);
193 metric.set_max_pull_delay_sec(INT_MAX);
194 return metric;
195 }
196
197 static ValueMetric createMetricWithCondition() {
198 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
199 metric.set_condition(StringToId("SCREEN_ON"));
200 return metric;
201 }
202
203 static ValueMetric createMetricWithState(string state) {
204 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
205 metric.add_slice_by_state(StringToId(state));
206 return metric;
207 }
208};
209
Tej Singhe678cb72020-04-14 16:23:30 -0700210// Setup for parameterized tests.
211class ValueMetricProducerTest_PartialBucket : public TestWithParam<BucketSplitEvent> {};
212
213INSTANTIATE_TEST_SUITE_P(ValueMetricProducerTest_PartialBucket,
214 ValueMetricProducerTest_PartialBucket,
215 testing::Values(APP_UPGRADE, BOOT_COMPLETE));
216
tsaichristinebb33b802020-03-16 09:46:41 -0700217/*
218 * Tests that the first bucket works correctly
219 */
220TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
221 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
222
223 int64_t startTimeBase = 11;
224 UidMap uidMap;
225 SimpleAtomMatcher atomMatcher;
226 atomMatcher.set_atom_id(tagId);
227 sp<EventMatcherWizard> eventMatcherWizard =
228 new EventMatcherWizard({new SimpleLogMatchingTracker(
229 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
230 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
231 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
232
233 // statsd started long ago.
234 // The metric starts in the middle of the bucket
235 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
236 logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
237 22, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800238 valueProducer.prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700239
240 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
241 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
242 EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
243 valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
244 EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
245 valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
246}
247
248/*
249 * Tests that the first bucket works correctly
250 */
251TEST(ValueMetricProducerTest, TestFirstBucket) {
252 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
253
254 UidMap uidMap;
255 SimpleAtomMatcher atomMatcher;
256 atomMatcher.set_atom_id(tagId);
257 sp<EventMatcherWizard> eventMatcherWizard =
258 new EventMatcherWizard({new SimpleLogMatchingTracker(
259 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
260 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
261 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
262
263 // statsd started long ago.
264 // The metric starts in the middle of the bucket
265 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
266 logEventMatcherIndex, eventMatcherWizard, -1, 5,
267 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800268 valueProducer.prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700269
270 EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
271 EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
272 EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
273}
274
275/*
276 * Tests pulled atoms with no conditions
277 */
278TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
279 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
280 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -0800281 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
282 .WillOnce(Invoke(
283 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
284 data->clear();
285 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
286 return true;
287 }));
tsaichristinebb33b802020-03-16 09:46:41 -0700288
289 sp<ValueMetricProducer> valueProducer =
290 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
291
292 vector<shared_ptr<LogEvent>> allData;
293 allData.clear();
294 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
295
296 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
297 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700298 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700299 ValueMetricProducer::Interval curInterval =
300 valueProducer->mCurrentSlicedBucket.begin()->second[0];
301 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
302
303 EXPECT_EQ(true, curBaseInfo.hasBase);
304 EXPECT_EQ(11, curBaseInfo.base.long_value);
305 EXPECT_EQ(false, curInterval.hasValue);
306 EXPECT_EQ(8, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700307 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700308 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
309 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
310
311 allData.clear();
312 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
313 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
314 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700315 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700316 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
317 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
318
319 EXPECT_EQ(true, curBaseInfo.hasBase);
320 EXPECT_EQ(23, curBaseInfo.base.long_value);
321 EXPECT_EQ(false, curInterval.hasValue);
322 EXPECT_EQ(12, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700323 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
324 ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700325 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
326 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
327 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
328 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
329
330 allData.clear();
331 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
332 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700333 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700334 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
335 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
336
337 EXPECT_EQ(true, curBaseInfo.hasBase);
338 EXPECT_EQ(36, curBaseInfo.base.long_value);
339 EXPECT_EQ(false, curInterval.hasValue);
340 EXPECT_EQ(13, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700341 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
342 ASSERT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700343 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
344 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
345 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
346 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
347 EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
348 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
349}
350
Tej Singhe678cb72020-04-14 16:23:30 -0700351TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
tsaichristinebb33b802020-03-16 09:46:41 -0700352 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
353 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singhe678cb72020-04-14 16:23:30 -0700354 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
Tej Singh3be093b2020-03-04 20:08:38 -0800355 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinebb33b802020-03-16 09:46:41 -0700356 // Initialize bucket.
Tej Singh3be093b2020-03-04 20:08:38 -0800357 .WillOnce(Invoke([](int tagId, const ConfigKey&,
358 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinebb33b802020-03-16 09:46:41 -0700359 data->clear();
360 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
361 return true;
362 }))
363 // Partial bucket.
Tej Singhe678cb72020-04-14 16:23:30 -0700364 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
365 vector<std::shared_ptr<LogEvent>>* data,
366 bool) {
tsaichristinebb33b802020-03-16 09:46:41 -0700367 data->clear();
Tej Singhe678cb72020-04-14 16:23:30 -0700368 data->push_back(
369 CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs + 8, 5));
tsaichristinebb33b802020-03-16 09:46:41 -0700370 return true;
371 }));
372
373 sp<ValueMetricProducer> valueProducer =
374 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
375
376 // First bucket ends.
377 vector<shared_ptr<LogEvent>> allData;
378 allData.clear();
379 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 2));
380 valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
381
382 // Partial buckets created in 2nd bucket.
Tej Singhe678cb72020-04-14 16:23:30 -0700383 switch (GetParam()) {
384 case APP_UPGRADE:
385 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
386 break;
387 case BOOT_COMPLETE:
388 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
389 break;
390 }
391 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
392 EXPECT_EQ(1, valueProducer->getCurrentBucketNum());
tsaichristinebb33b802020-03-16 09:46:41 -0700393
Tej Singhe678cb72020-04-14 16:23:30 -0700394 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1, 3},
395 {bucketSizeNs, partialBucketSplitTimeNs - bucket2StartTimeNs},
396 {bucketStartTimeNs, bucket2StartTimeNs},
397 {bucket2StartTimeNs, partialBucketSplitTimeNs});
tsaichristinebb33b802020-03-16 09:46:41 -0700398}
399
400/*
401 * Tests pulled atoms with filtering
402 */
403TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
404 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
405
406 UidMap uidMap;
407 SimpleAtomMatcher atomMatcher;
408 atomMatcher.set_atom_id(tagId);
409 auto keyValue = atomMatcher.add_field_value_matcher();
410 keyValue->set_field(1);
411 keyValue->set_eq_int(3);
412 sp<EventMatcherWizard> eventMatcherWizard =
413 new EventMatcherWizard({new SimpleLogMatchingTracker(
414 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
415 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
416 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -0800417 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
418 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
419 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
420 .WillOnce(Invoke(
421 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
422 data->clear();
423 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
424 return true;
425 }));
tsaichristinebb33b802020-03-16 09:46:41 -0700426
427 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
428 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
429 eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800430 valueProducer->prepareFirstBucket();
tsaichristinebb33b802020-03-16 09:46:41 -0700431
432 vector<shared_ptr<LogEvent>> allData;
433 allData.clear();
434 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 3, 11));
435
436 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
437 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700438 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700439 ValueMetricProducer::Interval curInterval =
440 valueProducer->mCurrentSlicedBucket.begin()->second[0];
441 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
442
443 EXPECT_EQ(true, curBaseInfo.hasBase);
444 EXPECT_EQ(11, curBaseInfo.base.long_value);
445 EXPECT_EQ(false, curInterval.hasValue);
446 EXPECT_EQ(8, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700447 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700448 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
449 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
450
451 allData.clear();
452 allData.push_back(CreateTwoValueLogEvent(tagId, bucket3StartTimeNs + 1, 4, 23));
453 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
454 // No new data seen, so data has been cleared.
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700455 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700456
457 EXPECT_EQ(true, curBaseInfo.hasBase);
458 EXPECT_EQ(11, curBaseInfo.base.long_value);
459 EXPECT_EQ(false, curInterval.hasValue);
460 EXPECT_EQ(8, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700461 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700462 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
463 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
464
465 allData.clear();
466 allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
467 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700468 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700469 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
470 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
471
472 // the base was reset
473 EXPECT_EQ(true, curBaseInfo.hasBase);
474 EXPECT_EQ(36, curBaseInfo.base.long_value);
475 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700476 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
477 ASSERT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
tsaichristinebb33b802020-03-16 09:46:41 -0700478 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
479 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
480}
481
tsaichristinef487f2a2020-03-17 17:46:19 -0700482/*
483 * Tests pulled atoms with no conditions and take absolute value after reset
484 */
485TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
486 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
487 metric.set_use_absolute_value_on_reset(true);
488
489 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -0800490 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
tsaichristinef487f2a2020-03-17 17:46:19 -0700491 sp<ValueMetricProducer> valueProducer =
492 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
493
494 vector<shared_ptr<LogEvent>> allData;
495 allData.clear();
496 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
497
498 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
499 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700500 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700501 ValueMetricProducer::Interval curInterval =
502 valueProducer->mCurrentSlicedBucket.begin()->second[0];
503 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
504
505 EXPECT_EQ(true, curBaseInfo.hasBase);
506 EXPECT_EQ(11, curBaseInfo.base.long_value);
507 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700508 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700509
510 allData.clear();
511 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
512 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
513 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700514 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700515 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
516 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
517 EXPECT_EQ(true, curBaseInfo.hasBase);
518 EXPECT_EQ(10, curBaseInfo.base.long_value);
519 EXPECT_EQ(false, curInterval.hasValue);
520 EXPECT_EQ(10, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700521 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700522 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
523 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
524
525 allData.clear();
526 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
527 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700528 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700529 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
530 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
531 EXPECT_EQ(true, curBaseInfo.hasBase);
532 EXPECT_EQ(36, curBaseInfo.base.long_value);
533 EXPECT_EQ(false, curInterval.hasValue);
534 EXPECT_EQ(26, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700535 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
536 ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700537 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
538 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
539 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
540 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
541}
542
543/*
544 * Tests pulled atoms with no conditions and take zero value after reset
545 */
546TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
547 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
548 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -0800549 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
tsaichristinef487f2a2020-03-17 17:46:19 -0700550 sp<ValueMetricProducer> valueProducer =
551 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
552
553 vector<shared_ptr<LogEvent>> allData;
554 allData.clear();
555 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
556
557 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
558 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700559 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700560 ValueMetricProducer::Interval curInterval =
561 valueProducer->mCurrentSlicedBucket.begin()->second[0];
562 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
563
564 EXPECT_EQ(true, curBaseInfo.hasBase);
565 EXPECT_EQ(11, curBaseInfo.base.long_value);
566 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700567 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700568
569 allData.clear();
570 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
571 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
572 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700573 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700574 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
575 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
576 EXPECT_EQ(true, curBaseInfo.hasBase);
577 EXPECT_EQ(10, curBaseInfo.base.long_value);
578 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700579 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700580
581 allData.clear();
582 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
583 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700584 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700585 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
586 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
587 EXPECT_EQ(true, curBaseInfo.hasBase);
588 EXPECT_EQ(36, curBaseInfo.base.long_value);
589 EXPECT_EQ(false, curInterval.hasValue);
590 EXPECT_EQ(26, curInterval.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700591 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700592 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
593 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
594}
595
596/*
597 * Test pulled event with non sliced condition.
598 */
599TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
600 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
601
602 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
603
Tej Singh3be093b2020-03-04 20:08:38 -0800604 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
605 .WillOnce(Invoke([](int tagId, const ConfigKey&,
606 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700607 data->clear();
608 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
609 return true;
610 }))
Tej Singh3be093b2020-03-04 20:08:38 -0800611 .WillOnce(Invoke([](int tagId, const ConfigKey&,
612 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700613 data->clear();
614 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
615 return true;
616 }))
Tej Singh3be093b2020-03-04 20:08:38 -0800617 .WillOnce(Invoke([](int tagId, const ConfigKey&,
618 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700619 data->clear();
620 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
621 return true;
622 }));
623
624 sp<ValueMetricProducer> valueProducer =
625 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
626
627 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
628
629 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700630 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700631 ValueMetricProducer::Interval curInterval =
632 valueProducer->mCurrentSlicedBucket.begin()->second[0];
633 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
634 // startUpdated:false sum:0 start:100
635 EXPECT_EQ(true, curBaseInfo.hasBase);
636 EXPECT_EQ(100, curBaseInfo.base.long_value);
637 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700638 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700639
640 vector<shared_ptr<LogEvent>> allData;
641 allData.clear();
tsaichristine8dca82e2020-04-07 09:40:03 -0700642 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
tsaichristinef487f2a2020-03-17 17:46:19 -0700643 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -0700644 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8},
645 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700646
647 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700648 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700649 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
650 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
651 EXPECT_EQ(true, curBaseInfo.hasBase);
652 EXPECT_EQ(110, curBaseInfo.base.long_value);
653 EXPECT_EQ(false, curInterval.hasValue);
654 EXPECT_EQ(10, curInterval.value.long_value);
655
656 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
Tej Singhe678cb72020-04-14 16:23:30 -0700657 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8},
658 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700659
660 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700661 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700662 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
663 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
664 EXPECT_EQ(true, curInterval.hasValue);
665 EXPECT_EQ(20, curInterval.value.long_value);
666 EXPECT_EQ(false, curBaseInfo.hasBase);
667
668 valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
Tej Singhe678cb72020-04-14 16:23:30 -0700669 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1},
670 {bucketStartTimeNs, bucket2StartTimeNs},
671 {bucket2StartTimeNs, bucket3StartTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700672}
673
Tej Singhe678cb72020-04-14 16:23:30 -0700674TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700675 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
676
677 UidMap uidMap;
678 SimpleAtomMatcher atomMatcher;
679 atomMatcher.set_atom_id(tagId);
680 sp<EventMatcherWizard> eventMatcherWizard =
681 new EventMatcherWizard({new SimpleLogMatchingTracker(
682 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
683 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
684 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
685 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
686 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
687 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800688 valueProducer.prepareFirstBucket();
tsaichristinef487f2a2020-03-17 17:46:19 -0700689
690 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700691 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristinef487f2a2020-03-17 17:46:19 -0700692 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700693 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700694
Tej Singhe678cb72020-04-14 16:23:30 -0700695 int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 150;
696 switch (GetParam()) {
697 case APP_UPGRADE:
698 valueProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
699 break;
700 case BOOT_COMPLETE:
701 valueProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
702 break;
703 }
704 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10},
705 {partialBucketSplitTimeNs - bucketStartTimeNs},
706 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
707 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
708 EXPECT_EQ(0, valueProducer.getCurrentBucketNum());
tsaichristinef487f2a2020-03-17 17:46:19 -0700709
Tej Singhe678cb72020-04-14 16:23:30 -0700710 // Event arrives after the bucket split.
tsaichristinef487f2a2020-03-17 17:46:19 -0700711 LogEvent event2(/*uid=*/0, /*pid=*/0);
Tej Singhe678cb72020-04-14 16:23:30 -0700712 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 59 * NS_PER_SEC, 20);
tsaichristinef487f2a2020-03-17 17:46:19 -0700713 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
Tej Singhe678cb72020-04-14 16:23:30 -0700714
715 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10},
716 {partialBucketSplitTimeNs - bucketStartTimeNs},
717 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
718 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
719 EXPECT_EQ(0, valueProducer.getCurrentBucketNum());
tsaichristinef487f2a2020-03-17 17:46:19 -0700720
721 // Next value should create a new bucket.
722 LogEvent event3(/*uid=*/0, /*pid=*/0);
Tej Singhe678cb72020-04-14 16:23:30 -0700723 CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 5 * NS_PER_SEC, 10);
tsaichristinef487f2a2020-03-17 17:46:19 -0700724 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
Tej Singhe678cb72020-04-14 16:23:30 -0700725 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10, 20},
726 {partialBucketSplitTimeNs - bucketStartTimeNs,
727 bucket2StartTimeNs - partialBucketSplitTimeNs},
728 {bucketStartTimeNs, partialBucketSplitTimeNs},
729 {partialBucketSplitTimeNs, bucket2StartTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700730 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -0700731 EXPECT_EQ(1, valueProducer.getCurrentBucketNum());
tsaichristinef487f2a2020-03-17 17:46:19 -0700732}
733
Tej Singhe678cb72020-04-14 16:23:30 -0700734TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700735 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
736
737 UidMap uidMap;
738 SimpleAtomMatcher atomMatcher;
739 atomMatcher.set_atom_id(tagId);
740 sp<EventMatcherWizard> eventMatcherWizard =
741 new EventMatcherWizard({new SimpleLogMatchingTracker(
742 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
743 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
744 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singhe678cb72020-04-14 16:23:30 -0700745 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
Tej Singh3be093b2020-03-04 20:08:38 -0800746 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
747 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
748 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinef487f2a2020-03-17 17:46:19 -0700749 .WillOnce(Return(true))
Tej Singhe678cb72020-04-14 16:23:30 -0700750 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
751 vector<std::shared_ptr<LogEvent>>* data,
752 bool) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700753 data->clear();
Tej Singhe678cb72020-04-14 16:23:30 -0700754 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120));
tsaichristinef487f2a2020-03-17 17:46:19 -0700755 return true;
756 }));
757 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
758 eventMatcherWizard, tagId, bucketStartTimeNs,
759 bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800760 valueProducer.prepareFirstBucket();
tsaichristinef487f2a2020-03-17 17:46:19 -0700761
762 vector<shared_ptr<LogEvent>> allData;
763 allData.clear();
764 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
765
766 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700767 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700768
Tej Singhe678cb72020-04-14 16:23:30 -0700769 switch (GetParam()) {
770 case APP_UPGRADE:
771 valueProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
772 break;
773 case BOOT_COMPLETE:
774 valueProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
775 break;
776 }
777 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
778 EXPECT_EQ(1, valueProducer.getCurrentBucketNum());
779 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150}, {bucket2StartTimeNs},
780 {partialBucketSplitTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700781
782 allData.clear();
783 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 150));
784 valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
tsaichristinef487f2a2020-03-17 17:46:19 -0700785 EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -0700786 EXPECT_EQ(2, valueProducer.getCurrentBucketNum());
787 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30}, {150, bucketSizeNs - 150},
788 {bucket2StartTimeNs, partialBucketSplitTimeNs},
789 {partialBucketSplitTimeNs, bucket3StartTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700790}
791
792TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
793 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
794 metric.set_split_bucket_for_app_upgrade(false);
795
796 UidMap uidMap;
797 SimpleAtomMatcher atomMatcher;
798 atomMatcher.set_atom_id(tagId);
799 sp<EventMatcherWizard> eventMatcherWizard =
800 new EventMatcherWizard({new SimpleLogMatchingTracker(
801 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
802 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
803 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -0800804 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
805 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
806 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
tsaichristinef487f2a2020-03-17 17:46:19 -0700807 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
808 eventMatcherWizard, tagId, bucketStartTimeNs,
809 bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800810 valueProducer.prepareFirstBucket();
tsaichristinef487f2a2020-03-17 17:46:19 -0700811
812 vector<shared_ptr<LogEvent>> allData;
813 allData.clear();
814 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
815
816 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700817 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700818
Tej Singhe678cb72020-04-14 16:23:30 -0700819 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700820 ASSERT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
tsaichristinef487f2a2020-03-17 17:46:19 -0700821 EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
822}
823
Tej Singhe678cb72020-04-14 16:23:30 -0700824TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700825 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
826
827 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -0800828 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
829 .WillOnce(Invoke([](int tagId, const ConfigKey&,
830 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700831 data->clear();
832 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
833 return true;
834 }))
Tej Singh3be093b2020-03-04 20:08:38 -0800835 .WillOnce(Invoke([](int tagId, const ConfigKey&,
836 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinef487f2a2020-03-17 17:46:19 -0700837 data->clear();
838 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
839 return true;
840 }));
841 sp<ValueMetricProducer> valueProducer =
842 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
843
844 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
845
846 valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
847 EXPECT_FALSE(valueProducer->mCondition);
848
Tej Singhe678cb72020-04-14 16:23:30 -0700849 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs - 50;
850 switch (GetParam()) {
851 case APP_UPGRADE:
852 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
853 break;
854 case BOOT_COMPLETE:
855 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
856 break;
857 }
tsaichristinef487f2a2020-03-17 17:46:19 -0700858 // Expect one full buckets already done and starting a partial bucket.
Tej Singhe678cb72020-04-14 16:23:30 -0700859 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
860 EXPECT_EQ(0, valueProducer->getCurrentBucketNum());
tsaichristinef487f2a2020-03-17 17:46:19 -0700861 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
Tej Singhe678cb72020-04-14 16:23:30 -0700862 {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)},
863 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
tsaichristinef487f2a2020-03-17 17:46:19 -0700864 EXPECT_FALSE(valueProducer->mCondition);
865}
tsaichristine5adb1b12020-03-17 18:04:34 -0700866TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
867 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
tsaichristinef487f2a2020-03-17 17:46:19 -0700868
tsaichristine5adb1b12020-03-17 18:04:34 -0700869 UidMap uidMap;
870 SimpleAtomMatcher atomMatcher;
871 atomMatcher.set_atom_id(tagId);
872 sp<EventMatcherWizard> eventMatcherWizard =
873 new EventMatcherWizard({new SimpleLogMatchingTracker(
874 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
875 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
876 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
877
878 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
879 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
880 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800881 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -0700882
883 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700884 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -0700885
886 LogEvent event2(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700887 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
tsaichristine5adb1b12020-03-17 18:04:34 -0700888
889 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
890 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700891 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -0700892 ValueMetricProducer::Interval curInterval =
893 valueProducer.mCurrentSlicedBucket.begin()->second[0];
894 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
895 EXPECT_EQ(10, curInterval.value.long_value);
896 EXPECT_EQ(true, curInterval.hasValue);
897
898 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
899
900 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700901 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -0700902 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
903 EXPECT_EQ(30, curInterval.value.long_value);
904
905 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -0700906 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs},
907 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -0700908}
909
910TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
911 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
912
913 UidMap uidMap;
914 SimpleAtomMatcher atomMatcher;
915 atomMatcher.set_atom_id(tagId);
916 sp<EventMatcherWizard> eventMatcherWizard =
917 new EventMatcherWizard({new SimpleLogMatchingTracker(
918 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
919 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
920 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
921
922 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
923 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
924 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800925 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -0700926 valueProducer.mCondition = ConditionState::kFalse;
927
928 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700929 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -0700930 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
931 // has 1 slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700932 ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -0700933
934 valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
935
936 LogEvent event2(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700937 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
tsaichristine5adb1b12020-03-17 18:04:34 -0700938 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
939
940 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700941 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -0700942 ValueMetricProducer::Interval curInterval =
943 valueProducer.mCurrentSlicedBucket.begin()->second[0];
944 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
945 EXPECT_EQ(20, curInterval.value.long_value);
946
947 LogEvent event3(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700948 CreateRepeatedValueLogEvent(&event3, tagId, bucketStartTimeNs + 30, 30);
tsaichristine5adb1b12020-03-17 18:04:34 -0700949 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
950
951 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700952 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -0700953 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
954 EXPECT_EQ(50, curInterval.value.long_value);
955
956 valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
957
958 LogEvent event4(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -0700959 CreateRepeatedValueLogEvent(&event4, tagId, bucketStartTimeNs + 40, 40);
tsaichristine5adb1b12020-03-17 18:04:34 -0700960 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
961
962 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700963 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -0700964 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
965 EXPECT_EQ(50, curInterval.value.long_value);
966
967 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -0700968 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20}, {bucketStartTimeNs},
969 {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -0700970}
971
972TEST(ValueMetricProducerTest, TestAnomalyDetection) {
973 sp<AlarmMonitor> alarmMonitor;
974 Alert alert;
975 alert.set_id(101);
976 alert.set_metric_id(metricId);
977 alert.set_trigger_if_sum_gt(130);
978 alert.set_num_buckets(2);
979 const int32_t refPeriodSec = 3;
980 alert.set_refractory_period_secs(refPeriodSec);
981
982 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
983
984 UidMap uidMap;
985 SimpleAtomMatcher atomMatcher;
986 atomMatcher.set_atom_id(tagId);
987 sp<EventMatcherWizard> eventMatcherWizard =
988 new EventMatcherWizard({new SimpleLogMatchingTracker(
989 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
990 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
991 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
992 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
993 logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
994 bucketStartTimeNs, bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -0800995 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -0700996
997 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
998
999 LogEvent event1(/*uid=*/0, /*pid=*/0);
1000 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 1 * NS_PER_SEC, 10);
1001
1002 LogEvent event2(/*uid=*/0, /*pid=*/0);
1003 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 2 + NS_PER_SEC, 20);
1004
1005 LogEvent event3(/*uid=*/0, /*pid=*/0);
1006 CreateRepeatedValueLogEvent(&event3, tagId,
1007 bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, 130);
1008
1009 LogEvent event4(/*uid=*/0, /*pid=*/0);
1010 CreateRepeatedValueLogEvent(&event4, tagId,
1011 bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC, 1);
1012
1013 LogEvent event5(/*uid=*/0, /*pid=*/0);
1014 CreateRepeatedValueLogEvent(&event5, tagId,
1015 bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC, 150);
1016
1017 LogEvent event6(/*uid=*/0, /*pid=*/0);
1018 CreateRepeatedValueLogEvent(&event6, tagId,
1019 bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC, 160);
1020
1021 // Two events in bucket #0.
1022 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1023 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1024 // Value sum == 30 <= 130.
1025 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1026
1027 // One event in bucket #2. No alarm as bucket #0 is trashed out.
1028 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1029 // Value sum == 130 <= 130.
1030 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1031
1032 // Three events in bucket #3.
1033 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1034 // Anomaly at event 4 since Value sum == 131 > 130!
1035 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1036 std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1037 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
1038 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
1039 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1040 std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1041
1042 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
1043 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
1044 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1045 std::ceil(1.0 * event6.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1046}
1047
1048// Test value metric no condition, the pull on bucket boundary come in time and too late
1049TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
1050 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1051 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001052 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
tsaichristine5adb1b12020-03-17 18:04:34 -07001053 sp<ValueMetricProducer> valueProducer =
1054 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1055
1056 vector<shared_ptr<LogEvent>> allData;
1057 // pull 1
1058 allData.clear();
1059 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
1060
1061 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1062 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001063 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001064 ValueMetricProducer::Interval curInterval =
1065 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1066 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1067
1068 // startUpdated:true sum:0 start:11
1069 EXPECT_EQ(true, curBaseInfo.hasBase);
1070 EXPECT_EQ(11, curBaseInfo.base.long_value);
1071 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001072 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001073
1074 // pull 2 at correct time
1075 allData.clear();
1076 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
1077 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1078 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001079 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001080 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1081 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1082 // tartUpdated:false sum:12
1083 EXPECT_EQ(true, curBaseInfo.hasBase);
1084 EXPECT_EQ(23, curBaseInfo.base.long_value);
1085 EXPECT_EQ(false, curInterval.hasValue);
Tej Singhe678cb72020-04-14 16:23:30 -07001086 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
1087 {bucket2StartTimeNs}, {bucket3StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001088
1089 // pull 3 come late.
1090 // The previous bucket gets closed with error. (Has start value 23, no ending)
1091 // Another bucket gets closed with error. (No start, but ending with 36)
1092 // The new bucket is back to normal.
1093 allData.clear();
1094 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
1095 valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001096 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001097 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1098 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1099 // startUpdated:false sum:12
1100 EXPECT_EQ(true, curBaseInfo.hasBase);
1101 EXPECT_EQ(36, curBaseInfo.base.long_value);
1102 EXPECT_EQ(false, curInterval.hasValue);
Tej Singhe678cb72020-04-14 16:23:30 -07001103 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
1104 {bucket2StartTimeNs}, {bucket3StartTimeNs});
1105 // The 3rd bucket is dropped due to multiple buckets being skipped.
1106 ASSERT_EQ(1, valueProducer->mSkippedBuckets.size());
1107 EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
1108 EXPECT_EQ(bucket4StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
1109 ASSERT_EQ(1, valueProducer->mSkippedBuckets[0].dropEvents.size());
1110 EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
1111 EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[0].dropEvents[0].dropTimeNs);
tsaichristine5adb1b12020-03-17 18:04:34 -07001112}
1113
1114/*
1115 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
1116 * was delivered late.
1117 */
1118TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
1119 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1120
1121 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001122 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine5adb1b12020-03-17 18:04:34 -07001123 // condition becomes true
Tej Singh3be093b2020-03-04 20:08:38 -08001124 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1125 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine5adb1b12020-03-17 18:04:34 -07001126 data->clear();
1127 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1128 return true;
1129 }))
1130 // condition becomes false
Tej Singh3be093b2020-03-04 20:08:38 -08001131 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1132 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine5adb1b12020-03-17 18:04:34 -07001133 data->clear();
1134 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
1135 return true;
1136 }));
1137 sp<ValueMetricProducer> valueProducer =
1138 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1139
1140 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1141
1142 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001143 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001144 ValueMetricProducer::Interval curInterval =
1145 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1146 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1147 EXPECT_EQ(true, curBaseInfo.hasBase);
1148 EXPECT_EQ(100, curBaseInfo.base.long_value);
1149 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001150 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001151
1152 // pull on bucket boundary come late, condition change happens before it
1153 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1154 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1155 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
Tej Singhe678cb72020-04-14 16:23:30 -07001156 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1157 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001158 EXPECT_EQ(false, curBaseInfo.hasBase);
1159
1160 // Now the alarm is delivered.
1161 // since the condition turned to off before this pull finish, it has no effect
1162 vector<shared_ptr<LogEvent>> allData;
1163 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
1164 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1165
Tej Singhe678cb72020-04-14 16:23:30 -07001166 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1167 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001168 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1169 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1170 EXPECT_EQ(false, curBaseInfo.hasBase);
1171 EXPECT_EQ(false, curInterval.hasValue);
1172}
1173
1174/*
Tej Singhe678cb72020-04-14 16:23:30 -07001175 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
1176 * change to false, and then true again. This is due to alarm delivered late.
1177 */
tsaichristine5adb1b12020-03-17 18:04:34 -07001178TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
1179 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1180
1181 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001182 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine5adb1b12020-03-17 18:04:34 -07001183 // condition becomes true
Tej Singh3be093b2020-03-04 20:08:38 -08001184 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1185 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine5adb1b12020-03-17 18:04:34 -07001186 data->clear();
1187 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1188 return true;
1189 }))
1190 // condition becomes false
Tej Singh3be093b2020-03-04 20:08:38 -08001191 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1192 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine5adb1b12020-03-17 18:04:34 -07001193 data->clear();
1194 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
1195 return true;
1196 }))
1197 // condition becomes true again
Tej Singh3be093b2020-03-04 20:08:38 -08001198 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1199 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine5adb1b12020-03-17 18:04:34 -07001200 data->clear();
1201 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
1202 return true;
1203 }));
1204
1205 sp<ValueMetricProducer> valueProducer =
1206 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1207
1208 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1209
1210 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001211 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001212 ValueMetricProducer::Interval curInterval =
1213 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1214 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1215 // startUpdated:false sum:0 start:100
1216 EXPECT_EQ(true, curBaseInfo.hasBase);
1217 EXPECT_EQ(100, curBaseInfo.base.long_value);
1218 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001219 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001220
1221 // pull on bucket boundary come late, condition change happens before it
1222 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
Tej Singhe678cb72020-04-14 16:23:30 -07001223 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1224 {bucketStartTimeNs}, {bucket2StartTimeNs});
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001225 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001226 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1227 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1228 EXPECT_EQ(false, curBaseInfo.hasBase);
1229 EXPECT_EQ(false, curInterval.hasValue);
1230
1231 // condition changed to true again, before the pull alarm is delivered
1232 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
Tej Singhe678cb72020-04-14 16:23:30 -07001233 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1234 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001235 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1236 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1237 EXPECT_EQ(true, curBaseInfo.hasBase);
1238 EXPECT_EQ(130, curBaseInfo.base.long_value);
1239 EXPECT_EQ(false, curInterval.hasValue);
1240
1241 // Now the alarm is delivered, but it is considered late, the data will be used
1242 // for the new bucket since it was just pulled.
1243 vector<shared_ptr<LogEvent>> allData;
1244 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
1245 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
1246
1247 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1248 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1249 EXPECT_EQ(true, curBaseInfo.hasBase);
1250 EXPECT_EQ(140, curBaseInfo.base.long_value);
1251 EXPECT_EQ(true, curInterval.hasValue);
1252 EXPECT_EQ(10, curInterval.value.long_value);
Tej Singhe678cb72020-04-14 16:23:30 -07001253 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1254 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001255
1256 allData.clear();
1257 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 160));
1258 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -07001259 assertPastBucketValuesSingleKey(
1260 valueProducer->mPastBuckets, {20, 30}, {bucketSizeNs - 8, bucketSizeNs - 24},
1261 {bucketStartTimeNs, bucket2StartTimeNs}, {bucket2StartTimeNs, bucket3StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001262}
1263
1264TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
1265 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1266 metric.set_aggregation_type(ValueMetric::MIN);
1267
1268 UidMap uidMap;
1269 SimpleAtomMatcher atomMatcher;
1270 atomMatcher.set_atom_id(tagId);
1271 sp<EventMatcherWizard> eventMatcherWizard =
1272 new EventMatcherWizard({new SimpleLogMatchingTracker(
1273 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1274 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1275 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1276
1277 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1278 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1279 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08001280 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -07001281
1282 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001283 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -07001284
1285 LogEvent event2(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001286 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
tsaichristine5adb1b12020-03-17 18:04:34 -07001287
1288 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1289 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001290 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001291 ValueMetricProducer::Interval curInterval =
1292 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1293 EXPECT_EQ(10, curInterval.value.long_value);
1294 EXPECT_EQ(true, curInterval.hasValue);
1295
1296 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1297
1298 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001299 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001300 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1301 EXPECT_EQ(10, curInterval.value.long_value);
1302
1303 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -07001304 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs},
1305 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001306}
1307
1308TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
1309 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1310 metric.set_aggregation_type(ValueMetric::MAX);
1311
1312 UidMap uidMap;
1313 SimpleAtomMatcher atomMatcher;
1314 atomMatcher.set_atom_id(tagId);
1315 sp<EventMatcherWizard> eventMatcherWizard =
1316 new EventMatcherWizard({new SimpleLogMatchingTracker(
1317 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1318 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1319 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1320
1321 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1322 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1323 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08001324 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -07001325
1326 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001327 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -07001328 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1329
1330 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001331 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001332 ValueMetricProducer::Interval curInterval =
1333 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1334 EXPECT_EQ(10, curInterval.value.long_value);
1335 EXPECT_EQ(true, curInterval.hasValue);
1336
Tej Singhe678cb72020-04-14 16:23:30 -07001337 LogEvent event2(/*uid=*/0, /*pid=*/0);
1338 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
tsaichristine5adb1b12020-03-17 18:04:34 -07001339 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1340
1341 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001342 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001343 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1344 EXPECT_EQ(20, curInterval.value.long_value);
1345
Tej Singhe678cb72020-04-14 16:23:30 -07001346 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1347 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {bucketSizeNs},
1348 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001349}
1350
1351TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
1352 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1353 metric.set_aggregation_type(ValueMetric::AVG);
1354
1355 UidMap uidMap;
1356 SimpleAtomMatcher atomMatcher;
1357 atomMatcher.set_atom_id(tagId);
1358 sp<EventMatcherWizard> eventMatcherWizard =
1359 new EventMatcherWizard({new SimpleLogMatchingTracker(
1360 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1361 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1362 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1363
1364 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1365 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1366 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08001367 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -07001368
1369 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001370 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -07001371
1372 LogEvent event2(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001373 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
tsaichristine5adb1b12020-03-17 18:04:34 -07001374 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1375 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001376 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001377 ValueMetricProducer::Interval curInterval;
1378 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1379 EXPECT_EQ(10, curInterval.value.long_value);
1380 EXPECT_EQ(true, curInterval.hasValue);
1381 EXPECT_EQ(1, curInterval.sampleSize);
1382
1383 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1384
1385 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001386 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001387 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1388 EXPECT_EQ(25, curInterval.value.long_value);
1389 EXPECT_EQ(2, curInterval.sampleSize);
1390
1391 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001392 ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
1393 ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001394
1395 EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
1396 12.5) < epsilon);
1397}
1398
1399TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
1400 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1401 metric.set_aggregation_type(ValueMetric::SUM);
1402
1403 UidMap uidMap;
1404 SimpleAtomMatcher atomMatcher;
1405 atomMatcher.set_atom_id(tagId);
1406 sp<EventMatcherWizard> eventMatcherWizard =
1407 new EventMatcherWizard({new SimpleLogMatchingTracker(
1408 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1409 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1410 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1411
1412 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1413 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1414 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08001415 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -07001416
1417 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001418 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -07001419
1420 LogEvent event2(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001421 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
tsaichristine5adb1b12020-03-17 18:04:34 -07001422 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1423 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001424 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001425 ValueMetricProducer::Interval curInterval =
1426 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1427 EXPECT_EQ(10, curInterval.value.long_value);
1428 EXPECT_EQ(true, curInterval.hasValue);
1429
1430 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1431
1432 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001433 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001434 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1435 EXPECT_EQ(25, curInterval.value.long_value);
1436
1437 valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -07001438 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs},
1439 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001440}
1441
1442TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
1443 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1444 metric.set_aggregation_type(ValueMetric::MIN);
1445 metric.set_use_diff(true);
1446
1447 UidMap uidMap;
1448 SimpleAtomMatcher atomMatcher;
1449 atomMatcher.set_atom_id(tagId);
1450 sp<EventMatcherWizard> eventMatcherWizard =
1451 new EventMatcherWizard({new SimpleLogMatchingTracker(
1452 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1453 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1454 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1455
1456 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1457 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1458 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08001459 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -07001460
1461 LogEvent event1(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001462 CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
tsaichristine5adb1b12020-03-17 18:04:34 -07001463 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
Tej Singhe678cb72020-04-14 16:23:30 -07001464
tsaichristine5adb1b12020-03-17 18:04:34 -07001465 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001466 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001467 ValueMetricProducer::Interval curInterval =
1468 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1469 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1470 EXPECT_EQ(true, curBaseInfo.hasBase);
1471 EXPECT_EQ(10, curBaseInfo.base.long_value);
1472 EXPECT_EQ(false, curInterval.hasValue);
1473
Tej Singhe678cb72020-04-14 16:23:30 -07001474 LogEvent event2(/*uid=*/0, /*pid=*/0);
1475 CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 15);
tsaichristine5adb1b12020-03-17 18:04:34 -07001476 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1477
1478 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001479 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001480 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1481 EXPECT_EQ(true, curInterval.hasValue);
1482 EXPECT_EQ(5, curInterval.value.long_value);
1483
1484 // no change in data.
1485 LogEvent event3(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001486 CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 15);
tsaichristine5adb1b12020-03-17 18:04:34 -07001487 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
Tej Singhe678cb72020-04-14 16:23:30 -07001488
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001489 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001490 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1491 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1492 EXPECT_EQ(true, curBaseInfo.hasBase);
1493 EXPECT_EQ(15, curBaseInfo.base.long_value);
1494 EXPECT_EQ(true, curInterval.hasValue);
Tej Singhe678cb72020-04-14 16:23:30 -07001495 EXPECT_EQ(0, curInterval.value.long_value);
tsaichristine5adb1b12020-03-17 18:04:34 -07001496
1497 LogEvent event4(/*uid=*/0, /*pid=*/0);
tsaichristine8dca82e2020-04-07 09:40:03 -07001498 CreateRepeatedValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 15);
tsaichristine5adb1b12020-03-17 18:04:34 -07001499 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001500 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001501 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1502 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1503 EXPECT_EQ(true, curBaseInfo.hasBase);
1504 EXPECT_EQ(15, curBaseInfo.base.long_value);
1505 EXPECT_EQ(true, curInterval.hasValue);
Tej Singhe678cb72020-04-14 16:23:30 -07001506 EXPECT_EQ(0, curInterval.value.long_value);
tsaichristine5adb1b12020-03-17 18:04:34 -07001507
1508 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Tej Singhe678cb72020-04-14 16:23:30 -07001509 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs},
1510 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine5adb1b12020-03-17 18:04:34 -07001511}
1512
1513TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
1514 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1515 metric.mutable_value_field()->add_child()->set_field(3);
1516 metric.set_aggregation_type(ValueMetric::MIN);
1517 metric.set_use_diff(true);
1518
1519 UidMap uidMap;
1520 SimpleAtomMatcher atomMatcher;
1521 atomMatcher.set_atom_id(tagId);
1522 sp<EventMatcherWizard> eventMatcherWizard =
1523 new EventMatcherWizard({new SimpleLogMatchingTracker(
1524 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
1525 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1526 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1527
1528 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
1529 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
1530 pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08001531 valueProducer.prepareFirstBucket();
tsaichristine5adb1b12020-03-17 18:04:34 -07001532
1533 LogEvent event1(/*uid=*/0, /*pid=*/0);
1534 CreateThreeValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10, 20);
1535
1536 LogEvent event2(/*uid=*/0, /*pid=*/0);
1537 CreateThreeValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 1, 15, 22);
1538
1539 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1540 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001541 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001542 ValueMetricProducer::Interval curInterval =
1543 valueProducer.mCurrentSlicedBucket.begin()->second[0];
1544 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1545 EXPECT_EQ(true, curBaseInfo.hasBase);
1546 EXPECT_EQ(10, curBaseInfo.base.long_value);
1547 EXPECT_EQ(false, curInterval.hasValue);
1548 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
1549 EXPECT_EQ(true, curBaseInfo.hasBase);
1550 EXPECT_EQ(20, curBaseInfo.base.long_value);
1551 EXPECT_EQ(false, curInterval.hasValue);
1552
1553 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1554
1555 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001556 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001557 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1558 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1559 EXPECT_EQ(true, curInterval.hasValue);
1560 EXPECT_EQ(5, curInterval.value.long_value);
1561 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
1562 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
1563 EXPECT_EQ(true, curInterval.hasValue);
1564 EXPECT_EQ(2, curInterval.value.long_value);
1565
1566 // no change in first value field
1567 LogEvent event3(/*uid=*/0, /*pid=*/0);
1568 CreateThreeValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 1, 15, 25);
1569
1570 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001571 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001572 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1573 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1574
1575 EXPECT_EQ(true, curBaseInfo.hasBase);
1576 EXPECT_EQ(15, curBaseInfo.base.long_value);
1577 EXPECT_EQ(true, curInterval.hasValue);
1578 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
1579 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
1580 EXPECT_EQ(true, curBaseInfo.hasBase);
1581 EXPECT_EQ(25, curBaseInfo.base.long_value);
1582 EXPECT_EQ(true, curInterval.hasValue);
1583
1584 LogEvent event4(/*uid=*/0, /*pid=*/0);
1585 CreateThreeValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 1, 15, 29);
1586
1587 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001588 ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001589 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
1590 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
1591 EXPECT_EQ(true, curBaseInfo.hasBase);
1592 EXPECT_EQ(15, curBaseInfo.base.long_value);
1593 EXPECT_EQ(true, curInterval.hasValue);
1594 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
1595 curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
1596 EXPECT_EQ(true, curBaseInfo.hasBase);
1597 EXPECT_EQ(29, curBaseInfo.base.long_value);
1598 EXPECT_EQ(true, curInterval.hasValue);
1599
1600 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1601
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001602 ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
1603 ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
1604 ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
1605 ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
tsaichristine5adb1b12020-03-17 18:04:34 -07001606
1607 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
1608 EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
1609 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
1610 EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
1611 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
1612
1613 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
1614 EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
1615 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
1616}
1617
tsaichristine3ca4d782020-03-17 18:18:28 -07001618/*
1619 * Tests zero default base.
1620 */
1621TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
1622 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1623 metric.mutable_dimensions_in_what()->set_field(tagId);
1624 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1625 metric.set_use_zero_default_base(true);
1626
1627 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001628 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1629 .WillOnce(Invoke(
1630 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
1631 data->clear();
1632 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1633 return true;
1634 }));
tsaichristine3ca4d782020-03-17 18:18:28 -07001635
1636 sp<ValueMetricProducer> valueProducer =
1637 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1638
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001639 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001640 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1641 auto& interval1 = iter->second[0];
1642 auto iterBase = valueProducer->mCurrentBaseInfo.begin();
1643 auto& baseInfo1 = iterBase->second[0];
1644 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1645 EXPECT_EQ(true, baseInfo1.hasBase);
1646 EXPECT_EQ(3, baseInfo1.base.long_value);
1647 EXPECT_EQ(false, interval1.hasValue);
1648 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001649 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001650 vector<shared_ptr<LogEvent>> allData;
1651
1652 allData.clear();
1653 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1654 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1655
1656 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001657 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001658 EXPECT_EQ(true, baseInfo1.hasBase);
1659 EXPECT_EQ(11, baseInfo1.base.long_value);
1660 EXPECT_EQ(false, interval1.hasValue);
1661 EXPECT_EQ(8, interval1.value.long_value);
1662
1663 auto it = valueProducer->mCurrentSlicedBucket.begin();
1664 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1665 if (it != iter) {
1666 break;
1667 }
1668 }
1669 auto itBase = valueProducer->mCurrentBaseInfo.begin();
1670 for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
1671 if (itBase != iterBase) {
1672 break;
1673 }
1674 }
1675 EXPECT_TRUE(it != iter);
1676 EXPECT_TRUE(itBase != iterBase);
1677 auto& interval2 = it->second[0];
1678 auto& baseInfo2 = itBase->second[0];
1679 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1680 EXPECT_EQ(true, baseInfo2.hasBase);
1681 EXPECT_EQ(4, baseInfo2.base.long_value);
1682 EXPECT_EQ(false, interval2.hasValue);
1683 EXPECT_EQ(4, interval2.value.long_value);
1684
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001685 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001686 auto iterator = valueProducer->mPastBuckets.begin();
1687 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1688 EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1689 iterator++;
1690 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1691 EXPECT_EQ(4, iterator->second[0].values[0].long_value);
1692}
1693
1694/*
1695 * Tests using zero default base with failed pull.
1696 */
1697TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
1698 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1699 metric.mutable_dimensions_in_what()->set_field(tagId);
1700 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1701 metric.set_use_zero_default_base(true);
1702
1703 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001704 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1705 .WillOnce(Invoke(
1706 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
1707 data->clear();
1708 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1709 return true;
1710 }));
tsaichristine3ca4d782020-03-17 18:18:28 -07001711
1712 sp<ValueMetricProducer> valueProducer =
1713 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1714
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001715 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
Tej Singh547f4632020-03-25 00:32:05 -07001716 const auto& it = valueProducer->mCurrentSlicedBucket.begin();
1717 ValueMetricProducer::Interval& interval1 = it->second[0];
1718 ValueMetricProducer::BaseInfo& baseInfo1 =
tsaichristine3ca4d782020-03-17 18:18:28 -07001719 valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
1720 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1721 EXPECT_EQ(true, baseInfo1.hasBase);
1722 EXPECT_EQ(3, baseInfo1.base.long_value);
1723 EXPECT_EQ(false, interval1.hasValue);
1724 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001725 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001726 vector<shared_ptr<LogEvent>> allData;
1727
1728 allData.clear();
1729 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1730 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1731
1732 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001733 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001734 EXPECT_EQ(true, baseInfo1.hasBase);
1735 EXPECT_EQ(11, baseInfo1.base.long_value);
1736 EXPECT_EQ(false, interval1.hasValue);
1737 EXPECT_EQ(8, interval1.value.long_value);
1738
1739 auto it2 = valueProducer->mCurrentSlicedBucket.begin();
1740 for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
1741 if (it2 != it) {
1742 break;
1743 }
1744 }
tsaichristine3ca4d782020-03-17 18:18:28 -07001745 EXPECT_TRUE(it2 != it);
Tej Singh547f4632020-03-25 00:32:05 -07001746 ValueMetricProducer::Interval& interval2 = it2->second[0];
1747 ValueMetricProducer::BaseInfo& baseInfo2 =
tsaichristine3ca4d782020-03-17 18:18:28 -07001748 valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
1749 EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1750 EXPECT_EQ(true, baseInfo2.hasBase);
1751 EXPECT_EQ(4, baseInfo2.base.long_value);
1752 EXPECT_EQ(false, interval2.hasValue);
1753 EXPECT_EQ(4, interval2.value.long_value);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001754 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001755
1756 // next pull somehow did not happen, skip to end of bucket 3
1757 allData.clear();
1758 allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
1759 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1760
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001761 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001762 EXPECT_EQ(true, baseInfo2.hasBase);
1763 EXPECT_EQ(5, baseInfo2.base.long_value);
1764 EXPECT_EQ(false, interval2.hasValue);
1765 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001766 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001767
1768 allData.clear();
1769 allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 13));
1770 allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 1, 5));
1771 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1772
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001773 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
Tej Singh547f4632020-03-25 00:32:05 -07001774 // Get new references now that entries have been deleted from the map
1775 const auto& it3 = valueProducer->mCurrentSlicedBucket.begin();
1776 const auto& it4 = std::next(valueProducer->mCurrentSlicedBucket.begin());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001777 ASSERT_EQ(it3->second.size(), 1);
1778 ASSERT_EQ(it4->second.size(), 1);
Tej Singh547f4632020-03-25 00:32:05 -07001779 ValueMetricProducer::Interval& interval3 = it3->second[0];
1780 ValueMetricProducer::Interval& interval4 = it4->second[0];
1781 ValueMetricProducer::BaseInfo& baseInfo3 =
1782 valueProducer->mCurrentBaseInfo.find(it3->first.getDimensionKeyInWhat())->second[0];
1783 ValueMetricProducer::BaseInfo& baseInfo4 =
1784 valueProducer->mCurrentBaseInfo.find(it4->first.getDimensionKeyInWhat())->second[0];
tsaichristine3ca4d782020-03-17 18:18:28 -07001785
Tej Singh547f4632020-03-25 00:32:05 -07001786 EXPECT_EQ(true, baseInfo3.hasBase);
1787 EXPECT_EQ(5, baseInfo3.base.long_value);
1788 EXPECT_EQ(false, interval3.hasValue);
1789 EXPECT_EQ(5, interval3.value.long_value);
tsaichristine3ca4d782020-03-17 18:18:28 -07001790 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1791
Tej Singh547f4632020-03-25 00:32:05 -07001792 EXPECT_EQ(true, baseInfo4.hasBase);
1793 EXPECT_EQ(13, baseInfo4.base.long_value);
1794 EXPECT_EQ(false, interval4.hasValue);
1795 EXPECT_EQ(8, interval4.value.long_value);
tsaichristine3ca4d782020-03-17 18:18:28 -07001796
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001797 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001798}
1799
1800/*
1801 * Tests trim unused dimension key if no new data is seen in an entire bucket.
1802 */
1803TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
1804 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1805 metric.mutable_dimensions_in_what()->set_field(tagId);
1806 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1807
1808 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001809 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1810 .WillOnce(Invoke(
1811 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
1812 data->clear();
1813 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1814 return true;
1815 }));
tsaichristine3ca4d782020-03-17 18:18:28 -07001816
1817 sp<ValueMetricProducer> valueProducer =
1818 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1819
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001820 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001821 auto iter = valueProducer->mCurrentSlicedBucket.begin();
1822 auto& interval1 = iter->second[0];
1823 auto iterBase = valueProducer->mCurrentBaseInfo.begin();
1824 auto& baseInfo1 = iterBase->second[0];
1825 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1826 EXPECT_EQ(true, baseInfo1.hasBase);
1827 EXPECT_EQ(3, baseInfo1.base.long_value);
1828 EXPECT_EQ(false, interval1.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001829 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001830
Tej Singhe678cb72020-04-14 16:23:30 -07001831 vector<shared_ptr<LogEvent>> allData;
tsaichristine3ca4d782020-03-17 18:18:28 -07001832 allData.clear();
1833 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1834 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1835 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1836
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001837 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001838 EXPECT_EQ(true, baseInfo1.hasBase);
1839 EXPECT_EQ(11, baseInfo1.base.long_value);
1840 EXPECT_EQ(false, interval1.hasValue);
1841 EXPECT_EQ(8, interval1.value.long_value);
1842 EXPECT_FALSE(interval1.seenNewData);
Tej Singhe678cb72020-04-14 16:23:30 -07001843 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs},
1844 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine3ca4d782020-03-17 18:18:28 -07001845
1846 auto it = valueProducer->mCurrentSlicedBucket.begin();
1847 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1848 if (it != iter) {
1849 break;
1850 }
1851 }
1852 auto itBase = valueProducer->mCurrentBaseInfo.begin();
1853 for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
1854 if (itBase != iterBase) {
1855 break;
1856 }
1857 }
1858 EXPECT_TRUE(it != iter);
1859 EXPECT_TRUE(itBase != iterBase);
Tej Singhe678cb72020-04-14 16:23:30 -07001860 auto interval2 = it->second[0];
1861 auto baseInfo2 = itBase->second[0];
tsaichristine3ca4d782020-03-17 18:18:28 -07001862 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1863 EXPECT_EQ(true, baseInfo2.hasBase);
1864 EXPECT_EQ(4, baseInfo2.base.long_value);
1865 EXPECT_EQ(false, interval2.hasValue);
1866 EXPECT_FALSE(interval2.seenNewData);
tsaichristine3ca4d782020-03-17 18:18:28 -07001867
1868 // next pull somehow did not happen, skip to end of bucket 3
1869 allData.clear();
1870 allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
1871 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1872 // Only one interval left. One was trimmed.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001873 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001874 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1875 baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
1876 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1877 EXPECT_EQ(true, baseInfo2.hasBase);
1878 EXPECT_EQ(5, baseInfo2.base.long_value);
1879 EXPECT_EQ(false, interval2.hasValue);
1880 EXPECT_FALSE(interval2.seenNewData);
Tej Singhe678cb72020-04-14 16:23:30 -07001881 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs},
1882 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristine3ca4d782020-03-17 18:18:28 -07001883
1884 allData.clear();
1885 allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 14));
1886 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1887
1888 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
1889 baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
1890 EXPECT_EQ(true, baseInfo2.hasBase);
1891 EXPECT_EQ(14, baseInfo2.base.long_value);
1892 EXPECT_EQ(false, interval2.hasValue);
1893 EXPECT_FALSE(interval2.seenNewData);
1894 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1895 auto iterator = valueProducer->mPastBuckets.begin();
Tej Singhe678cb72020-04-14 16:23:30 -07001896 EXPECT_EQ(bucket4StartTimeNs, iterator->second[0].mBucketStartNs);
1897 EXPECT_EQ(bucket5StartTimeNs, iterator->second[0].mBucketEndNs);
tsaichristine3ca4d782020-03-17 18:18:28 -07001898 EXPECT_EQ(9, iterator->second[0].values[0].long_value);
1899 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1900 iterator++;
Tej Singhe678cb72020-04-14 16:23:30 -07001901 EXPECT_EQ(bucketStartTimeNs, iterator->second[0].mBucketStartNs);
1902 EXPECT_EQ(bucket2StartTimeNs, iterator->second[0].mBucketEndNs);
tsaichristine3ca4d782020-03-17 18:18:28 -07001903 EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1904 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1905}
1906
1907TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
1908 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1909
1910 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1911 // Used by onConditionChanged.
Tej Singh3be093b2020-03-04 20:08:38 -08001912 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1913 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1914 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07001915 data->clear();
1916 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1917 return true;
1918 }));
1919
1920 sp<ValueMetricProducer> valueProducer =
1921 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1922
1923 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1924 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001925 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001926 ValueMetricProducer::Interval& curInterval =
1927 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1928 ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1929 EXPECT_EQ(true, curBaseInfo.hasBase);
1930 EXPECT_EQ(100, curBaseInfo.base.long_value);
1931 EXPECT_EQ(false, curInterval.hasValue);
1932
1933 vector<shared_ptr<LogEvent>> allData;
1934 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001935 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001936 EXPECT_EQ(false, curBaseInfo.hasBase);
1937 EXPECT_EQ(false, curInterval.hasValue);
1938 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
1939}
1940
1941TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
1942 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1943
1944 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001945 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1946 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1947 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07001948 data->clear();
1949 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1950 return true;
1951 }))
1952 .WillOnce(Return(false));
1953
1954 sp<ValueMetricProducer> valueProducer =
1955 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1956
1957 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1958
1959 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001960 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001961 ValueMetricProducer::Interval& curInterval =
1962 valueProducer->mCurrentSlicedBucket.begin()->second[0];
1963 ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
1964 EXPECT_EQ(true, curBaseInfo.hasBase);
1965 EXPECT_EQ(100, curBaseInfo.base.long_value);
1966 EXPECT_EQ(false, curInterval.hasValue);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001967 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001968
1969 valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
1970
1971 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07001972 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07001973 EXPECT_EQ(false, curInterval.hasValue);
1974 EXPECT_EQ(false, curBaseInfo.hasBase);
1975 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
1976}
1977
1978TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
1979 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1980
1981 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08001982 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1983 .WillOnce(Invoke(
1984 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
1985 data->clear();
1986 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
1987 return false;
1988 }))
1989 .WillOnce(Invoke([](int tagId, const ConfigKey&,
1990 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07001991 data->clear();
1992 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1993 return true;
1994 }));
1995
1996 sp<ValueMetricProducer> valueProducer =
1997 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
1998
1999 // Don't directly set mCondition; the real code never does that. Go through regular code path
2000 // to avoid unexpected behaviors.
2001 // valueProducer->mCondition = ConditionState::kTrue;
2002 valueProducer->onConditionChanged(true, bucketStartTimeNs);
2003
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002004 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002005
2006 valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002007 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002008 ValueMetricProducer::Interval& curInterval =
2009 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2010 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2011 EXPECT_EQ(false, curBaseInfo.hasBase);
2012 EXPECT_EQ(false, curInterval.hasValue);
2013 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2014}
2015
2016TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
2017 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2018 metric.set_condition(StringToId("SCREEN_ON"));
2019 metric.set_max_pull_delay_sec(0);
2020
2021 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002022 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2023 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2024 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002025 data->clear();
2026 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
2027 return true;
2028 }));
2029
2030 sp<ValueMetricProducer> valueProducer =
2031 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2032
2033 valueProducer->mCondition = ConditionState::kFalse;
2034
2035 // Max delay is set to 0 so pull will exceed max delay.
2036 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002037 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002038}
2039
2040TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
2041 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2042
2043 UidMap uidMap;
2044 SimpleAtomMatcher atomMatcher;
2045 atomMatcher.set_atom_id(tagId);
2046 sp<EventMatcherWizard> eventMatcherWizard =
2047 new EventMatcherWizard({new SimpleLogMatchingTracker(
2048 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2049 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2050 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002051 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2052 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
tsaichristine3ca4d782020-03-17 18:18:28 -07002053
2054 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
2055 eventMatcherWizard, tagId, bucket2StartTimeNs,
2056 bucket2StartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08002057 valueProducer.prepareFirstBucket();
tsaichristine3ca4d782020-03-17 18:18:28 -07002058 valueProducer.mCondition = ConditionState::kFalse;
2059
2060 // Event should be skipped since it is from previous bucket.
2061 // Pull should not be called.
2062 valueProducer.onConditionChanged(true, bucketStartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002063 ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002064}
2065
2066TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
2067 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2068
2069 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002070 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2071 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2072 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002073 data->clear();
2074 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
2075 return true;
2076 }));
2077
2078 sp<ValueMetricProducer> valueProducer =
2079 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2080
2081 valueProducer->mCondition = ConditionState::kFalse;
2082 valueProducer->mHasGlobalBase = false;
2083
2084 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2085 valueProducer->mHasGlobalBase = true;
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002086 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002087 ValueMetricProducer::Interval& curInterval =
2088 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2089 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2090 EXPECT_EQ(true, curBaseInfo.hasBase);
2091 EXPECT_EQ(100, curBaseInfo.base.long_value);
2092 EXPECT_EQ(false, curInterval.hasValue);
2093 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2094}
2095
2096/*
2097 * Tests that a bucket is marked invalid when a condition change pull fails.
2098 */
2099TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
2100 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2101
2102 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002103 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine3ca4d782020-03-17 18:18:28 -07002104 // First onConditionChanged
2105 .WillOnce(Return(false))
2106 // Second onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002107 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2108 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002109 data->clear();
2110 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2111 return true;
2112 }));
2113
2114 sp<ValueMetricProducer> valueProducer =
2115 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2116
2117 valueProducer->mCondition = ConditionState::kTrue;
2118
2119 // Bucket start.
2120 vector<shared_ptr<LogEvent>> allData;
2121 allData.clear();
2122 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2123 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2124
2125 // This will fail and should invalidate the whole bucket since we do not have all the data
2126 // needed to compute the metric value when the screen was on.
2127 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2128 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2129
2130 // Bucket end.
2131 allData.clear();
2132 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2133 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2134
2135 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2136
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002137 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002138 // Contains base from last pull which was successful.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002139 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002140 ValueMetricProducer::Interval& curInterval =
2141 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2142 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2143 EXPECT_EQ(true, curBaseInfo.hasBase);
2144 EXPECT_EQ(140, curBaseInfo.base.long_value);
2145 EXPECT_EQ(false, curInterval.hasValue);
2146 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2147
2148 // Check dump report.
2149 ProtoOutputStream output;
2150 std::set<string> strSet;
2151 valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
2152 FAST /* dumpLatency */, &strSet, &output);
2153
2154 StatsLogReport report = outputStreamToProto(&output);
2155 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002156 ASSERT_EQ(0, report.value_metrics().data_size());
2157 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002158
2159 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2160 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2161 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2162 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002163 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002164
2165 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2166 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2167 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2168}
2169
2170/*
2171 * Tests that a bucket is marked invalid when the guardrail is hit.
2172 */
2173TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
2174 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2175 metric.mutable_dimensions_in_what()->set_field(tagId);
2176 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2177 metric.set_condition(StringToId("SCREEN_ON"));
2178
2179 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002180 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine3ca4d782020-03-17 18:18:28 -07002181 // First onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002182 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2183 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002184 for (int i = 0; i < 2000; i++) {
2185 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
2186 }
2187 return true;
2188 }));
2189
2190 sp<ValueMetricProducer> valueProducer =
2191 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2192 valueProducer->mCondition = ConditionState::kFalse;
2193
2194 valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
2195 EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002196 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2197 ASSERT_EQ(0UL, valueProducer->mSkippedBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002198
2199 // Bucket 2 start.
2200 vector<shared_ptr<LogEvent>> allData;
2201 allData.clear();
2202 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 10));
2203 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2204
2205 // First bucket added to mSkippedBuckets after flush.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002206 ASSERT_EQ(1UL, valueProducer->mSkippedBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002207
2208 // Check dump report.
2209 ProtoOutputStream output;
2210 std::set<string> strSet;
2211 valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2212 true, FAST /* dumpLatency */, &strSet, &output);
2213
2214 StatsLogReport report = outputStreamToProto(&output);
2215 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002216 ASSERT_EQ(0, report.value_metrics().data_size());
2217 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002218
2219 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2220 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2221 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2222 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002223 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002224
2225 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2226 EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
2227 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2228}
2229
2230/*
2231 * Tests that a bucket is marked invalid when the bucket's initial pull fails.
2232 */
2233TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
2234 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2235
2236 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002237 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine3ca4d782020-03-17 18:18:28 -07002238 // First onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002239 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2240 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002241 data->clear();
2242 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
2243 return true;
2244 }))
2245 // Second onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002246 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2247 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002248 data->clear();
2249 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2250 return true;
2251 }));
2252
2253 sp<ValueMetricProducer> valueProducer =
2254 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2255
2256 valueProducer->mCondition = ConditionState::kTrue;
2257
2258 // Bucket start.
2259 vector<shared_ptr<LogEvent>> allData;
2260 allData.clear();
tsaichristine8dca82e2020-04-07 09:40:03 -07002261 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
tsaichristine3ca4d782020-03-17 18:18:28 -07002262 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
2263
2264 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2265 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2266
2267 // Bucket end.
2268 allData.clear();
tsaichristine8dca82e2020-04-07 09:40:03 -07002269 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
tsaichristine3ca4d782020-03-17 18:18:28 -07002270 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2271
2272 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2273
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002274 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002275 // Contains base from last pull which was successful.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002276 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002277 ValueMetricProducer::Interval& curInterval =
2278 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2279 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2280 EXPECT_EQ(true, curBaseInfo.hasBase);
2281 EXPECT_EQ(140, curBaseInfo.base.long_value);
2282 EXPECT_EQ(false, curInterval.hasValue);
2283 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2284
2285 // Check dump report.
2286 ProtoOutputStream output;
2287 std::set<string> strSet;
2288 valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2289 true, FAST /* dumpLatency */, &strSet, &output);
2290
2291 StatsLogReport report = outputStreamToProto(&output);
2292 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002293 ASSERT_EQ(0, report.value_metrics().data_size());
2294 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002295
2296 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2297 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2298 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2299 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002300 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002301
2302 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2303 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2304 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2305}
2306
2307/*
2308 * Tests that a bucket is marked invalid when the bucket's final pull fails
2309 * (i.e. failed pull on bucket boundary).
2310 */
2311TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
2312 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2313
2314 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002315 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine3ca4d782020-03-17 18:18:28 -07002316 // First onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002317 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2318 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002319 data->clear();
2320 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
2321 return true;
2322 }))
2323 // Second onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002324 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2325 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristine3ca4d782020-03-17 18:18:28 -07002326 data->clear();
2327 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2328 return true;
2329 }));
2330
2331 sp<ValueMetricProducer> valueProducer =
2332 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2333
2334 valueProducer->mCondition = ConditionState::kTrue;
2335
2336 // Bucket start.
2337 vector<shared_ptr<LogEvent>> allData;
2338 allData.clear();
2339 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2340 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2341
2342 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2343 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2344
2345 // Bucket end.
2346 allData.clear();
2347 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2348 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2349
2350 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2351
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002352 ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002353 // Last pull failed so base has been reset.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002354 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002355 ValueMetricProducer::Interval& curInterval =
2356 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2357 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2358 EXPECT_EQ(false, curBaseInfo.hasBase);
2359 EXPECT_EQ(false, curInterval.hasValue);
2360 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2361
2362 // Check dump report.
2363 ProtoOutputStream output;
2364 std::set<string> strSet;
2365 valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2366 true, FAST /* dumpLatency */, &strSet, &output);
2367
2368 StatsLogReport report = outputStreamToProto(&output);
2369 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002370 ASSERT_EQ(0, report.value_metrics().data_size());
2371 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002372
2373 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2374 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2375 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2376 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002377 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002378
2379 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2380 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2381 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
2382}
2383
2384TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
2385 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2386 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002387 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristine3ca4d782020-03-17 18:18:28 -07002388 // Start bucket.
Tej Singh3be093b2020-03-04 20:08:38 -08002389 .WillOnce(Invoke(
2390 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2391 data->clear();
2392 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2393 return true;
2394 }));
tsaichristine3ca4d782020-03-17 18:18:28 -07002395
2396 sp<ValueMetricProducer> valueProducer =
2397 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2398
2399 // Bucket 2 start.
2400 vector<shared_ptr<LogEvent>> allData;
2401 allData.clear();
2402 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
2403 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002404 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2405 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002406
2407 // Bucket 3 empty.
2408 allData.clear();
2409 allData.push_back(CreateNoValuesLogEvent(tagId, bucket3StartTimeNs + 1));
2410 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
2411 // Data has been trimmed.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002412 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2413 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
tsaichristine3ca4d782020-03-17 18:18:28 -07002414}
tsaichristineb828fe22020-03-17 18:25:37 -07002415
2416TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
2417 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2418
2419 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002420 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002421 // First onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002422 .WillOnce(Invoke(
2423 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2424 data->clear();
2425 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2426 return true;
2427 }))
2428 .WillOnce(Invoke(
2429 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2430 data->clear();
2431 return true;
2432 }));
tsaichristineb828fe22020-03-17 18:25:37 -07002433
2434 sp<ValueMetricProducer> valueProducer =
2435 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2436
2437 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002438 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002439 ValueMetricProducer::Interval& curInterval =
2440 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2441 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2442 EXPECT_EQ(true, curBaseInfo.hasBase);
2443 EXPECT_EQ(false, curInterval.hasValue);
2444 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2445
2446 // Empty pull.
2447 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002448 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002449 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2450 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2451 EXPECT_EQ(false, curBaseInfo.hasBase);
2452 EXPECT_EQ(false, curInterval.hasValue);
2453 EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2454}
2455
2456TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
2457 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2458
2459 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002460 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002461 // First onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002462 .WillOnce(Invoke(
2463 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2464 data->clear();
2465 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2466 return true;
2467 }))
2468 .WillOnce(Invoke(
2469 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2470 data->clear();
2471 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
2472 return true;
2473 }))
2474 .WillOnce(Invoke(
2475 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2476 data->clear();
2477 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
2478 return true;
2479 }));
tsaichristineb828fe22020-03-17 18:25:37 -07002480
2481 sp<ValueMetricProducer> valueProducer =
2482 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2483
2484 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2485 valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
2486 valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002487 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002488 ValueMetricProducer::Interval& curInterval =
2489 valueProducer->mCurrentSlicedBucket.begin()->second[0];
2490 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2491 EXPECT_EQ(true, curBaseInfo.hasBase);
2492 EXPECT_EQ(true, curInterval.hasValue);
2493 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2494
2495 // End of bucket
2496 vector<shared_ptr<LogEvent>> allData;
2497 allData.clear();
2498 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002499 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002500 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2501 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2502 // Data is empty, base should be reset.
2503 EXPECT_EQ(false, curBaseInfo.hasBase);
2504 EXPECT_EQ(5, curBaseInfo.base.long_value);
2505 EXPECT_EQ(false, curInterval.hasValue);
2506 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2507
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002508 ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
Tej Singhe678cb72020-04-14 16:23:30 -07002509 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1},
2510 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002511}
2512
2513TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
2514 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2515 metric.mutable_dimensions_in_what()->set_field(tagId);
2516 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2517 metric.set_condition(StringToId("SCREEN_ON"));
2518
2519 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002520 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002521 // First onConditionChanged
Tej Singh3be093b2020-03-04 20:08:38 -08002522 .WillOnce(Invoke(
2523 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2524 data->clear();
2525 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2526 return true;
2527 }));
tsaichristineb828fe22020-03-17 18:25:37 -07002528
2529 sp<ValueMetricProducer> valueProducer =
2530 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2531
2532 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002533 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002534
2535 // End of bucket
2536 vector<shared_ptr<LogEvent>> allData;
2537 allData.clear();
2538 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 2));
2539 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2540
2541 // Key 1 should be reset since in not present in the most pull.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002542 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002543 auto iterator = valueProducer->mCurrentSlicedBucket.begin();
2544 auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
2545 EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
2546 EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
2547 EXPECT_EQ(false, iterator->second[0].hasValue);
2548 iterator++;
2549 baseInfoIter++;
2550 EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
2551 EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
2552 EXPECT_EQ(false, iterator->second[0].hasValue);
2553
2554 EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2555}
2556
Tej Singhe678cb72020-04-14 16:23:30 -07002557TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketInvalid) {
tsaichristineb828fe22020-03-17 18:25:37 -07002558 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2559
2560 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singhe678cb72020-04-14 16:23:30 -07002561 int64_t partialBucketSplitTimeNs = bucketStartTimeNs + bucketSizeNs / 2;
Tej Singh3be093b2020-03-04 20:08:38 -08002562 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002563 // Initialization.
Tej Singh3be093b2020-03-04 20:08:38 -08002564 .WillOnce(Invoke(
2565 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2566 data->clear();
2567 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2568 return true;
2569 }))
tsaichristineb828fe22020-03-17 18:25:37 -07002570 // notifyAppUpgrade.
Tej Singhe678cb72020-04-14 16:23:30 -07002571 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
2572 vector<std::shared_ptr<LogEvent>>* data,
2573 bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002574 data->clear();
Tej Singhe678cb72020-04-14 16:23:30 -07002575 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
tsaichristineb828fe22020-03-17 18:25:37 -07002576 return true;
2577 }));
2578 sp<ValueMetricProducer> valueProducer =
2579 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2580 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2581
Tej Singhe678cb72020-04-14 16:23:30 -07002582 switch (GetParam()) {
2583 case APP_UPGRADE:
2584 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
2585 break;
2586 case BOOT_COMPLETE:
2587 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
2588 break;
2589 }
2590 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
2591 EXPECT_EQ(0, valueProducer->getCurrentBucketNum());
2592 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
2593 {partialBucketSplitTimeNs - bucketStartTimeNs},
2594 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002595 ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
2596
2597 vector<shared_ptr<LogEvent>> allData;
2598 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 4));
2599 valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
Tej Singhe678cb72020-04-14 16:23:30 -07002600 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
2601 {partialBucketSplitTimeNs - bucketStartTimeNs},
2602 {bucketStartTimeNs}, {partialBucketSplitTimeNs});
2603 ASSERT_EQ(1, valueProducer->mSkippedBuckets.size());
2604 EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
2605 EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
tsaichristineb828fe22020-03-17 18:25:37 -07002606 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2607}
2608
2609TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
2610 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2611 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002612 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002613 // Second onConditionChanged.
Tej Singh3be093b2020-03-04 20:08:38 -08002614 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2615 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002616 data->clear();
2617 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
2618 return true;
2619 }))
2620 // Third onConditionChanged.
Tej Singh3be093b2020-03-04 20:08:38 -08002621 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2622 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002623 data->clear();
2624 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
2625 return true;
2626 }));
2627
2628 sp<ValueMetricProducer> valueProducer =
2629 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2630 valueProducer->mCondition = ConditionState::kUnknown;
2631
2632 valueProducer->onConditionChanged(false, bucketStartTimeNs);
2633 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2634
2635 // End of first bucket
2636 vector<shared_ptr<LogEvent>> allData;
2637 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 4));
2638 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2639 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2640
2641 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2642 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2643 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2644 auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2645 EXPECT_EQ(true, curBaseInfo.hasBase);
2646 EXPECT_EQ(5, curBaseInfo.base.long_value);
2647 EXPECT_EQ(false, curInterval.hasValue);
2648
2649 valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
2650
2651 // Bucket should have been completed.
Tej Singhe678cb72020-04-14 16:23:30 -07002652 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10},
2653 {bucket2StartTimeNs}, {bucket3StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002654}
2655
2656TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
2657 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2658 metric.set_use_diff(false);
2659
2660 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2661 sp<ValueMetricProducer> valueProducer =
2662 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2663
2664 vector<shared_ptr<LogEvent>> allData;
2665 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2666 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2667
2668 allData.clear();
2669 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2670 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2671
2672 // Bucket should have been completed.
Tej Singhe678cb72020-04-14 16:23:30 -07002673 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs},
2674 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002675}
2676
2677TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
2678 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2679
2680 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002681 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002682 // Initialization.
Tej Singh3be093b2020-03-04 20:08:38 -08002683 .WillOnce(Invoke(
2684 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2685 data->clear();
2686 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2687 return true;
2688 }));
tsaichristineb828fe22020-03-17 18:25:37 -07002689
2690 sp<ValueMetricProducer> valueProducer =
2691 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2692
2693 vector<shared_ptr<LogEvent>> allData;
2694 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2695 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2696
2697 allData.clear();
2698 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2699 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2700
2701 // Bucket should have been completed.
Tej Singhe678cb72020-04-14 16:23:30 -07002702 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs},
2703 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002704}
2705
Tej Singhe678cb72020-04-14 16:23:30 -07002706TEST_P(ValueMetricProducerTest_PartialBucket, TestBucketBoundariesOnPartialBucket) {
tsaichristineb828fe22020-03-17 18:25:37 -07002707 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2708
Tej Singhe678cb72020-04-14 16:23:30 -07002709 int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
tsaichristineb828fe22020-03-17 18:25:37 -07002710 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002711 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002712 // Initialization.
Tej Singh3be093b2020-03-04 20:08:38 -08002713 .WillOnce(Invoke(
2714 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2715 data->clear();
2716 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2717 return true;
2718 }))
tsaichristineb828fe22020-03-17 18:25:37 -07002719 // notifyAppUpgrade.
Tej Singhe678cb72020-04-14 16:23:30 -07002720 .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
2721 vector<std::shared_ptr<LogEvent>>* data,
2722 bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002723 data->clear();
Tej Singhe678cb72020-04-14 16:23:30 -07002724 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
tsaichristineb828fe22020-03-17 18:25:37 -07002725 return true;
2726 }));
2727
2728 sp<ValueMetricProducer> valueProducer =
2729 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2730
Tej Singhe678cb72020-04-14 16:23:30 -07002731 switch (GetParam()) {
2732 case APP_UPGRADE:
2733 valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
2734 break;
2735 case BOOT_COMPLETE:
2736 valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
2737 break;
2738 }
tsaichristineb828fe22020-03-17 18:25:37 -07002739
2740 // Bucket should have been completed.
Tej Singhe678cb72020-04-14 16:23:30 -07002741 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs},
2742 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002743}
2744
2745TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
2746 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2747
2748 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002749 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002750 // First on condition changed.
Tej Singh3be093b2020-03-04 20:08:38 -08002751 .WillOnce(Invoke(
2752 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2753 data->clear();
2754 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2755 return true;
2756 }))
tsaichristineb828fe22020-03-17 18:25:37 -07002757 // Second on condition changed.
Tej Singh3be093b2020-03-04 20:08:38 -08002758 .WillOnce(Invoke(
2759 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2760 data->clear();
2761 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2762 return true;
2763 }));
tsaichristineb828fe22020-03-17 18:25:37 -07002764
2765 sp<ValueMetricProducer> valueProducer =
2766 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2767
2768 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
2769 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
Tej Singhe678cb72020-04-14 16:23:30 -07002770 valueProducer->onConditionChanged(false, bucketStartTimeNs + 12);
tsaichristineb828fe22020-03-17 18:25:37 -07002771
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002772 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07002773 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
2774 auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
2775 EXPECT_EQ(true, curInterval.hasValue);
2776 EXPECT_EQ(2, curInterval.value.long_value);
2777
2778 vector<shared_ptr<LogEvent>> allData;
2779 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 10));
2780 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2781
Tej Singhe678cb72020-04-14 16:23:30 -07002782 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2}, {bucketStartTimeNs},
2783 {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002784}
2785
2786// TODO: b/145705635 fix or delete this test
2787TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
2788 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2789
2790 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002791 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002792 // First condition change.
Tej Singh3be093b2020-03-04 20:08:38 -08002793 .WillOnce(Invoke(
2794 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2795 data->clear();
2796 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2797 return true;
2798 }))
tsaichristineb828fe22020-03-17 18:25:37 -07002799 // 2nd condition change.
Tej Singh3be093b2020-03-04 20:08:38 -08002800 .WillOnce(Invoke(
2801 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2802 data->clear();
2803 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
2804 return true;
2805 }))
tsaichristineb828fe22020-03-17 18:25:37 -07002806 // 3rd condition change.
Tej Singh3be093b2020-03-04 20:08:38 -08002807 .WillOnce(Invoke(
2808 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
2809 data->clear();
2810 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
2811 return true;
2812 }));
tsaichristineb828fe22020-03-17 18:25:37 -07002813
2814 sp<ValueMetricProducer> valueProducer =
2815 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
2816 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2817
2818 vector<shared_ptr<LogEvent>> allData;
2819 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 3, 10));
2820 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
2821
2822 allData.clear();
2823 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2824 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2825
2826 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
2827 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2828
2829 allData.clear();
2830 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 30));
2831 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2832
2833 // There was not global base available so all buckets are invalid.
Tej Singhe678cb72020-04-14 16:23:30 -07002834 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
tsaichristineb828fe22020-03-17 18:25:37 -07002835}
2836
2837TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
2838 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2839
2840 UidMap uidMap;
2841 SimpleAtomMatcher atomMatcher;
2842 atomMatcher.set_atom_id(tagId);
2843 sp<EventMatcherWizard> eventMatcherWizard =
2844 new EventMatcherWizard({new SimpleLogMatchingTracker(
2845 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2846 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2847 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002848 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2849 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
tsaichristineb828fe22020-03-17 18:25:37 -07002850
Tej Singh3be093b2020-03-04 20:08:38 -08002851 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002852 // Initial pull.
Tej Singh3be093b2020-03-04 20:08:38 -08002853 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2854 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002855 data->clear();
2856 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2857 return true;
2858 }));
2859
2860 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
2861 eventMatcherWizard, tagId, bucketStartTimeNs,
2862 bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08002863 valueProducer.prepareFirstBucket();
tsaichristineb828fe22020-03-17 18:25:37 -07002864
2865 ProtoOutputStream output;
2866 std::set<string> strSet;
2867 valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
2868 FAST, &strSet, &output);
2869
2870 StatsLogReport report = outputStreamToProto(&output);
2871 // Bucket is invalid since we did not pull when dump report was called.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002872 ASSERT_EQ(0, report.value_metrics().data_size());
tsaichristineb828fe22020-03-17 18:25:37 -07002873}
2874
2875TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
2876 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2877
2878 UidMap uidMap;
2879 SimpleAtomMatcher atomMatcher;
2880 atomMatcher.set_atom_id(tagId);
2881 sp<EventMatcherWizard> eventMatcherWizard =
2882 new EventMatcherWizard({new SimpleLogMatchingTracker(
2883 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2884 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2885 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002886 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2887 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
tsaichristineb828fe22020-03-17 18:25:37 -07002888
Tej Singh3be093b2020-03-04 20:08:38 -08002889 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002890 // Initial pull.
Tej Singh3be093b2020-03-04 20:08:38 -08002891 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2892 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002893 data->clear();
2894 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2895 return true;
2896 }));
2897
2898 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
2899 eventMatcherWizard, tagId, bucketStartTimeNs,
2900 bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08002901 valueProducer.prepareFirstBucket();
tsaichristineb828fe22020-03-17 18:25:37 -07002902
2903 vector<shared_ptr<LogEvent>> allData;
2904 allData.clear();
2905 allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, tagId, 2, 2));
2906 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2907
2908 ProtoOutputStream output;
2909 std::set<string> strSet;
2910 valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
2911 &strSet, &output);
2912
2913 StatsLogReport report = outputStreamToProto(&output);
2914 // Previous bucket is part of the report.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002915 ASSERT_EQ(1, report.value_metrics().data_size());
tsaichristineb828fe22020-03-17 18:25:37 -07002916 EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
2917}
2918
2919TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
2920 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2921
2922 UidMap uidMap;
2923 SimpleAtomMatcher atomMatcher;
2924 atomMatcher.set_atom_id(tagId);
2925 sp<EventMatcherWizard> eventMatcherWizard =
2926 new EventMatcherWizard({new SimpleLogMatchingTracker(
2927 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
2928 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2929 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002930 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2931 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
tsaichristineb828fe22020-03-17 18:25:37 -07002932
Tej Singh3be093b2020-03-04 20:08:38 -08002933 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002934 // Initial pull.
Tej Singh3be093b2020-03-04 20:08:38 -08002935 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2936 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002937 data->clear();
2938 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2939 return true;
2940 }))
Tej Singh3be093b2020-03-04 20:08:38 -08002941 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2942 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002943 data->clear();
2944 data->push_back(
2945 CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
2946 return true;
2947 }));
2948
2949 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
2950 eventMatcherWizard, tagId, bucketStartTimeNs,
2951 bucketStartTimeNs, pullerManager);
Tej Singh3be093b2020-03-04 20:08:38 -08002952 valueProducer.prepareFirstBucket();
tsaichristineb828fe22020-03-17 18:25:37 -07002953
2954 ProtoOutputStream output;
2955 std::set<string> strSet;
2956 valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
2957 NO_TIME_CONSTRAINTS, &strSet, &output);
2958
2959 StatsLogReport report = outputStreamToProto(&output);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07002960 ASSERT_EQ(1, report.value_metrics().data_size());
2961 ASSERT_EQ(1, report.value_metrics().data(0).bucket_info_size());
tsaichristineb828fe22020-03-17 18:25:37 -07002962 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
2963}
2964
2965TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
2966 ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2967 metric.set_use_diff(false);
2968
2969 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2970 sp<ValueMetricProducer> valueProducer =
2971 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2972
2973 vector<shared_ptr<LogEvent>> allData;
2974 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 10));
2975 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
2976
2977 // Bucket should have been completed.
Tej Singhe678cb72020-04-14 16:23:30 -07002978 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs},
2979 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07002980}
2981
2982TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
2983 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2984 metric.set_use_diff(false);
2985
2986 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08002987 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07002988 // condition becomes true
Tej Singh3be093b2020-03-04 20:08:38 -08002989 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2990 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002991 data->clear();
2992 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2993 return true;
2994 }))
2995 // condition becomes false
Tej Singh3be093b2020-03-04 20:08:38 -08002996 .WillOnce(Invoke([](int tagId, const ConfigKey&,
2997 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07002998 data->clear();
2999 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
3000 return true;
3001 }));
3002 sp<ValueMetricProducer> valueProducer =
3003 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3004 valueProducer->mCondition = ConditionState::kFalse;
3005
3006 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3007 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3008 // has one slice
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003009 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristineb828fe22020-03-17 18:25:37 -07003010 ValueMetricProducer::Interval curInterval =
3011 valueProducer->mCurrentSlicedBucket.begin()->second[0];
3012 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
3013 EXPECT_EQ(false, curBaseInfo.hasBase);
3014 EXPECT_EQ(true, curInterval.hasValue);
3015 EXPECT_EQ(20, curInterval.value.long_value);
3016
3017 // Now the alarm is delivered. Condition is off though.
3018 vector<shared_ptr<LogEvent>> allData;
3019 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
3020 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3021
Tej Singhe678cb72020-04-14 16:23:30 -07003022 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8},
3023 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07003024 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
3025 curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
3026 EXPECT_EQ(false, curBaseInfo.hasBase);
3027 EXPECT_EQ(false, curInterval.hasValue);
3028}
3029
3030TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
3031 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3032 metric.set_use_diff(false);
3033
3034 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003035 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003036 // condition becomes true
Tej Singh3be093b2020-03-04 20:08:38 -08003037 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3038 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003039 data->clear();
3040 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3041 return true;
3042 }));
3043 sp<ValueMetricProducer> valueProducer =
3044 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3045 valueProducer->mCondition = ConditionState::kFalse;
3046
3047 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3048
3049 // Now the alarm is delivered. Condition is off though.
3050 vector<shared_ptr<LogEvent>> allData;
3051 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3052 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3053
Tej Singhe678cb72020-04-14 16:23:30 -07003054 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8},
3055 {bucketStartTimeNs}, {bucket2StartTimeNs});
tsaichristineb828fe22020-03-17 18:25:37 -07003056 ValueMetricProducer::Interval curInterval =
3057 valueProducer->mCurrentSlicedBucket.begin()->second[0];
3058 ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
3059 EXPECT_EQ(false, curBaseInfo.hasBase);
3060 EXPECT_EQ(false, curInterval.hasValue);
3061}
3062
3063TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
3064 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3065 metric.set_use_diff(false);
3066
3067 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3068 sp<ValueMetricProducer> valueProducer =
3069 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3070 valueProducer->mCondition = ConditionState::kFalse;
3071
3072 // Now the alarm is delivered. Condition is off though.
3073 vector<shared_ptr<LogEvent>> allData;
3074 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3075 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3076
3077 // Condition was always false.
Tej Singhe678cb72020-04-14 16:23:30 -07003078 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
tsaichristineb828fe22020-03-17 18:25:37 -07003079}
3080
3081TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
3082 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3083 metric.set_use_diff(false);
3084
3085 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003086 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003087 // condition becomes true
Tej Singh3be093b2020-03-04 20:08:38 -08003088 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3089 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003090 data->clear();
3091 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3092 return true;
3093 }))
3094 .WillOnce(Return(false));
3095 sp<ValueMetricProducer> valueProducer =
3096 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3097 valueProducer->mCondition = ConditionState::kFalse;
3098
3099 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3100 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3101
3102 // Now the alarm is delivered. Condition is off though.
3103 vector<shared_ptr<LogEvent>> allData;
3104 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3105 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3106
3107 // No buckets, we had a failure.
Tej Singhe678cb72020-04-14 16:23:30 -07003108 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
tsaichristineb828fe22020-03-17 18:25:37 -07003109}
3110
3111/*
3112 * Test that DUMP_REPORT_REQUESTED dump reason is logged.
3113 *
3114 * For the bucket to be marked invalid during a dump report requested,
3115 * three things must be true:
3116 * - we want to include the current partial bucket
3117 * - we need a pull (metric is pulled and condition is true)
3118 * - the dump latency must be FAST
3119 */
3120
3121TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
3122 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3123
3124 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003125 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003126 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003127 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3128 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003129 data->clear();
3130 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
3131 return true;
3132 }));
3133
3134 sp<ValueMetricProducer> valueProducer =
3135 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3136
3137 // Condition change event.
3138 valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
3139
3140 // Check dump report.
3141 ProtoOutputStream output;
3142 std::set<string> strSet;
3143 valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
3144 FAST /* dumpLatency */, &strSet, &output);
3145
3146 StatsLogReport report = outputStreamToProto(&output);
3147 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003148 ASSERT_EQ(0, report.value_metrics().data_size());
3149 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003150
3151 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3152 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3153 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
3154 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003155 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003156
3157 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3158 EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
3159 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
3160}
3161
3162/*
3163 * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
3164 * change event (i.e. the condition change occurs in the wrong bucket).
3165 */
3166TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
3167 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3168
3169 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003170 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003171 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003172 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3173 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003174 data->clear();
3175 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3176 return true;
3177 }));
3178
3179 sp<ValueMetricProducer> valueProducer =
3180 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3181
3182 // Condition change event.
3183 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3184
3185 // Bucket boundary pull.
3186 vector<shared_ptr<LogEvent>> allData;
3187 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
3188 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
3189
3190 // Late condition change event.
3191 valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
3192
3193 // Check dump report.
3194 ProtoOutputStream output;
3195 std::set<string> strSet;
3196 valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
3197 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3198
3199 StatsLogReport report = outputStreamToProto(&output);
3200 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003201 ASSERT_EQ(1, report.value_metrics().data_size());
3202 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003203
3204 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3205 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3206 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
3207 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003208 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003209
3210 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3211 EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
3212 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
3213}
3214
3215/*
3216 * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
3217 * event (i.e. the accumulate events call occurs in the wrong bucket).
3218 */
3219TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
3220 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3221
3222 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003223 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003224 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003225 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3226 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003227 data->clear();
3228 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3229 return true;
3230 }))
3231 // Dump report requested.
Tej Singh3be093b2020-03-04 20:08:38 -08003232 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3233 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003234 data->clear();
3235 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
3236 return true;
3237 }));
3238
3239 sp<ValueMetricProducer> valueProducer =
3240 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3241
3242 // Condition change event.
3243 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3244
3245 // Bucket boundary pull.
3246 vector<shared_ptr<LogEvent>> allData;
3247 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
3248 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
3249
3250 allData.clear();
3251 allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 20));
3252
3253 // Late accumulateEvents event.
3254 valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
3255
3256 // Check dump report.
3257 ProtoOutputStream output;
3258 std::set<string> strSet;
3259 valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
3260 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3261
3262 StatsLogReport report = outputStreamToProto(&output);
3263 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003264 ASSERT_EQ(1, report.value_metrics().data_size());
3265 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003266
3267 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3268 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3269 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
3270 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003271 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003272
3273 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3274 EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
3275 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
3276}
3277
3278/*
3279 * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
3280 * when a metric is initialized.
3281 */
3282TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
3283 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3284
3285 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003286 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003287 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003288 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3289 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003290 data->clear();
3291 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3292 return true;
3293 }))
3294 // Dump report requested.
Tej Singh3be093b2020-03-04 20:08:38 -08003295 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3296 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003297 data->clear();
3298 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
3299 return true;
3300 }));
3301
3302 sp<ValueMetricProducer> valueProducer =
3303 ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
3304 metric);
3305
3306 // Condition change event.
3307 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3308
3309 // Check dump report.
3310 ProtoOutputStream output;
3311 std::set<string> strSet;
3312 int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
3313 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3314 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3315
3316 StatsLogReport report = outputStreamToProto(&output);
3317 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003318 ASSERT_EQ(0, report.value_metrics().data_size());
3319 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003320
3321 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3322 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3323 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3324 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003325 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003326
3327 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3328 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3329 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3330}
3331
3332/*
3333 * Test that PULL_FAILED dump reason is logged due to a pull failure in
3334 * #pullAndMatchEventsLocked.
3335 */
3336TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
3337 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3338
3339 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003340 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristineb828fe22020-03-17 18:25:37 -07003341 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003342 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3343 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristineb828fe22020-03-17 18:25:37 -07003344 data->clear();
3345 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3346 return true;
3347 }))
3348 // Dump report requested, pull fails.
3349 .WillOnce(Return(false));
3350
3351 sp<ValueMetricProducer> valueProducer =
3352 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3353
3354 // Condition change event.
3355 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3356
3357 // Check dump report.
3358 ProtoOutputStream output;
3359 std::set<string> strSet;
3360 int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
3361 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3362 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3363
3364 StatsLogReport report = outputStreamToProto(&output);
3365 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003366 ASSERT_EQ(0, report.value_metrics().data_size());
3367 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003368
3369 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3370 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3371 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3372 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003373 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristineb828fe22020-03-17 18:25:37 -07003374
3375 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3376 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3377 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3378}
3379
tsaichristinee5405ba2020-03-17 18:34:08 -07003380/*
3381 * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
3382 * skips over more than one bucket.
3383 */
3384TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
3385 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3386
3387 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003388 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003389 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003390 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3391 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003392 data->clear();
3393 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3394 return true;
3395 }))
3396 // Dump report requested.
Tej Singh3be093b2020-03-04 20:08:38 -08003397 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3398 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003399 data->clear();
3400 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
3401 return true;
3402 }));
3403
3404 sp<ValueMetricProducer> valueProducer =
3405 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3406
3407 // Condition change event.
3408 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3409
3410 // Condition change event that skips forward by three buckets.
3411 valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
3412
3413 // Check dump report.
3414 ProtoOutputStream output;
3415 std::set<string> strSet;
3416 valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
3417 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3418
3419 StatsLogReport report = outputStreamToProto(&output);
3420 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003421 ASSERT_EQ(0, report.value_metrics().data_size());
3422 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003423
3424 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3425 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3426 EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3427 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003428 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003429
3430 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3431 EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
3432 EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
3433}
3434
3435/*
3436 * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
3437 * is smaller than the "min_bucket_size_nanos" specified in the metric config.
3438 */
3439TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
3440 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3441 metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
3442
3443 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003444 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003445 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003446 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3447 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003448 data->clear();
3449 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3450 return true;
3451 }))
3452 // Dump report requested.
Tej Singh3be093b2020-03-04 20:08:38 -08003453 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3454 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003455 data->clear();
3456 data->push_back(
3457 CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15));
3458 return true;
3459 }));
3460
3461 sp<ValueMetricProducer> valueProducer =
3462 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
3463
3464 // Condition change event.
3465 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3466
3467 // Check dump report.
3468 ProtoOutputStream output;
3469 std::set<string> strSet;
3470 int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
3471 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3472 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3473
3474 StatsLogReport report = outputStreamToProto(&output);
3475 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003476 ASSERT_EQ(0, report.value_metrics().data_size());
3477 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003478
3479 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3480 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3481 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3482 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003483 ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003484
3485 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3486 EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
3487 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3488}
3489
3490/*
3491 * Test multiple bucket drop events in the same bucket.
3492 */
3493TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
3494 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3495
3496 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003497 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003498 // Condition change to true.
Tej Singh3be093b2020-03-04 20:08:38 -08003499 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3500 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003501 data->clear();
3502 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3503 return true;
3504 }));
3505
3506 sp<ValueMetricProducer> valueProducer =
3507 ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
3508 metric);
3509
3510 // Condition change event.
3511 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3512
3513 // Check dump report.
3514 ProtoOutputStream output;
3515 std::set<string> strSet;
3516 int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
3517 valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3518 FAST /* dumpLatency */, &strSet, &output);
3519
3520 StatsLogReport report = outputStreamToProto(&output);
3521 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003522 ASSERT_EQ(0, report.value_metrics().data_size());
3523 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003524
3525 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3526 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3527 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3528 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003529 ASSERT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003530
3531 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3532 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3533 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
3534
3535 dropEvent = report.value_metrics().skipped(0).drop_event(1);
3536 EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
3537 EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3538}
3539
3540/*
3541 * Test that the number of logged bucket drop events is capped at the maximum.
3542 * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
3543 */
3544TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
3545 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3546
3547 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003548 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003549 // First condition change event.
Tej Singh3be093b2020-03-04 20:08:38 -08003550 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3551 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003552 for (int i = 0; i < 2000; i++) {
3553 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
3554 }
3555 return true;
3556 }))
3557 .WillOnce(Return(false))
3558 .WillOnce(Return(false))
3559 .WillOnce(Return(false))
3560 .WillOnce(Return(false))
3561 .WillOnce(Return(false))
3562 .WillOnce(Return(false))
3563 .WillOnce(Return(false))
3564 .WillOnce(Return(false))
3565 .WillOnce(Return(false))
Tej Singh3be093b2020-03-04 20:08:38 -08003566 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3567 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003568 data->clear();
3569 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
3570 return true;
3571 }));
3572
3573 sp<ValueMetricProducer> valueProducer =
3574 ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
3575 metric);
3576
3577 // First condition change event causes guardrail to be reached.
3578 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3579
3580 // 2-10 condition change events result in failed pulls.
3581 valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
3582 valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3583 valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
3584 valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
3585 valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
3586 valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
3587 valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
3588 valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
3589 valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
3590
3591 // Condition change event 11
3592 valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
3593
3594 // Check dump report.
3595 ProtoOutputStream output;
3596 std::set<string> strSet;
3597 int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
3598 // Because we already have 10 dump events in the current bucket,
3599 // this case should not be added to the list of dump events.
3600 valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
3601 FAST /* dumpLatency */, &strSet, &output);
3602
3603 StatsLogReport report = outputStreamToProto(&output);
3604 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003605 ASSERT_EQ(0, report.value_metrics().data_size());
3606 ASSERT_EQ(1, report.value_metrics().skipped_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003607
3608 EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3609 report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3610 EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3611 report.value_metrics().skipped(0).end_bucket_elapsed_millis());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003612 ASSERT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003613
3614 auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3615 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3616 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
3617
3618 dropEvent = report.value_metrics().skipped(0).drop_event(1);
3619 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3620 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
3621
3622 dropEvent = report.value_metrics().skipped(0).drop_event(2);
3623 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3624 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
3625
3626 dropEvent = report.value_metrics().skipped(0).drop_event(3);
3627 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3628 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
3629
3630 dropEvent = report.value_metrics().skipped(0).drop_event(4);
3631 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3632 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
3633
3634 dropEvent = report.value_metrics().skipped(0).drop_event(5);
3635 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3636 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
3637
3638 dropEvent = report.value_metrics().skipped(0).drop_event(6);
3639 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3640 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
3641
3642 dropEvent = report.value_metrics().skipped(0).drop_event(7);
3643 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3644 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
3645
3646 dropEvent = report.value_metrics().skipped(0).drop_event(8);
3647 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3648 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
3649
3650 dropEvent = report.value_metrics().skipped(0).drop_event(9);
3651 EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3652 EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
3653}
3654
3655/*
3656 * Test metric with a simple sliced state
3657 * - Increasing values
3658 * - Using diff
3659 * - Second field is value field
3660 */
3661TEST(ValueMetricProducerTest, TestSlicedState) {
3662 // Set up ValueMetricProducer.
3663 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
3664 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003665 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003666 // ValueMetricProducer initialized.
Tej Singh3be093b2020-03-04 20:08:38 -08003667 .WillOnce(Invoke(
3668 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
3669 data->clear();
3670 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
3671 return true;
3672 }))
tsaichristinee5405ba2020-03-17 18:34:08 -07003673 // Screen state change to ON.
Tej Singh3be093b2020-03-04 20:08:38 -08003674 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3675 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003676 data->clear();
3677 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
3678 return true;
3679 }))
3680 // Screen state change to OFF.
Tej Singh3be093b2020-03-04 20:08:38 -08003681 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3682 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003683 data->clear();
3684 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
3685 return true;
3686 }))
3687 // Screen state change to ON.
Tej Singh3be093b2020-03-04 20:08:38 -08003688 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3689 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003690 data->clear();
3691 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
3692 return true;
3693 }))
3694 // Dump report requested.
Tej Singh3be093b2020-03-04 20:08:38 -08003695 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3696 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003697 data->clear();
3698 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
3699 return true;
3700 }));
3701
3702 sp<ValueMetricProducer> valueProducer =
3703 ValueMetricProducerTestHelper::createValueProducerWithState(
3704 pullerManager, metric, {util::SCREEN_STATE_CHANGED}, {});
3705
3706 // Set up StateManager and check that StateTrackers are initialized.
3707 StateManager::getInstance().clear();
3708 StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
3709 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
3710 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
3711
3712 // Bucket status after metric initialized.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003713 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003714 // Base for dimension key {}
3715 auto it = valueProducer->mCurrentSlicedBucket.begin();
3716 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3717 EXPECT_EQ(true, itBase->second[0].hasBase);
3718 EXPECT_EQ(3, itBase->second[0].base.long_value);
3719 // Value for dimension, state key {{}, kStateUnknown}
3720 EXPECT_EQ(false, it->second[0].hasValue);
3721
3722 // Bucket status after screen state change kStateUnknown->ON.
3723 auto screenEvent = CreateScreenStateChangedEvent(
3724 bucketStartTimeNs + 5, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
3725 StateManager::getInstance().onLogEvent(*screenEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003726 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003727 // Base for dimension key {}
3728 it = valueProducer->mCurrentSlicedBucket.begin();
3729 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3730 EXPECT_EQ(true, itBase->second[0].hasBase);
3731 EXPECT_EQ(5, itBase->second[0].base.long_value);
3732 // Value for dimension, state key {{}, kStateUnknown}
3733 EXPECT_EQ(true, it->second[0].hasValue);
3734 EXPECT_EQ(2, it->second[0].value.long_value);
3735
3736 // Bucket status after screen state change ON->OFF.
3737 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
3738 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
3739 StateManager::getInstance().onLogEvent(*screenEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003740 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003741 // Base for dimension key {}
3742 it = valueProducer->mCurrentSlicedBucket.begin();
3743 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3744 EXPECT_EQ(true, itBase->second[0].hasBase);
3745 EXPECT_EQ(9, itBase->second[0].base.long_value);
3746 // Value for dimension, state key {{}, ON}
3747 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
3748 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
3749 EXPECT_EQ(true, it->second[0].hasValue);
3750 EXPECT_EQ(4, it->second[0].value.long_value);
3751 // Value for dimension, state key {{}, kStateUnknown}
3752 it++;
3753 EXPECT_EQ(true, it->second[0].hasValue);
3754 EXPECT_EQ(2, it->second[0].value.long_value);
3755
3756 // Bucket status after screen state change OFF->ON.
3757 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
3758 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
3759 StateManager::getInstance().onLogEvent(*screenEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003760 ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003761 // Base for dimension key {}
3762 it = valueProducer->mCurrentSlicedBucket.begin();
3763 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3764 EXPECT_EQ(true, itBase->second[0].hasBase);
3765 EXPECT_EQ(21, itBase->second[0].base.long_value);
3766 // Value for dimension, state key {{}, OFF}
3767 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
3768 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
3769 EXPECT_EQ(true, it->second[0].hasValue);
3770 EXPECT_EQ(12, it->second[0].value.long_value);
3771 // Value for dimension, state key {{}, ON}
3772 it++;
3773 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
3774 it->first.getStateValuesKey().getValues()[0].mValue.int_value);
3775 EXPECT_EQ(true, it->second[0].hasValue);
3776 EXPECT_EQ(4, it->second[0].value.long_value);
3777 // Value for dimension, state key {{}, kStateUnknown}
3778 it++;
3779 EXPECT_EQ(true, it->second[0].hasValue);
3780 EXPECT_EQ(2, it->second[0].value.long_value);
3781
3782 // Start dump report and check output.
3783 ProtoOutputStream output;
3784 std::set<string> strSet;
3785 valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
3786 NO_TIME_CONSTRAINTS, &strSet, &output);
3787
3788 StatsLogReport report = outputStreamToProto(&output);
3789 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003790 ASSERT_EQ(3, report.value_metrics().data_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003791
3792 auto data = report.value_metrics().data(0);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003793 ASSERT_EQ(1, data.bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003794 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
3795
3796 data = report.value_metrics().data(1);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003797 ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003798 EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
3799 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
3800 EXPECT_TRUE(data.slice_by_state(0).has_value());
3801 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
3802
3803 data = report.value_metrics().data(2);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003804 ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003805 EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
3806 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
3807 EXPECT_TRUE(data.slice_by_state(0).has_value());
3808 EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
3809}
3810
3811/*
3812 * Test metric with sliced state with map
3813 * - Increasing values
3814 * - Using diff
3815 * - Second field is value field
3816 */
3817TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
3818 // Set up ValueMetricProducer.
3819 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
3820 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003821 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003822 // ValueMetricProducer initialized.
Tej Singh3be093b2020-03-04 20:08:38 -08003823 .WillOnce(Invoke(
3824 [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
3825 data->clear();
3826 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
3827 return true;
3828 }))
tsaichristinee5405ba2020-03-17 18:34:08 -07003829 // Screen state change to ON.
Tej Singh3be093b2020-03-04 20:08:38 -08003830 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3831 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003832 data->clear();
3833 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
3834 return true;
3835 }))
3836 // Screen state change to VR.
Tej Singh3be093b2020-03-04 20:08:38 -08003837 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3838 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003839 data->clear();
3840 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
3841 return true;
3842 }))
3843 // Screen state change to OFF.
Tej Singh3be093b2020-03-04 20:08:38 -08003844 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3845 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003846 data->clear();
3847 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
3848 return true;
3849 }))
3850 // Dump report requested.
Tej Singh3be093b2020-03-04 20:08:38 -08003851 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3852 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003853 data->clear();
3854 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
3855 return true;
3856 }));
3857
Tej Singh5d823b32019-05-21 20:13:21 -07003858 const StateMap& stateMap =
3859 CreateScreenStateOnOffMap(/*screen on id=*/321, /*screen off id=*/123);
tsaichristinee5405ba2020-03-17 18:34:08 -07003860 const StateMap_StateGroup screenOnGroup = stateMap.group(0);
3861 const StateMap_StateGroup screenOffGroup = stateMap.group(1);
3862
3863 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
3864 for (auto group : stateMap.group()) {
3865 for (auto value : group.value()) {
3866 stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
3867 }
3868 }
3869
3870 sp<ValueMetricProducer> valueProducer =
3871 ValueMetricProducerTestHelper::createValueProducerWithState(
3872 pullerManager, metric, {util::SCREEN_STATE_CHANGED}, stateGroupMap);
3873
3874 // Set up StateManager and check that StateTrackers are initialized.
3875 StateManager::getInstance().clear();
3876 StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
3877 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
3878 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
3879
3880 // Bucket status after metric initialized.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003881 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003882 // Base for dimension key {}
3883 auto it = valueProducer->mCurrentSlicedBucket.begin();
3884 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3885 EXPECT_EQ(true, itBase->second[0].hasBase);
3886 EXPECT_EQ(3, itBase->second[0].base.long_value);
3887 // Value for dimension, state key {{}, {}}
3888 EXPECT_EQ(false, it->second[0].hasValue);
3889
3890 // Bucket status after screen state change kStateUnknown->ON.
3891 auto screenEvent = CreateScreenStateChangedEvent(
3892 bucketStartTimeNs + 5, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
3893 StateManager::getInstance().onLogEvent(*screenEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003894 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003895 // Base for dimension key {}
3896 it = valueProducer->mCurrentSlicedBucket.begin();
3897 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3898 EXPECT_EQ(true, itBase->second[0].hasBase);
3899 EXPECT_EQ(5, itBase->second[0].base.long_value);
3900 // Value for dimension, state key {{}, kStateUnknown}
3901 EXPECT_EQ(true, it->second[0].hasValue);
3902 EXPECT_EQ(2, it->second[0].value.long_value);
3903
3904 // Bucket status after screen state change ON->VR (also ON).
3905 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
3906 android::view::DisplayStateEnum::DISPLAY_STATE_VR);
3907 StateManager::getInstance().onLogEvent(*screenEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003908 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003909 // Base for dimension key {}
3910 it = valueProducer->mCurrentSlicedBucket.begin();
3911 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3912 EXPECT_EQ(true, itBase->second[0].hasBase);
3913 EXPECT_EQ(9, itBase->second[0].base.long_value);
3914 // Value for dimension, state key {{}, ON GROUP}
3915 EXPECT_EQ(screenOnGroup.group_id(),
3916 it->first.getStateValuesKey().getValues()[0].mValue.long_value);
3917 EXPECT_EQ(true, it->second[0].hasValue);
3918 EXPECT_EQ(4, it->second[0].value.long_value);
3919 // Value for dimension, state key {{}, kStateUnknown}
3920 it++;
3921 EXPECT_EQ(true, it->second[0].hasValue);
3922 EXPECT_EQ(2, it->second[0].value.long_value);
3923
3924 // Bucket status after screen state change VR->OFF.
3925 screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
3926 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
3927 StateManager::getInstance().onLogEvent(*screenEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003928 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003929 // Base for dimension key {}
3930 it = valueProducer->mCurrentSlicedBucket.begin();
3931 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
3932 EXPECT_EQ(true, itBase->second[0].hasBase);
3933 EXPECT_EQ(21, itBase->second[0].base.long_value);
3934 // Value for dimension, state key {{}, ON GROUP}
3935 EXPECT_EQ(screenOnGroup.group_id(),
3936 it->first.getStateValuesKey().getValues()[0].mValue.long_value);
3937 EXPECT_EQ(true, it->second[0].hasValue);
3938 EXPECT_EQ(16, it->second[0].value.long_value);
3939 // Value for dimension, state key {{}, kStateUnknown}
3940 it++;
3941 EXPECT_EQ(true, it->second[0].hasValue);
3942 EXPECT_EQ(2, it->second[0].value.long_value);
3943
3944 // Start dump report and check output.
3945 ProtoOutputStream output;
3946 std::set<string> strSet;
3947 valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
3948 NO_TIME_CONSTRAINTS, &strSet, &output);
3949
3950 StatsLogReport report = outputStreamToProto(&output);
3951 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003952 ASSERT_EQ(3, report.value_metrics().data_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003953
3954 auto data = report.value_metrics().data(0);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003955 ASSERT_EQ(1, data.bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003956 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
3957
3958 data = report.value_metrics().data(1);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003959 ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003960 EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
3961 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
3962 EXPECT_TRUE(data.slice_by_state(0).has_group_id());
3963 EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
3964
3965 data = report.value_metrics().data(2);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07003966 ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07003967 EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
3968 EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
3969 EXPECT_TRUE(data.slice_by_state(0).has_group_id());
3970 EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
3971}
3972
3973/*
3974 * Test metric that slices by state with a primary field and has dimensions
3975 * - Increasing values
3976 * - Using diff
3977 * - Second field is value field
3978 */
3979TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
3980 // Set up ValueMetricProducer.
3981 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
3982 metric.mutable_dimensions_in_what()->set_field(tagId);
3983 metric.mutable_dimensions_in_what()->add_child()->set_field(1);
3984
3985 MetricStateLink* stateLink = metric.add_state_link();
3986 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
3987 auto fieldsInWhat = stateLink->mutable_fields_in_what();
3988 *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
3989 auto fieldsInState = stateLink->mutable_fields_in_state();
3990 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
3991
3992 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
Tej Singh3be093b2020-03-04 20:08:38 -08003993 EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
tsaichristinee5405ba2020-03-17 18:34:08 -07003994 // ValueMetricProducer initialized.
Tej Singh3be093b2020-03-04 20:08:38 -08003995 .WillOnce(Invoke([](int tagId, const ConfigKey&,
3996 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07003997 data->clear();
3998 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
3999 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3));
4000 return true;
4001 }))
4002 // Uid 1 process state change from kStateUnknown -> Foreground
Tej Singh3be093b2020-03-04 20:08:38 -08004003 .WillOnce(Invoke([](int tagId, const ConfigKey&,
4004 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07004005 data->clear();
4006 data->push_back(
4007 CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 1 /*uid*/, 6));
4008
4009 // This event should be skipped.
4010 data->push_back(
4011 CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 2 /*uid*/, 8));
4012 return true;
4013 }))
4014 // Uid 2 process state change from kStateUnknown -> Background
Tej Singh3be093b2020-03-04 20:08:38 -08004015 .WillOnce(Invoke([](int tagId, const ConfigKey&,
4016 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07004017 data->clear();
4018 data->push_back(
4019 CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40, 2 /*uid*/, 9));
4020
4021 // This event should be skipped.
4022 data->push_back(
4023 CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40, 1 /*uid*/, 12));
4024 return true;
4025 }))
4026 // Uid 1 process state change from Foreground -> Background
Tej Singh3be093b2020-03-04 20:08:38 -08004027 .WillOnce(Invoke([](int tagId, const ConfigKey&,
4028 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07004029 data->clear();
4030 data->push_back(
4031 CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20, 1 /*uid*/, 13));
4032
4033 // This event should be skipped.
4034 data->push_back(
4035 CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20, 2 /*uid*/, 11));
4036 return true;
4037 }))
4038 // Uid 1 process state change from Background -> Foreground
Tej Singh3be093b2020-03-04 20:08:38 -08004039 .WillOnce(Invoke([](int tagId, const ConfigKey&,
4040 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07004041 data->clear();
4042 data->push_back(
4043 CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40, 1 /*uid*/, 17));
4044
4045 // This event should be skipped.
4046 data->push_back(
4047 CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40, 2 /*uid */, 15));
4048 return true;
4049 }))
4050 // Dump report pull.
Tej Singh3be093b2020-03-04 20:08:38 -08004051 .WillOnce(Invoke([](int tagId, const ConfigKey&,
4052 vector<std::shared_ptr<LogEvent>>* data, bool) {
tsaichristinee5405ba2020-03-17 18:34:08 -07004053 data->clear();
4054 data->push_back(
4055 CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50, 2 /*uid*/, 20));
4056 data->push_back(
4057 CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50, 1 /*uid*/, 21));
4058 return true;
4059 }));
4060
4061 sp<ValueMetricProducer> valueProducer =
4062 ValueMetricProducerTestHelper::createValueProducerWithState(
4063 pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
4064
4065 // Set up StateManager and check that StateTrackers are initialized.
4066 StateManager::getInstance().clear();
4067 StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
4068 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4069 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
4070
4071 // Bucket status after metric initialized.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004072 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004073 // Base for dimension key {uid 1}.
4074 auto it = valueProducer->mCurrentSlicedBucket.begin();
4075 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4076 auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4077 EXPECT_EQ(true, itBase->second[0].hasBase);
4078 EXPECT_EQ(3, itBase->second[0].base.long_value);
4079 // Value for dimension, state key {{uid 1}, kStateUnknown}
4080 // TODO(tsaichristine): test equality of state values key
4081 // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4082 EXPECT_EQ(false, it->second[0].hasValue);
4083 // Base for dimension key {uid 2}
4084 it++;
4085 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4086 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4087 EXPECT_EQ(true, itBase->second[0].hasBase);
4088 EXPECT_EQ(7, itBase->second[0].base.long_value);
4089 // Value for dimension, state key {{uid 2}, kStateUnknown}
4090 // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4091 EXPECT_EQ(false, it->second[0].hasValue);
4092
4093 // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
4094 auto uidProcessEvent = CreateUidProcessStateChangedEvent(
4095 bucketStartTimeNs + 20, 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
4096 StateManager::getInstance().onLogEvent(*uidProcessEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004097 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004098 // Base for dimension key {uid 1}.
4099 it = valueProducer->mCurrentSlicedBucket.begin();
4100 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4101 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4102 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4103 EXPECT_EQ(true, itBase->second[0].hasBase);
4104 EXPECT_EQ(6, itBase->second[0].base.long_value);
4105 // Value for key {uid 1, kStateUnknown}.
4106 // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4107 EXPECT_EQ(true, it->second[0].hasValue);
4108 EXPECT_EQ(3, it->second[0].value.long_value);
4109
4110 // Base for dimension key {uid 2}
4111 it++;
4112 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4113 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4114 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4115 EXPECT_EQ(true, itBase->second[0].hasBase);
4116 EXPECT_EQ(7, itBase->second[0].base.long_value);
4117 // Value for key {uid 2, kStateUnknown}
4118 EXPECT_EQ(false, it->second[0].hasValue);
4119
4120 // Bucket status after uid 2 process state change kStateUnknown -> Background.
4121 uidProcessEvent = CreateUidProcessStateChangedEvent(
4122 bucketStartTimeNs + 40, 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
4123 StateManager::getInstance().onLogEvent(*uidProcessEvent);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004124 ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004125 // Base for dimension key {uid 1}.
4126 it = valueProducer->mCurrentSlicedBucket.begin();
4127 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4128 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4129 EXPECT_EQ(true, itBase->second[0].hasBase);
4130 EXPECT_EQ(6, itBase->second[0].base.long_value);
4131 // Value for key {uid 1, kStateUnknown}.
4132 EXPECT_EQ(true, it->second[0].hasValue);
4133 EXPECT_EQ(3, it->second[0].value.long_value);
4134
4135 // Base for dimension key {uid 2}
4136 it++;
4137 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4138 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4139 EXPECT_EQ(true, itBase->second[0].hasBase);
4140 EXPECT_EQ(9, itBase->second[0].base.long_value);
4141 // Value for key {uid 2, kStateUnknown}
4142 // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4143 EXPECT_EQ(true, it->second[0].hasValue);
4144 EXPECT_EQ(2, it->second[0].value.long_value);
4145
4146 // Pull at end of first bucket.
4147 vector<shared_ptr<LogEvent>> allData;
4148 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 10));
4149 allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 15));
4150 valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
4151
4152 // Buckets flushed after end of first bucket.
4153 // None of the buckets should have a value.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004154 ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
4155 ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
4156 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004157 // Base for dimension key {uid 2}.
4158 it = valueProducer->mCurrentSlicedBucket.begin();
4159 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4160 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4161 EXPECT_EQ(true, itBase->second[0].hasBase);
4162 EXPECT_EQ(15, itBase->second[0].base.long_value);
4163 // Value for key {uid 2, BACKGROUND}.
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004164 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004165 EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4166 EXPECT_EQ(false, it->second[0].hasValue);
4167
4168 // Base for dimension key {uid 1}
4169 it++;
4170 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4171 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4172 EXPECT_EQ(true, itBase->second[0].hasBase);
4173 EXPECT_EQ(10, itBase->second[0].base.long_value);
4174 // Value for key {uid 1, kStateUnknown}
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004175 ASSERT_EQ(0, it->first.getStateValuesKey().getValues().size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004176 // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4177 EXPECT_EQ(false, it->second[0].hasValue);
4178
4179 // Value for key {uid 1, FOREGROUND}
4180 it++;
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004181 ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004182 EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4183 EXPECT_EQ(false, it->second[0].hasValue);
4184
4185 // Value for key {uid 2, kStateUnknown}
4186 it++;
4187 EXPECT_EQ(false, it->second[0].hasValue);
4188
4189 // Bucket status after uid 1 process state change from Foreground -> Background.
4190 uidProcessEvent = CreateUidProcessStateChangedEvent(
4191 bucket2StartTimeNs + 20, 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
4192 StateManager::getInstance().onLogEvent(*uidProcessEvent);
4193
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004194 ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
4195 ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
4196 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004197 // Base for dimension key {uid 2}.
4198 it = valueProducer->mCurrentSlicedBucket.begin();
4199 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4200 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4201 EXPECT_EQ(true, itBase->second[0].hasBase);
4202 EXPECT_EQ(15, itBase->second[0].base.long_value);
4203 // Value for key {uid 2, BACKGROUND}.
4204 EXPECT_EQ(false, it->second[0].hasValue);
4205 // Base for dimension key {uid 1}
4206 it++;
4207 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4208 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4209 EXPECT_EQ(true, itBase->second[0].hasBase);
4210 EXPECT_EQ(13, itBase->second[0].base.long_value);
4211 // Value for key {uid 1, kStateUnknown}
4212 EXPECT_EQ(false, it->second[0].hasValue);
4213 // Value for key {uid 1, FOREGROUND}
4214 it++;
4215 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4216 EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4217 EXPECT_EQ(true, it->second[0].hasValue);
4218 EXPECT_EQ(3, it->second[0].value.long_value);
4219 // Value for key {uid 2, kStateUnknown}
4220 it++;
4221 EXPECT_EQ(false, it->second[0].hasValue);
4222
4223 // Bucket status after uid 1 process state change Background->Foreground.
4224 uidProcessEvent = CreateUidProcessStateChangedEvent(
4225 bucket2StartTimeNs + 40, 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
4226 StateManager::getInstance().onLogEvent(*uidProcessEvent);
4227
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004228 ASSERT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
4229 ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004230 // Base for dimension key {uid 2}
4231 it = valueProducer->mCurrentSlicedBucket.begin();
4232 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4233 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4234 EXPECT_EQ(true, itBase->second[0].hasBase);
4235 EXPECT_EQ(15, itBase->second[0].base.long_value);
4236 EXPECT_EQ(false, it->second[0].hasValue);
4237
4238 it++;
4239 EXPECT_EQ(false, it->second[0].hasValue);
4240
4241 // Base for dimension key {uid 1}
4242 it++;
4243 EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4244 itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4245 EXPECT_EQ(17, itBase->second[0].base.long_value);
4246 // Value for key {uid 1, BACKGROUND}
4247 EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4248 EXPECT_EQ(true, it->second[0].hasValue);
4249 EXPECT_EQ(4, it->second[0].value.long_value);
4250 // Value for key {uid 1, FOREGROUND}
4251 it++;
4252 EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4253 EXPECT_EQ(true, it->second[0].hasValue);
4254 EXPECT_EQ(3, it->second[0].value.long_value);
4255
4256 // Start dump report and check output.
4257 ProtoOutputStream output;
4258 std::set<string> strSet;
4259 valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
4260 NO_TIME_CONSTRAINTS, &strSet, &output);
4261
4262 StatsLogReport report = outputStreamToProto(&output);
4263 EXPECT_TRUE(report.has_value_metrics());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004264 ASSERT_EQ(5, report.value_metrics().data_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004265
4266 auto data = report.value_metrics().data(0);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004267 ASSERT_EQ(1, data.bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004268 EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4269 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4270 EXPECT_TRUE(data.slice_by_state(0).has_value());
4271 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
4272 data.slice_by_state(0).value());
4273
4274 data = report.value_metrics().data(1);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004275 ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004276 EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
4277
4278 data = report.value_metrics().data(2);
4279 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4280 EXPECT_TRUE(data.slice_by_state(0).has_value());
4281 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
4282 data.slice_by_state(0).value());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004283 ASSERT_EQ(2, report.value_metrics().data(2).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004284 EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
4285 EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
4286
4287 data = report.value_metrics().data(3);
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004288 ASSERT_EQ(1, report.value_metrics().data(3).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004289 EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
4290
4291 data = report.value_metrics().data(4);
4292 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4293 EXPECT_TRUE(data.slice_by_state(0).has_value());
4294 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
4295 data.slice_by_state(0).value());
Muhammad Qureshidff78d62020-05-11 13:37:43 -07004296 ASSERT_EQ(2, report.value_metrics().data(4).bucket_info_size());
tsaichristinee5405ba2020-03-17 18:34:08 -07004297 EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
4298 EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
4299}
tsaichristinec876b492019-12-10 13:47:05 -08004300
Chenjie Yu6736c892017-11-09 10:50:09 -08004301} // namespace statsd
4302} // namespace os
4303} // namespace android
4304#else
4305GTEST_LOG_(INFO) << "This test does nothing.\n";
4306#endif