File indexing completed on 2025-07-02 08:08:15
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 # pragma GCC diagnostic ignored "-Wsign-conversion"
0157 #endif
0158
0159
0160 template <class T> inline const T& test_output_impl(const T& v) { return v; }
0161 inline const void* test_output_impl(const char* v) { return v; }
0162 inline const void* test_output_impl(const unsigned char* v) { return v; }
0163 inline const void* test_output_impl(const signed char* v) { return v; }
0164 inline const void* test_output_impl(char* v) { return v; }
0165 inline const void* test_output_impl(unsigned char* v) { return v; }
0166 inline const void* test_output_impl(signed char* v) { return v; }
0167 template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
0168
0169 #if !defined( BOOST_NO_CXX11_NULLPTR )
0170 inline const void* test_output_impl(std::nullptr_t) { return nullptr; }
0171 #endif
0172
0173
0174
0175 inline int test_output_impl( signed char const& v ) { return v; }
0176 inline unsigned test_output_impl( unsigned char const& v ) { return v; }
0177
0178
0179
0180 template<bool Signed> struct lwt_long_type {};
0181 template<> struct lwt_long_type<true> { typedef long type; };
0182 template<> struct lwt_long_type<false> { typedef unsigned long type; };
0183
0184 inline lwt_long_type<(static_cast<wchar_t>(-1) < static_cast<wchar_t>(0))>::type test_output_impl( wchar_t const& v ) { return v; }
0185
0186 #if !defined( BOOST_NO_CXX11_CHAR16_T )
0187 inline unsigned long test_output_impl( char16_t const& v ) { return v; }
0188 #endif
0189
0190 #if !defined( BOOST_NO_CXX11_CHAR32_T )
0191 inline unsigned long test_output_impl( char32_t const& v ) { return v; }
0192 #endif
0193
0194 inline std::string test_output_impl( char const& v )
0195 {
0196 if( std::isprint( static_cast<unsigned char>( v ) ) )
0197 {
0198 return std::string( 1, v );
0199 }
0200 else
0201 {
0202 static const char char_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0203 char buffer[ 4 ];
0204 buffer[ 0 ] = '\\';
0205 buffer[ 1 ] = 'x';
0206 buffer[ 2 ] = char_table[ (static_cast<unsigned char>( v ) >> 4u) & 0x0f ];
0207 buffer[ 3 ] = char_table[ static_cast<unsigned char>( v ) & 0x0f ];
0208
0209 return std::string( buffer, 4u );
0210 }
0211 }
0212
0213
0214
0215 struct lw_test_eq
0216 {
0217 template <typename T, typename U>
0218 bool operator()(const T& t, const U& u) const { return t == u; }
0219 };
0220
0221 struct lw_test_ne
0222 {
0223 template <typename T, typename U>
0224 bool operator()(const T& t, const U& u) const { return t != u; }
0225 };
0226
0227 struct lw_test_lt
0228 {
0229 template <typename T, typename U>
0230 bool operator()(const T& t, const U& u) const { return t < u; }
0231 };
0232
0233 struct lw_test_le
0234 {
0235 template <typename T, typename U>
0236 bool operator()(const T& t, const U& u) const { return t <= u; }
0237 };
0238
0239 struct lw_test_gt
0240 {
0241 template <typename T, typename U>
0242 bool operator()(const T& t, const U& u) const { return t > u; }
0243 };
0244
0245 struct lw_test_ge
0246 {
0247 template <typename T, typename U>
0248 bool operator()(const T& t, const U& u) const { return t >= u; }
0249 };
0250
0251
0252
0253 template<class T> char const * lwt_predicate_name( T const& )
0254 {
0255 return "~=";
0256 }
0257
0258 inline char const * lwt_predicate_name( lw_test_eq const& )
0259 {
0260 return "==";
0261 }
0262
0263 inline char const * lwt_predicate_name( lw_test_ne const& )
0264 {
0265 return "!=";
0266 }
0267
0268 inline char const * lwt_predicate_name( lw_test_lt const& )
0269 {
0270 return "<";
0271 }
0272
0273 inline char const * lwt_predicate_name( lw_test_le const& )
0274 {
0275 return "<=";
0276 }
0277
0278 inline char const * lwt_predicate_name( lw_test_gt const& )
0279 {
0280 return ">";
0281 }
0282
0283 inline char const * lwt_predicate_name( lw_test_ge const& )
0284 {
0285 return ">=";
0286 }
0287
0288
0289
0290 template<class BinaryPredicate, class T, class U>
0291 inline bool test_with_impl(BinaryPredicate pred, char const * expr1, char const * expr2,
0292 char const * file, int line, char const * function,
0293 T const & t, U const & u)
0294 {
0295 if( pred(t, u) )
0296 {
0297 test_results();
0298 return true;
0299 }
0300 else
0301 {
0302 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0303 << file << "(" << line << "): test '" << expr1 << " " << lwt_predicate_name(pred) << " " << expr2
0304 << "' ('" << test_output_impl(t) << "' " << lwt_predicate_name(pred) << " '" << test_output_impl(u)
0305 << "') failed in function '" << function << "'" << std::endl;
0306 ++test_results().errors();
0307 return false;
0308 }
0309 }
0310
0311 inline bool test_cstr_eq_impl( char const * expr1, char const * expr2,
0312 char const * file, int line, char const * function, char const * const t, char const * const u )
0313 {
0314 if( std::strcmp(t, u) == 0 )
0315 {
0316 test_results();
0317 return true;
0318 }
0319 else
0320 {
0321 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0322 << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' ('" << t
0323 << "' == '" << u << "') failed in function '" << function << "'" << std::endl;
0324 ++test_results().errors();
0325 return false;
0326 }
0327 }
0328
0329 inline bool test_cstr_ne_impl( char const * expr1, char const * expr2,
0330 char const * file, int line, char const * function, char const * const t, char const * const u )
0331 {
0332 if( std::strcmp(t, u) != 0 )
0333 {
0334 test_results();
0335 return true;
0336 }
0337 else
0338 {
0339 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0340 << file << "(" << line << "): test '" << expr1 << " != " << expr2 << "' ('" << t
0341 << "' != '" << u << "') failed in function '" << function << "'" << std::endl;
0342 ++test_results().errors();
0343 return false;
0344 }
0345 }
0346
0347 template<class FormattedOutputFunction, class InputIterator1, class InputIterator2>
0348 bool test_all_eq_impl(FormattedOutputFunction& output,
0349 char const * file, int line, char const * function,
0350 InputIterator1 first_begin, InputIterator1 first_end,
0351 InputIterator2 second_begin, InputIterator2 second_end)
0352 {
0353 InputIterator1 first_it = first_begin;
0354 InputIterator2 second_it = second_begin;
0355 typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
0356 typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
0357 std::size_t error_count = 0;
0358 const std::size_t max_count = 8;
0359 do
0360 {
0361 while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it))
0362 {
0363 ++first_it;
0364 ++second_it;
0365 ++first_index;
0366 ++second_index;
0367 }
0368 if ((first_it == first_end) || (second_it == second_end))
0369 {
0370 break;
0371 }
0372 if (error_count == 0)
0373 {
0374 output << file << "(" << line << "): Container contents differ in function '" << function << "':";
0375 }
0376 else if (error_count >= max_count)
0377 {
0378 output << " ...";
0379 break;
0380 }
0381 output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'";
0382 ++first_it;
0383 ++second_it;
0384 ++first_index;
0385 ++second_index;
0386 ++error_count;
0387 } while (first_it != first_end);
0388
0389 first_index += std::distance(first_it, first_end);
0390 second_index += std::distance(second_it, second_end);
0391 if (first_index != second_index)
0392 {
0393 if (error_count == 0)
0394 {
0395 output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
0396 }
0397 else
0398 {
0399 output << " [*] size(" << first_index << ") != size(" << second_index << ")";
0400 }
0401 ++error_count;
0402 }
0403
0404 if (error_count == 0)
0405 {
0406 test_results();
0407 return true;
0408 }
0409 else
0410 {
0411 output << std::endl;
0412 ++test_results().errors();
0413 return false;
0414 }
0415 }
0416
0417 template<class FormattedOutputFunction, class InputIterator1, class InputIterator2, typename BinaryPredicate>
0418 bool test_all_with_impl(FormattedOutputFunction& output,
0419 char const * file, int line, char const * function,
0420 InputIterator1 first_begin, InputIterator1 first_end,
0421 InputIterator2 second_begin, InputIterator2 second_end,
0422 BinaryPredicate predicate)
0423 {
0424 InputIterator1 first_it = first_begin;
0425 InputIterator2 second_it = second_begin;
0426 typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
0427 typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
0428 std::size_t error_count = 0;
0429 const std::size_t max_count = 8;
0430 do
0431 {
0432 while ((first_it != first_end) && (second_it != second_end) && predicate(*first_it, *second_it))
0433 {
0434 ++first_it;
0435 ++second_it;
0436 ++first_index;
0437 ++second_index;
0438 }
0439 if ((first_it == first_end) || (second_it == second_end))
0440 {
0441 break;
0442 }
0443 if (error_count == 0)
0444 {
0445 output << file << "(" << line << "): Container contents differ in function '" << function << "':";
0446 }
0447 else if (error_count >= max_count)
0448 {
0449 output << " ...";
0450 break;
0451 }
0452 output << " [" << first_index << "]";
0453 ++first_it;
0454 ++second_it;
0455 ++first_index;
0456 ++second_index;
0457 ++error_count;
0458 } while (first_it != first_end);
0459
0460 first_index += std::distance(first_it, first_end);
0461 second_index += std::distance(second_it, second_end);
0462 if (first_index != second_index)
0463 {
0464 if (error_count == 0)
0465 {
0466 output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
0467 }
0468 else
0469 {
0470 output << " [*] size(" << first_index << ") != size(" << second_index << ")";
0471 }
0472 ++error_count;
0473 }
0474
0475 if (error_count == 0)
0476 {
0477 test_results();
0478 return true;
0479 }
0480 else
0481 {
0482 output << std::endl;
0483 ++test_results().errors();
0484 return false;
0485 }
0486 }
0487
0488 #if defined(__clang__) && defined(__has_warning)
0489 # if __has_warning("-Wsign-compare")
0490 # pragma clang diagnostic pop
0491 # endif
0492 #elif defined(_MSC_VER)
0493 # pragma warning(pop)
0494 #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
0495 # pragma GCC diagnostic pop
0496 #endif
0497
0498 }
0499
0500 inline int report_errors()
0501 {
0502 boost::detail::test_result& result = boost::detail::test_results();
0503 result.done();
0504
0505 int errors = result.errors();
0506
0507 if( errors == 0 )
0508 {
0509 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0510 << "No errors detected." << std::endl;
0511 }
0512 else
0513 {
0514 BOOST_LIGHTWEIGHT_TEST_OSTREAM
0515 << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
0516 }
0517
0518
0519 return errors < 256? errors: 255;
0520 }
0521
0522 namespace core
0523 {
0524
0525 inline void lwt_init()
0526 {
0527 boost::detail::test_results();
0528 }
0529
0530 }
0531 }
0532
0533 #define BOOST_TEST(expr) ( ::boost::detail::test_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (expr)? true: false) )
0534 #define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr))
0535
0536 #define BOOST_ERROR(msg) ( ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
0537
0538 #define BOOST_TEST_WITH(expr1,expr2,predicate) ( ::boost::detail::test_with_impl(predicate, #expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0539
0540 #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) )
0541 #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) )
0542
0543 #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) )
0544 #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) )
0545 #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) )
0546 #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) )
0547
0548 #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0549 #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
0550
0551 #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) )
0552 #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) )
0553
0554 #ifndef BOOST_NO_EXCEPTIONS
0555 #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
0556 try { \
0557 EXPR; \
0558 ::boost::detail::throw_failed_impl \
0559 (#EXPR, #EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0560 } \
0561 catch(EXCEP const&) { \
0562 ::boost::detail::test_results(); \
0563 } \
0564 catch(...) { \
0565 ::boost::detail::throw_failed_impl \
0566 (#EXPR, #EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0567 } \
0568
0569 #else
0570 #define BOOST_TEST_THROWS( EXPR, EXCEP )
0571 #endif
0572
0573 #ifndef BOOST_NO_EXCEPTIONS
0574 # define BOOST_TEST_NO_THROW(EXPR) \
0575 try { \
0576 EXPR; \
0577 } catch (const std::exception& e) { \
0578 ::boost::detail::no_throw_failed_impl \
0579 (#EXPR, e.what(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0580 } catch (...) { \
0581 ::boost::detail::no_throw_failed_impl \
0582 (#EXPR, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
0583 }
0584
0585 #else
0586 # define BOOST_TEST_NO_THROW(EXPR) { EXPR; }
0587 #endif
0588
0589 #endif