File indexing completed on 2025-01-30 09:35:14
0001 #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP
0002 #define BOOST_CORE_LIGHTWEIGHT_TEST_HPP
0003
0004
0005
0006 #if defined(_MSC_VER)
0007 # pragma once
0008 #endif
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <boost/core/detail/lwt_unattended.hpp>
0026 #include <boost/current_function.hpp>
0027 #include <boost/config.hpp>
0028 #include <exception>
0029 #include <iostream>
0030 #include <iterator>
0031 #include <string>
0032 #include <cstdlib>
0033 #include <cstring>
0034 #include <cstddef>
0035 #include <cctype>
0036
0037
0038
0039 #ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
0040 # define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
0041 #endif
0042
0043 namespace boost
0044 {
0045 namespace detail
0046 {
0047
0048 class test_result
0049 {
0050 public:
0051
0052 test_result(): report_( false ), errors_( 0 )
0053 {
0054 core::detail::lwt_unattended();
0055 }
0056
0057 ~test_result()
0058 {
0059 if( !report_ )
0060 {
0061 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "main() should return report_errors()" << std::endl;
0062 std::abort();
0063 }
0064 }
0065
0066 int& errors()
0067 {
0068 return errors_;
0069 }
0070
0071 void done()
0072 {
0073 report_ = true;
0074 }
0075
0076 private:
0077
0078 bool report_;
0079 int errors_;
0080 };
0081
0082 inline test_result& test_results()
0083 {
0084 static test_result instance;
0085 return instance;
0086 }
0087
0088 inline int& test_errors()
0089 {
0090 return test_results().errors();
0091 }
0092
0093 inline bool test_impl(char const * expr, char const * file, int line, char const * function, bool v)
0094 {
0095 if( v )
0096 {
0097 test_results();
0098 return true;
0099 }
0100 else
0101 {
0102 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0103 << file << "(" << line << "): test '" << expr << "' failed in function '"
0104 << function << "'" << std::endl;
0105 ++test_results().errors();
0106 return false;
0107 }
0108 }
0109
0110 inline void error_impl(char const * msg, char const * file, int line, char const * function)
0111 {
0112 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0113 << file << "(" << line << "): " << msg << " in function '"
0114 << function << "'" << std::endl;
0115 ++test_results().errors();
0116 }
0117
0118 inline void throw_failed_impl(const char* expr, char const * excep, char const * file, int line, char const * function)
0119 {
0120 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0121 << file << "(" << line << "): expression '" << expr << "' did not throw exception '" << excep << "' in function '"
0122 << function << "'" << std::endl;
0123 ++test_results().errors();
0124 }
0125
0126 inline void no_throw_failed_impl(const char* expr, const char* file, int line, const char* function)
0127 {
0128 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0129 << file << "(" << line << "): expression '" << expr << "' threw an exception in function '"
0130 << function << "'" << std::endl;
0131 ++test_results().errors();
0132 }
0133
0134 inline void no_throw_failed_impl(const char* expr, const char* what, const char* file, int line, const char* function)
0135 {
0136 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0137 << file << "(" << line << "): expression '" << expr << "' threw an exception in function '"
0138 << function << "': " << what << std::endl;
0139 ++test_results().errors();
0140 }
0141
0142
0143
0144
0145 #if defined(__clang__) && defined(__has_warning)
0146 # if __has_warning("-Wsign-compare")
0147 # pragma clang diagnostic push
0148 # pragma clang diagnostic ignored "-Wsign-compare"
0149 # endif
0150 #elif defined(_MSC_VER)
0151 # pragma warning(push)
0152 # pragma warning(disable: 4389)
0153 #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
0154 # pragma GCC diagnostic push
0155 # pragma GCC diagnostic ignored "-Wsign-compare"
0156 #endif
0157
0158
0159 template <class T> inline const T& test_output_impl(const T& v) { return v; }
0160 inline const void* test_output_impl(const char* v) { return v; }
0161 inline const void* test_output_impl(const unsigned char* v) { return v; }
0162 inline const void* test_output_impl(const signed char* v) { return v; }
0163 inline const void* test_output_impl(char* v) { return v; }
0164 inline const void* test_output_impl(unsigned char* v) { return v; }
0165 inline const void* test_output_impl(signed char* v) { return v; }
0166 template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
0167
0168 #if !defined( BOOST_NO_CXX11_NULLPTR )
0169 inline const void* test_output_impl(std::nullptr_t) { return nullptr; }
0170 #endif
0171
0172
0173
0174 inline int test_output_impl( signed char const& v ) { return v; }
0175 inline unsigned test_output_impl( unsigned char const& v ) { return v; }
0176
0177
0178
0179 template<bool Signed> struct lwt_long_type {};
0180 template<> struct lwt_long_type<true> { typedef long type; };
0181 template<> struct lwt_long_type<false> { typedef unsigned long type; };
0182
0183 inline lwt_long_type<(static_cast<wchar_t>(-1) < static_cast<wchar_t>(0))>::type test_output_impl( wchar_t const& v ) { return v; }
0184
0185 #if !defined( BOOST_NO_CXX11_CHAR16_T )
0186 inline unsigned long test_output_impl( char16_t const& v ) { return v; }
0187 #endif
0188
0189 #if !defined( BOOST_NO_CXX11_CHAR32_T )
0190 inline unsigned long test_output_impl( char32_t const& v ) { return v; }
0191 #endif
0192
0193 inline std::string test_output_impl( char const& v )
0194 {
0195 if( std::isprint( static_cast<unsigned char>( v ) ) )
0196 {
0197 return std::string( 1, v );
0198 }
0199 else
0200 {
0201 static const char char_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0202 char buffer[ 4 ];
0203 buffer[ 0 ] = '\\';
0204 buffer[ 1 ] = 'x';
0205 buffer[ 2 ] = char_table[ (static_cast<unsigned char>( v ) >> 4u) & 0x0f ];
0206 buffer[ 3 ] = char_table[ static_cast<unsigned char>( v ) & 0x0f ];
0207
0208 return std::string( buffer, 4u );
0209 }
0210 }
0211
0212
0213
0214 struct lw_test_eq
0215 {
0216 template <typename T, typename U>
0217 bool operator()(const T& t, const U& u) const { return t == u; }
0218 };
0219
0220 struct lw_test_ne
0221 {
0222 template <typename T, typename U>
0223 bool operator()(const T& t, const U& u) const { return t != u; }
0224 };
0225
0226 struct lw_test_lt
0227 {
0228 template <typename T, typename U>
0229 bool operator()(const T& t, const U& u) const { return t < u; }
0230 };
0231
0232 struct lw_test_le
0233 {
0234 template <typename T, typename U>
0235 bool operator()(const T& t, const U& u) const { return t <= u; }
0236 };
0237
0238 struct lw_test_gt
0239 {
0240 template <typename T, typename U>
0241 bool operator()(const T& t, const U& u) const { return t > u; }
0242 };
0243
0244 struct lw_test_ge
0245 {
0246 template <typename T, typename U>
0247 bool operator()(const T& t, const U& u) const { return t >= u; }
0248 };
0249
0250
0251
0252 template<class T> char const * lwt_predicate_name( T const& )
0253 {
0254 return "~=";
0255 }
0256
0257 inline char const * lwt_predicate_name( lw_test_eq const& )
0258 {
0259 return "==";
0260 }
0261
0262 inline char const * lwt_predicate_name( lw_test_ne const& )
0263 {
0264 return "!=";
0265 }
0266
0267 inline char const * lwt_predicate_name( lw_test_lt const& )
0268 {
0269 return "<";
0270 }
0271
0272 inline char const * lwt_predicate_name( lw_test_le const& )
0273 {
0274 return "<=";
0275 }
0276
0277 inline char const * lwt_predicate_name( lw_test_gt const& )
0278 {
0279 return ">";
0280 }
0281
0282 inline char const * lwt_predicate_name( lw_test_ge const& )
0283 {
0284 return ">=";
0285 }
0286
0287
0288
0289 template<class BinaryPredicate, class T, class U>
0290 inline bool test_with_impl(BinaryPredicate pred, char const * expr1, char const * expr2,
0291 char const * file, int line, char const * function,
0292 T const & t, U const & u)
0293 {
0294 if( pred(t, u) )
0295 {
0296 test_results();
0297 return true;
0298 }
0299 else
0300 {
0301 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0302 << file << "(" << line << "): test '" << expr1 << " " << lwt_predicate_name(pred) << " " << expr2
0303 << "' ('" << test_output_impl(t) << "' " << lwt_predicate_name(pred) << " '" << test_output_impl(u)
0304 << "') failed in function '" << function << "'" << std::endl;
0305 ++test_results().errors();
0306 return false;
0307 }
0308 }
0309
0310 inline bool test_cstr_eq_impl( char const * expr1, char const * expr2,
0311 char const * file, int line, char const * function, char const * const t, char const * const u )
0312 {
0313 if( std::strcmp(t, u) == 0 )
0314 {
0315 test_results();
0316 return true;
0317 }
0318 else
0319 {
0320 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0321 << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' ('" << t
0322 << "' == '" << u << "') failed in function '" << function << "'" << std::endl;
0323 ++test_results().errors();
0324 return false;
0325 }
0326 }
0327
0328 inline bool test_cstr_ne_impl( char const * expr1, char const * expr2,
0329 char const * file, int line, char const * function, char const * const t, char const * const u )
0330 {
0331 if( std::strcmp(t, u) != 0 )
0332 {
0333 test_results();
0334 return true;
0335 }
0336 else
0337 {
0338 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0339 << file << "(" << line << "): test '" << expr1 << " != " << expr2 << "' ('" << t
0340 << "' != '" << u << "') failed in function '" << function << "'" << std::endl;
0341 ++test_results().errors();
0342 return false;
0343 }
0344 }
0345
0346 template<class FormattedOutputFunction, class InputIterator1, class InputIterator2>
0347 bool test_all_eq_impl(FormattedOutputFunction& output,
0348 char const * file, int line, char const * function,
0349 InputIterator1 first_begin, InputIterator1 first_end,
0350 InputIterator2 second_begin, InputIterator2 second_end)
0351 {
0352 InputIterator1 first_it = first_begin;
0353 InputIterator2 second_it = second_begin;
0354 typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
0355 typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
0356 std::size_t error_count = 0;
0357 const std::size_t max_count = 8;
0358 do
0359 {
0360 while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it))
0361 {
0362 ++first_it;
0363 ++second_it;
0364 ++first_index;
0365 ++second_index;
0366 }
0367 if ((first_it == first_end) || (second_it == second_end))
0368 {
0369 break;
0370 }
0371 if (error_count == 0)
0372 {
0373 output << file << "(" << line << "): Container contents differ in function '" << function << "':";
0374 }
0375 else if (error_count >= max_count)
0376 {
0377 output << " ...";
0378 break;
0379 }
0380 output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'";
0381 ++first_it;
0382 ++second_it;
0383 ++first_index;
0384 ++second_index;
0385 ++error_count;
0386 } while (first_it != first_end);
0387
0388 first_index += std::distance(first_it, first_end);
0389 second_index += std::distance(second_it, second_end);
0390 if (first_index != second_index)
0391 {
0392 if (error_count == 0)
0393 {
0394 output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
0395 }
0396 else
0397 {
0398 output << " [*] size(" << first_index << ") != size(" << second_index << ")";
0399 }
0400 ++error_count;
0401 }
0402
0403 if (error_count == 0)
0404 {
0405 test_results();
0406 return true;
0407 }
0408 else
0409 {
0410 output << std::endl;
0411 ++test_results().errors();
0412 return false;
0413 }
0414 }
0415
0416 template<class FormattedOutputFunction, class InputIterator1, class InputIterator2, typename BinaryPredicate>
0417 bool test_all_with_impl(FormattedOutputFunction& output,
0418 char const * file, int line, char const * function,
0419 InputIterator1 first_begin, InputIterator1 first_end,
0420 InputIterator2 second_begin, InputIterator2 second_end,
0421 BinaryPredicate predicate)
0422 {
0423 InputIterator1 first_it = first_begin;
0424 InputIterator2 second_it = second_begin;
0425 typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
0426 typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
0427 std::size_t error_count = 0;
0428 const std::size_t max_count = 8;
0429 do
0430 {
0431 while ((first_it != first_end) && (second_it != second_end) && predicate(*first_it, *second_it))
0432 {
0433 ++first_it;
0434 ++second_it;
0435 ++first_index;
0436 ++second_index;
0437 }
0438 if ((first_it == first_end) || (second_it == second_end))
0439 {
0440 break;
0441 }
0442 if (error_count == 0)
0443 {
0444 output << file << "(" << line << "): Container contents differ in function '" << function << "':";
0445 }
0446 else if (error_count >= max_count)
0447 {
0448 output << " ...";
0449 break;
0450 }
0451 output << " [" << first_index << "]";
0452 ++first_it;
0453 ++second_it;
0454 ++first_index;
0455 ++second_index;
0456 ++error_count;
0457 } while (first_it != first_end);
0458
0459 first_index += std::distance(first_it, first_end);
0460 second_index += std::distance(second_it, second_end);
0461 if (first_index != second_index)
0462 {
0463 if (error_count == 0)
0464 {
0465 output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
0466 }
0467 else
0468 {
0469 output << " [*] size(" << first_index << ") != size(" << second_index << ")";
0470 }
0471 ++error_count;
0472 }
0473
0474 if (error_count == 0)
0475 {
0476 test_results();
0477 return true;
0478 }
0479 else
0480 {
0481 output << std::endl;
0482 ++test_results().errors();
0483 return false;
0484 }
0485 }
0486
0487 #if defined(__clang__) && defined(__has_warning)
0488 # if __has_warning("-Wsign-compare")
0489 # pragma clang diagnostic pop
0490 # endif
0491 #elif defined(_MSC_VER)
0492 # pragma warning(pop)
0493 #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
0494 # pragma GCC diagnostic pop
0495 #endif
0496
0497 }
0498
0499 inline int report_errors()
0500 {
0501 boost::detail::test_result& result = boost::detail::test_results();
0502 result.done();
0503
0504 int errors = result.errors();
0505
0506 if( errors == 0 )
0507 {
0508 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0509 << "No errors detected." << std::endl;
0510 }
0511 else
0512 {
0513 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0514 << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
0515 }
0516
0517
0518 return errors < 256? errors: 255;
0519 }
0520
0521 namespace core
0522 {
0523
0524 inline void lwt_init()
0525 {
0526 boost::detail::test_results();
0527 }
0528
0529 }
0530 }
0531
0532 #define BOOST_TEST(expr) ( ::boost::detail::test_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (expr)? true: false) )
0533 #define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr))
0534
0535 #define BOOST_ERROR(msg) ( ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
0536
0537 #define BOOST_TEST_WITH(expr1,expr2,predicate) ( ::boost::detail::test_with_impl(predicate, #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0538
0539 #define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_eq(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0540 #define BOOST_TEST_NE(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_ne(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0541
0542 #define BOOST_TEST_LT(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_lt(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0543 #define BOOST_TEST_LE(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_le(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0544 #define BOOST_TEST_GT(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_gt(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0545 #define BOOST_TEST_GE(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_ge(), #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0546
0547 #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0548 #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0549
0550 #define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) )
0551 #define BOOST_TEST_ALL_WITH(begin1, end1, begin2, end2, predicate) ( ::boost::detail::test_all_with_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2, predicate) )
0552
0553 #ifndef BOOST_NO_EXCEPTIONS
0554 #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
0555 try { \
0556 EXPR; \
0557 ::boost::detail::throw_failed_impl \
0558 (#EXPR, #EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0559 } \
0560 catch(EXCEP const&) { \
0561 ::boost::detail::test_results(); \
0562 } \
0563 catch(...) { \
0564 ::boost::detail::throw_failed_impl \
0565 (#EXPR, #EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0566 } \
0567
0568 #else
0569 #define BOOST_TEST_THROWS( EXPR, EXCEP )
0570 #endif
0571
0572 #ifndef BOOST_NO_EXCEPTIONS
0573 # define BOOST_TEST_NO_THROW(EXPR) \
0574 try { \
0575 EXPR; \
0576 } catch (const std::exception& e) { \
0577 ::boost::detail::no_throw_failed_impl \
0578 (#EXPR, e.what(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0579 } catch (...) { \
0580 ::boost::detail::no_throw_failed_impl \
0581 (#EXPR, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0582 }
0583
0584 #else
0585 # define BOOST_TEST_NO_THROW(EXPR) { EXPR; }
0586 #endif
0587
0588 #endif