Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: benchmark_list_tests benchmark-format=json #1647

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
73867c7
feat: benchmark_list_tests benchmark-format=json
varshneydevansh Aug 11, 2023
a41e9d6
feat: made method virtual and get rid of errors
varshneydevansh Aug 12, 2023
ecb97ff
Merge branch 'main' into benchmark_list_tests-work-with-benchmark-for…
varshneydevansh Aug 12, 2023
b83465c
feat: added the missing BENCHMARK_OVERRIDE
varshneydevansh Aug 12, 2023
d37b7c3
feat: run the clang-format again
varshneydevansh Aug 12, 2023
644a5fb
feat: removed Out as it's now in console reporter
varshneydevansh Aug 12, 2023
5c5914c
feat: forgot to supress the unused parameter
varshneydevansh Aug 12, 2023
4de740d
feat: deleted test / benchmark.pc
varshneydevansh Aug 12, 2023
550ceca
feat: deleted CMakeLists.txt
varshneydevansh Aug 12, 2023
4132a67
feat: added virtual method to abstract class
varshneydevansh Aug 12, 2023
a29702c
feat: modified the List() in output_test_helper
varshneydevansh Aug 12, 2023
cd632b2
feat: added List() NullReporter & chnagedback enum
varshneydevansh Aug 12, 2023
cb5be7d
feat: removed the extra spaces from the endif
varshneydevansh Aug 12, 2023
fa29dab
feat: Corrected if FLAGS_benchmark_list_tests)
varshneydevansh Aug 12, 2023
139e29c
feat: improvement with display_reporter, FormatKV
varshneydevansh Aug 14, 2023
e1b21e0
Merge branch 'main' into benchmark_list_tests-work-with-benchmark-for…
dmah42 Sep 26, 2023
b8ad5ac
Merge branch 'google:main' into benchmark_list_tests-work-with-benchm…
varshneydevansh Feb 20, 2024
f4832c3
Merge branch 'google:main' into benchmark_list_tests-work-with-benchm…
varshneydevansh May 12, 2024
3b07ebf
add the test case for List
varshneydevansh May 12, 2024
438c8c3
modified the gtest file
varshneydevansh May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions include/benchmark/benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<internal::BenchmarkInstance>& benchmarks) = 0;

private:
std::ostream* output_stream_;
std::ostream* error_stream_;
Expand All @@ -1948,6 +1962,8 @@ class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter {

bool ReportContext(const Context& context) BENCHMARK_OVERRIDE;
void ReportRuns(const std::vector<Run>& reports) BENCHMARK_OVERRIDE;
void List(const std::vector<internal::BenchmarkInstance>& benchmarks)
BENCHMARK_OVERRIDE;

protected:
virtual void PrintRunData(const Run& report);
Expand All @@ -1965,6 +1981,8 @@ class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter {
bool ReportContext(const Context& context) BENCHMARK_OVERRIDE;
void ReportRuns(const std::vector<Run>& reports) BENCHMARK_OVERRIDE;
void Finalize() BENCHMARK_OVERRIDE;
void List(const std::vector<internal::BenchmarkInstance>& benchmarks)
BENCHMARK_OVERRIDE;

private:
void PrintRunData(const Run& report);
Expand All @@ -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<Run>& reports) BENCHMARK_OVERRIDE;
void List(const std::vector<internal::BenchmarkInstance>& benchmarks)
BENCHMARK_OVERRIDE;

private:
void PrintRunData(const Run& report);
Expand Down
3 changes: 1 addition & 2 deletions src/benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
11 changes: 10 additions & 1 deletion src/console_reporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <tuple>
#include <vector>

#include "benchmark/benchmark.h"
#include "benchmark_api_internal.h"
#include "check.h"
#include "colorprint.h"
#include "commandlineflags.h"
Expand Down Expand Up @@ -207,4 +207,13 @@ void ConsoleReporter::PrintRunData(const Run& result) {
printer(Out, COLOR_DEFAULT, "\n");
}

BENCHMARK_EXPORT
void ConsoleReporter::List(
const std::vector<internal::BenchmarkInstance>& benchmarks) {
std::ostream& Out = GetOutputStream();
for (auto const& benchmark : benchmarks) {
Out << benchmark.name().str() << "\n";
}
}

} // end namespace benchmark
9 changes: 8 additions & 1 deletion src/csv_reporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <tuple>
#include <vector>

#include "benchmark/benchmark.h"
#include "benchmark_api_internal.h"
#include "check.h"
#include "complexity.h"
#include "string_util.h"
Expand Down Expand Up @@ -166,4 +166,11 @@ void CSVReporter::PrintRunData(const Run& run) {
Out << '\n';
}

void CSVReporter::List(
const std::vector<internal::BenchmarkInstance>& benchmarks) {
(void)benchmarks; // Suppress unused parameter warning
std::ostream& err = GetErrorStream();
err << "List() method is not implemented for CSVReporter.\n";
}

} // end namespace benchmark
16 changes: 15 additions & 1 deletion src/json_reporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <tuple>
#include <vector>

#include "benchmark/benchmark.h"
#include "benchmark_api_internal.h"
#include "complexity.h"
#include "string_util.h"
#include "timers.h"
Expand Down Expand Up @@ -324,4 +324,18 @@ void JSONReporter::PrintRunData(Run const& run) {
const int64_t MemoryManager::TombstoneValue =
std::numeric_limits<int64_t>::max();

void JSONReporter::List(
const std::vector<internal::BenchmarkInstance>& 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
2 changes: 2 additions & 0 deletions test/benchmark_random_interleaving_gtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class NullReporter : public BenchmarkReporter {
public:
bool ReportContext(const Context& /*context*/) override { return true; }
void ReportRuns(const std::vector<Run>& /* report */) override {}
void List(
const std::vector<benchmark::internal::BenchmarkInstance>&) override {}
};

class BenchmarkTest : public testing::Test {
Expand Down
8 changes: 8 additions & 0 deletions test/output_test_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ class TestReporter : public benchmark::BenchmarkReporter {
for (auto rep : reporters_) rep->Finalize();
}

void List(const std::vector<benchmark::internal::BenchmarkInstance>&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we could have a gtest for the List function?

benchmarks) override {
// simply logging the status
for (const auto& benchmark : benchmarks) {
std::cout << benchmark.name().str() << std::endl;
}
}

private:
std::vector<benchmark::BenchmarkReporter*> reporters_;
};
Expand Down
109 changes: 109 additions & 0 deletions test/reporter_list_gtest.cc
Original file line number Diff line number Diff line change
@@ -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 <gtest/gtest.h>
#include <gmock/gmock.h>
#include <sstream>
#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
Loading