xref: /aosp_15_r20/external/google-benchmark/test/register_benchmark_test.cc (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
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 
9 namespace {
10 
11 class TestReporter : public benchmark::ConsoleReporter {
12  public:
ReportRuns(const std::vector<Run> & report)13   void ReportRuns(const std::vector<Run>& report) override {
14     all_runs_.insert(all_runs_.end(), begin(report), end(report));
15     ConsoleReporter::ReportRuns(report);
16   }
17 
18   std::vector<Run> all_runs_;
19 };
20 
21 struct 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.
TestCase__anon3d8d12fc0111::TestCase25   TestCase(const std::string& xname) : TestCase(xname, "") {}
TestCase__anon3d8d12fc0111::TestCase26   TestCase(const std::string& xname, const std::string& xlabel)
27       : name(xname), label(xlabel) {}
28 
29   typedef benchmark::BenchmarkReporter::Run Run;
30 
CheckRun__anon3d8d12fc0111::TestCase31   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 
45 std::vector<TestCase> ExpectedResults;
46 
AddCases(std::initializer_list<TestCase> const & v)47 int AddCases(std::initializer_list<TestCase> const& v) {
48   for (const auto& N : v) {
49     ExpectedResults.push_back(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 
60 typedef benchmark::internal::Benchmark* ReturnVal;
61 
62 //----------------------------------------------------------------------------//
63 // Test RegisterBenchmark with no additional arguments
64 //----------------------------------------------------------------------------//
BM_function(benchmark::State & state)65 void BM_function(benchmark::State& state) {
66   for (auto _ : state) {
67   }
68 }
69 BENCHMARK(BM_function);
70 ReturnVal dummy = benchmark::RegisterBenchmark(
71     "BM_function_manual_registration", BM_function);
72 ADD_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 
BM_extra_args(benchmark::State & st,const char * label)81 void BM_extra_args(benchmark::State& st, const char* label) {
82   for (auto _ : st) {
83   }
84   st.SetLabel(label);
85 }
RegisterFromFunction()86 int 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(c.first, &BM_extra_args, c.second);
91   return 0;
92 }
93 int dummy2 = RegisterFromFunction();
94 ADD_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 //----------------------------------------------------------------------------//
DISABLED_BM_function(benchmark::State & state)101 void DISABLED_BM_function(benchmark::State& state) {
102   for (auto _ : state) {
103   }
104 }
105 BENCHMARK(DISABLED_BM_function);
106 ReturnVal dummy3 = benchmark::RegisterBenchmark("DISABLED_BM_function_manual",
107                                                 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 
114 struct CustomFixture {
operator ()CustomFixture115   void operator()(benchmark::State& st) {
116     for (auto _ : st) {
117     }
118   }
119 };
120 
TestRegistrationAtRuntime()121 void TestRegistrationAtRuntime() {
122 #ifdef BENCHMARK_HAS_CXX11
123   {
124     CustomFixture fx;
125     benchmark::RegisterBenchmark("custom_fixture", fx);
126     AddCases({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("lambda_benchmark", capturing_lam);
138     AddCases({{"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.
RunTestOne()145 void RunTestOne() {
146   TestRegistrationAtRuntime();
147 
148   TestReporter test_reporter;
149   benchmark::RunSpecifiedBenchmarks(&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.
RunTestTwo()165 void 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(&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(&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 
main(int argc,char * argv[])191 int main(int argc, char* argv[]) {
192   benchmark::Initialize(&argc, argv);
193 
194   RunTestOne();
195   RunTestTwo();
196 }
197