| |
| #undef NDEBUG |
| #include <cassert> |
| #include <vector> |
| |
| #include "../src/check.h" // NOTE: check.h is for internal use only! |
| #include "benchmark/benchmark.h" |
| |
| namespace { |
| |
| class TestReporter : public benchmark::ConsoleReporter { |
| public: |
| virtual void ReportRuns(const std::vector<Run>& report) { |
| all_runs_.insert(all_runs_.end(), begin(report), end(report)); |
| ConsoleReporter::ReportRuns(report); |
| } |
| |
| std::vector<Run> all_runs_; |
| }; |
| |
| struct TestCase { |
| std::string name; |
| const char* label; |
| // Note: not explicit as we rely on it being converted through ADD_CASES. |
| TestCase(const char* xname) : TestCase(xname, nullptr) {} |
| TestCase(const char* xname, const char* xlabel) |
| : name(xname), label(xlabel) {} |
| |
| typedef benchmark::BenchmarkReporter::Run Run; |
| |
| void CheckRun(Run const& run) const { |
| // clang-format off |
| CHECK(name == run.benchmark_name()) << "expected " << name << " got " |
| << run.benchmark_name(); |
| if (label) { |
| CHECK(run.report_label == label) << "expected " << label << " got " |
| << run.report_label; |
| } else { |
| CHECK(run.report_label == ""); |
| } |
| // clang-format on |
| } |
| }; |
| |
| std::vector<TestCase> ExpectedResults; |
| |
| int AddCases(std::initializer_list<TestCase> const& v) { |
| for (auto N : v) { |
| ExpectedResults.push_back(N); |
| } |
| return 0; |
| } |
| |
| #define CONCAT(x, y) CONCAT2(x, y) |
| #define CONCAT2(x, y) x##y |
| #define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases({__VA_ARGS__}) |
| |
| } // end namespace |
| |
| typedef benchmark::internal::Benchmark* ReturnVal; |
| |
| //----------------------------------------------------------------------------// |
| // Test RegisterBenchmark with no additional arguments |
| //----------------------------------------------------------------------------// |
| void BM_function(benchmark::State& state) { |
| for (auto _ : state) { |
| } |
| } |
| BENCHMARK(BM_function); |
| ReturnVal dummy = benchmark::RegisterBenchmark( |
| "BM_function_manual_registration", BM_function); |
| ADD_CASES({"BM_function"}, {"BM_function_manual_registration"}); |
| |
| //----------------------------------------------------------------------------// |
| // Test RegisterBenchmark with additional arguments |
| // Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they |
| // reject the variadic pack expansion of lambda captures. |
| //----------------------------------------------------------------------------// |
| #ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK |
| |
| void BM_extra_args(benchmark::State& st, const char* label) { |
| for (auto _ : st) { |
| } |
| st.SetLabel(label); |
| } |
| int RegisterFromFunction() { |
| std::pair<const char*, const char*> cases[] = { |
| {"test1", "One"}, {"test2", "Two"}, {"test3", "Three"}}; |
| for (auto const& c : cases) |
| benchmark::RegisterBenchmark(c.first, &BM_extra_args, c.second); |
| return 0; |
| } |
| int dummy2 = RegisterFromFunction(); |
| ADD_CASES({"test1", "One"}, {"test2", "Two"}, {"test3", "Three"}); |
| |
| #endif // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK |
| |
| //----------------------------------------------------------------------------// |
| // Test RegisterBenchmark with different callable types |
| //----------------------------------------------------------------------------// |
| |
| struct CustomFixture { |
| void operator()(benchmark::State& st) { |
| for (auto _ : st) { |
| } |
| } |
| }; |
| |
| void TestRegistrationAtRuntime() { |
| #ifdef BENCHMARK_HAS_CXX11 |
| { |
| CustomFixture fx; |
| benchmark::RegisterBenchmark("custom_fixture", fx); |
| AddCases({"custom_fixture"}); |
| } |
| #endif |
| #ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK |
| { |
| const char* x = "42"; |
| auto capturing_lam = [=](benchmark::State& st) { |
| for (auto _ : st) { |
| } |
| st.SetLabel(x); |
| }; |
| benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam); |
| AddCases({{"lambda_benchmark", x}}); |
| } |
| #endif |
| } |
| |
| // Test that all benchmarks, registered at either during static init or runtime, |
| // are run and the results are passed to the reported. |
| void RunTestOne() { |
| TestRegistrationAtRuntime(); |
| |
| TestReporter test_reporter; |
| benchmark::RunSpecifiedBenchmarks(&test_reporter); |
| |
| typedef benchmark::BenchmarkReporter::Run Run; |
| auto EB = ExpectedResults.begin(); |
| |
| for (Run const& run : test_reporter.all_runs_) { |
| assert(EB != ExpectedResults.end()); |
| EB->CheckRun(run); |
| ++EB; |
| } |
| assert(EB == ExpectedResults.end()); |
| } |
| |
| // Test that ClearRegisteredBenchmarks() clears all previously registered |
| // benchmarks. |
| // Also test that new benchmarks can be registered and ran afterwards. |
| void RunTestTwo() { |
| assert(ExpectedResults.size() != 0 && |
| "must have at least one registered benchmark"); |
| ExpectedResults.clear(); |
| benchmark::ClearRegisteredBenchmarks(); |
| |
| TestReporter test_reporter; |
| size_t num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter); |
| assert(num_ran == 0); |
| assert(test_reporter.all_runs_.begin() == test_reporter.all_runs_.end()); |
| |
| TestRegistrationAtRuntime(); |
| num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter); |
| assert(num_ran == ExpectedResults.size()); |
| |
| typedef benchmark::BenchmarkReporter::Run Run; |
| auto EB = ExpectedResults.begin(); |
| |
| for (Run const& run : test_reporter.all_runs_) { |
| assert(EB != ExpectedResults.end()); |
| EB->CheckRun(run); |
| ++EB; |
| } |
| assert(EB == ExpectedResults.end()); |
| } |
| |
| int main(int argc, char* argv[]) { |
| benchmark::Initialize(&argc, argv); |
| |
| RunTestOne(); |
| RunTestTwo(); |
| } |