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)
6 #if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
7 #define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
11 #include <boost/preprocessor/seq/for_each_product.hpp>
12 #include <boost/preprocessor/seq/elem.hpp>
13 #include <boost/preprocessor/cat.hpp>
15 # define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
16 UNORDERED_AUTO_TEST(name) \
18 test_func< type > fixture; \
19 ::test::lightweight::exception_safety( \
20 fixture, BOOST_STRINGIZE(test_func<type>)); \
23 # define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
24 UNORDERED_AUTO_TEST(name) \
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>)); \
34 # define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
36 #define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
38 #define EXCEPTION_TESTS(test_seq, param_seq) \
39 BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
40 (test_seq)((1))(param_seq))
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))
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)) \
51 BOOST_PP_SEQ_ELEM(0, product), \
52 BOOST_PP_SEQ_ELEM(1, product), \
53 BOOST_PP_SEQ_ELEM(2, product) \
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()) \
62 #define UNORDERED_EPOINT(name) \
63 if(::test::exceptions_enabled) { \
64 UNORDERED_EPOINT_IMPL(name); \
67 #define ENABLE_EXCEPTIONS \
68 ::test::exceptions_enable BOOST_PP_CAT( \
69 ENABLE_EXCEPTIONS_, __LINE__)(true) \
71 #define DISABLE_EXCEPTIONS \
72 ::test::exceptions_enable BOOST_PP_CAT( \
73 ENABLE_EXCEPTIONS_, __LINE__)(false) \
76 static char const* scope = "";
77 bool exceptions_enabled = false;
80 scope_guard& operator=(scope_guard const&);
81 scope_guard(scope_guard const&);
83 char const* old_scope_;
87 scope_guard(char const* name)
96 if(dismissed_) scope = old_scope_;
103 bool dismissed() const {
108 class exceptions_enable
110 exceptions_enable& operator=(exceptions_enable const&);
111 exceptions_enable(exceptions_enable const&);
116 exceptions_enable(bool enable)
117 : old_value_(exceptions_enabled), released_(false)
119 exceptions_enabled = enable;
125 exceptions_enabled = old_value_;
133 exceptions_enabled = old_value_;
139 struct exception_base {
142 template <class T> void store(T const&) {}
143 template <class T> void test(T const&) const {}
145 data_type init() const { return data_type(); }
146 void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
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,
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,
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,
174 T const& constant(T const& x) {
178 template <class Test>
182 bool exception_in_check_;
184 test_runner(test_runner const&);
185 test_runner& operator=(test_runner const&);
187 test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
191 BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
192 BOOST_DEDUCED_TYPENAME Test::strong_type strong;
196 call_ignore_extra_parameters<
198 BOOST_DEDUCED_TYPENAME Test::data_type,
199 BOOST_DEDUCED_TYPENAME Test::strong_type
200 >(&Test::run, test_, x, strong);
205 call_ignore_extra_parameters<
207 BOOST_DEDUCED_TYPENAME Test::data_type const,
208 BOOST_DEDUCED_TYPENAME Test::strong_type const
209 >(&Test::check, test_, constant(x), constant(strong));
211 exception_in_check_ = true;
217 if (exception_in_check_) {
218 BOOST_ERROR("Unexcpected exception in test_runner check call.");
223 // Quick exception testing based on lightweight test
225 namespace lightweight {
226 static int iteration;
229 struct test_exception {
231 test_exception(char const* n) : name(n) {}
234 struct test_failure {
237 void epoint(char const* name) {
239 if(count == iteration) {
240 throw test_exception(name);
244 template <class Test>
245 void exception_safety(Test const& f, char const* /*name*/) {
246 test_runner<Test> runner(f);
249 bool success = false;
250 char const* error_msg = 0;
259 catch(test_failure) {
260 error_msg = "test_failure caught.";
263 catch(test_exception) {
267 error_msg = "Unexpected exception.";
272 if (error_msg) { BOOST_ERROR(error_msg); }