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

source code of boost/libs/unordered/test/helpers/test.hpp