| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-09 20:56:23 +00:00
										 |  |  | // Copyright 2006-2009 Daniel James.
 | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
					
						
							|  |  |  | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-01 18:35:50 +00:00
										 |  |  | #include "./count.hpp"
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #include "./test.hpp"
 | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <boost/preprocessor/cat.hpp>
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #include <boost/preprocessor/seq/elem.hpp>
 | 
					
						
							|  |  |  | #include <boost/preprocessor/seq/for_each_product.hpp>
 | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type)                   \
 | 
					
						
							|  |  |  |     UNORDERED_AUTO_TEST(name)                                                  \ | 
					
						
							|  |  |  |     {                                                                          \ | 
					
						
							|  |  |  |         test_func<type> fixture;                                               \ | 
					
						
							|  |  |  |         ::test::lightweight::exception_safety(                                 \ | 
					
						
							|  |  |  |             fixture, BOOST_STRINGIZE(test_func<type>));                        \ | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-10-21 00:20:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type)         \
 | 
					
						
							|  |  |  |     UNORDERED_AUTO_TEST(name)                                                  \ | 
					
						
							|  |  |  |     {                                                                          \ | 
					
						
							|  |  |  |         for (unsigned i = 0; i < n; ++i) {                                     \ | 
					
						
							|  |  |  |             test_func<type> fixture;                                           \ | 
					
						
							|  |  |  |             ::test::lightweight::exception_safety(                             \ | 
					
						
							|  |  |  |                 fixture, BOOST_STRINGIZE(test_func<type>));                    \ | 
					
						
							|  |  |  |         }                                                                      \ | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-10-21 00:20:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
 | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-24 17:03:15 +00:00
										 |  |  | #define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #define EXCEPTION_TESTS(test_seq, param_seq)                                   \
 | 
					
						
							|  |  |  |     BOOST_PP_SEQ_FOR_EACH_PRODUCT(                                             \ | 
					
						
							|  |  |  |         EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq)                         \
 | 
					
						
							|  |  |  |     BOOST_PP_SEQ_FOR_EACH_PRODUCT(                                             \ | 
					
						
							|  |  |  |         EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EXCEPTION_TESTS_OP(r, product)                                         \
 | 
					
						
							|  |  |  |     UNORDERED_EXCEPTION_TEST_CASE_REPEAT(                                      \ | 
					
						
							|  |  |  |         BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product),                            \ | 
					
						
							|  |  |  |             BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))),                   \ | 
					
						
							|  |  |  |         BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product),          \ | 
					
						
							|  |  |  |         BOOST_PP_SEQ_ELEM(2, product)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define UNORDERED_SCOPE(scope_name)                                            \
 | 
					
						
							|  |  |  |     for (::test::scope_guard unordered_test_guard(                             \ | 
					
						
							|  |  |  |              BOOST_STRINGIZE(scope_name));                                     \ | 
					
						
							|  |  |  |          !unordered_test_guard.dismissed(); unordered_test_guard.dismiss()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define UNORDERED_EPOINT(name)                                                 \
 | 
					
						
							|  |  |  |     if (::test::exceptions_enabled) {                                          \ | 
					
						
							|  |  |  |         UNORDERED_EPOINT_IMPL(name);                                           \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ENABLE_EXCEPTIONS                                                      \
 | 
					
						
							|  |  |  |     ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DISABLE_EXCEPTIONS                                                     \
 | 
					
						
							|  |  |  |     ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false) | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace test { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | static char const* scope = ""; | 
					
						
							|  |  |  | bool exceptions_enabled = false; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | class scope_guard | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     scope_guard& operator=(scope_guard const&); | 
					
						
							|  |  |  |     scope_guard(scope_guard const&); | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     char const* old_scope_; | 
					
						
							|  |  |  |     char const* scope_; | 
					
						
							|  |  |  |     bool dismissed_; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |   public: | 
					
						
							|  |  |  |     scope_guard(char const* name) | 
					
						
							|  |  |  |         : old_scope_(scope), scope_(name), dismissed_(false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         scope = scope_; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     ~scope_guard() | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         if (dismissed_) | 
					
						
							|  |  |  |             scope = old_scope_; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     void dismiss() { dismissed_ = true; } | 
					
						
							| 
									
										
										
										
											2016-10-02 13:04:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     bool dismissed() const { return dismissed_; } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | class exceptions_enable | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     exceptions_enable& operator=(exceptions_enable const&); | 
					
						
							|  |  |  |     exceptions_enable(exceptions_enable const&); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool old_value_; | 
					
						
							|  |  |  |     bool released_; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |   public: | 
					
						
							|  |  |  |     exceptions_enable(bool enable) | 
					
						
							|  |  |  |         : old_value_(exceptions_enabled), released_(false) | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         exceptions_enabled = enable; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     ~exceptions_enable() | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         if (!released_) { | 
					
						
							|  |  |  |             exceptions_enabled = old_value_; | 
					
						
							|  |  |  |             released_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     void release() | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         if (!released_) { | 
					
						
							|  |  |  |             exceptions_enabled = old_value_; | 
					
						
							|  |  |  |             released_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | struct exception_base | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct data_type | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     struct strong_type | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         template <class T> void store(T const&) {} | 
					
						
							|  |  |  |         template <class T> void test(T const&) const {} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     data_type init() const { return data_type(); } | 
					
						
							|  |  |  |     void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class T, class P1, class P2, class T2> | 
					
						
							|  |  |  | inline void call_ignore_extra_parameters( | 
					
						
							|  |  |  |     void (T::*fn)() const, T2 const& obj, P1&, P2&) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (obj.*fn)(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class T, class P1, class P2, class T2> | 
					
						
							|  |  |  | inline void call_ignore_extra_parameters( | 
					
						
							|  |  |  |     void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (obj.*fn)(p1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class T, class P1, class P2, class T2> | 
					
						
							|  |  |  | inline void call_ignore_extra_parameters( | 
					
						
							|  |  |  |     void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (obj.*fn)(p1, p2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class T> T const& constant(T const& x) { return x; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class Test> class test_runner | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Test const& test_; | 
					
						
							|  |  |  |     bool exception_in_check_; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     test_runner(test_runner const&); | 
					
						
							|  |  |  |     test_runner& operator=(test_runner const&); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     test_runner(Test const& t) : test_(t), exception_in_check_(false) {} | 
					
						
							|  |  |  |     void run() | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         DISABLE_EXCEPTIONS; | 
					
						
							|  |  |  |         test::check_instances check; | 
					
						
							|  |  |  |         test::scope = ""; | 
					
						
							|  |  |  |         BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init()); | 
					
						
							|  |  |  |         BOOST_DEDUCED_TYPENAME Test::strong_type strong; | 
					
						
							|  |  |  |         strong.store(x); | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             ENABLE_EXCEPTIONS; | 
					
						
							|  |  |  |             call_ignore_extra_parameters<Test, | 
					
						
							|  |  |  |                 BOOST_DEDUCED_TYPENAME Test::data_type, | 
					
						
							|  |  |  |                 BOOST_DEDUCED_TYPENAME Test::strong_type>( | 
					
						
							|  |  |  |                 &Test::run, test_, x, strong); | 
					
						
							|  |  |  |         } catch (...) { | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |             try { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |                 DISABLE_EXCEPTIONS; | 
					
						
							|  |  |  |                 call_ignore_extra_parameters<Test, | 
					
						
							|  |  |  |                     BOOST_DEDUCED_TYPENAME Test::data_type const, | 
					
						
							|  |  |  |                     BOOST_DEDUCED_TYPENAME Test::strong_type const>( | 
					
						
							|  |  |  |                     &Test::check, test_, constant(x), constant(strong)); | 
					
						
							|  |  |  |             } catch (...) { | 
					
						
							|  |  |  |                 exception_in_check_ = true; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |             throw; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     void end() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (exception_in_check_) { | 
					
						
							|  |  |  |             BOOST_ERROR("Unexcpected exception in test_runner check call."); | 
					
						
							| 
									
										
										
										
											2016-10-24 09:46:13 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | // Quick exception testing based on lightweight test
 | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | namespace lightweight { | 
					
						
							|  |  |  | static int iteration; | 
					
						
							|  |  |  | static int count; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | struct test_exception | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     char const* name; | 
					
						
							|  |  |  |     test_exception(char const* n) : name(n) {} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | struct test_failure | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | void epoint(char const* name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ++count; | 
					
						
							|  |  |  |     if (count == iteration) { | 
					
						
							|  |  |  |         throw test_exception(name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | template <class Test> void exception_safety(Test const& f, char const* /*name*/) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     test_runner<Test> runner(f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iteration = 0; | 
					
						
							|  |  |  |     bool success = false; | 
					
						
							| 
									
										
										
										
											2017-04-25 01:10:53 +01:00
										 |  |  |     unsigned int failure_count = 0; | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     char const* error_msg = 0; | 
					
						
							|  |  |  |     do { | 
					
						
							| 
									
										
										
										
											2017-04-25 01:10:53 +01:00
										 |  |  |         int error_count = boost::detail::test_errors(); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         ++iteration; | 
					
						
							|  |  |  |         count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             runner.run(); | 
					
						
							|  |  |  |             success = true; | 
					
						
							|  |  |  |         } catch (test_failure) { | 
					
						
							|  |  |  |             error_msg = "test_failure caught."; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2017-04-25 01:11:18 +01:00
										 |  |  |         } catch (test_exception e) { | 
					
						
							|  |  |  |             if (error_count != boost::detail::test_errors()) { | 
					
						
							|  |  |  |                 BOOST_LIGHTWEIGHT_TEST_OSTREAM | 
					
						
							|  |  |  |                     << "Iteration: " << iteration | 
					
						
							|  |  |  |                     << " Error found for epoint: " << e.name << std::endl; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } catch (...) { | 
					
						
							|  |  |  |             error_msg = "Unexpected exception."; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-04-25 01:10:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (error_count != boost::detail::test_errors()) { | 
					
						
							|  |  |  |             ++failure_count; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } while (!success && failure_count < 5); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (error_msg) { | 
					
						
							|  |  |  |         BOOST_ERROR(error_msg); | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     runner.end(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-01-13 16:19:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |