From 684d195227bf9eaeb21698cbdcf865afb570c454 Mon Sep 17 00:00:00 2001 From: Yangster-mac Date: Sat, 24 Mar 2018 16:47:16 -0700 Subject: [PATCH] E2e test for periodic alarm. Test: new test BUG: b/76281156 Change-Id: I60cb28baaeec6996e946a7cb3358ec8e0aca80e5 --- cmds/statsd/Android.mk | 1 + cmds/statsd/src/StatsLogProcessor.cpp | 4 +- cmds/statsd/src/StatsLogProcessor.h | 9 ++- cmds/statsd/src/StatsService.cpp | 2 +- cmds/statsd/src/anomaly/AlarmTracker.cpp | 15 ++-- cmds/statsd/src/anomaly/AlarmTracker.h | 6 ++ cmds/statsd/src/metrics/MetricsManager.cpp | 4 +- cmds/statsd/src/metrics/MetricsManager.h | 5 +- cmds/statsd/tests/e2e/Alarm_e2e_test.cpp | 92 ++++++++++++++++++++++ cmds/statsd/tests/statsd_test_util.cpp | 4 +- 10 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 cmds/statsd/tests/e2e/Alarm_e2e_test.cpp diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 1aef0c4c43c51..7723615245b79 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -202,6 +202,7 @@ LOCAL_SRC_FILES := \ tests/statsd_test_util.cpp \ tests/e2e/WakelockDuration_e2e_test.cpp \ tests/e2e/MetricConditionLink_e2e_test.cpp \ + tests/e2e/Alarm_e2e_test.cpp \ tests/e2e/Attribution_e2e_test.cpp \ tests/e2e/GaugeMetric_e2e_push_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \ diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index a35570bd7bba7..dac731d6b5212 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -87,7 +87,7 @@ StatsLogProcessor::~StatsLogProcessor() { } void StatsLogProcessor::onAnomalyAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash> alarmSet) { std::lock_guard lock(mMetricsMutex); for (const auto& itr : mMetricsManagers) { @@ -95,7 +95,7 @@ void StatsLogProcessor::onAnomalyAlarmFired( } } void StatsLogProcessor::onPeriodicAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash> alarmSet) { std::lock_guard lock(mMetricsMutex); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index a07a35587b11f..387a9295055f2 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -51,12 +51,12 @@ public: /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */ void onAnomalyAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash> alarmSet); /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */ void onPeriodicAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash> alarmSet); /* Flushes data to disk. Data on memory will be gone after written to disk. */ @@ -74,6 +74,10 @@ private: return mAnomalyAlarmMonitor; } + inline sp getPeriodicAlarmMonitor() const { + return mPeriodicAlarmMonitor; + } + mutable mutex mMetricsMutex; std::unordered_map> mMetricsManagers; @@ -147,6 +151,7 @@ private: FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); + FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms); }; } // namespace statsd diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index b03b4b4a942c5..192152876da79 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -698,7 +698,7 @@ Status StatsService::informAlarmForSubscriberTriggeringFired() { "Only system uid can call informAlarmForSubscriberTriggeringFired"); } - uint64_t currentTimeSec = time(nullptr); + uint64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set, SpHash> alarmSet = mPeriodicAlarmMonitor->popSoonerThan(static_cast(currentTimeSec)); if (alarmSet.size() > 0) { diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp index eb283838afd76..249cb596d3c6c 100644 --- a/cmds/statsd/src/anomaly/AlarmTracker.cpp +++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp @@ -39,12 +39,14 @@ AlarmTracker::AlarmTracker(uint64_t startMillis, VLOG("AlarmTracker() called"); mAlarmSec = (startMillis + mAlarmConfig.offset_millis()) / MS_PER_SEC; mInternalAlarm = new InternalAlarm{static_cast(mAlarmSec)}; - mAlarmMonitor->add(mInternalAlarm); + if (mAlarmMonitor != nullptr) { + mAlarmMonitor->add(mInternalAlarm); + } } AlarmTracker::~AlarmTracker() { VLOG("~AlarmTracker() called"); - if (mInternalAlarm != nullptr) { + if (mInternalAlarm != nullptr && mAlarmMonitor != nullptr) { mAlarmMonitor->remove(mInternalAlarm); } } @@ -61,7 +63,8 @@ uint64_t AlarmTracker::findNextAlarmSec(uint64_t currentTimeSec) { void AlarmTracker::informAlarmsFired( const uint64_t& timestampNs, unordered_set, SpHash>& firedAlarms) { - if (firedAlarms.empty() || firedAlarms.find(mInternalAlarm) == firedAlarms.end()) { + if (firedAlarms.empty() || mInternalAlarm == nullptr || + firedAlarms.find(mInternalAlarm) == firedAlarms.end()) { return; } if (!mSubscriptions.empty()) { @@ -69,9 +72,11 @@ void AlarmTracker::informAlarmsFired( mSubscriptions); } firedAlarms.erase(mInternalAlarm); - mAlarmSec = findNextAlarmSec(timestampNs / NS_PER_SEC); + mAlarmSec = findNextAlarmSec((timestampNs-1) / NS_PER_SEC + 1); // round up mInternalAlarm = new InternalAlarm{static_cast(mAlarmSec)}; - mAlarmMonitor->add(mInternalAlarm); + if (mAlarmMonitor != nullptr) { + mAlarmMonitor->add(mInternalAlarm); + } } } // namespace statsd diff --git a/cmds/statsd/src/anomaly/AlarmTracker.h b/cmds/statsd/src/anomaly/AlarmTracker.h index d59dacaa1b698..13180a53ccbf1 100644 --- a/cmds/statsd/src/anomaly/AlarmTracker.h +++ b/cmds/statsd/src/anomaly/AlarmTracker.h @@ -48,6 +48,11 @@ public: unordered_set, SpHash>& firedAlarms); protected: + // For test only. Returns the alarm timestamp in seconds. Otherwise returns 0. + inline uint32_t getAlarmTimestampSec() const { + return mInternalAlarm == nullptr ? 0 : mInternalAlarm->timestampSec; + } + uint64_t findNextAlarmSec(uint64_t currentTimeMillis); // statsd_config.proto Alarm message that defines this tracker. @@ -69,6 +74,7 @@ protected: sp mInternalAlarm; FRIEND_TEST(AlarmTrackerTest, TestTriggerTimestamp); + FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms); }; } // namespace statsd diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index c773d4f1387e4..80a860c82c6e7 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -350,7 +350,7 @@ void MetricsManager::onLogEvent(const LogEvent& event) { } void MetricsManager::onAnomalyAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash>& alarmSet) { for (const auto& itr : mAllAnomalyTrackers) { itr->informAlarmsFired(timestampNs, alarmSet); @@ -358,7 +358,7 @@ void MetricsManager::onAnomalyAlarmFired( } void MetricsManager::onPeriodicAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash>& alarmSet) { for (const auto& itr : mAllPeriodicAlarmTrackers) { itr->informAlarmsFired(timestampNs, alarmSet); diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 05ce84d7ea8f9..da0cd4a29d3b8 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -48,11 +48,11 @@ public: void onLogEvent(const LogEvent& event); void onAnomalyAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash>& alarmSet); void onPeriodicAlarmFired( - const uint64_t timestampNs, + const uint64_t& timestampNs, unordered_set, SpHash>& alarmSet); void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid, @@ -184,6 +184,7 @@ private: FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); + FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms); }; } // namespace statsd diff --git a/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp b/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp new file mode 100644 index 0000000000000..73c4e7b859ded --- /dev/null +++ b/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "src/StatsLogProcessor.h" +#include "src/stats_log_util.h" +#include "tests/statsd_test_util.h" + +#include + +namespace android { +namespace os { +namespace statsd { + +#ifdef __ANDROID__ + +namespace { + +StatsdConfig CreateStatsdConfig() { + StatsdConfig config; + config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + + auto alarm = config.add_alarm(); + alarm->set_id(123456); + alarm->set_offset_millis(TimeUnitToBucketSizeInMillis(TEN_MINUTES)); + alarm->set_period_millis(TimeUnitToBucketSizeInMillis(ONE_HOUR)); + + alarm = config.add_alarm(); + alarm->set_id(654321); + alarm->set_offset_millis(TimeUnitToBucketSizeInMillis(FIVE_MINUTES)); + alarm->set_period_millis(TimeUnitToBucketSizeInMillis(THIRTY_MINUTES)); + return config; +} + +} // namespace + +TEST(AlarmE2eTest, TestMultipleAlarms) { + auto config = CreateStatsdConfig(); + int64_t bucketStartTimeNs = 10000000000; + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + EXPECT_EQ(2u, processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers.size()); + + auto alarmTracker1 = processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers[0]; + auto alarmTracker2 = processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers[1]; + + int64_t alarmTimestampSec0 = bucketStartTimeNs / NS_PER_SEC + 10 * 60; + int64_t alarmTimestampSec1 = bucketStartTimeNs / NS_PER_SEC + 5 * 60; + EXPECT_EQ(alarmTimestampSec0, alarmTracker1->getAlarmTimestampSec()); + EXPECT_EQ(alarmTimestampSec1, alarmTracker2->getAlarmTimestampSec()); + + // Alarm fired. + const int64_t alarmFiredTimestampSec0 = alarmTimestampSec1 + 5; + auto alarmSet = processor->getPeriodicAlarmMonitor()->popSoonerThan( + static_cast(alarmFiredTimestampSec0)); + EXPECT_EQ(1u, alarmSet.size()); + processor->onPeriodicAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet); + EXPECT_EQ(alarmTimestampSec0, alarmTracker1->getAlarmTimestampSec()); + EXPECT_EQ(alarmTimestampSec1 + 30 * 60, alarmTracker2->getAlarmTimestampSec()); + + // Alarms fired very late. + const int64_t alarmFiredTimestampSec1 = alarmTimestampSec0 + 2 * 60 * 60 + 125; + alarmSet = processor->getPeriodicAlarmMonitor()->popSoonerThan( + static_cast(alarmFiredTimestampSec1)); + EXPECT_EQ(2u, alarmSet.size()); + processor->onPeriodicAlarmFired(alarmFiredTimestampSec1 * NS_PER_SEC, alarmSet); + EXPECT_EQ(alarmTimestampSec0 + 60 * 60 * 3, alarmTracker1->getAlarmTimestampSec()); + EXPECT_EQ(alarmTimestampSec1 + 30 * 60 * 5, alarmTracker2->getAlarmTimestampSec()); +} + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index ce44a35cbf212..8a93770c64ce6 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -450,7 +450,9 @@ sp CreateStatsLogProcessor(const long timeBaseSec, const Stat sp anomalyAlarmMonitor = new AlarmMonitor(1, [](const sp&, int64_t){}, [](const sp&){}); - sp periodicAlarmMonitor; + sp periodicAlarmMonitor = + new AlarmMonitor(1, [](const sp&, int64_t){}, + [](const sp&){}); sp processor = new StatsLogProcessor( uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, [](const ConfigKey&){}); processor->OnConfigUpdated(key, config);