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   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.
TestCase__anon0939ce2d0111::TestCase25   TestCase(const char* xname) : TestCase(xname, nullptr) {}
TestCase__anon0939ce2d0111::TestCase26   TestCase(const char* xname, const char* xlabel)
27       : name(xname), label(xlabel) {}
28 
29   typedef benchmark::BenchmarkReporter::Run Run;
30 
CheckRun__anon0939ce2d0111::TestCase31   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 
AddCases(std::initializer_list<TestCase> const & v)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 //----------------------------------------------------------------------------//
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 different callable types
100 //----------------------------------------------------------------------------//
101 
102 struct CustomFixture {
operator ()CustomFixture103   void operator()(benchmark::State& st) {
104     for (auto _ : st) {
105     }
106   }
107 };
108 
TestRegistrationAtRuntime()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.
RunTestOne()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.
RunTestTwo()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 
main(int argc,char * argv[])179 int main(int argc, char* argv[]) {
180   benchmark::Initialize(&argc, argv);
181 
182   RunTestOne();
183   RunTestTwo();
184 }
185