blob: 751180db0890d6a70beeccd788f258df42f0a137 [file] [log] [blame]
Yang Lu3eba6212017-10-25 19:54:45 -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
Yangster-mace2cd6d52017-11-09 20:38:30 -080015#include "src/anomaly/AnomalyTracker.h"
Yao Chend5aa01b32017-12-19 16:46:36 -080016#include "../metrics/metrics_test_helper.h"
Yang Lu3eba6212017-10-25 19:54:45 -070017
18#include <gtest/gtest.h>
19#include <stdio.h>
20#include <vector>
21
22using namespace testing;
23using android::sp;
24using std::set;
25using std::unordered_map;
26using std::vector;
27
28#ifdef __ANDROID__
29
30namespace android {
31namespace os {
32namespace statsd {
33
Yangster-mac94e197c2018-01-02 16:03:03 -080034const ConfigKey kConfigKey(0, 12345);
Bookatz8f2f3d82017-12-07 13:53:21 -080035
Yao Chend5aa01b32017-12-19 16:46:36 -080036HashableDimensionKey getMockDimensionKey(int key, string value) {
Yangster-mac20877162017-12-22 17:19:39 -080037 DimensionsValue dimensionsValue;
38 dimensionsValue.set_field(key);
39 dimensionsValue.set_value_str(value);
40 return HashableDimensionKey(dimensionsValue);
Yao Chend5aa01b32017-12-19 16:46:36 -080041}
42
43void AddValueToBucket(const std::vector<std::pair<HashableDimensionKey, long>>& key_value_pair_list,
Yang Lu3eba6212017-10-25 19:54:45 -070044 std::shared_ptr<DimToValMap> bucket) {
45 for (auto itr = key_value_pair_list.begin(); itr != key_value_pair_list.end(); itr++) {
46 (*bucket)[itr->first] += itr->second;
47 }
48}
49
Yangster-mace2cd6d52017-11-09 20:38:30 -080050std::shared_ptr<DimToValMap> MockBucket(
Yao Chend5aa01b32017-12-19 16:46:36 -080051 const std::vector<std::pair<HashableDimensionKey, long>>& key_value_pair_list) {
Yang Lu3eba6212017-10-25 19:54:45 -070052 std::shared_ptr<DimToValMap> bucket = std::make_shared<DimToValMap>();
53 AddValueToBucket(key_value_pair_list, bucket);
54 return bucket;
55}
56
57TEST(AnomalyTrackerTest, TestConsecutiveBuckets) {
Yangster-mace2cd6d52017-11-09 20:38:30 -080058 const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Yang Lu3eba6212017-10-25 19:54:45 -070059 Alert alert;
60 alert.set_number_of_buckets(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -080061 alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
Yang Lu3eba6212017-10-25 19:54:45 -070062 alert.set_trigger_if_sum_gt(2);
63
Bookatz8f2f3d82017-12-07 13:53:21 -080064 AnomalyTracker anomalyTracker(alert, kConfigKey);
Yao Chend5aa01b32017-12-19 16:46:36 -080065 HashableDimensionKey keyA = getMockDimensionKey(1, "a");
66 HashableDimensionKey keyB = getMockDimensionKey(1, "b");
67 HashableDimensionKey keyC = getMockDimensionKey(1, "c");
Yang Lu3eba6212017-10-25 19:54:45 -070068
Yao Chend5aa01b32017-12-19 16:46:36 -080069 std::shared_ptr<DimToValMap> bucket0 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080070 int64_t eventTimestamp0 = 10;
Yao Chend5aa01b32017-12-19 16:46:36 -080071 std::shared_ptr<DimToValMap> bucket1 = MockBucket({{keyA, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080072 int64_t eventTimestamp1 = bucketSizeNs + 11;
Yao Chend5aa01b32017-12-19 16:46:36 -080073 std::shared_ptr<DimToValMap> bucket2 = MockBucket({{keyB, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080074 int64_t eventTimestamp2 = 2 * bucketSizeNs + 12;
Yao Chend5aa01b32017-12-19 16:46:36 -080075 std::shared_ptr<DimToValMap> bucket3 = MockBucket({{keyA, 2}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080076 int64_t eventTimestamp3 = 3 * bucketSizeNs + 13;
Yao Chend5aa01b32017-12-19 16:46:36 -080077 std::shared_ptr<DimToValMap> bucket4 = MockBucket({{keyB, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080078 int64_t eventTimestamp4 = 4 * bucketSizeNs + 14;
Yao Chend5aa01b32017-12-19 16:46:36 -080079 std::shared_ptr<DimToValMap> bucket5 = MockBucket({{keyA, 2}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080080 int64_t eventTimestamp5 = 5 * bucketSizeNs + 15;
Yao Chend5aa01b32017-12-19 16:46:36 -080081 std::shared_ptr<DimToValMap> bucket6 = MockBucket({{keyA, 2}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080082 int64_t eventTimestamp6 = 6 * bucketSizeNs + 16;
Yang Lu3eba6212017-10-25 19:54:45 -070083
Yangster-mace2cd6d52017-11-09 20:38:30 -080084 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0u);
85 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
86 EXPECT_FALSE(anomalyTracker.detectAnomaly(0, *bucket0));
87 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp0, 0, *bucket0);
Bookatz857aaa52017-12-19 15:29:06 -080088 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
Yang Lu3eba6212017-10-25 19:54:45 -070089
Yangster-mace2cd6d52017-11-09 20:38:30 -080090 // Adds past bucket #0
91 anomalyTracker.addPastBucket(bucket0, 0);
92 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
Yao Chend5aa01b32017-12-19 16:46:36 -080093 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
94 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
95 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -080096 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
97 EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
98 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 1, *bucket1);
Bookatz857aaa52017-12-19 15:29:06 -080099 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
Yang Lu3eba6212017-10-25 19:54:45 -0700100
Yangster-mace2cd6d52017-11-09 20:38:30 -0800101 // Adds past bucket #0 again. The sum does not change.
102 anomalyTracker.addPastBucket(bucket0, 0);
103 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
Yao Chend5aa01b32017-12-19 16:46:36 -0800104 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
105 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
106 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800107 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
108 EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
109 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1 + 1, 1, *bucket1);
Bookatz857aaa52017-12-19 15:29:06 -0800110 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
Yang Lu3eba6212017-10-25 19:54:45 -0700111
Yangster-mace2cd6d52017-11-09 20:38:30 -0800112 // Adds past bucket #1.
113 anomalyTracker.addPastBucket(bucket1, 1);
114 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L);
115 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800116 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
117 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
118 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800119 EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
120 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 2, *bucket2);
Bookatz857aaa52017-12-19 15:29:06 -0800121 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800122
123 // Adds past bucket #1 again. Nothing changes.
124 anomalyTracker.addPastBucket(bucket1, 1);
125 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L);
126 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800127 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
128 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
129 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800130 EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
131 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2 + 1, 2, *bucket2);
Bookatz857aaa52017-12-19 15:29:06 -0800132 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800133
134 // Adds past bucket #2.
135 anomalyTracker.addPastBucket(bucket2, 2);
136 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 2L);
137 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800138 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
139 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800140 EXPECT_TRUE(anomalyTracker.detectAnomaly(3, *bucket3));
141 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 3, *bucket3);
Yang Lu3eba6212017-10-25 19:54:45 -0700142 // Within refractory period.
Bookatz857aaa52017-12-19 15:29:06 -0800143 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yang Lu3eba6212017-10-25 19:54:45 -0700144
145 // Adds bucket #3.
Yangster-mace2cd6d52017-11-09 20:38:30 -0800146 anomalyTracker.addPastBucket(bucket3, 3L);
147 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 3L);
148 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800149 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
150 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800151 EXPECT_FALSE(anomalyTracker.detectAnomaly(4, *bucket4));
152 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 4, *bucket4);
Bookatz857aaa52017-12-19 15:29:06 -0800153 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yang Lu3eba6212017-10-25 19:54:45 -0700154
Yangster-mace2cd6d52017-11-09 20:38:30 -0800155 // Adds bucket #4.
156 anomalyTracker.addPastBucket(bucket4, 4);
157 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 4L);
158 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800159 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
160 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800161 EXPECT_TRUE(anomalyTracker.detectAnomaly(5, *bucket5));
162 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 5, *bucket5);
Bookatz857aaa52017-12-19 15:29:06 -0800163 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
Yang Lu3eba6212017-10-25 19:54:45 -0700164
Yangster-mace2cd6d52017-11-09 20:38:30 -0800165 // Adds bucket #5.
166 anomalyTracker.addPastBucket(bucket5, 5);
167 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 5L);
168 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800169 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
170 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800171 EXPECT_TRUE(anomalyTracker.detectAnomaly(6, *bucket6));
Yang Lu3eba6212017-10-25 19:54:45 -0700172 // Within refractory period.
Yangster-mace2cd6d52017-11-09 20:38:30 -0800173 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 6, *bucket6);
Bookatz857aaa52017-12-19 15:29:06 -0800174 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
Yang Lu3eba6212017-10-25 19:54:45 -0700175}
176
177TEST(AnomalyTrackerTest, TestSparseBuckets) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800178 const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Yang Lu3eba6212017-10-25 19:54:45 -0700179 Alert alert;
180 alert.set_number_of_buckets(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800181 alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
Yang Lu3eba6212017-10-25 19:54:45 -0700182 alert.set_trigger_if_sum_gt(2);
183
Bookatz8f2f3d82017-12-07 13:53:21 -0800184 AnomalyTracker anomalyTracker(alert, kConfigKey);
Yao Chend5aa01b32017-12-19 16:46:36 -0800185 HashableDimensionKey keyA = getMockDimensionKey(1, "a");
186 HashableDimensionKey keyB = getMockDimensionKey(1, "b");
187 HashableDimensionKey keyC = getMockDimensionKey(1, "c");
188 HashableDimensionKey keyD = getMockDimensionKey(1, "d");
189 HashableDimensionKey keyE = getMockDimensionKey(1, "e");
Yang Lu3eba6212017-10-25 19:54:45 -0700190
Yao Chend5aa01b32017-12-19 16:46:36 -0800191 std::shared_ptr<DimToValMap> bucket9 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}});
192 std::shared_ptr<DimToValMap> bucket16 = MockBucket({{keyB, 4}});
193 std::shared_ptr<DimToValMap> bucket18 = MockBucket({{keyB, 1}, {keyC, 1}});
194 std::shared_ptr<DimToValMap> bucket20 = MockBucket({{keyB, 3}, {keyC, 1}});
195 std::shared_ptr<DimToValMap> bucket25 = MockBucket({{keyD, 1}});
196 std::shared_ptr<DimToValMap> bucket28 = MockBucket({{keyE, 2}});
Yang Lu3eba6212017-10-25 19:54:45 -0700197
Yangster-mace2cd6d52017-11-09 20:38:30 -0800198 int64_t eventTimestamp1 = bucketSizeNs * 8 + 1;
199 int64_t eventTimestamp2 = bucketSizeNs * 15 + 11;
200 int64_t eventTimestamp3 = bucketSizeNs * 17 + 1;
201 int64_t eventTimestamp4 = bucketSizeNs * 19 + 2;
202 int64_t eventTimestamp5 = bucketSizeNs * 24 + 3;
203 int64_t eventTimestamp6 = bucketSizeNs * 27 + 3;
Yang Lu3eba6212017-10-25 19:54:45 -0700204
Yangster-mace2cd6d52017-11-09 20:38:30 -0800205 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
206 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
207 EXPECT_FALSE(anomalyTracker.detectAnomaly(9, *bucket9));
208 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 9, *bucket9);
Bookatz857aaa52017-12-19 15:29:06 -0800209 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800210
211 // Add past bucket #9
212 anomalyTracker.addPastBucket(bucket9, 9);
213 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 9L);
214 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800215 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
216 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
217 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800218 EXPECT_TRUE(anomalyTracker.detectAnomaly(16, *bucket16));
219 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
220 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
221 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 16, *bucket16);
222 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
Bookatz857aaa52017-12-19 15:29:06 -0800223 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800224 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
225
226 // Add past bucket #16
227 anomalyTracker.addPastBucket(bucket16, 16);
228 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 16L);
229 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800230 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800231 EXPECT_TRUE(anomalyTracker.detectAnomaly(18, *bucket18));
232 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800233 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
Yang Lu3eba6212017-10-25 19:54:45 -0700234 // Within refractory period.
Yangster-mace2cd6d52017-11-09 20:38:30 -0800235 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 18, *bucket18);
Bookatz857aaa52017-12-19 15:29:06 -0800236 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800237 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800238 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
Yang Lu3eba6212017-10-25 19:54:45 -0700239
Yangster-mace2cd6d52017-11-09 20:38:30 -0800240 // Add past bucket #18
241 anomalyTracker.addPastBucket(bucket18, 18);
242 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 18L);
243 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800244 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
245 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800246 EXPECT_TRUE(anomalyTracker.detectAnomaly(20, *bucket20));
247 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
248 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800249 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
250 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800251 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 20, *bucket20);
Bookatz857aaa52017-12-19 15:29:06 -0800252 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yang Lu3eba6212017-10-25 19:54:45 -0700253
Yangster-mace2cd6d52017-11-09 20:38:30 -0800254 // Add bucket #18 again. Nothing changes.
255 anomalyTracker.addPastBucket(bucket18, 18);
256 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
257 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800258 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
259 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800260 EXPECT_TRUE(anomalyTracker.detectAnomaly(20, *bucket20));
261 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800262 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
263 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800264 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4 + 1, 20, *bucket20);
265 // Within refractory period.
Bookatz857aaa52017-12-19 15:29:06 -0800266 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yang Lu3eba6212017-10-25 19:54:45 -0700267
Yangster-mace2cd6d52017-11-09 20:38:30 -0800268 // Add past bucket #20
269 anomalyTracker.addPastBucket(bucket20, 20);
270 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 20L);
271 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800272 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 3LL);
273 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800274 EXPECT_FALSE(anomalyTracker.detectAnomaly(25, *bucket25));
275 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 24L);
276 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
277 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 25, *bucket25);
Bookatz857aaa52017-12-19 15:29:06 -0800278 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yang Lu3eba6212017-10-25 19:54:45 -0700279
Yangster-mace2cd6d52017-11-09 20:38:30 -0800280 // Add past bucket #25
281 anomalyTracker.addPastBucket(bucket25, 25);
282 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 25L);
283 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800284 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyD), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800285 EXPECT_FALSE(anomalyTracker.detectAnomaly(28, *bucket28));
286 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
287 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
288 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 28, *bucket28);
289 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
Bookatz857aaa52017-12-19 15:29:06 -0800290 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800291
292 // Updates current bucket #28.
Yao Chend5aa01b32017-12-19 16:46:36 -0800293 (*bucket28)[keyE] = 5;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800294 EXPECT_TRUE(anomalyTracker.detectAnomaly(28, *bucket28));
295 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
296 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
297 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6 + 7, 28, *bucket28);
298 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
Bookatz857aaa52017-12-19 15:29:06 -0800299 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp6 + 7);
Yang Lu3eba6212017-10-25 19:54:45 -0700300}
301
302} // namespace statsd
303} // namespace os
304} // namespace android
305#else
306GTEST_LOG_(INFO) << "This test does nothing.\n";
307#endif