diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h index 08cfe29da3..58d45681ef 100644 --- a/include/benchmark/benchmark.h +++ b/include/benchmark/benchmark.h @@ -1927,6 +1927,20 @@ class BENCHMARK_EXPORT BenchmarkReporter { // REQUIRES: 'out' is non-null. static void PrintBasicContext(std::ostream* out, Context const& context); + /** + * @brief Lists and describes the provided benchmarks. + * + * This virtual method is intended to be overridden by derived classes + * to provide specific implementations for listing benchmarks. + * It can be used for outputting, logging, or any other operation + * needed to handle or display the benchmarks' names and metadata. + * + * @param benchmarks A vector containing names and details of benchmarks + * that need to be listed or processed. + */ + virtual void List( + const std::vector& benchmarks) = 0; + private: std::ostream* output_stream_; std::ostream* error_stream_; @@ -1948,6 +1962,8 @@ class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter { bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; + void List(const std::vector& benchmarks) + BENCHMARK_OVERRIDE; protected: virtual void PrintRunData(const Run& report); @@ -1965,6 +1981,8 @@ class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter { bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; void Finalize() BENCHMARK_OVERRIDE; + void List(const std::vector& benchmarks) + BENCHMARK_OVERRIDE; private: void PrintRunData(const Run& report); @@ -1979,6 +1997,8 @@ class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG( CSVReporter() : printed_header_(false) {} bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; + void List(const std::vector& benchmarks) + BENCHMARK_OVERRIDE; private: void PrintRunData(const Run& report); diff --git a/src/benchmark.cc b/src/benchmark.cc index 337bb3faa7..66ebfb7ca3 100644 --- a/src/benchmark.cc +++ b/src/benchmark.cc @@ -624,8 +624,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, } if (FLAGS_benchmark_list_tests) { - for (auto const& benchmark : benchmarks) - Out << benchmark.name().str() << "\n"; + display_reporter->List(benchmarks); } else { internal::RunBenchmarks(benchmarks, display_reporter, file_reporter); } diff --git a/src/console_reporter.cc b/src/console_reporter.cc index 35c3de2a4d..c2ea7cad23 100644 --- a/src/console_reporter.cc +++ b/src/console_reporter.cc @@ -21,7 +21,7 @@ #include #include -#include "benchmark/benchmark.h" +#include "benchmark_api_internal.h" #include "check.h" #include "colorprint.h" #include "commandlineflags.h" @@ -207,4 +207,13 @@ void ConsoleReporter::PrintRunData(const Run& result) { printer(Out, COLOR_DEFAULT, "\n"); } +BENCHMARK_EXPORT +void ConsoleReporter::List( + const std::vector& benchmarks) { + std::ostream& Out = GetOutputStream(); + for (auto const& benchmark : benchmarks) { + Out << benchmark.name().str() << "\n"; + } +} + } // end namespace benchmark diff --git a/src/csv_reporter.cc b/src/csv_reporter.cc index 4b39e2c52f..ceb8e98eb1 100644 --- a/src/csv_reporter.cc +++ b/src/csv_reporter.cc @@ -19,7 +19,7 @@ #include #include -#include "benchmark/benchmark.h" +#include "benchmark_api_internal.h" #include "check.h" #include "complexity.h" #include "string_util.h" @@ -166,4 +166,11 @@ void CSVReporter::PrintRunData(const Run& run) { Out << '\n'; } +void CSVReporter::List( + const std::vector& benchmarks) { + (void)benchmarks; // Suppress unused parameter warning + std::ostream& err = GetErrorStream(); + err << "List() method is not implemented for CSVReporter.\n"; +} + } // end namespace benchmark diff --git a/src/json_reporter.cc b/src/json_reporter.cc index b8c8c94c08..44bbfb406c 100644 --- a/src/json_reporter.cc +++ b/src/json_reporter.cc @@ -22,7 +22,7 @@ #include #include -#include "benchmark/benchmark.h" +#include "benchmark_api_internal.h" #include "complexity.h" #include "string_util.h" #include "timers.h" @@ -324,4 +324,18 @@ void JSONReporter::PrintRunData(Run const& run) { const int64_t MemoryManager::TombstoneValue = std::numeric_limits::max(); +void JSONReporter::List( + const std::vector& benchmarks) { + std::ostream& Out = GetOutputStream(); + Out << "["; + for (size_t i = 0; i < benchmarks.size(); ++i) { + const auto& benchmark = benchmarks[i]; + Out << "{" << FormatKV("name", benchmark.name().str()) << "}"; + if (i != benchmarks.size() - 1) { + Out << ", "; + } + } + Out << "]"; +} + } // end namespace benchmark diff --git a/test/benchmark_random_interleaving_gtest.cc b/test/benchmark_random_interleaving_gtest.cc index 7f2086750d..9b394efdbb 100644 --- a/test/benchmark_random_interleaving_gtest.cc +++ b/test/benchmark_random_interleaving_gtest.cc @@ -40,6 +40,8 @@ class NullReporter : public BenchmarkReporter { public: bool ReportContext(const Context& /*context*/) override { return true; } void ReportRuns(const std::vector& /* report */) override {} + void List( + const std::vector&) override {} }; class BenchmarkTest : public testing::Test { diff --git a/test/output_test_helper.cc b/test/output_test_helper.cc index 265f28aae7..d99ad92387 100644 --- a/test/output_test_helper.cc +++ b/test/output_test_helper.cc @@ -165,6 +165,14 @@ class TestReporter : public benchmark::BenchmarkReporter { for (auto rep : reporters_) rep->Finalize(); } + void List(const std::vector& + benchmarks) override { + // simply logging the status + for (const auto& benchmark : benchmarks) { + std::cout << benchmark.name().str() << std::endl; + } + } + private: std::vector reporters_; }; diff --git a/test/reporter_list_gtest.cc b/test/reporter_list_gtest.cc new file mode 100644 index 0000000000..b1f37537c9 --- /dev/null +++ b/test/reporter_list_gtest.cc @@ -0,0 +1,109 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "benchmark/benchmark.h" + +namespace benchmark { +namespace internal { + +// Helper function to register benchmarks +void RegisterBenchmarks() { + benchmark::RegisterBenchmark("BM_simple", [](benchmark::State& state) { + for (auto _ : state) {} + }); + benchmark::RegisterBenchmark("BM_complex", [](benchmark::State& state) { + for (auto _ : state) { + // Simulating a complex operation + for (int i = 0; i < 1000; ++i) { + benchmark::DoNotOptimize(i * i); + } + } + }); + benchmark::RegisterBenchmark("BM_special_chars", [](benchmark::State& state) { + for (auto _ : state) {} + })->Name("BM_special!@#"); +} + +class ReporterListTest : public ::testing::Test { +protected: + std::stringstream ss; + BenchmarkReporter::Context context; + + void SetUp() override { + benchmark::ClearRegisteredBenchmarks(); + ss.str(""); + ss.clear(); + } + + void RunList(BenchmarkReporter& reporter) { + RegisterBenchmarks(); // Register all benchmarks + benchmark::RunSpecifiedBenchmarks(&reporter); + } +}; + +// Tests the behavior of reporters when no benchmarks are registered +TEST_F(ReporterListTest, HandlesEmptyBenchmarkList) { + benchmark::ConsoleReporter console_reporter(&ss); + benchmark::JSONReporter json_reporter(&ss); + benchmark::CSVReporter csv_reporter(&ss); + + // Expect no output as no benchmarks are registered + RunList(console_reporter); + EXPECT_TRUE(ss.str().empty()); + + ss.str(""); + RunList(json_reporter); + EXPECT_TRUE(ss.str().empty()); + + ss.str(""); + RunList(csv_reporter); + EXPECT_TRUE(ss.str().empty()); +} + +// Tests the output of reporters when benchmarks are listed +TEST_F(ReporterListTest, ListsBenchmarksWithDifferentReporters) { + benchmark::ConsoleReporter console_reporter(&ss); + benchmark::JSONReporter json_reporter(&ss); + benchmark::CSVReporter csv_reporter(&ss); + + RegisterBenchmarks(); // Ensure some benchmarks are registered + + RunList(console_reporter); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("BM_simple")); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("BM_complex")); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("BM_special!@#")); + + ss.str(""); + RunList(json_reporter); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("\"name\": \"BM_simple\"")); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("\"name\": \"BM_complex\"")); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("\"name\": \"BM_special!@#\"")); + + // Check JSON structure + std::string json_output = ss.str(); + EXPECT_THAT(json_output.front(), testing::Eq('[')); + EXPECT_THAT(json_output.back(), testing::Eq(']')) + + ss.str(""); + RunList(csv_reporter); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("BM_simple")); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("BM_complex")); + EXPECT_THAT(ss.str(), ::testing::HasSubstr("BM_special!@#")); +} + +} // namespace internal +} // namespace benchmark