Home | History | Annotate | Download | only in e2e
      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 <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 const int64_t metricId = 123456;
     32 
     33 StatsdConfig CreateStatsdConfig(bool useCondition = true) {
     34     StatsdConfig config;
     35     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
     36     auto pulledAtomMatcher =
     37             CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
     38     *config.add_atom_matcher() = pulledAtomMatcher;
     39     *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
     40     *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
     41 
     42     auto screenIsOffPredicate = CreateScreenIsOffPredicate();
     43     *config.add_predicate() = screenIsOffPredicate;
     44 
     45     auto valueMetric = config.add_value_metric();
     46     valueMetric->set_id(metricId);
     47     valueMetric->set_what(pulledAtomMatcher.id());
     48     if (useCondition) {
     49         valueMetric->set_condition(screenIsOffPredicate.id());
     50     }
     51     *valueMetric->mutable_value_field() =
     52             CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
     53     *valueMetric->mutable_dimensions_in_what() =
     54             CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
     55     valueMetric->set_bucket(FIVE_MINUTES);
     56     valueMetric->set_use_absolute_value_on_reset(true);
     57     valueMetric->set_skip_zero_diff_output(false);
     58     valueMetric->set_max_pull_delay_sec(INT_MAX);
     59     return config;
     60 }
     61 
     62 }  // namespace
     63 
     64 TEST(ValueMetricE2eTest, TestPulledEvents) {
     65     auto config = CreateStatsdConfig();
     66     int64_t baseTimeNs = getElapsedRealtimeNs();
     67     int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
     68     int64_t bucketSizeNs =
     69         TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
     70 
     71     ConfigKey cfgKey;
     72     auto processor = CreateStatsLogProcessor(
     73         baseTimeNs, configAddedTimeNs, config, cfgKey);
     74     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
     75     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     76     processor->mPullerManager->ForceClearPullerCache();
     77 
     78     int startBucketNum = processor->mMetricsManagers.begin()->second->
     79             mAllMetricProducers[0]->getCurrentBucketNum();
     80     EXPECT_GT(startBucketNum, (int64_t)0);
     81 
     82     // When creating the config, the value metric producer should register the alarm at the
     83     // end of the current bucket.
     84     EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     85     EXPECT_EQ(bucketSizeNs,
     86               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     87     int64_t& expectedPullTimeNs =
     88             processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
     89     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
     90 
     91     auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
     92                                                         configAddedTimeNs + 55);
     93     processor->OnLogEvent(screenOffEvent.get());
     94 
     95     auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
     96                                                        configAddedTimeNs + 65);
     97     processor->OnLogEvent(screenOnEvent.get());
     98 
     99     screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
    100                                                    configAddedTimeNs + 75);
    101     processor->OnLogEvent(screenOffEvent.get());
    102 
    103     // Pulling alarm arrives on time and reset the sequential pulling alarm.
    104     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    105     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
    106 
    107     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    108 
    109     screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
    110                                                        configAddedTimeNs + 2 * bucketSizeNs + 15);
    111     processor->OnLogEvent(screenOnEvent.get());
    112 
    113     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    114 
    115     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    116 
    117     screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
    118                                                    configAddedTimeNs + 4 * bucketSizeNs + 11);
    119     processor->OnLogEvent(screenOffEvent.get());
    120 
    121     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    122 
    123     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    124 
    125     ConfigMetricsReportList reports;
    126     vector<uint8_t> buffer;
    127     processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
    128                             ADB_DUMP, FAST, &buffer);
    129     EXPECT_TRUE(buffer.size() > 0);
    130     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
    131     backfillDimensionPath(&reports);
    132     backfillStringInReport(&reports);
    133     backfillStartEndTimestamp(&reports);
    134     EXPECT_EQ(1, reports.reports_size());
    135     EXPECT_EQ(1, reports.reports(0).metrics_size());
    136     StatsLogReport::ValueMetricDataWrapper valueMetrics;
    137     sortMetricDataByDimensionsValue(
    138             reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
    139     EXPECT_GT((int)valueMetrics.data_size(), 1);
    140 
    141     auto data = valueMetrics.data(0);
    142     EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
    143     EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
    144     EXPECT_EQ(1 /* subsystem name field */,
    145               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
    146     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
    147     // We have 4 buckets, the first one was incomplete since the condition was unknown.
    148     EXPECT_EQ(4, data.bucket_info_size());
    149 
    150     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
    151     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
    152     EXPECT_EQ(1, data.bucket_info(0).values_size());
    153 
    154     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
    155     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
    156     EXPECT_EQ(1, data.bucket_info(1).values_size());
    157 
    158     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
    159     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
    160     EXPECT_EQ(1, data.bucket_info(2).values_size());
    161 
    162     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
    163     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
    164     EXPECT_EQ(1, data.bucket_info(3).values_size());
    165 }
    166 
    167 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
    168     auto config = CreateStatsdConfig();
    169     int64_t baseTimeNs = getElapsedRealtimeNs();
    170     // 10 mins == 2 bucket durations.
    171     int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
    172     int64_t bucketSizeNs =
    173         TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
    174 
    175     ConfigKey cfgKey;
    176     auto processor = CreateStatsLogProcessor(
    177         baseTimeNs, configAddedTimeNs, config, cfgKey);
    178     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
    179     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
    180     processor->mPullerManager->ForceClearPullerCache();
    181 
    182     int startBucketNum = processor->mMetricsManagers.begin()->second->
    183             mAllMetricProducers[0]->getCurrentBucketNum();
    184     EXPECT_GT(startBucketNum, (int64_t)0);
    185 
    186     // When creating the config, the value metric producer should register the alarm at the
    187     // end of the current bucket.
    188     EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
    189     EXPECT_EQ(bucketSizeNs,
    190               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
    191     int64_t& expectedPullTimeNs =
    192             processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
    193     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
    194 
    195     // Screen off/on/off events.
    196     auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
    197                                                         configAddedTimeNs + 55);
    198     processor->OnLogEvent(screenOffEvent.get());
    199 
    200     auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
    201                                                        configAddedTimeNs + 65);
    202     processor->OnLogEvent(screenOnEvent.get());
    203 
    204     screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
    205                                                    configAddedTimeNs + 75);
    206     processor->OnLogEvent(screenOffEvent.get());
    207 
    208     // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
    209     // future, data will be skipped.
    210     processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
    211     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
    212 
    213     // This screen state change will start a new bucket.
    214     screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
    215                                                        configAddedTimeNs + 4 * bucketSizeNs + 65);
    216     processor->OnLogEvent(screenOnEvent.get());
    217 
    218     // The alarm is delayed but we already created a bucket thanks to the screen state condition.
    219     // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
    220     processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
    221     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
    222 
    223     screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
    224                                                    configAddedTimeNs + 6 * bucketSizeNs + 31);
    225     processor->OnLogEvent(screenOffEvent.get());
    226 
    227     processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
    228     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
    229 
    230     processor->informPullAlarmFired(expectedPullTimeNs + 1);
    231     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
    232 
    233     ConfigMetricsReportList reports;
    234     vector<uint8_t> buffer;
    235     processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
    236                             ADB_DUMP, FAST, &buffer);
    237     EXPECT_TRUE(buffer.size() > 0);
    238     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
    239     backfillDimensionPath(&reports);
    240     backfillStringInReport(&reports);
    241     backfillStartEndTimestamp(&reports);
    242     EXPECT_EQ(1, reports.reports_size());
    243     EXPECT_EQ(1, reports.reports(0).metrics_size());
    244     StatsLogReport::ValueMetricDataWrapper valueMetrics;
    245     sortMetricDataByDimensionsValue(
    246             reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
    247     EXPECT_GT((int)valueMetrics.data_size(), 1);
    248 
    249     auto data = valueMetrics.data(0);
    250     EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
    251     EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
    252     EXPECT_EQ(1 /* subsystem name field */,
    253               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
    254     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
    255     EXPECT_EQ(3, data.bucket_info_size());
    256 
    257     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
    258     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
    259     EXPECT_EQ(1, data.bucket_info(0).values_size());
    260 
    261     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
    262     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
    263     EXPECT_EQ(1, data.bucket_info(1).values_size());
    264 
    265     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
    266     EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
    267     EXPECT_EQ(1, data.bucket_info(2).values_size());
    268 }
    269 
    270 TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
    271     auto config = CreateStatsdConfig(false);
    272     int64_t baseTimeNs = getElapsedRealtimeNs();
    273     int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
    274     int64_t bucketSizeNs =
    275         TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
    276 
    277     auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
    278     *config.add_atom_matcher() = batterySaverStartMatcher;
    279     const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
    280     auto metric_activation = config.add_metric_activation();
    281     metric_activation->set_metric_id(metricId);
    282     metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
    283     auto event_activation = metric_activation->add_event_activation();
    284     event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
    285     event_activation->set_ttl_seconds(ttlNs / 1000000000);
    286 
    287     ConfigKey cfgKey;
    288     auto processor = CreateStatsLogProcessor(
    289         baseTimeNs, configAddedTimeNs, config, cfgKey);
    290     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
    291     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
    292     processor->mPullerManager->ForceClearPullerCache();
    293 
    294     int startBucketNum = processor->mMetricsManagers.begin()->second->
    295             mAllMetricProducers[0]->getCurrentBucketNum();
    296     EXPECT_GT(startBucketNum, (int64_t)0);
    297     EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
    298 
    299     // When creating the config, the value metric producer should register the alarm at the
    300     // end of the current bucket.
    301     EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
    302     EXPECT_EQ(bucketSizeNs,
    303               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
    304     int64_t& expectedPullTimeNs =
    305             processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
    306     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
    307 
    308     // Pulling alarm arrives on time and reset the sequential pulling alarm.
    309     processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
    310     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
    311     EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
    312 
    313     // Activate the metric. A pull occurs here
    314     const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
    315     auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
    316     processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
    317     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
    318 
    319     processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
    320     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
    321 
    322     processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
    323     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
    324 
    325     // Create random event to deactivate metric.
    326     auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
    327     processor->OnLogEvent(deactivationEvent.get());
    328     EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
    329 
    330     processor->informPullAlarmFired(expectedPullTimeNs + 3);
    331     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
    332 
    333     processor->informPullAlarmFired(expectedPullTimeNs + 4);
    334     EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
    335 
    336     ConfigMetricsReportList reports;
    337     vector<uint8_t> buffer;
    338     processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
    339                             ADB_DUMP, FAST, &buffer);
    340     EXPECT_TRUE(buffer.size() > 0);
    341     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
    342     backfillDimensionPath(&reports);
    343     backfillStringInReport(&reports);
    344     backfillStartEndTimestamp(&reports);
    345     EXPECT_EQ(1, reports.reports_size());
    346     EXPECT_EQ(1, reports.reports(0).metrics_size());
    347     StatsLogReport::ValueMetricDataWrapper valueMetrics;
    348     sortMetricDataByDimensionsValue(
    349             reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
    350     EXPECT_GT((int)valueMetrics.data_size(), 0);
    351 
    352     auto data = valueMetrics.data(0);
    353     EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
    354     EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
    355     EXPECT_EQ(1 /* subsystem name field */,
    356               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
    357     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
    358     // We have 2 full buckets, the two surrounding the activation are dropped.
    359     EXPECT_EQ(2, data.bucket_info_size());
    360 
    361     auto bucketInfo = data.bucket_info(0);
    362     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
    363     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
    364     EXPECT_EQ(1, bucketInfo.values_size());
    365 
    366     bucketInfo = data.bucket_info(1);
    367     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
    368     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
    369     EXPECT_EQ(1, bucketInfo.values_size());
    370 }
    371 
    372 #else
    373 GTEST_LOG_(INFO) << "This test does nothing.\n";
    374 #endif
    375 
    376 }  // namespace statsd
    377 }  // namespace os
    378 }  // namespace android
    379