diff --git a/test/BUILD.gn b/test/BUILD.gn index 464f44f60a..4617dd0980 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -226,7 +226,6 @@ rtc_library("perf_test") { "testsupport/perf_test.h", "testsupport/perf_test_graphjson_writer.cc", "testsupport/perf_test_graphjson_writer.h", - "testsupport/perf_test_histogram_writer.cc", "testsupport/perf_test_histogram_writer.h", "testsupport/perf_test_result_writer.h", ] @@ -234,9 +233,19 @@ rtc_library("perf_test") { "../api:array_view", "../rtc_base:checks", "../rtc_base:criticalsection", + "../rtc_base:logging", "../rtc_base:rtc_numerics", "//third_party/abseil-cpp/absl/flags:flag", ] + if (rtc_enable_protobuf) { + sources += [ "testsupport/perf_test_histogram_writer.cc" ] + deps += [ + "//third_party/catapult/tracing/tracing:histogram", + "//third_party/catapult/tracing/tracing:reserved_infos", + ] + } else { + sources += [ "testsupport/perf_test_histogram_writer_no_protobuf.cc" ] + } } if (is_ios) { @@ -502,6 +511,11 @@ if (rtc_include_tests) { "testsupport/yuv_frame_writer_unittest.cc", ] + if (rtc_enable_protobuf) { + sources += [ "testsupport/perf_test_histogram_writer_unittest.cc" ] + deps += [ "//third_party/catapult/tracing/tracing:histogram" ] + } + data = test_support_unittests_resources if (is_android) { deps += [ "//testing/android/native_test:native_test_support" ] diff --git a/test/testsupport/DEPS b/test/testsupport/DEPS new file mode 100644 index 0000000000..6f6150ad30 --- /dev/null +++ b/test/testsupport/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + # Histogram C++ API, used by perf tests. + "+third_party/catapult/tracing/tracing/value" +] diff --git a/test/testsupport/perf_test.cc b/test/testsupport/perf_test.cc index eedb0c8062..ae9ce6ee1f 100644 --- a/test/testsupport/perf_test.cc +++ b/test/testsupport/perf_test.cc @@ -17,7 +17,6 @@ #include #include -#include "absl/flags/flag.h" #include "rtc_base/checks.h" #include "rtc_base/critical_section.h" #include "test/testsupport/perf_test_graphjson_writer.h" @@ -213,8 +212,8 @@ void SetPerfResultsOutput(FILE* output) { GetResultsLinePrinter().SetOutput(output); } -std::string GetPerfResultsJSON() { - return GetPerfWriter().ToJSON(); +std::string GetPerfResults() { + return GetPerfWriter().Serialize(); } void PrintPlottableResults(const std::vector& desired_graphs) { @@ -222,10 +221,10 @@ void PrintPlottableResults(const std::vector& desired_graphs) { } void WritePerfResults(const std::string& output_path) { - std::string json_results = GetPerfResultsJSON(); - std::fstream json_file(output_path, std::fstream::out); - json_file << json_results; - json_file.close(); + std::string results = GetPerfResults(); + std::fstream output(output_path, std::fstream::out); + output << results; + output.close(); } void PrintResult(const std::string& measurement, diff --git a/test/testsupport/perf_test.h b/test/testsupport/perf_test.h index 0550e44231..53de6692bb 100644 --- a/test/testsupport/perf_test.h +++ b/test/testsupport/perf_test.h @@ -15,6 +15,7 @@ #include #include +#include "absl/flags/flag.h" #include "api/array_view.h" #include "rtc_base/numerics/samples_stats_counter.h" @@ -88,9 +89,13 @@ void PrintResult(const std::string& measurement, const bool important, ImproveDirection improve_direction = ImproveDirection::kNone); -// Returns all perf results to date in a JSON string formatted as described in -// https://github.com/catapult-project/catapult/blob/master/dashboard/docs/data-format.md -std::string GetPerfResultsJSON(); +// If --write_histogram_proto_json=false, this returns all perf results to date +// in a JSON string formatted as described in dashboard/docs/data-format.md +// in https://github.com/catapult-project/catapult/blob/master/. If +// --write_histogram_proto_json=true, returns a string-encoded proto as +// described in tracing/tracing/proto/histogram.proto in +// https://github.com/catapult-project/catapult/blob/master/. +std::string GetPerfResults(); // Print into stdout plottable metrics for further post processing. // |desired_graphs| - list of metrics, that should be plotted. If empty - all @@ -98,18 +103,20 @@ std::string GetPerfResultsJSON(); // they will be skipped. void PrintPlottableResults(const std::vector& desired_graphs); -// Writes the JSON representation of the perf results returned by -// GetPerfResultsJSON() to the file in output_path. +// Call GetPerfResults() and write its output to a file. void WritePerfResults(const std::string& output_path); // By default, perf results are printed to stdout. Set the FILE* to where they // should be printing instead. void SetPerfResultsOutput(FILE* output); -// You shouldn't use this function. It's only used to test the functions above. +// Only for use by tests. void ClearPerfResults(); } // namespace test } // namespace webrtc +// Only for use by tests. +ABSL_DECLARE_FLAG(bool, write_histogram_proto_json); + #endif // TEST_TESTSUPPORT_PERF_TEST_H_ diff --git a/test/testsupport/perf_test_graphjson_writer.cc b/test/testsupport/perf_test_graphjson_writer.cc index 5a8ee64709..cf49b29320 100644 --- a/test/testsupport/perf_test_graphjson_writer.cc +++ b/test/testsupport/perf_test_graphjson_writer.cc @@ -110,7 +110,7 @@ class PerfTestGraphJsonWriter : public PerfTestResultWriter { graphs_[graph_name].push_back(json_stream.str()); } - std::string ToJSON() const { + std::string Serialize() const { std::ostringstream json_stream; json_stream << R"({"format_version":"1.0",)"; json_stream << R"("charts":{)"; diff --git a/test/testsupport/perf_test_histogram_writer.cc b/test/testsupport/perf_test_histogram_writer.cc index d82294bc68..523834bcc8 100644 --- a/test/testsupport/perf_test_histogram_writer.cc +++ b/test/testsupport/perf_test_histogram_writer.cc @@ -13,15 +13,180 @@ #include #include +#include + +#include "rtc_base/critical_section.h" +#include "rtc_base/logging.h" +#include "third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.h" +#include "third_party/catapult/tracing/tracing/value/histogram.h" namespace webrtc { namespace test { -namespace {} // namespace +namespace { + +namespace proto = catapult::tracing::tracing::proto; + +std::string AsJsonString(const std::string string) { + return "\"" + string + "\""; +} + +class PerfTestHistogramWriter : public PerfTestResultWriter { + public: + PerfTestHistogramWriter() : crit_() {} + void ClearResults() override { + rtc::CritScope lock(&crit_); + histograms_.clear(); + } + + void LogResult(const std::string& graph_name, + const std::string& trace_name, + const double value, + const std::string& units, + const bool important, + ImproveDirection improve_direction) override { + (void)important; + AddSample(graph_name, trace_name, value, units, improve_direction); + } + void LogResultMeanAndError(const std::string& graph_name, + const std::string& trace_name, + const double mean, + const double error, + const std::string& units, + const bool important, + ImproveDirection improve_direction) override { + RTC_LOG(LS_WARNING) << "Discarding stddev, not supported by histograms"; + (void)error; + (void)important; + + AddSample(graph_name, trace_name, mean, units, improve_direction); + } + void LogResultList(const std::string& graph_name, + const std::string& trace_name, + const rtc::ArrayView values, + const std::string& units, + const bool important, + ImproveDirection improve_direction) override { + (void)important; + for (double value : values) { + AddSample(graph_name, trace_name, value, units, improve_direction); + } + } + std::string Serialize() const override { + proto::HistogramSet histogram_set; + + rtc::CritScope lock(&crit_); + for (const auto& histogram : histograms_) { + std::unique_ptr proto = histogram.second->toProto(); + histogram_set.mutable_histograms()->AddAllocated(proto.release()); + } + + std::string output; + bool ok = histogram_set.SerializeToString(&output); + RTC_DCHECK(ok) << "Failed to serialize histogram set to string"; + return output; + } + + private: + void AddSample(const std::string& original_graph_name, + const std::string& trace_name, + const double value, + const std::string& units, + ImproveDirection improve_direction) { + // WebRTC annotates the units into the metric name when they are not + // supported by the Histogram API. + std::string graph_name = original_graph_name; + if (units == "dB") { + graph_name += "_dB"; + } else if (units == "fps") { + graph_name += "_fps"; + } else if (units == "%") { + graph_name += "_%"; + } + + // Lookup on graph name + trace name (or measurement + story in catapult + // parlance). There should be several histograms with the same measurement + // if they're for different stories. + std::string measurement_and_story = graph_name + trace_name; + rtc::CritScope lock(&crit_); + if (histograms_.count(measurement_and_story) == 0) { + proto::UnitAndDirection unit = ParseUnit(units, improve_direction); + std::unique_ptr builder = + std::make_unique(graph_name, unit); + histograms_[measurement_and_story] = std::move(builder); + + proto::Diagnostic stories; + proto::GenericSet* generic_set = stories.mutable_generic_set(); + generic_set->add_values(AsJsonString(trace_name)); + histograms_[measurement_and_story]->AddDiagnostic( + catapult::kStoriesDiagnostic, stories); + } + + if (units == "bps") { + // Bps has been interpreted as bits per second in WebRTC tests. + histograms_[measurement_and_story]->AddSample(value / 8); + } else { + histograms_[measurement_and_story]->AddSample(value); + } + } + + proto::UnitAndDirection ParseUnit(const std::string& units, + ImproveDirection improve_direction) { + RTC_DCHECK(units.find('_') == std::string::npos) + << "The unit_bigger|smallerIsBetter syntax isn't supported in WebRTC, " + "use the enum instead."; + + proto::UnitAndDirection result; + result.set_improvement_direction(ParseDirection(improve_direction)); + if (units == "bps") { + result.set_unit(proto::BYTES_PER_SECOND); + } else if (units == "dB") { + result.set_unit(proto::UNITLESS); + } else if (units == "fps") { + result.set_unit(proto::HERTZ); + } else if (units == "frames") { + result.set_unit(proto::COUNT); + } else if (units == "ms") { + result.set_unit(proto::MS_BEST_FIT_FORMAT); + } else if (units == "%") { + result.set_unit(proto::UNITLESS); + } else { + proto::Unit unit = catapult::UnitFromJsonUnit(units); + + // UnitFromJsonUnit returns UNITLESS if it doesn't recognize the unit. + if (unit == proto::UNITLESS && units != "unitless") { + RTC_LOG(LS_WARNING) << "Unit " << units << " is unsupported."; + } + + result.set_unit(unit); + } + return result; + } + + proto::ImprovementDirection ParseDirection( + ImproveDirection improve_direction) { + switch (improve_direction) { + case ImproveDirection::kNone: + return proto::NOT_SPECIFIED; + case ImproveDirection::kSmallerIsBetter: + return proto::SMALLER_IS_BETTER; + case ImproveDirection::kBiggerIsBetter: + return proto::BIGGER_IS_BETTER; + default: + RTC_NOTREACHED() << "Invalid enum value " << improve_direction; + } + } + + private: + rtc::CriticalSection crit_; + std::map> histograms_ + RTC_GUARDED_BY(&crit_); +}; + +} // namespace PerfTestResultWriter* CreateHistogramWriter() { - RTC_CHECK(false) << "Not implemented"; - return nullptr; + return new PerfTestHistogramWriter(); } } // namespace test diff --git a/test/testsupport/perf_test_histogram_writer_no_protobuf.cc b/test/testsupport/perf_test_histogram_writer_no_protobuf.cc new file mode 100644 index 0000000000..17685ccb0d --- /dev/null +++ b/test/testsupport/perf_test_histogram_writer_no_protobuf.cc @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 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 "test/testsupport/perf_test_histogram_writer.h" + +namespace webrtc { +namespace test { + +PerfTestResultWriter* CreateHistogramWriter() { + RTC_NOTREACHED() << "Cannot run perf tests with rtc_enable_protobuf = false. " + "Perf write results as protobufs."; +} + +} // namespace test +} // namespace webrtc diff --git a/test/testsupport/perf_test_histogram_writer_unittest.cc b/test/testsupport/perf_test_histogram_writer_unittest.cc new file mode 100644 index 0000000000..6b083d6543 --- /dev/null +++ b/test/testsupport/perf_test_histogram_writer_unittest.cc @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2020 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 "test/testsupport/perf_test_histogram_writer.h" + +#include +#include + +#include "test/gtest.h" +#include "third_party/catapult/tracing/tracing/value/histogram.h" + +namespace webrtc { +namespace test { + +namespace proto = catapult::tracing::tracing::proto; + +TEST(PerfHistogramWriterUnittest, TestSimpleHistogram) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("-", "-", 0, "ms", false, ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + EXPECT_TRUE(histogram_set.ParseFromString(writer->Serialize())) + << "Expected valid histogram set"; + + ASSERT_EQ(histogram_set.histograms_size(), 1); +} + +TEST(PerfHistogramWriterUnittest, WritesSamplesAndUserStory) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("measurement", "user_story", 15e7, "Hz", false, + ImproveDirection::kBiggerIsBetter); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + + EXPECT_EQ(hist1.name(), "measurement"); + + EXPECT_EQ(hist1.unit().unit(), proto::HERTZ); + EXPECT_EQ(hist1.unit().improvement_direction(), proto::BIGGER_IS_BETTER); + + EXPECT_EQ(hist1.sample_values_size(), 1); + EXPECT_EQ(hist1.sample_values(0), 15e7); + + EXPECT_EQ(hist1.diagnostics().diagnostic_map().count("stories"), 1u); + const proto::Diagnostic& stories = + hist1.diagnostics().diagnostic_map().at("stories"); + ASSERT_EQ(stories.generic_set().values_size(), 1); + EXPECT_EQ(stories.generic_set().values(0), "\"user_story\""); +} + +TEST(PerfHistogramWriterUnittest, WritesOneHistogramPerMeasurementAndStory) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("measurement", "story1", 1, "ms", false, + ImproveDirection::kNone); + writer->LogResult("measurement", "story1", 2, "ms", false, + ImproveDirection::kNone); + writer->LogResult("measurement", "story2", 2, "ms", false, + ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + ASSERT_EQ(histogram_set.histograms_size(), 2); + + const proto::Histogram& hist1 = histogram_set.histograms(0); + const proto::Histogram& hist2 = histogram_set.histograms(1); + + EXPECT_EQ(hist1.name(), "measurement"); + EXPECT_EQ(hist2.name(), "measurement"); + + const proto::Diagnostic& stories1 = + hist1.diagnostics().diagnostic_map().at("stories"); + EXPECT_EQ(stories1.generic_set().values(0), "\"story1\""); + EXPECT_EQ(hist1.sample_values_size(), 2); + + const proto::Diagnostic& stories2 = + hist2.diagnostics().diagnostic_map().at("stories"); + EXPECT_EQ(stories2.generic_set().values(0), "\"story2\""); + EXPECT_EQ(hist2.sample_values_size(), 1); +} + +TEST(PerfHistogramWriterUnittest, IgnoresError) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResultMeanAndError("-", "-", 17, 12345, "ms", false, + ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + + EXPECT_EQ(hist1.running().mean(), 17); + EXPECT_EQ(hist1.running().variance(), 0) << "The error should be ignored."; +} + +TEST(PerfHistogramWriterUnittest, WritesDecibelIntoMeasurementName) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("measurement", "-", 0, "dB", false, + ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + + EXPECT_EQ(hist1.unit().unit(), proto::UNITLESS) + << "dB should map to unitless"; + EXPECT_EQ(hist1.name(), "measurement_dB") << "measurement should be renamed"; +} + +TEST(PerfHistogramWriterUnittest, WritesFpsIntoMeasurementName) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("measurement", "-", 0, "fps", false, + ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + + EXPECT_EQ(hist1.unit().unit(), proto::HERTZ) << "fps should map to hertz"; + EXPECT_EQ(hist1.name(), "measurement_fps") << "measurement should be renamed"; +} + +TEST(PerfHistogramWriterUnittest, WritesPercentIntoMeasurementName) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("measurement", "-", 0, "%", false, ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + + EXPECT_EQ(hist1.unit().unit(), proto::UNITLESS) + << "percent should map to hertz"; + EXPECT_EQ(hist1.name(), "measurement_%") << "measurement should be renamed"; +} + +TEST(PerfHistogramWriterUnittest, BitsPerSecondIsConvertedToBytes) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("-", "-", 1024, "bps", false, ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + + EXPECT_EQ(hist1.sample_values(0), 128) << "1024 bits = 128 bytes"; +} + +TEST(PerfHistogramWriterUnittest, ParsesDirection) { + std::unique_ptr writer = + std::unique_ptr(CreateHistogramWriter()); + + writer->LogResult("measurement1", "-", 0, "bps", false, + ImproveDirection::kBiggerIsBetter); + writer->LogResult("measurement2", "-", 0, "frames", false, + ImproveDirection::kSmallerIsBetter); + writer->LogResult("measurement3", "-", 0, "sigma", false, + ImproveDirection::kNone); + + proto::HistogramSet histogram_set; + histogram_set.ParseFromString(writer->Serialize()); + const proto::Histogram& hist1 = histogram_set.histograms(0); + const proto::Histogram& hist2 = histogram_set.histograms(1); + const proto::Histogram& hist3 = histogram_set.histograms(2); + + EXPECT_EQ(hist1.unit().unit(), proto::BYTES_PER_SECOND); + EXPECT_EQ(hist1.unit().improvement_direction(), proto::BIGGER_IS_BETTER); + + EXPECT_EQ(hist2.unit().unit(), proto::COUNT); + EXPECT_EQ(hist2.unit().improvement_direction(), proto::SMALLER_IS_BETTER); + + EXPECT_EQ(hist3.unit().unit(), proto::SIGMA); + EXPECT_EQ(hist3.unit().improvement_direction(), proto::NOT_SPECIFIED); +} + +} // namespace test +} // namespace webrtc diff --git a/test/testsupport/perf_test_result_writer.h b/test/testsupport/perf_test_result_writer.h index 5e932ba51c..d5d7011749 100644 --- a/test/testsupport/perf_test_result_writer.h +++ b/test/testsupport/perf_test_result_writer.h @@ -47,7 +47,7 @@ class PerfTestResultWriter { const bool important, webrtc::test::ImproveDirection improve_direction) = 0; - virtual std::string ToJSON() const = 0; + virtual std::string Serialize() const = 0; }; } // namespace test diff --git a/test/testsupport/perf_test_unittest.cc b/test/testsupport/perf_test_unittest.cc index 8202471923..1004c6495e 100644 --- a/test/testsupport/perf_test_unittest.cc +++ b/test/testsupport/perf_test_unittest.cc @@ -17,6 +17,11 @@ #include "test/gtest.h" #include "test/testsupport/rtc_expect_death.h" +#if WEBRTC_ENABLE_PROTOBUF +#include "third_party/catapult/tracing/tracing/value/histogram.h" +namespace proto = catapult::tracing::tracing::proto; +#endif + namespace { const char* kJsonExpected = R"({ @@ -98,15 +103,72 @@ TEST_F(PerfTest, TestGetPerfResultsJSON) { const double kListOfScalars[] = {1, 2, 3}; PrintResultList("foo", "bar", "baz_vl", kListOfScalars, "units", false); - EXPECT_EQ(RemoveSpaces(kJsonExpected), GetPerfResultsJSON()); + EXPECT_EQ(RemoveSpaces(kJsonExpected), GetPerfResults()); } TEST_F(PerfTest, TestClearPerfResults) { PrintResult("measurement", "modifier", "trace", 42, "units", false); ClearPerfResults(); - EXPECT_EQ(R"({"format_version":"1.0","charts":{}})", GetPerfResultsJSON()); + EXPECT_EQ(R"({"format_version":"1.0","charts":{}})", GetPerfResults()); } +#if WEBRTC_ENABLE_PROTOBUF + +TEST_F(PerfTest, TestGetPerfResultsHistograms) { + bool original_flag = absl::GetFlag(FLAGS_write_histogram_proto_json); + absl::SetFlag(&FLAGS_write_histogram_proto_json, true); + PrintResult("measurement", "_modifier", "story_1", 42, "ms", false); + PrintResult("foo", "bar", "story_1", 7, "sigma", true); + // Note: the error will be ignored, not supported by histograms. + PrintResultMeanAndError("foo", "bar", "story_1", 1, 2000, "sigma", false); + const double kListOfScalars[] = {1, 2, 3}; + PrintResultList("foo", "bar", "story_1", kListOfScalars, "sigma", false); + + proto::HistogramSet histogram_set; + EXPECT_TRUE(histogram_set.ParseFromString(GetPerfResults())) + << "Expected valid histogram set"; + + ASSERT_EQ(histogram_set.histograms_size(), 2) + << "Should be two histograms: foobar and measurement_modifier"; + const proto::Histogram& hist1 = histogram_set.histograms(0); + const proto::Histogram& hist2 = histogram_set.histograms(1); + + EXPECT_EQ(hist1.name(), "foobar"); + + // Spot check some things in here (there's a more thorough test on the + // histogram writer itself). + EXPECT_EQ(hist1.unit().unit(), proto::SIGMA); + EXPECT_EQ(hist1.sample_values_size(), 5); + EXPECT_EQ(hist1.sample_values(0), 7); + EXPECT_EQ(hist1.sample_values(1), 1); + EXPECT_EQ(hist1.sample_values(2), 1); + EXPECT_EQ(hist1.sample_values(3), 2); + EXPECT_EQ(hist1.sample_values(4), 3); + + EXPECT_EQ(hist1.diagnostics().diagnostic_map().count("stories"), 1u); + const proto::Diagnostic& stories = + hist1.diagnostics().diagnostic_map().at("stories"); + ASSERT_EQ(stories.generic_set().values_size(), 1); + EXPECT_EQ(stories.generic_set().values(0), "\"story_1\""); + + EXPECT_EQ(hist2.name(), "measurement_modifier"); + EXPECT_EQ(hist2.unit().unit(), proto::MS_BEST_FIT_FORMAT); + + absl::SetFlag(&FLAGS_write_histogram_proto_json, original_flag); +} + +TEST_F(PerfTest, TestClearPerfResultsHistograms) { + bool original_flag = absl::GetFlag(FLAGS_write_histogram_proto_json); + absl::SetFlag(&FLAGS_write_histogram_proto_json, true); + PrintResult("measurement", "modifier", "trace", 42, "ms", false); + ClearPerfResults(); + EXPECT_EQ("", GetPerfResults()); + + absl::SetFlag(&FLAGS_write_histogram_proto_json, original_flag); +} + +#endif // WEBRTC_ENABLE_PROTOBUF + #if GTEST_HAS_DEATH_TEST using PerfDeathTest = PerfTest;