1 | // (C) Copyright Gennadiy Rozental 2001. |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // (See accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | // See http://www.boost.org/libs/test for the library home page. |
7 | // |
8 | // File : $RCSfile$ |
9 | // |
10 | // Version : $Revision: 74248 $ |
11 | // |
12 | // Description : implementation details for old toolbox |
13 | // *************************************************************************** |
14 | |
15 | #ifndef BOOST_TEST_TOOLS_OLD_IMPL_HPP_012705GER |
16 | #define BOOST_TEST_TOOLS_OLD_IMPL_HPP_012705GER |
17 | |
18 | // Boost.Test |
19 | #include <boost/test/unit_test_log.hpp> |
20 | #include <boost/test/tools/assertion_result.hpp> |
21 | #include <boost/test/tools/floating_point_comparison.hpp> |
22 | |
23 | #include <boost/test/tools/detail/fwd.hpp> |
24 | #include <boost/test/tools/detail/print_helper.hpp> |
25 | |
26 | // Boost |
27 | #include <boost/limits.hpp> |
28 | #include <boost/numeric/conversion/conversion_traits.hpp> // for numeric::conversion_traits |
29 | #include <boost/type_traits/is_array.hpp> |
30 | |
31 | #include <boost/preprocessor/repetition/repeat.hpp> |
32 | #include <boost/preprocessor/arithmetic/add.hpp> |
33 | |
34 | // STL |
35 | #include <cstddef> // for std::size_t |
36 | #include <climits> // for CHAR_BIT |
37 | |
38 | #include <boost/test/detail/suppress_warnings.hpp> |
39 | |
40 | //____________________________________________________________________________// |
41 | |
42 | namespace boost { |
43 | namespace test_tools { |
44 | namespace tt_detail { |
45 | |
46 | // ************************************************************************** // |
47 | // ************** old TOOLBOX Implementation ************** // |
48 | // ************************************************************************** // |
49 | |
50 | // This function adds level of indirection, but it makes sure we evaluate predicate |
51 | // arguments only once |
52 | |
53 | #ifndef BOOST_TEST_PROD |
54 | #define TEMPL_PARAMS( z, m, dummy ) , typename BOOST_JOIN( Arg, m ) |
55 | |
56 | #define FUNC_PARAMS( z, m, dummy ) \ |
57 | , BOOST_JOIN( Arg, m ) const& BOOST_JOIN( arg, m ) \ |
58 | , char const* BOOST_JOIN( BOOST_JOIN( arg, m ), _descr ) \ |
59 | /**/ |
60 | |
61 | #define PRED_PARAMS( z, m, dummy ) BOOST_PP_COMMA_IF( m ) BOOST_JOIN( arg, m ) |
62 | |
63 | #define ARG_INFO( z, m, dummy ) \ |
64 | , BOOST_JOIN( BOOST_JOIN( arg, m ), _descr ) \ |
65 | , &static_cast<const unit_test::lazy_ostream&>(unit_test::lazy_ostream::instance() \ |
66 | << ::boost::test_tools::tt_detail::print_helper( BOOST_JOIN( arg, m ) )) \ |
67 | /**/ |
68 | |
69 | #define IMPL_FRWD( z, n, dummy ) \ |
70 | template<typename Pred \ |
71 | BOOST_PP_REPEAT_ ## z( BOOST_PP_ADD( n, 1 ), TEMPL_PARAMS, _ )> \ |
72 | inline bool \ |
73 | check_frwd( Pred P, unit_test::lazy_ostream const& assertion_descr, \ |
74 | const_string file_name, std::size_t line_num, \ |
75 | tool_level tl, check_type ct \ |
76 | BOOST_PP_REPEAT_ ## z( BOOST_PP_ADD( n, 1 ), FUNC_PARAMS, _ ) \ |
77 | ) \ |
78 | { \ |
79 | return \ |
80 | report_assertion( P( BOOST_PP_REPEAT_ ## z(BOOST_PP_ADD(n, 1), PRED_PARAMS,_) ),\ |
81 | assertion_descr, file_name, line_num, tl, ct, \ |
82 | BOOST_PP_ADD( n, 1 ) \ |
83 | BOOST_PP_REPEAT_ ## z( BOOST_PP_ADD( n, 1 ), ARG_INFO, _ ) \ |
84 | ); \ |
85 | } \ |
86 | /**/ |
87 | |
88 | #ifndef BOOST_TEST_MAX_PREDICATE_ARITY |
89 | #define BOOST_TEST_MAX_PREDICATE_ARITY 5 |
90 | #endif |
91 | |
92 | BOOST_PP_REPEAT( BOOST_TEST_MAX_PREDICATE_ARITY, IMPL_FRWD, _ ) |
93 | |
94 | #undef TEMPL_PARAMS |
95 | #undef FUNC_PARAMS |
96 | #undef PRED_INFO |
97 | #undef ARG_INFO |
98 | #undef IMPL_FRWD |
99 | |
100 | #endif |
101 | |
102 | //____________________________________________________________________________// |
103 | |
104 | template <class Left, class Right> |
105 | inline assertion_result equal_impl( Left const& left, Right const& right ) |
106 | { |
107 | return left == right; |
108 | } |
109 | |
110 | //____________________________________________________________________________// |
111 | |
112 | inline assertion_result equal_impl( char* left, char const* right ) { return equal_impl( left: static_cast<char const*>(left), right: static_cast<char const*>(right) ); } |
113 | inline assertion_result equal_impl( char const* left, char* right ) { return equal_impl( left: static_cast<char const*>(left), right: static_cast<char const*>(right) ); } |
114 | inline assertion_result equal_impl( char* left, char* right ) { return equal_impl( left: static_cast<char const*>(left), right: static_cast<char const*>(right) ); } |
115 | |
116 | #if !defined( BOOST_NO_CWCHAR ) |
117 | BOOST_TEST_DECL assertion_result equal_impl( wchar_t const* left, wchar_t const* right ); |
118 | inline assertion_result equal_impl( wchar_t* left, wchar_t const* right ) { return equal_impl( left: static_cast<wchar_t const*>(left), right: static_cast<wchar_t const*>(right) ); } |
119 | inline assertion_result equal_impl( wchar_t const* left, wchar_t* right ) { return equal_impl( left: static_cast<wchar_t const*>(left), right: static_cast<wchar_t const*>(right) ); } |
120 | inline assertion_result equal_impl( wchar_t* left, wchar_t* right ) { return equal_impl( left: static_cast<wchar_t const*>(left), right: static_cast<wchar_t const*>(right) ); } |
121 | #endif |
122 | |
123 | //____________________________________________________________________________// |
124 | |
125 | struct equal_impl_frwd { |
126 | template <typename Left, typename Right> |
127 | inline assertion_result |
128 | call_impl( Left const& left, Right const& right, mpl::false_ ) const |
129 | { |
130 | return equal_impl( left, right ); |
131 | } |
132 | |
133 | template <typename Left, typename Right> |
134 | inline assertion_result |
135 | call_impl( Left const& left, Right const& right, mpl::true_ ) const |
136 | { |
137 | return (*this)( right, &left[0] ); |
138 | } |
139 | |
140 | template <typename Left, typename Right> |
141 | inline assertion_result |
142 | operator()( Left const& left, Right const& right ) const |
143 | { |
144 | typedef typename is_array<Left>::type left_is_array; |
145 | return call_impl( left, right, left_is_array() ); |
146 | } |
147 | }; |
148 | |
149 | //____________________________________________________________________________// |
150 | |
151 | struct ne_impl { |
152 | template <class Left, class Right> |
153 | assertion_result operator()( Left const& left, Right const& right ) |
154 | { |
155 | return !equal_impl_frwd()( left, right ); |
156 | } |
157 | }; |
158 | |
159 | //____________________________________________________________________________// |
160 | |
161 | struct lt_impl { |
162 | template <class Left, class Right> |
163 | assertion_result operator()( Left const& left, Right const& right ) |
164 | { |
165 | return left < right; |
166 | } |
167 | }; |
168 | |
169 | //____________________________________________________________________________// |
170 | |
171 | struct le_impl { |
172 | template <class Left, class Right> |
173 | assertion_result operator()( Left const& left, Right const& right ) |
174 | { |
175 | return left <= right; |
176 | } |
177 | }; |
178 | |
179 | //____________________________________________________________________________// |
180 | |
181 | struct gt_impl { |
182 | template <class Left, class Right> |
183 | assertion_result operator()( Left const& left, Right const& right ) |
184 | { |
185 | return left > right; |
186 | } |
187 | }; |
188 | |
189 | //____________________________________________________________________________// |
190 | |
191 | struct ge_impl { |
192 | template <class Left, class Right> |
193 | assertion_result operator()( Left const& left, Right const& right ) |
194 | { |
195 | return left >= right; |
196 | } |
197 | }; |
198 | |
199 | //____________________________________________________________________________// |
200 | |
201 | struct equal_coll_impl { |
202 | template <typename Left, typename Right> |
203 | assertion_result operator()( Left left_begin, Left left_end, Right right_begin, Right right_end ) |
204 | { |
205 | assertion_result pr( true ); |
206 | std::size_t pos = 0; |
207 | |
208 | for( ; left_begin != left_end && right_begin != right_end; ++left_begin, ++right_begin, ++pos ) { |
209 | if( *left_begin != *right_begin ) { |
210 | pr = false; |
211 | pr.message() << "\nMismatch at position " << pos << ": " |
212 | << ::boost::test_tools::tt_detail::print_helper(*left_begin) |
213 | << " != " |
214 | << ::boost::test_tools::tt_detail::print_helper(*right_begin); |
215 | } |
216 | } |
217 | |
218 | if( left_begin != left_end ) { |
219 | std::size_t r_size = pos; |
220 | while( left_begin != left_end ) { |
221 | ++pos; |
222 | ++left_begin; |
223 | } |
224 | |
225 | pr = false; |
226 | pr.message() << "\nCollections size mismatch: " << pos << " != " << r_size; |
227 | } |
228 | |
229 | if( right_begin != right_end ) { |
230 | std::size_t l_size = pos; |
231 | while( right_begin != right_end ) { |
232 | ++pos; |
233 | ++right_begin; |
234 | } |
235 | |
236 | pr = false; |
237 | pr.message() << "\nCollections size mismatch: " << l_size << " != " << pos; |
238 | } |
239 | |
240 | return pr; |
241 | } |
242 | }; |
243 | |
244 | //____________________________________________________________________________// |
245 | |
246 | struct bitwise_equal_impl { |
247 | template <class Left, class Right> |
248 | assertion_result operator()( Left const& left, Right const& right ) |
249 | { |
250 | assertion_result pr( true ); |
251 | |
252 | std::size_t left_bit_size = sizeof(Left)*CHAR_BIT; |
253 | std::size_t right_bit_size = sizeof(Right)*CHAR_BIT; |
254 | |
255 | static Left const leftOne( 1 ); |
256 | static Right const rightOne( 1 ); |
257 | |
258 | std::size_t total_bits = left_bit_size < right_bit_size ? left_bit_size : right_bit_size; |
259 | |
260 | for( std::size_t counter = 0; counter < total_bits; ++counter ) { |
261 | if( ( left & ( leftOne << counter ) ) != ( right & ( rightOne << counter ) ) ) { |
262 | pr = false; |
263 | pr.message() << "\nMismatch at position " << counter; |
264 | } |
265 | } |
266 | |
267 | if( left_bit_size != right_bit_size ) { |
268 | pr = false; |
269 | pr.message() << "\nOperands bit sizes mismatch: " << left_bit_size << " != " << right_bit_size; |
270 | } |
271 | |
272 | return pr; |
273 | } |
274 | }; |
275 | |
276 | //____________________________________________________________________________// |
277 | |
278 | template<typename FPT1, typename FPT2> |
279 | struct comp_supertype { |
280 | // deduce "better" type from types of arguments being compared |
281 | // if one type is floating and the second integral we use floating type and |
282 | // value of integral type is promoted to the floating. The same for float and double |
283 | // But we don't want to compare two values of integral types using this tool. |
284 | typedef typename numeric::conversion_traits<FPT1,FPT2>::supertype type; |
285 | BOOST_STATIC_ASSERT_MSG( !is_integral<type>::value, "Only floating-point types can be compared!" ); |
286 | }; |
287 | |
288 | } // namespace tt_detail |
289 | |
290 | namespace fpc = math::fpc; |
291 | |
292 | // ************************************************************************** // |
293 | // ************** check_is_close ************** // |
294 | // ************************************************************************** // |
295 | |
296 | struct BOOST_TEST_DECL check_is_close_t { |
297 | // Public typedefs |
298 | typedef assertion_result result_type; |
299 | |
300 | template<typename FPT1, typename FPT2, typename ToleranceType> |
301 | assertion_result |
302 | operator()( FPT1 left, FPT2 right, ToleranceType tolerance ) const |
303 | { |
304 | fpc::close_at_tolerance<typename tt_detail::comp_supertype<FPT1,FPT2>::type> pred( tolerance, fpc::FPC_STRONG ); |
305 | |
306 | assertion_result ar( pred( left, right ) ); |
307 | |
308 | if( !ar ) |
309 | ar.message() << pred.tested_rel_diff(); |
310 | |
311 | return ar; |
312 | } |
313 | }; |
314 | |
315 | //____________________________________________________________________________// |
316 | |
317 | template<typename FPT1, typename FPT2, typename ToleranceType> |
318 | inline assertion_result |
319 | check_is_close( FPT1 left, FPT2 right, ToleranceType tolerance ) |
320 | { |
321 | return check_is_close_t()( left, right, tolerance ); |
322 | } |
323 | |
324 | //____________________________________________________________________________// |
325 | |
326 | // ************************************************************************** // |
327 | // ************** check_is_small ************** // |
328 | // ************************************************************************** // |
329 | |
330 | struct BOOST_TEST_DECL check_is_small_t { |
331 | // Public typedefs |
332 | typedef bool result_type; |
333 | |
334 | template<typename FPT> |
335 | bool |
336 | operator()( FPT fpv, FPT tolerance ) const |
337 | { |
338 | return fpc::is_small( fpv, tolerance ); |
339 | } |
340 | }; |
341 | |
342 | //____________________________________________________________________________// |
343 | |
344 | template<typename FPT> |
345 | inline bool |
346 | check_is_small( FPT fpv, FPT tolerance ) |
347 | { |
348 | return fpc::is_small( fpv, tolerance ); |
349 | } |
350 | |
351 | //____________________________________________________________________________// |
352 | |
353 | } // namespace test_tools |
354 | } // namespace boost |
355 | |
356 | #include <boost/test/detail/enable_warnings.hpp> |
357 | |
358 | #endif // BOOST_TEST_TOOLS_OLD_IMPL_HPP_012705GER |
359 | |