| // 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 |