1
2#undef NDEBUG
3#include <cassert>
4#include <vector>
5
6#include "../src/check.h" // NOTE: check.h is for internal use only!
7#include "benchmark/benchmark.h"
8
9namespace {
10
11class TestReporter : public benchmark::ConsoleReporter {
12 public:
13 void ReportRuns(const std::vector<Run>& report) override {
14 all_runs_.insert(position: all_runs_.end(), first: begin(cont: report), last: end(cont: report));
15 ConsoleReporter::ReportRuns(reports: report);
16 }
17
18 std::vector<Run> all_runs_;
19};
20
21struct TestCase {
22 const std::string name;
23 const std::string label;
24 // Note: not explicit as we rely on it being converted through ADD_CASES.
25 TestCase(const std::string& xname) : TestCase(xname, "") {}
26 TestCase(const std::string& xname, const std::string& xlabel)
27 : name(xname), label(xlabel) {}
28
29 typedef benchmark::BenchmarkReporter::Run Run;
30
31 void CheckRun(Run const& run) const {
32 // clang-format off
33 BM_CHECK(name == run.benchmark_name()) << "expected " << name << " got "
34 << run.benchmark_name();
35 if (!label.empty()) {
36 BM_CHECK(run.report_label == label) << "expected " << label << " got "
37 << run.report_label;
38 } else {
39 BM_CHECK(run.report_label.empty());
40 }
41 // clang-format on
42 }
43};
44
45std::vector<TestCase> ExpectedResults;
46
47int AddCases(std::initializer_list<TestCase> const& v) {
48 for (const auto& N : v) {
49 ExpectedResults.push_back(x: N);
50 }
51 return 0;
52}
53
54#define CONCAT(x, y) CONCAT2(x, y)
55#define CONCAT2(x, y) x##y
56#define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases({__VA_ARGS__})
57
58} // end namespace
59
60typedef benchmark::internal::Benchmark* ReturnVal;
61
62//----------------------------------------------------------------------------//
63// Test RegisterBenchmark with no additional arguments
64//----------------------------------------------------------------------------//
65void BM_function(benchmark::State& state) {
66 for (auto _ : state) {
67 }
68}
69BENCHMARK(BM_function);
70ReturnVal dummy = benchmark::RegisterBenchmark(
71 name: "BM_function_manual_registration", fn: BM_function);
72ADD_CASES({"BM_function"}, {"BM_function_manual_registration"});
73
74//----------------------------------------------------------------------------//
75// Test RegisterBenchmark with additional arguments
76// Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they
77// reject the variadic pack expansion of lambda captures.
78//----------------------------------------------------------------------------//
79#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
80
81void BM_extra_args(benchmark::State& st, const char* label) {
82 for (auto _ : st) {
83 }
84 st.SetLabel(label);
85}
86int RegisterFromFunction() {
87 std::pair<const char*, const char*> cases[] = {
88 {"test1", "One"}, {"test2", "Two"}, {"test3", "Three"}};
89 for (auto const& c : cases)
90 benchmark::RegisterBenchmark(name: c.first, fn: &BM_extra_args, args: c.second);
91 return 0;
92}
93int dummy2 = RegisterFromFunction();
94ADD_CASES({"test1", "One"}, {"test2", "Two"}, {"test3", "Three"});
95
96#endif // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
97
98//----------------------------------------------------------------------------//
99// Test RegisterBenchmark with DISABLED_ benchmark
100//----------------------------------------------------------------------------//
101void DISABLED_BM_function(benchmark::State& state) {
102 for (auto _ : state) {
103 }
104}
105BENCHMARK(DISABLED_BM_function);
106ReturnVal dummy3 = benchmark::RegisterBenchmark(name: "DISABLED_BM_function_manual",
107 fn: DISABLED_BM_function);
108// No need to add cases because we don't expect them to run.
109
110//----------------------------------------------------------------------------//
111// Test RegisterBenchmark with different callable types
112//----------------------------------------------------------------------------//
113
114struct CustomFixture {
115 void operator()(benchmark::State& st) {
116 for (auto _ : st) {
117 }
118 }
119};
120
121void TestRegistrationAtRuntime() {
122#ifdef BENCHMARK_HAS_CXX11
123 {
124 CustomFixture fx;
125 benchmark::RegisterBenchmark(name: "custom_fixture", fn&: fx);
126 AddCases(v: {std::string("custom_fixture")});
127 }
128#endif
129#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
130 {
131 const char* x = "42";
132 auto capturing_lam = [=](benchmark::State& st) {
133 for (auto _ : st) {
134 }
135 st.SetLabel(x);
136 };
137 benchmark::RegisterBenchmark(name: "lambda_benchmark", fn&: capturing_lam);
138 AddCases(v: {{"lambda_benchmark", x}});
139 }
140#endif
141}
142
143// Test that all benchmarks, registered at either during static init or runtime,
144// are run and the results are passed to the reported.
145void RunTestOne() {
146 TestRegistrationAtRuntime();
147
148 TestReporter test_reporter;
149 benchmark::RunSpecifiedBenchmarks(display_reporter: &test_reporter);
150
151 typedef benchmark::BenchmarkReporter::Run Run;
152 auto EB = ExpectedResults.begin();
153
154 for (Run const& run : test_reporter.all_runs_) {
155 assert(EB != ExpectedResults.end());
156 EB->CheckRun(run);
157 ++EB;
158 }
159 assert(EB == ExpectedResults.end());
160}
161
162// Test that ClearRegisteredBenchmarks() clears all previously registered
163// benchmarks.
164// Also test that new benchmarks can be registered and ran afterwards.
165void RunTestTwo() {
166 assert(ExpectedResults.size() != 0 &&
167 "must have at least one registered benchmark");
168 ExpectedResults.clear();
169 benchmark::ClearRegisteredBenchmarks();
170
171 TestReporter test_reporter;
172 size_t num_ran = benchmark::RunSpecifiedBenchmarks(display_reporter: &test_reporter);
173 assert(num_ran == 0);
174 assert(test_reporter.all_runs_.begin() == test_reporter.all_runs_.end());
175
176 TestRegistrationAtRuntime();
177 num_ran = benchmark::RunSpecifiedBenchmarks(display_reporter: &test_reporter);
178 assert(num_ran == ExpectedResults.size());
179
180 typedef benchmark::BenchmarkReporter::Run Run;
181 auto EB = ExpectedResults.begin();
182
183 for (Run const& run : test_reporter.all_runs_) {
184 assert(EB != ExpectedResults.end());
185 EB->CheckRun(run);
186 ++EB;
187 }
188 assert(EB == ExpectedResults.end());
189}
190
191int main(int argc, char* argv[]) {
192 benchmark::Initialize(argc: &argc, argv);
193
194 RunTestOne();
195 RunTestTwo();
196}
197

source code of third-party/benchmark/test/register_benchmark_test.cc