From 6390fca71a18c401c06ed398e3442ded413313a9 Mon Sep 17 00:00:00 2001 From: Krylov Yaroslav Date: Sat, 12 Dec 2020 05:27:03 +0300 Subject: [PATCH] Doctest is updated to v2.4.1 --- test/thirdparty/doctest/LICENSE.txt | 4 +- test/thirdparty/doctest/doctest.h | 888 +++++++++++++++++++--------- 2 files changed, 598 insertions(+), 294 deletions(-) diff --git a/test/thirdparty/doctest/LICENSE.txt b/test/thirdparty/doctest/LICENSE.txt index a20472146..155dbe942 100755 --- a/test/thirdparty/doctest/LICENSE.txt +++ b/test/thirdparty/doctest/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2019 Viktor Kirilov +Copyright (c) 2016-2020 Viktor Kirilov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/test/thirdparty/doctest/doctest.h b/test/thirdparty/doctest/doctest.h index 2f0ff2131..4aff80b19 100755 --- a/test/thirdparty/doctest/doctest.h +++ b/test/thirdparty/doctest/doctest.h @@ -4,7 +4,7 @@ // // doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD // -// Copyright (c) 2016-2019 Viktor Kirilov +// Copyright (c) 2016-2020 Viktor Kirilov // // Distributed under the MIT Software License // See accompanying file LICENSE.txt or copy at @@ -47,9 +47,9 @@ // ================================================================================================= #define DOCTEST_VERSION_MAJOR 2 -#define DOCTEST_VERSION_MINOR 3 -#define DOCTEST_VERSION_PATCH 7 -#define DOCTEST_VERSION_STR "2.3.7" +#define DOCTEST_VERSION_MINOR 4 +#define DOCTEST_VERSION_PATCH 1 +#define DOCTEST_VERSION_STR "2.4.1" #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -301,11 +301,23 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' #define DOCTEST_NOINLINE __declspec(noinline) #define DOCTEST_UNUSED #define DOCTEST_ALIGNMENT(x) -#else // MSVC +#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) +#define DOCTEST_NOINLINE +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#else #define DOCTEST_NOINLINE __attribute__((noinline)) #define DOCTEST_UNUSED __attribute__((unused)) #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) -#endif // MSVC +#endif + +#ifndef DOCTEST_NORETURN +#define DOCTEST_NORETURN [[noreturn]] +#endif // DOCTEST_NORETURN + +#ifndef DOCTEST_NOEXCEPT +#define DOCTEST_NOEXCEPT noexcept +#endif // DOCTEST_NOEXCEPT // ================================================================================================= // == FEATURE DETECTION END ======================================================================== @@ -347,8 +359,20 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' #ifndef DOCTEST_BREAK_INTO_DEBUGGER // should probably take a look at https://github.com/scottt/debugbreak -#ifdef DOCTEST_PLATFORM_MAC +#ifdef DOCTEST_PLATFORM_LINUX +#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) +// Break at the location of the failing check if possible #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) +#else +#include +#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) +#endif +#elif defined(DOCTEST_PLATFORM_MAC) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) +#else +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); +#endif #elif DOCTEST_MSVC #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() #elif defined(__MINGW32__) @@ -357,7 +381,7 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak(); DOCTEST_GCC_SUPPRESS_WARNING_POP #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() #else // linux -#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0) +#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) #endif // linux #endif // DOCTEST_BREAK_INTO_DEBUGGER @@ -367,6 +391,9 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_USE_IOSFWD #ifdef DOCTEST_CONFIG_USE_STD_HEADERS +#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #include #include #include @@ -629,7 +656,7 @@ DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); struct DOCTEST_INTERFACE TestCaseData { - const char* m_file; // the file in which the test was registered + String m_file; // the file in which the test was registered unsigned m_line; // the line where the test was registered const char* m_name; // name of the test case const char* m_test_suite; // the test suite in which the test was added @@ -721,6 +748,7 @@ struct ContextOptions //!OCLINT too many fields bool no_path_in_filenames; // if the path to files should be removed from the output bool no_line_numbers; // if source code line numbers should be omitted from the output bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! + bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! bool help; // to print the help bool version; // to print the version @@ -731,7 +759,6 @@ struct ContextOptions //!OCLINT too many fields }; namespace detail { -#if defined(DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING) || defined(DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS) template struct enable_if {}; @@ -739,7 +766,6 @@ namespace detail { template struct enable_if { typedef TYPE type; }; -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING) || DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS // clang-format off template struct remove_reference { typedef T type; }; @@ -748,6 +774,14 @@ namespace detail { template struct remove_const { typedef T type; }; template struct remove_const { typedef T type; }; +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template struct is_enum : public std::is_enum {}; + template struct underlying_type : public std::underlying_type {}; +#else + // Use compiler intrinsics + template struct is_enum { constexpr static bool value = __is_enum(T); }; + template struct underlying_type { typedef __underlying_type(T) type; }; +#endif // clang-format on template @@ -756,33 +790,23 @@ namespace detail { { static const bool value = false; }; namespace has_insertion_operator_impl { - typedef char no; - typedef char yes[2]; + std::ostream &os(); + template + DOCTEST_REF_WRAP(T) val(); - struct any_t - { - template - // cppcheck-suppress noExplicitConstructor - any_t(const DOCTEST_REF_WRAP(T)); + template + struct check { + static constexpr bool value = false; }; - yes& testStreamable(std::ostream&); - no testStreamable(no); - - no operator<<(const std::ostream&, const any_t&); - - template - struct has_insertion_operator - { - static std::ostream& s; - static const DOCTEST_REF_WRAP(T) t; - static const bool value = sizeof(decltype(testStreamable(s << t))) == sizeof(yes); + template + struct check(), void())> { + static constexpr bool value = true; }; } // namespace has_insertion_operator_impl - template - struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator - {}; + template + using has_insertion_operator = has_insertion_operator_impl::check; DOCTEST_INTERFACE void my_memcpy(void* dest, const void* src, unsigned num); @@ -846,7 +870,7 @@ struct StringMaker } }; -template +template ::value, bool>::type = true> String toString(const DOCTEST_REF_WRAP(T) value) { return StringMaker::convert(value); } @@ -873,6 +897,12 @@ DOCTEST_INTERFACE String toString(int long long in); DOCTEST_INTERFACE String toString(int long long unsigned in); DOCTEST_INTERFACE String toString(std::nullptr_t in); +template ::value, bool>::type = true> +String toString(const DOCTEST_REF_WRAP(T) value) { + typedef typename detail::underlying_type::type UT; + return toString(static_cast(value)); +} + #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) // see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 DOCTEST_INTERFACE String toString(const std::string& in); @@ -987,7 +1017,7 @@ namespace detail { DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - [[noreturn]] + DOCTEST_NORETURN #endif // DOCTEST_CONFIG_NO_EXCEPTIONS DOCTEST_INTERFACE void throwException(); @@ -1284,12 +1314,12 @@ namespace detail { template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; // clang-format on - DOCTEST_BINARY_RELATIONAL_OP(0, eq) - DOCTEST_BINARY_RELATIONAL_OP(1, ne) - DOCTEST_BINARY_RELATIONAL_OP(2, gt) - DOCTEST_BINARY_RELATIONAL_OP(3, lt) - DOCTEST_BINARY_RELATIONAL_OP(4, ge) - DOCTEST_BINARY_RELATIONAL_OP(5, le) + DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) + DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) + DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) + DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) + DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) + DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) struct DOCTEST_INTERFACE ResultBuilder : public AssertData { @@ -1416,9 +1446,9 @@ namespace detail { } catch(T ex) { // NOLINT res = m_translateFunction(ex); //!OCLINT parameter reassignment return true; - } catch(...) {} //!OCLINT - empty catch statement -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - ((void)res); // to silence -Wunused-parameter + } catch(...) {} //!OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter return false; } @@ -1480,7 +1510,7 @@ namespace detail { DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in); DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in); - // ContextScope base class used to allow implementing methods of ContextScope + // ContextScope base class used to allow implementing methods of ContextScope // that don't depend on the template parameter in doctest.cpp. class DOCTEST_INTERFACE ContextScopeBase : public IContextScope { protected: @@ -1737,12 +1767,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { #endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS -#define DOCTEST_CAST_TO_VOID(x) \ +#define DOCTEST_CAST_TO_VOID(...) \ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ - static_cast(x); \ + static_cast(__VA_ARGS__); \ DOCTEST_GCC_SUPPRESS_WARNING_POP #else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS -#define DOCTEST_CAST_TO_VOID(x) x; +#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; #endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS // registers the test by initializing a dummy var with a function @@ -1953,7 +1983,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ mb << x; \ DOCTEST_ASSERT_LOG_AND_REACT(mb); \ - } while((void)0, 0) + } while(false) // clang-format off #define DOCTEST_ADD_MESSAGE_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) @@ -1982,7 +2012,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ do { \ DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ - } while((void)0, 0) + } while(false) #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2006,12 +2036,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) // clang-format off -#define DOCTEST_WARN_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while((void)0, 0) -#define DOCTEST_CHECK_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while((void)0, 0) -#define DOCTEST_REQUIRE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while((void)0, 0) -#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while((void)0, 0) -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while((void)0, 0) -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while((void)0, 0) +#define DOCTEST_WARN_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while(false) +#define DOCTEST_CHECK_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while(false) +#define DOCTEST_REQUIRE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while(false) +#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while(false) +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while(false) +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while(false) // clang-format on #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ @@ -2028,66 +2058,66 @@ int registerReporter(const char* name, int priority, bool isReporter) { } catch(...) { _DOCTEST_RB.translateException(); } \ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ } \ - } while((void)0, 0) + } while(false) -#define DOCTEST_ASSERT_THROWS_WITH(expr, assert_type, ...) \ +#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ do { \ if(!doctest::getContextOptions()->no_throw) { \ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr, "", __VA_ARGS__); \ + __LINE__, expr_str, "", __VA_ARGS__); \ try { \ DOCTEST_CAST_TO_VOID(expr) \ } catch(...) { _DOCTEST_RB.translateException(); } \ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ } \ - } while((void)0, 0) + } while(false) -#define DOCTEST_ASSERT_NOTHROW(expr, assert_type) \ +#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ do { \ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr); \ + __LINE__, #__VA_ARGS__); \ try { \ - DOCTEST_CAST_TO_VOID(expr) \ + DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ } catch(...) { _DOCTEST_RB.translateException(); } \ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ - } while((void)0, 0) + } while(false) // clang-format off -#define DOCTEST_WARN_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS, "") -#define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS, "") -#define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS, "") +#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") +#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "") +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "") #define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) #define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) #define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS_WITH, __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) #define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) #define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) -#define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW) -#define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW) -#define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW) +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__) +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS(expr); } while((void)0, 0) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS(expr); } while((void)0, 0) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS(expr); } while((void)0, 0) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while((void)0, 0) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while((void)0, 0) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while((void)0, 0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, with); } while((void)0, 0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, with); } while((void)0, 0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while((void)0, 0) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while((void)0, 0) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while((void)0, 0) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while((void)0, 0) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS(expr); } while(false) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS(expr); } while(false) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS(expr); } while(false) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while(false) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while(false) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while(false) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, with); } while(false) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, with); } while(false) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while(false) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while(false) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while(false) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while(false) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while(false) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while(false) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while(false) // clang-format on #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2100,7 +2130,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { _DOCTEST_RB.binary_assert( \ __VA_ARGS__)) \ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ - } while((void)0, 0) + } while(false) #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ do { \ @@ -2108,7 +2138,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { __LINE__, #__VA_ARGS__); \ DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(__VA_ARGS__)) \ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ - } while((void)0, 0) + } while(false) #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2184,37 +2214,37 @@ int registerReporter(const char* name, int priority, bool isReporter) { #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_WARN_THROWS(expr) ((void)0) -#define DOCTEST_CHECK_THROWS(expr) ((void)0) -#define DOCTEST_REQUIRE_THROWS(expr) ((void)0) -#define DOCTEST_WARN_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_WARN_NOTHROW(expr) ((void)0) -#define DOCTEST_CHECK_NOTHROW(expr) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) +#define DOCTEST_WARN_THROWS(...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS(...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS(...) (static_cast(0)) +#define DOCTEST_WARN_THROWS_AS(expr, ...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH(expr, ...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) (static_cast(0)) +#define DOCTEST_WARN_NOTHROW(...) (static_cast(0)) +#define DOCTEST_CHECK_NOTHROW(...) (static_cast(0)) +#define DOCTEST_REQUIRE_NOTHROW(...) (static_cast(0)) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast(0)) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) (static_cast(0)) #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS @@ -2305,86 +2335,86 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define DOCTEST_INFO(x) ((void)0) -#define DOCTEST_CAPTURE(x) ((void)0) -#define DOCTEST_ADD_MESSAGE_AT(file, line, x) ((void)0) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) ((void)0) -#define DOCTEST_ADD_FAIL_AT(file, line, x) ((void)0) -#define DOCTEST_MESSAGE(x) ((void)0) -#define DOCTEST_FAIL_CHECK(x) ((void)0) -#define DOCTEST_FAIL(x) ((void)0) +#define DOCTEST_INFO(x) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, x) (static_cast(0)) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) (static_cast(0)) +#define DOCTEST_ADD_FAIL_AT(file, line, x) (static_cast(0)) +#define DOCTEST_MESSAGE(x) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(x) (static_cast(0)) +#define DOCTEST_FAIL(x) (static_cast(0)) -#define DOCTEST_WARN(...) ((void)0) -#define DOCTEST_CHECK(...) ((void)0) -#define DOCTEST_REQUIRE(...) ((void)0) -#define DOCTEST_WARN_FALSE(...) ((void)0) -#define DOCTEST_CHECK_FALSE(...) ((void)0) -#define DOCTEST_REQUIRE_FALSE(...) ((void)0) +#define DOCTEST_WARN(...) (static_cast(0)) +#define DOCTEST_CHECK(...) (static_cast(0)) +#define DOCTEST_REQUIRE(...) (static_cast(0)) +#define DOCTEST_WARN_FALSE(...) (static_cast(0)) +#define DOCTEST_CHECK_FALSE(...) (static_cast(0)) +#define DOCTEST_REQUIRE_FALSE(...) (static_cast(0)) -#define DOCTEST_WARN_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_CHECK_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_REQUIRE_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) ((void)0) -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) ((void)0) +#define DOCTEST_WARN_MESSAGE(cond, msg) (static_cast(0)) +#define DOCTEST_CHECK_MESSAGE(cond, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_MESSAGE(cond, msg) (static_cast(0)) +#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) (static_cast(0)) +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) (static_cast(0)) -#define DOCTEST_WARN_THROWS(expr) ((void)0) -#define DOCTEST_CHECK_THROWS(expr) ((void)0) -#define DOCTEST_REQUIRE_THROWS(expr) ((void)0) -#define DOCTEST_WARN_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0) -#define DOCTEST_WARN_NOTHROW(expr) ((void)0) -#define DOCTEST_CHECK_NOTHROW(expr) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) +#define DOCTEST_WARN_THROWS(...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS(...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS(...) (static_cast(0)) +#define DOCTEST_WARN_THROWS_AS(expr, ...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH(expr, ...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) (static_cast(0)) +#define DOCTEST_WARN_NOTHROW(...) (static_cast(0)) +#define DOCTEST_CHECK_NOTHROW(...) (static_cast(0)) +#define DOCTEST_REQUIRE_NOTHROW(...) (static_cast(0)) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast(0)) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast(0)) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast(0)) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) (static_cast(0)) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) (static_cast(0)) -#define DOCTEST_WARN_EQ(...) ((void)0) -#define DOCTEST_CHECK_EQ(...) ((void)0) -#define DOCTEST_REQUIRE_EQ(...) ((void)0) -#define DOCTEST_WARN_NE(...) ((void)0) -#define DOCTEST_CHECK_NE(...) ((void)0) -#define DOCTEST_REQUIRE_NE(...) ((void)0) -#define DOCTEST_WARN_GT(...) ((void)0) -#define DOCTEST_CHECK_GT(...) ((void)0) -#define DOCTEST_REQUIRE_GT(...) ((void)0) -#define DOCTEST_WARN_LT(...) ((void)0) -#define DOCTEST_CHECK_LT(...) ((void)0) -#define DOCTEST_REQUIRE_LT(...) ((void)0) -#define DOCTEST_WARN_GE(...) ((void)0) -#define DOCTEST_CHECK_GE(...) ((void)0) -#define DOCTEST_REQUIRE_GE(...) ((void)0) -#define DOCTEST_WARN_LE(...) ((void)0) -#define DOCTEST_CHECK_LE(...) ((void)0) -#define DOCTEST_REQUIRE_LE(...) ((void)0) +#define DOCTEST_WARN_EQ(...) (static_cast(0)) +#define DOCTEST_CHECK_EQ(...) (static_cast(0)) +#define DOCTEST_REQUIRE_EQ(...) (static_cast(0)) +#define DOCTEST_WARN_NE(...) (static_cast(0)) +#define DOCTEST_CHECK_NE(...) (static_cast(0)) +#define DOCTEST_REQUIRE_NE(...) (static_cast(0)) +#define DOCTEST_WARN_GT(...) (static_cast(0)) +#define DOCTEST_CHECK_GT(...) (static_cast(0)) +#define DOCTEST_REQUIRE_GT(...) (static_cast(0)) +#define DOCTEST_WARN_LT(...) (static_cast(0)) +#define DOCTEST_CHECK_LT(...) (static_cast(0)) +#define DOCTEST_REQUIRE_LT(...) (static_cast(0)) +#define DOCTEST_WARN_GE(...) (static_cast(0)) +#define DOCTEST_CHECK_GE(...) (static_cast(0)) +#define DOCTEST_REQUIRE_GE(...) (static_cast(0)) +#define DOCTEST_WARN_LE(...) (static_cast(0)) +#define DOCTEST_CHECK_LE(...) (static_cast(0)) +#define DOCTEST_REQUIRE_LE(...) (static_cast(0)) -#define DOCTEST_WARN_UNARY(...) ((void)0) -#define DOCTEST_CHECK_UNARY(...) ((void)0) -#define DOCTEST_REQUIRE_UNARY(...) ((void)0) -#define DOCTEST_WARN_UNARY_FALSE(...) ((void)0) -#define DOCTEST_CHECK_UNARY_FALSE(...) ((void)0) -#define DOCTEST_REQUIRE_UNARY_FALSE(...) ((void)0) +#define DOCTEST_WARN_UNARY(...) (static_cast(0)) +#define DOCTEST_CHECK_UNARY(...) (static_cast(0)) +#define DOCTEST_REQUIRE_UNARY(...) (static_cast(0)) +#define DOCTEST_WARN_UNARY_FALSE(...) (static_cast(0)) +#define DOCTEST_CHECK_UNARY_FALSE(...) (static_cast(0)) +#define DOCTEST_REQUIRE_UNARY_FALSE(...) (static_cast(0)) #endif // DOCTEST_CONFIG_DISABLE @@ -2751,7 +2781,11 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #ifdef __AFXDLL #include #else +#if defined(__MINGW32__) || defined(__MINGW64__) +#include +#else // MINGW #include +#endif // MINGW #endif #include @@ -2762,6 +2796,12 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #endif // DOCTEST_PLATFORM_WINDOWS +// this is a fix for https://github.com/onqtam/doctest/issues/348 +// https://mail.gnome.org/archives/xml/2012-January/msg00000.html +#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) +#define STDOUT_FILENO fileno(stdout) +#endif // HAVE_UNISTD_H + DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END // counts the number of elements in a C array @@ -2872,7 +2912,7 @@ namespace detail { namespace timer_large_integer { - + #if defined(DOCTEST_PLATFORM_WINDOWS) typedef ULONGLONG type; #else // DOCTEST_PLATFORM_WINDOWS @@ -2913,7 +2953,7 @@ typedef timer_large_integer::type ticks_t; //unsigned int getElapsedMilliseconds() const { // return static_cast(getElapsedMicroseconds() / 1000); //} - double getElapsedSeconds() const { return static_cast((getCurrentTicks() - m_ticks)) / 1000000.0; } + double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } private: ticks_t m_ticks = 0; @@ -3450,7 +3490,7 @@ namespace detail { } #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - [[noreturn]] void throwException() { + DOCTEST_NORETURN void throwException() { g_cs->shouldLogCurrentException = false; throw TestFailureException(); } // NOLINT(cert-err60-cpp) @@ -3464,8 +3504,8 @@ namespace { // matching of a string against a wildcard mask (case sensitivity configurable) taken from // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing int wildcmp(const char* str, const char* wild, bool caseSensitive) { - const char* cp = nullptr; - const char* mp = nullptr; + const char* cp = str; + const char* mp = wild; while((*str) && (*wild != '*')) { if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && @@ -3554,6 +3594,10 @@ namespace detail { DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + Subcase::~Subcase() { if(m_entered) { // only mark the subcase stack as passed if no subcases have been skipped @@ -3561,7 +3605,7 @@ namespace detail { g_cs->subcasesPassed.insert(g_cs->subcasesStack); g_cs->subcasesStack.pop_back(); -#if __cplusplus >= 201703L && defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411 +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L if(std::uncaught_exceptions() > 0 #else if(std::uncaught_exception() @@ -3578,6 +3622,10 @@ namespace detail { } } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + Subcase::operator bool() const { return m_entered; } Result::Result(bool passed, const String& decomposition) @@ -3652,7 +3700,7 @@ namespace detail { bool TestCase::operator<(const TestCase& other) const { if(m_line != other.m_line) return m_line < other.m_line; - const int file_cmp = std::strcmp(m_file, other.m_file); + const int file_cmp = m_file.compare(other.m_file); if(file_cmp != 0) return file_cmp < 0; return m_template_id < other.m_template_id; @@ -3662,13 +3710,9 @@ namespace { using namespace detail; // for sorting tests by file/line bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { -#if DOCTEST_MSVC // this is needed because MSVC gives different case for drive letters // for __FILE__ when evaluated in a header and a source file - const int res = doctest::stricmp(lhs->m_file, rhs->m_file); -#else // MSVC - const int res = std::strcmp(lhs->m_file, rhs->m_file); -#endif // MSVC + const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); if(res != 0) return res < 0; if(lhs->m_line != rhs->m_line) @@ -3723,8 +3767,8 @@ namespace { DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") void color_to_stream(std::ostream& s, Color::Enum code) { - ((void)s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS - ((void)code); // for DOCTEST_CONFIG_COLORS_NONE + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE #ifdef DOCTEST_CONFIG_COLORS_ANSI if(g_no_colors || (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) @@ -3830,7 +3874,28 @@ namespace detail { #ifdef DOCTEST_IS_DEBUGGER_ACTIVE bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } #else // DOCTEST_IS_DEBUGGER_ACTIVE -#ifdef DOCTEST_PLATFORM_MAC +#ifdef DOCTEST_PLATFORM_LINUX + class ErrnoGuard { + public: + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + // See the comments in Catch2 for the reasoning behind this implementation: + // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 + bool isDebuggerActive() { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for(std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; + } +#elif defined(DOCTEST_PLATFORM_MAC) // The following function is taken directly from the following technical note: // https://developer.apple.com/library/archive/qa/qa1361/_index.html // Returns true if the current process is being debugged (either @@ -3857,7 +3922,7 @@ namespace detail { // We're being debugged if the P_TRACED flag is set. return ((info.kp_proc.p_flag & P_TRACED) != 0); } -#elif DOCTEST_MSVC || defined(__MINGW32__) +#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } #else bool isDebuggerActive() { return false; } @@ -3897,11 +3962,15 @@ namespace detail { g_infoContexts.push_back(this); } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + // destroy cannot be inlined into the destructor because that would mean calling stringify after // 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 __cplusplus >= 201703L && defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411 +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L if(std::uncaught_exceptions() > 0) { #else if(std::uncaught_exception()) { @@ -3913,19 +3982,13 @@ namespace detail { g_infoContexts.pop_back(); } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP } // namespace detail namespace { using namespace detail; - std::ostream& file_line_to_stream(std::ostream& s, const char* file, int line, - const char* tail = "") { - const auto opt = getContextOptions(); - s << Color::LightGrey << skipPathFromFilename(file) << (opt->gnu_file_line ? ":" : "(") - << (opt->no_line_numbers ? 0 : line) // 0 or the real num depending on the option - << (opt->gnu_file_line ? ":" : "):") << tail; - return s; - } - #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) struct FatalConditionHandler { @@ -4232,7 +4295,7 @@ namespace { using namespace detail; template - [[noreturn]] void throw_exception(Ex const& e) { + DOCTEST_NORETURN void throw_exception(Ex const& e) { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS throw e; #else // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -4242,9 +4305,11 @@ namespace { #endif // DOCTEST_CONFIG_NO_EXCEPTIONS } +#ifndef DOCTEST_INTERNAL_ERROR #define DOCTEST_INTERNAL_ERROR(msg) \ throw_exception(std::logic_error( \ __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) +#endif // DOCTEST_INTERNAL_ERROR // clang-format off @@ -4275,8 +4340,8 @@ namespace { public: ScopedElement( XmlWriter* writer ); - ScopedElement( ScopedElement&& other ) noexcept; - ScopedElement& operator=( ScopedElement&& other ) noexcept; + ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT; + ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT; ~ScopedElement(); @@ -4493,11 +4558,11 @@ namespace { : m_writer( writer ) {} - XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT : m_writer( other.m_writer ){ other.m_writer = nullptr; } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT { if ( m_writer ) { m_writer->endElement(); } @@ -4676,7 +4741,7 @@ namespace { tc = ∈ xml.startElement("TestCase") .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file)) + .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) .writeAttribute("line", line(in.m_line)) .writeAttribute("description", in.m_description); @@ -4707,7 +4772,7 @@ namespace { for(unsigned i = 0; i < in.num_data; ++i) { xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) .writeAttribute("testsuite", in.data[i]->m_test_suite) - .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file)) + .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) .writeAttribute("line", line(in.data[i]->m_line)); } xml.scopedElement("OverallResultsTestCases") @@ -4863,6 +4928,263 @@ namespace { DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); + void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { + if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == + 0) //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " + << Color::None; + + if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } else if((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //!OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None; + if(rb.m_threw) { + if(!rb.m_failed) { + s << "threw as expected!\n"; + } else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } + } else { + s << "did NOT throw at all!\n"; + } + } else if(rb.m_at & + assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " + << rb.m_exception_type << " ) " << Color::None + << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } else if(rb.m_at & + assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string << "\" ) " << Color::None + << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan + << rb.m_exception << "\n"; + } else { + s << (rb.m_threw ? "THREW exception: " : + (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); + if(rb.m_threw) + s << rb.m_exception << "\n"; + else + s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + } + } + + // TODO: + // - log_contexts() + // - log_message() + // - respond to queries + // - honor remaining options + // - more attributes in tags + struct JUnitReporter : public IReporter + { + XmlWriter xml; + std::mutex mutex; + Timer timer; + std::vector deepestSubcaseStackNames; + + struct JUnitTestCaseData + { +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime + static std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + + std::tm* timeInfo; + timeInfo = std::gmtime(&rawtime); + + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; + + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); + return std::string(timeStamp); + } +DOCTEST_CLANG_SUPPRESS_WARNING_POP + + struct JUnitTestMessage + { + JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) + : message(_message), type(_type), details(_details) {} + + JUnitTestMessage(const std::string& _message, const std::string& _details) + : message(_message), type(), details(_details) {} + + std::string message, type, details; + }; + + struct JUnitTestCase + { + JUnitTestCase(const std::string& _classname, const std::string& _name) + : classname(_classname), name(_name), time(0), failures() {} + + std::string classname, name; + double time; + std::vector failures, errors; + }; + + void add(const std::string& classname, const std::string& name) { + testcases.emplace_back(classname, name); + } + + void appendSubcaseNamesToLastTestcase(std::vector nameStack) { + for(auto& curr: nameStack) + if(curr.size()) + testcases.back().name += std::string("/") + curr.c_str(); + } + + void addTime(double time) { + if(time < 1e-4) + time = 0; + testcases.back().time = time; + totalSeconds += time; + } + + void addFailure(const std::string& message, const std::string& type, const std::string& details) { + testcases.back().failures.emplace_back(message, type, details); + ++totalFailures; + } + + void addError(const std::string& message, const std::string& details) { + testcases.back().errors.emplace_back(message, details); + ++totalErrors; + } + + std::vector testcases; + double totalSeconds = 0; + int totalErrors = 0, totalFailures = 0; + }; + + JUnitTestCaseData testCaseData; + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + JUnitReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData&) override {} + + void test_run_start() override {} + + void test_run_end(const TestRunStats& p) override { + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if(binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + xml.startElement("testsuites"); + xml.startElement("testsuite").writeAttribute("name", binary_name) + .writeAttribute("errors", testCaseData.totalErrors) + .writeAttribute("failures", testCaseData.totalFailures) + .writeAttribute("tests", p.numAsserts); + if(opt.no_time_in_output == false) { + xml.writeAttribute("time", testCaseData.totalSeconds); + xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); + } + if(opt.no_version == false) + xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); + + for(const auto& testCase : testCaseData.testcases) { + xml.startElement("testcase") + .writeAttribute("classname", testCase.classname) + .writeAttribute("name", testCase.name); + if(opt.no_time_in_output == false) + xml.writeAttribute("time", testCase.time); + // This is not ideal, but it should be enough to mimic gtest's junit output. + xml.writeAttribute("status", "run"); + + for(const auto& failure : testCase.failures) { + xml.scopedElement("failure") + .writeAttribute("message", failure.message) + .writeAttribute("type", failure.type) + .writeText(failure.details, false); + } + + for(const auto& error : testCase.errors) { + xml.scopedElement("error") + .writeAttribute("message", error.message) + .writeText(error.details); + } + + xml.endElement(); + } + xml.endElement(); + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + timer.start(); + } + + void test_case_reenter(const TestCaseData& in) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + + timer.start(); + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + } + + void test_case_end(const CurrentTestCaseStats&) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + } + + void test_case_exception(const TestCaseException& e) override { + std::lock_guard lock(mutex); + testCaseData.addError("exception", e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + std::lock_guard lock(mutex); + deepestSubcaseStackNames.push_back(in.m_name); + } + + void subcase_end() override {} + + void log_assert(const AssertData& rb) override { + if(!rb.m_failed) // report only failures & ignore the `success` option + return; + + std::lock_guard lock(mutex); + + std::ostringstream os; + os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + fulltext_log_assert_to_stream(os, rb); + testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + } + + void log_message(const MessageData&) override {} + + void test_case_skipped(const TestCaseData&) override {} + }; + + DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); + struct Whitespace { int nrSpaces; @@ -4881,6 +5203,7 @@ namespace { std::ostream& s; bool hasLoggedCurrentTestStart; std::vector subcasesStack; + size_t currentSubcaseLevel; std::mutex mutex; // caching pointers/references to objects of these types - safe to do @@ -4939,23 +5262,40 @@ namespace { s << "\n"; } + // this was requested to be made virtual so users could override it + virtual void file_line_to_stream(const char* file, int line, + const char* tail = "") { + s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") + << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option + << (opt.gnu_file_line ? ":" : "):") << tail; + } + void logTestStart() { if(hasLoggedCurrentTestStart) return; separator_to_stream(); - file_line_to_stream(s, tc->m_file, tc->m_line, "\n"); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); if(tc->m_description) s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; if(tc->m_test_suite && tc->m_test_suite[0] != '\0') s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; if(strncmp(tc->m_name, " Scenario:", 11) != 0) - s << Color::None << "TEST CASE: "; + s << Color::Yellow << "TEST CASE: "; s << Color::None << tc->m_name << "\n"; - for(auto& curr : subcasesStack) - if(curr.m_name[0] != '\0') - s << " " << curr.m_name << "\n"; + for(size_t i = 0; i < currentSubcaseLevel; ++i) { + if(subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + + if(currentSubcaseLevel != subcasesStack.size()) { + s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; + for(size_t i = 0; i < subcasesStack.size(); ++i) { + if(subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + } s << "\n"; @@ -5166,25 +5506,28 @@ namespace { separator_to_stream(); s << std::dec; + auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); + auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); + auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; - s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(6) + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) << p.numTestCasesPassingFilters << " | " << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(6) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) - << std::setw(6) << p.numTestCasesFailed << " failed" << Color::None << " | "; + << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; if(opt.no_skipped_summary == false) { const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; - s << (numSkipped == 0 ? Color::None : Color::Yellow) << std::setw(6) << numSkipped + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped << " skipped" << Color::None; } s << "\n"; - s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(6) + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) << p.numAsserts << " | " << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(6) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None - << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(6) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) << p.numAssertsFailed << " failed" << Color::None << " |\n"; s << Color::Cyan << "[doctest] " << Color::None << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) @@ -5194,9 +5537,13 @@ namespace { void test_case_start(const TestCaseData& in) override { hasLoggedCurrentTestStart = false; tc = ∈ + subcasesStack.clear(); + currentSubcaseLevel = 0; } - void test_case_reenter(const TestCaseData&) override {} + void test_case_reenter(const TestCaseData&) override { + subcasesStack.clear(); + } void test_case_end(const CurrentTestCaseStats& st) override { // log the preamble of the test case only if there is something @@ -5235,7 +5582,7 @@ namespace { void test_case_exception(const TestCaseException& e) override { logTestStart(); - file_line_to_stream(s, tc->m_file, tc->m_line, " "); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : assertType::is_check); s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") @@ -5256,12 +5603,13 @@ namespace { void subcase_start(const SubcaseSignature& subc) override { std::lock_guard lock(mutex); subcasesStack.push_back(subc); + ++currentSubcaseLevel; hasLoggedCurrentTestStart = false; } void subcase_end() override { std::lock_guard lock(mutex); - subcasesStack.pop_back(); + --currentSubcaseLevel; hasLoggedCurrentTestStart = false; } @@ -5273,55 +5621,10 @@ namespace { logTestStart(); - file_line_to_stream(s, rb.m_file, rb.m_line, " "); + file_line_to_stream(rb.m_file, rb.m_line, " "); successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); - if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == - 0) //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " - << Color::None; - if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; - } else if((rb.m_at & assertType::is_throws_as) && - (rb.m_at & assertType::is_throws_with)) { //!OCLINT - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None; - if(rb.m_threw) { - if(!rb.m_failed) { - s << "threw as expected!\n"; - } else { - s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; - } - } else { - s << "did NOT throw at all!\n"; - } - } else if(rb.m_at & - assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " - << rb.m_exception_type << " ) " << Color::None - << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & - assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string << "\" ) " << Color::None - << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan - << rb.m_exception << "\n"; - } else { - s << (rb.m_threw ? "THREW exception: " : - (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); - if(rb.m_threw) - s << rb.m_exception << "\n"; - else - s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; - } + fulltext_log_assert_to_stream(s, rb); log_contexts(); } @@ -5331,7 +5634,7 @@ namespace { logTestStart(); - file_line_to_stream(s, mb.m_file, mb.m_line, " "); + file_line_to_stream(mb.m_file, mb.m_line, " "); s << getSuccessOrFailColor(false, mb.m_severity) << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, "MESSAGE") << ": "; @@ -5592,6 +5895,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); // clang-format on if(withDefaults) { @@ -5778,9 +6082,9 @@ int Context::run() { if(tc.m_skip && !p->no_skip) skip_me = true; - if(!matchesAny(tc.m_file, p->filters[0], true, p->case_sensitive)) + if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) skip_me = true; - if(matchesAny(tc.m_file, p->filters[1], false, p->case_sensitive)) + if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) skip_me = true; if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) skip_me = true; @@ -5953,4 +6257,4 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP #endif // DOCTEST_LIBRARY_IMPLEMENTATION -#endif // DOCTEST_CONFIG_IMPLEMENT +#endif // DOCTEST_CONFIG_IMPLEMENT \ No newline at end of file