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 namespace {
     29 
     30 StatsdConfig CreateStatsdConfig() {
     31     StatsdConfig config;
     32     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
     33 
     34     *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
     35     *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
     36 
     37     *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
     38     *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
     39 
     40     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
     41     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
     42 
     43     auto appCrashMatcher = CreateProcessCrashAtomMatcher();
     44     *config.add_atom_matcher() = appCrashMatcher;
     45 
     46     auto screenIsOffPredicate = CreateScreenIsOffPredicate();
     47 
     48     auto isSyncingPredicate = CreateIsSyncingPredicate();
     49     auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
     50     *syncDimension = CreateAttributionUidDimensions(
     51         android::util::SYNC_STATE_CHANGED, {Position::FIRST});
     52     syncDimension->add_child()->set_field(2 /* name field*/);
     53 
     54     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
     55     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
     56         CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
     57 
     58     *config.add_predicate() = screenIsOffPredicate;
     59     *config.add_predicate() = isSyncingPredicate;
     60     *config.add_predicate() = isInBackgroundPredicate;
     61 
     62     auto combinationPredicate = config.add_predicate();
     63     combinationPredicate->set_id(StringToId("combinationPredicate"));
     64     combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
     65     addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
     66     addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
     67     addPredicateToPredicateCombination(isInBackgroundPredicate, combinationPredicate);
     68 
     69     auto countMetric = config.add_count_metric();
     70     countMetric->set_id(StringToId("AppCrashes"));
     71     countMetric->set_what(appCrashMatcher.id());
     72     countMetric->set_condition(combinationPredicate->id());
     73     // The metric is dimensioning by uid only.
     74     *countMetric->mutable_dimensions_in_what() =
     75         CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
     76     countMetric->set_bucket(FIVE_MINUTES);
     77 
     78     // Links between crash atom and condition of app is in syncing.
     79     auto links = countMetric->add_links();
     80     links->set_condition(isSyncingPredicate.id());
     81     auto dimensionWhat = links->mutable_fields_in_what();
     82     dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     83     dimensionWhat->add_child()->set_field(1);  // uid field.
     84     *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
     85             android::util::SYNC_STATE_CHANGED, {Position::FIRST});
     86 
     87     // Links between crash atom and condition of app is in background.
     88     links = countMetric->add_links();
     89     links->set_condition(isInBackgroundPredicate.id());
     90     dimensionWhat = links->mutable_fields_in_what();
     91     dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     92     dimensionWhat->add_child()->set_field(1);  // uid field.
     93     auto dimensionCondition = links->mutable_fields_in_condition();
     94     dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
     95     dimensionCondition->add_child()->set_field(1);  // uid field.
     96     return config;
     97 }
     98 }  // namespace
     99 
    100 // If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
    101 // we should use the real API which will clear the data after dump data is called.
    102 TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
    103     auto config = CreateStatsdConfig();
    104     uint64_t bucketStartTimeNs = 10000000000;
    105     uint64_t bucketSizeNs =
    106         TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
    107 
    108     ConfigKey cfgKey;
    109     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
    110     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
    111     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
    112 
    113     int appUid = 123;
    114     auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
    115     auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
    116     auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
    117 
    118     auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
    119     auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
    120     auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
    121 
    122     auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
    123     auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
    124 
    125     auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
    126     auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
    127 
    128     auto screenTurnedOnEvent =
    129         CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
    130                                       bucketStartTimeNs + 2);
    131     auto screenTurnedOffEvent =
    132         CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
    133                                       bucketStartTimeNs + 200);
    134     auto screenTurnedOnEvent2 =
    135         CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
    136                                       bucketStartTimeNs + 2 * bucketSizeNs - 100);
    137 
    138     std::vector<AttributionNodeInternal> attributions = {
    139             CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
    140     auto syncOnEvent1 =
    141         CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
    142     auto syncOffEvent1 =
    143         CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
    144     auto syncOnEvent2 =
    145         CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
    146 
    147     auto moveToBackgroundEvent1 =
    148         CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
    149     auto moveToForegroundEvent1 =
    150         CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
    151 
    152     auto moveToBackgroundEvent2 =
    153         CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
    154     auto moveToForegroundEvent2 =
    155         CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
    156 
    157     /*
    158                     bucket #1                               bucket #2
    159 
    160 
    161        |      |   |  |                      |   |          |        |   |   |     (crashEvents)
    162     |-------------------------------------|-----------------------------------|---------
    163 
    164              |                                           |                        (MoveToBkground)
    165 
    166                                              |                               |    (MoveToForeground)
    167 
    168                 |                                                 |                (SyncIsOn)
    169                                                   |                                (SyncIsOff)
    170           |                                                               |        (ScreenIsOn)
    171                    |                                                               (ScreenIsOff)
    172     */
    173     std::vector<std::unique_ptr<LogEvent>> events;
    174     events.push_back(std::move(crashEvent1));
    175     events.push_back(std::move(crashEvent2));
    176     events.push_back(std::move(crashEvent3));
    177     events.push_back(std::move(crashEvent4));
    178     events.push_back(std::move(crashEvent5));
    179     events.push_back(std::move(crashEvent6));
    180     events.push_back(std::move(crashEvent7));
    181     events.push_back(std::move(crashEvent8));
    182     events.push_back(std::move(crashEvent9));
    183     events.push_back(std::move(crashEvent10));
    184     events.push_back(std::move(screenTurnedOnEvent));
    185     events.push_back(std::move(screenTurnedOffEvent));
    186     events.push_back(std::move(screenTurnedOnEvent2));
    187     events.push_back(std::move(syncOnEvent1));
    188     events.push_back(std::move(syncOffEvent1));
    189     events.push_back(std::move(syncOnEvent2));
    190     events.push_back(std::move(moveToBackgroundEvent1));
    191     events.push_back(std::move(moveToForegroundEvent1));
    192     events.push_back(std::move(moveToBackgroundEvent2));
    193     events.push_back(std::move(moveToForegroundEvent2));
    194 
    195     sortLogEventsByTimestamp(&events);
    196 
    197     for (const auto& event : events) {
    198         processor->OnLogEvent(event.get());
    199     }
    200     ConfigMetricsReportList reports;
    201     vector<uint8_t> buffer;
    202     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
    203                             ADB_DUMP, FAST, &buffer);
    204     EXPECT_TRUE(buffer.size() > 0);
    205     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
    206     backfillDimensionPath(&reports);
    207     backfillStringInReport(&reports);
    208     backfillStartEndTimestamp(&reports);
    209     EXPECT_EQ(reports.reports_size(), 1);
    210     EXPECT_EQ(reports.reports(0).metrics_size(), 1);
    211     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
    212     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
    213     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
    214     auto data = reports.reports(0).metrics(0).count_metrics().data(0);
    215     // Validate dimension value.
    216     EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
    217     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
    218     // Uid field.
    219     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
    220     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
    221 }
    222 
    223 TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
    224     auto config = CreateStatsdConfig();
    225     uint64_t bucketStartTimeNs = 10000000000;
    226     uint64_t bucketSizeNs =
    227             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
    228 
    229     ConfigKey cfgKey;
    230     auto processor = CreateStatsLogProcessor(
    231             bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
    232     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
    233     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
    234 
    235     int appUid = 123;
    236     auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
    237     auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
    238     auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
    239 
    240     auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
    241     auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
    242     auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
    243 
    244     auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
    245     auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
    246 
    247     auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
    248     auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
    249 
    250     auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
    251             android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
    252     auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
    253             android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
    254     auto screenTurnedOnEvent2 =
    255             CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
    256                                           bucketStartTimeNs + 2 * bucketSizeNs - 100);
    257 
    258     std::vector<AttributionNodeInternal> attributions = {
    259             CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
    260     auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
    261     auto syncOffEvent1 =
    262             CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
    263     auto syncOnEvent2 =
    264             CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
    265 
    266     auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
    267     auto moveToForegroundEvent1 =
    268             CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
    269 
    270     auto moveToBackgroundEvent2 =
    271             CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
    272     auto moveToForegroundEvent2 =
    273             CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
    274 
    275     /*
    276                     bucket #1                               bucket #2
    277 
    278 
    279        |      |   |  |                      |   |          |        |   |   |     (crashEvents)
    280     |-------------------------------------|-----------------------------------|---------
    281 
    282              |                                           |                        (MoveToBkground)
    283 
    284                                              |                               |    (MoveToForeground)
    285 
    286                 |                                                 |                (SyncIsOn)
    287                                                   |                                (SyncIsOff)
    288           |                                                               |        (ScreenIsOn)
    289                    |                                                               (ScreenIsOff)
    290     */
    291     std::vector<std::unique_ptr<LogEvent>> events;
    292     events.push_back(std::move(crashEvent1));
    293     events.push_back(std::move(crashEvent2));
    294     events.push_back(std::move(crashEvent3));
    295     events.push_back(std::move(crashEvent4));
    296     events.push_back(std::move(crashEvent5));
    297     events.push_back(std::move(crashEvent6));
    298     events.push_back(std::move(crashEvent7));
    299     events.push_back(std::move(crashEvent8));
    300     events.push_back(std::move(crashEvent9));
    301     events.push_back(std::move(crashEvent10));
    302     events.push_back(std::move(screenTurnedOnEvent));
    303     events.push_back(std::move(screenTurnedOffEvent));
    304     events.push_back(std::move(screenTurnedOnEvent2));
    305     events.push_back(std::move(syncOnEvent1));
    306     events.push_back(std::move(syncOffEvent1));
    307     events.push_back(std::move(syncOnEvent2));
    308     events.push_back(std::move(moveToBackgroundEvent1));
    309     events.push_back(std::move(moveToForegroundEvent1));
    310     events.push_back(std::move(moveToBackgroundEvent2));
    311     events.push_back(std::move(moveToForegroundEvent2));
    312 
    313     sortLogEventsByTimestamp(&events);
    314 
    315     for (const auto& event : events) {
    316         processor->OnLogEvent(event.get());
    317     }
    318     ConfigMetricsReportList reports;
    319     vector<uint8_t> buffer;
    320 
    321     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
    322                             ADB_DUMP, FAST, &buffer);
    323     EXPECT_TRUE(buffer.size() > 0);
    324     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
    325     backfillDimensionPath(&reports);
    326     backfillStringInReport(&reports);
    327     backfillStartEndTimestamp(&reports);
    328     EXPECT_EQ(reports.reports_size(), 1);
    329     EXPECT_EQ(reports.reports(0).metrics_size(), 1);
    330     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
    331     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
    332     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
    333     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
    334     auto data = reports.reports(0).metrics(0).count_metrics().data(0);
    335     // Validate dimension value.
    336     EXPECT_EQ(data.dimensions_in_what().field(),
    337               android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
    338     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
    339     // Uid field.
    340     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
    341     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
    342 }
    343 
    344 #else
    345 GTEST_LOG_(INFO) << "This test does nothing.\n";
    346 #endif
    347 
    348 }  // namespace statsd
    349 }  // namespace os
    350 }  // namespace android
    351