• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ReportContext(const Context & context)13   virtual bool ReportContext(const Context& context) {
14     return ConsoleReporter::ReportContext(context);
15   };
16 
ReportRuns(const std::vector<Run> & report)17   virtual void ReportRuns(const std::vector<Run>& report) {
18     all_runs_.insert(all_runs_.end(), begin(report), end(report));
19     ConsoleReporter::ReportRuns(report);
20   }
21 
TestReporter()22   TestReporter() {}
~TestReporter()23   virtual ~TestReporter() {}
24 
25   mutable std::vector<Run> all_runs_;
26 };
27 
28 struct TestCase {
29   std::string name;
30   bool error_occurred;
31   std::string error_message;
32 
33   typedef benchmark::BenchmarkReporter::Run Run;
34 
CheckRun__anon6563ee4f0111::TestCase35   void CheckRun(Run const& run) const {
36     CHECK(name == run.benchmark_name) << "expected " << name << " got "
37                                       << run.benchmark_name;
38     CHECK(error_occurred == run.error_occurred);
39     CHECK(error_message == run.error_message);
40     if (error_occurred) {
41       // CHECK(run.iterations == 0);
42     } else {
43       CHECK(run.iterations != 0);
44     }
45   }
46 };
47 
48 std::vector<TestCase> ExpectedResults;
49 
AddCases(const char * base_name,std::initializer_list<TestCase> const & v)50 int AddCases(const char* base_name, std::initializer_list<TestCase> const& v) {
51   for (auto TC : v) {
52     TC.name = base_name + TC.name;
53     ExpectedResults.push_back(std::move(TC));
54   }
55   return 0;
56 }
57 
58 #define CONCAT(x, y) CONCAT2(x, y)
59 #define CONCAT2(x, y) x##y
60 #define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases(__VA_ARGS__)
61 
62 }  // end namespace
63 
BM_error_before_running(benchmark::State & state)64 void BM_error_before_running(benchmark::State& state) {
65   state.SkipWithError("error message");
66   while (state.KeepRunning()) {
67     assert(false);
68   }
69 }
70 BENCHMARK(BM_error_before_running);
71 ADD_CASES("BM_error_before_running", {{"", true, "error message"}});
72 
BM_error_before_running_range_for(benchmark::State & state)73 void BM_error_before_running_range_for(benchmark::State& state) {
74   state.SkipWithError("error message");
75   for (auto _ : state) {
76     assert(false);
77   }
78 }
79 BENCHMARK(BM_error_before_running_range_for);
80 ADD_CASES("BM_error_before_running_range_for", {{"", true, "error message"}});
81 
BM_error_during_running(benchmark::State & state)82 void BM_error_during_running(benchmark::State& state) {
83   int first_iter = true;
84   while (state.KeepRunning()) {
85     if (state.range(0) == 1 && state.thread_index <= (state.threads / 2)) {
86       assert(first_iter);
87       first_iter = false;
88       state.SkipWithError("error message");
89     } else {
90       state.PauseTiming();
91       state.ResumeTiming();
92     }
93   }
94 }
95 BENCHMARK(BM_error_during_running)->Arg(1)->Arg(2)->ThreadRange(1, 8);
96 ADD_CASES("BM_error_during_running", {{"/1/threads:1", true, "error message"},
97                                       {"/1/threads:2", true, "error message"},
98                                       {"/1/threads:4", true, "error message"},
99                                       {"/1/threads:8", true, "error message"},
100                                       {"/2/threads:1", false, ""},
101                                       {"/2/threads:2", false, ""},
102                                       {"/2/threads:4", false, ""},
103                                       {"/2/threads:8", false, ""}});
104 
BM_error_during_running_ranged_for(benchmark::State & state)105 void BM_error_during_running_ranged_for(benchmark::State& state) {
106   assert(state.max_iterations > 3 && "test requires at least a few iterations");
107   int first_iter = true;
108   // NOTE: Users should not write the for loop explicitly.
109   for (auto It = state.begin(), End = state.end(); It != End; ++It) {
110     if (state.range(0) == 1) {
111       assert(first_iter);
112       first_iter = false;
113       state.SkipWithError("error message");
114       // Test the unfortunate but documented behavior that the ranged-for loop
115       // doesn't automatically terminate when SkipWithError is set.
116       assert(++It != End);
117       break; // Required behavior
118     }
119   }
120 }
121 BENCHMARK(BM_error_during_running_ranged_for)->Arg(1)->Arg(2)->Iterations(5);
122 ADD_CASES("BM_error_during_running_ranged_for",
123           {{"/1/iterations:5", true, "error message"},
124            {"/2/iterations:5", false, ""}});
125 
126 
127 
BM_error_after_running(benchmark::State & state)128 void BM_error_after_running(benchmark::State& state) {
129   for (auto _ : state) {
130     benchmark::DoNotOptimize(state.iterations());
131   }
132   if (state.thread_index <= (state.threads / 2))
133     state.SkipWithError("error message");
134 }
135 BENCHMARK(BM_error_after_running)->ThreadRange(1, 8);
136 ADD_CASES("BM_error_after_running", {{"/threads:1", true, "error message"},
137                                      {"/threads:2", true, "error message"},
138                                      {"/threads:4", true, "error message"},
139                                      {"/threads:8", true, "error message"}});
140 
BM_error_while_paused(benchmark::State & state)141 void BM_error_while_paused(benchmark::State& state) {
142   bool first_iter = true;
143   while (state.KeepRunning()) {
144     if (state.range(0) == 1 && state.thread_index <= (state.threads / 2)) {
145       assert(first_iter);
146       first_iter = false;
147       state.PauseTiming();
148       state.SkipWithError("error message");
149     } else {
150       state.PauseTiming();
151       state.ResumeTiming();
152     }
153   }
154 }
155 BENCHMARK(BM_error_while_paused)->Arg(1)->Arg(2)->ThreadRange(1, 8);
156 ADD_CASES("BM_error_while_paused", {{"/1/threads:1", true, "error message"},
157                                     {"/1/threads:2", true, "error message"},
158                                     {"/1/threads:4", true, "error message"},
159                                     {"/1/threads:8", true, "error message"},
160                                     {"/2/threads:1", false, ""},
161                                     {"/2/threads:2", false, ""},
162                                     {"/2/threads:4", false, ""},
163                                     {"/2/threads:8", false, ""}});
164 
main(int argc,char * argv[])165 int main(int argc, char* argv[]) {
166   benchmark::Initialize(&argc, argv);
167 
168   TestReporter test_reporter;
169   benchmark::RunSpecifiedBenchmarks(&test_reporter);
170 
171   typedef benchmark::BenchmarkReporter::Run Run;
172   auto EB = ExpectedResults.begin();
173 
174   for (Run const& run : test_reporter.all_runs_) {
175     assert(EB != ExpectedResults.end());
176     EB->CheckRun(run);
177     ++EB;
178   }
179   assert(EB == ExpectedResults.end());
180 
181   return 0;
182 }
183