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