| // 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/select_most_common_aggregation_procedure.h" |
| |
| #include <memory> |
| |
| #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.h" |
| #include "src/logger/project_context_factory.h" |
| #include "src/registry/report_definition.pb.h" |
| |
| namespace cobalt::local_aggregation { |
| |
| class SelectMostCommonAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| logger::EventRecord GetEventRecord(uint32_t metric_id) { |
| return logger::EventRecord(GetProjectContext(), metric_id); |
| } |
| |
| std::unique_ptr<AggregationProcedure> GetProcedure(uint32_t metric_id, uint32_t report_index) { |
| return std::make_unique<SelectMostCommonAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(SelectMostCommonAggregationProcedureTest, UpdateAggregate1DayReport) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| uint32_t report_index = kOccurrenceMetricUniqueDeviceCountsSelectMostCommonReport1DayReportIndex; |
| |
| auto report = GetReportDef(metric_id, report_index); |
| auto procedure = GetProcedure(metric_id, report_index); |
| |
| const uint32_t kDayIndex = 10000; |
| uint32_t kNumEventCodes = 100; |
| ASSERT_GE(GetMetricDef(metric_id).event_code_buffer_max(), kNumEventCodes); |
| |
| ReportAggregate aggregate; |
| AddOccurrenceEventsForDay(kNumEventCodes, kDayIndex, procedure.get(), &aggregate); |
| |
| for (uint32_t i = 0; i < kNumEventCodes; ++i) { |
| ASSERT_EQ(aggregate.daily().by_day_index().count(kDayIndex), 1u); |
| EXPECT_EQ(aggregate.daily().by_day_index().at(kDayIndex).by_event_code(i).data().count(), i + 1) |
| << "Incorrect count for event code " << i + 1; |
| } |
| } |
| |
| TEST_F(SelectMostCommonAggregationProcedureTest, GenerateObservation1DayReportNoEvents) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| uint32_t report_index = kOccurrenceMetricUniqueDeviceCountsSelectMostCommonReport1DayReportIndex; |
| auto procedure = GetProcedure(metric_id, report_index); |
| |
| const uint32_t kDayIndex = 10000; |
| util::TimeInfo time_info; |
| time_info.day_index = kDayIndex; |
| |
| ReportAggregate report_aggregate; |
| |
| auto status_or_observation = procedure->GenerateObservation(time_info, &report_aggregate); |
| ASSERT_TRUE(status_or_observation.ok()); |
| auto observation = std::move(status_or_observation.ValueOrDie()); |
| |
| ASSERT_TRUE(observation->has_integer()); |
| const auto &integer_obs = observation->integer(); |
| ASSERT_EQ(integer_obs.values_size(), 0); |
| } |
| |
| TEST_F(SelectMostCommonAggregationProcedureTest, GenerateObservation1DayReport) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| uint32_t report_index = kOccurrenceMetricUniqueDeviceCountsSelectMostCommonReport1DayReportIndex; |
| auto procedure = GetProcedure(metric_id, report_index); |
| |
| const uint32_t kDayIndex = 10000; |
| util::TimeInfo time_info; |
| time_info.day_index = kDayIndex; |
| |
| const uint32_t kNumEventCodes = 100; |
| ASSERT_GE(GetMetricDef(metric_id).event_code_buffer_max(), kNumEventCodes); |
| |
| ReportAggregate report_aggregate; |
| // Log |event_code| OccurrenceEvents, each with a count of 1, for each |event_code| in the range |
| // [1, kNumEventCodes]. The most common event code will be |kNumEventCodes|. |
| AddOccurrenceEventsForDay(kNumEventCodes, kDayIndex, procedure.get(), &report_aggregate); |
| |
| auto status_or_observation = procedure->GenerateObservation(time_info, &report_aggregate); |
| ASSERT_TRUE(status_or_observation.ok()); |
| auto observation = std::move(status_or_observation.ValueOrDie()); |
| |
| ASSERT_TRUE(observation->has_integer()); |
| const auto &integer_obs = observation->integer(); |
| ASSERT_EQ(integer_obs.values_size(), 1); |
| EXPECT_EQ(integer_obs.values(0).event_codes_size(), 1); |
| EXPECT_EQ(integer_obs.values(0).event_codes(0), kNumEventCodes); |
| EXPECT_EQ(integer_obs.values(0).value(), 1); |
| |
| // Check that obsolete aggregates were cleaned up. |
| EXPECT_EQ(report_aggregate.daily().by_day_index().count(kDayIndex), 0u); |
| } |
| |
| TEST_F(SelectMostCommonAggregationProcedureTest, GenerateObservation7DaysReport) { |
| uint32_t metric_id = kOccurrenceMetricMetricId; |
| uint32_t report_index = kOccurrenceMetricUniqueDeviceCountsSelectMostCommonReport7DaysReportIndex; |
| auto procedure = GetProcedure(metric_id, report_index); |
| |
| const uint32_t kDayIndex = 10000; |
| util::TimeInfo time_info; |
| time_info.day_index = kDayIndex; |
| |
| const uint32_t kNumEventCodes = 7; |
| ASSERT_GE(GetMetricDef(metric_id).event_code_buffer_max(), kNumEventCodes); |
| |
| ReportAggregate report_aggregate; |
| const uint32_t kMostCommonEventCode = 1; |
| // Log |event_code| OccurrenceEvents, each with a count of 1, for each |event_code| in the |
| // range [1, kNumEventCodes]. |
| AddOccurrenceEventsForDay(kNumEventCodes, kDayIndex - 1, procedure.get(), &report_aggregate); |
| // For another day in the aggregation period, log |kNumEventCodes| + 1 OccurrenceEvents, each with |
| // a count of 1, for event code |kMostCommonEventCode|. The most common event code over the |
| // aggregation period is now |kMostCommonEventCode|. |
| for (int i = 0; i < kNumEventCodes + 1; ++i) { |
| AddOccurrenceEventsForDay(kMostCommonEventCode, kDayIndex, procedure.get(), &report_aggregate); |
| } |
| |
| auto status_or_observation = procedure->GenerateObservation(time_info, &report_aggregate); |
| ASSERT_TRUE(status_or_observation.ok()); |
| auto observation = std::move(status_or_observation.ValueOrDie()); |
| |
| ASSERT_TRUE(observation->has_integer()); |
| const auto &integer_obs = observation->integer(); |
| ASSERT_EQ(integer_obs.values_size(), 1); |
| EXPECT_EQ(integer_obs.values(0).event_codes_size(), 1); |
| EXPECT_EQ(integer_obs.values(0).event_codes(0), kMostCommonEventCode); |
| EXPECT_EQ(integer_obs.values(0).value(), 1); |
| |
| // Check that obsolete aggregates were cleaned up. |
| EXPECT_EQ(report_aggregate.daily().by_day_index().count(kDayIndex - 6), 0u); |
| for (uint32_t day = kDayIndex; day > kDayIndex - 6; --day) { |
| EXPECT_EQ(report_aggregate.daily().by_day_index().count(day), 1u); |
| } |
| } |
| |
| } // namespace cobalt::local_aggregation |