blob: 9e096efbf11ecca114f06cdfc10da84a69bbf967 [file] [log] [blame]
// 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