1#include <atomic>
2#include <cassert>
3#include <cstdlib>
4#include <cstring>
5#include <iostream>
6#include <limits>
7#include <string>
8
9#include "benchmark/benchmark.h"
10
11// Test that Setup() and Teardown() are called exactly once
12// for each benchmark run (single-threaded).
13namespace singlethreaded {
14static int setup_call = 0;
15static int teardown_call = 0;
16} // namespace singlethreaded
17static void DoSetup1(const benchmark::State& state) {
18 ++singlethreaded::setup_call;
19
20 // Setup/Teardown should never be called with any thread_idx != 0.
21 assert(state.thread_index() == 0);
22}
23
24static void DoTeardown1(const benchmark::State& state) {
25 ++singlethreaded::teardown_call;
26 assert(state.thread_index() == 0);
27}
28
29static void BM_with_setup(benchmark::State& state) {
30 for (auto s : state) {
31 }
32}
33BENCHMARK(BM_with_setup)
34 ->Arg(x: 1)
35 ->Arg(x: 3)
36 ->Arg(x: 5)
37 ->Arg(x: 7)
38 ->Iterations(n: 100)
39 ->Setup(DoSetup1)
40 ->Teardown(teardown: DoTeardown1);
41
42// Test that Setup() and Teardown() are called once for each group of threads.
43namespace concurrent {
44static std::atomic<int> setup_call(0);
45static std::atomic<int> teardown_call(0);
46static std::atomic<int> func_call(0);
47} // namespace concurrent
48
49static void DoSetup2(const benchmark::State& state) {
50 concurrent::setup_call.fetch_add(i: 1, m: std::memory_order_acquire);
51 assert(state.thread_index() == 0);
52}
53
54static void DoTeardown2(const benchmark::State& state) {
55 concurrent::teardown_call.fetch_add(i: 1, m: std::memory_order_acquire);
56 assert(state.thread_index() == 0);
57}
58
59static void BM_concurrent(benchmark::State& state) {
60 for (auto s : state) {
61 }
62 concurrent::func_call.fetch_add(i: 1, m: std::memory_order_acquire);
63}
64
65BENCHMARK(BM_concurrent)
66 ->Setup(DoSetup2)
67 ->Teardown(teardown: DoTeardown2)
68 ->Iterations(n: 100)
69 ->Threads(t: 5)
70 ->Threads(t: 10)
71 ->Threads(t: 15);
72
73// Testing interaction with Fixture::Setup/Teardown
74namespace fixture_interaction {
75int setup = 0;
76int fixture_setup = 0;
77} // namespace fixture_interaction
78
79#define FIXTURE_BECHMARK_NAME MyFixture
80
81class FIXTURE_BECHMARK_NAME : public ::benchmark::Fixture {
82 public:
83 void SetUp(const ::benchmark::State&) override {
84 fixture_interaction::fixture_setup++;
85 }
86
87 ~FIXTURE_BECHMARK_NAME() override {}
88};
89
90BENCHMARK_F(FIXTURE_BECHMARK_NAME, BM_WithFixture)(benchmark::State& st) {
91 for (auto _ : st) {
92 }
93}
94
95static void DoSetupWithFixture(const benchmark::State&) {
96 fixture_interaction::setup++;
97}
98
99BENCHMARK_REGISTER_F(FIXTURE_BECHMARK_NAME, BM_WithFixture)
100 ->Arg(x: 1)
101 ->Arg(x: 3)
102 ->Arg(x: 5)
103 ->Arg(x: 7)
104 ->Setup(DoSetupWithFixture)
105 ->Repetitions(n: 1)
106 ->Iterations(n: 100);
107
108// Testing repetitions.
109namespace repetitions {
110int setup = 0;
111}
112
113static void DoSetupWithRepetitions(const benchmark::State&) {
114 repetitions::setup++;
115}
116static void BM_WithRep(benchmark::State& state) {
117 for (auto _ : state) {
118 }
119}
120
121BENCHMARK(BM_WithRep)
122 ->Arg(x: 1)
123 ->Arg(x: 3)
124 ->Arg(x: 5)
125 ->Arg(x: 7)
126 ->Setup(DoSetupWithRepetitions)
127 ->Iterations(n: 100)
128 ->Repetitions(n: 4);
129
130int main(int argc, char** argv) {
131 benchmark::Initialize(argc: &argc, argv);
132
133 size_t ret = benchmark::RunSpecifiedBenchmarks(spec: ".");
134 assert(ret > 0);
135
136 // Setup/Teardown is called once for each arg group (1,3,5,7).
137 assert(singlethreaded::setup_call == 4);
138 assert(singlethreaded::teardown_call == 4);
139
140 // 3 group of threads calling this function (3,5,10).
141 assert(concurrent::setup_call.load(std::memory_order_relaxed) == 3);
142 assert(concurrent::teardown_call.load(std::memory_order_relaxed) == 3);
143 assert((5 + 10 + 15) ==
144 concurrent::func_call.load(std::memory_order_relaxed));
145
146 // Setup is called 4 times, once for each arg group (1,3,5,7)
147 assert(fixture_interaction::setup == 4);
148 // Fixture::Setup is called every time the bm routine is run.
149 // The exact number is indeterministic, so we just assert that
150 // it's more than setup.
151 assert(fixture_interaction::fixture_setup > fixture_interaction::setup);
152
153 // Setup is call once for each repetition * num_arg = 4 * 4 = 16.
154 assert(repetitions::setup == 16);
155
156 return 0;
157}
158

source code of third-party/benchmark/test/benchmark_setup_teardown_test.cc