15dda2efdSMircea Trofin
25dda2efdSMircea Trofin #undef NDEBUG
35dda2efdSMircea Trofin #include <cassert>
45dda2efdSMircea Trofin #include <vector>
55dda2efdSMircea Trofin
65dda2efdSMircea Trofin #include "../src/check.h" // NOTE: check.h is for internal use only!
75dda2efdSMircea Trofin #include "benchmark/benchmark.h"
85dda2efdSMircea Trofin
95dda2efdSMircea Trofin namespace {
105dda2efdSMircea Trofin
115dda2efdSMircea Trofin class TestReporter : public benchmark::ConsoleReporter {
125dda2efdSMircea Trofin public:
ReportContext(const Context & context)13*a5b79717SMircea Trofin bool ReportContext(const Context& context) override {
145dda2efdSMircea Trofin return ConsoleReporter::ReportContext(context);
155dda2efdSMircea Trofin };
165dda2efdSMircea Trofin
ReportRuns(const std::vector<Run> & report)17*a5b79717SMircea Trofin void ReportRuns(const std::vector<Run>& report) override {
185dda2efdSMircea Trofin all_runs_.insert(all_runs_.end(), begin(report), end(report));
195dda2efdSMircea Trofin ConsoleReporter::ReportRuns(report);
205dda2efdSMircea Trofin }
215dda2efdSMircea Trofin
TestReporter()225dda2efdSMircea Trofin TestReporter() {}
~TestReporter()23*a5b79717SMircea Trofin ~TestReporter() override {}
245dda2efdSMircea Trofin
255dda2efdSMircea Trofin mutable std::vector<Run> all_runs_;
265dda2efdSMircea Trofin };
275dda2efdSMircea Trofin
285dda2efdSMircea Trofin struct TestCase {
295dda2efdSMircea Trofin std::string name;
305dda2efdSMircea Trofin bool error_occurred;
315dda2efdSMircea Trofin std::string error_message;
325dda2efdSMircea Trofin
335dda2efdSMircea Trofin typedef benchmark::BenchmarkReporter::Run Run;
345dda2efdSMircea Trofin
CheckRun__anon88acd1000111::TestCase355dda2efdSMircea Trofin void CheckRun(Run const& run) const {
36a290770fSMircea Trofin BM_CHECK(name == run.benchmark_name())
375dda2efdSMircea Trofin << "expected " << name << " got " << run.benchmark_name();
38*a5b79717SMircea Trofin BM_CHECK_EQ(error_occurred,
39*a5b79717SMircea Trofin benchmark::internal::SkippedWithError == run.skipped);
40*a5b79717SMircea Trofin BM_CHECK(error_message == run.skip_message);
415dda2efdSMircea Trofin if (error_occurred) {
42a290770fSMircea Trofin // BM_CHECK(run.iterations == 0);
435dda2efdSMircea Trofin } else {
44a290770fSMircea Trofin BM_CHECK(run.iterations != 0);
455dda2efdSMircea Trofin }
465dda2efdSMircea Trofin }
475dda2efdSMircea Trofin };
485dda2efdSMircea Trofin
495dda2efdSMircea Trofin std::vector<TestCase> ExpectedResults;
505dda2efdSMircea Trofin
AddCases(const std::string & base_name,std::initializer_list<TestCase> const & v)51*a5b79717SMircea Trofin int AddCases(const std::string& base_name,
52*a5b79717SMircea Trofin std::initializer_list<TestCase> const& v) {
535dda2efdSMircea Trofin for (auto TC : v) {
545dda2efdSMircea Trofin TC.name = base_name + TC.name;
555dda2efdSMircea Trofin ExpectedResults.push_back(std::move(TC));
565dda2efdSMircea Trofin }
575dda2efdSMircea Trofin return 0;
585dda2efdSMircea Trofin }
595dda2efdSMircea Trofin
605dda2efdSMircea Trofin #define CONCAT(x, y) CONCAT2(x, y)
615dda2efdSMircea Trofin #define CONCAT2(x, y) x##y
625dda2efdSMircea Trofin #define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases(__VA_ARGS__)
635dda2efdSMircea Trofin
645dda2efdSMircea Trofin } // end namespace
655dda2efdSMircea Trofin
BM_error_no_running(benchmark::State & state)665dda2efdSMircea Trofin void BM_error_no_running(benchmark::State& state) {
675dda2efdSMircea Trofin state.SkipWithError("error message");
685dda2efdSMircea Trofin }
695dda2efdSMircea Trofin BENCHMARK(BM_error_no_running);
705dda2efdSMircea Trofin ADD_CASES("BM_error_no_running", {{"", true, "error message"}});
715dda2efdSMircea Trofin
BM_error_before_running(benchmark::State & state)725dda2efdSMircea Trofin void BM_error_before_running(benchmark::State& state) {
735dda2efdSMircea Trofin state.SkipWithError("error message");
745dda2efdSMircea Trofin while (state.KeepRunning()) {
755dda2efdSMircea Trofin assert(false);
765dda2efdSMircea Trofin }
775dda2efdSMircea Trofin }
785dda2efdSMircea Trofin BENCHMARK(BM_error_before_running);
795dda2efdSMircea Trofin ADD_CASES("BM_error_before_running", {{"", true, "error message"}});
805dda2efdSMircea Trofin
BM_error_before_running_batch(benchmark::State & state)815dda2efdSMircea Trofin void BM_error_before_running_batch(benchmark::State& state) {
825dda2efdSMircea Trofin state.SkipWithError("error message");
835dda2efdSMircea Trofin while (state.KeepRunningBatch(17)) {
845dda2efdSMircea Trofin assert(false);
855dda2efdSMircea Trofin }
865dda2efdSMircea Trofin }
875dda2efdSMircea Trofin BENCHMARK(BM_error_before_running_batch);
885dda2efdSMircea Trofin ADD_CASES("BM_error_before_running_batch", {{"", true, "error message"}});
895dda2efdSMircea Trofin
BM_error_before_running_range_for(benchmark::State & state)905dda2efdSMircea Trofin void BM_error_before_running_range_for(benchmark::State& state) {
915dda2efdSMircea Trofin state.SkipWithError("error message");
925dda2efdSMircea Trofin for (auto _ : state) {
935dda2efdSMircea Trofin assert(false);
945dda2efdSMircea Trofin }
955dda2efdSMircea Trofin }
965dda2efdSMircea Trofin BENCHMARK(BM_error_before_running_range_for);
975dda2efdSMircea Trofin ADD_CASES("BM_error_before_running_range_for", {{"", true, "error message"}});
985dda2efdSMircea Trofin
BM_error_during_running(benchmark::State & state)995dda2efdSMircea Trofin void BM_error_during_running(benchmark::State& state) {
1005dda2efdSMircea Trofin int first_iter = true;
1015dda2efdSMircea Trofin while (state.KeepRunning()) {
102a290770fSMircea Trofin if (state.range(0) == 1 && state.thread_index() <= (state.threads() / 2)) {
1035dda2efdSMircea Trofin assert(first_iter);
1045dda2efdSMircea Trofin first_iter = false;
1055dda2efdSMircea Trofin state.SkipWithError("error message");
1065dda2efdSMircea Trofin } else {
1075dda2efdSMircea Trofin state.PauseTiming();
1085dda2efdSMircea Trofin state.ResumeTiming();
1095dda2efdSMircea Trofin }
1105dda2efdSMircea Trofin }
1115dda2efdSMircea Trofin }
1125dda2efdSMircea Trofin BENCHMARK(BM_error_during_running)->Arg(1)->Arg(2)->ThreadRange(1, 8);
1135dda2efdSMircea Trofin ADD_CASES("BM_error_during_running", {{"/1/threads:1", true, "error message"},
1145dda2efdSMircea Trofin {"/1/threads:2", true, "error message"},
1155dda2efdSMircea Trofin {"/1/threads:4", true, "error message"},
1165dda2efdSMircea Trofin {"/1/threads:8", true, "error message"},
1175dda2efdSMircea Trofin {"/2/threads:1", false, ""},
1185dda2efdSMircea Trofin {"/2/threads:2", false, ""},
1195dda2efdSMircea Trofin {"/2/threads:4", false, ""},
1205dda2efdSMircea Trofin {"/2/threads:8", false, ""}});
1215dda2efdSMircea Trofin
BM_error_during_running_ranged_for(benchmark::State & state)1225dda2efdSMircea Trofin void BM_error_during_running_ranged_for(benchmark::State& state) {
1235dda2efdSMircea Trofin assert(state.max_iterations > 3 && "test requires at least a few iterations");
124a290770fSMircea Trofin bool first_iter = true;
1255dda2efdSMircea Trofin // NOTE: Users should not write the for loop explicitly.
1265dda2efdSMircea Trofin for (auto It = state.begin(), End = state.end(); It != End; ++It) {
1275dda2efdSMircea Trofin if (state.range(0) == 1) {
1285dda2efdSMircea Trofin assert(first_iter);
1295dda2efdSMircea Trofin first_iter = false;
130a290770fSMircea Trofin (void)first_iter;
1315dda2efdSMircea Trofin state.SkipWithError("error message");
1325dda2efdSMircea Trofin // Test the unfortunate but documented behavior that the ranged-for loop
1335dda2efdSMircea Trofin // doesn't automatically terminate when SkipWithError is set.
1345dda2efdSMircea Trofin assert(++It != End);
1355dda2efdSMircea Trofin break; // Required behavior
1365dda2efdSMircea Trofin }
1375dda2efdSMircea Trofin }
1385dda2efdSMircea Trofin }
1395dda2efdSMircea Trofin BENCHMARK(BM_error_during_running_ranged_for)->Arg(1)->Arg(2)->Iterations(5);
1405dda2efdSMircea Trofin ADD_CASES("BM_error_during_running_ranged_for",
1415dda2efdSMircea Trofin {{"/1/iterations:5", true, "error message"},
1425dda2efdSMircea Trofin {"/2/iterations:5", false, ""}});
1435dda2efdSMircea Trofin
BM_error_after_running(benchmark::State & state)1445dda2efdSMircea Trofin void BM_error_after_running(benchmark::State& state) {
1455dda2efdSMircea Trofin for (auto _ : state) {
146*a5b79717SMircea Trofin auto iterations = double(state.iterations()) * double(state.iterations());
147*a5b79717SMircea Trofin benchmark::DoNotOptimize(iterations);
1485dda2efdSMircea Trofin }
149a290770fSMircea Trofin if (state.thread_index() <= (state.threads() / 2))
1505dda2efdSMircea Trofin state.SkipWithError("error message");
1515dda2efdSMircea Trofin }
1525dda2efdSMircea Trofin BENCHMARK(BM_error_after_running)->ThreadRange(1, 8);
1535dda2efdSMircea Trofin ADD_CASES("BM_error_after_running", {{"/threads:1", true, "error message"},
1545dda2efdSMircea Trofin {"/threads:2", true, "error message"},
1555dda2efdSMircea Trofin {"/threads:4", true, "error message"},
1565dda2efdSMircea Trofin {"/threads:8", true, "error message"}});
1575dda2efdSMircea Trofin
BM_error_while_paused(benchmark::State & state)1585dda2efdSMircea Trofin void BM_error_while_paused(benchmark::State& state) {
1595dda2efdSMircea Trofin bool first_iter = true;
1605dda2efdSMircea Trofin while (state.KeepRunning()) {
161a290770fSMircea Trofin if (state.range(0) == 1 && state.thread_index() <= (state.threads() / 2)) {
1625dda2efdSMircea Trofin assert(first_iter);
1635dda2efdSMircea Trofin first_iter = false;
1645dda2efdSMircea Trofin state.PauseTiming();
1655dda2efdSMircea Trofin state.SkipWithError("error message");
1665dda2efdSMircea Trofin } else {
1675dda2efdSMircea Trofin state.PauseTiming();
1685dda2efdSMircea Trofin state.ResumeTiming();
1695dda2efdSMircea Trofin }
1705dda2efdSMircea Trofin }
1715dda2efdSMircea Trofin }
1725dda2efdSMircea Trofin BENCHMARK(BM_error_while_paused)->Arg(1)->Arg(2)->ThreadRange(1, 8);
1735dda2efdSMircea Trofin ADD_CASES("BM_error_while_paused", {{"/1/threads:1", true, "error message"},
1745dda2efdSMircea Trofin {"/1/threads:2", true, "error message"},
1755dda2efdSMircea Trofin {"/1/threads:4", true, "error message"},
1765dda2efdSMircea Trofin {"/1/threads:8", true, "error message"},
1775dda2efdSMircea Trofin {"/2/threads:1", false, ""},
1785dda2efdSMircea Trofin {"/2/threads:2", false, ""},
1795dda2efdSMircea Trofin {"/2/threads:4", false, ""},
1805dda2efdSMircea Trofin {"/2/threads:8", false, ""}});
1815dda2efdSMircea Trofin
main(int argc,char * argv[])1825dda2efdSMircea Trofin int main(int argc, char* argv[]) {
1835dda2efdSMircea Trofin benchmark::Initialize(&argc, argv);
1845dda2efdSMircea Trofin
1855dda2efdSMircea Trofin TestReporter test_reporter;
1865dda2efdSMircea Trofin benchmark::RunSpecifiedBenchmarks(&test_reporter);
1875dda2efdSMircea Trofin
1885dda2efdSMircea Trofin typedef benchmark::BenchmarkReporter::Run Run;
1895dda2efdSMircea Trofin auto EB = ExpectedResults.begin();
1905dda2efdSMircea Trofin
1915dda2efdSMircea Trofin for (Run const& run : test_reporter.all_runs_) {
1925dda2efdSMircea Trofin assert(EB != ExpectedResults.end());
1935dda2efdSMircea Trofin EB->CheckRun(run);
1945dda2efdSMircea Trofin ++EB;
1955dda2efdSMircea Trofin }
1965dda2efdSMircea Trofin assert(EB == ExpectedResults.end());
1975dda2efdSMircea Trofin
1985dda2efdSMircea Trofin return 0;
1995dda2efdSMircea Trofin }
200