test.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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_TEST_TEST_HEADER)
  5. #define BOOST_UNORDERED_TEST_TEST_HEADER
  6. #include <boost/core/lightweight_test.hpp>
  7. #include <boost/preprocessor/cat.hpp>
  8. #include <boost/preprocessor/stringize.hpp>
  9. #define UNORDERED_AUTO_TEST(x) \
  10. struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
  11. { \
  12. BOOST_PP_CAT(x, _type) \
  13. () : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
  14. { \
  15. ::test::get_state().add_test(this); \
  16. } \
  17. void run(); \
  18. }; \
  19. BOOST_PP_CAT(x, _type) x; \
  20. void BOOST_PP_CAT(x, _type)::run()
  21. #define RUN_TESTS() \
  22. int main(int, char**) \
  23. { \
  24. BOOST_UNORDERED_TEST_COMPILER_INFO() \
  25. ::test::get_state().run_tests(); \
  26. return boost::report_errors(); \
  27. }
  28. #define RUN_TESTS_QUIET() \
  29. int main(int, char**) \
  30. { \
  31. BOOST_UNORDERED_TEST_COMPILER_INFO() \
  32. ::test::get_state().run_tests(true); \
  33. return boost::report_errors(); \
  34. }
  35. #define UNORDERED_SUB_TEST(x) \
  36. for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
  37. UNORDERED_SUB_TEST_VALUE; \
  38. UNORDERED_SUB_TEST_VALUE = \
  39. ::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
  40. namespace test {
  41. struct registered_test_base
  42. {
  43. registered_test_base* next;
  44. char const* name;
  45. explicit registered_test_base(char const* n) : name(n) {}
  46. virtual void run() = 0;
  47. virtual ~registered_test_base() {}
  48. };
  49. struct state
  50. {
  51. bool is_quiet;
  52. registered_test_base* first_test;
  53. registered_test_base* last_test;
  54. state() : is_quiet(false), first_test(0), last_test(0) {}
  55. void add_test(registered_test_base* test)
  56. {
  57. if (last_test) {
  58. last_test->next = test;
  59. } else {
  60. first_test = test;
  61. }
  62. last_test = test;
  63. }
  64. void run_tests(bool quiet = false)
  65. {
  66. is_quiet = quiet;
  67. for (registered_test_base* i = first_test; i; i = i->next) {
  68. int error_count = boost::detail::test_errors();
  69. if (!quiet) {
  70. BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
  71. << std::flush;
  72. }
  73. i->run();
  74. BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
  75. if (quiet && error_count != boost::detail::test_errors()) {
  76. BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name << "\n"
  77. << std::flush;
  78. }
  79. }
  80. }
  81. int start_sub_test(char const* name)
  82. {
  83. if (!is_quiet) {
  84. BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
  85. << std::flush;
  86. }
  87. // Add one because it's used as a loop condition.
  88. return boost::detail::test_errors() + 1;
  89. }
  90. int end_sub_test(char const* name, int value)
  91. {
  92. if (is_quiet && value != boost::detail::test_errors() + 1) {
  93. BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name << "\n"
  94. << std::flush;
  95. }
  96. return 0;
  97. }
  98. };
  99. // Get the currnet translation unit's test state.
  100. static inline state& get_state()
  101. {
  102. static state instance;
  103. return instance;
  104. }
  105. }
  106. #if defined(__cplusplus)
  107. #define BOOST_UNORDERED_CPLUSPLUS __cplusplus
  108. #else
  109. #define BOOST_UNORDERED_CPLUSPLUS "(not defined)"
  110. #endif
  111. #define BOOST_UNORDERED_TEST_COMPILER_INFO() \
  112. { \
  113. BOOST_LIGHTWEIGHT_TEST_OSTREAM \
  114. << "Compiler: " << BOOST_COMPILER << "\n" \
  115. << "Library: " << BOOST_STDLIB << "\n" \
  116. << "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
  117. << "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
  118. << BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
  119. << "BOOST_UNORDERED_EMPLACE_LIMIT: " << BOOST_UNORDERED_EMPLACE_LIMIT \
  120. << "\n" \
  121. << "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
  122. << BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
  123. << "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
  124. << BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
  125. << std::flush; \
  126. }
  127. #include <boost/preprocessor/cat.hpp>
  128. #include <boost/preprocessor/seq/fold_left.hpp>
  129. #include <boost/preprocessor/seq/for_each_product.hpp>
  130. #include <boost/preprocessor/seq/seq.hpp>
  131. #include <boost/preprocessor/seq/to_tuple.hpp>
  132. // Run test with every combination of the parameters (a sequence of sequences)
  133. #define UNORDERED_TEST(name, parameters) \
  134. BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
  135. #define UNORDERED_TEST_REPEAT(name, n, parameters) \
  136. BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters)
  137. #define UNORDERED_TEST_OP(r, product) \
  138. UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
  139. BOOST_PP_SEQ_ELEM(1, product), \
  140. BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
  141. #define UNORDERED_TEST_OP2(name, n, params) \
  142. UNORDERED_AUTO_TEST ( \
  143. BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) { \
  144. for (int i = 0; i < n; ++i) \
  145. name BOOST_PP_SEQ_TO_TUPLE(params); \
  146. }
  147. #define UNORDERED_TEST_OP_JOIN(s, state, elem) \
  148. BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
  149. #define UNORDERED_MULTI_TEST(name, impl, parameters) \
  150. UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
  151. #define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
  152. UNORDERED_AUTO_TEST (name) { \
  153. BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
  154. UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
  155. }
  156. #define UNORDERED_MULTI_TEST_OP(r, product) \
  157. UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
  158. BOOST_PP_SEQ_ELEM(1, product), \
  159. BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
  160. // Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
  161. // https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
  162. #define UNORDERED_MULTI_TEST_OP2(name, n, params) \
  163. { \
  164. UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
  165. BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \
  166. { \
  167. for (int i = 0; i < n; ++i) \
  168. name BOOST_PP_SEQ_TO_TUPLE(params); \
  169. } \
  170. }
  171. #endif