123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP
- #define BOOST_CORE_LIGHTWEIGHT_TEST_HPP
- // MS compatible compilers support #pragma once
- #if defined(_MSC_VER)
- # pragma once
- #endif
- //
- // boost/core/lightweight_test.hpp - lightweight test library
- //
- // Copyright (c) 2002, 2009, 2014 Peter Dimov
- // Copyright (2) Beman Dawes 2010, 2011
- // Copyright (3) Ion Gaztanaga 2013
- //
- // Copyright 2018 Glen Joseph Fernandes
- // ([email protected])
- //
- // 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
- //
- #include <boost/current_function.hpp>
- #include <boost/config.hpp>
- #include <iostream>
- #include <iterator>
- #include <cstdlib>
- #include <cstring>
- #include <cstddef>
- // IDE's like Visual Studio perform better if output goes to std::cout or
- // some other stream, so allow user to configure output stream:
- #ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
- # define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
- #endif
- namespace boost
- {
- namespace detail
- {
- class test_result {
- public:
- test_result()
- : report_(false)
- , errors_(0) {
- #if defined(_MSC_VER) && (_MSC_VER > 1310)
- ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
- #endif
- }
- ~test_result() {
- if (!report_) {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM << "main() should return report_errors()" << std::endl;
- std::abort();
- }
- }
- int& errors() {
- return errors_;
- }
- void done() {
- report_ = true;
- }
- private:
- bool report_;
- int errors_;
- };
- inline test_result& test_results()
- {
- static test_result instance;
- return instance;
- }
- inline int& test_errors()
- {
- return test_results().errors();
- }
- inline void test_failed_impl(char const * expr, char const * file, int line, char const * function)
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test '" << expr << "' failed in function '"
- << function << "'" << std::endl;
- ++test_results().errors();
- }
- inline void error_impl(char const * msg, char const * file, int line, char const * function)
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): " << msg << " in function '"
- << function << "'" << std::endl;
- ++test_results().errors();
- }
- inline void throw_failed_impl(char const * excep, char const * file, int line, char const * function)
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): Exception '" << excep << "' not thrown in function '"
- << function << "'" << std::endl;
- ++test_results().errors();
- }
- // In the comparisons below, it is possible that T and U are signed and unsigned integer types, which generates warnings in some compilers.
- // A cleaner fix would require common_type trait or some meta-programming, which would introduce a dependency on Boost.TypeTraits. To avoid
- // the dependency we just disable the warnings.
- #if defined(_MSC_VER)
- # pragma warning(push)
- # pragma warning(disable: 4389)
- #elif defined(__clang__) && defined(__has_warning)
- # if __has_warning("-Wsign-compare")
- # pragma clang diagnostic push
- # pragma clang diagnostic ignored "-Wsign-compare"
- # endif
- #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
- # pragma GCC diagnostic push
- # pragma GCC diagnostic ignored "-Wsign-compare"
- #endif
- // specialize test output for char pointers to avoid printing as cstring
- template <class T> inline const T& test_output_impl(const T& v) { return v; }
- inline const void* test_output_impl(const char* v) { return v; }
- inline const void* test_output_impl(const unsigned char* v) { return v; }
- inline const void* test_output_impl(const signed char* v) { return v; }
- inline const void* test_output_impl(char* v) { return v; }
- inline const void* test_output_impl(unsigned char* v) { return v; }
- inline const void* test_output_impl(signed char* v) { return v; }
- template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
- #if !defined( BOOST_NO_CXX11_NULLPTR )
- inline const void* test_output_impl(std::nullptr_t) { return nullptr; }
- #endif
- struct lw_test_eq {
- template <typename T, typename U>
- bool operator()(const T& t, const U& u) const { return t == u; }
- static const char* op() { return "=="; }
- };
- struct lw_test_ne {
- template <typename T, typename U>
- bool operator()(const T& t, const U& u) const { return t != u; }
- static const char* op() { return "!="; }
- };
- struct lw_test_lt {
- template <typename T, typename U>
- bool operator()(const T& t, const U& u) const { return t < u; }
- static const char* op() { return "<"; }
- };
- struct lw_test_le {
- template <typename T, typename U>
- bool operator()(const T& t, const U& u) const { return t <= u; }
- static const char* op() { return "<="; }
- };
- struct lw_test_gt {
- template <typename T, typename U>
- bool operator()(const T& t, const U& u) const { return t > u; }
- static const char* op() { return ">"; }
- };
- struct lw_test_ge {
- template <typename T, typename U>
- bool operator()(const T& t, const U& u) const { return t >= u; }
- static const char* op() { return ">="; }
- };
- template<class BinaryPredicate, class T, class U>
- inline void test_with_impl(BinaryPredicate pred, char const * expr1, char const * expr2,
- char const * file, int line, char const * function,
- T const & t, U const & u)
- {
- if( pred(t, u) )
- {
- test_results();
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test '" << expr1 << " " << pred.op() << " " << expr2
- << "' ('" << test_output_impl(t) << "' " << pred.op() << " '" << test_output_impl(u)
- << "') failed in function '" << function << "'" << std::endl;
- ++test_results().errors();
- }
- }
- inline void test_cstr_eq_impl( char const * expr1, char const * expr2,
- char const * file, int line, char const * function, char const * const t, char const * const u )
- {
- if( std::strcmp(t, u) == 0 )
- {
- test_results();
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' ('" << t
- << "' == '" << u << "') failed in function '" << function << "'" << std::endl;
- ++test_results().errors();
- }
- }
- inline void test_cstr_ne_impl( char const * expr1, char const * expr2,
- char const * file, int line, char const * function, char const * const t, char const * const u )
- {
- if( std::strcmp(t, u) != 0 )
- {
- test_results();
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test '" << expr1 << " != " << expr2 << "' ('" << t
- << "' != '" << u << "') failed in function '" << function << "'" << std::endl;
- ++test_results().errors();
- }
- }
- template<class FormattedOutputFunction, class InputIterator1, class InputIterator2>
- void test_all_eq_impl(FormattedOutputFunction& output,
- char const * file, int line, char const * function,
- InputIterator1 first_begin, InputIterator1 first_end,
- InputIterator2 second_begin, InputIterator2 second_end)
- {
- InputIterator1 first_it = first_begin;
- InputIterator2 second_it = second_begin;
- typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
- typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
- std::size_t error_count = 0;
- const std::size_t max_count = 8;
- do
- {
- while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it))
- {
- ++first_it;
- ++second_it;
- ++first_index;
- ++second_index;
- }
- if ((first_it == first_end) || (second_it == second_end))
- {
- break; // do-while
- }
- if (error_count == 0)
- {
- output << file << "(" << line << "): Container contents differ in function '" << function << "':";
- }
- else if (error_count >= max_count)
- {
- output << " ...";
- break;
- }
- output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'";
- ++first_it;
- ++second_it;
- ++first_index;
- ++second_index;
- ++error_count;
- } while (first_it != first_end);
- first_index += std::distance(first_it, first_end);
- second_index += std::distance(second_it, second_end);
- if (first_index != second_index)
- {
- if (error_count == 0)
- {
- output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
- }
- else
- {
- output << " [*] size(" << first_index << ") != size(" << second_index << ")";
- }
- ++error_count;
- }
- if (error_count == 0)
- {
- test_results();
- }
- else
- {
- output << std::endl;
- ++test_results().errors();
- }
- }
- template<class FormattedOutputFunction, class InputIterator1, class InputIterator2, typename BinaryPredicate>
- void test_all_with_impl(FormattedOutputFunction& output,
- char const * file, int line, char const * function,
- InputIterator1 first_begin, InputIterator1 first_end,
- InputIterator2 second_begin, InputIterator2 second_end,
- BinaryPredicate predicate)
- {
- InputIterator1 first_it = first_begin;
- InputIterator2 second_it = second_begin;
- typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
- typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
- std::size_t error_count = 0;
- const std::size_t max_count = 8;
- do
- {
- while ((first_it != first_end) && (second_it != second_end) && predicate(*first_it, *second_it))
- {
- ++first_it;
- ++second_it;
- ++first_index;
- ++second_index;
- }
- if ((first_it == first_end) || (second_it == second_end))
- {
- break; // do-while
- }
- if (error_count == 0)
- {
- output << file << "(" << line << "): Container contents differ in function '" << function << "':";
- }
- else if (error_count >= max_count)
- {
- output << " ...";
- break;
- }
- output << " [" << first_index << "]";
- ++first_it;
- ++second_it;
- ++first_index;
- ++second_index;
- ++error_count;
- } while (first_it != first_end);
- first_index += std::distance(first_it, first_end);
- second_index += std::distance(second_it, second_end);
- if (first_index != second_index)
- {
- if (error_count == 0)
- {
- output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
- }
- else
- {
- output << " [*] size(" << first_index << ") != size(" << second_index << ")";
- }
- ++error_count;
- }
- if (error_count == 0)
- {
- test_results();
- }
- else
- {
- output << std::endl;
- ++test_results().errors();
- }
- }
- #if defined(_MSC_VER)
- # pragma warning(pop)
- #elif defined(__clang__) && defined(__has_warning)
- # if __has_warning("-Wsign-compare")
- # pragma clang diagnostic pop
- # endif
- #elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
- # pragma GCC diagnostic pop
- #endif
- } // namespace detail
- inline int report_errors()
- {
- boost::detail::test_result& result = boost::detail::test_results();
- result.done();
- int errors = result.errors();
- if( errors == 0 )
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << "No errors detected." << std::endl;
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
- }
- // `return report_errors();` from main only supports 8 bit exit codes
- return errors < 256? errors: 255;
- }
- } // namespace boost
- #define BOOST_TEST(expr) ((expr)? (void)::boost::detail::test_results(): ::boost::detail::test_failed_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
- #define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr))
- #define BOOST_ERROR(msg) ( ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
- #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) )
- #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) )
- #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) )
- #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) )
- #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) )
- #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) )
- #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
- #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
- #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) )
- #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) )
- #ifndef BOOST_NO_EXCEPTIONS
- #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
- try { \
- EXPR; \
- ::boost::detail::throw_failed_impl \
- (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
- } \
- catch(EXCEP const&) { \
- ::boost::detail::test_results(); \
- } \
- catch(...) { \
- ::boost::detail::throw_failed_impl \
- (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
- } \
- //
- #else
- #define BOOST_TEST_THROWS( EXPR, EXCEP )
- #endif
- #endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_HPP
|