197 lines · plain
1 2#undef NDEBUG3#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 9namespace {10 11class TestReporter : public benchmark::ConsoleReporter {12 public:13 void ReportRuns(const std::vector<Run>& report) override {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 21struct TestCase {22 const std::string name;23 const std::string label;24 // Note: not explicit as we rely on it being converted through ADD_CASES.25 TestCase(const std::string& xname) : TestCase(xname, "") {}26 TestCase(const std::string& xname, const std::string& xlabel)27 : name(xname), label(xlabel) {}28 29 typedef benchmark::BenchmarkReporter::Run Run;30 31 void CheckRun(Run const& run) const {32 // clang-format off33 BM_CHECK(name == run.benchmark_name()) << "expected " << name << " got "34 << run.benchmark_name();35 if (!label.empty()) {36 BM_CHECK(run.report_label == label) << "expected " << label << " got "37 << run.report_label;38 } else {39 BM_CHECK(run.report_label.empty());40 }41 // clang-format on42 }43};44 45std::vector<TestCase> ExpectedResults;46 47int AddCases(std::initializer_list<TestCase> const& v) {48 for (const 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##y56#define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases({__VA_ARGS__})57 58} // end namespace59 60typedef benchmark::internal::Benchmark* ReturnVal;61 62//----------------------------------------------------------------------------//63// Test RegisterBenchmark with no additional arguments64//----------------------------------------------------------------------------//65void BM_function(benchmark::State& state) {66 for (auto _ : state) {67 }68}69BENCHMARK(BM_function);70ReturnVal dummy = benchmark::RegisterBenchmark(71 "BM_function_manual_registration", BM_function);72ADD_CASES({"BM_function"}, {"BM_function_manual_registration"});73 74//----------------------------------------------------------------------------//75// Test RegisterBenchmark with additional arguments76// Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they77// reject the variadic pack expansion of lambda captures.78//----------------------------------------------------------------------------//79#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK80 81void BM_extra_args(benchmark::State& st, const char* label) {82 for (auto _ : st) {83 }84 st.SetLabel(label);85}86int 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}93int dummy2 = RegisterFromFunction();94ADD_CASES({"test1", "One"}, {"test2", "Two"}, {"test3", "Three"});95 96#endif // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK97 98//----------------------------------------------------------------------------//99// Test RegisterBenchmark with DISABLED_ benchmark100//----------------------------------------------------------------------------//101void DISABLED_BM_function(benchmark::State& state) {102 for (auto _ : state) {103 }104}105BENCHMARK(DISABLED_BM_function);106ReturnVal dummy3 = benchmark::RegisterBenchmark("DISABLED_BM_function_manual",107 DISABLED_BM_function);108// No need to add cases because we don't expect them to run.109 110//----------------------------------------------------------------------------//111// Test RegisterBenchmark with different callable types112//----------------------------------------------------------------------------//113 114struct CustomFixture {115 void operator()(benchmark::State& st) {116 for (auto _ : st) {117 }118 }119};120 121void TestRegistrationAtRuntime() {122#ifdef BENCHMARK_HAS_CXX11123 {124 CustomFixture fx;125 benchmark::RegisterBenchmark("custom_fixture", fx);126 AddCases({std::string("custom_fixture")});127 }128#endif129#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK130 {131 const char* x = "42";132 auto capturing_lam = [=](benchmark::State& st) {133 for (auto _ : st) {134 }135 st.SetLabel(x);136 };137 benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam);138 AddCases({{"lambda_benchmark", x}});139 }140#endif141}142 143// Test that all benchmarks, registered at either during static init or runtime,144// are run and the results are passed to the reported.145void RunTestOne() {146 TestRegistrationAtRuntime();147 148 TestReporter test_reporter;149 benchmark::RunSpecifiedBenchmarks(&test_reporter);150 151 typedef benchmark::BenchmarkReporter::Run Run;152 auto EB = ExpectedResults.begin();153 154 for (Run const& run : test_reporter.all_runs_) {155 assert(EB != ExpectedResults.end());156 EB->CheckRun(run);157 ++EB;158 }159 assert(EB == ExpectedResults.end());160}161 162// Test that ClearRegisteredBenchmarks() clears all previously registered163// benchmarks.164// Also test that new benchmarks can be registered and ran afterwards.165void RunTestTwo() {166 assert(ExpectedResults.size() != 0 &&167 "must have at least one registered benchmark");168 ExpectedResults.clear();169 benchmark::ClearRegisteredBenchmarks();170 171 TestReporter test_reporter;172 size_t num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter);173 assert(num_ran == 0);174 assert(test_reporter.all_runs_.begin() == test_reporter.all_runs_.end());175 176 TestRegistrationAtRuntime();177 num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter);178 assert(num_ran == ExpectedResults.size());179 180 typedef benchmark::BenchmarkReporter::Run Run;181 auto EB = ExpectedResults.begin();182 183 for (Run const& run : test_reporter.all_runs_) {184 assert(EB != ExpectedResults.end());185 EB->CheckRun(run);186 ++EB;187 }188 assert(EB == ExpectedResults.end());189}190 191int main(int argc, char* argv[]) {192 benchmark::Initialize(&argc, argv);193 194 RunTestOne();195 RunTestTwo();196}197