Home | History | Annotate | Download | only in e2e
      1 // Copyright (C) 2018 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 <gtest/gtest.h>
     16 
     17 #include "src/StatsLogProcessor.h"
     18 #include "src/stats_log_util.h"
     19 #include "tests/statsd_test_util.h"
     20 
     21 #include <vector>
     22 
     23 namespace android {
     24 namespace os {
     25 namespace statsd {
     26 
     27 #ifdef __ANDROID__
     28 
     29 namespace {
     30 
     31 StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) {
     32     StatsdConfig config;
     33     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
     34     auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
     35 
     36     *config.add_atom_matcher() = wakelockAcquireMatcher;
     37 
     38     auto countMetric = config.add_count_metric();
     39     countMetric->set_id(123456);
     40     countMetric->set_what(wakelockAcquireMatcher.id());
     41     *countMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
     42             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
     43     countMetric->set_bucket(FIVE_MINUTES);
     44 
     45     auto alert = config.add_alert();
     46     alert->set_id(StringToId("alert"));
     47     alert->set_metric_id(123456);
     48     alert->set_num_buckets(num_buckets);
     49     alert->set_refractory_period_secs(10);
     50     alert->set_trigger_if_sum_gt(threshold);
     51     return config;
     52 }
     53 
     54 }  // namespace
     55 
     56 TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
     57     const int num_buckets = 1;
     58     const int threshold = 3;
     59     auto config = CreateStatsdConfig(num_buckets, threshold);
     60     const uint64_t alert_id = config.alert(0).id();
     61     const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
     62 
     63     int64_t bucketStartTimeNs = 10000000000;
     64     int64_t bucketSizeNs =
     65         TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
     66 
     67     ConfigKey cfgKey;
     68     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
     69     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
     70     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     71     EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
     72 
     73     sp<AnomalyTracker> anomalyTracker =
     74         processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
     75 
     76     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
     77     std::vector<AttributionNodeInternal> attributions2 = {
     78         CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
     79     std::vector<AttributionNodeInternal> attributions3 = {
     80         CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
     81     std::vector<AttributionNodeInternal> attributions4 = {
     82         CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
     83     std::vector<AttributionNodeInternal> attributions5 = {
     84         CreateAttribution(222, "GMSCoreModule1") };
     85 
     86     FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
     87                            Value((int32_t)111));
     88     HashableDimensionKey whatKey1({fieldValue1});
     89     MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
     90 
     91     FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
     92                            Value((int32_t)222));
     93     HashableDimensionKey whatKey2({fieldValue2});
     94     MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
     95 
     96     auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
     97     processor->OnLogEvent(event.get());
     98     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
     99 
    100     event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
    101     processor->OnLogEvent(event.get());
    102     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    103 
    104     event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
    105     processor->OnLogEvent(event.get());
    106     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    107 
    108     event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
    109     processor->OnLogEvent(event.get());
    110     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    111 
    112     event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
    113     processor->OnLogEvent(event.get());
    114     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    115 
    116     event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
    117     processor->OnLogEvent(event.get());
    118     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    119 
    120     // Fired alarm and refractory period end timestamp updated.
    121     event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
    122     processor->OnLogEvent(event.get());
    123     EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
    124               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    125 
    126     event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
    127     processor->OnLogEvent(event.get());
    128     EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
    129               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    130 
    131     event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
    132     processor->OnLogEvent(event.get());
    133     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
    134               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    135 
    136     event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
    137     processor->OnLogEvent(event.get());
    138     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
    139               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    140 
    141     event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
    142     processor->OnLogEvent(event.get());
    143     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    144 
    145     event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
    146     processor->OnLogEvent(event.get());
    147     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    148 
    149     event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
    150     processor->OnLogEvent(event.get());
    151     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    152 
    153     event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
    154     processor->OnLogEvent(event.get());
    155     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
    156               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
    157 }
    158 
    159 TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
    160     const int num_buckets = 3;
    161     const int threshold = 3;
    162     auto config = CreateStatsdConfig(num_buckets, threshold);
    163     const uint64_t alert_id = config.alert(0).id();
    164     const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
    165 
    166     int64_t bucketStartTimeNs = 10000000000;
    167     int64_t bucketSizeNs =
    168         TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
    169 
    170     ConfigKey cfgKey;
    171     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
    172     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
    173     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
    174     EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
    175 
    176     sp<AnomalyTracker> anomalyTracker =
    177         processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
    178 
    179     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
    180     std::vector<AttributionNodeInternal> attributions2 = {
    181         CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
    182     std::vector<AttributionNodeInternal> attributions3 = {
    183         CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
    184     std::vector<AttributionNodeInternal> attributions4 = {
    185         CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
    186     std::vector<AttributionNodeInternal> attributions5 = {
    187         CreateAttribution(222, "GMSCoreModule1") };
    188 
    189     FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
    190                            Value((int32_t)111));
    191     HashableDimensionKey whatKey1({fieldValue1});
    192     MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
    193 
    194     FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
    195                            Value((int32_t)222));
    196     HashableDimensionKey whatKey2({fieldValue2});
    197     MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
    198 
    199     auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
    200     processor->OnLogEvent(event.get());
    201     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    202 
    203     event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
    204     processor->OnLogEvent(event.get());
    205     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    206 
    207     // Fired alarm and refractory period end timestamp updated.
    208     event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
    209     processor->OnLogEvent(event.get());
    210     EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    211 
    212     event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
    213     processor->OnLogEvent(event.get());
    214     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
    215               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    216 
    217     event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
    218     processor->OnLogEvent(event.get());
    219     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
    220               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    221 
    222     event = CreateAcquireWakelockEvent(
    223         attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
    224     processor->OnLogEvent(event.get());
    225     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
    226               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    227 
    228     event = CreateAcquireWakelockEvent(
    229         attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
    230     processor->OnLogEvent(event.get());
    231     EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
    232               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
    233 }
    234 
    235 #else
    236 GTEST_LOG_(INFO) << "This test does nothing.\n";
    237 #endif
    238 
    239 }  // namespace statsd
    240 }  // namespace os
    241 }  // namespace android
    242