diff options
Diffstat (limited to 'cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp')
-rw-r--r-- | cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp | 299 |
1 files changed, 219 insertions, 80 deletions
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp index 0bc3ebb81ce6..c03b9254f70d 100644 --- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp @@ -12,45 +12,47 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <android/binder_ibinder.h> +#include <android/binder_interface_utils.h> #include <gtest/gtest.h> -#include <binder/IPCThreadState.h> +#include <vector> + #include "src/StatsLogProcessor.h" #include "src/StatsService.h" #include "src/stats_log_util.h" #include "tests/statsd_test_util.h" -#include <vector> +using::ndk::SharedRefBase; +using std::shared_ptr; namespace android { namespace os { namespace statsd { #ifdef __ANDROID__ - -const string kAndroid = "android"; +namespace { const string kApp1 = "app1.sharing.1"; const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs. +const int kCallingUid = 0; // Randomly chosen -void SendConfig(StatsService& service, const StatsdConfig& config) { +void SendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) { string str; config.SerializeToString(&str); std::vector<uint8_t> configAsVec(str.begin(), str.end()); - bool success; - service.addConfiguration(kConfigKey, configAsVec, String16(kAndroid.c_str())); + service->addConfiguration(kConfigKey, configAsVec, kCallingUid); } ConfigMetricsReport GetReports(sp<StatsLogProcessor> processor, int64_t timestamp, bool include_current = false) { vector<uint8_t> output; - IPCThreadState* ipc = IPCThreadState::self(); - ConfigKey configKey(ipc->getCallingUid(), kConfigKey); + ConfigKey configKey(AIBinder_getCallingUid(), kConfigKey); processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/, true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output); ConfigMetricsReportList reports; reports.ParseFromArray(output.data(), output.size()); EXPECT_EQ(1, reports.reports_size()); - return reports.reports(0); + return reports.reports(kCallingUid); } StatsdConfig MakeConfig() { @@ -69,9 +71,10 @@ StatsdConfig MakeConfig() { StatsdConfig MakeValueMetricConfig(int64_t minTime) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root. auto pulledAtomMatcher = - CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE); + CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE); *config.add_atom_matcher() = pulledAtomMatcher; *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); @@ -80,21 +83,23 @@ StatsdConfig MakeValueMetricConfig(int64_t minTime) { valueMetric->set_id(123456); valueMetric->set_what(pulledAtomMatcher.id()); *valueMetric->mutable_value_field() = - CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); *valueMetric->mutable_dimensions_in_what() = - CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */}); + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */}); valueMetric->set_bucket(FIVE_MINUTES); valueMetric->set_min_bucket_size_nanos(minTime); valueMetric->set_use_absolute_value_on_reset(true); + valueMetric->set_skip_zero_diff_output(false); return config; } StatsdConfig MakeGaugeMetricConfig(int64_t minTime) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root. auto pulledAtomMatcher = - CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE); + CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE); *config.add_atom_matcher() = pulledAtomMatcher; *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); @@ -104,135 +109,192 @@ StatsdConfig MakeGaugeMetricConfig(int64_t minTime) { gaugeMetric->set_what(pulledAtomMatcher.id()); gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true); *gaugeMetric->mutable_dimensions_in_what() = - CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */}); + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */}); gaugeMetric->set_bucket(FIVE_MINUTES); gaugeMetric->set_min_bucket_size_nanos(minTime); return config; } +} // anonymous namespace TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); SendConfig(service, MakeConfig()); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get()); - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get()); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get()); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get()); - ConfigMetricsReport report = GetReports(service.mProcessor, start + 3); + ConfigMetricsReport report = GetReports(service->mProcessor, start + 3); // Expect no metrics since the bucket has not finished yet. - EXPECT_EQ(1, report.metrics_size()); - EXPECT_EQ(0, report.metrics(0).count_metrics().data_size()); + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(0, report.metrics(0).count_metrics().data_size()); } TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); SendConfig(service, MakeConfig()); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. // Force the uidmap to update at timestamp 2. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get()); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get()); // This is a new installation, so there shouldn't be a split (should be same as the without // split case). - service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"), - String16("")); + service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"), + String16("")); // Goes into the second bucket. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get()); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get()); - ConfigMetricsReport report = GetReports(service.mProcessor, start + 4); - EXPECT_EQ(1, report.metrics_size()); - EXPECT_EQ(0, report.metrics(0).count_metrics().data_size()); + ConfigMetricsReport report = GetReports(service->mProcessor, start + 4); + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(0, report.metrics(0).count_metrics().data_size()); } TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); SendConfig(service, MakeConfig()); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. - service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())}, - {String16("")}); + service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())}, + {String16("")}); // Force the uidmap to update at timestamp 2. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get()); - service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"), - String16("")); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get()); + service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"), + String16("")); // Goes into the second bucket. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get()); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get()); - ConfigMetricsReport report = GetReports(service.mProcessor, start + 4); + ConfigMetricsReport report = GetReports(service->mProcessor, start + 4); backfillStartEndTimestamp(&report); ASSERT_EQ(1, report.metrics_size()); ASSERT_EQ(1, report.metrics(0).count_metrics().data_size()); ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size()); - EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0). - has_start_bucket_elapsed_nanos()); - EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0). - has_end_bucket_elapsed_nanos()); + EXPECT_TRUE(report.metrics(0) + .count_metrics() + .data(0) + .bucket_info(0) + .has_start_bucket_elapsed_nanos()); + EXPECT_TRUE(report.metrics(0) + .count_metrics() + .data(0) + .bucket_info(0) + .has_end_bucket_elapsed_nanos()); EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count()); } TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); SendConfig(service, MakeConfig()); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. - service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())}, - {String16("")}); + service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())}, + {String16("")}); // Force the uidmap to update at timestamp 2. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get()); - service.mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get()); + service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1); + // Goes into the second bucket. + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get()); + + ConfigMetricsReport report = GetReports(service->mProcessor, start + 4); + backfillStartEndTimestamp(&report); + + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(1, report.metrics(0).count_metrics().data_size()); + ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size()); + EXPECT_TRUE(report.metrics(0) + .count_metrics() + .data(0) + .bucket_info(0) + .has_start_bucket_elapsed_nanos()); + EXPECT_TRUE(report.metrics(0) + .count_metrics() + .data(0) + .bucket_info(0) + .has_end_bucket_elapsed_nanos()); + EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count()); +} + +TEST(PartialBucketE2eTest, TestCountMetricSplitOnBoot) { + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); + SendConfig(service, MakeConfig()); + int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are + // initialized with. + + // Goes into the first bucket + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + NS_PER_SEC, 100).get()); + int64_t bootCompleteTimeNs = start + 2 * NS_PER_SEC; + service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs); // Goes into the second bucket. - service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get()); + service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3 * NS_PER_SEC, 100).get()); - ConfigMetricsReport report = GetReports(service.mProcessor, start + 4); + ConfigMetricsReport report = GetReports(service->mProcessor, start + 4 * NS_PER_SEC); backfillStartEndTimestamp(&report); ASSERT_EQ(1, report.metrics_size()); ASSERT_EQ(1, report.metrics(0).count_metrics().data_size()); ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size()); - EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0). - has_start_bucket_elapsed_nanos()); - EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0). - has_end_bucket_elapsed_nanos()); + EXPECT_TRUE(report.metrics(0) + .count_metrics() + .data(0) + .bucket_info(0) + .has_start_bucket_elapsed_nanos()); + EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)), + report.metrics(0).count_metrics().data(0).bucket_info(0).end_bucket_elapsed_nanos()); EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count()); } TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); + service->mPullerManager->RegisterPullAtomCallback( + /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {}, + SharedRefBase::make<FakeSubsystemSleepCallback>()); // Partial buckets don't occur when app is first installed. - service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); + service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); SendConfig(service, MakeValueMetricConfig(0)); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. - service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); - service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2, - String16("v2"), String16("")); + service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); + int64_t appUpgradeTimeNs = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC; + service->mUidMap->updateApp(appUpgradeTimeNs, String16(kApp1.c_str()), 1, 2, String16("v2"), + String16("")); ConfigMetricsReport report = - GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true); - EXPECT_EQ(1, report.metrics_size()); - EXPECT_EQ(0, report.metrics(0).value_metrics().skipped_size()); + GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC); + backfillStartEndTimestamp(&report); + + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(0, report.metrics(0).value_metrics().skipped_size()); + + // The fake subsystem state sleep puller returns two atoms. + ASSERT_EQ(2, report.metrics(0).value_metrics().data_size()); + ASSERT_EQ(2, report.metrics(0).value_metrics().data(0).bucket_info_size()); + EXPECT_EQ(MillisToNano(NanoToMillis(appUpgradeTimeNs)), + report.metrics(0).value_metrics().data(0).bucket_info(1).end_bucket_elapsed_nanos()); } TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); + service->mPullerManager->RegisterPullAtomCallback( + /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {}, + SharedRefBase::make<FakeSubsystemSleepCallback>()); // Partial buckets don't occur when app is first installed. - service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); + service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */)); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. - const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2; - service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); - service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"), + const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC; + service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); + service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"), String16("")); ConfigMetricsReport report = - GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true); + GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC); backfillStartEndTimestamp(&report); ASSERT_EQ(1, report.metrics_size()); @@ -241,41 +303,86 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) { // Can't test the start time since it will be based on the actual time when the pulling occurs. EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)), report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos()); + + ASSERT_EQ(2, report.metrics(0).value_metrics().data_size()); + ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size()); +} + +TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) { + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); + // Initial pull will fail since puller is not registered. + SendConfig(service, MakeValueMetricConfig(0)); + int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are + // initialized with. + + service->mPullerManager->RegisterPullAtomCallback( + /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {}, + SharedRefBase::make<FakeSubsystemSleepCallback>()); + + int64_t bootCompleteTimeNs = start + NS_PER_SEC; + service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs); + + service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); + + ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100); + backfillStartEndTimestamp(&report); + + // First bucket is dropped due to the initial pull failing + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size()); + EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)), + report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos()); + + // The fake subsystem state sleep puller returns two atoms. + ASSERT_EQ(2, report.metrics(0).value_metrics().data_size()); + ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size()); + EXPECT_EQ( + MillisToNano(NanoToMillis(bootCompleteTimeNs)), + report.metrics(0).value_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos()); } TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); + service->mPullerManager->RegisterPullAtomCallback( + /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {}, + SharedRefBase::make<FakeSubsystemSleepCallback>()); // Partial buckets don't occur when app is first installed. - service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); + service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); SendConfig(service, MakeGaugeMetricConfig(0)); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. - service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); - service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2, + service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); + service->mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"), String16("")); - ConfigMetricsReport report = - GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true); - EXPECT_EQ(1, report.metrics_size()); - EXPECT_EQ(0, report.metrics(0).gauge_metrics().skipped_size()); + ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100); + backfillStartEndTimestamp(&report); + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size()); + // The fake subsystem state sleep puller returns two atoms. + ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size()); + ASSERT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size()); } TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) { - StatsService service(nullptr, nullptr); + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); // Partial buckets don't occur when app is first installed. - service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); + service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16("")); + service->mPullerManager->RegisterPullAtomCallback( + /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {}, + SharedRefBase::make<FakeSubsystemSleepCallback>()); SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */)); int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are // initialized with. const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2; - service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); - service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"), - String16("")); + service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); + service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"), + String16("")); ConfigMetricsReport report = - GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true); + GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC); backfillStartEndTimestamp(&report); ASSERT_EQ(1, report.metrics_size()); ASSERT_EQ(1, report.metrics(0).gauge_metrics().skipped_size()); @@ -283,6 +390,38 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) { EXPECT_TRUE(report.metrics(0).gauge_metrics().skipped(0).has_start_bucket_elapsed_nanos()); EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)), report.metrics(0).gauge_metrics().skipped(0).end_bucket_elapsed_nanos()); + ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size()); + ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size()); +} + +TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) { + shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr); + // Initial pull will fail since puller hasn't been registered. + SendConfig(service, MakeGaugeMetricConfig(0)); + int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are + // initialized with. + + service->mPullerManager->RegisterPullAtomCallback( + /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {}, + SharedRefBase::make<FakeSubsystemSleepCallback>()); + + int64_t bootCompleteTimeNs = start + NS_PER_SEC; + service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs); + + service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start); + + ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100); + backfillStartEndTimestamp(&report); + + ASSERT_EQ(1, report.metrics_size()); + ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size()); + // The fake subsystem state sleep puller returns two atoms. + ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size()); + // No data in the first bucket, so nothing is reported + ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size()); + EXPECT_EQ( + MillisToNano(NanoToMillis(bootCompleteTimeNs)), + report.metrics(0).gauge_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos()); } #else |