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