]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/unordered/test/helpers/exception_test.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / unordered / test / helpers / exception_test.hpp
1
2 // Copyright 2006-2009 Daniel James.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
7 #define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
8
9 #include "./test.hpp"
10
11 #include <boost/preprocessor/seq/for_each_product.hpp>
12 #include <boost/preprocessor/seq/elem.hpp>
13 #include <boost/preprocessor/cat.hpp>
14
15 # define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
16 UNORDERED_AUTO_TEST(name) \
17 { \
18 test_func< type > fixture; \
19 ::test::lightweight::exception_safety( \
20 fixture, BOOST_STRINGIZE(test_func<type>)); \
21 } \
22
23 # define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
24 UNORDERED_AUTO_TEST(name) \
25 { \
26 for (unsigned i = 0; i < n; ++i) { \
27 test_func< type > fixture; \
28 ::test::lightweight::exception_safety( \
29 fixture, BOOST_STRINGIZE(test_func<type>)); \
30 } \
31 } \
32
33
34 # define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
35
36 #define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
37
38 #define EXCEPTION_TESTS(test_seq, param_seq) \
39 BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
40 (test_seq)((1))(param_seq))
41
42 #define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
43 BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
44 (test_seq)((n))(param_seq))
45
46 #define EXCEPTION_TESTS_OP(r, product) \
47 UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
48 BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
49 BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product)) \
50 ), \
51 BOOST_PP_SEQ_ELEM(0, product), \
52 BOOST_PP_SEQ_ELEM(1, product), \
53 BOOST_PP_SEQ_ELEM(2, product) \
54 ) \
55
56 #define UNORDERED_SCOPE(scope_name) \
57 for(::test::scope_guard unordered_test_guard( \
58 BOOST_STRINGIZE(scope_name)); \
59 !unordered_test_guard.dismissed(); \
60 unordered_test_guard.dismiss()) \
61
62 #define UNORDERED_EPOINT(name) \
63 if(::test::exceptions_enabled) { \
64 UNORDERED_EPOINT_IMPL(name); \
65 } \
66
67 #define ENABLE_EXCEPTIONS \
68 ::test::exceptions_enable BOOST_PP_CAT( \
69 ENABLE_EXCEPTIONS_, __LINE__)(true) \
70
71 #define DISABLE_EXCEPTIONS \
72 ::test::exceptions_enable BOOST_PP_CAT( \
73 ENABLE_EXCEPTIONS_, __LINE__)(false) \
74
75 namespace test {
76 static char const* scope = "";
77 bool exceptions_enabled = false;
78
79 class scope_guard {
80 scope_guard& operator=(scope_guard const&);
81 scope_guard(scope_guard const&);
82
83 char const* old_scope_;
84 char const* scope_;
85 bool dismissed_;
86 public:
87 scope_guard(char const* name)
88 : old_scope_(scope),
89 scope_(name),
90 dismissed_(false)
91 {
92 scope = scope_;
93 }
94
95 ~scope_guard() {
96 if(dismissed_) scope = old_scope_;
97 }
98
99 void dismiss() {
100 dismissed_ = true;
101 }
102
103 bool dismissed() const {
104 return dismissed_;
105 }
106 };
107
108 class exceptions_enable
109 {
110 exceptions_enable& operator=(exceptions_enable const&);
111 exceptions_enable(exceptions_enable const&);
112
113 bool old_value_;
114 bool released_;
115 public:
116 exceptions_enable(bool enable)
117 : old_value_(exceptions_enabled), released_(false)
118 {
119 exceptions_enabled = enable;
120 }
121
122 ~exceptions_enable()
123 {
124 if (!released_) {
125 exceptions_enabled = old_value_;
126 released_ = true;
127 }
128 }
129
130 void release()
131 {
132 if (!released_) {
133 exceptions_enabled = old_value_;
134 released_ = true;
135 }
136 }
137 };
138
139 struct exception_base {
140 struct data_type {};
141 struct strong_type {
142 template <class T> void store(T const&) {}
143 template <class T> void test(T const&) const {}
144 };
145 data_type init() const { return data_type(); }
146 void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
147 };
148
149 template <class T, class P1, class P2, class T2>
150 inline void call_ignore_extra_parameters(
151 void (T::*fn)() const, T2 const& obj,
152 P1&, P2&)
153 {
154 (obj.*fn)();
155 }
156
157 template <class T, class P1, class P2, class T2>
158 inline void call_ignore_extra_parameters(
159 void (T::*fn)(P1&) const, T2 const& obj,
160 P1& p1, P2&)
161 {
162 (obj.*fn)(p1);
163 }
164
165 template <class T, class P1, class P2, class T2>
166 inline void call_ignore_extra_parameters(
167 void (T::*fn)(P1&, P2&) const, T2 const& obj,
168 P1& p1, P2& p2)
169 {
170 (obj.*fn)(p1, p2);
171 }
172
173 template <class T>
174 T const& constant(T const& x) {
175 return x;
176 }
177
178 template <class Test>
179 class test_runner
180 {
181 Test const& test_;
182 bool exception_in_check_;
183
184 test_runner(test_runner const&);
185 test_runner& operator=(test_runner const&);
186 public:
187 test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
188 void run() {
189 DISABLE_EXCEPTIONS;
190 test::scope = "";
191 BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
192 BOOST_DEDUCED_TYPENAME Test::strong_type strong;
193 strong.store(x);
194 try {
195 ENABLE_EXCEPTIONS;
196 call_ignore_extra_parameters<
197 Test,
198 BOOST_DEDUCED_TYPENAME Test::data_type,
199 BOOST_DEDUCED_TYPENAME Test::strong_type
200 >(&Test::run, test_, x, strong);
201 }
202 catch(...) {
203 try {
204 DISABLE_EXCEPTIONS;
205 call_ignore_extra_parameters<
206 Test,
207 BOOST_DEDUCED_TYPENAME Test::data_type const,
208 BOOST_DEDUCED_TYPENAME Test::strong_type const
209 >(&Test::check, test_, constant(x), constant(strong));
210 } catch(...) {
211 exception_in_check_ = true;
212 }
213 throw;
214 }
215 }
216 void end() {
217 if (exception_in_check_) {
218 BOOST_ERROR("Unexcpected exception in test_runner check call.");
219 }
220 }
221 };
222
223 // Quick exception testing based on lightweight test
224
225 namespace lightweight {
226 static int iteration;
227 static int count;
228
229 struct test_exception {
230 char const* name;
231 test_exception(char const* n) : name(n) {}
232 };
233
234 struct test_failure {
235 };
236
237 void epoint(char const* name) {
238 ++count;
239 if(count == iteration) {
240 throw test_exception(name);
241 }
242 }
243
244 template <class Test>
245 void exception_safety(Test const& f, char const* /*name*/) {
246 test_runner<Test> runner(f);
247
248 iteration = 0;
249 bool success = false;
250 char const* error_msg = 0;
251 do {
252 ++iteration;
253 count = 0;
254
255 try {
256 runner.run();
257 success = true;
258 }
259 catch(test_failure) {
260 error_msg = "test_failure caught.";
261 break;
262 }
263 catch(test_exception) {
264 continue;
265 }
266 catch(...) {
267 error_msg = "Unexpected exception.";
268 break;
269 }
270 } while(!success);
271
272 if (error_msg) { BOOST_ERROR(error_msg); }
273 runner.end();
274 }
275 }
276 }
277
278 #endif