blob: 638aaaffd389e4b91e1c3c1105a576b09b8a1fd0 [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/logger/event_vector_index.h"
#include <gtest/gtest.h>
#include "src/registry/metric_definition.pb.h"
namespace cobalt::logger {
namespace {
std::string EventVectorAsString(const std::vector<uint32_t> &event_vector) {
std::stringstream buf;
buf << "{";
for (uint32_t event_code : event_vector) {
buf << event_code << ", ";
}
buf << "}";
return buf.str();
}
} // namespace
// Test GetNumEventCodes() when the metric dimension has no max_event_code and
// its enumerated event codes are consecutive.
TEST(GetNumEventCodesTest, ConsecutiveNoMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
(*dimension.mutable_event_codes())[0] = "dim_0";
(*dimension.mutable_event_codes())[1] = "dim_1";
(*dimension.mutable_event_codes())[2] = "dim_2";
EXPECT_EQ(GetNumEventCodes(dimension), 3u);
}
// Test GetNumEventCodes() when the metric dimension has no max_event_code and
// its enumerated event codes are not consecutive.
TEST(GetNumEventCodesTest, NotConsecutiveNoMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
(*dimension.mutable_event_codes())[0] = "dim_0";
(*dimension.mutable_event_codes())[100] = "dim_1";
(*dimension.mutable_event_codes())[200] = "dim_2";
EXPECT_EQ(GetNumEventCodes(dimension), 3u);
}
// Test GetNumEventCodes() when the metric dimension has a max_event_code.
TEST(GetNumEventCodesTest, MaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
dimension.set_max_event_code(10);
(*dimension.mutable_event_codes())[1] = "dim_0";
(*dimension.mutable_event_codes())[2] = "dim_1";
EXPECT_EQ(GetNumEventCodes(dimension), 11u);
}
// Test GetNumEventVectors with MetricDimensions which have
// consecutive and non-consecutive event codes and max_event_code.
TEST(GetNumEventVectorsTest, AllDimensionTypes) {
google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension> metric_dimensions;
auto dimension = metric_dimensions.Add();
dimension->set_dimension("dimension_consecutive");
(*dimension->mutable_event_codes())[0] = "dim_0";
(*dimension->mutable_event_codes())[1] = "dim_1";
(*dimension->mutable_event_codes())[2] = "dim_2";
dimension = metric_dimensions.Add();
dimension->set_dimension("dimension_non_consecutive");
(*dimension->mutable_event_codes())[0] = "dim_0";
(*dimension->mutable_event_codes())[100] = "dim_1";
(*dimension->mutable_event_codes())[200] = "dim_2";
(*dimension->mutable_event_codes())[300] = "dim_3";
dimension = metric_dimensions.Add();
dimension->set_dimension("dimension_max_event_code");
dimension->set_max_event_code(10);
(*dimension->mutable_event_codes())[1] = "dim_0";
(*dimension->mutable_event_codes())[2] = "dim_1";
uint64_t expected = 132;
EXPECT_EQ(GetNumEventVectors(metric_dimensions), expected);
}
// Test EventCodeToIndexForDimension() when the metric dimension has no
// max_event_code, its enumerated event codes are consecutive, and the supplied
// event code is valid. Also check that EventCodeFromIndexForDimension() gives
// us back the original event code.
TEST(EventCodeToIndexForDimensionTest, ConsecutiveNoMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
(*dimension.mutable_event_codes())[0] = "dim_0";
(*dimension.mutable_event_codes())[1] = "dim_1";
(*dimension.mutable_event_codes())[2] = "dim_2";
uint32_t event_code = 1;
uint64_t index = 1u;
auto status_or_index = EventCodeToIndexForDimension(event_code, dimension);
ASSERT_TRUE(status_or_index.ok());
EXPECT_EQ(status_or_index.ValueOrDie(), index);
auto status_or_event_code = EventCodeFromIndexForDimension(index, dimension);
ASSERT_TRUE(status_or_event_code.ok());
EXPECT_EQ(status_or_event_code.ValueOrDie(), event_code);
}
// Test EventCodeToIndexForDimension() when the metric dimension has no
// max_event_code, its enumerated event codes are not consecutive, and the
// supplied event code is valid. Also check that
// EventCodeFromIndexForDimension() gives us back the original event code.
TEST(EventCodeToIndexForDimensionTest, NotConsecutiveNoMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
(*dimension.mutable_event_codes())[0] = "dim_0";
(*dimension.mutable_event_codes())[100] = "dim_1";
(*dimension.mutable_event_codes())[200] = "dim_2";
uint32_t event_code = 100;
uint64_t index = 1u;
auto status_or_index = EventCodeToIndexForDimension(event_code, dimension);
ASSERT_TRUE(status_or_index.ok());
EXPECT_EQ(status_or_index.ValueOrDie(), index);
auto status_or_event_code = EventCodeFromIndexForDimension(index, dimension);
ASSERT_TRUE(status_or_event_code.ok());
EXPECT_EQ(status_or_event_code.ValueOrDie(), event_code);
}
// Test EventCodeToIndexForDimension() when the metric dimension has a
// max_event_code and the supplied event code is valid. Also check that
// EventCodeFromIndexForDimension() gives us back the original event code.
TEST(EventCodeToIndexForDimensionTest, MaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
dimension.set_max_event_code(10);
(*dimension.mutable_event_codes())[1] = "dim_0";
(*dimension.mutable_event_codes())[2] = "dim_1";
uint32_t event_code = 8;
uint64_t index = 8u;
auto status_or_index = EventCodeToIndexForDimension(event_code, dimension);
ASSERT_TRUE(status_or_index.ok());
EXPECT_EQ(status_or_index.ValueOrDie(), index);
auto status_or_event_code = EventCodeFromIndexForDimension(index, dimension);
ASSERT_TRUE(status_or_event_code.ok());
EXPECT_EQ(status_or_event_code.ValueOrDie(), event_code);
}
// Test that EventCodeToIndexForDimension() returns an error status when the
// metric dimension has a max_event_code and the supplied event code is too
// large.
TEST(EventCodeToIndexForDimensionTest, EventCodeLargerThanMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
dimension.set_max_event_code(10);
(*dimension.mutable_event_codes())[1] = "dim_0";
(*dimension.mutable_event_codes())[2] = "dim_1";
uint32_t event_code = 20;
auto status_or_encoded = EventCodeToIndexForDimension(event_code, dimension);
ASSERT_FALSE(status_or_encoded.ok());
}
// Test that EventCodeToIndexForDimension() returns an error status when the
// metric dimension has no max_event_code and the supplied event code is not one
// of the valid enumerated event codes.
TEST(EventCodeToIndexForDimensionTest, InvalidEventCodeNoMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
(*dimension.mutable_event_codes())[1] = "dim_0";
(*dimension.mutable_event_codes())[3] = "dim_1";
uint32_t event_code = 2;
auto status_or_index = EventCodeToIndexForDimension(event_code, dimension);
ASSERT_FALSE(status_or_index.ok());
}
// Test that EventCodeFromIndexForDimension() returns an error status when the
// metric dimension has no max_event_code and the supplied index is larger than
// the number of enumerated event codes.
TEST(EventCodeFromIndexForDimensionTest, InvalidIndexNoMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
(*dimension.mutable_event_codes())[1] = "dim_0";
(*dimension.mutable_event_codes())[3] = "dim_1";
uint64_t index = 10;
auto status_or_event_code = EventCodeFromIndexForDimension(index, dimension);
ASSERT_FALSE(status_or_event_code.ok());
}
// Test that EventCodeFromIndexForDimension() returns an error status when the
// supplied index is larger than the metric definition's max_event_code.
TEST(EventCodeFromIndexForDimensionTest, InvalidIndexMaxEventCode) {
MetricDefinition::MetricDimension dimension;
dimension.set_dimension("dimension 1");
dimension.set_max_event_code(10);
uint64_t index = 20;
auto status_or_event_code = EventCodeFromIndexForDimension(index, dimension);
ASSERT_FALSE(status_or_event_code.ok());
}
// Test EventVectorToIndex() when the supplied event vector is valid for the
// metric definition. Also check that EventVectorFromIndex() gives back the
// original event vector.
TEST(EventVectorToIndexTest, WorksWithValidEventCodes) {
MetricDefinition metric_def;
// A dimension with no max_event_code and consecutive enumerated event codes.
auto dim_0 = metric_def.add_metric_dimensions();
dim_0->set_dimension("dimension_consecutive");
(*dim_0->mutable_event_codes())[0] = "code_0";
(*dim_0->mutable_event_codes())[1] = "code_1";
(*dim_0->mutable_event_codes())[2] = "code_2";
// A dimension with no max_event_code and consecutive enumerated event codes.
auto dim_1 = metric_def.add_metric_dimensions();
dim_1->set_dimension("dimension_non_consecutive");
(*dim_1->mutable_event_codes())[0] = "code_0";
(*dim_1->mutable_event_codes())[100] = "code_1";
(*dim_1->mutable_event_codes())[200] = "code_2";
(*dim_1->mutable_event_codes())[300] = "code_3";
// The enumerated event codes from this dimension.
std::vector<uint32_t> non_consecutive_codes = {0, 100, 200, 300};
// A dimension with a max_event_code.
auto dim_2 = metric_def.add_metric_dimensions();
dim_2->set_dimension("dimension_max_event_code");
dim_2->set_max_event_code(10);
(*dim_2->mutable_event_codes())[1] = "code_0";
(*dim_2->mutable_event_codes())[2] = "code_1";
// Iterate over all valid event vectors for |metric_def|, testing
// EventVectorToIndex() and EventVectorFromIndex().
std::vector<uint32_t> event_vector = {0, 0, 0};
uint64_t expected = 0;
for (event_vector[2] = 0; event_vector[2] < uint32_t(dim_2->event_codes_size());
++event_vector[2]) {
for (uint32_t event_code_1 : non_consecutive_codes) {
event_vector[1] = event_code_1;
for (event_vector[0] = 0; event_vector[0] < uint32_t(dim_0->event_codes_size());
event_vector[0]++) {
auto status_or_index_event_vector = EventVectorToIndex(event_vector, metric_def);
ASSERT_TRUE(status_or_index_event_vector.ok());
uint64_t index = status_or_index_event_vector.ValueOrDie();
EXPECT_EQ(index, expected) << EventVectorAsString(event_vector);
auto status_or_event_code_event_vector =
EventVectorFromIndex(index, metric_def.metric_dimensions());
ASSERT_TRUE(status_or_event_code_event_vector.ok());
EXPECT_EQ(status_or_event_code_event_vector.ValueOrDie(), event_vector);
expected++;
}
}
}
}
// Check that EventVectorToIndex() returns an error status when the size of the
// supplied event vector is not equal to the number of metric dimensions.
TEST(EventVectorToIndexTest, WrongEventVectorSize) {
MetricDefinition metric_def;
auto dimension = metric_def.add_metric_dimensions();
dimension->set_dimension("dimension_consecutive");
(*dimension->mutable_event_codes())[0] = "dim_0";
(*dimension->mutable_event_codes())[1] = "dim_1";
(*dimension->mutable_event_codes())[2] = "dim_2";
dimension = metric_def.add_metric_dimensions();
dimension->set_dimension("dimension_non_consecutive");
(*dimension->mutable_event_codes())[0] = "dim_0";
(*dimension->mutable_event_codes())[100] = "dim_1";
(*dimension->mutable_event_codes())[200] = "dim_2";
(*dimension->mutable_event_codes())[300] = "dim_3";
dimension = metric_def.add_metric_dimensions();
dimension->set_dimension("dimension_max_event_code");
dimension->set_max_event_code(10);
(*dimension->mutable_event_codes())[1] = "dim_0";
(*dimension->mutable_event_codes())[2] = "dim_1";
std::vector<uint32_t> event_vector = {2, 3};
EXPECT_FALSE(EventVectorToIndex(event_vector, metric_def).ok());
}
// Check that EventVectorFromIndex() returns an error status when the supplied
// index is larger than the number of valid event vectors for the metric
// definition.
TEST(EventVectorFromIndexTest, InvalidEventVectorIndex) {
MetricDefinition metric_def;
auto dimension = metric_def.add_metric_dimensions();
dimension->set_dimension("dimension_consecutive");
(*dimension->mutable_event_codes())[0] = "dim_0";
(*dimension->mutable_event_codes())[1] = "dim_1";
(*dimension->mutable_event_codes())[2] = "dim_2";
dimension = metric_def.add_metric_dimensions();
dimension->set_dimension("dimension_non_consecutive");
(*dimension->mutable_event_codes())[0] = "dim_0";
(*dimension->mutable_event_codes())[100] = "dim_1";
(*dimension->mutable_event_codes())[200] = "dim_2";
(*dimension->mutable_event_codes())[300] = "dim_3";
dimension = metric_def.add_metric_dimensions();
dimension->set_dimension("dimension_max_event_code");
dimension->set_max_event_code(10);
(*dimension->mutable_event_codes())[1] = "dim_0";
(*dimension->mutable_event_codes())[2] = "dim_1";
// There are 132 distinct event vectors. So, 134 cannot refer to an event
// vector.
uint64_t invalid_index = 134;
EXPECT_FALSE(EventVectorFromIndex(invalid_index, metric_def.metric_dimensions()).ok());
}
} // namespace cobalt::logger