blob: fff11552df40ae2d15a7ff48ccc9473a50f1b273 [file] [log] [blame]
Yao Chen93fe3a32017-11-02 13:52:59 -07001// 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
Yao Chen93fe3a32017-11-02 13:52:59 -070015#include "src/metrics/CountMetricProducer.h"
Yangster-macb8144812018-01-04 10:56:23 -080016#include "src/stats_log_util.h"
Yao Chend5aa01b32017-12-19 16:46:36 -080017#include "metrics_test_helper.h"
Yangster-mac94e197c2018-01-02 16:03:03 -080018#include "tests/statsd_test_util.h"
Yao Chen93fe3a32017-11-02 13:52:59 -070019
20#include <gmock/gmock.h>
21#include <gtest/gtest.h>
Bookatz6bf98252018-03-14 10:44:24 -070022#include <math.h>
Yao Chen93fe3a32017-11-02 13:52:59 -070023#include <stdio.h>
24#include <vector>
25
26using namespace testing;
27using android::sp;
28using std::set;
29using std::unordered_map;
30using std::vector;
31
32#ifdef __ANDROID__
33
34namespace android {
35namespace os {
36namespace statsd {
37
Yangster-mac94e197c2018-01-02 16:03:03 -080038const ConfigKey kConfigKey(0, 12345);
Yao Chenb3561512017-11-21 18:07:17 -080039
Yao Chen93fe3a32017-11-02 13:52:59 -070040TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
41 int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080042 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Yao Chen93fe3a32017-11-02 13:52:59 -070043 int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
44 int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
45 int tagId = 1;
46
47 CountMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080048 metric.set_id(1);
Yangster-macb8144812018-01-04 10:56:23 -080049 metric.set_bucket(ONE_MINUTE);
Yao Chen93fe3a32017-11-02 13:52:59 -070050
51 LogEvent event1(tagId, bucketStartTimeNs + 1);
Yangster-mac330af582018-02-08 15:24:38 -080052 event1.init();
Yao Chen93fe3a32017-11-02 13:52:59 -070053 LogEvent event2(tagId, bucketStartTimeNs + 2);
Yangster-mac330af582018-02-08 15:24:38 -080054 event2.init();
Yao Chen93fe3a32017-11-02 13:52:59 -070055
56 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
57
Yao Chenb3561512017-11-21 18:07:17 -080058 CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yao Chen93fe3a32017-11-02 13:52:59 -070059 bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -080060 countProducer.setBucketSize(60 * NS_PER_SEC);
Yao Chen93fe3a32017-11-02 13:52:59 -070061
62 // 2 events in bucket 1.
Chenjie Yua7259ab2017-12-10 08:31:05 -080063 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
64 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
Yangster-mace2cd6d52017-11-09 20:38:30 -080065
66 // Flushes at event #2.
Yangsterf2bee6f2017-11-29 12:01:05 -080067 countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
Yangster-mace2cd6d52017-11-09 20:38:30 -080068 EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
69
70 // Flushes.
Yangsterf2bee6f2017-11-29 12:01:05 -080071 countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
Yao Chen93fe3a32017-11-02 13:52:59 -070072 EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
Yangster-mac93694462018-01-22 20:49:31 -080073 EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
Yao Chen93fe3a32017-11-02 13:52:59 -070074 countProducer.mPastBuckets.end());
Yangster-mac93694462018-01-22 20:49:31 -080075 const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
Yao Chen93fe3a32017-11-02 13:52:59 -070076 EXPECT_EQ(1UL, buckets.size());
Yangster-mace2cd6d52017-11-09 20:38:30 -080077 EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
78 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
79 EXPECT_EQ(2LL, buckets[0].mCount);
Yao Chen93fe3a32017-11-02 13:52:59 -070080
81 // 1 matched event happens in bucket 2.
82 LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
Yangster-mac330af582018-02-08 15:24:38 -080083 event3.init();
84
Chenjie Yua7259ab2017-12-10 08:31:05 -080085 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
Yangsterf2bee6f2017-11-29 12:01:05 -080086 countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
Yao Chen93fe3a32017-11-02 13:52:59 -070087 EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
Yangster-mac93694462018-01-22 20:49:31 -080088 EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
Yao Chen93fe3a32017-11-02 13:52:59 -070089 countProducer.mPastBuckets.end());
Yangster-mac93694462018-01-22 20:49:31 -080090 EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
91 const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
Yao Chen93fe3a32017-11-02 13:52:59 -070092 EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
93 EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
94 EXPECT_EQ(1LL, bucketInfo2.mCount);
95
96 // nothing happens in bucket 3. we should not record anything for bucket 3.
Yangsterf2bee6f2017-11-29 12:01:05 -080097 countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
Yao Chen93fe3a32017-11-02 13:52:59 -070098 EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
Yangster-mac93694462018-01-22 20:49:31 -080099 EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
Yao Chen93fe3a32017-11-02 13:52:59 -0700100 countProducer.mPastBuckets.end());
Yangster-mac93694462018-01-22 20:49:31 -0800101 const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
Yao Chen93fe3a32017-11-02 13:52:59 -0700102 EXPECT_EQ(2UL, buckets3.size());
103}
104
105TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
106 int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -0800107 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Yao Chen93fe3a32017-11-02 13:52:59 -0700108
109 CountMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800110 metric.set_id(1);
Yangster-macb8144812018-01-04 10:56:23 -0800111 metric.set_bucket(ONE_MINUTE);
Yangster-mac94e197c2018-01-02 16:03:03 -0800112 metric.set_condition(StringToId("SCREEN_ON"));
Yao Chen93fe3a32017-11-02 13:52:59 -0700113
114 LogEvent event1(1, bucketStartTimeNs + 1);
Yangster-mac330af582018-02-08 15:24:38 -0800115 event1.init();
116
Yao Chen93fe3a32017-11-02 13:52:59 -0700117 LogEvent event2(1, bucketStartTimeNs + 10);
Yangster-mac330af582018-02-08 15:24:38 -0800118 event2.init();
Yao Chen93fe3a32017-11-02 13:52:59 -0700119
120 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
121
Yao Chenb3561512017-11-21 18:07:17 -0800122 CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800123 countProducer.setBucketSize(60 * NS_PER_SEC);
Yao Chen93fe3a32017-11-02 13:52:59 -0700124
125 countProducer.onConditionChanged(true, bucketStartTimeNs);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800126 countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
Yao Chen93fe3a32017-11-02 13:52:59 -0700127 EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
128
129 countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800130 // Upon this match event, the matched event1 is flushed.
Chenjie Yua7259ab2017-12-10 08:31:05 -0800131 countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
Yao Chen93fe3a32017-11-02 13:52:59 -0700132 EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
133
Yangsterf2bee6f2017-11-29 12:01:05 -0800134 countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
Yao Chen93fe3a32017-11-02 13:52:59 -0700135 EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
Yangster-mac93694462018-01-22 20:49:31 -0800136 EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
Yao Chen93fe3a32017-11-02 13:52:59 -0700137 countProducer.mPastBuckets.end());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800138 {
Yangster-mac93694462018-01-22 20:49:31 -0800139 const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
Yangster-mace2cd6d52017-11-09 20:38:30 -0800140 EXPECT_EQ(1UL, buckets.size());
141 const auto& bucketInfo = buckets[0];
142 EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
143 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
144 EXPECT_EQ(1LL, bucketInfo.mCount);
145 }
Yao Chen93fe3a32017-11-02 13:52:59 -0700146}
147
148TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
149 int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -0800150 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Yao Chen93fe3a32017-11-02 13:52:59 -0700151
Yangster-mac20877162017-12-22 17:19:39 -0800152 int tagId = 1;
153 int conditionTagId = 2;
154
Yao Chen93fe3a32017-11-02 13:52:59 -0700155 CountMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800156 metric.set_id(1);
Yangster-macb8144812018-01-04 10:56:23 -0800157 metric.set_bucket(ONE_MINUTE);
Yangster-mac94e197c2018-01-02 16:03:03 -0800158 metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
Stefan Lafona5b51912017-12-05 21:43:52 -0800159 MetricConditionLink* link = metric.add_links();
Yangster-mac94e197c2018-01-02 16:03:03 -0800160 link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
Yangster-mac7ba8fc32018-01-24 16:16:46 -0800161 buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
162 buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
Yao Chen93fe3a32017-11-02 13:52:59 -0700163
Yangster-mac20877162017-12-22 17:19:39 -0800164 LogEvent event1(tagId, bucketStartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800165 event1.write("111"); // uid
Yao Chen93fe3a32017-11-02 13:52:59 -0700166 event1.init();
167 ConditionKey key1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800168 key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
169 {getMockedDimensionKey(conditionTagId, 2, "111")};
Yao Chen93fe3a32017-11-02 13:52:59 -0700170
Yangster-mac20877162017-12-22 17:19:39 -0800171 LogEvent event2(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800172 event2.write("222"); // uid
Yao Chen93fe3a32017-11-02 13:52:59 -0700173 event2.init();
174 ConditionKey key2;
Yangster-mac94e197c2018-01-02 16:03:03 -0800175 key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
176 {getMockedDimensionKey(conditionTagId, 2, "222")};
Yao Chen93fe3a32017-11-02 13:52:59 -0700177
178 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yangster13fb7e42018-03-07 17:30:49 -0800179 EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
Yao Chen93fe3a32017-11-02 13:52:59 -0700180
Yangster13fb7e42018-03-07 17:30:49 -0800181 EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
Yao Chen93fe3a32017-11-02 13:52:59 -0700182
Yao Chenb3561512017-11-21 18:07:17 -0800183 CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
Yao Chen93fe3a32017-11-02 13:52:59 -0700184 bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800185 countProducer.setBucketSize(60 * NS_PER_SEC);
Yao Chen93fe3a32017-11-02 13:52:59 -0700186
Chenjie Yua7259ab2017-12-10 08:31:05 -0800187 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
Yangsterf2bee6f2017-11-29 12:01:05 -0800188 countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800189 EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
190
Chenjie Yua7259ab2017-12-10 08:31:05 -0800191 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
Yangsterf2bee6f2017-11-29 12:01:05 -0800192 countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
Yao Chen93fe3a32017-11-02 13:52:59 -0700193 EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
Yangster-mac93694462018-01-22 20:49:31 -0800194 EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
Yao Chen93fe3a32017-11-02 13:52:59 -0700195 countProducer.mPastBuckets.end());
Yangster-mac93694462018-01-22 20:49:31 -0800196 const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
Yao Chen93fe3a32017-11-02 13:52:59 -0700197 EXPECT_EQ(1UL, buckets.size());
198 const auto& bucketInfo = buckets[0];
199 EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
200 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
201 EXPECT_EQ(1LL, bucketInfo.mCount);
202}
203
David Chen27785a82018-01-19 17:06:45 -0800204TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800205 sp<AlarmMonitor> alarmMonitor;
David Chen27785a82018-01-19 17:06:45 -0800206 uint64_t bucketStartTimeNs = 10000000000;
207 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
208 uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
209
210 int tagId = 1;
211 int conditionTagId = 2;
212
213 CountMetric metric;
214 metric.set_id(1);
215 metric.set_bucket(ONE_MINUTE);
216 Alert alert;
217 alert.set_num_buckets(3);
218 alert.set_trigger_if_sum_gt(2);
219 LogEvent event1(tagId, bucketStartTimeNs + 1);
220 event1.write("111"); // uid
221 event1.init();
222 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
223 CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
224 bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800225 countProducer.setBucketSize(60 * NS_PER_SEC);
226
Yangster-mac932ecec2018-02-01 10:23:52 -0800227 sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
David Chen27785a82018-01-19 17:06:45 -0800228 EXPECT_TRUE(anomalyTracker != nullptr);
229
230 // Bucket is flushed yet.
231 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
232 EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
233 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
234
235 // App upgrade forces bucket flush.
236 // Check that there's a past bucket and the bucket end is not adjusted.
237 countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
238 EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
239 EXPECT_EQ((long long)bucketStartTimeNs,
240 countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
241 EXPECT_EQ((long long)eventUpgradeTimeNs,
242 countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
243 EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
244 // Anomaly tracker only contains full buckets.
245 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
246
247 uint64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
248 // Next event occurs in same bucket as partial bucket created.
249 LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
250 event2.write("222"); // uid
251 event2.init();
252 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
253 EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
254 EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
255 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
256
257 // Third event in following bucket.
258 LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
259 event3.write("333"); // uid
260 event3.init();
261 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
262 EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
263 EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
264 EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
265}
266
267TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
268 uint64_t bucketStartTimeNs = 10000000000;
269 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
270 uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
271
272 int tagId = 1;
273 int conditionTagId = 2;
274
275 CountMetric metric;
276 metric.set_id(1);
277 metric.set_bucket(ONE_MINUTE);
278 LogEvent event1(tagId, bucketStartTimeNs + 1);
279 event1.write("111"); // uid
280 event1.init();
281 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
282 CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
283 bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800284 countProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800285
286 // Bucket is flushed yet.
287 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
288 EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
289
290 // App upgrade forces bucket flush.
291 // Check that there's a past bucket and the bucket end is not adjusted.
292 countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
293 EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
294 EXPECT_EQ((int64_t)bucketStartTimeNs,
295 countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
296 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
297 (uint64_t)countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
298 EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
299
300 // Next event occurs in same bucket as partial bucket created.
301 LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
302 event2.write("222"); // uid
303 event2.init();
304 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
305 EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
306
307 // Third event in following bucket.
308 LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
309 event3.write("333"); // uid
310 event3.init();
311 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
312 EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
313 EXPECT_EQ((int64_t)eventUpgradeTimeNs,
314 countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
315 EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
316 (uint64_t)countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
317}
318
Bookatz1bf94382018-01-04 11:43:20 -0800319TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800320 sp<AlarmMonitor> alarmMonitor;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800321 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800322 alert.set_id(11);
323 alert.set_metric_id(1);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800324 alert.set_trigger_if_sum_gt(2);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800325 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800326 const int32_t refPeriodSec = 1;
327 alert.set_refractory_period_secs(refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800328
329 int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -0800330 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800331 int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
332 int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
333
Yangster-mace2cd6d52017-11-09 20:38:30 -0800334 CountMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800335 metric.set_id(1);
Yangster-macb8144812018-01-04 10:56:23 -0800336 metric.set_bucket(ONE_MINUTE);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800337
338 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800339 CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-mace2cd6d52017-11-09 20:38:30 -0800340 bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800341 countProducer.setBucketSize(60 * NS_PER_SEC);
342
Yangster-mac932ecec2018-02-01 10:23:52 -0800343 sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800344
345 int tagId = 1;
346 LogEvent event1(tagId, bucketStartTimeNs + 1);
Yangster-mac330af582018-02-08 15:24:38 -0800347 event1.init();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800348 LogEvent event2(tagId, bucketStartTimeNs + 2);
Yangster-mac330af582018-02-08 15:24:38 -0800349 event2.init();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800350 LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
Yangster-mac330af582018-02-08 15:24:38 -0800351 event3.init();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800352 LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
Yangster-mac330af582018-02-08 15:24:38 -0800353 event4.init();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800354 LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
Yangster-mac330af582018-02-08 15:24:38 -0800355 event5.init();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800356 LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
Yangster-mac330af582018-02-08 15:24:38 -0800357 event6.init();
Bookatz1bf94382018-01-04 11:43:20 -0800358 LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
Yangster-mac330af582018-02-08 15:24:38 -0800359 event7.init();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800360
361 // Two events in bucket #0.
Chenjie Yua7259ab2017-12-10 08:31:05 -0800362 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
363 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800364
365 EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
366 EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
Yangster-mac93694462018-01-22 20:49:31 -0800367 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800368
369 // One event in bucket #2. No alarm as bucket #0 is trashed out.
Chenjie Yua7259ab2017-12-10 08:31:05 -0800370 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800371 EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
372 EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
Yangster-mac93694462018-01-22 20:49:31 -0800373 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800374
375 // Two events in bucket #3.
Chenjie Yua7259ab2017-12-10 08:31:05 -0800376 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
377 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
378 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800379 EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
380 EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
381 // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
Yangster-mac93694462018-01-22 20:49:31 -0800382 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700383 std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800384
Chenjie Yua7259ab2017-12-10 08:31:05 -0800385 countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800386 EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
387 EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
Yangster-mac93694462018-01-22 20:49:31 -0800388 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700389 std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800390}
391
Yao Chen93fe3a32017-11-02 13:52:59 -0700392} // namespace statsd
393} // namespace os
394} // namespace android
395#else
396GTEST_LOG_(INFO) << "This test does nothing.\n";
397#endif