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&);
115 exceptions_enable(bool enable)
116 : old_value_(exceptions_enabled)
118 exceptions_enabled = enable;
123 exceptions_enabled = old_value_;
127 struct exception_base {
130 template <class T> void store(T const&) {}
131 template <class T> void test(T const&) const {}
133 data_type init() const { return data_type(); }
134 void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
137 template <class T, class P1, class P2, class T2>
138 inline void call_ignore_extra_parameters(
139 void (T::*fn)() const, T2 const& obj,
145 template <class T, class P1, class P2, class T2>
146 inline void call_ignore_extra_parameters(
147 void (T::*fn)(P1&) const, T2 const& obj,
153 template <class T, class P1, class P2, class T2>
154 inline void call_ignore_extra_parameters(
155 void (T::*fn)(P1&, P2&) const, T2 const& obj,
162 T const& constant(T const& x) {
166 template <class Test>
171 test_runner(test_runner const&);
172 test_runner& operator=(test_runner const&);
174 test_runner(Test const& t) : test_(t) {}
175 void operator()() const {
178 BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
179 BOOST_DEDUCED_TYPENAME Test::strong_type strong;
183 call_ignore_extra_parameters<
185 BOOST_DEDUCED_TYPENAME Test::data_type,
186 BOOST_DEDUCED_TYPENAME Test::strong_type
187 >(&Test::run, test_, x, strong);
190 call_ignore_extra_parameters<
192 BOOST_DEDUCED_TYPENAME Test::data_type const,
193 BOOST_DEDUCED_TYPENAME Test::strong_type const
194 >(&Test::check, test_, constant(x), constant(strong));
200 // Quick exception testing based on lightweight test
202 namespace lightweight {
203 static int iteration;
206 struct test_exception {
208 test_exception(char const* n) : name(n) {}
211 struct test_failure {
214 void epoint(char const* name) {
216 if(count == iteration) {
217 throw test_exception(name);
221 template <class Test>
222 void exception_safety(Test const& f, char const* /*name*/) {
223 test_runner<Test> runner(f);
226 bool success = false;
235 catch(test_failure) {
236 BOOST_ERROR("test_failure caught.");
239 catch(test_exception) {
243 BOOST_ERROR("Unexpected exception.");