13eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// Copyright (C) 2017 The Android Open Source Project 23eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// 33eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// Licensed under the Apache License, Version 2.0 (the "License"); 43eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// you may not use this file except in compliance with the License. 53eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// You may obtain a copy of the License at 63eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// 73eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// http://www.apache.org/licenses/LICENSE-2.0 83eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// 93eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// Unless required by applicable law or agreed to in writing, software 103eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// distributed under the License is distributed on an "AS IS" BASIS, 113eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// See the License for the specific language governing permissions and 133eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu// limitations under the License. 143eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 15e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac#include "src/anomaly/AnomalyTracker.h" 16d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen#include "../metrics/metrics_test_helper.h" 173eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 183eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu#include <gtest/gtest.h> 196bf9825b1575bfc3c62ef0a5129f94b6a776ef66Bookatz#include <math.h> 203eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu#include <stdio.h> 213eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu#include <vector> 223eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 233eba62186592382ed3d97cecca0c547487e4b2e4Yang Luusing namespace testing; 243eba62186592382ed3d97cecca0c547487e4b2e4Yang Luusing android::sp; 253eba62186592382ed3d97cecca0c547487e4b2e4Yang Luusing std::set; 263eba62186592382ed3d97cecca0c547487e4b2e4Yang Luusing std::unordered_map; 273eba62186592382ed3d97cecca0c547487e4b2e4Yang Luusing std::vector; 283eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 293eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu#ifdef __ANDROID__ 303eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 313eba62186592382ed3d97cecca0c547487e4b2e4Yang Lunamespace android { 323eba62186592382ed3d97cecca0c547487e4b2e4Yang Lunamespace os { 333eba62186592382ed3d97cecca0c547487e4b2e4Yang Lunamespace statsd { 343eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 3594e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-macconst ConfigKey kConfigKey(0, 12345); 368f2f3d82053693b0dac828e848e2bb238e1db2d2Bookatz 379369446f0b04945d6674550728ae81196d6fb5c2Yangster-macMetricDimensionKey getMockMetricDimensionKey(int key, string value) { 388a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen int pos[] = {key, 0, 0}; 398a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen HashableDimensionKey dim; 408a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen dim.addValue(FieldValue(Field(1, pos, 0), Value(value))); 418a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen return MetricDimensionKey(dim, DEFAULT_DIMENSION_KEY); 42d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen} 43d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen 449369446f0b04945d6674550728ae81196d6fb5c2Yangster-macvoid AddValueToBucket(const std::vector<std::pair<MetricDimensionKey, long>>& key_value_pair_list, 453eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu std::shared_ptr<DimToValMap> bucket) { 463eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu for (auto itr = key_value_pair_list.begin(); itr != key_value_pair_list.end(); itr++) { 473eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu (*bucket)[itr->first] += itr->second; 483eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu } 493eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} 503eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 51e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-macstd::shared_ptr<DimToValMap> MockBucket( 529369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac const std::vector<std::pair<MetricDimensionKey, long>>& key_value_pair_list) { 533eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu std::shared_ptr<DimToValMap> bucket = std::make_shared<DimToValMap>(); 543eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu AddValueToBucket(key_value_pair_list, bucket); 553eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu return bucket; 563eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} 573eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 581bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// Returns the value, for the given key, in that bucket, or 0 if not present. 591bf94382d036fa8d61258205c5f4e18cd53cb61dBookatzint64_t getBucketValue(const std::shared_ptr<DimToValMap>& bucket, 609369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac const MetricDimensionKey& key) { 611bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const auto& itr = bucket->find(key); 621bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz if (itr != bucket->end()) { 631bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz return itr->second; 641bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 651bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz return 0; 661bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz} 671bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 681bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// Returns true if keys in trueList are detected as anomalies and keys in falseList are not. 691bf94382d036fa8d61258205c5f4e18cd53cb61dBookatzbool detectAnomaliesPass(AnomalyTracker& tracker, 701bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int64_t& bucketNum, 711bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const std::shared_ptr<DimToValMap>& currentBucket, 729369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac const std::set<const MetricDimensionKey>& trueList, 739369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac const std::set<const MetricDimensionKey>& falseList) { 749369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac for (MetricDimensionKey key : trueList) { 751bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz if (!tracker.detectAnomaly(bucketNum, key, getBucketValue(currentBucket, key))) { 761bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz return false; 771bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 781bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 799369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac for (MetricDimensionKey key : falseList) { 801bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz if (tracker.detectAnomaly(bucketNum, key, getBucketValue(currentBucket, key))) { 811bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz return false; 821bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 831bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 841bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz return true; 851bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz} 861bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 871bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// Calls tracker.detectAndDeclareAnomaly on each key in the bucket. 881bf94382d036fa8d61258205c5f4e18cd53cb61dBookatzvoid detectAndDeclareAnomalies(AnomalyTracker& tracker, 891bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int64_t& bucketNum, 901bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const std::shared_ptr<DimToValMap>& bucket, 911bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int64_t& eventTimestamp) { 921bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz for (const auto& kv : *bucket) { 931bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, kv.first, kv.second); 941bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 951bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz} 961bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 971bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// Asserts that the refractory time for each key in timestamps is the corresponding 981bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// timestamp (in ns) + refractoryPeriodSec. 991bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// If a timestamp value is negative, instead asserts that the refractory period is inapplicable 1001bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz// (either non-existant or already past). 1011bf94382d036fa8d61258205c5f4e18cd53cb61dBookatzvoid checkRefractoryTimes(AnomalyTracker& tracker, 1021bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int64_t& currTimestampNs, 1031bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int32_t& refractoryPeriodSec, 1049369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac const std::unordered_map<MetricDimensionKey, int64_t>& timestamps) { 1051bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz for (const auto& kv : timestamps) { 1061bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz if (kv.second < 0) { 1071bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Make sure that, if there is a refractory period, it is already past. 1086bf9825b1575bfc3c62ef0a5129f94b6a776ef66Bookatz EXPECT_LT(tracker.getRefractoryPeriodEndsSec(kv.first) * NS_PER_SEC, 1096bf9825b1575bfc3c62ef0a5129f94b6a776ef66Bookatz (uint64_t)currTimestampNs) 1101bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz << "Failure was at currTimestampNs " << currTimestampNs; 1111bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } else { 1121bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_EQ(tracker.getRefractoryPeriodEndsSec(kv.first), 1136bf9825b1575bfc3c62ef0a5129f94b6a776ef66Bookatz std::ceil(1.0 * kv.second / NS_PER_SEC) + refractoryPeriodSec) 1141bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz << "Failure was at currTimestampNs " << currTimestampNs; 1151bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 1161bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz } 1171bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz} 1181bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 1193eba62186592382ed3d97cecca0c547487e4b2e4Yang LuTEST(AnomalyTrackerTest, TestConsecutiveBuckets) { 120e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac const int64_t bucketSizeNs = 30 * NS_PER_SEC; 1211bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int32_t refractoryPeriodSec = 2 * bucketSizeNs / NS_PER_SEC; 1223eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu Alert alert; 123a7fb12d2d285a3a62f5e8956d1bacfa0e15e9d0fYangster-mac alert.set_num_buckets(3); 1241bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz alert.set_refractory_period_secs(refractoryPeriodSec); 1253eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu alert.set_trigger_if_sum_gt(2); 1263eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 1278f2f3d82053693b0dac828e848e2bb238e1db2d2Bookatz AnomalyTracker anomalyTracker(alert, kConfigKey); 1289369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyA = getMockMetricDimensionKey(1, "a"); 1299369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyB = getMockMetricDimensionKey(1, "b"); 1309369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyC = getMockMetricDimensionKey(1, "c"); 131e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1321bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp0 = 10 * NS_PER_SEC; 1331bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp1 = bucketSizeNs + 11 * NS_PER_SEC; 1341bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp2 = 2 * bucketSizeNs + 12 * NS_PER_SEC; 1351bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp3 = 3 * bucketSizeNs + 13 * NS_PER_SEC; 1361bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp4 = 4 * bucketSizeNs + 14 * NS_PER_SEC; 1371bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp5 = 5 * bucketSizeNs + 5 * NS_PER_SEC; 1381bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz int64_t eventTimestamp6 = 6 * bucketSizeNs + 16 * NS_PER_SEC; 1391bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 140d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket0 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}}); 141d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket1 = MockBucket({{keyA, 1}}); 142d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket2 = MockBucket({{keyB, 1}}); 143d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket3 = MockBucket({{keyA, 2}}); 1441bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz std::shared_ptr<DimToValMap> bucket4 = MockBucket({{keyB, 5}}); 145d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket5 = MockBucket({{keyA, 2}}); 146d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket6 = MockBucket({{keyA, 2}}); 147e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1481bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Start time with no events. 149e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0u); 150e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL); 1511bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 1521bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #0 occurs. 1531bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 0, bucket0, {}, {keyA, keyB, keyC})); 1541bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 0, bucket0, eventTimestamp1); 1551bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp0, refractoryPeriodSec, 1561bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, -1}, {keyC, -1}}); 157e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 158e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds past bucket #0 159e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket0, 0); 160e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u); 161d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL); 162d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL); 163d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 164e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL); 1651bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 1661bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #1 occurs. 1671bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 1, bucket1, {}, {keyA, keyB, keyC})); 1681bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 1, bucket1, eventTimestamp1); 1691bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec, 1701bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, -1}, {keyC, -1}}); 171e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 172e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds past bucket #0 again. The sum does not change. 173e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket0, 0); 174e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u); 175d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL); 176d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL); 177d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 178e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL); 1791bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 1, bucket1, {}, {keyA, keyB, keyC})); 1801bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 1, bucket1, eventTimestamp1 + 1); 1811bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec, 1821bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, -1}, {keyC, -1}}); 183e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 184e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds past bucket #1. 185e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket1, 1); 186e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L); 187e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL); 188d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL); 189d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL); 190d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 1911bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 1921bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #2 occurs. New anomaly on keyB. 1931bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 2, bucket2, {keyB}, {keyA, keyC})); 1941bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 2, bucket2, eventTimestamp2); 1951bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec, 1961bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}}); 197e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 198e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds past bucket #1 again. Nothing changes. 199e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket1, 1); 200e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L); 201e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL); 202d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL); 203d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL); 204d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 2051bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #2 occurs (again). 2061bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 2, bucket2, {keyB}, {keyA, keyC})); 2071bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 2, bucket2, eventTimestamp2 + 1); 2081bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec, 2091bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}}); 210e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 211e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds past bucket #2. 212e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket2, 2); 213e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 2L); 214e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 215d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL); 216d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL); 2171bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 2181bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #3 occurs. New anomaly on keyA. 2191bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 3, bucket3, {keyA}, {keyB, keyC})); 2201bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 3, bucket3, eventTimestamp3); 2211bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp3, refractoryPeriodSec, 2221bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, eventTimestamp3}, {keyB, eventTimestamp2}, {keyC, -1}}); 2233eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 2243eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu // Adds bucket #3. 225e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket3, 3L); 226e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 3L); 227e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 228d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL); 229d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL); 2301bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 2311bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #4 occurs. New anomaly on keyB. 2321bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 4, bucket4, {keyB}, {keyA, keyC})); 2331bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 4, bucket4, eventTimestamp4); 2341bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp4, refractoryPeriodSec, 2351bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, eventTimestamp3}, {keyB, eventTimestamp4}, {keyC, -1}}); 2363eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 237e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds bucket #4. 238e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket4, 4); 239e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 4L); 240e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 241d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL); 2421bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 5LL); 2431bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 2441bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #5 occurs. New anomaly on keyA, which is still in refractory. 2451bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 5, bucket5, {keyA, keyB}, {keyC})); 2461bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 5, bucket5, eventTimestamp5); 2471bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp5, refractoryPeriodSec, 2481bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, eventTimestamp3}, {keyB, eventTimestamp4}, {keyC, -1}}); 249e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 250e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Adds bucket #5. 251e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket5, 5); 252e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 5L); 253e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 254d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL); 2551bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 5LL); 2561bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz 2571bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // Event from bucket #6 occurs. New anomaly on keyA, which is now out of refractory. 2581bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 6, bucket6, {keyA, keyB}, {keyC})); 2591bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 6, bucket6, eventTimestamp6); 2601bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec, 2611bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, eventTimestamp6}, {keyB, eventTimestamp4}, {keyC, -1}}); 2623eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} 2633eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 2643eba62186592382ed3d97cecca0c547487e4b2e4Yang LuTEST(AnomalyTrackerTest, TestSparseBuckets) { 265e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac const int64_t bucketSizeNs = 30 * NS_PER_SEC; 2661bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz const int32_t refractoryPeriodSec = 2 * bucketSizeNs / NS_PER_SEC; 2673eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu Alert alert; 268a7fb12d2d285a3a62f5e8956d1bacfa0e15e9d0fYangster-mac alert.set_num_buckets(3); 2691bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz alert.set_refractory_period_secs(refractoryPeriodSec); 2703eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu alert.set_trigger_if_sum_gt(2); 2713eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 2728f2f3d82053693b0dac828e848e2bb238e1db2d2Bookatz AnomalyTracker anomalyTracker(alert, kConfigKey); 2739369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyA = getMockMetricDimensionKey(1, "a"); 2749369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyB = getMockMetricDimensionKey(1, "b"); 2759369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyC = getMockMetricDimensionKey(1, "c"); 2769369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyD = getMockMetricDimensionKey(1, "d"); 2779369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey keyE = getMockMetricDimensionKey(1, "e"); 278d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen 279d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket9 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}}); 280d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket16 = MockBucket({{keyB, 4}}); 281d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket18 = MockBucket({{keyB, 1}, {keyC, 1}}); 282d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket20 = MockBucket({{keyB, 3}, {keyC, 1}}); 283d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket25 = MockBucket({{keyD, 1}}); 284d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen std::shared_ptr<DimToValMap> bucket28 = MockBucket({{keyE, 2}}); 285e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 286e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac int64_t eventTimestamp1 = bucketSizeNs * 8 + 1; 287e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac int64_t eventTimestamp2 = bucketSizeNs * 15 + 11; 288e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac int64_t eventTimestamp3 = bucketSizeNs * 17 + 1; 289e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac int64_t eventTimestamp4 = bucketSizeNs * 19 + 2; 290e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac int64_t eventTimestamp5 = bucketSizeNs * 24 + 3; 291e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac int64_t eventTimestamp6 = bucketSizeNs * 27 + 3; 292e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 293e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL); 294e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 2951bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 9, bucket9, {}, {keyA, keyB, keyC, keyD})); 2961bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 9, bucket9, eventTimestamp1); 2971bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec, 2981bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 299e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 300e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Add past bucket #9 301e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket9, 9); 302e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 9L); 303e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL); 304d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL); 305d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL); 306d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 3071bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 16, bucket16, {keyB}, {keyA, keyC, keyD})); 3081bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 309e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L); 3101bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 16, bucket16, eventTimestamp2); 3111bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 312e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L); 3131bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec, 3141bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 315e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 316e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Add past bucket #16 317e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket16, 16); 318e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 16L); 319e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL); 320d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL); 3211bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 18, bucket18, {keyB}, {keyA, keyC, keyD})); 322e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL); 323d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL); 324e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Within refractory period. 3251bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 18, bucket18, eventTimestamp3); 3261bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp3, refractoryPeriodSec, 3271bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 328e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL); 329d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL); 330e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 331e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Add past bucket #18 332e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket18, 18); 333e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 18L); 334e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 335d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL); 336d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 3371bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 20, bucket20, {keyB}, {keyA, keyC, keyD})); 338e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L); 339e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 340d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL); 341d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 3421bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 20, bucket20, eventTimestamp4); 3431bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp4, refractoryPeriodSec, 3441bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 345e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 346e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Add bucket #18 again. Nothing changes. 347e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket18, 18); 348e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L); 349e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 350d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL); 351d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 3521bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 20, bucket20, {keyB}, {keyA, keyC, keyD})); 353e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 354d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL); 355d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 3561bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 20, bucket20, eventTimestamp4 + 1); 3573eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu // Within refractory period. 3581bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp4 + 1, refractoryPeriodSec, 3591bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 360e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 361e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Add past bucket #20 362e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket20, 20); 363e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 20L); 364e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL); 365d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 3LL); 366d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL); 3671bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 25, bucket25, {}, {keyA, keyB, keyC, keyD})); 368e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 24L); 3691bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 3701bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 25, bucket25, eventTimestamp5); 3711bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp5, refractoryPeriodSec, 3721bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 373e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 374e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Add past bucket #25 375e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker.addPastBucket(bucket25, 25); 376e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 25L); 3771bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL); 378d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyD), 1LL); 3791bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 28, bucket28, {}, 3801bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {keyA, keyB, keyC, keyD, keyE})); 381e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L); 3821bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 3831bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 28, bucket28, eventTimestamp6); 3841bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 3851bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec, 3861bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, -1}}); 387e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 388e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Updates current bucket #28. 389d5aa01b3716e07463019fa772f07a40613f9e39eYao Chen (*bucket28)[keyE] = 5; 3901bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 28, bucket28, {keyE}, 3911bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {keyA, keyB, keyC, keyD})); 392e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L); 3931bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 3941bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz detectAndDeclareAnomalies(anomalyTracker, 28, bucket28, eventTimestamp6 + 7); 3951bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL); 3961bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec, 3971bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, eventTimestamp6 + 7}}); 3983eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} 3993eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu 4003eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} // namespace statsd 4013eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} // namespace os 4023eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu} // namespace android 4033eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu#else 4043eba62186592382ed3d97cecca0c547487e4b2e4Yang LuGTEST_LOG_(INFO) << "This test does nothing.\n"; 4053eba62186592382ed3d97cecca0c547487e4b2e4Yang Lu#endif 406