blob: a0160541cc9751bbde507a15f425fe0e2c4a9105 [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
Bookatz8f2f3d82017-12-07 13:53:21 -080034const ConfigKey kConfigKey(0, "test");
35
Yao Chend5aa01b32017-12-19 16:46:36 -080036HashableDimensionKey getMockDimensionKey(int key, string value) {
37 KeyValuePair pair;
38 pair.set_key(key);
39 pair.set_value_str(value);
40
41 vector<KeyValuePair> pairs;
42 pairs.push_back(pair);
43
44 return HashableDimensionKey(pairs);
45}
46
47void AddValueToBucket(const std::vector<std::pair<HashableDimensionKey, long>>& key_value_pair_list,
Yang Lu3eba6212017-10-25 19:54:45 -070048 std::shared_ptr<DimToValMap> bucket) {
49 for (auto itr = key_value_pair_list.begin(); itr != key_value_pair_list.end(); itr++) {
50 (*bucket)[itr->first] += itr->second;
51 }
52}
53
Yangster-mace2cd6d52017-11-09 20:38:30 -080054std::shared_ptr<DimToValMap> MockBucket(
Yao Chend5aa01b32017-12-19 16:46:36 -080055 const std::vector<std::pair<HashableDimensionKey, long>>& key_value_pair_list) {
Yang Lu3eba6212017-10-25 19:54:45 -070056 std::shared_ptr<DimToValMap> bucket = std::make_shared<DimToValMap>();
57 AddValueToBucket(key_value_pair_list, bucket);
58 return bucket;
59}
60
61TEST(AnomalyTrackerTest, TestConsecutiveBuckets) {
Yangster-mace2cd6d52017-11-09 20:38:30 -080062 const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Yang Lu3eba6212017-10-25 19:54:45 -070063 Alert alert;
64 alert.set_number_of_buckets(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -080065 alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
Yang Lu3eba6212017-10-25 19:54:45 -070066 alert.set_trigger_if_sum_gt(2);
67
Bookatz8f2f3d82017-12-07 13:53:21 -080068 AnomalyTracker anomalyTracker(alert, kConfigKey);
Yao Chend5aa01b32017-12-19 16:46:36 -080069 HashableDimensionKey keyA = getMockDimensionKey(1, "a");
70 HashableDimensionKey keyB = getMockDimensionKey(1, "b");
71 HashableDimensionKey keyC = getMockDimensionKey(1, "c");
Yang Lu3eba6212017-10-25 19:54:45 -070072
Yao Chend5aa01b32017-12-19 16:46:36 -080073 std::shared_ptr<DimToValMap> bucket0 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080074 int64_t eventTimestamp0 = 10;
Yao Chend5aa01b32017-12-19 16:46:36 -080075 std::shared_ptr<DimToValMap> bucket1 = MockBucket({{keyA, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080076 int64_t eventTimestamp1 = bucketSizeNs + 11;
Yao Chend5aa01b32017-12-19 16:46:36 -080077 std::shared_ptr<DimToValMap> bucket2 = MockBucket({{keyB, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080078 int64_t eventTimestamp2 = 2 * bucketSizeNs + 12;
Yao Chend5aa01b32017-12-19 16:46:36 -080079 std::shared_ptr<DimToValMap> bucket3 = MockBucket({{keyA, 2}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080080 int64_t eventTimestamp3 = 3 * bucketSizeNs + 13;
Yao Chend5aa01b32017-12-19 16:46:36 -080081 std::shared_ptr<DimToValMap> bucket4 = MockBucket({{keyB, 1}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080082 int64_t eventTimestamp4 = 4 * bucketSizeNs + 14;
Yao Chend5aa01b32017-12-19 16:46:36 -080083 std::shared_ptr<DimToValMap> bucket5 = MockBucket({{keyA, 2}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080084 int64_t eventTimestamp5 = 5 * bucketSizeNs + 15;
Yao Chend5aa01b32017-12-19 16:46:36 -080085 std::shared_ptr<DimToValMap> bucket6 = MockBucket({{keyA, 2}});
Yangster-mace2cd6d52017-11-09 20:38:30 -080086 int64_t eventTimestamp6 = 6 * bucketSizeNs + 16;
Yang Lu3eba6212017-10-25 19:54:45 -070087
Yangster-mace2cd6d52017-11-09 20:38:30 -080088 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0u);
89 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
90 EXPECT_FALSE(anomalyTracker.detectAnomaly(0, *bucket0));
91 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp0, 0, *bucket0);
Bookatz857aaa52017-12-19 15:29:06 -080092 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
Yang Lu3eba6212017-10-25 19:54:45 -070093
Yangster-mace2cd6d52017-11-09 20:38:30 -080094 // Adds past bucket #0
95 anomalyTracker.addPastBucket(bucket0, 0);
96 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
Yao Chend5aa01b32017-12-19 16:46:36 -080097 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
98 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
99 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800100 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
101 EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
102 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 1, *bucket1);
Bookatz857aaa52017-12-19 15:29:06 -0800103 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
Yang Lu3eba6212017-10-25 19:54:45 -0700104
Yangster-mace2cd6d52017-11-09 20:38:30 -0800105 // Adds past bucket #0 again. The sum does not change.
106 anomalyTracker.addPastBucket(bucket0, 0);
107 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
Yao Chend5aa01b32017-12-19 16:46:36 -0800108 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
109 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
110 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800111 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
112 EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
113 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1 + 1, 1, *bucket1);
Bookatz857aaa52017-12-19 15:29:06 -0800114 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
Yang Lu3eba6212017-10-25 19:54:45 -0700115
Yangster-mace2cd6d52017-11-09 20:38:30 -0800116 // Adds past bucket #1.
117 anomalyTracker.addPastBucket(bucket1, 1);
118 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L);
119 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800120 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
121 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
122 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800123 EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
124 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 2, *bucket2);
Bookatz857aaa52017-12-19 15:29:06 -0800125 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800126
127 // Adds past bucket #1 again. Nothing changes.
128 anomalyTracker.addPastBucket(bucket1, 1);
129 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L);
130 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800131 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
132 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
133 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800134 EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
135 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2 + 1, 2, *bucket2);
Bookatz857aaa52017-12-19 15:29:06 -0800136 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800137
138 // Adds past bucket #2.
139 anomalyTracker.addPastBucket(bucket2, 2);
140 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 2L);
141 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800142 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
143 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800144 EXPECT_TRUE(anomalyTracker.detectAnomaly(3, *bucket3));
145 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 3, *bucket3);
Yang Lu3eba6212017-10-25 19:54:45 -0700146 // Within refractory period.
Bookatz857aaa52017-12-19 15:29:06 -0800147 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yang Lu3eba6212017-10-25 19:54:45 -0700148
149 // Adds bucket #3.
Yangster-mace2cd6d52017-11-09 20:38:30 -0800150 anomalyTracker.addPastBucket(bucket3, 3L);
151 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 3L);
152 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800153 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
154 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800155 EXPECT_FALSE(anomalyTracker.detectAnomaly(4, *bucket4));
156 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 4, *bucket4);
Bookatz857aaa52017-12-19 15:29:06 -0800157 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yang Lu3eba6212017-10-25 19:54:45 -0700158
Yangster-mace2cd6d52017-11-09 20:38:30 -0800159 // Adds bucket #4.
160 anomalyTracker.addPastBucket(bucket4, 4);
161 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 4L);
162 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800163 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
164 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800165 EXPECT_TRUE(anomalyTracker.detectAnomaly(5, *bucket5));
166 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 5, *bucket5);
Bookatz857aaa52017-12-19 15:29:06 -0800167 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
Yang Lu3eba6212017-10-25 19:54:45 -0700168
Yangster-mace2cd6d52017-11-09 20:38:30 -0800169 // Adds bucket #5.
170 anomalyTracker.addPastBucket(bucket5, 5);
171 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 5L);
172 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800173 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
174 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800175 EXPECT_TRUE(anomalyTracker.detectAnomaly(6, *bucket6));
Yang Lu3eba6212017-10-25 19:54:45 -0700176 // Within refractory period.
Yangster-mace2cd6d52017-11-09 20:38:30 -0800177 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 6, *bucket6);
Bookatz857aaa52017-12-19 15:29:06 -0800178 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
Yang Lu3eba6212017-10-25 19:54:45 -0700179}
180
181TEST(AnomalyTrackerTest, TestSparseBuckets) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800182 const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Yang Lu3eba6212017-10-25 19:54:45 -0700183 Alert alert;
184 alert.set_number_of_buckets(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800185 alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
Yang Lu3eba6212017-10-25 19:54:45 -0700186 alert.set_trigger_if_sum_gt(2);
187
Bookatz8f2f3d82017-12-07 13:53:21 -0800188 AnomalyTracker anomalyTracker(alert, kConfigKey);
Yao Chend5aa01b32017-12-19 16:46:36 -0800189 HashableDimensionKey keyA = getMockDimensionKey(1, "a");
190 HashableDimensionKey keyB = getMockDimensionKey(1, "b");
191 HashableDimensionKey keyC = getMockDimensionKey(1, "c");
192 HashableDimensionKey keyD = getMockDimensionKey(1, "d");
193 HashableDimensionKey keyE = getMockDimensionKey(1, "e");
Yang Lu3eba6212017-10-25 19:54:45 -0700194
Yao Chend5aa01b32017-12-19 16:46:36 -0800195 std::shared_ptr<DimToValMap> bucket9 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}});
196 std::shared_ptr<DimToValMap> bucket16 = MockBucket({{keyB, 4}});
197 std::shared_ptr<DimToValMap> bucket18 = MockBucket({{keyB, 1}, {keyC, 1}});
198 std::shared_ptr<DimToValMap> bucket20 = MockBucket({{keyB, 3}, {keyC, 1}});
199 std::shared_ptr<DimToValMap> bucket25 = MockBucket({{keyD, 1}});
200 std::shared_ptr<DimToValMap> bucket28 = MockBucket({{keyE, 2}});
Yang Lu3eba6212017-10-25 19:54:45 -0700201
Yangster-mace2cd6d52017-11-09 20:38:30 -0800202 int64_t eventTimestamp1 = bucketSizeNs * 8 + 1;
203 int64_t eventTimestamp2 = bucketSizeNs * 15 + 11;
204 int64_t eventTimestamp3 = bucketSizeNs * 17 + 1;
205 int64_t eventTimestamp4 = bucketSizeNs * 19 + 2;
206 int64_t eventTimestamp5 = bucketSizeNs * 24 + 3;
207 int64_t eventTimestamp6 = bucketSizeNs * 27 + 3;
Yang Lu3eba6212017-10-25 19:54:45 -0700208
Yangster-mace2cd6d52017-11-09 20:38:30 -0800209 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
210 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
211 EXPECT_FALSE(anomalyTracker.detectAnomaly(9, *bucket9));
212 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 9, *bucket9);
Bookatz857aaa52017-12-19 15:29:06 -0800213 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800214
215 // Add past bucket #9
216 anomalyTracker.addPastBucket(bucket9, 9);
217 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 9L);
218 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800219 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
220 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
221 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800222 EXPECT_TRUE(anomalyTracker.detectAnomaly(16, *bucket16));
223 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
224 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
225 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 16, *bucket16);
226 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
Bookatz857aaa52017-12-19 15:29:06 -0800227 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800228 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
229
230 // Add past bucket #16
231 anomalyTracker.addPastBucket(bucket16, 16);
232 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 16L);
233 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800234 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800235 EXPECT_TRUE(anomalyTracker.detectAnomaly(18, *bucket18));
236 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800237 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
Yang Lu3eba6212017-10-25 19:54:45 -0700238 // Within refractory period.
Yangster-mace2cd6d52017-11-09 20:38:30 -0800239 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 18, *bucket18);
Bookatz857aaa52017-12-19 15:29:06 -0800240 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800241 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800242 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
Yang Lu3eba6212017-10-25 19:54:45 -0700243
Yangster-mace2cd6d52017-11-09 20:38:30 -0800244 // Add past bucket #18
245 anomalyTracker.addPastBucket(bucket18, 18);
246 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 18L);
247 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800248 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
249 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800250 EXPECT_TRUE(anomalyTracker.detectAnomaly(20, *bucket20));
251 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
252 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800253 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
254 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800255 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 20, *bucket20);
Bookatz857aaa52017-12-19 15:29:06 -0800256 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yang Lu3eba6212017-10-25 19:54:45 -0700257
Yangster-mace2cd6d52017-11-09 20:38:30 -0800258 // Add bucket #18 again. Nothing changes.
259 anomalyTracker.addPastBucket(bucket18, 18);
260 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
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 EXPECT_TRUE(anomalyTracker.detectAnomaly(20, *bucket20));
265 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800266 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
267 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800268 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4 + 1, 20, *bucket20);
269 // Within refractory period.
Bookatz857aaa52017-12-19 15:29:06 -0800270 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yang Lu3eba6212017-10-25 19:54:45 -0700271
Yangster-mace2cd6d52017-11-09 20:38:30 -0800272 // Add past bucket #20
273 anomalyTracker.addPastBucket(bucket20, 20);
274 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 20L);
275 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800276 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 3LL);
277 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800278 EXPECT_FALSE(anomalyTracker.detectAnomaly(25, *bucket25));
279 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 24L);
280 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
281 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 25, *bucket25);
Bookatz857aaa52017-12-19 15:29:06 -0800282 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yang Lu3eba6212017-10-25 19:54:45 -0700283
Yangster-mace2cd6d52017-11-09 20:38:30 -0800284 // Add past bucket #25
285 anomalyTracker.addPastBucket(bucket25, 25);
286 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 25L);
287 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
Yao Chend5aa01b32017-12-19 16:46:36 -0800288 EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyD), 1LL);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800289 EXPECT_FALSE(anomalyTracker.detectAnomaly(28, *bucket28));
290 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
291 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
292 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 28, *bucket28);
293 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
Bookatz857aaa52017-12-19 15:29:06 -0800294 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800295
296 // Updates current bucket #28.
Yao Chend5aa01b32017-12-19 16:46:36 -0800297 (*bucket28)[keyE] = 5;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800298 EXPECT_TRUE(anomalyTracker.detectAnomaly(28, *bucket28));
299 EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
300 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
301 anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6 + 7, 28, *bucket28);
302 EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
Bookatz857aaa52017-12-19 15:29:06 -0800303 EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp6 + 7);
Yang Lu3eba6212017-10-25 19:54:45 -0700304}
305
306} // namespace statsd
307} // namespace os
308} // namespace android
309#else
310GTEST_LOG_(INFO) << "This test does nothing.\n";
311#endif