blob: 7ada64c470e3ccbbbd414c55cf3d486abe3195ba [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/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