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  void ReportRuns(const std::vector<Run>& report) override {
14a8c51b3fSopenharmony_ci    all_runs_.insert(all_runs_.end(), begin(report), end(report));
15a8c51b3fSopenharmony_ci    ConsoleReporter::ReportRuns(report);
16a8c51b3fSopenharmony_ci  }
17a8c51b3fSopenharmony_ci
18a8c51b3fSopenharmony_ci  std::vector<Run> all_runs_;
19a8c51b3fSopenharmony_ci};
20a8c51b3fSopenharmony_ci
21a8c51b3fSopenharmony_cistruct TestCase {
22a8c51b3fSopenharmony_ci  const std::string name;
23a8c51b3fSopenharmony_ci  const std::string label;
24a8c51b3fSopenharmony_ci  // Note: not explicit as we rely on it being converted through ADD_CASES.
25a8c51b3fSopenharmony_ci  TestCase(const std::string& xname) : TestCase(xname, "") {}
26a8c51b3fSopenharmony_ci  TestCase(const std::string& xname, const std::string& xlabel)
27a8c51b3fSopenharmony_ci      : name(xname), label(xlabel) {}
28a8c51b3fSopenharmony_ci
29a8c51b3fSopenharmony_ci  typedef benchmark::BenchmarkReporter::Run Run;
30a8c51b3fSopenharmony_ci
31a8c51b3fSopenharmony_ci  void CheckRun(Run const& run) const {
32a8c51b3fSopenharmony_ci    // clang-format off
33a8c51b3fSopenharmony_ci    BM_CHECK(name == run.benchmark_name()) << "expected " << name << " got "
34a8c51b3fSopenharmony_ci                                      << run.benchmark_name();
35a8c51b3fSopenharmony_ci    if (!label.empty()) {
36a8c51b3fSopenharmony_ci      BM_CHECK(run.report_label == label) << "expected " << label << " got "
37a8c51b3fSopenharmony_ci                                       << run.report_label;
38a8c51b3fSopenharmony_ci    } else {
39a8c51b3fSopenharmony_ci      BM_CHECK(run.report_label.empty());
40a8c51b3fSopenharmony_ci    }
41a8c51b3fSopenharmony_ci    // clang-format on
42a8c51b3fSopenharmony_ci  }
43a8c51b3fSopenharmony_ci};
44a8c51b3fSopenharmony_ci
45a8c51b3fSopenharmony_cistd::vector<TestCase> ExpectedResults;
46a8c51b3fSopenharmony_ci
47a8c51b3fSopenharmony_ciint AddCases(std::initializer_list<TestCase> const& v) {
48a8c51b3fSopenharmony_ci  for (const auto& N : v) {
49a8c51b3fSopenharmony_ci    ExpectedResults.push_back(N);
50a8c51b3fSopenharmony_ci  }
51a8c51b3fSopenharmony_ci  return 0;
52a8c51b3fSopenharmony_ci}
53a8c51b3fSopenharmony_ci
54a8c51b3fSopenharmony_ci#define CONCAT(x, y) CONCAT2(x, y)
55a8c51b3fSopenharmony_ci#define CONCAT2(x, y) x##y
56a8c51b3fSopenharmony_ci#define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases({__VA_ARGS__})
57a8c51b3fSopenharmony_ci
58a8c51b3fSopenharmony_ci}  // end namespace
59a8c51b3fSopenharmony_ci
60a8c51b3fSopenharmony_citypedef benchmark::internal::Benchmark* ReturnVal;
61a8c51b3fSopenharmony_ci
62a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
63a8c51b3fSopenharmony_ci// Test RegisterBenchmark with no additional arguments
64a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
65a8c51b3fSopenharmony_civoid BM_function(benchmark::State& state) {
66a8c51b3fSopenharmony_ci  for (auto _ : state) {
67a8c51b3fSopenharmony_ci  }
68a8c51b3fSopenharmony_ci}
69a8c51b3fSopenharmony_ciBENCHMARK(BM_function);
70a8c51b3fSopenharmony_ciReturnVal dummy = benchmark::RegisterBenchmark(
71a8c51b3fSopenharmony_ci    "BM_function_manual_registration", BM_function);
72a8c51b3fSopenharmony_ciADD_CASES({"BM_function"}, {"BM_function_manual_registration"});
73a8c51b3fSopenharmony_ci
74a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
75a8c51b3fSopenharmony_ci// Test RegisterBenchmark with additional arguments
76a8c51b3fSopenharmony_ci// Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they
77a8c51b3fSopenharmony_ci//       reject the variadic pack expansion of lambda captures.
78a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
79a8c51b3fSopenharmony_ci#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
80a8c51b3fSopenharmony_ci
81a8c51b3fSopenharmony_civoid BM_extra_args(benchmark::State& st, const char* label) {
82a8c51b3fSopenharmony_ci  for (auto _ : st) {
83a8c51b3fSopenharmony_ci  }
84a8c51b3fSopenharmony_ci  st.SetLabel(label);
85a8c51b3fSopenharmony_ci}
86a8c51b3fSopenharmony_ciint RegisterFromFunction() {
87a8c51b3fSopenharmony_ci  std::pair<const char*, const char*> cases[] = {
88a8c51b3fSopenharmony_ci      {"test1", "One"}, {"test2", "Two"}, {"test3", "Three"}};
89a8c51b3fSopenharmony_ci  for (auto const& c : cases)
90a8c51b3fSopenharmony_ci    benchmark::RegisterBenchmark(c.first, &BM_extra_args, c.second);
91a8c51b3fSopenharmony_ci  return 0;
92a8c51b3fSopenharmony_ci}
93a8c51b3fSopenharmony_ciint dummy2 = RegisterFromFunction();
94a8c51b3fSopenharmony_ciADD_CASES({"test1", "One"}, {"test2", "Two"}, {"test3", "Three"});
95a8c51b3fSopenharmony_ci
96a8c51b3fSopenharmony_ci#endif  // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
97a8c51b3fSopenharmony_ci
98a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
99a8c51b3fSopenharmony_ci// Test RegisterBenchmark with DISABLED_ benchmark
100a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
101a8c51b3fSopenharmony_civoid DISABLED_BM_function(benchmark::State& state) {
102a8c51b3fSopenharmony_ci  for (auto _ : state) {
103a8c51b3fSopenharmony_ci  }
104a8c51b3fSopenharmony_ci}
105a8c51b3fSopenharmony_ciBENCHMARK(DISABLED_BM_function);
106a8c51b3fSopenharmony_ciReturnVal dummy3 = benchmark::RegisterBenchmark("DISABLED_BM_function_manual",
107a8c51b3fSopenharmony_ci                                                DISABLED_BM_function);
108a8c51b3fSopenharmony_ci// No need to add cases because we don't expect them to run.
109a8c51b3fSopenharmony_ci
110a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
111a8c51b3fSopenharmony_ci// Test RegisterBenchmark with different callable types
112a8c51b3fSopenharmony_ci//----------------------------------------------------------------------------//
113a8c51b3fSopenharmony_ci
114a8c51b3fSopenharmony_cistruct CustomFixture {
115a8c51b3fSopenharmony_ci  void operator()(benchmark::State& st) {
116a8c51b3fSopenharmony_ci    for (auto _ : st) {
117a8c51b3fSopenharmony_ci    }
118a8c51b3fSopenharmony_ci  }
119a8c51b3fSopenharmony_ci};
120a8c51b3fSopenharmony_ci
121a8c51b3fSopenharmony_civoid TestRegistrationAtRuntime() {
122a8c51b3fSopenharmony_ci#ifdef BENCHMARK_HAS_CXX11
123a8c51b3fSopenharmony_ci  {
124a8c51b3fSopenharmony_ci    CustomFixture fx;
125a8c51b3fSopenharmony_ci    benchmark::RegisterBenchmark("custom_fixture", fx);
126a8c51b3fSopenharmony_ci    AddCases({std::string("custom_fixture")});
127a8c51b3fSopenharmony_ci  }
128a8c51b3fSopenharmony_ci#endif
129a8c51b3fSopenharmony_ci#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
130a8c51b3fSopenharmony_ci  {
131a8c51b3fSopenharmony_ci    const char* x = "42";
132a8c51b3fSopenharmony_ci    auto capturing_lam = [=](benchmark::State& st) {
133a8c51b3fSopenharmony_ci      for (auto _ : st) {
134a8c51b3fSopenharmony_ci      }
135a8c51b3fSopenharmony_ci      st.SetLabel(x);
136a8c51b3fSopenharmony_ci    };
137a8c51b3fSopenharmony_ci    benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam);
138a8c51b3fSopenharmony_ci    AddCases({{"lambda_benchmark", x}});
139a8c51b3fSopenharmony_ci  }
140a8c51b3fSopenharmony_ci#endif
141a8c51b3fSopenharmony_ci}
142a8c51b3fSopenharmony_ci
143a8c51b3fSopenharmony_ci// Test that all benchmarks, registered at either during static init or runtime,
144a8c51b3fSopenharmony_ci// are run and the results are passed to the reported.
145a8c51b3fSopenharmony_civoid RunTestOne() {
146a8c51b3fSopenharmony_ci  TestRegistrationAtRuntime();
147a8c51b3fSopenharmony_ci
148a8c51b3fSopenharmony_ci  TestReporter test_reporter;
149a8c51b3fSopenharmony_ci  benchmark::RunSpecifiedBenchmarks(&test_reporter);
150a8c51b3fSopenharmony_ci
151a8c51b3fSopenharmony_ci  typedef benchmark::BenchmarkReporter::Run Run;
152a8c51b3fSopenharmony_ci  auto EB = ExpectedResults.begin();
153a8c51b3fSopenharmony_ci
154a8c51b3fSopenharmony_ci  for (Run const& run : test_reporter.all_runs_) {
155a8c51b3fSopenharmony_ci    assert(EB != ExpectedResults.end());
156a8c51b3fSopenharmony_ci    EB->CheckRun(run);
157a8c51b3fSopenharmony_ci    ++EB;
158a8c51b3fSopenharmony_ci  }
159a8c51b3fSopenharmony_ci  assert(EB == ExpectedResults.end());
160a8c51b3fSopenharmony_ci}
161a8c51b3fSopenharmony_ci
162a8c51b3fSopenharmony_ci// Test that ClearRegisteredBenchmarks() clears all previously registered
163a8c51b3fSopenharmony_ci// benchmarks.
164a8c51b3fSopenharmony_ci// Also test that new benchmarks can be registered and ran afterwards.
165a8c51b3fSopenharmony_civoid RunTestTwo() {
166a8c51b3fSopenharmony_ci  assert(ExpectedResults.size() != 0 &&
167a8c51b3fSopenharmony_ci         "must have at least one registered benchmark");
168a8c51b3fSopenharmony_ci  ExpectedResults.clear();
169a8c51b3fSopenharmony_ci  benchmark::ClearRegisteredBenchmarks();
170a8c51b3fSopenharmony_ci
171a8c51b3fSopenharmony_ci  TestReporter test_reporter;
172a8c51b3fSopenharmony_ci  size_t num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter);
173a8c51b3fSopenharmony_ci  assert(num_ran == 0);
174a8c51b3fSopenharmony_ci  assert(test_reporter.all_runs_.begin() == test_reporter.all_runs_.end());
175a8c51b3fSopenharmony_ci
176a8c51b3fSopenharmony_ci  TestRegistrationAtRuntime();
177a8c51b3fSopenharmony_ci  num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter);
178a8c51b3fSopenharmony_ci  assert(num_ran == ExpectedResults.size());
179a8c51b3fSopenharmony_ci
180a8c51b3fSopenharmony_ci  typedef benchmark::BenchmarkReporter::Run Run;
181a8c51b3fSopenharmony_ci  auto EB = ExpectedResults.begin();
182a8c51b3fSopenharmony_ci
183a8c51b3fSopenharmony_ci  for (Run const& run : test_reporter.all_runs_) {
184a8c51b3fSopenharmony_ci    assert(EB != ExpectedResults.end());
185a8c51b3fSopenharmony_ci    EB->CheckRun(run);
186a8c51b3fSopenharmony_ci    ++EB;
187a8c51b3fSopenharmony_ci  }
188a8c51b3fSopenharmony_ci  assert(EB == ExpectedResults.end());
189a8c51b3fSopenharmony_ci}
190a8c51b3fSopenharmony_ci
191a8c51b3fSopenharmony_ciint main(int argc, char* argv[]) {
192a8c51b3fSopenharmony_ci  benchmark::Initialize(&argc, argv);
193a8c51b3fSopenharmony_ci
194a8c51b3fSopenharmony_ci  RunTestOne();
195a8c51b3fSopenharmony_ci  RunTestTwo();
196a8c51b3fSopenharmony_ci}
197