1 // 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 
15 #include "src/metrics/GaugeMetricProducer.h"
16 #include "src/stats_log_util.h"
17 #include "logd/LogEvent.h"
18 #include "metrics_test_helper.h"
19 #include "tests/statsd_test_util.h"
20 
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include <vector>
26 
27 using namespace testing;
28 using android::sp;
29 using std::set;
30 using std::unordered_map;
31 using std::vector;
32 using std::make_shared;
33 
34 #ifdef __ANDROID__
35 
36 namespace android {
37 namespace os {
38 namespace statsd {
39 
40 const ConfigKey kConfigKey(0, 12345);
41 const int tagId = 1;
42 const int64_t metricId = 123;
43 const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
44 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
45 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
46 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
47 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
48 const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
49 
TEST(GaugeMetricProducerTest,TestNoCondition)50 TEST(GaugeMetricProducerTest, TestNoCondition) {
51     GaugeMetric metric;
52     metric.set_id(metricId);
53     metric.set_bucket(ONE_MINUTE);
54     metric.mutable_gauge_fields_filter()->set_include_all(false);
55     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
56     gaugeFieldMatcher->set_field(tagId);
57     gaugeFieldMatcher->add_child()->set_field(1);
58     gaugeFieldMatcher->add_child()->set_field(3);
59 
60     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
61 
62     // TODO: pending refactor of StatsPullerManager
63     // For now we still need this so that it doesn't do real pulling.
64     shared_ptr<MockStatsPullerManager> pullerManager =
65             make_shared<StrictMock<MockStatsPullerManager>>();
66     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
67     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
68 
69     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
70                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
71     gaugeProducer.setBucketSize(60 * NS_PER_SEC);
72 
73     vector<shared_ptr<LogEvent>> allData;
74     allData.clear();
75     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
76     event->write(10);
77     event->write("some value");
78     event->write(11);
79     event->init();
80     allData.push_back(event);
81 
82     gaugeProducer.onDataPulled(allData);
83     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
84     auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
85     EXPECT_EQ(INT, it->mValue.getType());
86     EXPECT_EQ(10, it->mValue.int_value);
87     it++;
88     EXPECT_EQ(11, it->mValue.int_value);
89     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
90 
91     allData.clear();
92     std::shared_ptr<LogEvent> event2 =
93             std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
94     event2->write(24);
95     event2->write("some value");
96     event2->write(25);
97     event2->init();
98     allData.push_back(event2);
99     gaugeProducer.onDataPulled(allData);
100     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
101     it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
102     EXPECT_EQ(INT, it->mValue.getType());
103     EXPECT_EQ(24, it->mValue.int_value);
104     it++;
105     EXPECT_EQ(INT, it->mValue.getType());
106     EXPECT_EQ(25, it->mValue.int_value);
107     // One dimension.
108     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
109     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
110     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
111     EXPECT_EQ(INT, it->mValue.getType());
112     EXPECT_EQ(10L, it->mValue.int_value);
113     it++;
114     EXPECT_EQ(INT, it->mValue.getType());
115     EXPECT_EQ(11L, it->mValue.int_value);
116 
117     gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
118     EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
119     // One dimension.
120     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
121     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
122     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
123     EXPECT_EQ(INT, it->mValue.getType());
124     EXPECT_EQ(24L, it->mValue.int_value);
125     it++;
126     EXPECT_EQ(INT, it->mValue.getType());
127     EXPECT_EQ(25L, it->mValue.int_value);
128 }
129 
TEST(GaugeMetricProducerTest,TestPushedEventsWithUpgrade)130 TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
131     sp<AlarmMonitor> alarmMonitor;
132     GaugeMetric metric;
133     metric.set_id(metricId);
134     metric.set_bucket(ONE_MINUTE);
135     metric.mutable_gauge_fields_filter()->set_include_all(true);
136 
137     Alert alert;
138     alert.set_id(101);
139     alert.set_metric_id(metricId);
140     alert.set_trigger_if_sum_gt(25);
141     alert.set_num_buckets(100);
142     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
143     shared_ptr<MockStatsPullerManager> pullerManager =
144             make_shared<StrictMock<MockStatsPullerManager>>();
145     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
146                                       -1 /* -1 means no pulling */, bucketStartTimeNs,
147                                       bucketStartTimeNs, pullerManager);
148 
149     gaugeProducer.setBucketSize(60 * NS_PER_SEC);
150     sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
151     EXPECT_TRUE(anomalyTracker != nullptr);
152 
153     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
154     event1->write(1);
155     event1->write(10);
156     event1->init();
157     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
158     EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
159 
160     gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
161     EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
162     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
163     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
164     EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
165     // Partial buckets are not sent to anomaly tracker.
166     EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
167 
168     // Create an event in the same partial bucket.
169     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
170     event2->write(1);
171     event2->write(10);
172     event2->init();
173     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
174     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
175     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
176     EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
177     // Partial buckets are not sent to anomaly tracker.
178     EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
179 
180     // Next event should trigger creation of new bucket and send previous full bucket to anomaly
181     // tracker.
182     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
183     event3->write(1);
184     event3->write(10);
185     event3->init();
186     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
187     EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
188     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
189     EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
190     EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
191 
192     // Next event should trigger creation of new bucket.
193     shared_ptr<LogEvent> event4 =
194             make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
195     event4->write(1);
196     event4->write(10);
197     event4->init();
198     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
199     EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
200     EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
201     EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
202 }
203 
TEST(GaugeMetricProducerTest,TestPulledWithUpgrade)204 TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
205     GaugeMetric metric;
206     metric.set_id(metricId);
207     metric.set_bucket(ONE_MINUTE);
208     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
209     gaugeFieldMatcher->set_field(tagId);
210     gaugeFieldMatcher->add_child()->set_field(2);
211 
212     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
213 
214     shared_ptr<MockStatsPullerManager> pullerManager =
215             make_shared<StrictMock<MockStatsPullerManager>>();
216     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
217     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
218     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
219             .WillOnce(Invoke([](int tagId, int64_t timeNs,
220                                 vector<std::shared_ptr<LogEvent>>* data) {
221                 data->clear();
222                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
223                 event->write("some value");
224                 event->write(2);
225                 event->init();
226                 data->push_back(event);
227                 return true;
228             }));
229 
230     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
231                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
232     gaugeProducer.setBucketSize(60 * NS_PER_SEC);
233 
234     vector<shared_ptr<LogEvent>> allData;
235     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
236     event->write("some value");
237     event->write(1);
238     event->init();
239     allData.push_back(event);
240     gaugeProducer.onDataPulled(allData);
241     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
242     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
243                          ->second.front()
244                          .mFields->begin()
245                          ->mValue.int_value);
246 
247     gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
248     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
249     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
250     EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
251     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
252     EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
253                          ->second.front()
254                          .mFields->begin()
255                          ->mValue.int_value);
256 
257     allData.clear();
258     event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
259     event->write("some value");
260     event->write(3);
261     event->init();
262     allData.push_back(event);
263     gaugeProducer.onDataPulled(allData);
264     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
265     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
266     EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
267                          ->second.front()
268                          .mFields->begin()
269                          ->mValue.int_value);
270 }
271 
TEST(GaugeMetricProducerTest,TestWithCondition)272 TEST(GaugeMetricProducerTest, TestWithCondition) {
273     GaugeMetric metric;
274     metric.set_id(metricId);
275     metric.set_bucket(ONE_MINUTE);
276     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
277     gaugeFieldMatcher->set_field(tagId);
278     gaugeFieldMatcher->add_child()->set_field(2);
279     metric.set_condition(StringToId("SCREEN_ON"));
280 
281     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
282 
283     shared_ptr<MockStatsPullerManager> pullerManager =
284             make_shared<StrictMock<MockStatsPullerManager>>();
285     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
286     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
287     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
288             .WillOnce(Invoke([](int tagId, int64_t timeNs,
289                                 vector<std::shared_ptr<LogEvent>>* data) {
290                 data->clear();
291                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
292                 event->write("some value");
293                 event->write(100);
294                 event->init();
295                 data->push_back(event);
296                 return true;
297             }));
298 
299     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
300                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
301     gaugeProducer.setBucketSize(60 * NS_PER_SEC);
302 
303     gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
304     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
305     EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
306                            ->second.front()
307                            .mFields->begin()
308                            ->mValue.int_value);
309     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
310 
311     vector<shared_ptr<LogEvent>> allData;
312     allData.clear();
313     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
314     event->write("some value");
315     event->write(110);
316     event->init();
317     allData.push_back(event);
318     gaugeProducer.onDataPulled(allData);
319 
320     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
321     EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
322                            ->second.front()
323                            .mFields->begin()
324                            ->mValue.int_value);
325     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
326     EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
327                            ->second.back()
328                            .mGaugeAtoms.front()
329                            .mFields->begin()
330                            ->mValue.int_value);
331 
332     gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
333     gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
334     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
335     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
336     EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
337                             ->second.back()
338                             .mGaugeAtoms.front()
339                             .mFields->begin()
340                             ->mValue.int_value);
341 }
342 
TEST(GaugeMetricProducerTest,TestWithSlicedCondition)343 TEST(GaugeMetricProducerTest, TestWithSlicedCondition) {
344     const int conditionTag = 65;
345     GaugeMetric metric;
346     metric.set_id(1111111);
347     metric.set_bucket(ONE_MINUTE);
348     metric.mutable_gauge_fields_filter()->set_include_all(true);
349     metric.set_condition(StringToId("APP_DIED"));
350     auto dim = metric.mutable_dimensions_in_what();
351     dim->set_field(tagId);
352     dim->add_child()->set_field(1);
353 
354     dim = metric.mutable_dimensions_in_condition();
355     dim->set_field(conditionTag);
356     dim->add_child()->set_field(1);
357 
358     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
359     EXPECT_CALL(*wizard, query(_, _, _, _, _, _))
360             .WillRepeatedly(
361                     Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
362                               const vector<Matcher>& dimensionFields, const bool isSubsetDim,
363                               const bool isPartialLink,
364                               std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
365                         dimensionKeySet->clear();
366                         int pos[] = {1, 0, 0};
367                         Field f(conditionTag, pos, 0);
368                         HashableDimensionKey key;
369                         key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
370                         dimensionKeySet->insert(key);
371 
372                         return ConditionState::kTrue;
373                     }));
374 
375     shared_ptr<MockStatsPullerManager> pullerManager =
376             make_shared<StrictMock<MockStatsPullerManager>>();
377     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
378     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
379     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
380             .WillOnce(Invoke([](int tagId, int64_t timeNs,
381                                 vector<std::shared_ptr<LogEvent>>* data) {
382                 data->clear();
383                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
384                 event->write(1000);
385                 event->write(100);
386                 event->init();
387                 data->push_back(event);
388                 return true;
389             }));
390 
391     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
392                                       bucketStartTimeNs, pullerManager);
393     gaugeProducer.setBucketSize(60 * NS_PER_SEC);
394 
395     gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
396 
397     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
398     const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
399     EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
400     EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
401 
402     EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size());
403     EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value);
404 
405     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
406 
407     vector<shared_ptr<LogEvent>> allData;
408     allData.clear();
409     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
410     event->write(1000);
411     event->write(110);
412     event->init();
413     allData.push_back(event);
414     gaugeProducer.onDataPulled(allData);
415 
416     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
417     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
418 }
419 
TEST(GaugeMetricProducerTest,TestAnomalyDetection)420 TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
421     sp<AlarmMonitor> alarmMonitor;
422     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
423 
424     shared_ptr<MockStatsPullerManager> pullerManager =
425             make_shared<StrictMock<MockStatsPullerManager>>();
426     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
427     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
428 
429     GaugeMetric metric;
430     metric.set_id(metricId);
431     metric.set_bucket(ONE_MINUTE);
432     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
433     gaugeFieldMatcher->set_field(tagId);
434     gaugeFieldMatcher->add_child()->set_field(2);
435     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
436                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
437     gaugeProducer.setBucketSize(60 * NS_PER_SEC);
438 
439     Alert alert;
440     alert.set_id(101);
441     alert.set_metric_id(metricId);
442     alert.set_trigger_if_sum_gt(25);
443     alert.set_num_buckets(2);
444     const int32_t refPeriodSec = 60;
445     alert.set_refractory_period_secs(refPeriodSec);
446     sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
447 
448     int tagId = 1;
449     std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
450     event1->write("some value");
451     event1->write(13);
452     event1->init();
453 
454     gaugeProducer.onDataPulled({event1});
455     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
456     EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
457                            ->second.front()
458                            .mFields->begin()
459                            ->mValue.int_value);
460     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
461 
462     std::shared_ptr<LogEvent> event2 =
463             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
464     event2->write("some value");
465     event2->write(15);
466     event2->init();
467 
468     gaugeProducer.onDataPulled({event2});
469     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
470     EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
471                            ->second.front()
472                            .mFields->begin()
473                            ->mValue.int_value);
474     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
475             std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
476 
477     std::shared_ptr<LogEvent> event3 =
478             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
479     event3->write("some value");
480     event3->write(26);
481     event3->init();
482 
483     gaugeProducer.onDataPulled({event3});
484     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
485     EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
486                            ->second.front()
487                            .mFields->begin()
488                            ->mValue.int_value);
489     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
490             std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
491 
492     // The event4 does not have the gauge field. Thus the current bucket value is 0.
493     std::shared_ptr<LogEvent> event4 =
494             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
495     event4->write("some value");
496     event4->init();
497     gaugeProducer.onDataPulled({event4});
498     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
499     EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
500 }
501 
502 }  // namespace statsd
503 }  // namespace os
504 }  // namespace android
505 #else
506 GTEST_LOG_(INFO) << "This test does nothing.\n";
507 #endif
508