| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/local_aggregation_1_1/aggregation_procedures/count_aggregation_procedure.h" |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/lib/util/datetime_util.h" |
| #include "src/local_aggregation_1_1/aggregation_procedures/aggregation_procedure.h" |
| #include "src/local_aggregation_1_1/aggregation_procedures/testing/test_aggregation_procedure.h" |
| #include "src/local_aggregation_1_1/testing/test_registry.cb.h" |
| #include "src/logger/project_context_factory.h" |
| |
| namespace cobalt::local_aggregation { |
| |
| class CountAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<CountAggregationProcedure> GetProcedure(uint32_t metric_id, int report_index) { |
| return std::make_unique<CountAggregationProcedure>(GetMetricDef(metric_id), |
| GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(CountAggregationProcedureTest, UpdateAggregateWorks) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| std::unique_ptr<AggregationProcedure> procedure = |
| GetProcedureFor(metric_id, kOccurrenceMetricFleetwideOccurrenceCountsReportReportIndex); |
| |
| ReportAggregate aggregate; |
| const uint32_t kHourId = 1; |
| const uint64_t system_profile_hash = uint64_t{56789}; |
| const uint32_t kNumEventCodes = 100; |
| AddOccurrenceEventsForHour(kNumEventCodes, kHourId, system_profile_hash, *procedure, aggregate); |
| |
| ASSERT_TRUE(aggregate.hourly().by_hour_id().contains(kHourId)); |
| ASSERT_EQ(aggregate.hourly().by_hour_id().at(kHourId).system_profile_aggregates_size(), 1u); |
| const SystemProfileAggregate &system_profile_agg = |
| aggregate.hourly().by_hour_id().at(kHourId).system_profile_aggregates(0); |
| EXPECT_EQ(system_profile_agg.system_profile_hash(), system_profile_hash); |
| ASSERT_EQ(system_profile_agg.by_event_code_size(), kNumEventCodes); |
| for (uint32_t i = 0; i < kNumEventCodes; ++i) { |
| EXPECT_EQ(system_profile_agg.by_event_code(i).event_codes(0), i + 1); |
| EXPECT_EQ(system_profile_agg.by_event_code(i).data().count(), i + 1); |
| } |
| } |
| |
| TEST_F(CountAggregationProcedureTest, UpdateAggregateWorksCountAsInt) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| std::unique_ptr<AggregationProcedure> procedure = |
| GetProcedureFor(metric_id, kOccurrenceMetricHourlyDeviceHistogramsReportIndex); |
| |
| ReportAggregate aggregate; |
| const uint32_t kHourId = 1; |
| const uint64_t system_profile_hash = uint64_t{56789}; |
| const uint32_t kNumEventCodes = 100; |
| AddOccurrenceEventsForHourWithCount(kNumEventCodes, 5, kHourId, system_profile_hash, *procedure, |
| aggregate); |
| |
| ASSERT_TRUE(aggregate.hourly().by_hour_id().contains(kHourId)); |
| ASSERT_EQ(aggregate.hourly().by_hour_id().at(kHourId).system_profile_aggregates_size(), 1u); |
| const SystemProfileAggregate &system_profile_agg = |
| aggregate.hourly().by_hour_id().at(kHourId).system_profile_aggregates(0); |
| EXPECT_EQ(system_profile_agg.system_profile_hash(), system_profile_hash); |
| ASSERT_EQ(system_profile_agg.by_event_code_size(), kNumEventCodes); |
| for (uint32_t i = 0; i < kNumEventCodes; ++i) { |
| EXPECT_EQ(system_profile_agg.by_event_code(i).event_codes(0), i + 1); |
| EXPECT_EQ(system_profile_agg.by_event_code(i).data().count(), (i + 1) * 5); |
| } |
| } |
| |
| TEST_F(CountAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.set_count(10); |
| AggregateData merged_data; |
| merged_data.set_count(20); |
| |
| std::unique_ptr<CountAggregationProcedure> procedure = |
| GetProcedure(kOccurrenceMetricMetricId, kOccurrenceMetricHourlyDeviceHistogramsReportIndex); |
| procedure->MergeAggregateData(merged_data, data); |
| |
| EXPECT_EQ(merged_data.count(), 30); |
| } |
| |
| TEST_F(CountAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<CountAggregationProcedure> procedure = |
| GetProcedure(kOccurrenceMetricMetricId, kOccurrenceMetricHourlyDeviceHistogramsReportIndex); |
| procedure->MergeAggregateData(merged_data, data); |
| |
| EXPECT_EQ(merged_data.count(), 0); |
| } |
| |
| TEST_F(CountAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.set_count(10); |
| AggregateData merged_data; |
| |
| std::unique_ptr<CountAggregationProcedure> procedure = |
| GetProcedure(kOccurrenceMetricMetricId, kOccurrenceMetricHourlyDeviceHistogramsReportIndex); |
| procedure->MergeAggregateData(merged_data, data); |
| |
| EXPECT_EQ(merged_data.count(), 10); |
| } |
| |
| TEST_F(CountAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.set_count(20); |
| |
| std::unique_ptr<CountAggregationProcedure> procedure = |
| GetProcedure(kOccurrenceMetricMetricId, kOccurrenceMetricHourlyDeviceHistogramsReportIndex); |
| procedure->MergeAggregateData(merged_data, data); |
| |
| EXPECT_EQ(merged_data.count(), 20); |
| } |
| |
| TEST_F(CountAggregationProcedureTest, GenerateObservationWorks) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| int report_index = kOccurrenceMetricFleetwideOccurrenceCountsReportReportIndex; |
| std::unique_ptr<AggregationProcedure> procedure = GetProcedureFor(metric_id, report_index); |
| |
| ReportAggregate aggregate; |
| const uint32_t kNumEventCodes = 10; |
| ASSERT_GE(GetReportDef(metric_id, report_index).event_vector_buffer_max(), kNumEventCodes); |
| |
| const uint32_t kEndHourId = 11; |
| const uint64_t system_profile_hash = uint64_t{56789}; |
| for (int hour_id = 1; hour_id <= kEndHourId; hour_id += 2) { |
| AddOccurrenceEventsForHour(kNumEventCodes, hour_id, system_profile_hash, *procedure, aggregate); |
| } |
| |
| util::TimeInfo info; |
| info.hour_id = kEndHourId; |
| lib::statusor::StatusOr<std::vector<ObservationAndSystemProfile>> observations_or = |
| procedure->GenerateObservations(info, aggregate); |
| ASSERT_EQ(observations_or.status().error_code(), StatusCode::OK); |
| std::vector<ObservationAndSystemProfile> observations = std::move(observations_or).value(); |
| |
| // Should only generate for kEndHourId |
| ASSERT_EQ(observations.size(), 1u); |
| EXPECT_EQ(observations[0].system_profile_hash, system_profile_hash); |
| |
| EXPECT_EQ(observations[0].observation->integer().values_size(), kNumEventCodes); |
| |
| for (const IntegerObservation::Value &value : observations[0].observation->integer().values()) { |
| EXPECT_EQ(value.event_codes(0), value.value()); |
| } |
| // Check that obsolete aggregates get cleaned up. |
| procedure->ObservationsCommitted(aggregate, info, system_profile_hash); |
| EXPECT_EQ(aggregate.hourly().by_hour_id_size(), 0); |
| } |
| |
| TEST_F(CountAggregationProcedureTest, GenerateObservationWorksCountAsInt) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| int report_index = kOccurrenceMetricHourlyDeviceHistogramsReportIndex; |
| std::unique_ptr<AggregationProcedure> procedure = GetProcedureFor(metric_id, report_index); |
| |
| ReportAggregate aggregate; |
| const uint32_t kNumEventCodes = 10; |
| ASSERT_GE(GetReportDef(metric_id, report_index).event_vector_buffer_max(), kNumEventCodes); |
| |
| const uint32_t kEndHourId = 11; |
| const uint64_t system_profile_hash = uint64_t{56789}; |
| for (int hour_id = 1; hour_id <= kEndHourId; hour_id += 2) { |
| AddOccurrenceEventsForHour(kNumEventCodes, hour_id, system_profile_hash, *procedure, aggregate); |
| } |
| |
| util::TimeInfo info; |
| info.hour_id = kEndHourId; |
| lib::statusor::StatusOr<std::vector<ObservationAndSystemProfile>> observations_or = |
| procedure->GenerateObservations(info, aggregate); |
| ASSERT_EQ(observations_or.status().error_code(), StatusCode::OK); |
| std::vector<ObservationAndSystemProfile> observations = std::move(observations_or).value(); |
| |
| // Should only generate for kEndHourId |
| ASSERT_EQ(observations.size(), 1u); |
| EXPECT_EQ(observations[0].system_profile_hash, system_profile_hash); |
| |
| EXPECT_EQ(observations[0].observation->integer().values_size(), kNumEventCodes); |
| |
| for (const IntegerObservation::Value &value : observations[0].observation->integer().values()) { |
| EXPECT_EQ(value.event_codes(0), value.value()); |
| } |
| // Check that obsolete aggregates get cleaned up. |
| procedure->ObservationsCommitted(aggregate, info, system_profile_hash); |
| EXPECT_EQ(aggregate.hourly().by_hour_id_size(), 0); |
| } |
| |
| } // namespace cobalt::local_aggregation |