1#ifndef BANDIT_CONTEXT_H
2#define BANDIT_CONTEXT_H
3
4#include <algorithm>
5#include <deque>
6#include <list>
7#include <string>
8#include <bandit/types.h>
9#include <bandit/test_run_error.h>
10
11namespace bandit {
12 namespace detail {
13 struct context {
14 virtual ~context() {}
15 virtual const std::string& name() = 0;
16 virtual void execution_is_starting() = 0;
17 virtual void register_before_each(voidfunc_t func) = 0;
18 virtual void register_after_each(voidfunc_t func) = 0;
19 virtual void run_before_eaches() = 0;
20 virtual void run_after_eaches() = 0;
21 virtual bool hard_skip() = 0;
22 };
23
24 struct bandit_context : public context {
25 bandit_context(const std::string& desc, bool hard_skip_a)
26 : desc_(desc), hard_skip_(hard_skip_a), is_executing_(false) {}
27
28 const std::string& name() override {
29 return desc_;
30 }
31
32 void execution_is_starting() override {
33 is_executing_ = true;
34 }
35
36 void register_before_each(voidfunc_t func) override {
37 if (is_executing_) {
38 throw test_run_error("before_each was called after 'describe' or 'it'");
39 }
40
41 before_eaches_.push_back(func);
42 }
43
44 void register_after_each(voidfunc_t func) override {
45 if (is_executing_) {
46 throw test_run_error("after_each was called after 'describe' or 'it'");
47 }
48
49 after_eaches_.push_back(func);
50 }
51
52 void run_before_eaches() override {
53 run_all(before_eaches_);
54 }
55
56 void run_after_eaches() override {
57 run_all(after_eaches_);
58 }
59
60 bool hard_skip() override {
61 return hard_skip_;
62 }
63
64 private:
65 void run_all(const std::list<voidfunc_t>& funcs) {
66 for (auto f : funcs) {
67 f();
68 }
69 }
70
71 std::string desc_;
72 bool hard_skip_;
73 bool is_executing_;
74 std::list<voidfunc_t> before_eaches_;
75 std::list<voidfunc_t> after_eaches_;
76 };
77
78 typedef std::deque<context*> contextstack_t;
79
80 inline contextstack_t& context_stack() {
81 static contextstack_t contexts;
82 return contexts;
83 }
84 }
85}
86#endif
87