// Copyright 2018 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 #include #include #include #include #include namespace cobalt_client { namespace { bool TestLocal() { BEGIN_TEST; MetricOptions options; options.SetMode(MetricOptions::Mode::kLocal); ASSERT_TRUE(options.IsLocal()); ASSERT_FALSE(options.IsRemote()); ASSERT_FALSE(options.IsLazy()); END_TEST; } bool TestRemote() { BEGIN_TEST; MetricOptions options; options.SetMode(MetricOptions::Mode::kRemote); EXPECT_TRUE(options.IsRemote()); EXPECT_FALSE(options.IsLocal()); EXPECT_FALSE(options.IsLazy()); END_TEST; } bool TestLocalAndRemote() { BEGIN_TEST; MetricOptions options; options.SetMode(MetricOptions::Mode::kRemoteAndLocal); EXPECT_TRUE(options.IsRemote()); EXPECT_TRUE(options.IsLocal()); EXPECT_FALSE(options.IsLazy()); END_TEST; } bool TestLazy() { BEGIN_TEST; MetricOptions options; options.SetMode(MetricOptions::Mode::kLazy); EXPECT_TRUE(options.IsLazy()); EXPECT_FALSE(options.IsRemote()); EXPECT_FALSE(options.IsLocal()); END_TEST; } bool TestMakeExponentialOptions() { BEGIN_TEST; HistogramOptions options = HistogramOptions::CustomizedExponential( /*bucket_count*/ 3, /*base*/ 4, /*scalar*/ 2, /*min*/ -10); ASSERT_EQ(options.base, 4); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, -12); ASSERT_EQ(options.type, HistogramOptions::Type::kExponential); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestMakeExponentialOptionsMaxOnly() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Exponential( /*bucket_count*/ 3, /*max*/ 14); ASSERT_EQ(options.base, 2); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, -2); // We should be greater than the predecessor of max_value, // which means that our max would fit in the overflow bucket. ASSERT_LT(nextafter(options.max_value, 0), 24); ASSERT_EQ(options.type, HistogramOptions::Type::kExponential); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestMakeExponentialOptionsMaxOnly2() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Exponential( /*bucket_count*/ 12, /*max*/ (4096 - 1) * 10); ASSERT_EQ(options.base, 2); // We scale by 11, instead of 10, because 12 buckets // can represent at mos 2^12 -1 = 4095, which would // leave 4096 in the overflow bucket. ASSERT_EQ(options.scalar, 10); ASSERT_EQ(options.offset, -10); // We should be greater than the predecessor of max_value, // which means that our max would fit in the overflow bucket. ASSERT_LT(nextafter(options.max_value, 0), 40950); ASSERT_EQ(options.type, HistogramOptions::Type::kExponential); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestMakeExponentialOptionsMinAndMaxOnly() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Exponential( /*bucket_count*/ 3, /*min*/ 10, /*max*/ 24); ASSERT_EQ(options.base, 2); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, 8); ASSERT_LT(nextafter(options.max_value, 0), 24); ASSERT_EQ(options.type, HistogramOptions::Type::kExponential); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestMakeExponentialOptionsMaxContainedInLastBucket() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Exponential( /*bucket_count*/ 3, /*min*/ 10, /*max*/ 23); ASSERT_EQ(options.base, 2); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, 8); // |max_value| should be greater than our max, which means that // our max fits in the last non overflow bucket. ASSERT_GT(options.max_value, 23); ASSERT_EQ(options.type, HistogramOptions::Type::kExponential); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestExponentialInvalidBase() { BEGIN_TEST; HistogramOptions options = HistogramOptions::CustomizedExponential( /*bucket_count*/ 1, /*base*/ 0, /*scalar*/ 2, /*min*/ -10); ASSERT_FALSE(options.IsValid()); END_TEST; } bool TestExponentialInvalidScalar() { BEGIN_TEST; HistogramOptions options = HistogramOptions::CustomizedExponential( /*bucket_count*/ 1, /*base*/ 1, /*scalar*/ 0, /*min*/ -10); ASSERT_FALSE(options.IsValid()); END_TEST; } // Verify correct buckect assignment along the boundaries and points within the bucket for // exponential bucket width. bool TestExponentialMap() { BEGIN_TEST; // This generates the following histogram: // | | | | | | // -inf 5 8 14 26 +inf HistogramOptions options = HistogramOptions::CustomizedExponential( /*bucket_count*/ 3, /*base*/ 2, /*scalar*/ 3, /*min*/ 5); // Bucket count differs in 2, due to underflow and overflow additional buckets. EXPECT_EQ(options.map_fn(/*value*/ 4, /*bucket_count*/ 5, options), 0); EXPECT_EQ(options.map_fn(nextafter(5, 4), 5, options), 0); EXPECT_EQ(options.map_fn(5, 5, options), 1); EXPECT_EQ(options.map_fn(7.5, 5, options), 1); EXPECT_EQ(options.map_fn(nextafter(8, 7), 5, options), 1); EXPECT_EQ(options.map_fn(8, 5, options), 2); EXPECT_EQ(options.map_fn(12, 5, options), 2); EXPECT_EQ(options.map_fn(nextafter(12, 11), 5, options), 2); EXPECT_EQ(options.map_fn(14, 5, options), 3); EXPECT_EQ(options.map_fn(18, 5, options), 3); EXPECT_EQ(options.map_fn(nextafter(26, 25), 5, options), 3); EXPECT_EQ(options.map_fn(26, 5, options), 4); END_TEST; } bool TestExponentialReverseMap() { BEGIN_TEST; // This generates the following histogram: // | | | | | | // -inf 5 8 14 26 +inf HistogramOptions options = HistogramOptions::CustomizedExponential( /*bucket_count*/ 3, /*base*/ 2, /*scalar*/ 3, /*min*/ 5); EXPECT_EQ(options.reverse_map_fn(/*bucket_index*/ 0, 3, options), -DBL_MAX); // Bucket count differs in 2, due to underflow and overflow additional buckets. EXPECT_EQ(options.reverse_map_fn(1, 5, options), 5); EXPECT_EQ(options.reverse_map_fn(2, 5, options), 8); EXPECT_EQ(options.reverse_map_fn(3, 5, options), 14); EXPECT_EQ(options.reverse_map_fn(4, 5, options), 26); END_TEST; } bool TestMakeLinearOptions() { BEGIN_TEST; HistogramOptions options = HistogramOptions::CustomizedLinear(/*bucket_count*/ 3, /*scalar*/ 2, /*min*/ -10); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, -10); ASSERT_EQ(options.type, HistogramOptions::Type::kLinear); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); ASSERT_TRUE(options.IsValid()); END_TEST; } bool TestMakeLinearOptionsMaxOnly() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Linear(/*bucket_count*/ 3, /*max*/ 15); ASSERT_EQ(options.scalar, 5); ASSERT_EQ(options.offset, 0); ASSERT_EQ(options.type, HistogramOptions::Type::kLinear); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestMakeLinearOptionsMinAndMaxOnly() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Linear(/*bucket_count*/ 3, /*min*/ 9, /*max*/ 15); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, 9); ASSERT_EQ(options.type, HistogramOptions::Type::kLinear); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestMakeLinearOptionsMaxContainedInLastBucket() { BEGIN_TEST; HistogramOptions options = HistogramOptions::Linear(/*bucket_count*/ 3, /*min*/ 9, /*max*/ 14); ASSERT_EQ(options.scalar, 2); ASSERT_EQ(options.offset, 9); ASSERT_GT(options.max_value, 14); ASSERT_EQ(options.type, HistogramOptions::Type::kLinear); ASSERT_TRUE(options.map_fn); ASSERT_NOT_NULL(options.map_fn); ASSERT_NOT_NULL(options.reverse_map_fn); END_TEST; } bool TestLinearInvalidScalar() { BEGIN_TEST; HistogramOptions options = HistogramOptions::CustomizedLinear(/*bucket_count*/ 1, /*scalar*/ 0, /*min*/ -10); ASSERT_FALSE(options.IsValid()); END_TEST; } // Verify correct bucket assignment along the boundaries and points within the bucket for // linear bucket width. bool TestLinearMap() { BEGIN_TEST; // This generates the following histogram: // | | | | | | // -inf -10 -8 -6 -4 +inf HistogramOptions options = HistogramOptions::CustomizedLinear(/*bucket_count*/ 3, /*scalar*/ 2, /*min*/ -10); // bucket count differs in 2 due to underflow and overflow additional buckets. EXPECT_EQ(options.map_fn(/*value*/ -15, 5, options), 0); EXPECT_EQ(options.map_fn(nextafter(-10.0, -11), 5, options), 0); EXPECT_EQ(options.map_fn(-10.0, 5, options), 1); EXPECT_EQ(options.map_fn(-9.0, 5, options), 1); EXPECT_EQ(options.map_fn(-8.0, 5, options), 2); EXPECT_EQ(options.map_fn(-7.0, 5, options), 2); EXPECT_EQ(options.map_fn(-6.0, 5, options), 3); EXPECT_EQ(options.map_fn(-5.0, 5, options), 3); EXPECT_EQ(options.map_fn(nexttoward(-4.0, -5.0), 5, options), 3); EXPECT_EQ(options.map_fn(-4.0, 5, options), 4); END_TEST; } bool TestLinearReverseMap() { BEGIN_TEST; // This generates the following histogram: // | | | | | | // -inf -10 -8 -6 -4 +inf HistogramOptions options = HistogramOptions::CustomizedLinear(/*bucket_count*/ 3, /*scalar*/ 2, /*min*/ -10); // bucket count differs in 2 due to underflow and overflow additional buckets. EXPECT_EQ(options.reverse_map_fn(/*bucket_index*/ 0, 3, options), -DBL_MAX); EXPECT_EQ(options.reverse_map_fn(1, 5, options), -10); EXPECT_EQ(options.reverse_map_fn(2, 5, options), -8); EXPECT_EQ(options.reverse_map_fn(3, 5, options), -6); EXPECT_EQ(options.reverse_map_fn(4, 5, options), -4); END_TEST; } BEGIN_TEST_CASE(MetricOptionsTest) RUN_TEST(TestLocal) RUN_TEST(TestRemote) RUN_TEST(TestLocalAndRemote) RUN_TEST(TestLazy) END_TEST_CASE(MetricOptionsTest); BEGIN_TEST_CASE(HistogramOptionsTest) RUN_TEST(TestMakeExponentialOptions) RUN_TEST(TestMakeExponentialOptionsMaxOnly) RUN_TEST(TestMakeExponentialOptionsMaxOnly2) RUN_TEST(TestMakeExponentialOptionsMinAndMaxOnly) RUN_TEST(TestMakeExponentialOptionsMaxContainedInLastBucket) RUN_TEST(TestExponentialInvalidBase) RUN_TEST(TestExponentialInvalidScalar) RUN_TEST(TestExponentialMap) RUN_TEST(TestExponentialReverseMap) RUN_TEST(TestMakeLinearOptions) RUN_TEST(TestMakeLinearOptionsMaxOnly) RUN_TEST(TestMakeLinearOptionsMinAndMaxOnly) RUN_TEST(TestMakeLinearOptionsMaxContainedInLastBucket) RUN_TEST(TestLinearInvalidScalar) RUN_TEST(TestLinearMap) RUN_TEST(TestLinearReverseMap) END_TEST_CASE(HistogramOptionsTest) } // namespace } // namespace cobalt_client