1 | #ifndef BANDIT_GRAMMAR_H |
2 | #define BANDIT_GRAMMAR_H |
3 | |
4 | #include <bandit/adapters/adapters.h> |
5 | #include <bandit/reporters/reporters.h> |
6 | #include <bandit/run_policies/run_policy.h> |
7 | |
8 | namespace bandit { |
9 | inline void describe(const std::string& desc, detail::voidfunc_t func, |
10 | detail::listener& listener, detail::contextstack_t& context_stack, |
11 | bool hard_skip = false) { |
12 | listener.context_starting(desc); |
13 | |
14 | context_stack.back()->execution_is_starting(); |
15 | |
16 | detail::bandit_context ctxt(desc, hard_skip); |
17 | |
18 | context_stack.push_back(&ctxt); |
19 | |
20 | try { |
21 | func(); |
22 | } catch (const bandit::detail::test_run_error& error) { |
23 | listener.test_run_error(desc, error); |
24 | } |
25 | |
26 | context_stack.pop_back(); |
27 | |
28 | listener.context_ended(desc); |
29 | } |
30 | |
31 | inline void describe(const std::string& desc, detail::voidfunc_t func, bool hard_skip = false) { |
32 | describe(desc, func, detail::registered_listener(), detail::context_stack(), hard_skip); |
33 | } |
34 | |
35 | inline void describe_skip(const std::string& desc, detail::voidfunc_t func, |
36 | detail::listener& listener, detail::contextstack_t& context_stack) { |
37 | describe(desc, func, listener, context_stack, true); |
38 | } |
39 | |
40 | inline void describe_skip(const std::string& desc, detail::voidfunc_t func) { |
41 | describe_skip(desc, func, detail::registered_listener(), |
42 | detail::context_stack()); |
43 | } |
44 | |
45 | inline void xdescribe(const std::string& desc, detail::voidfunc_t func, |
46 | detail::listener& listener = detail::registered_listener(), |
47 | detail::contextstack_t& context_stack = detail::context_stack()) { |
48 | describe_skip(desc, func, listener, context_stack); |
49 | } |
50 | |
51 | inline void before_each(detail::voidfunc_t func, |
52 | detail::contextstack_t& context_stack) { |
53 | context_stack.back()->register_before_each(func); |
54 | } |
55 | |
56 | inline void before_each(detail::voidfunc_t func) { |
57 | before_each(func, detail::context_stack()); |
58 | } |
59 | |
60 | inline void after_each(detail::voidfunc_t func, |
61 | detail::contextstack_t& context_stack) { |
62 | context_stack.back()->register_after_each(func); |
63 | } |
64 | |
65 | inline void after_each(detail::voidfunc_t func) { |
66 | after_each(func, detail::context_stack()); |
67 | } |
68 | |
69 | inline void it_skip(const std::string& desc, detail::voidfunc_t, detail::listener& listener) { |
70 | listener.it_skip(desc); |
71 | } |
72 | |
73 | inline void it_skip(const std::string& desc, detail::voidfunc_t func) { |
74 | it_skip(desc, func, detail::registered_listener()); |
75 | } |
76 | |
77 | inline void xit(const std::string& desc, detail::voidfunc_t func, |
78 | detail::listener& listener = detail::registered_listener()) { |
79 | it_skip(desc, func, listener); |
80 | } |
81 | |
82 | inline void it(const std::string& desc, detail::voidfunc_t func, detail::listener& listener, |
83 | detail::contextstack_t& context_stack, |
84 | bandit::adapters::assertion_adapter& assertion_adapter, |
85 | detail::run_policy& run_policy, |
86 | bool hard_skip = false) { |
87 | if (hard_skip || !run_policy.should_run(desc, context_stack)) { |
88 | it_skip(desc, func, listener); |
89 | return; |
90 | } |
91 | |
92 | listener.it_starting(desc); |
93 | |
94 | context_stack.back()->execution_is_starting(); |
95 | |
96 | auto try_with_adapter = [&](detail::voidfunc_t do_it) { |
97 | try { |
98 | assertion_adapter.adapt_exceptions([&] { do_it(); }); |
99 | } catch (const bandit::detail::assertion_exception& ex) { |
100 | listener.it_failed(desc, ex); |
101 | run_policy.encountered_failure(); |
102 | } catch (const std::exception& ex) { |
103 | std::string err = std::string("exception: " ) + ex.what(); |
104 | listener.it_failed(desc, bandit::detail::assertion_exception(err)); |
105 | run_policy.encountered_failure(); |
106 | } catch (...) { |
107 | listener.it_unknown_error(desc); |
108 | run_policy.encountered_failure(); |
109 | } |
110 | }; |
111 | |
112 | bool success = false; |
113 | try_with_adapter([&] { |
114 | for (auto context : context_stack) { |
115 | context->run_before_eaches(); |
116 | } |
117 | |
118 | func(); |
119 | success = true; |
120 | }); |
121 | |
122 | try_with_adapter([&] { |
123 | for (auto context : context_stack) { |
124 | context->run_after_eaches(); |
125 | } |
126 | |
127 | if (success) { |
128 | listener.it_succeeded(desc); |
129 | } |
130 | }); |
131 | } |
132 | |
133 | inline void it(const std::string& desc, detail::voidfunc_t func, bool hard_skip = false) { |
134 | it(desc, func, detail::registered_listener(), detail::context_stack(), |
135 | detail::registered_adapter(), detail::registered_run_policy(), hard_skip); |
136 | } |
137 | } |
138 | #endif |
139 | |