diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-09-09 10:41:17 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-09-09 10:41:17 +0100 |
commit | 4dcee38fd3728efb9ec7b1309526e174eb918b21 (patch) | |
tree | 7c878b36534f53a5a4c68200a61a909b142b644e /contrib/doctest | |
parent | 4c6234a1a07c3fd777551c6789ad0b44523da210 (diff) | |
download | rspamd-4dcee38fd3728efb9ec7b1309526e174eb918b21.tar.gz rspamd-4dcee38fd3728efb9ec7b1309526e174eb918b21.zip |
[Minor] Update bundled doctest to the latest version
Diffstat (limited to 'contrib/doctest')
-rw-r--r-- | contrib/doctest/CMakeLists.txt | 4 | ||||
-rw-r--r-- | contrib/doctest/doctest/doctest.h | 167 | ||||
-rw-r--r-- | contrib/doctest/doctest/parts/doctest.cpp | 86 | ||||
-rw-r--r-- | contrib/doctest/doctest/parts/doctest_fwd.h | 81 |
4 files changed, 242 insertions, 96 deletions
diff --git a/contrib/doctest/CMakeLists.txt b/contrib/doctest/CMakeLists.txt index 563726deb..4a17708ff 100644 --- a/contrib/doctest/CMakeLists.txt +++ b/contrib/doctest/CMakeLists.txt @@ -8,7 +8,7 @@ endif() ## DOCTEST ################################################################################ -project(doctest VERSION 2.4.5 LANGUAGES CXX) +project(doctest VERSION 2.4.6 LANGUAGES CXX) # Determine if doctest is built as a subproject (using add_subdirectory) or if it is the main project. set(MAIN_PROJECT OFF) @@ -60,4 +60,4 @@ endif() if(DOCTEST_USE_STD_HEADERS) target_compile_definitions(${PROJECT_NAME} INTERFACE DOCTEST_CONFIG_USE_STD_HEADERS) -endif()
\ No newline at end of file +endif() diff --git a/contrib/doctest/doctest/doctest.h b/contrib/doctest/doctest/doctest.h index 7a2534d79..42eb03997 100644 --- a/contrib/doctest/doctest/doctest.h +++ b/contrib/doctest/doctest/doctest.h @@ -48,8 +48,8 @@ #define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 5 -#define DOCTEST_VERSION_STR "2.4.5" +#define DOCTEST_VERSION_PATCH 6 +#define DOCTEST_VERSION_STR "2.4.6" #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -781,6 +781,29 @@ namespace detail { template<class T> struct remove_reference<T&> { typedef T type; }; template<class T> struct remove_reference<T&&> { typedef T type; }; + template<typename T, typename U = T&&> U declval(int); + + template<typename T> T declval(long); + + template<typename T> auto declval() DOCTEST_NOEXCEPT -> decltype(declval<T>(0)) ; + + template<class T> struct is_lvalue_reference { const static bool value=false; }; + template<class T> struct is_lvalue_reference<T&> { const static bool value=true; }; + + template <class T> + inline T&& forward(typename remove_reference<T>::type& t) DOCTEST_NOEXCEPT + { + return static_cast<T&&>(t); + } + + template <class T> + inline T&& forward(typename remove_reference<T>::type&& t) DOCTEST_NOEXCEPT + { + static_assert(!is_lvalue_reference<T>::value, + "Can not forward an rvalue as an lvalue."); + return static_cast<T&&>(t); + } + template<class T> struct remove_const { typedef T type; }; template<class T> struct remove_const<const T> { typedef T type; }; #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS @@ -1048,10 +1071,20 @@ namespace detail { return toString(lhs) + op + toString(rhs); } +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + +// This will check if there is any way it could find a operator like member or friend and uses it. +// If not it doesn't find the operator or if the operator at global scope is defined after +// this template, the template won't be instantiated due to SFINAE. Once the template is not +// instantiated it can look for global operator using normal conversions. +#define SFINAE_OP(ret,op) decltype(doctest::detail::declval<L>() op doctest::detail::declval<R>(),static_cast<ret>(0)) + #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ template <typename R> \ - DOCTEST_NOINLINE Result operator op(const DOCTEST_REF_WRAP(R) rhs) { \ - bool res = op_macro(lhs, rhs); \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + bool res = op_macro(doctest::detail::forward<L>(lhs), doctest::detail::forward<R>(rhs)); \ if(m_at & assertType::is_false) \ res = !res; \ if(!res || doctest::getContextOptions()->success) \ @@ -1179,12 +1212,16 @@ namespace detail { L lhs; assertType::Enum m_at; - explicit Expression_lhs(L in, assertType::Enum at) - : lhs(in) + explicit Expression_lhs(L&& in, assertType::Enum at) + : lhs(doctest::detail::forward<L>(in)) , m_at(at) {} DOCTEST_NOINLINE operator Result() { - bool res = !!lhs; +// this is needed only foc MSVC 2015: +// https://ci.appveyor.com/project/onqtam/doctest/builds/38181202 +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast<bool>(lhs); +DOCTEST_MSVC_SUPPRESS_WARNING_POP if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional res = !res; @@ -1193,6 +1230,10 @@ namespace detail { return Result(res); } + /* This is required for user-defined conversions from Expression_lhs to L */ + //operator L() const { return lhs; } + operator L() const { return lhs; } + // clang-format off DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional @@ -1233,6 +1274,10 @@ namespace detail { #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_POP +#endif + struct DOCTEST_INTERFACE ExpressionDecomposer { assertType::Enum m_at; @@ -1244,8 +1289,8 @@ namespace detail { // https://github.com/catchorg/Catch2/issues/870 // https://github.com/catchorg/Catch2/issues/565 template <typename L> - Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) { - return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand, m_at); + Expression_lhs<L> operator<<(L &&operand) { + return Expression_lhs<L>(doctest::detail::forward<L>(operand), m_at); } }; @@ -1534,7 +1579,7 @@ namespace detail { template <typename L> class ContextScope : public ContextScopeBase { - const L &lambda_; + const L lambda_; public: explicit ContextScope(const L &lambda) : lambda_(lambda) {} @@ -1933,10 +1978,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - static doctest::detail::TestSuite data; \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ static bool inited = false; \ DOCTEST_MSVC_SUPPRESS_WARNING_POP \ DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ if(!inited) { \ data* decorators; \ inited = true; \ @@ -1991,17 +2038,15 @@ int registerReporter(const char* name, int priority, bool isReporter) { // for logging #define DOCTEST_INFO(...) \ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \ - DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), __VA_ARGS__) + __VA_ARGS__) -#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, ...) \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \ - auto lambda_name = [&](std::ostream* s_name) { \ +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ + [&](std::ostream* s_name) { \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ mb_name.m_stream = s_name; \ mb_name * __VA_ARGS__; \ - }; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name) + }) #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) @@ -2857,6 +2902,10 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #define DOCTEST_OPTIONS_PREFIX_DISPLAY "" #endif +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS +#endif + namespace doctest { bool is_running_in_test = false; @@ -3017,21 +3066,21 @@ typedef timer_large_integer::type ticks_t; "guarantee one atomic takes exactly one cache line"); public: - T operator++() noexcept { return fetch_add(1) + 1; } + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } - T operator++(int) noexcept { return fetch_add(1); } + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept { + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { return myAtomic().fetch_add(arg, order); } - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept { + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { return myAtomic().fetch_sub(arg, order); } - operator T() const noexcept { return load(); } + operator T() const DOCTEST_NOEXCEPT { return load(); } - T load(std::memory_order order = std::memory_order_seq_cst) const noexcept { + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { auto result = T(); for(auto const& c : m_atomics) { result += c.atomic.load(order); @@ -3039,12 +3088,12 @@ typedef timer_large_integer::type ticks_t; return result; } - T operator=(T desired) noexcept { + T operator=(T desired) DOCTEST_NOEXCEPT { store(desired); return desired; } - void store(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept { + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { // first value becomes desired", all others become 0. for(auto& c : m_atomics) { c.atomic.store(desired, order); @@ -3065,7 +3114,7 @@ typedef timer_large_integer::type ticks_t; // assigned in a round-robin fashion. // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with // little overhead. - std::atomic<T>& myAtomic() noexcept { + std::atomic<T>& myAtomic() DOCTEST_NOEXCEPT { static std::atomic<size_t> laneCounter; DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; @@ -3577,7 +3626,7 @@ int registerReporter(const char*, int, IReporter*) { return 0; } namespace doctest_detail_test_suite_ns { // holds the current test suite doctest::detail::TestSuite& getCurrentTestSuite() { - static doctest::detail::TestSuite data; + static doctest::detail::TestSuite data{}; return data; } } // namespace doctest_detail_test_suite_ns @@ -3731,7 +3780,7 @@ namespace detail { g_cs->subcasesPassed.insert(g_cs->subcasesStack); g_cs->subcasesStack.pop_back(); -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) if(std::uncaught_exceptions() > 0 #else if(std::uncaught_exception() @@ -3839,6 +3888,12 @@ namespace detail { return file_cmp < 0; return m_template_id < other.m_template_id; } + + // all the registered tests + std::set<TestCase>& getRegisteredTests() { + static std::set<TestCase> data; + return data; + } } // namespace detail namespace { using namespace detail; @@ -3870,12 +3925,6 @@ namespace { return suiteOrderComparator(lhs, rhs); } - // all the registered tests - std::set<TestCase>& getRegisteredTests() { - static std::set<TestCase> data; - return data; - } - #ifdef DOCTEST_CONFIG_COLORS_WINDOWS HANDLE g_stdoutHandle; WORD g_origFgAttrs; @@ -4104,7 +4153,7 @@ namespace detail { // ContextScope has been destroyed (base class destructors run after derived class destructors). // Instead, ContextScope calls this method directly from its destructor. void ContextScopeBase::destroy() { -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) if(std::uncaught_exceptions() > 0) { #else if(std::uncaught_exception()) { @@ -4126,7 +4175,9 @@ namespace { #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) struct FatalConditionHandler { - void reset() {} + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} }; #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH @@ -4179,6 +4230,9 @@ namespace { std::exit(EXIT_FAILURE); } + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + FatalConditionHandler() { isSet = true; // 32k seems enough for doctest to handle stack overflow, @@ -4196,7 +4250,7 @@ namespace { // - std::terminate is called FROM THE TEST RUNNER THREAD // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD original_terminate_handler = std::get_terminate(); - std::set_terminate([]() noexcept { + std::set_terminate([]() DOCTEST_NOEXCEPT { reportFatal("Terminate handler called"); if(isDebuggerActive() && !g_cs->no_breaks) DOCTEST_BREAK_INTO_DEBUGGER(); @@ -4207,7 +4261,7 @@ namespace { // - std::terminate is called FROM A DIFFERENT THREAD // - an exception is thrown from a destructor FROM A DIFFERENT THREAD // - an uncaught exception is thrown FROM A DIFFERENT THREAD - prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) noexcept { + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { if(signal == SIGABRT) { reportFatal("SIGABRT - Abort (abnormal termination) signal"); if(isDebuggerActive() && !g_cs->no_breaks) @@ -4296,7 +4350,8 @@ namespace { static bool isSet; static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; static stack_t oldSigStack; - static char altStackMem[4 * SIGSTKSZ]; + static size_t altStackSize; + static char* altStackMem; static void handleSignal(int sig) { const char* name = "<unknown signal>"; @@ -4312,11 +4367,19 @@ namespace { raise(sig); } + static void allocateAltStackMem() { + altStackMem = new char[altStackSize]; + } + + static void freeAltStackMem() { + delete[] altStackMem; + } + FatalConditionHandler() { isSet = true; stack_t sigStack; sigStack.ss_sp = altStackMem; - sigStack.ss_size = sizeof(altStackMem); + sigStack.ss_size = altStackSize; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = {}; @@ -4341,10 +4404,11 @@ namespace { } }; - bool FatalConditionHandler::isSet = false; + bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; + char* FatalConditionHandler::altStackMem = nullptr; #endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH @@ -5902,8 +5966,10 @@ namespace { bool with_col = g_no_colors; \ g_no_colors = false; \ ConsoleReporter::func(arg); \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ + if(oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ g_no_colors = with_col; \ } @@ -6090,7 +6156,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ - p->var = !!intRes; \ + p->var = static_cast<bool>(intRes); \ else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ p->var = true; \ @@ -6235,7 +6301,11 @@ int Context::run() { p->cout = &fstr; } + FatalConditionHandler::allocateAltStackMem(); + auto cleanup_and_return = [&]() { + FatalConditionHandler::freeAltStackMem(); + if(fstr.is_open()) fstr.close(); @@ -6409,10 +6479,13 @@ int Context::run() { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS try { #endif // DOCTEST_CONFIG_NO_EXCEPTIONS +// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable FatalConditionHandler fatalConditionHandler; // Handle signals // execute the test tc.m_test(); fatalConditionHandler.reset(); +DOCTEST_MSVC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS } catch(const TestFailureException&) { p->failure_flags |= TestCaseFailureReason::AssertFailure; diff --git a/contrib/doctest/doctest/parts/doctest.cpp b/contrib/doctest/doctest/parts/doctest.cpp index a76193bbf..5b7442086 100644 --- a/contrib/doctest/doctest/parts/doctest.cpp +++ b/contrib/doctest/doctest/parts/doctest.cpp @@ -188,6 +188,10 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #define DOCTEST_OPTIONS_PREFIX_DISPLAY "" #endif +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS +#endif + namespace doctest { bool is_running_in_test = false; @@ -348,21 +352,21 @@ typedef timer_large_integer::type ticks_t; "guarantee one atomic takes exactly one cache line"); public: - T operator++() noexcept { return fetch_add(1) + 1; } + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } - T operator++(int) noexcept { return fetch_add(1); } + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept { + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { return myAtomic().fetch_add(arg, order); } - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept { + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { return myAtomic().fetch_sub(arg, order); } - operator T() const noexcept { return load(); } + operator T() const DOCTEST_NOEXCEPT { return load(); } - T load(std::memory_order order = std::memory_order_seq_cst) const noexcept { + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { auto result = T(); for(auto const& c : m_atomics) { result += c.atomic.load(order); @@ -370,12 +374,12 @@ typedef timer_large_integer::type ticks_t; return result; } - T operator=(T desired) noexcept { + T operator=(T desired) DOCTEST_NOEXCEPT { store(desired); return desired; } - void store(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept { + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { // first value becomes desired", all others become 0. for(auto& c : m_atomics) { c.atomic.store(desired, order); @@ -396,7 +400,7 @@ typedef timer_large_integer::type ticks_t; // assigned in a round-robin fashion. // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with // little overhead. - std::atomic<T>& myAtomic() noexcept { + std::atomic<T>& myAtomic() DOCTEST_NOEXCEPT { static std::atomic<size_t> laneCounter; DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; @@ -908,7 +912,7 @@ int registerReporter(const char*, int, IReporter*) { return 0; } namespace doctest_detail_test_suite_ns { // holds the current test suite doctest::detail::TestSuite& getCurrentTestSuite() { - static doctest::detail::TestSuite data; + static doctest::detail::TestSuite data{}; return data; } } // namespace doctest_detail_test_suite_ns @@ -1062,7 +1066,7 @@ namespace detail { g_cs->subcasesPassed.insert(g_cs->subcasesStack); g_cs->subcasesStack.pop_back(); -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) if(std::uncaught_exceptions() > 0 #else if(std::uncaught_exception() @@ -1170,6 +1174,12 @@ namespace detail { return file_cmp < 0; return m_template_id < other.m_template_id; } + + // all the registered tests + std::set<TestCase>& getRegisteredTests() { + static std::set<TestCase> data; + return data; + } } // namespace detail namespace { using namespace detail; @@ -1201,12 +1211,6 @@ namespace { return suiteOrderComparator(lhs, rhs); } - // all the registered tests - std::set<TestCase>& getRegisteredTests() { - static std::set<TestCase> data; - return data; - } - #ifdef DOCTEST_CONFIG_COLORS_WINDOWS HANDLE g_stdoutHandle; WORD g_origFgAttrs; @@ -1435,7 +1439,7 @@ namespace detail { // ContextScope has been destroyed (base class destructors run after derived class destructors). // Instead, ContextScope calls this method directly from its destructor. void ContextScopeBase::destroy() { -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) if(std::uncaught_exceptions() > 0) { #else if(std::uncaught_exception()) { @@ -1457,7 +1461,9 @@ namespace { #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) struct FatalConditionHandler { - void reset() {} + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} }; #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH @@ -1510,6 +1516,9 @@ namespace { std::exit(EXIT_FAILURE); } + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + FatalConditionHandler() { isSet = true; // 32k seems enough for doctest to handle stack overflow, @@ -1527,7 +1536,7 @@ namespace { // - std::terminate is called FROM THE TEST RUNNER THREAD // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD original_terminate_handler = std::get_terminate(); - std::set_terminate([]() noexcept { + std::set_terminate([]() DOCTEST_NOEXCEPT { reportFatal("Terminate handler called"); if(isDebuggerActive() && !g_cs->no_breaks) DOCTEST_BREAK_INTO_DEBUGGER(); @@ -1538,7 +1547,7 @@ namespace { // - std::terminate is called FROM A DIFFERENT THREAD // - an exception is thrown from a destructor FROM A DIFFERENT THREAD // - an uncaught exception is thrown FROM A DIFFERENT THREAD - prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) noexcept { + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { if(signal == SIGABRT) { reportFatal("SIGABRT - Abort (abnormal termination) signal"); if(isDebuggerActive() && !g_cs->no_breaks) @@ -1627,7 +1636,8 @@ namespace { static bool isSet; static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; static stack_t oldSigStack; - static char altStackMem[4 * SIGSTKSZ]; + static size_t altStackSize; + static char* altStackMem; static void handleSignal(int sig) { const char* name = "<unknown signal>"; @@ -1643,11 +1653,19 @@ namespace { raise(sig); } + static void allocateAltStackMem() { + altStackMem = new char[altStackSize]; + } + + static void freeAltStackMem() { + delete[] altStackMem; + } + FatalConditionHandler() { isSet = true; stack_t sigStack; sigStack.ss_sp = altStackMem; - sigStack.ss_size = sizeof(altStackMem); + sigStack.ss_size = altStackSize; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = {}; @@ -1672,10 +1690,11 @@ namespace { } }; - bool FatalConditionHandler::isSet = false; + bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; + char* FatalConditionHandler::altStackMem = nullptr; #endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH @@ -3233,8 +3252,10 @@ namespace { bool with_col = g_no_colors; \ g_no_colors = false; \ ConsoleReporter::func(arg); \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ + if(oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ g_no_colors = with_col; \ } @@ -3421,7 +3442,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ - p->var = !!intRes; \ + p->var = static_cast<bool>(intRes); \ else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ p->var = true; \ @@ -3566,7 +3587,11 @@ int Context::run() { p->cout = &fstr; } + FatalConditionHandler::allocateAltStackMem(); + auto cleanup_and_return = [&]() { + FatalConditionHandler::freeAltStackMem(); + if(fstr.is_open()) fstr.close(); @@ -3740,10 +3765,13 @@ int Context::run() { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS try { #endif // DOCTEST_CONFIG_NO_EXCEPTIONS +// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable FatalConditionHandler fatalConditionHandler; // Handle signals // execute the test tc.m_test(); fatalConditionHandler.reset(); +DOCTEST_MSVC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS } catch(const TestFailureException&) { p->failure_flags |= TestCaseFailureReason::AssertFailure; diff --git a/contrib/doctest/doctest/parts/doctest_fwd.h b/contrib/doctest/doctest/parts/doctest_fwd.h index 1ae807a4e..e83b0ca7e 100644 --- a/contrib/doctest/doctest/parts/doctest_fwd.h +++ b/contrib/doctest/doctest/parts/doctest_fwd.h @@ -45,8 +45,8 @@ #define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 5 -#define DOCTEST_VERSION_STR "2.4.5" +#define DOCTEST_VERSION_PATCH 6 +#define DOCTEST_VERSION_STR "2.4.6" #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -778,6 +778,29 @@ namespace detail { template<class T> struct remove_reference<T&> { typedef T type; }; template<class T> struct remove_reference<T&&> { typedef T type; }; + template<typename T, typename U = T&&> U declval(int); + + template<typename T> T declval(long); + + template<typename T> auto declval() DOCTEST_NOEXCEPT -> decltype(declval<T>(0)) ; + + template<class T> struct is_lvalue_reference { const static bool value=false; }; + template<class T> struct is_lvalue_reference<T&> { const static bool value=true; }; + + template <class T> + inline T&& forward(typename remove_reference<T>::type& t) DOCTEST_NOEXCEPT + { + return static_cast<T&&>(t); + } + + template <class T> + inline T&& forward(typename remove_reference<T>::type&& t) DOCTEST_NOEXCEPT + { + static_assert(!is_lvalue_reference<T>::value, + "Can not forward an rvalue as an lvalue."); + return static_cast<T&&>(t); + } + template<class T> struct remove_const { typedef T type; }; template<class T> struct remove_const<const T> { typedef T type; }; #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS @@ -1045,10 +1068,20 @@ namespace detail { return toString(lhs) + op + toString(rhs); } +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + +// This will check if there is any way it could find a operator like member or friend and uses it. +// If not it doesn't find the operator or if the operator at global scope is defined after +// this template, the template won't be instantiated due to SFINAE. Once the template is not +// instantiated it can look for global operator using normal conversions. +#define SFINAE_OP(ret,op) decltype(doctest::detail::declval<L>() op doctest::detail::declval<R>(),static_cast<ret>(0)) + #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ template <typename R> \ - DOCTEST_NOINLINE Result operator op(const DOCTEST_REF_WRAP(R) rhs) { \ - bool res = op_macro(lhs, rhs); \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + bool res = op_macro(doctest::detail::forward<L>(lhs), doctest::detail::forward<R>(rhs)); \ if(m_at & assertType::is_false) \ res = !res; \ if(!res || doctest::getContextOptions()->success) \ @@ -1176,12 +1209,16 @@ namespace detail { L lhs; assertType::Enum m_at; - explicit Expression_lhs(L in, assertType::Enum at) - : lhs(in) + explicit Expression_lhs(L&& in, assertType::Enum at) + : lhs(doctest::detail::forward<L>(in)) , m_at(at) {} DOCTEST_NOINLINE operator Result() { - bool res = !!lhs; +// this is needed only foc MSVC 2015: +// https://ci.appveyor.com/project/onqtam/doctest/builds/38181202 +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast<bool>(lhs); +DOCTEST_MSVC_SUPPRESS_WARNING_POP if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional res = !res; @@ -1190,6 +1227,10 @@ namespace detail { return Result(res); } + /* This is required for user-defined conversions from Expression_lhs to L */ + //operator L() const { return lhs; } + operator L() const { return lhs; } + // clang-format off DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional @@ -1230,6 +1271,10 @@ namespace detail { #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_POP +#endif + struct DOCTEST_INTERFACE ExpressionDecomposer { assertType::Enum m_at; @@ -1241,8 +1286,8 @@ namespace detail { // https://github.com/catchorg/Catch2/issues/870 // https://github.com/catchorg/Catch2/issues/565 template <typename L> - Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) { - return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand, m_at); + Expression_lhs<L> operator<<(L &&operand) { + return Expression_lhs<L>(doctest::detail::forward<L>(operand), m_at); } }; @@ -1531,7 +1576,7 @@ namespace detail { template <typename L> class ContextScope : public ContextScopeBase { - const L &lambda_; + const L lambda_; public: explicit ContextScope(const L &lambda) : lambda_(lambda) {} @@ -1930,10 +1975,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - static doctest::detail::TestSuite data; \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ static bool inited = false; \ DOCTEST_MSVC_SUPPRESS_WARNING_POP \ DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ if(!inited) { \ data* decorators; \ inited = true; \ @@ -1988,17 +2035,15 @@ int registerReporter(const char* name, int priority, bool isReporter) { // for logging #define DOCTEST_INFO(...) \ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \ - DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), __VA_ARGS__) + __VA_ARGS__) -#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, ...) \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \ - auto lambda_name = [&](std::ostream* s_name) { \ +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ + [&](std::ostream* s_name) { \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ mb_name.m_stream = s_name; \ mb_name * __VA_ARGS__; \ - }; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name) + }) #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) |