blob: b56b8176cceb1a8b9e2fc09967d6bc9fd56330fc [file] [log] [blame]
Yangster-mac20877162017-12-22 17:19:39 -08001// 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 "tests/statsd_test_util.h"
19
20#include <vector>
21
22namespace android {
23namespace os {
24namespace statsd {
25
26#ifdef __ANDROID__
27
28StatsdConfig CreateStatsdConfig() {
29 StatsdConfig config;
30 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
31 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
32
33 *config.add_atom_matcher() = CreateSyncStartAtomMatcher();
34 *config.add_atom_matcher() = CreateSyncEndAtomMatcher();
35
36 *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
37 *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
38
39 auto appCrashMatcher = CreateProcessCrashAtomMatcher();
40 *config.add_atom_matcher() = appCrashMatcher;
41
42 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
43
44 auto isSyncingPredicate = CreateIsSyncingPredicate();
45 *isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions() =
46 CreateDimensions(
47 android::util::SYNC_STATE_CHANGED, {1 /* uid field */});
48
49 auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
50 *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
51 CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
52
53 *config.add_predicate() = screenIsOffPredicate;
54 *config.add_predicate() = isSyncingPredicate;
55 *config.add_predicate() = isInBackgroundPredicate;
56
57 auto combinationPredicate = config.add_predicate();
Yangster-mac94e197c2018-01-02 16:03:03 -080058 combinationPredicate->set_id(StringToId("combinationPredicate"));
Yangster-mac20877162017-12-22 17:19:39 -080059 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
60 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate);
61 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
62 addPredicateToPredicateCombination(isInBackgroundPredicate, combinationPredicate);
63
64 auto countMetric = config.add_count_metric();
Yangster-mac94e197c2018-01-02 16:03:03 -080065 countMetric->set_id(StringToId("AppCrashes"));
66 countMetric->set_what(appCrashMatcher.id());
67 countMetric->set_condition(combinationPredicate->id());
Yangster-mac20877162017-12-22 17:19:39 -080068 // The metric is dimensioning by uid only.
69 *countMetric->mutable_dimensions() =
70 CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
71 countMetric->mutable_bucket()->set_bucket_size_millis(30 * 1000LL);
72
73 // Links between crash atom and condition of app is in syncing.
74 auto links = countMetric->add_links();
Yangster-mac94e197c2018-01-02 16:03:03 -080075 links->set_condition(isSyncingPredicate.id());
Yangster-mac20877162017-12-22 17:19:39 -080076 auto dimensionWhat = links->mutable_dimensions_in_what();
77 dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
78 dimensionWhat->add_child()->set_field(1); // uid field.
79 auto dimensionCondition = links->mutable_dimensions_in_condition();
80 dimensionCondition->set_field(android::util::SYNC_STATE_CHANGED);
81 dimensionCondition->add_child()->set_field(1); // uid field.
82
83 // Links between crash atom and condition of app is in background.
84 links = countMetric->add_links();
Yangster-mac94e197c2018-01-02 16:03:03 -080085 links->set_condition(isInBackgroundPredicate.id());
Yangster-mac20877162017-12-22 17:19:39 -080086 dimensionWhat = links->mutable_dimensions_in_what();
87 dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
88 dimensionWhat->add_child()->set_field(1); // uid field.
89 dimensionCondition = links->mutable_dimensions_in_condition();
90 dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
91 dimensionCondition->add_child()->set_field(1); // uid field.
92 return config;
93}
94
95TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks) {
96 auto config = CreateStatsdConfig();
97 uint64_t bucketStartTimeNs = 10000000000;
98 uint64_t bucketSizeNs = config.count_metric(0).bucket().bucket_size_millis() * 1000 * 1000;
99
100 ConfigKey cfgKey;
101 auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
102 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
103 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
104
105 int appUid = 123;
106 auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
107 auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
108 auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
109
110 auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
111 auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
112 auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
113
114 auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
115 auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
116
117 auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
118 auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
119
120 auto screenTurnedOnEvent =
121 CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, bucketStartTimeNs + 2);
122 auto screenTurnedOffEvent =
123 CreateScreenStateChangedEvent(ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 200);
124 auto screenTurnedOnEvent2 =
125 CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON,
126 bucketStartTimeNs + 2 * bucketSizeNs - 100);
127
128 auto syncOnEvent1 =
129 CreateSyncStartEvent(appUid, "ReadEmail", bucketStartTimeNs + 50);
130 auto syncOffEvent1 =
131 CreateSyncEndEvent(appUid, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
132 auto syncOnEvent2 =
133 CreateSyncStartEvent(appUid, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
134
135 auto moveToBackgroundEvent1 =
136 CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
137 auto moveToForegroundEvent1 =
138 CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
139
140 auto moveToBackgroundEvent2 =
141 CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
142 auto moveToForegroundEvent2 =
143 CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
144
145 /*
146 bucket #1 bucket #2
147
148
149 | | | | | | | | | | (crashEvents)
150 |-------------------------------------|-----------------------------------|---------
151
152 | | (MoveToBkground)
153
154 | | (MoveToForeground)
155
156 | | (SyncIsOn)
157 | (SyncIsOff)
158 | | (ScreenIsOn)
159 | (ScreenIsOff)
160 */
161 std::vector<std::unique_ptr<LogEvent>> events;
162 events.push_back(std::move(crashEvent1));
163 events.push_back(std::move(crashEvent2));
164 events.push_back(std::move(crashEvent3));
165 events.push_back(std::move(crashEvent4));
166 events.push_back(std::move(crashEvent5));
167 events.push_back(std::move(crashEvent6));
168 events.push_back(std::move(crashEvent7));
169 events.push_back(std::move(crashEvent8));
170 events.push_back(std::move(crashEvent9));
171 events.push_back(std::move(crashEvent10));
172 events.push_back(std::move(screenTurnedOnEvent));
173 events.push_back(std::move(screenTurnedOffEvent));
174 events.push_back(std::move(screenTurnedOnEvent2));
175 events.push_back(std::move(syncOnEvent1));
176 events.push_back(std::move(syncOffEvent1));
177 events.push_back(std::move(syncOnEvent2));
178 events.push_back(std::move(moveToBackgroundEvent1));
179 events.push_back(std::move(moveToForegroundEvent1));
180 events.push_back(std::move(moveToBackgroundEvent2));
181 events.push_back(std::move(moveToForegroundEvent2));
182
183 sortLogEventsByTimestamp(&events);
184
185 for (const auto& event : events) {
186 processor->OnLogEvent(*event);
187 }
188 ConfigMetricsReportList reports;
189 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &reports);
190 EXPECT_EQ(reports.reports_size(), 1);
191 EXPECT_EQ(reports.reports(0).metrics_size(), 1);
192 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
193 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
194 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
195 auto data = reports.reports(0).metrics(0).count_metrics().data(0);
196 // Validate dimension value.
197 EXPECT_EQ(data.dimension().field(),
198 android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
199 EXPECT_EQ(data.dimension().value_tuple().dimensions_value_size(), 1);
200 // Uid field.
201 EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).field(), 1);
202 EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).value_int(), appUid);
203
204 reports.Clear();
205 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
206 EXPECT_EQ(reports.reports_size(), 1);
207 EXPECT_EQ(reports.reports(0).metrics_size(), 1);
208 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
209 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
210 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
211 EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
212 data = reports.reports(0).metrics(0).count_metrics().data(0);
213 // Validate dimension value.
214 EXPECT_EQ(data.dimension().field(),
215 android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
216 EXPECT_EQ(data.dimension().value_tuple().dimensions_value_size(), 1);
217 // Uid field.
218 EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).field(), 1);
219 EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).value_int(), appUid);
220}
221
222#else
223GTEST_LOG_(INFO) << "This test does nothing.\n";
224#endif
225
226} // namespace statsd
227} // namespace os
228} // namespace android