diff --git a/doc/markdown/assertions.md b/doc/markdown/assertions.md index 02567be4f..a9df63ae8 100644 --- a/doc/markdown/assertions.md +++ b/doc/markdown/assertions.md @@ -123,19 +123,6 @@ Note that these asserts also have a ```_MESSAGE``` form - like ```CHECK_THROWS_M One may use the [**```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**](configuration.md#doctest_config_void_cast_expressions) config identifier to cast the expression in these asserts to void to avoid warnings or other issues - for example nodiscard statements whose result isn't checked. This will however limit the ability to write entire ```{}``` blocks of code as the expression (or multiple statements) but in that case a simple lambda can be used. This should have been the default behavior from day 1 of the framework... -## NaN checking - -`````` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```. - -- ```_NAN(expression)``` -- ```_NOT_NAN(expression)``` - -These utility macros check if a floating point value is or is not NaN respectively. - -They capture the actual float value on assertion failure. - -These macros are unaffected by `DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED`. - ## Using asserts out of a testing context Asserts can be used outside of a testing context (in code not called from a ```TEST_CASE()```) instead of [```assert()```](https://en.cppreference.com/w/cpp/error/assert). @@ -182,6 +169,18 @@ REQUIRE(22.0/7 == doctest::Approx(3.141).epsilon(0.01)); // allow for a 1% error When dealing with very large or very small numbers it can be useful to specify a scale, which can be achieved by calling the ```scale()``` method on the ```doctest::Approx``` instance. +## NaN checking + +Two NaN floating point numbers do not compare equal to each other. This makes it quite inconvenient to check for NaN while capturing the value. +```c++ +CHECK(std::isnan(performComputation()); // does not capture the result of the call +``` + +**doctest** provides `doctest::IsNaN` which can be used in assertions to check if a float (or any other floating point fundamental type) is indeed NaN, outputting the actual value if it is not. +```c++ +CHECK(doctest::IsNaN(performComputation()); // captures the result! +``` + -------- - Check out the [**example**](../../examples/all_features/assertion_macros.cpp) which shows many of these macros diff --git a/doctest/doctest.h b/doctest/doctest.h index f5fc12486..942f4af76 100644 --- a/doctest/doctest.h +++ b/doctest/doctest.h @@ -317,6 +317,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_INTERFACE #endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +// needed for extern template instantiations +// see https://github.com/fmtlib/fmt/issues/2228 +#if DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL +#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE +#else // DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE +#define DOCTEST_INTERFACE_DEF +#endif // DOCTEST_MSVC + #define DOCTEST_EMPTY #if DOCTEST_MSVC @@ -445,7 +455,6 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#include #include #include #include @@ -633,8 +642,6 @@ namespace assertType { is_ge = 2 * is_gt, is_le = 2 * is_ge, - is_nan = 2 * is_le, - // macro types DT_WARN = is_normal | is_warn, @@ -696,14 +703,6 @@ namespace assertType { DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, - - DT_WARN_NAN = is_normal | is_nan | is_warn, - DT_CHECK_NAN = is_normal | is_nan | is_check, - DT_REQUIRE_NAN = is_normal | is_nan | is_require, - - DT_WARN_NOT_NAN = is_normal | is_nan | is_false | is_warn, - DT_CHECK_NOT_NAN = is_normal | is_nan | is_false | is_check, - DT_REQUIRE_NOT_NAN = is_normal | is_nan | is_false | is_require, }; } // namespace assertType @@ -1134,6 +1133,22 @@ DOCTEST_INTERFACE String toString(const Approx& in); DOCTEST_INTERFACE const ContextOptions* getContextOptions(); +template +struct DOCTEST_INTERFACE_DECL IsNaN +{ + F val; + IsNaN(F f) : val(f) { } + operator bool() const; +}; +#ifndef __MINGW32__ +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +#endif +DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& out, IsNaN nanCheck); +DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& out, IsNaN nanCheck); +DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& out, IsNaN nanCheck); + #ifndef DOCTEST_CONFIG_DISABLE namespace detail { @@ -1501,12 +1516,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) - template - bool is_nan(T); - extern template bool is_nan(float); - extern template bool is_nan(double); - extern template bool is_nan(long double); - struct DOCTEST_INTERFACE ResultBuilder : public AssertData { ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, @@ -1536,19 +1545,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP return !m_failed; } - template - DOCTEST_NOINLINE bool nan_assert(L val) { - m_failed = !is_nan(val); - - if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional - m_failed = !m_failed; - - if(m_failed || getContextOptions()->success) - m_decomp = toString(val); - - return !m_failed; - } - void translateException(); bool log(); @@ -1628,23 +1624,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP return !failed; } - template - DOCTEST_NOINLINE bool nan_assert(assertType::Enum at, const char* file, int line, - const char* expr, L val) { - bool failed = !is_nan(val); - - if (at & assertType::is_false) //!OCLINT bitwise operator in conditional - failed = !failed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(toString(val)); - DOCTEST_ASSERT_IN_TESTS(toString(val)); - return !failed; - } - struct DOCTEST_INTERFACE IExceptionTranslator { IExceptionTranslator(); @@ -2430,32 +2409,6 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) -#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_NAN_ASSERT(assert_type, ...) \ - [&] { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY( \ - DOCTEST_RB.nan_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - }() - -#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_NAN_ASSERT(assert_type, ...) \ - doctest::detail::nan_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ - #__VA_ARGS__, __VA_ARGS__) - -#endif - -#define DOCTEST_WARN_NAN(...) DOCTEST_NAN_ASSERT(DT_WARN_NAN, __VA_ARGS__) -#define DOCTEST_CHECK_NAN(...) DOCTEST_NAN_ASSERT(DT_CHECK_NAN, __VA_ARGS__) -#define DOCTEST_REQUIRE_NAN(...) DOCTEST_NAN_ASSERT(DT_REQUIRE_NAN, __VA_ARGS__) -#define DOCTEST_WARN_NOT_NAN(...) DOCTEST_NAN_ASSERT(DT_WARN_NOT_NAN, __VA_ARGS__) -#define DOCTEST_CHECK_NOT_NAN(...) DOCTEST_NAN_ASSERT(DT_CHECK_NOT_NAN, __VA_ARGS__) -#define DOCTEST_REQUIRE_NOT_NAN(...) DOCTEST_NAN_ASSERT(DT_REQUIRE_NOT_NAN, __VA_ARGS__) - #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS #undef DOCTEST_WARN_THROWS @@ -2759,13 +2712,6 @@ namespace detail { #endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED -#define DOCTEST_WARN_NAN(...) [] { return false; }() -#define DOCTEST_CHECK_NAN(...) [] { return false; }() -#define DOCTEST_REQUIRE_NAN(...) [] { return false; }() -#define DOCTEST_WARN_NOT_NAN(...) [] { return false; }() -#define DOCTEST_CHECK_NOT_NAN(...) [] { return false; }() -#define DOCTEST_REQUIRE_NOT_NAN(...) [] { return false; }() - #define DOCTEST_WARN_THROWS_WITH(expr, ...) [] { return false; }() #define DOCTEST_CHECK_THROWS_WITH(expr, ...) [] { return false; }() #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) [] { return false; }() @@ -2934,13 +2880,6 @@ namespace detail { #define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) #define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) -#define WARN_NAN(...) DOCTEST_WARN_NAN(__VA_ARGS__) -#define CHECK_NAN(...) DOCTEST_CHECK_NAN(__VA_ARGS__) -#define REQUIRE_NAN(...) DOCTEST_REQUIRE_NAN(__VA_ARGS__) -#define WARN_NOT_NAN(...) DOCTEST_WARN_NOT_NAN(__VA_ARGS__) -#define CHECK_NOT_NAN(...) DOCTEST_CHECK_NOT_NAN(__VA_ARGS__) -#define REQUIRE_NOT_NAN(...) DOCTEST_REQUIRE_NOT_NAN(__VA_ARGS__) - // KEPT FOR BACKWARDS COMPATIBILITY #define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) #define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) @@ -3745,9 +3684,6 @@ const char* assertString(assertType::Enum at) { DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NAN); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOT_NAN); - default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); } DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -3875,6 +3811,22 @@ String toString(const Approx& in) { } const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) +template +IsNaN::operator bool() const { + return std::isnan(val); +} +DOCTEST_MSVC_SUPPRESS_WARNING_POP +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +std::ostream& operator<<(std::ostream& out, IsNaN nanCheck) + { out << nanCheck.val; return out; } +std::ostream& operator<<(std::ostream& out, IsNaN nanCheck) + { out << nanCheck.val; return out; } +std::ostream& operator<<(std::ostream& out, IsNaN nanCheck) + { out << nanCheck.val; return out; } + } // namespace doctest #ifdef DOCTEST_CONFIG_DISABLE @@ -4739,17 +4691,6 @@ namespace { #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH } // namespace namespace detail { - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) - template - bool is_nan(T t) { - return std::isnan(t); - } - DOCTEST_MSVC_SUPPRESS_WARNING_POP - template bool is_nan(float); - template bool is_nan(double); - template bool is_nan(long double); - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, const char* exception_type, const char* exception_string) { m_test_case = g_cs->currentTest; diff --git a/doctest/parts/doctest.cpp b/doctest/parts/doctest.cpp index 701654b95..30ac73b45 100644 --- a/doctest/parts/doctest.cpp +++ b/doctest/parts/doctest.cpp @@ -730,9 +730,6 @@ const char* assertString(assertType::Enum at) { DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NAN); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOT_NAN); - default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); } DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -860,6 +857,22 @@ String toString(const Approx& in) { } const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) +template +IsNaN::operator bool() const { + return std::isnan(val); +} +DOCTEST_MSVC_SUPPRESS_WARNING_POP +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +std::ostream& operator<<(std::ostream& out, IsNaN nanCheck) + { out << nanCheck.val; return out; } +std::ostream& operator<<(std::ostream& out, IsNaN nanCheck) + { out << nanCheck.val; return out; } +std::ostream& operator<<(std::ostream& out, IsNaN nanCheck) + { out << nanCheck.val; return out; } + } // namespace doctest #ifdef DOCTEST_CONFIG_DISABLE @@ -1724,17 +1737,6 @@ namespace { #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH } // namespace namespace detail { - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) - template - bool is_nan(T t) { - return std::isnan(t); - } - DOCTEST_MSVC_SUPPRESS_WARNING_POP - template bool is_nan(float); - template bool is_nan(double); - template bool is_nan(long double); - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, const char* exception_type, const char* exception_string) { m_test_case = g_cs->currentTest; diff --git a/doctest/parts/doctest_fwd.h b/doctest/parts/doctest_fwd.h index 12a1aebf5..92ba9574b 100644 --- a/doctest/parts/doctest_fwd.h +++ b/doctest/parts/doctest_fwd.h @@ -314,6 +314,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_INTERFACE #endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +// needed for extern template instantiations +// see https://github.com/fmtlib/fmt/issues/2228 +#if DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL +#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE +#else // DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE +#define DOCTEST_INTERFACE_DEF +#endif // DOCTEST_MSVC + #define DOCTEST_EMPTY #if DOCTEST_MSVC @@ -442,7 +452,6 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#include #include #include #include @@ -630,8 +639,6 @@ namespace assertType { is_ge = 2 * is_gt, is_le = 2 * is_ge, - is_nan = 2 * is_le, - // macro types DT_WARN = is_normal | is_warn, @@ -693,14 +700,6 @@ namespace assertType { DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, - - DT_WARN_NAN = is_normal | is_nan | is_warn, - DT_CHECK_NAN = is_normal | is_nan | is_check, - DT_REQUIRE_NAN = is_normal | is_nan | is_require, - - DT_WARN_NOT_NAN = is_normal | is_nan | is_false | is_warn, - DT_CHECK_NOT_NAN = is_normal | is_nan | is_false | is_check, - DT_REQUIRE_NOT_NAN = is_normal | is_nan | is_false | is_require, }; } // namespace assertType @@ -1131,6 +1130,22 @@ DOCTEST_INTERFACE String toString(const Approx& in); DOCTEST_INTERFACE const ContextOptions* getContextOptions(); +template +struct DOCTEST_INTERFACE_DECL IsNaN +{ + F val; + IsNaN(F f) : val(f) { } + operator bool() const; +}; +#ifndef __MINGW32__ +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +#endif +DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& out, IsNaN nanCheck); +DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& out, IsNaN nanCheck); +DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& out, IsNaN nanCheck); + #ifndef DOCTEST_CONFIG_DISABLE namespace detail { @@ -1498,12 +1513,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) - template - bool is_nan(T); - extern template bool is_nan(float); - extern template bool is_nan(double); - extern template bool is_nan(long double); - struct DOCTEST_INTERFACE ResultBuilder : public AssertData { ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, @@ -1533,19 +1542,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP return !m_failed; } - template - DOCTEST_NOINLINE bool nan_assert(L val) { - m_failed = !is_nan(val); - - if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional - m_failed = !m_failed; - - if(m_failed || getContextOptions()->success) - m_decomp = toString(val); - - return !m_failed; - } - void translateException(); bool log(); @@ -1625,23 +1621,6 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP return !failed; } - template - DOCTEST_NOINLINE bool nan_assert(assertType::Enum at, const char* file, int line, - const char* expr, L val) { - bool failed = !is_nan(val); - - if (at & assertType::is_false) //!OCLINT bitwise operator in conditional - failed = !failed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(toString(val)); - DOCTEST_ASSERT_IN_TESTS(toString(val)); - return !failed; - } - struct DOCTEST_INTERFACE IExceptionTranslator { IExceptionTranslator(); @@ -2427,32 +2406,6 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) -#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_NAN_ASSERT(assert_type, ...) \ - [&] { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY( \ - DOCTEST_RB.nan_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - }() - -#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_NAN_ASSERT(assert_type, ...) \ - doctest::detail::nan_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ - #__VA_ARGS__, __VA_ARGS__) - -#endif - -#define DOCTEST_WARN_NAN(...) DOCTEST_NAN_ASSERT(DT_WARN_NAN, __VA_ARGS__) -#define DOCTEST_CHECK_NAN(...) DOCTEST_NAN_ASSERT(DT_CHECK_NAN, __VA_ARGS__) -#define DOCTEST_REQUIRE_NAN(...) DOCTEST_NAN_ASSERT(DT_REQUIRE_NAN, __VA_ARGS__) -#define DOCTEST_WARN_NOT_NAN(...) DOCTEST_NAN_ASSERT(DT_WARN_NOT_NAN, __VA_ARGS__) -#define DOCTEST_CHECK_NOT_NAN(...) DOCTEST_NAN_ASSERT(DT_CHECK_NOT_NAN, __VA_ARGS__) -#define DOCTEST_REQUIRE_NOT_NAN(...) DOCTEST_NAN_ASSERT(DT_REQUIRE_NOT_NAN, __VA_ARGS__) - #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS #undef DOCTEST_WARN_THROWS @@ -2756,13 +2709,6 @@ namespace detail { #endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED -#define DOCTEST_WARN_NAN(...) [] { return false; }() -#define DOCTEST_CHECK_NAN(...) [] { return false; }() -#define DOCTEST_REQUIRE_NAN(...) [] { return false; }() -#define DOCTEST_WARN_NOT_NAN(...) [] { return false; }() -#define DOCTEST_CHECK_NOT_NAN(...) [] { return false; }() -#define DOCTEST_REQUIRE_NOT_NAN(...) [] { return false; }() - #define DOCTEST_WARN_THROWS_WITH(expr, ...) [] { return false; }() #define DOCTEST_CHECK_THROWS_WITH(expr, ...) [] { return false; }() #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) [] { return false; }() @@ -2931,13 +2877,6 @@ namespace detail { #define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) #define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) -#define WARN_NAN(...) DOCTEST_WARN_NAN(__VA_ARGS__) -#define CHECK_NAN(...) DOCTEST_CHECK_NAN(__VA_ARGS__) -#define REQUIRE_NAN(...) DOCTEST_REQUIRE_NAN(__VA_ARGS__) -#define WARN_NOT_NAN(...) DOCTEST_WARN_NOT_NAN(__VA_ARGS__) -#define CHECK_NOT_NAN(...) DOCTEST_CHECK_NOT_NAN(__VA_ARGS__) -#define REQUIRE_NOT_NAN(...) DOCTEST_REQUIRE_NOT_NAN(__VA_ARGS__) - // KEPT FOR BACKWARDS COMPATIBILITY #define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) #define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) diff --git a/examples/all_features/assert_returns_disabled.cpp b/examples/all_features/assert_returns_disabled.cpp index c181d1c80..d2774b4a2 100644 --- a/examples/all_features/assert_returns_disabled.cpp +++ b/examples/all_features/assert_returns_disabled.cpp @@ -1,7 +1,6 @@ #include #include -#include #ifndef TEST_FLIP @@ -24,8 +23,6 @@ static int test_disabled_var_ = [] { if (TEST_FLIP ^ CHECK_NOTHROW([]{ }())) { TEST_FAIL(); } if (CHECK_THROWS_WITH([] { throw 2; }(), "2")) { TEST_FAIL(); } #endif - if (CHECK_NAN(std::numeric_limits::quiet_NaN())) { TEST_FAIL(); } - if (CHECK_NOT_NAN(22.)) { TEST_FAIL(); } return 0; }(); diff --git a/examples/all_features/assertion_macros.cpp b/examples/all_features/assertion_macros.cpp index cd03dd15e..524751ca9 100644 --- a/examples/all_features/assertion_macros.cpp +++ b/examples/all_features/assertion_macros.cpp @@ -5,7 +5,6 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include #include -#include DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END TEST_CASE("normal macros") { @@ -210,8 +209,6 @@ TEST_CASE("check return values") { if (CHECK_THROWS_AS(throw_if(true, 2), int)) { MESSAGE(":D"); } if (CHECK_NOTHROW(throw_if(false, 2))) { MESSAGE(":D"); } if (CHECK_THROWS_WITH(throw_if(true, 2), "2")) { MESSAGE(":D"); } - if (CHECK_NAN(std::numeric_limits::quiet_NaN())) { MESSAGE(":D"); } - if (CHECK_NOT_NAN(22.)) { MESSAGE(":D"); } } TEST_CASE("check return values no print") { @@ -221,15 +218,5 @@ TEST_CASE("check return values no print") { if (CHECK_THROWS_AS(throw_if(true, 2), doctest::Approx)) { MESSAGE(":D"); } if (CHECK_NOTHROW(throw_if(true, 2))) { MESSAGE(":D"); } if (CHECK_THROWS_WITH(throw_if(true, 2), "1")) { MESSAGE(":D"); } - if (CHECK_NAN(0.)) { MESSAGE(":D"); } - // CHECK_NOT_NAN can't be checked because stringification is (partly) implementation defined } DOCTEST_MSVC_SUPPRESS_WARNING_POP - -TEST_CASE("nan") { - REQUIRE_NOT_NAN(0.f); - CHECK_NAN(std::numeric_limits::infinity()); - CHECK_NOT_NAN(0.); - WARN_NOT_NAN(std::numeric_limits::quiet_NaN()); - REQUIRE_NAN(std::numeric_limits::signaling_NaN()); -} diff --git a/examples/all_features/asserts_used_outside_of_tests.cpp b/examples/all_features/asserts_used_outside_of_tests.cpp index b42734813..289c26668 100644 --- a/examples/all_features/asserts_used_outside_of_tests.cpp +++ b/examples/all_features/asserts_used_outside_of_tests.cpp @@ -22,7 +22,6 @@ static void some_func() { CHECK(false); CHECK_THROWS(std::cout << "hello! \n"); - CHECK_NAN(0.); } // std::mutex g_mut; diff --git a/examples/all_features/stringification.cpp b/examples/all_features/stringification.cpp index 97e21e4fa..adca1e7f8 100644 --- a/examples/all_features/stringification.cpp +++ b/examples/all_features/stringification.cpp @@ -7,6 +7,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include #include #include +#include DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING(5045) // Spectre mitigation diagnostics @@ -146,6 +147,10 @@ TEST_CASE("all asserts should fail and show how the objects get stringified") { CHECK_MESSAGE(s1 == s2, s1, " is not really ", s2); } + CHECK(doctest::IsNaN(0.5)); + CHECK(doctest::IsNaN(std::numeric_limits::infinity())); + // can't test actual nan because it's implementation defined + // lets see if this exception gets translated throw_if(true, bla1); } diff --git a/examples/all_features/test_output/assertion_macros.cpp.txt b/examples/all_features/test_output/assertion_macros.cpp.txt index dbd831345..513939d42 100644 --- a/examples/all_features/test_output/assertion_macros.cpp.txt +++ b/examples/all_features/test_output/assertion_macros.cpp.txt @@ -219,10 +219,6 @@ assertion_macros.cpp(0): MESSAGE: :D assertion_macros.cpp(0): MESSAGE: :D -assertion_macros.cpp(0): MESSAGE: :D - -assertion_macros.cpp(0): MESSAGE: :D - =============================================================================== assertion_macros.cpp(0): TEST CASE: check return values no print @@ -250,21 +246,8 @@ assertion_macros.cpp(0): ERROR: CHECK_NOTHROW( throw_if(true, 2) ) THREW excepti assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH( throw_if(true, 2), "1" ) threw a DIFFERENT exception: "2" -assertion_macros.cpp(0): ERROR: CHECK_NAN( 0. ) is NOT correct! - values: CHECK_NAN( 0.0 ) - -=============================================================================== -assertion_macros.cpp(0): -TEST CASE: nan - -assertion_macros.cpp(0): ERROR: CHECK_NAN( std::numeric_limits::infinity() ) is NOT correct! - values: CHECK_NAN( inf ) - -assertion_macros.cpp(0): WARNING: WARN_NOT_NAN( std::numeric_limits::quiet_NaN() ) is NOT correct! - values: WARN_NOT_NAN( nanf ) - =============================================================================== -[doctest] test cases: 24 | 4 passed | 20 failed | -[doctest] assertions: 99 | 49 passed | 50 failed | +[doctest] test cases: 23 | 4 passed | 19 failed | +[doctest] assertions: 92 | 44 passed | 48 failed | [doctest] Status: FAILURE! Program code. diff --git a/examples/all_features/test_output/assertion_macros.cpp_junit.txt b/examples/all_features/test_output/assertion_macros.cpp_junit.txt index 966f923f7..bcc119c33 100644 --- a/examples/all_features/test_output/assertion_macros.cpp_junit.txt +++ b/examples/all_features/test_output/assertion_macros.cpp_junit.txt @@ -1,6 +1,6 @@ - + assertion_macros.cpp(0): @@ -368,26 +368,6 @@ CHECK_NOTHROW( throw_if(true, 2) ) THREW exception: "2" assertion_macros.cpp(0): CHECK_THROWS_WITH( throw_if(true, 2), "1" ) threw a DIFFERENT exception: "2" - - -assertion_macros.cpp(0): -CHECK_NAN( 0. ) is NOT correct! - values: CHECK_NAN( 0.0 ) - - - - - -assertion_macros.cpp(0): -CHECK_NAN( std::numeric_limits<long double>::infinity() ) is NOT correct! - values: CHECK_NAN( inf ) - - - -assertion_macros.cpp(0): -WARN_NOT_NAN( std::numeric_limits<float>::quiet_NaN() ) is NOT correct! - values: WARN_NOT_NAN( nanf ) - diff --git a/examples/all_features/test_output/assertion_macros.cpp_xml.txt b/examples/all_features/test_output/assertion_macros.cpp_xml.txt index c0bfcd98f..28e10330d 100644 --- a/examples/all_features/test_output/assertion_macros.cpp_xml.txt +++ b/examples/all_features/test_output/assertion_macros.cpp_xml.txt @@ -578,17 +578,7 @@ :D - - - :D - - - - - :D - - - + @@ -666,37 +656,10 @@ 1 - - - 0. - - - 0.0 - - - - - - - - std::numeric_limits<long double>::infinity() - - - inf - - - - - std::numeric_limits<float>::quiet_NaN() - - - nanf - - - + - - + + Program code. diff --git a/examples/all_features/test_output/asserts_used_outside_of_tests.cpp.txt b/examples/all_features/test_output/asserts_used_outside_of_tests.cpp.txt index f2d857716..9c0906069 100644 --- a/examples/all_features/test_output/asserts_used_outside_of_tests.cpp.txt +++ b/examples/all_features/test_output/asserts_used_outside_of_tests.cpp.txt @@ -14,5 +14,3 @@ asserts_used_outside_of_tests.cpp(23): ERROR: CHECK( false ) is NOT correct! values: CHECK( false ) hello! asserts_used_outside_of_tests.cpp(24): ERROR: an assert dealing with exceptions has failed! -asserts_used_outside_of_tests.cpp(25): ERROR: CHECK_NAN( 0. ) is NOT correct! - values: CHECK_NAN( 0.0 ) diff --git a/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_junit.txt b/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_junit.txt index 0b9472b0b..5727760ed 100644 --- a/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_junit.txt +++ b/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_junit.txt @@ -13,5 +13,3 @@ asserts_used_outside_of_tests.cpp(23): ERROR: CHECK( false ) is NOT correct! values: CHECK( false ) hello! asserts_used_outside_of_tests.cpp(24): ERROR: an assert dealing with exceptions has failed! -asserts_used_outside_of_tests.cpp(25): ERROR: CHECK_NAN( 0. ) is NOT correct! - values: CHECK_NAN( 0.0 ) diff --git a/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_xml.txt b/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_xml.txt index 935fda8b7..6490fb186 100644 --- a/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_xml.txt +++ b/examples/all_features/test_output/asserts_used_outside_of_tests.cpp_xml.txt @@ -15,5 +15,3 @@ asserts_used_outside_of_tests.cpp(23): ERROR: CHECK( false ) is NOT correct! values: CHECK( false ) hello! asserts_used_outside_of_tests.cpp(24): ERROR: an assert dealing with exceptions has failed! -asserts_used_outside_of_tests.cpp(25): ERROR: CHECK_NAN( 0. ) is NOT correct! - values: CHECK_NAN( 0.0 ) diff --git a/examples/all_features/test_output/filter_2.txt b/examples/all_features/test_output/filter_2.txt index 861827614..662a7e294 100644 --- a/examples/all_features/test_output/filter_2.txt +++ b/examples/all_features/test_output/filter_2.txt @@ -1,6 +1,6 @@ [doctest] run with "--help" for options =============================================================================== -[doctest] test cases: 0 | 0 passed | 0 failed | 97 skipped +[doctest] test cases: 0 | 0 passed | 0 failed | 96 skipped [doctest] assertions: 0 | 0 passed | 0 failed | [doctest] Status: SUCCESS! Program code. diff --git a/examples/all_features/test_output/filter_2_xml.txt b/examples/all_features/test_output/filter_2_xml.txt index bb6bd6531..8764a89dd 100644 --- a/examples/all_features/test_output/filter_2_xml.txt +++ b/examples/all_features/test_output/filter_2_xml.txt @@ -89,7 +89,6 @@ - @@ -137,6 +136,6 @@ - + Program code. diff --git a/examples/all_features/test_output/stringification.cpp.txt b/examples/all_features/test_output/stringification.cpp.txt index bdc5c5a84..234e806a7 100644 --- a/examples/all_features/test_output/stringification.cpp.txt +++ b/examples/all_features/test_output/stringification.cpp.txt @@ -27,6 +27,12 @@ stringification.cpp(0): ERROR: CHECK( s1 == s2 ) is NOT correct! logged: s1=MyOtherType: 42 s2=MyOtherType: 666 MyOtherType: 42 is not really MyOtherType: 666 +stringification.cpp(0): ERROR: CHECK( doctest::IsNaN(0.5) ) is NOT correct! + values: CHECK( 0.5 ) + +stringification.cpp(0): ERROR: CHECK( doctest::IsNaN(std::numeric_limits::infinity()) ) is NOT correct! + values: CHECK( inf ) + stringification.cpp(0): ERROR: test case THREW exception: MyTypeInherited(5, 4) =============================================================================== @@ -37,6 +43,6 @@ stringification.cpp(0): ERROR: test case THREW exception: 5 =============================================================================== [doctest] test cases: 2 | 0 passed | 2 failed | -[doctest] assertions: 7 | 0 passed | 7 failed | +[doctest] assertions: 9 | 0 passed | 9 failed | [doctest] Status: FAILURE! Program code. diff --git a/examples/all_features/test_output/stringification.cpp_junit.txt b/examples/all_features/test_output/stringification.cpp_junit.txt index 608cab131..a5e39dc2d 100644 --- a/examples/all_features/test_output/stringification.cpp_junit.txt +++ b/examples/all_features/test_output/stringification.cpp_junit.txt @@ -1,6 +1,6 @@ - + stringification.cpp(0): @@ -46,6 +46,18 @@ CHECK( s1 == s2 ) is NOT correct! logged: s1=MyOtherType: 42 s2=MyOtherType: 666 MyOtherType: 42 is not really MyOtherType: 666 + + +stringification.cpp(0): +CHECK( doctest::IsNaN<double>(0.5) ) is NOT correct! + values: CHECK( 0.5 ) + + + +stringification.cpp(0): +CHECK( doctest::IsNaN<float>(std::numeric_limits<float>::infinity()) ) is NOT correct! + values: CHECK( inf ) + MyTypeInherited<int>(5, 4) diff --git a/examples/all_features/test_output/stringification.cpp_xml.txt b/examples/all_features/test_output/stringification.cpp_xml.txt index a3af67b0d..67f6c96c4 100644 --- a/examples/all_features/test_output/stringification.cpp_xml.txt +++ b/examples/all_features/test_output/stringification.cpp_xml.txt @@ -68,10 +68,26 @@ MyOtherType: 42 is not really MyOtherType: 666 + + + doctest::IsNaN<double>(0.5) + + + 0.5 + + + + + doctest::IsNaN<float>(std::numeric_limits<float>::infinity()) + + + inf + + MyTypeInherited<int>(5, 4) - + @@ -80,7 +96,7 @@ - + Program code. diff --git a/examples/executable_dll_and_plugin/dll.cpp b/examples/executable_dll_and_plugin/dll.cpp index 0c025f615..22e498b47 100644 --- a/examples/executable_dll_and_plugin/dll.cpp +++ b/examples/executable_dll_and_plugin/dll.cpp @@ -2,11 +2,13 @@ #include DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN -#include +#include DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END TEST_CASE("dll") { - printf("I am a test from the dll!\n"); + std::cout << "I am a test from the dll!\n"; + CHECK(true); + CHECK(doctest::IsNaN(0.1L)); } DOCTEST_SYMBOL_EXPORT void from_dll(); // to silence "-Wmissing-declarations" with GCC diff --git a/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin.txt b/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin.txt index ea9bdebe3..d489082de 100644 --- a/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin.txt +++ b/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin.txt @@ -1,5 +1,12 @@ [doctest] run with "--help" for options I am a test from the dll! +=============================================================================== +dll.cpp(0): +TEST CASE: dll + +dll.cpp(0): ERROR: CHECK( doctest::IsNaN(0.1L) ) is NOT correct! + values: CHECK( 0.1 ) + I am a test from the implementation! I am a test from the implementation_2! I am a test from the executable! @@ -26,6 +33,6 @@ plugin.cpp(0): FATAL ERROR: certain death! logged: some info =============================================================================== -[doctest] test cases: 5 | 3 passed | 2 failed | 0 skipped -[doctest] assertions: 2 | 0 passed | 2 failed | +[doctest] test cases: 5 | 2 passed | 3 failed | 0 skipped +[doctest] assertions: 4 | 1 passed | 3 failed | [doctest] Status: FAILURE! diff --git a/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_junit.txt b/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_junit.txt index deb65a4ec..00d66345c 100644 --- a/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_junit.txt +++ b/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_junit.txt @@ -4,8 +4,15 @@ I am a test from the implementation! I am a test from the implementation_2! I am a test from the executable! - - + + + +dll.cpp(0): +CHECK( doctest::IsNaN<long double>(0.1L) ) is NOT correct! + values: CHECK( 0.1 ) + + + diff --git a/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_xml.txt b/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_xml.txt index d4f245c0b..960f03127 100644 --- a/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_xml.txt +++ b/examples/executable_dll_and_plugin/test_output/executable_dll_and_plugin_xml.txt @@ -4,7 +4,15 @@ I am a test from the dll! - + + + doctest::IsNaN<long double>(0.1L) + + + 0.1 + + + I am a test from the implementation! @@ -56,6 +64,6 @@ I am a test from the executable! - - + +