summaryrefslogtreecommitdiff
path: root/boost/test/tools/old/impl.hpp
blob: b975f61b38a8fce06a827e79363d155d8031c5ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//  (C) Copyright Gennadiy Rozental 2001.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision: 74248 $
//
//  Description : implementation details for old toolbox
// ***************************************************************************

#ifndef BOOST_TEST_TOOLS_OLD_IMPL_HPP_012705GER
#define BOOST_TEST_TOOLS_OLD_IMPL_HPP_012705GER

// Boost.Test
#include <boost/test/unit_test_log.hpp>
#include <boost/test/tools/assertion_result.hpp>
#include <boost/test/tools/floating_point_comparison.hpp>

#include <boost/test/tools/detail/fwd.hpp>
#include <boost/test/tools/detail/print_helper.hpp>

// Boost
#include <boost/limits.hpp>
#include <boost/numeric/conversion/conversion_traits.hpp> // for numeric::conversion_traits
#include <boost/type_traits/is_array.hpp>

#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>

// STL
#include <cstddef>          // for std::size_t
#include <climits>          // for CHAR_BIT

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace test_tools {
namespace tt_detail {

// ************************************************************************** //
// **************          old TOOLBOX Implementation          ************** //
// ************************************************************************** //

// This function adds level of indirection, but it makes sure we evaluate predicate
// arguments only once

#ifndef BOOST_TEST_PROD
#define TEMPL_PARAMS( z, m, dummy ) , typename BOOST_JOIN( Arg, m )

#define FUNC_PARAMS( z, m, dummy )                                                  \
 , BOOST_JOIN( Arg, m ) const& BOOST_JOIN( arg, m )                                 \
 , char const* BOOST_JOIN( BOOST_JOIN( arg, m ), _descr )                           \
/**/

#define PRED_PARAMS( z, m, dummy ) BOOST_PP_COMMA_IF( m ) BOOST_JOIN( arg, m )

#define ARG_INFO( z, m, dummy )                                                     \
 , BOOST_JOIN( BOOST_JOIN( arg, m ), _descr )                                       \
 , &static_cast<const unit_test::lazy_ostream&>(unit_test::lazy_ostream::instance() \
        << ::boost::test_tools::tt_detail::print_helper( BOOST_JOIN( arg, m ) ))    \
/**/

#define IMPL_FRWD( z, n, dummy )                                                    \
template<typename Pred                                                              \
         BOOST_PP_REPEAT_ ## z( BOOST_PP_ADD( n, 1 ), TEMPL_PARAMS, _ )>            \
inline bool                                                                         \
check_frwd( Pred P, unit_test::lazy_ostream const& assertion_descr,                 \
            const_string file_name, std::size_t line_num,                           \
            tool_level tl, check_type ct                                            \
            BOOST_PP_REPEAT_ ## z( BOOST_PP_ADD( n, 1 ), FUNC_PARAMS, _ )           \
)                                                                                   \
{                                                                                   \
    return                                                                          \
    report_assertion( P( BOOST_PP_REPEAT_ ## z(BOOST_PP_ADD(n, 1), PRED_PARAMS,_) ),\
                assertion_descr, file_name, line_num, tl, ct,                       \
                BOOST_PP_ADD( n, 1 )                                                \
                BOOST_PP_REPEAT_ ## z( BOOST_PP_ADD( n, 1 ), ARG_INFO, _ )          \
    );                                                                              \
}                                                                                   \
/**/

#ifndef BOOST_TEST_MAX_PREDICATE_ARITY
#define BOOST_TEST_MAX_PREDICATE_ARITY 5
#endif

BOOST_PP_REPEAT( BOOST_TEST_MAX_PREDICATE_ARITY, IMPL_FRWD, _ )

#undef TEMPL_PARAMS
#undef FUNC_PARAMS
#undef PRED_INFO
#undef ARG_INFO
#undef IMPL_FRWD

#endif

//____________________________________________________________________________//

template <class Left, class Right>
inline assertion_result equal_impl( Left const& left, Right const& right )
{
    return left == right;
}

//____________________________________________________________________________//

inline assertion_result equal_impl( char* left, char const* right ) { return equal_impl( static_cast<char const*>(left), static_cast<char const*>(right) ); }
inline assertion_result equal_impl( char const* left, char* right ) { return equal_impl( static_cast<char const*>(left), static_cast<char const*>(right) ); }
inline assertion_result equal_impl( char* left, char* right )       { return equal_impl( static_cast<char const*>(left), static_cast<char const*>(right) ); }

#if !defined( BOOST_NO_CWCHAR )
assertion_result        BOOST_TEST_DECL equal_impl( wchar_t const* left, wchar_t const* right );
inline assertion_result equal_impl( wchar_t* left, wchar_t const* right ) { return equal_impl( static_cast<wchar_t const*>(left), static_cast<wchar_t const*>(right) ); }
inline assertion_result equal_impl( wchar_t const* left, wchar_t* right ) { return equal_impl( static_cast<wchar_t const*>(left), static_cast<wchar_t const*>(right) ); }
inline assertion_result equal_impl( wchar_t* left, wchar_t* right )       { return equal_impl( static_cast<wchar_t const*>(left), static_cast<wchar_t const*>(right) ); }
#endif

//____________________________________________________________________________//

struct equal_impl_frwd {
    template <typename Left, typename Right>
    inline assertion_result
    call_impl( Left const& left, Right const& right, mpl::false_ ) const
    {
        return equal_impl( left, right );
    }

    template <typename Left, typename Right>
    inline assertion_result
    call_impl( Left const& left, Right const& right, mpl::true_ ) const
    {
        return (*this)( right, &left[0] );
    }

    template <typename Left, typename Right>
    inline assertion_result
    operator()( Left const& left, Right const& right ) const
    {
        typedef typename is_array<Left>::type left_is_array;
        return call_impl( left, right, left_is_array() );
    }
};

//____________________________________________________________________________//

struct ne_impl {
    template <class Left, class Right>
    assertion_result operator()( Left const& left, Right const& right )
    {
        return !equal_impl_frwd()( left, right );
    }
};

//____________________________________________________________________________//

struct lt_impl {
    template <class Left, class Right>
    assertion_result operator()( Left const& left, Right const& right )
    {
        return left < right;
    }
};

//____________________________________________________________________________//

struct le_impl {
    template <class Left, class Right>
    assertion_result operator()( Left const& left, Right const& right )
    {
        return left <= right;
    }
};

//____________________________________________________________________________//

struct gt_impl {
    template <class Left, class Right>
    assertion_result operator()( Left const& left, Right const& right )
    {
        return left > right;
    }
};

//____________________________________________________________________________//

struct ge_impl {
    template <class Left, class Right>
    assertion_result operator()( Left const& left, Right const& right )
    {
        return left >= right;
    }
};

//____________________________________________________________________________//

struct equal_coll_impl {
    template <typename Left, typename Right>
    assertion_result operator()( Left left_begin, Left left_end, Right right_begin, Right right_end )
    {
        assertion_result    pr( true );
        std::size_t         pos = 0;

        for( ; left_begin != left_end && right_begin != right_end; ++left_begin, ++right_begin, ++pos ) {
            if( *left_begin != *right_begin ) {
                pr = false;
                pr.message() << "\nMismatch at position " << pos << ": "
                  << ::boost::test_tools::tt_detail::print_helper(*left_begin)
                  << " != "
                  << ::boost::test_tools::tt_detail::print_helper(*right_begin);
            }
        }

        if( left_begin != left_end ) {
            std::size_t r_size = pos;
            while( left_begin != left_end ) {
                ++pos;
                ++left_begin;
            }

            pr = false;
            pr.message() << "\nCollections size mismatch: " << pos << " != " << r_size;
        }

        if( right_begin != right_end ) {
            std::size_t l_size = pos;
            while( right_begin != right_end ) {
                ++pos;
                ++right_begin;
            }

            pr = false;
            pr.message() << "\nCollections size mismatch: " << l_size << " != " << pos;
        }

        return pr;
    }
};

//____________________________________________________________________________//

struct bitwise_equal_impl {
    template <class Left, class Right>
    assertion_result    operator()( Left const& left, Right const& right )
    {
        assertion_result    pr( true );

        std::size_t left_bit_size  = sizeof(Left)*CHAR_BIT;
        std::size_t right_bit_size = sizeof(Right)*CHAR_BIT;

        static Left const leftOne( 1 );
        static Right const rightOne( 1 );

        std::size_t total_bits = left_bit_size < right_bit_size ? left_bit_size : right_bit_size;

        for( std::size_t counter = 0; counter < total_bits; ++counter ) {
            if( ( left & ( leftOne << counter ) ) != ( right & ( rightOne << counter ) ) ) {
                pr = false;
                pr.message() << "\nMismatch at position " << counter;
            }
        }

        if( left_bit_size != right_bit_size ) {
            pr = false;
            pr.message() << "\nOperands bit sizes mismatch: " << left_bit_size << " != " << right_bit_size;
        }

        return pr;
    }
};

//____________________________________________________________________________//

template<typename FPT1, typename FPT2>
struct comp_supertype {
    // deduce "better" type from types of arguments being compared
    // if one type is floating and the second integral we use floating type and
    // value of integral type is promoted to the floating. The same for float and double
    // But we don't want to compare two values of integral types using this tool.
    typedef typename numeric::conversion_traits<FPT1,FPT2>::supertype type;
    BOOST_STATIC_ASSERT_MSG( !is_integral<type>::value, "Only floating-point types can be compared!");
};

} // namespace tt_detail

namespace fpc = math::fpc;

// ************************************************************************** //
// **************               check_is_close                 ************** //
// ************************************************************************** //

struct BOOST_TEST_DECL check_is_close_t {
    // Public typedefs
    typedef assertion_result result_type;

    template<typename FPT1, typename FPT2, typename ToleranceType>
    assertion_result
    operator()( FPT1 left, FPT2 right, ToleranceType tolerance ) const
    {
        fpc::close_at_tolerance<typename tt_detail::comp_supertype<FPT1,FPT2>::type> pred( tolerance, fpc::FPC_STRONG );

        assertion_result ar( pred( left, right ) );

        if( !ar )
            ar.message() << pred.tested_rel_diff();

        return ar;
    }
};

//____________________________________________________________________________//

template<typename FPT1, typename FPT2, typename ToleranceType>
inline assertion_result
check_is_close( FPT1 left, FPT2 right, ToleranceType tolerance )
{
    return check_is_close_t()( left, right, tolerance );
}

//____________________________________________________________________________//

// ************************************************************************** //
// **************               check_is_small                 ************** //
// ************************************************************************** //

struct BOOST_TEST_DECL check_is_small_t {
    // Public typedefs
    typedef bool result_type;

    template<typename FPT>
    bool
    operator()( FPT fpv, FPT tolerance ) const
    {
        return fpc::is_small( fpv, tolerance );
    }
};

//____________________________________________________________________________//

template<typename FPT>
inline bool
check_is_small( FPT fpv, FPT tolerance )
{
    return fpc::is_small( fpv, tolerance );
}

//____________________________________________________________________________//

} // namespace test_tools
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_TOOLS_OLD_IMPL_HPP_012705GER