blob: 0063af968d070217773ae30e3e97a657b049b407 [file] [log] [blame]
#include "src/lib/privacy/private_index_decoding.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/logger/event_vector_index.h"
namespace cobalt {
namespace {
const int64_t kMinValue = -10;
const int64_t kMaxValue = 50;
const uint64_t kMaxCount = 100;
const uint64_t kNumIndexPoints = 5;
const uint64_t kMaxBucketIndex = 10;
} // namespace
class PrivateIndexDecodingTest : public testing::Test {
protected:
void SetUp() override { PrepareMetricDimensions(); }
void PrepareMetricDimensions() {
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 MaxEventVectorIndex() { return logger::GetNumEventVectors(metric_dimensions_) - 1; }
uint64_t MaxIndexForNumericValue() {
return logger::GetNumEventVectors(metric_dimensions_) * kNumIndexPoints - 1;
}
uint64_t MinIndexForCount() { return MaxIndexForNumericValue() + 1; }
uint64_t MaxIndexForCount() { return 2 * MinIndexForCount() - 1; }
uint64_t MaxIndexForHistogramBucket() {
return logger::GetNumEventVectors(metric_dimensions_) * (kMaxBucketIndex + 1) - 1;
}
uint64_t MaxIndexForHistogramBucketAndCount() {
return logger::GetNumEventVectors(metric_dimensions_) * (kMaxBucketIndex + 1) *
kNumIndexPoints -
1;
}
google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension> metric_dimensions_;
};
TEST_F(PrivateIndexDecodingTest, DecodeAsEventVectorValid) {
std::vector<uint32_t> event_vector;
// Check that the minimum private index is decoded correctly.
util::Status status = DecodePrivateIndexAsEventVector(0, metric_dimensions_, &event_vector);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
// Check that the maximum private index is decoded correctly.
status =
DecodePrivateIndexAsEventVector(MaxEventVectorIndex(), metric_dimensions_, &event_vector);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
}
TEST_F(PrivateIndexDecodingTest, DecodeAsEventVectorInvalid) {
std::vector<uint32_t> event_vector;
util::Status status =
DecodePrivateIndexAsEventVector(MaxEventVectorIndex() + 1, metric_dimensions_, &event_vector);
EXPECT_FALSE(status.ok());
}
TEST_F(PrivateIndexDecodingTest, DecodeAsIntegerValid) {
std::vector<uint32_t> event_vector;
int64_t integer_value;
// Check that the minimum private index is decoded correctly.
util::Status status = DecodePrivateIndexAsInteger(0, metric_dimensions_, kMinValue, kMaxValue,
kNumIndexPoints, &event_vector, &integer_value);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_EQ(integer_value, kMinValue);
// Check that the maximum private index is decoded correctly.
status = DecodePrivateIndexAsInteger(MaxIndexForNumericValue(), metric_dimensions_, kMinValue,
kMaxValue, kNumIndexPoints, &event_vector, &integer_value);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
EXPECT_EQ(integer_value, kMaxValue);
}
TEST_F(PrivateIndexDecodingTest, DecodeAsIntegerInvalid) {
std::vector<uint32_t> event_vector;
int64_t integer_value;
util::Status status =
DecodePrivateIndexAsInteger(MaxIndexForNumericValue() + 1, metric_dimensions_, kMinValue,
kMaxValue, kNumIndexPoints, &event_vector, &integer_value);
EXPECT_FALSE(status.ok());
}
TEST_F(PrivateIndexDecodingTest, DecodeAsDoubleValid) {
std::vector<uint32_t> event_vector;
double double_value;
// Check that the minimum private index is decoded correctly.
util::Status status = DecodePrivateIndexAsDouble(0, metric_dimensions_, kMinValue, kMaxValue,
kNumIndexPoints, &event_vector, &double_value);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_EQ(double_value, static_cast<double>(kMinValue));
// Check that an intermediate private index is decoded correctly.
// The private index (MaxEventVectorIndex() + 1) should be the first index whose |double_value| is
// larger than |kMinValue|, and its |event_vector| should be the lexicographically smallest event
// vector.
status = DecodePrivateIndexAsDouble(MaxEventVectorIndex() + 1, metric_dimensions_, kMinValue,
kMaxValue, kNumIndexPoints, &event_vector, &double_value);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_THAT(double_value,
testing::DoubleEq(kMinValue + static_cast<double>(kMaxValue - kMinValue) /
(kNumIndexPoints - 1)));
// Check that the maximum private index is decoded correctly.
status = DecodePrivateIndexAsDouble(MaxIndexForNumericValue(), metric_dimensions_, kMinValue,
kMaxValue, kNumIndexPoints, &event_vector, &double_value);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
EXPECT_EQ(double_value, static_cast<double>(kMaxValue));
}
TEST_F(PrivateIndexDecodingTest, DecodeAsDoubleInvalid) {
std::vector<uint32_t> event_vector;
double double_value;
util::Status status =
DecodePrivateIndexAsDouble(MaxIndexForNumericValue() + 1, metric_dimensions_, kMinValue,
kMaxValue, kNumIndexPoints, &event_vector, &double_value);
EXPECT_FALSE(status.ok());
}
TEST_F(PrivateIndexDecodingTest, DecodeAsSumOrCountValidSum) {
std::vector<uint32_t> event_vector;
SumOrCount sum_or_count;
// Check that the minimum private index that corresponds to sum is decoded correctly.
util::Status status =
DecodePrivateIndexAsSumOrCount(0, metric_dimensions_, kMinValue, kMaxValue, kMaxCount,
kNumIndexPoints, &event_vector, &sum_or_count);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_EQ(sum_or_count.type, SumOrCount::SUM);
EXPECT_EQ(sum_or_count.sum, kMinValue);
// Check that the maximum private index that corresponds to a sum is decoded correctly.
status = DecodePrivateIndexAsSumOrCount(MaxIndexForNumericValue(), metric_dimensions_, kMinValue,
kMaxValue, kMaxCount, kNumIndexPoints, &event_vector,
&sum_or_count);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
EXPECT_EQ(sum_or_count.type, SumOrCount::SUM);
EXPECT_EQ(sum_or_count.sum, kMaxValue);
}
TEST_F(PrivateIndexDecodingTest, DecodeAsSumOrCountValidCount) {
std::vector<uint32_t> event_vector;
SumOrCount sum_or_count;
// Check that the minimum private index that corresponds to a count is decoded correctly.
util::Status status =
DecodePrivateIndexAsSumOrCount(MinIndexForCount(), metric_dimensions_, kMinValue, kMaxValue,
kMaxCount, kNumIndexPoints, &event_vector, &sum_or_count);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_EQ(sum_or_count.type, SumOrCount::COUNT);
EXPECT_EQ(sum_or_count.count, 0u);
// Check that the maximum private index that corresponds to a count is decoded correctly.
status =
DecodePrivateIndexAsSumOrCount(MaxIndexForCount(), metric_dimensions_, kMinValue, kMaxValue,
kMaxCount, kNumIndexPoints, &event_vector, &sum_or_count);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
EXPECT_EQ(sum_or_count.type, SumOrCount::COUNT);
EXPECT_EQ(sum_or_count.count, kMaxCount);
}
TEST_F(PrivateIndexDecodingTest, DecodeAsSumOrCountInvalid) {
std::vector<uint32_t> event_vector;
SumOrCount sum_or_count;
util::Status status = DecodePrivateIndexAsSumOrCount(
MaxIndexForCount() + 1, metric_dimensions_, kMinValue, kMaxValue, kMaxCount, kNumIndexPoints,
&event_vector, &sum_or_count);
EXPECT_FALSE(status.ok());
}
TEST_F(PrivateIndexDecodingTest, DecodeAsHistogramBucketIndexValid) {
std::vector<uint32_t> event_vector;
uint32_t bucket_index;
// Check that the minimum private index is decoded correctly.
util::Status status = DecodePrivateIndexAsHistogramBucketIndex(
0, metric_dimensions_, kMaxBucketIndex, &event_vector, &bucket_index);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_EQ(bucket_index, 0u);
// Check that the maximum private index is decoded correctly.
status =
DecodePrivateIndexAsHistogramBucketIndex(MaxIndexForHistogramBucket(), metric_dimensions_,
kMaxBucketIndex, &event_vector, &bucket_index);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
EXPECT_EQ(bucket_index, kMaxBucketIndex);
}
TEST_F(PrivateIndexDecodingTest, DecodeAsHistogramBucketIndexInvalid) {
std::vector<uint32_t> event_vector;
uint32_t bucket_index;
util::Status status =
DecodePrivateIndexAsHistogramBucketIndex(MaxIndexForHistogramBucket() + 1, metric_dimensions_,
kMaxBucketIndex, &event_vector, &bucket_index);
EXPECT_FALSE(status.ok());
}
TEST_F(PrivateIndexDecodingTest, DecodeAsHistogramBucketIndexAndCountValid) {
std::vector<uint32_t> event_vector;
uint32_t bucket_index;
uint64_t bucket_count;
// Check that the minimum private index is decoded correctly.
util::Status status = DecodePrivateIndexAsHistogramBucketIndexAndCount(
0, metric_dimensions_, kMaxBucketIndex, kMaxCount, kNumIndexPoints, &event_vector,
&bucket_index, &bucket_count);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({0, 0, 0}));
EXPECT_EQ(bucket_index, 0u);
EXPECT_EQ(bucket_count, 0u);
// Check that the maximum private index is decoded correctly.
status = DecodePrivateIndexAsHistogramBucketIndexAndCount(
MaxIndexForHistogramBucketAndCount(), metric_dimensions_, kMaxBucketIndex, kMaxCount,
kNumIndexPoints, &event_vector, &bucket_index, &bucket_count);
ASSERT_TRUE(status.ok());
EXPECT_EQ(event_vector, std::vector<uint32_t>({2, 300, 10}));
EXPECT_EQ(bucket_index, kMaxBucketIndex);
EXPECT_EQ(bucket_count, kMaxCount);
}
TEST_F(PrivateIndexDecodingTest, DecodeAsHistogramBucketIndexAndCountInvalid) {
std::vector<uint32_t> event_vector;
uint32_t bucket_index;
uint64_t bucket_count;
util::Status status = DecodePrivateIndexAsHistogramBucketIndexAndCount(
MaxIndexForHistogramBucketAndCount() + 1, metric_dimensions_, kMaxBucketIndex, kMaxCount,
kNumIndexPoints, &event_vector, &bucket_index, &bucket_count);
ASSERT_FALSE(status.ok());
}
} // namespace cobalt