| // 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/numeric_stat_aggregation_procedure.h" |
| |
| #include <limits> |
| #include <memory> |
| |
| #include <gmock/gmock.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/local_aggregation.pb.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/pb/observation.pb.h" |
| #include "src/registry/report_definition.pb.h" |
| |
| namespace cobalt::local_aggregation { |
| |
| using TimeInfo = util::TimeInfo; |
| using ::testing::IsEmpty; |
| using ::testing::UnorderedElementsAre; |
| |
| class NumericStatAggregationProcedureTest |
| : public testing::TestAggregationProcedure, |
| public ::testing::WithParamInterface< |
| std::tuple<std::string /* test name */, int /* 7-day report index */, |
| int /* hourly-value report index */, std::vector<int64_t> /* value sequence */, |
| int64_t /* expected value */>> { |
| public: |
| void LogIntegerSequence(const std::vector<int64_t> &values, util::TimeInfo time_info, |
| uint64_t system_profile_hash, AggregationProcedure *procedure, |
| ReportAggregate *aggregate) { |
| std::unique_ptr<logger::EventRecord> record = MakeEventRecord(time_info); |
| IntegerEvent *event = record->event()->mutable_integer_event(); |
| for (int64_t value : values) { |
| event->set_value(value); |
| procedure->UpdateAggregate( |
| *record, aggregate, system_profile_hash, |
| util::FromUnixSeconds(util::HourIdToUnixSeconds(time_info.hour_id))); |
| } |
| event->add_event_code(1); |
| for (int64_t value : values) { |
| event->set_value(value); |
| procedure->UpdateAggregate( |
| *record, aggregate, system_profile_hash, |
| util::FromUnixSeconds(util::HourIdToUnixSeconds(time_info.hour_id))); |
| } |
| } |
| }; |
| |
| namespace { |
| |
| struct TestCase { |
| std::string name; |
| std::vector<int64_t> sequence; |
| |
| int64_t sum; |
| int64_t min; |
| int64_t max; |
| int64_t mean; |
| int64_t median; |
| int64_t percentile_75; |
| int64_t percentile_99; |
| }; |
| |
| ::testing::internal::ParamGenerator<NumericStatAggregationProcedureTest::ParamType> MakeSuite( |
| const std::vector<TestCase> &test_cases) { |
| std::vector<NumericStatAggregationProcedureTest::ParamType> cases; |
| for (const TestCase &test_case : test_cases) { |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7DaySumReportIndex, |
| kIntegerMetricHourlyValueNumericStatsSumReportIndex, test_case.sequence, test_case.sum)); |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7DayMinReportIndex, |
| kIntegerMetricHourlyValueNumericStatsMinReportIndex, test_case.sequence, test_case.min)); |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7DayMaxReportIndex, |
| kIntegerMetricHourlyValueNumericStatsMaxReportIndex, test_case.sequence, test_case.max)); |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7DayMeanReportIndex, |
| kIntegerMetricHourlyValueNumericStatsMeanReportIndex, test_case.sequence, test_case.mean)); |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7DayMedianReportIndex, |
| kIntegerMetricHourlyValueNumericStatsMedianReportIndex, test_case.sequence, |
| test_case.median)); |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7Day75thPercentileReportIndex, |
| kIntegerMetricHourlyValueNumericStats75thPercentileReportIndex, test_case.sequence, |
| test_case.percentile_75)); |
| cases.emplace_back(std::make_tuple( |
| test_case.name, kIntegerMetricUniqueDeviceNumericStatsReport7Day99thPercentileReportIndex, |
| kIntegerMetricHourlyValueNumericStats99thPercentileReportIndex, test_case.sequence, |
| test_case.percentile_99)); |
| } |
| return ::testing::ValuesIn(cases); |
| } |
| |
| std::string TestName( |
| const ::testing::TestParamInfo<NumericStatAggregationProcedureTest::ParamType> &info) { |
| std::string name = std::get<0>(info.param) + "_"; |
| switch (std::get<1>(info.param)) { |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DaySumReportIndex: |
| name += "Sum"; |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMinReportIndex: |
| name += "Min"; |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMaxReportIndex: |
| name += "Max"; |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMeanReportIndex: |
| name += "Mean"; |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMedianReportIndex: |
| name += "Median"; |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7Day75thPercentileReportIndex: |
| name += "75th_Percentile"; |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7Day99thPercentileReportIndex: |
| name += "99th_Percentile"; |
| break; |
| } |
| return name; |
| } |
| |
| void CheckDebugString(int64_t daily_report_type, AggregationProcedure *procedure) { |
| switch (daily_report_type) { |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DaySumReportIndex: |
| ASSERT_EQ(procedure->DebugString(), "SUM_NUMERIC_STAT"); |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMinReportIndex: |
| ASSERT_EQ(procedure->DebugString(), "MIN_NUMERIC_STAT"); |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMaxReportIndex: |
| ASSERT_EQ(procedure->DebugString(), "MAX_NUMERIC_STAT"); |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMeanReportIndex: |
| ASSERT_EQ(procedure->DebugString(), "MEAN_NUMERIC_STAT"); |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7DayMedianReportIndex: |
| ASSERT_EQ(procedure->DebugString(), "MEDIAN_NUMERIC_STAT"); |
| break; |
| case kIntegerMetricUniqueDeviceNumericStatsReport7Day75thPercentileReportIndex: |
| case kIntegerMetricUniqueDeviceNumericStatsReport7Day99thPercentileReportIndex: |
| ASSERT_EQ(procedure->DebugString(), "PERCENTILE_N_NUMERIC_STAT"); |
| break; |
| } |
| } |
| |
| } // namespace |
| |
| TEST_P(NumericStatAggregationProcedureTest, Generate7DayObservations) { |
| auto [_, daily_report_type, hourly_report_type, integer_sequence, expected_value] = GetParam(); |
| |
| uint32_t metric_id = kIntegerMetricMetricId; |
| std::unique_ptr<AggregationProcedure> procedure = GetProcedureFor(metric_id, daily_report_type); |
| |
| CheckDebugString(daily_report_type, procedure.get()); |
| |
| ReportAggregate report_aggregate; |
| const uint32_t kDayIndex = 7; |
| const uint64_t system_profile_hash = uint64_t{987}; |
| |
| int64_t window_size = static_cast<int64_t>(integer_sequence.size()) / kDayIndex; |
| std::vector<int64_t> window; |
| for (int64_t day = 0; day < kDayIndex; day++) { |
| if (day != kDayIndex - 1) { |
| window.assign(integer_sequence.begin() + (window_size * day), |
| integer_sequence.begin() + (window_size * (day + 1))); |
| } else { |
| window.assign(integer_sequence.begin() + (window_size * day), integer_sequence.end()); |
| } |
| LogIntegerSequence(window, TimeInfo::FromDayIndex(day + 1), system_profile_hash, |
| procedure.get(), &report_aggregate); |
| } |
| |
| lib::statusor::StatusOr<std::vector<ObservationAndSystemProfile>> observations_or = |
| procedure->GenerateObservations(util::TimeInfo::FromDayIndex(kDayIndex), &report_aggregate); |
| ASSERT_EQ(observations_or.status().error_code(), StatusCode::OK); |
| std::vector<ObservationAndSystemProfile> observations = observations_or.ConsumeValueOrDie(); |
| |
| ASSERT_EQ(observations.size(), 1u); |
| EXPECT_EQ(observations[0].system_profile_hash, system_profile_hash); |
| |
| ASSERT_TRUE(observations[0].observation->has_integer()); |
| const IntegerObservation &integer_obs = observations[0].observation->integer(); |
| ASSERT_EQ(integer_obs.values_size(), 2); |
| ASSERT_EQ(integer_obs.values(0).value(), expected_value); |
| ASSERT_EQ(integer_obs.values(1).event_codes(0), 1); |
| ASSERT_EQ(integer_obs.values(1).value(), expected_value); |
| |
| // Check that obsolete aggregates get cleaned up. |
| procedure->ObservationsCommitted(&report_aggregate, util::TimeInfo::FromDayIndex(kDayIndex), |
| system_profile_hash); |
| EXPECT_EQ(report_aggregate.daily().by_day_index().count(kDayIndex - 6), 0u); |
| } |
| |
| TEST_P(NumericStatAggregationProcedureTest, GenerateHourlyObservations) { |
| auto [_, daily_report_type, hourly_report_type, integer_sequence, expected_value] = GetParam(); |
| |
| uint32_t metric_id = kIntegerMetricMetricId; |
| std::unique_ptr<AggregationProcedure> procedure = GetProcedureFor(metric_id, hourly_report_type); |
| |
| CheckDebugString(daily_report_type, procedure.get()); |
| |
| ReportAggregate report_aggregate; |
| const uint32_t kHourId = 20; |
| const uint64_t system_profile_hash = uint64_t{987}; |
| |
| for (uint32_t hour = 0; hour <= kHourId; hour += 2) { |
| LogIntegerSequence(integer_sequence, TimeInfo::FromHourId(hour), system_profile_hash, |
| procedure.get(), &report_aggregate); |
| } |
| |
| lib::statusor::StatusOr<std::vector<ObservationAndSystemProfile>> observations_or = |
| procedure->GenerateObservations(util::TimeInfo::FromHourId(kHourId), &report_aggregate); |
| ASSERT_EQ(observations_or.status().error_code(), StatusCode::OK); |
| std::vector<ObservationAndSystemProfile> observations = observations_or.ConsumeValueOrDie(); |
| |
| ASSERT_EQ(observations.size(), 1u); |
| EXPECT_EQ(observations[0].system_profile_hash, system_profile_hash); |
| |
| ASSERT_TRUE(observations[0].observation->has_integer()); |
| const IntegerObservation &integer_obs = observations[0].observation->integer(); |
| ASSERT_EQ(integer_obs.values_size(), 2); |
| ASSERT_EQ(integer_obs.values(0).value(), expected_value); |
| ASSERT_EQ(integer_obs.values(1).event_codes(0), 1); |
| ASSERT_EQ(integer_obs.values(1).value(), expected_value); |
| |
| // Check that obsolete aggregates get cleaned up. |
| procedure->ObservationsCommitted(&report_aggregate, util::TimeInfo::FromHourId(kHourId), |
| system_profile_hash); |
| EXPECT_EQ(report_aggregate.hourly().by_hour_id().count(kHourId), 0u); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(Parameterized, NumericStatAggregationProcedureTest, |
| MakeSuite({ |
| {.name = "Increasing", |
| .sequence = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, |
| .sum = 55, |
| .min = 1, |
| .max = 10, |
| .mean = 5, |
| .median = 5, |
| .percentile_75 = 8, |
| .percentile_99 = 10}, |
| {.name = "Negative", |
| .sequence = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10}, |
| .sum = -55, |
| .min = -10, |
| .max = -1, |
| .mean = -5, |
| .median = -5, |
| .percentile_75 = -3, |
| .percentile_99 = -1}, |
| {.name = "Net_Zero", |
| .sequence = {-4, -3, -2, -1, 0, 1, 2, 3, 4}, |
| .sum = 0, |
| .min = -4, |
| .max = 4, |
| .mean = 0, |
| .median = 0, |
| .percentile_75 = 2, |
| .percentile_99 = 4}, |
| {.name = "Random", |
| .sequence = |
| { |
| -96, -93, -90, -86, -75, -62, -58, -57, -56, -42, |
| -38, -33, -28, -22, -20, -5, 8, 10, 20, 21, |
| 30, 31, 32, 52, 59, 65, 66, 67, 69, 74, |
| 77, 84, 85, 87, 88, 89, 98, |
| }, |
| .sum = 351, |
| .min = -96, |
| .max = 98, |
| .mean = 9, |
| .median = 20, |
| .percentile_75 = 67, |
| .percentile_99 = 98}, |
| }), |
| TestName); |
| |
| class SumNumericStatAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<SumNumericStatAggregationProcedure> GetProcedure(uint32_t metric_id, |
| int report_index) { |
| return std::make_unique<SumNumericStatAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(SumNumericStatAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.set_integer_value(200); |
| AggregateData merged_data; |
| merged_data.set_integer_value(100); |
| |
| std::unique_ptr<SumNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsSumReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.integer_value(), 300); |
| } |
| |
| TEST_F(SumNumericStatAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<SumNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsSumReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.integer_value(), 0); |
| } |
| |
| TEST_F(SumNumericStatAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.set_integer_value(200); |
| AggregateData merged_data; |
| |
| std::unique_ptr<SumNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsSumReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.integer_value(), 200); |
| } |
| |
| TEST_F(SumNumericStatAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.set_integer_value(100); |
| |
| std::unique_ptr<SumNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsSumReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.integer_value(), 100); |
| } |
| |
| class MinNumericStatAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<MinNumericStatAggregationProcedure> GetProcedure(uint32_t metric_id, |
| int report_index) { |
| return std::make_unique<MinNumericStatAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(MinNumericStatAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.set_integer_value(-15); |
| AggregateData merged_data; |
| merged_data.set_integer_value(100); |
| |
| std::unique_ptr<MinNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMinReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_TRUE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), -15); |
| } |
| |
| TEST_F(MinNumericStatAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<MinNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMinReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_FALSE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), 0); |
| } |
| |
| TEST_F(MinNumericStatAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.set_integer_value(-15); |
| AggregateData merged_data; |
| |
| std::unique_ptr<MinNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMinReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_TRUE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), -15); |
| } |
| |
| TEST_F(MinNumericStatAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.set_integer_value(100); |
| |
| std::unique_ptr<MinNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMinReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_TRUE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), 100); |
| } |
| |
| class MaxNumericStatAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<MaxNumericStatAggregationProcedure> GetProcedure(uint32_t metric_id, |
| int report_index) { |
| return std::make_unique<MaxNumericStatAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(MaxNumericStatAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.set_integer_value(-15); |
| AggregateData merged_data; |
| merged_data.set_integer_value(100); |
| |
| std::unique_ptr<MaxNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMaxReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_TRUE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), 100); |
| } |
| |
| TEST_F(MaxNumericStatAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<MaxNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMaxReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_FALSE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), 0); |
| } |
| |
| TEST_F(MaxNumericStatAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.set_integer_value(-15); |
| AggregateData merged_data; |
| |
| std::unique_ptr<MaxNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMaxReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_TRUE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), -15); |
| } |
| |
| TEST_F(MaxNumericStatAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.set_integer_value(100); |
| |
| std::unique_ptr<MaxNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMaxReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_TRUE(merged_data.has_integer_value()); |
| EXPECT_EQ(merged_data.integer_value(), 100); |
| } |
| |
| class MeanNumericStatAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<MeanNumericStatAggregationProcedure> GetProcedure(uint32_t metric_id, |
| int report_index) { |
| return std::make_unique<MeanNumericStatAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(MeanNumericStatAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.mutable_sum_and_count()->set_count(10); |
| data.mutable_sum_and_count()->set_sum(200); |
| AggregateData merged_data; |
| merged_data.mutable_sum_and_count()->set_count(20); |
| merged_data.mutable_sum_and_count()->set_sum(100); |
| |
| std::unique_ptr<MeanNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMeanReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.sum_and_count().count(), 30); |
| EXPECT_EQ(merged_data.sum_and_count().sum(), 300); |
| } |
| |
| TEST_F(MeanNumericStatAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<MeanNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMeanReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.sum_and_count().count(), 0); |
| EXPECT_EQ(merged_data.sum_and_count().sum(), 0); |
| } |
| |
| TEST_F(MeanNumericStatAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.mutable_sum_and_count()->set_count(10); |
| data.mutable_sum_and_count()->set_sum(200); |
| AggregateData merged_data; |
| |
| std::unique_ptr<MeanNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMeanReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.sum_and_count().count(), 10); |
| EXPECT_EQ(merged_data.sum_and_count().sum(), 200); |
| } |
| |
| TEST_F(MeanNumericStatAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.mutable_sum_and_count()->set_count(20); |
| merged_data.mutable_sum_and_count()->set_sum(100); |
| |
| std::unique_ptr<MeanNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMeanReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_EQ(merged_data.sum_and_count().count(), 20); |
| EXPECT_EQ(merged_data.sum_and_count().sum(), 100); |
| } |
| |
| class MedianNumericStatAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<MedianNumericStatAggregationProcedure> GetProcedure(uint32_t metric_id, |
| int report_index) { |
| return std::make_unique<MedianNumericStatAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(MedianNumericStatAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.mutable_integer_values()->add_value(-15); |
| data.mutable_integer_values()->add_value(150); |
| AggregateData merged_data; |
| merged_data.mutable_integer_values()->add_value(100); |
| merged_data.mutable_integer_values()->add_value(10); |
| |
| std::unique_ptr<MedianNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMedianReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), UnorderedElementsAre(-15, 10, 100, 150)); |
| } |
| |
| TEST_F(MedianNumericStatAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<MedianNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMedianReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), IsEmpty()); |
| } |
| |
| TEST_F(MedianNumericStatAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.mutable_integer_values()->add_value(-15); |
| data.mutable_integer_values()->add_value(150); |
| AggregateData merged_data; |
| |
| std::unique_ptr<MedianNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMedianReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), UnorderedElementsAre(-15, 150)); |
| } |
| |
| TEST_F(MedianNumericStatAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.mutable_integer_values()->add_value(100); |
| merged_data.mutable_integer_values()->add_value(10); |
| |
| std::unique_ptr<MedianNumericStatAggregationProcedure> procedure = |
| GetProcedure(kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStatsMedianReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), UnorderedElementsAre(10, 100)); |
| } |
| |
| class PercentileNNumericStatAggregationProcedureTest : public testing::TestAggregationProcedure { |
| protected: |
| std::unique_ptr<PercentileNNumericStatAggregationProcedure> GetProcedure(uint32_t metric_id, |
| int report_index) { |
| return std::make_unique<PercentileNNumericStatAggregationProcedure>( |
| GetMetricDef(metric_id), GetReportDef(metric_id, report_index)); |
| } |
| }; |
| |
| TEST_F(PercentileNNumericStatAggregationProcedureTest, MergeAggregateDataBothSet) { |
| AggregateData data; |
| data.mutable_integer_values()->add_value(-15); |
| data.mutable_integer_values()->add_value(150); |
| AggregateData merged_data; |
| merged_data.mutable_integer_values()->add_value(100); |
| merged_data.mutable_integer_values()->add_value(10); |
| |
| std::unique_ptr<PercentileNNumericStatAggregationProcedure> procedure = GetProcedure( |
| kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStats99thPercentileReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), UnorderedElementsAre(-15, 10, 100, 150)); |
| } |
| |
| TEST_F(PercentileNNumericStatAggregationProcedureTest, MergeAggregateDataNeitherSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| |
| std::unique_ptr<PercentileNNumericStatAggregationProcedure> procedure = GetProcedure( |
| kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStats99thPercentileReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), IsEmpty()); |
| } |
| |
| TEST_F(PercentileNNumericStatAggregationProcedureTest, MergeAggregateDataFromSet) { |
| AggregateData data; |
| data.mutable_integer_values()->add_value(-15); |
| data.mutable_integer_values()->add_value(150); |
| AggregateData merged_data; |
| |
| std::unique_ptr<PercentileNNumericStatAggregationProcedure> procedure = GetProcedure( |
| kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStats99thPercentileReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), UnorderedElementsAre(-15, 150)); |
| } |
| |
| TEST_F(PercentileNNumericStatAggregationProcedureTest, MergeAggregateDataToSet) { |
| AggregateData data; |
| AggregateData merged_data; |
| merged_data.mutable_integer_values()->add_value(100); |
| merged_data.mutable_integer_values()->add_value(10); |
| |
| std::unique_ptr<PercentileNNumericStatAggregationProcedure> procedure = GetProcedure( |
| kIntegerMetricMetricId, kIntegerMetricHourlyValueNumericStats99thPercentileReportIndex); |
| procedure->MergeAggregateData(&merged_data, data); |
| |
| EXPECT_THAT(merged_data.integer_values().value(), UnorderedElementsAre(10, 100)); |
| } |
| |
| } // namespace cobalt::local_aggregation |