blob: 911762339b70da3f9b3c356f6ba8943226e48b7a [file] [log] [blame]
David Chenbd125272018-04-04 19:02:50 -07001// 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
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080015#include <android/binder_ibinder.h>
16#include <android/binder_interface_utils.h>
David Chenbd125272018-04-04 19:02:50 -070017#include <gtest/gtest.h>
18
Tej Singh730ed292020-02-03 17:24:27 -080019#include <vector>
20
David Chenbd125272018-04-04 19:02:50 -070021#include "src/StatsLogProcessor.h"
22#include "src/StatsService.h"
23#include "src/stats_log_util.h"
24#include "tests/statsd_test_util.h"
25
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080026using::ndk::SharedRefBase;
27using std::shared_ptr;
28
David Chenbd125272018-04-04 19:02:50 -070029namespace android {
30namespace os {
31namespace statsd {
32
33#ifdef __ANDROID__
Tej Singh730ed292020-02-03 17:24:27 -080034namespace {
David Chenbd125272018-04-04 19:02:50 -070035const string kApp1 = "app1.sharing.1";
36const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs.
Jeffrey Huang94eafe72020-01-07 15:18:43 -080037const int kCallingUid = 0; // Randomly chosen
David Chenbd125272018-04-04 19:02:50 -070038
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080039void SendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
David Chenbd125272018-04-04 19:02:50 -070040 string str;
41 config.SerializeToString(&str);
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080042 std::vector<int8_t> configAsVec(str.begin(), str.end());
43 service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
David Chenbd125272018-04-04 19:02:50 -070044}
45
David Chen81245fd2018-04-12 14:33:37 -070046ConfigMetricsReport GetReports(sp<StatsLogProcessor> processor, int64_t timestamp,
47 bool include_current = false) {
David Chenbd125272018-04-04 19:02:50 -070048 vector<uint8_t> output;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080049 ConfigKey configKey(AIBinder_getCallingUid(), kConfigKey);
David Chen81245fd2018-04-12 14:33:37 -070050 processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
Olivier Gaillarde3c4b932019-03-15 17:58:04 +000051 true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output);
David Chenbd125272018-04-04 19:02:50 -070052 ConfigMetricsReportList reports;
53 reports.ParseFromArray(output.data(), output.size());
54 EXPECT_EQ(1, reports.reports_size());
Jeffrey Huang94eafe72020-01-07 15:18:43 -080055 return reports.reports(kCallingUid);
David Chenbd125272018-04-04 19:02:50 -070056}
57
58StatsdConfig MakeConfig() {
59 StatsdConfig config;
60 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
61
62 auto appCrashMatcher = CreateProcessCrashAtomMatcher();
63 *config.add_atom_matcher() = appCrashMatcher;
64 auto countMetric = config.add_count_metric();
65 countMetric->set_id(StringToId("AppCrashes"));
66 countMetric->set_what(appCrashMatcher.id());
67 countMetric->set_bucket(FIVE_MINUTES);
68 return config;
69}
70
David Chen81245fd2018-04-12 14:33:37 -070071StatsdConfig MakeValueMetricConfig(int64_t minTime) {
72 StatsdConfig config;
73 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
Tej Singh3be093b2020-03-04 20:08:38 -080074 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
David Chen81245fd2018-04-12 14:33:37 -070075
Tej Singhd7b51182019-01-29 17:02:12 -080076 auto pulledAtomMatcher =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070077 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
Tej Singhd7b51182019-01-29 17:02:12 -080078 *config.add_atom_matcher() = pulledAtomMatcher;
David Chen81245fd2018-04-12 14:33:37 -070079 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
80 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
81
82 auto valueMetric = config.add_value_metric();
83 valueMetric->set_id(123456);
Tej Singhd7b51182019-01-29 17:02:12 -080084 valueMetric->set_what(pulledAtomMatcher.id());
David Chen81245fd2018-04-12 14:33:37 -070085 *valueMetric->mutable_value_field() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070086 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
David Chen81245fd2018-04-12 14:33:37 -070087 *valueMetric->mutable_dimensions_in_what() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -070088 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
David Chen81245fd2018-04-12 14:33:37 -070089 valueMetric->set_bucket(FIVE_MINUTES);
90 valueMetric->set_min_bucket_size_nanos(minTime);
Chenjie Yu021e2532018-05-16 12:23:07 -070091 valueMetric->set_use_absolute_value_on_reset(true);
Tej Singhe678cb72020-04-14 16:23:30 -070092 valueMetric->set_skip_zero_diff_output(false);
David Chen81245fd2018-04-12 14:33:37 -070093 return config;
94}
95
96StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
97 StatsdConfig config;
98 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
Tej Singh3be093b2020-03-04 20:08:38 -080099 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
David Chen81245fd2018-04-12 14:33:37 -0700100
Tej Singhd7b51182019-01-29 17:02:12 -0800101 auto pulledAtomMatcher =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700102 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
Tej Singhd7b51182019-01-29 17:02:12 -0800103 *config.add_atom_matcher() = pulledAtomMatcher;
David Chen81245fd2018-04-12 14:33:37 -0700104 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
105 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
106
107 auto gaugeMetric = config.add_gauge_metric();
108 gaugeMetric->set_id(123456);
Tej Singhd7b51182019-01-29 17:02:12 -0800109 gaugeMetric->set_what(pulledAtomMatcher.id());
David Chen81245fd2018-04-12 14:33:37 -0700110 gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true);
111 *gaugeMetric->mutable_dimensions_in_what() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700112 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
David Chen81245fd2018-04-12 14:33:37 -0700113 gaugeMetric->set_bucket(FIVE_MINUTES);
114 gaugeMetric->set_min_bucket_size_nanos(minTime);
115 return config;
116}
Tej Singh730ed292020-02-03 17:24:27 -0800117} // anonymous namespace
David Chen81245fd2018-04-12 14:33:37 -0700118
tsaichristine7747d372020-02-28 17:36:59 -0800119TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
120 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
121 SendConfig(service, MakeConfig());
122 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
123 // initialized with.
124
125 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
126 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get());
127
128 ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
129 // Expect no metrics since the bucket has not finished yet.
130 EXPECT_EQ(1, report.metrics_size());
131 EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
132}
133
134TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
135 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
136 SendConfig(service, MakeConfig());
137 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
138 // initialized with.
139
140 // Force the uidmap to update at timestamp 2.
141 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
142 // This is a new installation, so there shouldn't be a split (should be same as the without
143 // split case).
144 service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
145 String16(""));
146 // Goes into the second bucket.
147 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
148
149 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
150 EXPECT_EQ(1, report.metrics_size());
151 EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
152}
153
154TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
155 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
156 SendConfig(service, MakeConfig());
157 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
158 // initialized with.
159 service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
160 {String16("")});
161
162 // Force the uidmap to update at timestamp 2.
163 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
164 service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
165 String16(""));
166 // Goes into the second bucket.
167 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
168
169 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
170 backfillStartEndTimestamp(&report);
171
172 ASSERT_EQ(1, report.metrics_size());
173 ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
174 ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
175 EXPECT_TRUE(report.metrics(0)
176 .count_metrics()
177 .data(0)
178 .bucket_info(0)
179 .has_start_bucket_elapsed_nanos());
180 EXPECT_TRUE(report.metrics(0)
181 .count_metrics()
182 .data(0)
183 .bucket_info(0)
184 .has_end_bucket_elapsed_nanos());
185 EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
186}
187
188TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
189 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
190 SendConfig(service, MakeConfig());
191 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
192 // initialized with.
193 service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
194 {String16("")});
195
196 // Force the uidmap to update at timestamp 2.
197 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
198 service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
199 // Goes into the second bucket.
200 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
201
202 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
203 backfillStartEndTimestamp(&report);
204
205 ASSERT_EQ(1, report.metrics_size());
206 ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
207 ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
208 EXPECT_TRUE(report.metrics(0)
209 .count_metrics()
210 .data(0)
211 .bucket_info(0)
212 .has_start_bucket_elapsed_nanos());
213 EXPECT_TRUE(report.metrics(0)
214 .count_metrics()
215 .data(0)
216 .bucket_info(0)
217 .has_end_bucket_elapsed_nanos());
218 EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
219}
David Chenbd125272018-04-04 19:02:50 -0700220
Tej Singhe678cb72020-04-14 16:23:30 -0700221TEST(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
222 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
223 SendConfig(service, MakeConfig());
224 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
225 // initialized with.
226
227 // Goes into the first bucket
228 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + NS_PER_SEC, 100).get());
229 int64_t bootCompleteTimeNs = start + 2 * NS_PER_SEC;
230 service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
231 // Goes into the second bucket.
232 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3 * NS_PER_SEC, 100).get());
233
234 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4 * NS_PER_SEC);
235 backfillStartEndTimestamp(&report);
236
237 ASSERT_EQ(1, report.metrics_size());
238 ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
239 ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
240 EXPECT_TRUE(report.metrics(0)
241 .count_metrics()
242 .data(0)
243 .bucket_info(0)
244 .has_start_bucket_elapsed_nanos());
245 EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
246 report.metrics(0).count_metrics().data(0).bucket_info(0).end_bucket_elapsed_nanos());
247 EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
248}
249
David Chen81245fd2018-04-12 14:33:37 -0700250TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800251 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
252 service->mPullerManager->RegisterPullAtomCallback(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700253 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800254 SharedRefBase::make<FakeSubsystemSleepCallback>());
David Chen81245fd2018-04-12 14:33:37 -0700255 // Partial buckets don't occur when app is first installed.
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800256 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700257 SendConfig(service, MakeValueMetricConfig(0));
Yao Chencc884df2018-05-07 10:34:31 -0700258 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
259 // initialized with.
David Chen81245fd2018-04-12 14:33:37 -0700260
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800261 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
Tej Singhe678cb72020-04-14 16:23:30 -0700262 int64_t appUpgradeTimeNs = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
263 service->mUidMap->updateApp(appUpgradeTimeNs, String16(kApp1.c_str()), 1, 2, String16("v2"),
264 String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700265
266 ConfigMetricsReport report =
Tej Singhe678cb72020-04-14 16:23:30 -0700267 GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
268 backfillStartEndTimestamp(&report);
269
David Chen81245fd2018-04-12 14:33:37 -0700270 EXPECT_EQ(1, report.metrics_size());
271 EXPECT_EQ(0, report.metrics(0).value_metrics().skipped_size());
Tej Singhe678cb72020-04-14 16:23:30 -0700272
273 // The fake subsystem state sleep puller returns two atoms.
274 ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
275 ASSERT_EQ(2, report.metrics(0).value_metrics().data(0).bucket_info_size());
276 EXPECT_EQ(MillisToNano(NanoToMillis(appUpgradeTimeNs)),
277 report.metrics(0).value_metrics().data(0).bucket_info(1).end_bucket_elapsed_nanos());
David Chen81245fd2018-04-12 14:33:37 -0700278}
279
280TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800281 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
282 service->mPullerManager->RegisterPullAtomCallback(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700283 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800284 SharedRefBase::make<FakeSubsystemSleepCallback>());
David Chen81245fd2018-04-12 14:33:37 -0700285 // Partial buckets don't occur when app is first installed.
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800286 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700287 SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
Yao Chencc884df2018-05-07 10:34:31 -0700288 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
289 // initialized with.
David Chen81245fd2018-04-12 14:33:37 -0700290
Tej Singhe678cb72020-04-14 16:23:30 -0700291 const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800292 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
293 service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
dwchen730403e2018-10-29 11:41:56 -0700294 String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700295
296 ConfigMetricsReport report =
Tej Singhe678cb72020-04-14 16:23:30 -0700297 GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
Yangster-mac9def8e32018-04-17 13:55:51 -0700298 backfillStartEndTimestamp(&report);
Tej Singh9ec159a2019-11-14 11:59:48 -0800299
300 ASSERT_EQ(1, report.metrics_size());
301 ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
Yangster-mac9def8e32018-04-17 13:55:51 -0700302 EXPECT_TRUE(report.metrics(0).value_metrics().skipped(0).has_start_bucket_elapsed_nanos());
David Chen81245fd2018-04-12 14:33:37 -0700303 // Can't test the start time since it will be based on the actual time when the pulling occurs.
Yangster-mac9def8e32018-04-17 13:55:51 -0700304 EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
305 report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
Tej Singhe678cb72020-04-14 16:23:30 -0700306
307 ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
308 EXPECT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
309}
310
311TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
312 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
313 // Initial pull will fail since puller is not registered.
314 SendConfig(service, MakeValueMetricConfig(0));
315 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
316 // initialized with.
317
318 service->mPullerManager->RegisterPullAtomCallback(
319 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
320 SharedRefBase::make<FakeSubsystemSleepCallback>());
321
322 int64_t bootCompleteTimeNs = start + NS_PER_SEC;
323 service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
324
325 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
326
327 ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
328 backfillStartEndTimestamp(&report);
329
330 // First bucket is dropped due to the initial pull failing
331 ASSERT_EQ(1, report.metrics_size());
332 EXPECT_EQ(1, report.metrics(0).value_metrics().skipped_size());
333 EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
334 report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
335
336 // The fake subsystem state sleep puller returns two atoms.
337 ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
338 ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
339 EXPECT_EQ(
340 MillisToNano(NanoToMillis(bootCompleteTimeNs)),
341 report.metrics(0).value_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
David Chen81245fd2018-04-12 14:33:37 -0700342}
343
344TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800345 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
Tej Singhe678cb72020-04-14 16:23:30 -0700346 service->mPullerManager->RegisterPullAtomCallback(
347 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
348 SharedRefBase::make<FakeSubsystemSleepCallback>());
David Chen81245fd2018-04-12 14:33:37 -0700349 // Partial buckets don't occur when app is first installed.
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800350 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700351 SendConfig(service, MakeGaugeMetricConfig(0));
Yao Chencc884df2018-05-07 10:34:31 -0700352 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
353 // initialized with.
David Chen81245fd2018-04-12 14:33:37 -0700354
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800355 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
356 service->mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
dwchen730403e2018-10-29 11:41:56 -0700357 String16("v2"), String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700358
Tej Singhe678cb72020-04-14 16:23:30 -0700359 ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
360 backfillStartEndTimestamp(&report);
361 ASSERT_EQ(1, report.metrics_size());
David Chen81245fd2018-04-12 14:33:37 -0700362 EXPECT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
Tej Singhe678cb72020-04-14 16:23:30 -0700363 // The fake subsystem state sleep puller returns two atoms.
364 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
365 EXPECT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
David Chen81245fd2018-04-12 14:33:37 -0700366}
367
368TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800369 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
David Chen81245fd2018-04-12 14:33:37 -0700370 // Partial buckets don't occur when app is first installed.
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800371 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
Tej Singhe678cb72020-04-14 16:23:30 -0700372 service->mPullerManager->RegisterPullAtomCallback(
373 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
374 SharedRefBase::make<FakeSubsystemSleepCallback>());
David Chen81245fd2018-04-12 14:33:37 -0700375 SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
Yao Chencc884df2018-05-07 10:34:31 -0700376 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
377 // initialized with.
David Chen81245fd2018-04-12 14:33:37 -0700378
379 const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800380 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
381 service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
382 String16(""));
David Chen81245fd2018-04-12 14:33:37 -0700383
384 ConfigMetricsReport report =
Tej Singhe678cb72020-04-14 16:23:30 -0700385 GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
Yangster-mac9def8e32018-04-17 13:55:51 -0700386 backfillStartEndTimestamp(&report);
Tej Singh9ec159a2019-11-14 11:59:48 -0800387 ASSERT_EQ(1, report.metrics_size());
388 ASSERT_EQ(1, report.metrics(0).gauge_metrics().skipped_size());
David Chen81245fd2018-04-12 14:33:37 -0700389 // Can't test the start time since it will be based on the actual time when the pulling occurs.
Yangster-mac9def8e32018-04-17 13:55:51 -0700390 EXPECT_TRUE(report.metrics(0).gauge_metrics().skipped(0).has_start_bucket_elapsed_nanos());
391 EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
392 report.metrics(0).gauge_metrics().skipped(0).end_bucket_elapsed_nanos());
Tej Singhe678cb72020-04-14 16:23:30 -0700393 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
394 EXPECT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
395}
396
397TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
398 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
399 // Initial pull will fail since puller hasn't been registered.
400 SendConfig(service, MakeGaugeMetricConfig(0));
401 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
402 // initialized with.
403
404 service->mPullerManager->RegisterPullAtomCallback(
405 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
406 SharedRefBase::make<FakeSubsystemSleepCallback>());
407
408 int64_t bootCompleteTimeNs = start + NS_PER_SEC;
409 service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
410
411 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
412
413 ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
414 backfillStartEndTimestamp(&report);
415
416 ASSERT_EQ(1, report.metrics_size());
417 EXPECT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
418 // The fake subsystem state sleep puller returns two atoms.
419 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
420 // No data in the first bucket, so nothing is reported
421 ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
422 EXPECT_EQ(
423 MillisToNano(NanoToMillis(bootCompleteTimeNs)),
424 report.metrics(0).gauge_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
David Chen81245fd2018-04-12 14:33:37 -0700425}
426
David Chenbd125272018-04-04 19:02:50 -0700427#else
428GTEST_LOG_(INFO) << "This test does nothing.\n";
429#endif
430
431} // namespace statsd
432} // namespace os
Jeff Sharkey6b649252018-04-16 09:50:22 -0600433} // namespace android