blob: 1d6f7de5e7e320ad56ee19e9818e0a80865c3452 [file] [log] [blame]
Yao Chen5154a372017-10-30 22:57:06 -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 Chend5aa01b32017-12-19 16:46:36 -080015#include "src/metrics/duration_helper/OringDurationTracker.h"
Yao Chen5154a372017-10-30 22:57:06 -070016#include "src/condition/ConditionWizard.h"
Yangster-mac94e197c2018-01-02 16:03:03 -080017#include "metrics_test_helper.h"
18#include "tests/statsd_test_util.h"
Yao Chen5154a372017-10-30 22:57:06 -070019
Yao Chen93fe3a32017-11-02 13:52:59 -070020#include <gmock/gmock.h>
21#include <gtest/gtest.h>
Bookatz6bf98252018-03-14 10:44:24 -070022#include <math.h>
Yao Chen5154a372017-10-30 22:57:06 -070023#include <stdio.h>
24#include <set>
25#include <unordered_map>
26#include <vector>
27
Yao Chen5154a372017-10-30 22:57:06 -070028using namespace testing;
29using android::sp;
30using std::set;
31using std::unordered_map;
32using std::vector;
33
34#ifdef __ANDROID__
Yao Chen93fe3a32017-11-02 13:52:59 -070035namespace android {
36namespace os {
37namespace statsd {
Yao Chen5154a372017-10-30 22:57:06 -070038
Yangster-mac94e197c2018-01-02 16:03:03 -080039const ConfigKey kConfigKey(0, 12345);
Yangster-mac20877162017-12-22 17:19:39 -080040const int TagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080041const int64_t metricId = 123;
David Chen27785a82018-01-19 17:06:45 -080042const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "event");
43
Yangster13fb7e42018-03-07 17:30:49 -080044const HashableDimensionKey kConditionKey1 = getMockedDimensionKey(TagId, 1, "maps");
David Chen27785a82018-01-19 17:06:45 -080045const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
46const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yangster-macb142cc82018-03-30 15:22:08 -070047const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Yao Chenb3561512017-11-21 18:07:17 -080048
Yao Chen5154a372017-10-30 22:57:06 -070049TEST(OringDurationTrackerTest, TestDurationOverlap) {
Yangster-mac93694462018-01-22 20:49:31 -080050 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
51
Yangster-mac93694462018-01-22 20:49:31 -080052 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
53 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yao Chen5154a372017-10-30 22:57:06 -070054 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
55
Yangster-mac93694462018-01-22 20:49:31 -080056 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yao Chen5154a372017-10-30 22:57:06 -070057
Yangster-macb142cc82018-03-30 15:22:08 -070058 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
59 int64_t bucketStartTimeNs = 10000000000;
60 int64_t bucketNum = 0;
61 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
62 int64_t durationTimeNs = 2 * 1000;
Yao Chen5154a372017-10-30 22:57:06 -070063
tsaichristine1449fa42020-01-02 12:12:05 -080064 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
65 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
66 false, false, {});
Yao Chen5154a372017-10-30 22:57:06 -070067
Yao Chend59a6582018-01-08 11:17:11 -080068 tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -080069 EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
Yao Chend59a6582018-01-08 11:17:11 -080070 tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
Yangster-mace2cd6d52017-11-09 20:38:30 -080071 EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
Yao Chen5154a372017-10-30 22:57:06 -070072
Yao Chend5aa01b32017-12-19 16:46:36 -080073 tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
Yao Chenf60e0ba2017-11-29 15:06:41 -080074 tracker.flushIfNeeded(eventStartTimeNs + bucketSizeNs + 1, &buckets);
75 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
76
Muhammad Qureshidff78d62020-05-11 13:37:43 -070077 ASSERT_EQ(1u, buckets[eventKey].size());
Yao Chenf60e0ba2017-11-29 15:06:41 -080078 EXPECT_EQ(durationTimeNs, buckets[eventKey][0].mDuration);
Yao Chen5154a372017-10-30 22:57:06 -070079}
80
Yao Chen0ea19902017-11-15 15:44:45 -080081TEST(OringDurationTrackerTest, TestDurationNested) {
Yangster-mac93694462018-01-22 20:49:31 -080082 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
83
Yangster-mac93694462018-01-22 20:49:31 -080084 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
85 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yao Chen0ea19902017-11-15 15:44:45 -080086 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
87
Yangster-mac93694462018-01-22 20:49:31 -080088 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yao Chen0ea19902017-11-15 15:44:45 -080089
Yangster-macb142cc82018-03-30 15:22:08 -070090 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
91 int64_t bucketStartTimeNs = 10000000000;
92 int64_t bucketNum = 0;
93 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
Yao Chen0ea19902017-11-15 15:44:45 -080094
tsaichristine1449fa42020-01-02 12:12:05 -080095 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
96 bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
Yao Chen0ea19902017-11-15 15:44:45 -080097
Yao Chend59a6582018-01-08 11:17:11 -080098 tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
99 tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
Yao Chen0ea19902017-11-15 15:44:45 -0800100
Yao Chend5aa01b32017-12-19 16:46:36 -0800101 tracker.noteStop(kEventKey1, eventStartTimeNs + 2000, false);
102 tracker.noteStop(kEventKey1, eventStartTimeNs + 2003, false);
Yao Chen0ea19902017-11-15 15:44:45 -0800103
Yao Chenf60e0ba2017-11-29 15:06:41 -0800104 tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
105 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700106 ASSERT_EQ(1u, buckets[eventKey].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700107 EXPECT_EQ(2003LL, buckets[eventKey][0].mDuration);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800108}
109
110TEST(OringDurationTrackerTest, TestStopAll) {
Yangster-mac93694462018-01-22 20:49:31 -0800111 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
112
113 const std::vector<HashableDimensionKey> kConditionKey1 =
114 {getMockedDimensionKey(TagId, 1, "maps")};
115 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
116 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800117 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
118
Yangster-mac93694462018-01-22 20:49:31 -0800119 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800120
Yangster-macb142cc82018-03-30 15:22:08 -0700121 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
122 int64_t bucketStartTimeNs = 10000000000;
123 int64_t bucketNum = 0;
124 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800125
tsaichristine1449fa42020-01-02 12:12:05 -0800126 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
127 bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
Yangster-mace2cd6d52017-11-09 20:38:30 -0800128
Yao Chend59a6582018-01-08 11:17:11 -0800129 tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
130 tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
Yangster-mace2cd6d52017-11-09 20:38:30 -0800131
132 tracker.noteStopAll(eventStartTimeNs + 2003);
133
Yao Chenf60e0ba2017-11-29 15:06:41 -0800134 tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
135 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700136 ASSERT_EQ(1u, buckets[eventKey].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700137 EXPECT_EQ(2003LL, buckets[eventKey][0].mDuration);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800138}
139
140TEST(OringDurationTrackerTest, TestCrossBucketBoundary) {
Yangster-mac93694462018-01-22 20:49:31 -0800141 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
142
Yangster-mac93694462018-01-22 20:49:31 -0800143 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
144 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800145 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
146
Yangster-mac93694462018-01-22 20:49:31 -0800147 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800148
Yangster-macb142cc82018-03-30 15:22:08 -0700149 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
150 int64_t bucketStartTimeNs = 10000000000;
151 int64_t bucketNum = 0;
152 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
153 int64_t durationTimeNs = 2 * 1000;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800154
tsaichristine1449fa42020-01-02 12:12:05 -0800155 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
156 bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
Yangster-mace2cd6d52017-11-09 20:38:30 -0800157
Yao Chend59a6582018-01-08 11:17:11 -0800158 tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800159 EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
Yao Chenf60e0ba2017-11-29 15:06:41 -0800160 tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs, &buckets);
Yao Chend59a6582018-01-08 11:17:11 -0800161 tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2 * bucketSizeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800162 EXPECT_EQ((long long)(bucketStartTimeNs + 2 * bucketSizeNs), tracker.mLastStartTime);
163
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700164 ASSERT_EQ(2u, buckets[eventKey].size());
Yao Chenf60e0ba2017-11-29 15:06:41 -0800165 EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
166 EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800167
Yao Chend5aa01b32017-12-19 16:46:36 -0800168 tracker.noteStop(kEventKey1, eventStartTimeNs + 2 * bucketSizeNs + 10, false);
169 tracker.noteStop(kEventKey1, eventStartTimeNs + 2 * bucketSizeNs + 12, false);
Yao Chenf60e0ba2017-11-29 15:06:41 -0800170 tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 12, &buckets);
171 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700172 ASSERT_EQ(2u, buckets[eventKey].size());
Yao Chenf60e0ba2017-11-29 15:06:41 -0800173 EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
174 EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration);
Yao Chen0ea19902017-11-15 15:44:45 -0800175}
176
Yao Chen5154a372017-10-30 22:57:06 -0700177TEST(OringDurationTrackerTest, TestDurationConditionChange) {
Yangster-mac93694462018-01-22 20:49:31 -0800178 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
179
Yangster-mac93694462018-01-22 20:49:31 -0800180 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
181 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yao Chen5154a372017-10-30 22:57:06 -0700182 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
183
184 ConditionKey key1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800185 key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
Yao Chen5154a372017-10-30 22:57:06 -0700186
tsaichristine76853372019-08-06 17:17:03 -0700187 EXPECT_CALL(*wizard, query(_, key1, _)) // #4
Yao Chen5154a372017-10-30 22:57:06 -0700188 .WillOnce(Return(ConditionState::kFalse));
189
Yangster-mac93694462018-01-22 20:49:31 -0800190 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yao Chen5154a372017-10-30 22:57:06 -0700191
Yangster-macb142cc82018-03-30 15:22:08 -0700192 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
193 int64_t bucketStartTimeNs = 10000000000;
194 int64_t bucketNum = 0;
195 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
196 int64_t durationTimeNs = 2 * 1000;
Yao Chen5154a372017-10-30 22:57:06 -0700197
tsaichristine1449fa42020-01-02 12:12:05 -0800198 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
199 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
200 true, false, {});
Yao Chen5154a372017-10-30 22:57:06 -0700201
Yao Chend5aa01b32017-12-19 16:46:36 -0800202 tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
Yao Chen5154a372017-10-30 22:57:06 -0700203
Yao Chen427d3722018-03-22 15:21:52 -0700204 tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 5);
Yao Chen09294ef2017-11-25 19:54:01 -0800205
Yao Chend5aa01b32017-12-19 16:46:36 -0800206 tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
Yao Chen09294ef2017-11-25 19:54:01 -0800207
Yao Chenf60e0ba2017-11-29 15:06:41 -0800208 tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
209 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700210 ASSERT_EQ(1u, buckets[eventKey].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700211 EXPECT_EQ(5LL, buckets[eventKey][0].mDuration);
Yao Chen09294ef2017-11-25 19:54:01 -0800212}
213
214TEST(OringDurationTrackerTest, TestDurationConditionChange2) {
Yangster-mac93694462018-01-22 20:49:31 -0800215 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
216
Yangster-mac93694462018-01-22 20:49:31 -0800217 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
218 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yao Chen09294ef2017-11-25 19:54:01 -0800219 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
220
221 ConditionKey key1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800222 key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
Yao Chen09294ef2017-11-25 19:54:01 -0800223
tsaichristine76853372019-08-06 17:17:03 -0700224 EXPECT_CALL(*wizard, query(_, key1, _))
Yao Chen09294ef2017-11-25 19:54:01 -0800225 .Times(2)
226 .WillOnce(Return(ConditionState::kFalse))
227 .WillOnce(Return(ConditionState::kTrue));
228
Yangster-mac93694462018-01-22 20:49:31 -0800229 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yao Chen09294ef2017-11-25 19:54:01 -0800230
Yangster-macb142cc82018-03-30 15:22:08 -0700231 int64_t bucketStartTimeNs = 10000000000;
232 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
233 int64_t bucketNum = 0;
234 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
235 int64_t durationTimeNs = 2 * 1000;
Yao Chen09294ef2017-11-25 19:54:01 -0800236
tsaichristine1449fa42020-01-02 12:12:05 -0800237 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
238 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
239 true, false, {});
Yao Chen09294ef2017-11-25 19:54:01 -0800240
Yao Chend5aa01b32017-12-19 16:46:36 -0800241 tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
Yao Chen09294ef2017-11-25 19:54:01 -0800242 // condition to false; record duration 5n
Yao Chen427d3722018-03-22 15:21:52 -0700243 tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 5);
Yao Chen09294ef2017-11-25 19:54:01 -0800244 // condition to true.
Yao Chen427d3722018-03-22 15:21:52 -0700245 tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 1000);
Yao Chen09294ef2017-11-25 19:54:01 -0800246 // 2nd duration: 1000ns
Yao Chend5aa01b32017-12-19 16:46:36 -0800247 tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
Yao Chen09294ef2017-11-25 19:54:01 -0800248
Yao Chenf60e0ba2017-11-29 15:06:41 -0800249 tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
250 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700251 ASSERT_EQ(1u, buckets[eventKey].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700252 EXPECT_EQ(1005LL, buckets[eventKey][0].mDuration);
Yao Chen5154a372017-10-30 22:57:06 -0700253}
Yao Chen0ea19902017-11-15 15:44:45 -0800254
255TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) {
Yangster-mac93694462018-01-22 20:49:31 -0800256 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
257
Yangster-mac93694462018-01-22 20:49:31 -0800258 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
259 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yao Chen0ea19902017-11-15 15:44:45 -0800260 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
261
262 ConditionKey key1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800263 key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
Yao Chen0ea19902017-11-15 15:44:45 -0800264
tsaichristine76853372019-08-06 17:17:03 -0700265 EXPECT_CALL(*wizard, query(_, key1, _)) // #4
Yao Chen0ea19902017-11-15 15:44:45 -0800266 .WillOnce(Return(ConditionState::kFalse));
267
Yangster-mac93694462018-01-22 20:49:31 -0800268 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yao Chen0ea19902017-11-15 15:44:45 -0800269
Yangster-macb142cc82018-03-30 15:22:08 -0700270 int64_t bucketStartTimeNs = 10000000000;
271 int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
272 int64_t bucketNum = 0;
273 int64_t eventStartTimeNs = bucketStartTimeNs + 1;
Yao Chen0ea19902017-11-15 15:44:45 -0800274
tsaichristine1449fa42020-01-02 12:12:05 -0800275 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
276 bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {});
Yao Chen0ea19902017-11-15 15:44:45 -0800277
Yao Chend5aa01b32017-12-19 16:46:36 -0800278 tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
279 tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2, key1);
Yao Chen0ea19902017-11-15 15:44:45 -0800280
Yao Chend5aa01b32017-12-19 16:46:36 -0800281 tracker.noteStop(kEventKey1, eventStartTimeNs + 3, false);
Yao Chen0ea19902017-11-15 15:44:45 -0800282
Yao Chen427d3722018-03-22 15:21:52 -0700283 tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 15);
Yao Chen0ea19902017-11-15 15:44:45 -0800284
Yao Chend5aa01b32017-12-19 16:46:36 -0800285 tracker.noteStop(kEventKey1, eventStartTimeNs + 2003, false);
Yao Chen0ea19902017-11-15 15:44:45 -0800286
Yao Chenf60e0ba2017-11-29 15:06:41 -0800287 tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
288 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700289 ASSERT_EQ(1u, buckets[eventKey].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700290 EXPECT_EQ(15LL, buckets[eventKey][0].mDuration);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800291}
292
293TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) {
Yangster-mac93694462018-01-22 20:49:31 -0800294 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
295
Yangster-mac93694462018-01-22 20:49:31 -0800296 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
297 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800298 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800299 alert.set_id(101);
300 alert.set_metric_id(1);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800301 alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800302 alert.set_num_buckets(2);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800303 alert.set_refractory_period_secs(1);
304
Yangster-mac93694462018-01-22 20:49:31 -0800305 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800306 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chend59a6582018-01-08 11:17:11 -0800307
Yangster-macb142cc82018-03-30 15:22:08 -0700308 int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
309 int64_t bucketNum = 0;
310 int64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800311
Yangster-mac932ecec2018-02-01 10:23:52 -0800312 sp<AlarmMonitor> alarmMonitor;
313 sp<DurationAnomalyTracker> anomalyTracker =
314 new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
tsaichristine1449fa42020-01-02 12:12:05 -0800315 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
316 bucketNum, bucketStartTimeNs, bucketSizeNs, true, false,
317 {anomalyTracker});
Yangster-mace2cd6d52017-11-09 20:38:30 -0800318
319 // Nothing in the past bucket.
Yao Chend59a6582018-01-08 11:17:11 -0800320 tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800321 EXPECT_EQ((long long)(alert.trigger_if_sum_gt() + eventStartTimeNs),
322 tracker.predictAnomalyTimestampNs(*anomalyTracker, eventStartTimeNs));
323
Yao Chend5aa01b32017-12-19 16:46:36 -0800324 tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 3, false);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700325 ASSERT_EQ(0u, buckets[eventKey].size());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800326
Yangster-macb142cc82018-03-30 15:22:08 -0700327 int64_t event1StartTimeNs = eventStartTimeNs + 10;
Yao Chend59a6582018-01-08 11:17:11 -0800328 tracker.noteStart(kEventKey1, true, event1StartTimeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800329 // No past buckets. The anomaly will happen in bucket #0.
330 EXPECT_EQ((long long)(event1StartTimeNs + alert.trigger_if_sum_gt() - 3),
331 tracker.predictAnomalyTimestampNs(*anomalyTracker, event1StartTimeNs));
332
Yangster-macb142cc82018-03-30 15:22:08 -0700333 int64_t event1StopTimeNs = eventStartTimeNs + bucketSizeNs + 10;
Yao Chenf60e0ba2017-11-29 15:06:41 -0800334 tracker.flushIfNeeded(event1StopTimeNs, &buckets);
Yao Chend5aa01b32017-12-19 16:46:36 -0800335 tracker.noteStop(kEventKey1, event1StopTimeNs, false);
Yao Chenf60e0ba2017-11-29 15:06:41 -0800336
337 EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700338 ASSERT_EQ(1u, buckets[eventKey].size());
Yangster-macb142cc82018-03-30 15:22:08 -0700339 EXPECT_EQ(3LL + bucketStartTimeNs + bucketSizeNs - eventStartTimeNs - 10,
Yao Chenf60e0ba2017-11-29 15:06:41 -0800340 buckets[eventKey][0].mDuration);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800341
342 const int64_t bucket0Duration = 3ULL + bucketStartTimeNs + bucketSizeNs - eventStartTimeNs - 10;
343 const int64_t bucket1Duration = eventStartTimeNs + 10 - bucketStartTimeNs;
344
345 // One past buckets. The anomaly will happen in bucket #1.
Yangster-macb142cc82018-03-30 15:22:08 -0700346 int64_t event2StartTimeNs = eventStartTimeNs + bucketSizeNs + 15;
Yao Chend59a6582018-01-08 11:17:11 -0800347 tracker.noteStart(kEventKey1, true, event2StartTimeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800348 EXPECT_EQ((long long)(event2StartTimeNs + alert.trigger_if_sum_gt() - bucket0Duration -
349 bucket1Duration),
350 tracker.predictAnomalyTimestampNs(*anomalyTracker, event2StartTimeNs));
Yao Chend5aa01b32017-12-19 16:46:36 -0800351 tracker.noteStop(kEventKey1, event2StartTimeNs + 1, false);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800352
353 // Only one past buckets is applicable. Bucket +0 should be trashed. The anomaly will happen in
354 // bucket #2.
Yangster-macb142cc82018-03-30 15:22:08 -0700355 int64_t event3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs - 9 * NS_PER_SEC;
Yao Chend59a6582018-01-08 11:17:11 -0800356 tracker.noteStart(kEventKey1, true, event3StartTimeNs, ConditionKey());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800357 EXPECT_EQ((long long)(event3StartTimeNs + alert.trigger_if_sum_gt() - bucket1Duration - 1LL),
358 tracker.predictAnomalyTimestampNs(*anomalyTracker, event3StartTimeNs));
359}
360
Yangster-macbe10ddf2018-03-13 15:39:51 -0700361TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp2) {
Yangster-macbe10ddf2018-03-13 15:39:51 -0700362 Alert alert;
363 alert.set_id(101);
364 alert.set_metric_id(1);
365 alert.set_trigger_if_sum_gt(5 * NS_PER_SEC);
366 alert.set_num_buckets(1);
367 alert.set_refractory_period_secs(20);
368
Yangster-macb142cc82018-03-30 15:22:08 -0700369 int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
370 int64_t bucketNum = 0;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700371
372 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
373 sp<AlarmMonitor> alarmMonitor;
374 sp<DurationAnomalyTracker> anomalyTracker =
375 new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
376 OringDurationTracker tracker(kConfigKey, metricId, DEFAULT_METRIC_DIMENSION_KEY, wizard, 1,
tsaichristine76853372019-08-06 17:17:03 -0700377
Yangster-macbe10ddf2018-03-13 15:39:51 -0700378 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
379 bucketSizeNs, true, false, {anomalyTracker});
380
Yangster-macb142cc82018-03-30 15:22:08 -0700381 int64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700382 tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
383 // Anomaly happens in the bucket #1.
384 EXPECT_EQ((long long)(bucketStartTimeNs + 14 * NS_PER_SEC),
385 tracker.predictAnomalyTimestampNs(*anomalyTracker, eventStartTimeNs));
386
387 tracker.noteStop(DEFAULT_DIMENSION_KEY, bucketStartTimeNs + 14 * NS_PER_SEC, false);
388
389 EXPECT_EQ((long long)(bucketStartTimeNs + 34 * NS_PER_SEC) / NS_PER_SEC,
390 anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY));
391
Yangster-macb142cc82018-03-30 15:22:08 -0700392 int64_t event2StartTimeNs = bucketStartTimeNs + 22 * NS_PER_SEC;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700393 EXPECT_EQ((long long)(bucketStartTimeNs + 34 * NS_PER_SEC) / NS_PER_SEC,
394 anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY));
395 EXPECT_EQ((long long)(bucketStartTimeNs + 35 * NS_PER_SEC),
396 tracker.predictAnomalyTimestampNs(*anomalyTracker, event2StartTimeNs));
397}
398
399TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp3) {
400 // Test the cases where the refractory period is smaller than the bucket size, longer than
401 // the bucket size, and longer than 2x of the anomaly detection window.
402 for (int j = 0; j < 3; j++) {
Yangster-macb142cc82018-03-30 15:22:08 -0700403 int64_t thresholdNs = j * bucketSizeNs + 5 * NS_PER_SEC;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700404 for (int i = 0; i <= 7; ++i) {
tsaichristine76853372019-08-06 17:17:03 -0700405
Yangster-macbe10ddf2018-03-13 15:39:51 -0700406 Alert alert;
407 alert.set_id(101);
408 alert.set_metric_id(1);
409 alert.set_trigger_if_sum_gt(thresholdNs);
410 alert.set_num_buckets(3);
411 alert.set_refractory_period_secs(
412 bucketSizeNs / NS_PER_SEC / 2 + i * bucketSizeNs / NS_PER_SEC);
413
Yangster-macb142cc82018-03-30 15:22:08 -0700414 int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
415 int64_t bucketNum = 101;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700416
417 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
418 sp<AlarmMonitor> alarmMonitor;
419 sp<DurationAnomalyTracker> anomalyTracker =
420 new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
tsaichristine1449fa42020-01-02 12:12:05 -0800421 OringDurationTracker tracker(kConfigKey, metricId, DEFAULT_METRIC_DIMENSION_KEY, wizard,
422 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
Yangster-macbe10ddf2018-03-13 15:39:51 -0700423 bucketSizeNs, true, false, {anomalyTracker});
424
Yangster-macb142cc82018-03-30 15:22:08 -0700425 int64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700426 tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
427 EXPECT_EQ((long long)(eventStartTimeNs + thresholdNs),
428 tracker.predictAnomalyTimestampNs(*anomalyTracker, eventStartTimeNs));
Yangster-macb142cc82018-03-30 15:22:08 -0700429 int64_t eventStopTimeNs = eventStartTimeNs + thresholdNs + NS_PER_SEC;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700430 tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStopTimeNs, false);
431
Yangster-macb142cc82018-03-30 15:22:08 -0700432 int64_t refractoryPeriodEndSec =
Yangster-macbe10ddf2018-03-13 15:39:51 -0700433 anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY);
Yangster-macb142cc82018-03-30 15:22:08 -0700434 EXPECT_EQ(eventStopTimeNs / (int64_t)NS_PER_SEC + alert.refractory_period_secs(),
Yangster-macbe10ddf2018-03-13 15:39:51 -0700435 refractoryPeriodEndSec);
436
437 // Acquire and release a wakelock in the next bucket.
Yangster-macb142cc82018-03-30 15:22:08 -0700438 int64_t event2StartTimeNs = eventStopTimeNs + bucketSizeNs;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700439 tracker.noteStart(DEFAULT_DIMENSION_KEY, true, event2StartTimeNs, ConditionKey());
Yangster-macb142cc82018-03-30 15:22:08 -0700440 int64_t event2StopTimeNs = event2StartTimeNs + 4 * NS_PER_SEC;
Yangster-macbe10ddf2018-03-13 15:39:51 -0700441 tracker.noteStop(DEFAULT_DIMENSION_KEY, event2StopTimeNs, false);
442
443 // Test the alarm prediction works well when seeing another wakelock start event.
444 for (int k = 0; k <= 2; ++k) {
Yangster-macb142cc82018-03-30 15:22:08 -0700445 int64_t event3StartTimeNs = event2StopTimeNs + NS_PER_SEC + k * bucketSizeNs;
446 int64_t alarmTimestampNs =
Yangster-macbe10ddf2018-03-13 15:39:51 -0700447 tracker.predictAnomalyTimestampNs(*anomalyTracker, event3StartTimeNs);
448 EXPECT_GT(alarmTimestampNs, 0u);
449 EXPECT_GE(alarmTimestampNs, event3StartTimeNs);
Yangster-macb142cc82018-03-30 15:22:08 -0700450 EXPECT_GE(alarmTimestampNs, refractoryPeriodEndSec *(int64_t) NS_PER_SEC);
Yangster-macbe10ddf2018-03-13 15:39:51 -0700451 }
452 }
453 }
454}
455
Bookatz1bf94382018-01-04 11:43:20 -0800456TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) {
Yangster-mac93694462018-01-22 20:49:31 -0800457 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
458
Yangster-mac93694462018-01-22 20:49:31 -0800459 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
460 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800461 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800462 alert.set_id(101);
463 alert.set_metric_id(1);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800464 alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800465 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800466 const int32_t refPeriodSec = 45;
467 alert.set_refractory_period_secs(refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800468
Yangster-mac93694462018-01-22 20:49:31 -0800469 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800470 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chend59a6582018-01-08 11:17:11 -0800471
Yangster-macb142cc82018-03-30 15:22:08 -0700472 int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
473 int64_t bucketNum = 0;
474 int64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800475
Yangster-mac932ecec2018-02-01 10:23:52 -0800476 sp<AlarmMonitor> alarmMonitor;
477 sp<DurationAnomalyTracker> anomalyTracker =
478 new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
tsaichristine1449fa42020-01-02 12:12:05 -0800479 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/,
480 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
481 false, false, {anomalyTracker});
Yangster-mace2cd6d52017-11-09 20:38:30 -0800482
Bookatz1bf94382018-01-04 11:43:20 -0800483 tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
484 tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false);
485 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800486 EXPECT_TRUE(tracker.mStarted.empty());
tsaichristine1449fa42020-01-02 12:12:05 -0800487 EXPECT_EQ(10LL, tracker.mStateKeyDurationMap[DEFAULT_DIMENSION_KEY].mDuration); // 10ns
Yangster-mace2cd6d52017-11-09 20:38:30 -0800488
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700489 ASSERT_EQ(0u, tracker.mStarted.size());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800490
Bookatz1bf94382018-01-04 11:43:20 -0800491 tracker.noteStart(kEventKey1, true, eventStartTimeNs + 20, ConditionKey());
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700492 ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
Bookatz14e0d852018-02-13 15:55:14 -0800493 EXPECT_EQ((long long)(52ULL * NS_PER_SEC), // (10s + 1s + 1ns + 20ns) - 10ns + 40s, rounded up
Yangster-mace2cd6d52017-11-09 20:38:30 -0800494 (long long)(anomalyTracker->mAlarms.begin()->second->timestampSec * NS_PER_SEC));
Bookatz14e0d852018-02-13 15:55:14 -0800495 // The alarm is set to fire at 52s, and when it does, an anomaly would be declared. However,
Bookatz1bf94382018-01-04 11:43:20 -0800496 // because this is a unit test, the alarm won't actually fire at all. Since the alarm fails
497 // to fire in time, the anomaly is instead caught when noteStop is called, at around 71s.
Yao Chenf60e0ba2017-11-29 15:06:41 -0800498 tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 25, &buckets);
Bookatz1bf94382018-01-04 11:43:20 -0800499 tracker.noteStop(kEventKey1, eventStartTimeNs + 2 * bucketSizeNs + 25, false);
Yao Chend5aa01b32017-12-19 16:46:36 -0800500 EXPECT_EQ(anomalyTracker->getSumOverPastBuckets(eventKey), (long long)(bucketSizeNs));
Bookatz1bf94382018-01-04 11:43:20 -0800501 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey),
Bookatz6bf98252018-03-14 10:44:24 -0700502 std::ceil((eventStartTimeNs + 2 * bucketSizeNs + 25.0) / NS_PER_SEC + refPeriodSec));
Bookatz1bf94382018-01-04 11:43:20 -0800503}
504
505TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) {
Yangster-mac93694462018-01-22 20:49:31 -0800506 const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
507
Yangster-mac93694462018-01-22 20:49:31 -0800508 const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
509 const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
Bookatz1bf94382018-01-04 11:43:20 -0800510 Alert alert;
511 alert.set_id(101);
512 alert.set_metric_id(1);
513 alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
514 alert.set_num_buckets(2);
515 const int32_t refPeriodSec = 45;
516 alert.set_refractory_period_secs(refPeriodSec);
517
Yangster-mac93694462018-01-22 20:49:31 -0800518 unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
Bookatz1bf94382018-01-04 11:43:20 -0800519 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
520 ConditionKey conkey;
521 conkey[StringToId("APP_BACKGROUND")] = kConditionKey1;
Yangster-macb142cc82018-03-30 15:22:08 -0700522 int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
523 int64_t bucketSizeNs = 30 * NS_PER_SEC;
Bookatz1bf94382018-01-04 11:43:20 -0800524
Yangster-mac932ecec2018-02-01 10:23:52 -0800525 sp<AlarmMonitor> alarmMonitor;
526 sp<DurationAnomalyTracker> anomalyTracker =
527 new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
tsaichristine1449fa42020-01-02 12:12:05 -0800528 OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/,
529 bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, false,
530 false, {anomalyTracker});
Bookatz1bf94382018-01-04 11:43:20 -0800531
tsaichristine1449fa42020-01-02 12:12:05 -0800532 tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey); // start key1
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700533 ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
Yangster-mac932ecec2018-02-01 10:23:52 -0800534 sp<const InternalAlarm> alarm = anomalyTracker->mAlarms.begin()->second;
Bookatz1bf94382018-01-04 11:43:20 -0800535 EXPECT_EQ((long long)(55ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
536 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
537
538 tracker.noteStop(kEventKey1, 17 * NS_PER_SEC, false); // stop key1 (2 seconds later)
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700539 ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
Bookatz1bf94382018-01-04 11:43:20 -0800540 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
541
tsaichristine1449fa42020-01-02 12:12:05 -0800542 tracker.noteStart(kEventKey1, true, 22 * NS_PER_SEC, conkey); // start key1 again
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700543 ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
Bookatz1bf94382018-01-04 11:43:20 -0800544 alarm = anomalyTracker->mAlarms.begin()->second;
545 EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
546 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
547
tsaichristine1449fa42020-01-02 12:12:05 -0800548 tracker.noteStart(kEventKey2, true, 32 * NS_PER_SEC, conkey); // start key2
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700549 ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
Bookatz1bf94382018-01-04 11:43:20 -0800550 alarm = anomalyTracker->mAlarms.begin()->second;
551 EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
552 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
553
554 tracker.noteStop(kEventKey1, 47 * NS_PER_SEC, false); // stop key1
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700555 ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
Bookatz1bf94382018-01-04 11:43:20 -0800556 alarm = anomalyTracker->mAlarms.begin()->second;
557 EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
558 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
559
560 // Now, at 60s, which is 38s after key1 started again, we have reached 40s of 'on' time.
Yangster-mac932ecec2018-02-01 10:23:52 -0800561 std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> firedAlarms({alarm});
Bookatz1bf94382018-01-04 11:43:20 -0800562 anomalyTracker->informAlarmsFired(62 * NS_PER_SEC, firedAlarms);
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700563 ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
Bookatz1bf94382018-01-04 11:43:20 -0800564 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 62U + refPeriodSec);
565
566 tracker.noteStop(kEventKey2, 69 * NS_PER_SEC, false); // stop key2
Muhammad Qureshidff78d62020-05-11 13:37:43 -0700567 ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
Bookatz1bf94382018-01-04 11:43:20 -0800568 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 62U + refPeriodSec);
Yao Chen0ea19902017-11-15 15:44:45 -0800569}
570
Yao Chen93fe3a32017-11-02 13:52:59 -0700571} // namespace statsd
572} // namespace os
573} // namespace android
Yao Chen5154a372017-10-30 22:57:06 -0700574#else
575GTEST_LOG_(INFO) << "This test does nothing.\n";
tsaichristine76853372019-08-06 17:17:03 -0700576#endif