Back to home page

EIC code displayed by LXR

 
 

    


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 // MS compatible compilers support #pragma once
0005 
0006 #if defined(_MSC_VER)
0007 # pragma once
0008 #endif
0009 
0010 //
0011 //  boost/core/lightweight_test.hpp - lightweight test library
0012 //
0013 //  Copyright (c) 2002, 2009, 2014 Peter Dimov
0014 //  Copyright (2) Beman Dawes 2010, 2011
0015 //  Copyright (3) Ion Gaztanaga 2013
0016 //
0017 //  Copyright 2018 Glen Joseph Fernandes
0018 //  (glenjofe@gmail.com)
0019 //
0020 //  Distributed under the Boost Software License, Version 1.0.
0021 //  See accompanying file LICENSE_1_0.txt or copy at
0022 //  http://www.boost.org/LICENSE_1_0.txt
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 //  IDE's like Visual Studio perform better if output goes to std::cout or
0038 //  some other stream, so allow user to configure output stream:
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 // In the comparisons below, it is possible that T and U are signed and unsigned integer types, which generates warnings in some compilers.
0143 // A cleaner fix would require common_type trait or some meta-programming, which would introduce a dependency on Boost.TypeTraits. To avoid
0144 // the dependency we just disable the warnings.
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 // specialize test output for char pointers to avoid printing as cstring
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 // print chars as numeric
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 // Whether wchar_t is signed is implementation-defined
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 // predicates
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 // lwt_predicate_name
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; // do-while
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; // do-while
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 } // namespace detail
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     // `return report_errors();` from main only supports 8 bit exit codes
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 } // namespace core
0531 } // namespace boost
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 // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP