/Src/Dependencies/Boost/libs/unordered/test/helpers/exception_test.hpp

http://hadesmem.googlecode.com/ · C++ Header · 236 lines · 194 code · 38 blank · 4 comment · 6 complexity · 514963d46c9eaef1009f627f2201b484 MD5 · raw file

  1. // Copyright 2006-2009 Daniel James.
  2. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
  5. #define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
  6. #include "./test.hpp"
  7. #include <boost/preprocessor/seq/for_each_product.hpp>
  8. #include <boost/preprocessor/seq/elem.hpp>
  9. #include <boost/preprocessor/cat.hpp>
  10. # define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
  11. UNORDERED_AUTO_TEST(name) \
  12. { \
  13. test_func< type > fixture; \
  14. ::test::lightweight::exception_safety( \
  15. fixture, BOOST_STRINGIZE(test_func<type>)); \
  16. } \
  17. # define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
  18. #define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
  19. #define RUN_EXCEPTION_TESTS(test_seq, param_seq) \
  20. BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, \
  21. (test_seq)(param_seq)) \
  22. RUN_TESTS() \
  23. #define RUN_EXCEPTION_TESTS_OP(r, product) \
  24. UNORDERED_EXCEPTION_TEST_CASE( \
  25. BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
  26. BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
  27. ), \
  28. BOOST_PP_SEQ_ELEM(0, product), \
  29. BOOST_PP_SEQ_ELEM(1, product) \
  30. ) \
  31. #define UNORDERED_SCOPE(scope_name) \
  32. for(::test::scope_guard unordered_test_guard( \
  33. BOOST_STRINGIZE(scope_name)); \
  34. !unordered_test_guard.dismissed(); \
  35. unordered_test_guard.dismiss()) \
  36. #define UNORDERED_EPOINT(name) \
  37. if(::test::exceptions_enabled) { \
  38. UNORDERED_EPOINT_IMPL(name); \
  39. } \
  40. #define ENABLE_EXCEPTIONS \
  41. ::test::exceptions_enable BOOST_PP_CAT( \
  42. ENABLE_EXCEPTIONS_, __LINE__)(true) \
  43. #define DISABLE_EXCEPTIONS \
  44. ::test::exceptions_enable BOOST_PP_CAT( \
  45. ENABLE_EXCEPTIONS_, __LINE__)(false) \
  46. namespace test {
  47. static char const* scope = "";
  48. bool exceptions_enabled = false;
  49. class scope_guard {
  50. scope_guard& operator=(scope_guard const&);
  51. scope_guard(scope_guard const&);
  52. char const* old_scope_;
  53. char const* scope_;
  54. bool dismissed_;
  55. public:
  56. scope_guard(char const* name)
  57. : old_scope_(scope),
  58. scope_(name),
  59. dismissed_(false)
  60. {
  61. scope = scope_;
  62. }
  63. ~scope_guard() {
  64. if(dismissed_) scope = old_scope_;
  65. }
  66. void dismiss() {
  67. dismissed_ = true;
  68. }
  69. bool dismissed() const {
  70. return dismissed_;
  71. }
  72. };
  73. class exceptions_enable
  74. {
  75. exceptions_enable& operator=(exceptions_enable const&);
  76. exceptions_enable(exceptions_enable const&);
  77. bool old_value_;
  78. public:
  79. exceptions_enable(bool enable)
  80. : old_value_(exceptions_enabled)
  81. {
  82. exceptions_enabled = enable;
  83. }
  84. ~exceptions_enable()
  85. {
  86. exceptions_enabled = old_value_;
  87. }
  88. };
  89. struct exception_base {
  90. struct data_type {};
  91. struct strong_type {
  92. template <class T> void store(T const&) {}
  93. template <class T> void test(T const&) const {}
  94. };
  95. data_type init() const { return data_type(); }
  96. void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
  97. };
  98. template <class T, class P1, class P2, class T2>
  99. inline void call_ignore_extra_parameters(
  100. void (T::*fn)() const, T2 const& obj,
  101. P1&, P2&)
  102. {
  103. (obj.*fn)();
  104. }
  105. template <class T, class P1, class P2, class T2>
  106. inline void call_ignore_extra_parameters(
  107. void (T::*fn)(P1&) const, T2 const& obj,
  108. P1& p1, P2&)
  109. {
  110. (obj.*fn)(p1);
  111. }
  112. template <class T, class P1, class P2, class T2>
  113. inline void call_ignore_extra_parameters(
  114. void (T::*fn)(P1&, P2&) const, T2 const& obj,
  115. P1& p1, P2& p2)
  116. {
  117. (obj.*fn)(p1, p2);
  118. }
  119. template <class T>
  120. T const& constant(T const& x) {
  121. return x;
  122. }
  123. template <class Test>
  124. class test_runner
  125. {
  126. Test const& test_;
  127. test_runner(test_runner const&);
  128. test_runner& operator=(test_runner const&);
  129. public:
  130. test_runner(Test const& t) : test_(t) {}
  131. void operator()() const {
  132. DISABLE_EXCEPTIONS;
  133. test::scope = "";
  134. BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
  135. BOOST_DEDUCED_TYPENAME Test::strong_type strong;
  136. strong.store(x);
  137. try {
  138. ENABLE_EXCEPTIONS;
  139. call_ignore_extra_parameters<
  140. Test,
  141. BOOST_DEDUCED_TYPENAME Test::data_type,
  142. BOOST_DEDUCED_TYPENAME Test::strong_type
  143. >(&Test::run, test_, x, strong);
  144. }
  145. catch(...) {
  146. call_ignore_extra_parameters<
  147. Test,
  148. BOOST_DEDUCED_TYPENAME Test::data_type const,
  149. BOOST_DEDUCED_TYPENAME Test::strong_type const
  150. >(&Test::check, test_, constant(x), constant(strong));
  151. throw;
  152. }
  153. }
  154. };
  155. // Quick exception testing based on lightweight test
  156. namespace lightweight {
  157. static int iteration;
  158. static int count;
  159. struct test_exception {
  160. char const* name;
  161. test_exception(char const* n) : name(n) {}
  162. };
  163. struct test_failure {
  164. };
  165. void epoint(char const* name) {
  166. ++count;
  167. if(count == iteration) {
  168. throw test_exception(name);
  169. }
  170. }
  171. template <class Test>
  172. void exception_safety(Test const& f, char const* /*name*/) {
  173. test_runner<Test> runner(f);
  174. iteration = 0;
  175. bool success = false;
  176. do {
  177. ++iteration;
  178. count = 0;
  179. try {
  180. runner();
  181. success = true;
  182. }
  183. catch(test_failure) {
  184. BOOST_ERROR("test_failure caught.");
  185. break;
  186. }
  187. catch(test_exception) {
  188. continue;
  189. }
  190. catch(...) {
  191. BOOST_ERROR("Unexpected exception.");
  192. break;
  193. }
  194. } while(!success);
  195. }
  196. }
  197. }
  198. #endif