|  | /* | 
|  | *  Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  | #include "api/test/metrics/metrics_logger.h" | 
|  |  | 
|  | #include <map> | 
|  | #include <optional> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "api/numerics/samples_stats_counter.h" | 
|  | #include "api/test/metrics/metric.h" | 
|  | #include "api/units/timestamp.h" | 
|  | #include "system_wrappers/include/clock.h" | 
|  | #include "test/gmock.h" | 
|  | #include "test/gtest.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace test { | 
|  | namespace { | 
|  |  | 
|  | using ::testing::Eq; | 
|  | using ::testing::IsEmpty; | 
|  | using ::testing::SizeIs; | 
|  |  | 
|  | std::map<std::string, std::string> DefaultMetadata() { | 
|  | return std::map<std::string, std::string>{{"key", "value"}}; | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, LogSingleValueMetricRecordsMetric) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | logger.LogSingleValueMetric( | 
|  | "metric_name", "test_case_name", | 
|  | /*value=*/10, Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | std::map<std::string, std::string>{{"key", "value"}}); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(1)); | 
|  | const Metric& metric = metrics[0]; | 
|  | EXPECT_THAT(metric.name, Eq("metric_name")); | 
|  | EXPECT_THAT(metric.test_case, Eq("test_case_name")); | 
|  | EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); | 
|  | EXPECT_THAT(metric.improvement_direction, | 
|  | Eq(ImprovementDirection::kBiggerIsBetter)); | 
|  | EXPECT_THAT(metric.metric_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"key", "value"}})); | 
|  | ASSERT_THAT(metric.time_series.samples, SizeIs(1)); | 
|  | EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); | 
|  | EXPECT_THAT(metric.time_series.samples[0].sample_metadata, | 
|  | Eq(std::map<std::string, std::string>{})); | 
|  | ASSERT_THAT(metric.stats.mean, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metric.stats.stddev, std::nullopt); | 
|  | ASSERT_THAT(metric.stats.min, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metric.stats.max, std::optional<double>(10.0)); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, LogMetricWithSamplesStatsCounterRecordsMetric) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  |  | 
|  | SamplesStatsCounter values; | 
|  | values.AddSample(SamplesStatsCounter::StatsSample{ | 
|  | .value = 10, | 
|  | .time = Clock::GetRealTimeClock()->CurrentTime(), | 
|  | .metadata = | 
|  | std::map<std::string, std::string>{{"point_key1", "value1"}}}); | 
|  | values.AddSample(SamplesStatsCounter::StatsSample{ | 
|  | .value = 20, | 
|  | .time = Clock::GetRealTimeClock()->CurrentTime(), | 
|  | .metadata = | 
|  | std::map<std::string, std::string>{{"point_key2", "value2"}}}); | 
|  | logger.LogMetric("metric_name", "test_case_name", values, Unit::kMilliseconds, | 
|  | ImprovementDirection::kBiggerIsBetter, | 
|  | std::map<std::string, std::string>{{"key", "value"}}); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(1)); | 
|  | const Metric& metric = metrics[0]; | 
|  | EXPECT_THAT(metric.name, Eq("metric_name")); | 
|  | EXPECT_THAT(metric.test_case, Eq("test_case_name")); | 
|  | EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); | 
|  | EXPECT_THAT(metric.improvement_direction, | 
|  | Eq(ImprovementDirection::kBiggerIsBetter)); | 
|  | EXPECT_THAT(metric.metric_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"key", "value"}})); | 
|  | ASSERT_THAT(metric.time_series.samples, SizeIs(2)); | 
|  | EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); | 
|  | EXPECT_THAT(metric.time_series.samples[0].sample_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"point_key1", "value1"}})); | 
|  | EXPECT_THAT(metric.time_series.samples[1].value, Eq(20.0)); | 
|  | EXPECT_THAT(metric.time_series.samples[1].sample_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"point_key2", "value2"}})); | 
|  | ASSERT_THAT(metric.stats.mean, std::optional<double>(15.0)); | 
|  | ASSERT_THAT(metric.stats.stddev, std::optional<double>(5.0)); | 
|  | ASSERT_THAT(metric.stats.min, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metric.stats.max, std::optional<double>(20.0)); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, | 
|  | LogMetricWithEmptySamplesStatsCounterRecordsEmptyMetric) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | SamplesStatsCounter values; | 
|  | logger.LogMetric("metric_name", "test_case_name", values, Unit::kUnitless, | 
|  | ImprovementDirection::kBiggerIsBetter, DefaultMetadata()); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(1)); | 
|  | EXPECT_THAT(metrics[0].name, Eq("metric_name")); | 
|  | EXPECT_THAT(metrics[0].test_case, Eq("test_case_name")); | 
|  | EXPECT_THAT(metrics[0].time_series.samples, IsEmpty()); | 
|  | ASSERT_THAT(metrics[0].stats.mean, Eq(std::nullopt)); | 
|  | ASSERT_THAT(metrics[0].stats.stddev, Eq(std::nullopt)); | 
|  | ASSERT_THAT(metrics[0].stats.min, Eq(std::nullopt)); | 
|  | ASSERT_THAT(metrics[0].stats.max, Eq(std::nullopt)); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, LogMetricWithStatsRecordsMetric) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20}; | 
|  | logger.LogMetric("metric_name", "test_case_name", metric_stats, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | std::map<std::string, std::string>{{"key", "value"}}); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(1)); | 
|  | const Metric& metric = metrics[0]; | 
|  | EXPECT_THAT(metric.name, Eq("metric_name")); | 
|  | EXPECT_THAT(metric.test_case, Eq("test_case_name")); | 
|  | EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); | 
|  | EXPECT_THAT(metric.improvement_direction, | 
|  | Eq(ImprovementDirection::kBiggerIsBetter)); | 
|  | EXPECT_THAT(metric.metric_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"key", "value"}})); | 
|  | ASSERT_THAT(metric.time_series.samples, IsEmpty()); | 
|  | ASSERT_THAT(metric.stats.mean, std::optional<double>(15.0)); | 
|  | ASSERT_THAT(metric.stats.stddev, std::optional<double>(5.0)); | 
|  | ASSERT_THAT(metric.stats.min, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metric.stats.max, std::optional<double>(20.0)); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, LogSingleValueMetricRecordsMultipleMetrics) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  |  | 
|  | logger.LogSingleValueMetric("metric_name1", "test_case_name1", | 
|  | /*value=*/10, Unit::kMilliseconds, | 
|  | ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  | logger.LogSingleValueMetric("metric_name2", "test_case_name2", | 
|  | /*value=*/10, Unit::kMilliseconds, | 
|  | ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(2)); | 
|  | EXPECT_THAT(metrics[0].name, Eq("metric_name1")); | 
|  | EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); | 
|  | EXPECT_THAT(metrics[1].name, Eq("metric_name2")); | 
|  | EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, | 
|  | LogMetricWithSamplesStatsCounterRecordsMultipleMetrics) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | SamplesStatsCounter values; | 
|  | values.AddSample(SamplesStatsCounter::StatsSample{ | 
|  | .value = 10, | 
|  | .time = Clock::GetRealTimeClock()->CurrentTime(), | 
|  | .metadata = DefaultMetadata()}); | 
|  | values.AddSample(SamplesStatsCounter::StatsSample{ | 
|  | .value = 20, | 
|  | .time = Clock::GetRealTimeClock()->CurrentTime(), | 
|  | .metadata = DefaultMetadata()}); | 
|  |  | 
|  | logger.LogMetric("metric_name1", "test_case_name1", values, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  | logger.LogMetric("metric_name2", "test_case_name2", values, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(2)); | 
|  | EXPECT_THAT(metrics[0].name, Eq("metric_name1")); | 
|  | EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); | 
|  | EXPECT_THAT(metrics[1].name, Eq("metric_name2")); | 
|  | EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, LogMetricWithStatsRecordsMultipleMetrics) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20}; | 
|  |  | 
|  | logger.LogMetric("metric_name1", "test_case_name1", metric_stats, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  | logger.LogMetric("metric_name2", "test_case_name2", metric_stats, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(2)); | 
|  | EXPECT_THAT(metrics[0].name, Eq("metric_name1")); | 
|  | EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); | 
|  | EXPECT_THAT(metrics[1].name, Eq("metric_name2")); | 
|  | EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, | 
|  | LogMetricThroughtAllMethodsAccumulateAllMetrics) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | SamplesStatsCounter values; | 
|  | values.AddSample(SamplesStatsCounter::StatsSample{ | 
|  | .value = 10, | 
|  | .time = Clock::GetRealTimeClock()->CurrentTime(), | 
|  | .metadata = DefaultMetadata()}); | 
|  | values.AddSample(SamplesStatsCounter::StatsSample{ | 
|  | .value = 20, | 
|  | .time = Clock::GetRealTimeClock()->CurrentTime(), | 
|  | .metadata = DefaultMetadata()}); | 
|  | Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20}; | 
|  |  | 
|  | logger.LogSingleValueMetric("metric_name1", "test_case_name1", | 
|  | /*value=*/10, Unit::kMilliseconds, | 
|  | ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  | logger.LogMetric("metric_name2", "test_case_name2", values, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  | logger.LogMetric("metric_name3", "test_case_name3", metric_stats, | 
|  | Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | DefaultMetadata()); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics.size(), Eq(3lu)); | 
|  | EXPECT_THAT(metrics[0].name, Eq("metric_name1")); | 
|  | EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); | 
|  | EXPECT_THAT(metrics[1].name, Eq("metric_name2")); | 
|  | EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); | 
|  | EXPECT_THAT(metrics[2].name, Eq("metric_name3")); | 
|  | EXPECT_THAT(metrics[2].test_case, Eq("test_case_name3")); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, AccumulatedMetricsReturnedInCollectedMetrics) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | logger.GetMetricsAccumulator()->AddSample( | 
|  | "metric_name", "test_case_name", | 
|  | /*value=*/10, Timestamp::Seconds(1), | 
|  | /*point_metadata=*/std::map<std::string, std::string>{{"key", "value"}}); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(1)); | 
|  | const Metric& metric = metrics[0]; | 
|  | EXPECT_THAT(metric.name, Eq("metric_name")); | 
|  | EXPECT_THAT(metric.test_case, Eq("test_case_name")); | 
|  | EXPECT_THAT(metric.unit, Eq(Unit::kUnitless)); | 
|  | EXPECT_THAT(metric.improvement_direction, | 
|  | Eq(ImprovementDirection::kNeitherIsBetter)); | 
|  | EXPECT_THAT(metric.metric_metadata, IsEmpty()); | 
|  | ASSERT_THAT(metric.time_series.samples, SizeIs(1)); | 
|  | EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); | 
|  | EXPECT_THAT(metric.time_series.samples[0].timestamp, | 
|  | Eq(Timestamp::Seconds(1))); | 
|  | EXPECT_THAT(metric.time_series.samples[0].sample_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"key", "value"}})); | 
|  | ASSERT_THAT(metric.stats.mean, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metric.stats.stddev, std::optional<double>(0.0)); | 
|  | ASSERT_THAT(metric.stats.min, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metric.stats.max, std::optional<double>(10.0)); | 
|  | } | 
|  |  | 
|  | TEST(DefaultMetricsLoggerTest, | 
|  | AccumulatedMetricsReturnedTogetherWithLoggedMetrics) { | 
|  | DefaultMetricsLogger logger(Clock::GetRealTimeClock()); | 
|  | logger.LogSingleValueMetric( | 
|  | "metric_name1", "test_case_name1", | 
|  | /*value=*/10, Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, | 
|  | std::map<std::string, std::string>{{"key_m", "value_m"}}); | 
|  | logger.GetMetricsAccumulator()->AddSample( | 
|  | "metric_name2", "test_case_name2", | 
|  | /*value=*/10, Timestamp::Seconds(1), | 
|  | /*point_metadata=*/ | 
|  | std::map<std::string, std::string>{{"key_s", "value_s"}}); | 
|  |  | 
|  | std::vector<Metric> metrics = logger.GetCollectedMetrics(); | 
|  | ASSERT_THAT(metrics, SizeIs(2)); | 
|  | EXPECT_THAT(metrics[0].name, Eq("metric_name2")); | 
|  | EXPECT_THAT(metrics[0].test_case, Eq("test_case_name2")); | 
|  | EXPECT_THAT(metrics[0].unit, Eq(Unit::kUnitless)); | 
|  | EXPECT_THAT(metrics[0].improvement_direction, | 
|  | Eq(ImprovementDirection::kNeitherIsBetter)); | 
|  | EXPECT_THAT(metrics[0].metric_metadata, IsEmpty()); | 
|  | ASSERT_THAT(metrics[0].time_series.samples, SizeIs(1)); | 
|  | EXPECT_THAT(metrics[0].time_series.samples[0].value, Eq(10.0)); | 
|  | EXPECT_THAT(metrics[0].time_series.samples[0].timestamp, | 
|  | Eq(Timestamp::Seconds(1))); | 
|  | EXPECT_THAT(metrics[0].time_series.samples[0].sample_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"key_s", "value_s"}})); | 
|  | ASSERT_THAT(metrics[0].stats.mean, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metrics[0].stats.stddev, std::optional<double>(0.0)); | 
|  | ASSERT_THAT(metrics[0].stats.min, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metrics[0].stats.max, std::optional<double>(10.0)); | 
|  | EXPECT_THAT(metrics[1].name, Eq("metric_name1")); | 
|  | EXPECT_THAT(metrics[1].test_case, Eq("test_case_name1")); | 
|  | EXPECT_THAT(metrics[1].unit, Eq(Unit::kMilliseconds)); | 
|  | EXPECT_THAT(metrics[1].improvement_direction, | 
|  | Eq(ImprovementDirection::kBiggerIsBetter)); | 
|  | EXPECT_THAT(metrics[1].metric_metadata, | 
|  | Eq(std::map<std::string, std::string>{{"key_m", "value_m"}})); | 
|  | ASSERT_THAT(metrics[1].time_series.samples, SizeIs(1)); | 
|  | EXPECT_THAT(metrics[1].time_series.samples[0].value, Eq(10.0)); | 
|  | EXPECT_THAT(metrics[1].time_series.samples[0].sample_metadata, | 
|  | Eq(std::map<std::string, std::string>{})); | 
|  | ASSERT_THAT(metrics[1].stats.mean, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metrics[1].stats.stddev, std::nullopt); | 
|  | ASSERT_THAT(metrics[1].stats.min, std::optional<double>(10.0)); | 
|  | ASSERT_THAT(metrics[1].stats.max, std::optional<double>(10.0)); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace test | 
|  | }  // namespace webrtc |