register_benchmark_test.cc (5441B)
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: 13 virtual void ReportRuns(const std::vector<Run>& report) { 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 std::string name; 23 const char* label; 24 // Note: not explicit as we rely on it being converted through ADD_CASES. 25 TestCase(const char* xname) : TestCase(xname, nullptr) {} 26 TestCase(const char* xname, const char* 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 CHECK(name == run.benchmark_name()) << "expected " << name << " got " 34 << run.benchmark_name(); 35 if (label) { 36 CHECK(run.report_label == label) << "expected " << label << " got " 37 << run.report_label; 38 } else { 39 CHECK(run.report_label == ""); 40 } 41 // clang-format on 42 } 43 }; 44 45 std::vector<TestCase> ExpectedResults; 46 47 int AddCases(std::initializer_list<TestCase> const& v) { 48 for (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 //----------------------------------------------------------------------------// 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 81 void BM_extra_args(benchmark::State& st, const char* label) { 82 for (auto _ : st) { 83 } 84 st.SetLabel(label); 85 } 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 different callable types 100 //----------------------------------------------------------------------------// 101 102 struct CustomFixture { 103 void operator()(benchmark::State& st) { 104 for (auto _ : st) { 105 } 106 } 107 }; 108 109 void TestRegistrationAtRuntime() { 110 #ifdef BENCHMARK_HAS_CXX11 111 { 112 CustomFixture fx; 113 benchmark::RegisterBenchmark("custom_fixture", fx); 114 AddCases({"custom_fixture"}); 115 } 116 #endif 117 #ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK 118 { 119 const char* x = "42"; 120 auto capturing_lam = [=](benchmark::State& st) { 121 for (auto _ : st) { 122 } 123 st.SetLabel(x); 124 }; 125 benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam); 126 AddCases({{"lambda_benchmark", x}}); 127 } 128 #endif 129 } 130 131 // Test that all benchmarks, registered at either during static init or runtime, 132 // are run and the results are passed to the reported. 133 void RunTestOne() { 134 TestRegistrationAtRuntime(); 135 136 TestReporter test_reporter; 137 benchmark::RunSpecifiedBenchmarks(&test_reporter); 138 139 typedef benchmark::BenchmarkReporter::Run Run; 140 auto EB = ExpectedResults.begin(); 141 142 for (Run const& run : test_reporter.all_runs_) { 143 assert(EB != ExpectedResults.end()); 144 EB->CheckRun(run); 145 ++EB; 146 } 147 assert(EB == ExpectedResults.end()); 148 } 149 150 // Test that ClearRegisteredBenchmarks() clears all previously registered 151 // benchmarks. 152 // Also test that new benchmarks can be registered and ran afterwards. 153 void RunTestTwo() { 154 assert(ExpectedResults.size() != 0 && 155 "must have at least one registered benchmark"); 156 ExpectedResults.clear(); 157 benchmark::ClearRegisteredBenchmarks(); 158 159 TestReporter test_reporter; 160 size_t num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter); 161 assert(num_ran == 0); 162 assert(test_reporter.all_runs_.begin() == test_reporter.all_runs_.end()); 163 164 TestRegistrationAtRuntime(); 165 num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter); 166 assert(num_ran == ExpectedResults.size()); 167 168 typedef benchmark::BenchmarkReporter::Run Run; 169 auto EB = ExpectedResults.begin(); 170 171 for (Run const& run : test_reporter.all_runs_) { 172 assert(EB != ExpectedResults.end()); 173 EB->CheckRun(run); 174 ++EB; 175 } 176 assert(EB == ExpectedResults.end()); 177 } 178 179 int main(int argc, char* argv[]) { 180 benchmark::Initialize(&argc, argv); 181 182 RunTestOne(); 183 RunTestTwo(); 184 }