// Copyright 2017 Google Inc. All Rights Reserved. // // Unit tests for EventMetric #include "event_metric.h" #include "metric_publisher.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "scoped_ptr.h" using testing::IsNull; using testing::NotNull; namespace wvcdm { namespace metrics { class MockEventMetricNotification : public MetricNotification { public: MOCK_METHOD2(UpdateString, void(const std::string& metric_id, const std::string& value)); MOCK_METHOD2(UpdateInt32, void(const std::string& metric_id, int32_t value)); MOCK_METHOD2(UpdateInt64, void(const std::string& metric_id, int64_t value)); MOCK_METHOD2(UpdateDouble, void(const std::string& metric_id, double value)); }; class EventMetricTest : public ::testing::Test { public: void SetUp() { mock_notification_.reset(new MockEventMetricNotification()); } protected: template const std::map GetValueMap( const wvcdm::metrics::EventMetric& metric) { return metric.value_map_; } scoped_ptr mock_notification_; }; TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) { wvcdm::metrics::EventMetric<> metric("no/fields/metric"); metric.Record(10LL); metric.Record(10LL); std::map value_map = GetValueMap(metric); ASSERT_EQ(1, GetValueMap(metric).size()); EXPECT_EQ(2, value_map.begin()->second->Count()); EXPECT_EQ("", value_map.begin()->first); } TEST_F(EventMetricTest, NoFieldsSuccessWithCallback) { wvcdm::metrics::EventMetric<> metric("no/fields/metric"); EXPECT_CALL(*mock_notification_, UpdateInt64("no/fields/metric/count", 1.0)); EXPECT_CALL(*mock_notification_, UpdateDouble("no/fields/metric/mean", 10.0)); EXPECT_CALL(*mock_notification_, UpdateDouble("no/fields/metric/variance", 0.0)); EXPECT_CALL(*mock_notification_, UpdateDouble("no/fields/metric/min", 10.0)); EXPECT_CALL(*mock_notification_, UpdateDouble("no/fields/metric/max", 10.0)); metric.Record(10); metric.Publish(mock_notification_.get()); std::map value_map = GetValueMap(metric); ASSERT_EQ(1, GetValueMap(metric).size()); EXPECT_EQ(1, value_map.begin()->second->Count()); EXPECT_EQ("", value_map.begin()->first); } TEST_F(EventMetricTest, OneFieldSuccessNoCallback) { wvcdm::metrics::EventMetric metric( "single/fields/metric", "error_code"); metric.Record(10LL, 7); metric.Record(11LL, 13); metric.Record(12LL, 13); std::map value_map = GetValueMap(metric); ASSERT_EQ(2, GetValueMap(metric).size()); // Verify both instances. // TODO(blueeyes): Export MakeFieldNameString so it can be used here. Distribution* distribution_error_7 = value_map["{error_code:7}"]; Distribution* distribution_error_13 = value_map["{error_code:13}"]; ASSERT_THAT(distribution_error_7, NotNull()); ASSERT_THAT(distribution_error_13, NotNull()); EXPECT_EQ(1, distribution_error_7->Count()); EXPECT_EQ(2, distribution_error_13->Count()); } TEST_F(EventMetricTest, TwoFieldsSuccess) { wvcdm::metrics::EventMetric metric( "two/fields/metric", "error_code", "size"); metric.Record(1, 7, 23); metric.Record(2, 7, 29); metric.Record(3, 11, 23); metric.Record(4, 11, 29); metric.Record(5, 7, 23); std::map value_map = GetValueMap(metric); ASSERT_EQ(4, GetValueMap(metric).size()); // Verify all instances. Distribution* distribution_7_23 = value_map["{error_code:7&size:23}"]; Distribution* distribution_7_29 = value_map["{error_code:7&size:29}"]; Distribution* distribution_11_23 = value_map["{error_code:11&size:23}"]; Distribution* distribution_11_29 = value_map["{error_code:11&size:29}"]; ASSERT_THAT(distribution_7_23, NotNull()); ASSERT_THAT(distribution_7_29, NotNull()); ASSERT_THAT(distribution_11_23, NotNull()); ASSERT_THAT(distribution_11_29, NotNull()); EXPECT_EQ(2, distribution_7_23->Count()); EXPECT_EQ(1, distribution_7_29->Count()); EXPECT_EQ(1, distribution_11_23->Count()); EXPECT_EQ(1, distribution_11_29->Count()); // Verify that a non-existent distribution returns nullptr. Distribution* null_distribution = value_map["error_code:1,size:1"]; ASSERT_THAT(null_distribution, IsNull()); } TEST_F(EventMetricTest, TwoFieldsSuccessWithCallback) { wvcdm::metrics::EventMetric metric("two/fields/metric", "error_code", "pow2_size"); // Callbacks from second record operation. EXPECT_CALL( *mock_notification_, UpdateInt64("two/fields/metric/count{error_code:11&pow2_size:16}", 2.0)); EXPECT_CALL( *mock_notification_, UpdateDouble("two/fields/metric/mean{error_code:11&pow2_size:16}", 3.5)); EXPECT_CALL( *mock_notification_, UpdateDouble("two/fields/metric/variance{error_code:11&pow2_size:16}", 0.25)); EXPECT_CALL( *mock_notification_, UpdateDouble("two/fields/metric/min{error_code:11&pow2_size:16}", 3.0)); EXPECT_CALL( *mock_notification_, UpdateDouble("two/fields/metric/max{error_code:11&pow2_size:16}", 4.0)); metric.Record(3, 11, Pow2Bucket(29)); metric.Record(4, 11, Pow2Bucket(29)); metric.Publish(mock_notification_.get()); } TEST_F(EventMetricTest, ThreeFieldsSuccess) { wvcdm::metrics::EventMetric metric( "three/fields/metric", "error_code", "size", "woke up happy"); metric.Record(10LL, 7, 13, false); std::map value_map = GetValueMap(metric); ASSERT_EQ(1, GetValueMap(metric).size()); EXPECT_EQ("{error_code:7&size:13&woke up happy:0}", value_map.begin()->first); EXPECT_EQ(1, value_map.begin()->second->Count()); } TEST_F(EventMetricTest, FourFieldsSuccess) { wvcdm::metrics::EventMetric metric( "Four/fields/metric", "error_code", "size", "woke up happy", "horoscope"); metric.Record(10LL, 7, 13, true, "find your true love"); std::map value_map = GetValueMap(metric); ASSERT_EQ(1, GetValueMap(metric).size()); EXPECT_EQ( "{error_code:7&size:13&woke up happy:1&horoscope:find your true love}", value_map.begin()->first); EXPECT_EQ(1, value_map.begin()->second->Count()); } TEST_F(EventMetricTest, Pow2BucketTest) { std::stringstream value; value << Pow2Bucket(1); EXPECT_EQ("1", value.str()); value.str(""); value << Pow2Bucket(0); EXPECT_EQ("0", value.str()); value.str(""); value << Pow2Bucket(2); EXPECT_EQ("2", value.str()); value.str(""); value << Pow2Bucket(0xFFFFFFFFu); EXPECT_EQ("2147483648", value.str()); value.str(""); value << Pow2Bucket(0x80000000u); EXPECT_EQ("2147483648", value.str()); value.str(""); value << Pow2Bucket(0x7FFFFFFF); EXPECT_EQ("1073741824", value.str()); } } // namespace metrics } // namespace wvcdm