diff --git a/doc/markdown/assertions.md b/doc/markdown/assertions.md index 381dd52b8..ef908fb87 100644 --- a/doc/markdown/assertions.md +++ b/doc/markdown/assertions.md @@ -133,6 +133,19 @@ Checkout the [**example**](../../examples/all_features/asserts_used_outside_of_t Currently [**logging macros**](logging.md) cannot be used for extra context for asserts outside of a test run. That means that the ```_MESSAGE``` variants of asserts are also not usable - since they are just a packed ```INFO()``` with an assert right after it. +## String containment + +```doctest::Contains``` can be used to check whether the string passed to its constructor is contained within the string it is compared with. Here's a simple example: + +```c++ +REQUIRE("foobar" == doctest::Contains("foo")); +``` + +It can also be used with the ```THROWS_WITH``` family of assertion macros to check whether the thrown exception [translated to a string](stringification.md#translating-exceptions) contains the provided string. Here's another example: +```c++ +REQUIRE_THROWS_WITH(func(), doctest::Contains("Oopsie")); +``` + ## Floating point comparisons When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations. diff --git a/doctest/doctest.h b/doctest/doctest.h index 8f403fae3..3b6e965b1 100644 --- a/doctest/doctest.h +++ b/doctest/doctest.h @@ -592,6 +592,22 @@ DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); +class DOCTEST_INTERFACE Contains { +public: + explicit Contains(const String& string); + + bool checkWith(const String& other) const; + + String string; +}; + +DOCTEST_INTERFACE String toString(const Contains& in); + +DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); + namespace Color { enum Enum { @@ -744,9 +760,27 @@ struct DOCTEST_INTERFACE AssertData String m_decomp; // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; - const char* m_exception_string; + bool m_threw_as; + const char* m_exception_type; + class DOCTEST_INTERFACE StringContains { + private: + Contains content; + bool isContains; + + public: + StringContains() : content(String()), isContains(false) { } + StringContains(const String& str) : content(str), isContains(false) { } + StringContains(const Contains& cntn) : content(cntn), isContains(true) { } + + bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + + operator const String&() const { return content.string; } + + const char* c_str() const { return content.string.c_str(); } + } m_exception_string; + + AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string); }; struct DOCTEST_INTERFACE MessageData @@ -1519,7 +1553,10 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP struct DOCTEST_INTERFACE ResultBuilder : public AssertData { ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = "", const char* exception_string = ""); + const char* exception_type = "", const String& exception_string = ""); + + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string); void setResult(const Result& res); @@ -3643,17 +3680,30 @@ int String::compare(const String& other, bool no_case) const { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } -// clang-format off bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } -// clang-format on std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } +Contains::Contains(const String& str) : string(str) { } + +bool Contains::checkWith(const String& full_string) const { + return strstr(full_string.c_str(), string.c_str()) != nullptr; +} + +String toString(const Contains& in) { + return "Contains( " + in.string + " )"; +} + +bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } +bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } +bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } +bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + namespace { void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) } // namespace @@ -4706,24 +4756,26 @@ namespace { } #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH } // namespace -namespace detail { - 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; - m_at = at; - m_file = file; - m_line = line; - m_expr = expr; - m_failed = true; - m_threw = false; - m_threw_as = false; - m_exception_type = exception_type; - m_exception_string = exception_string; + +AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) { #if DOCTEST_MSVC - if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC - ++m_expr; + if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC + ++m_expr; #endif // MSVC - } +} + +namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const String& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } void ResultBuilder::setResult(const Result& res) { m_decomp = res.m_decomp; @@ -4739,11 +4791,11 @@ namespace detail { if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional m_failed = !m_threw; } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT - m_failed = !m_threw_as || (m_exception != m_exception_string); + m_failed = !m_threw_as || !m_exception_string.check(m_exception); } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional m_failed = !m_threw_as; } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - m_failed = m_exception != m_exception_string; + m_failed = !m_exception_string.check(m_exception); } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional m_failed = m_threw; } @@ -5416,7 +5468,7 @@ namespace { if(rb.m_at & assertType::is_throws_as) xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); if(rb.m_at & assertType::is_throws_with) - xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string); + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); if((rb.m_at & assertType::is_normal) && !rb.m_threw) xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); @@ -5462,7 +5514,8 @@ namespace { } 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; + << rb.m_exception_string.c_str() + << "\", " << rb.m_exception_type << " ) " << Color::None; if(rb.m_threw) { if(!rb.m_failed) { s << "threw as expected!\n"; @@ -5483,7 +5536,8 @@ namespace { } 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_exception_string.c_str() + << "\" ) " << Color::None << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : "threw a DIFFERENT exception: ") : "did NOT throw at all!") diff --git a/doctest/parts/doctest.cpp b/doctest/parts/doctest.cpp index b2add9916..7b8670a86 100644 --- a/doctest/parts/doctest.cpp +++ b/doctest/parts/doctest.cpp @@ -673,17 +673,30 @@ int String::compare(const String& other, bool no_case) const { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } -// clang-format off bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } -// clang-format on std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } +Contains::Contains(const String& str) : string(str) { } + +bool Contains::checkWith(const String& full_string) const { + return strstr(full_string.c_str(), string.c_str()) != nullptr; +} + +String toString(const Contains& in) { + return "Contains( " + in.string + " )"; +} + +bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } +bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } +bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } +bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + namespace { void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) } // namespace @@ -1736,24 +1749,26 @@ namespace { } #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH } // namespace -namespace detail { - 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; - m_at = at; - m_file = file; - m_line = line; - m_expr = expr; - m_failed = true; - m_threw = false; - m_threw_as = false; - m_exception_type = exception_type; - m_exception_string = exception_string; + +AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) { #if DOCTEST_MSVC - if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC - ++m_expr; + if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC + ++m_expr; #endif // MSVC - } +} + +namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const String& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } void ResultBuilder::setResult(const Result& res) { m_decomp = res.m_decomp; @@ -1769,11 +1784,11 @@ namespace detail { if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional m_failed = !m_threw; } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT - m_failed = !m_threw_as || (m_exception != m_exception_string); + m_failed = !m_threw_as || !m_exception_string.check(m_exception); } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional m_failed = !m_threw_as; } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - m_failed = m_exception != m_exception_string; + m_failed = !m_exception_string.check(m_exception); } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional m_failed = m_threw; } @@ -2446,7 +2461,7 @@ namespace { if(rb.m_at & assertType::is_throws_as) xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); if(rb.m_at & assertType::is_throws_with) - xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string); + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); if((rb.m_at & assertType::is_normal) && !rb.m_threw) xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); @@ -2492,7 +2507,8 @@ namespace { } 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; + << rb.m_exception_string.c_str() + << "\", " << rb.m_exception_type << " ) " << Color::None; if(rb.m_threw) { if(!rb.m_failed) { s << "threw as expected!\n"; @@ -2513,7 +2529,8 @@ namespace { } 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_exception_string.c_str() + << "\" ) " << Color::None << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : "threw a DIFFERENT exception: ") : "did NOT throw at all!") diff --git a/doctest/parts/doctest_fwd.h b/doctest/parts/doctest_fwd.h index 13db6a34b..5f381b136 100644 --- a/doctest/parts/doctest_fwd.h +++ b/doctest/parts/doctest_fwd.h @@ -589,6 +589,22 @@ DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); +class DOCTEST_INTERFACE Contains { +public: + explicit Contains(const String& string); + + bool checkWith(const String& other) const; + + String string; +}; + +DOCTEST_INTERFACE String toString(const Contains& in); + +DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); + namespace Color { enum Enum { @@ -741,9 +757,27 @@ struct DOCTEST_INTERFACE AssertData String m_decomp; // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; - const char* m_exception_string; + bool m_threw_as; + const char* m_exception_type; + class DOCTEST_INTERFACE StringContains { + private: + Contains content; + bool isContains; + + public: + StringContains() : content(String()), isContains(false) { } + StringContains(const String& str) : content(str), isContains(false) { } + StringContains(const Contains& cntn) : content(cntn), isContains(true) { } + + bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + + operator const String&() const { return content.string; } + + const char* c_str() const { return content.string.c_str(); } + } m_exception_string; + + AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string); }; struct DOCTEST_INTERFACE MessageData @@ -1516,7 +1550,10 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP struct DOCTEST_INTERFACE ResultBuilder : public AssertData { ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = "", const char* exception_string = ""); + const char* exception_type = "", const String& exception_string = ""); + + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string); void setResult(const Result& res); diff --git a/examples/all_features/assertion_macros.cpp b/examples/all_features/assertion_macros.cpp index f0fbe9b0e..959a9c3d7 100644 --- a/examples/all_features/assertion_macros.cpp +++ b/examples/all_features/assertion_macros.cpp @@ -38,8 +38,11 @@ TEST_CASE("exceptions-related macros") { CHECK_THROWS_AS(throw_if(false, 0), int); // fails CHECK_THROWS_WITH(throw_if(true, "whops!"), "whops! no match!"); // fails + CHECK_THROWS_WITH(throw_if(true, "whops! does it match?"), doctest::Contains("whops!")); + CHECK_THROWS_WITH(throw_if(true, "whops! does it match?"), doctest::Contains("whops! no match!")); // fails CHECK_THROWS_WITH_AS(throw_if(true, "whops!"), "whops! no match!", bool); // fails CHECK_THROWS_WITH_AS(throw_if(true, "whops!"), "whops!", int); // fails + CHECK_THROWS_WITH_AS(throw_if(true, "whops! does it match?"), doctest::Contains("whops! no match!"), int); // fails CHECK_NOTHROW(throw_if(true, 0)); // fails CHECK_NOTHROW(throw_if(false, 0)); @@ -73,6 +76,10 @@ TEST_CASE("WARN level of asserts don't fail the test case") { WARN_NOTHROW(throw_if(true, 0)); WARN_EQ(1, 0); + doctest::String myStr = doctest::String("Hello world, how are you doing? Well, nice to meet you, Goodbye!"); + WARN_EQ(myStr, doctest::Contains("Hello")); + WARN(myStr == doctest::Contains("Goodbye")); + WARN(myStr != doctest::Contains("goodbye")); WARN_UNARY(0); WARN_UNARY_FALSE(1); } @@ -88,6 +95,10 @@ TEST_CASE("CHECK level of asserts fail the test case but don't abort it") { CHECK_NOTHROW(throw_if(true, 0)); CHECK_EQ(1, 0); + doctest::String myStr = doctest::String("Hello world, how are you doing? Well, nice to meet you, Goodbye!"); + CHECK_EQ(myStr, doctest::Contains("Hello")); + CHECK(myStr == doctest::Contains("Goodbye")); + CHECK(myStr != doctest::Contains("goodbye")); CHECK_UNARY(0); CHECK_UNARY_FALSE(1); diff --git a/examples/all_features/stringification.cpp b/examples/all_features/stringification.cpp index adca1e7f8..2add560de 100644 --- a/examples/all_features/stringification.cpp +++ b/examples/all_features/stringification.cpp @@ -151,6 +151,8 @@ TEST_CASE("all asserts should fail and show how the objects get stringified") { CHECK(doctest::IsNaN(std::numeric_limits::infinity())); // can't test actual nan because it's implementation defined + CHECK("a" == doctest::Contains("aaa")); + // 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 513939d42..fc4cc9468 100644 --- a/examples/all_features/test_output/assertion_macros.cpp.txt +++ b/examples/all_features/test_output/assertion_macros.cpp.txt @@ -20,10 +20,14 @@ assertion_macros.cpp(0): ERROR: CHECK_THROWS_AS( throw_if(false, 0), int ) did N assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH( throw_if(true, "whops!"), "whops! no match!" ) threw a DIFFERENT exception: "whops!" +assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH( throw_if(true, "whops! does it match?"), "whops! no match!" ) threw a DIFFERENT exception: "whops! does it match?" + assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH_AS( throw_if(true, "whops!"), "whops! no match!", bool ) threw a DIFFERENT exception! (contents: "whops!") assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH_AS( throw_if(true, "whops!"), "whops!", int ) threw a DIFFERENT exception! (contents: "whops!") +assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH_AS( throw_if(true, "whops! does it match?"), "whops! no match!", int ) threw a DIFFERENT exception! (contents: "whops! does it match?") + assertion_macros.cpp(0): ERROR: CHECK_NOTHROW( throw_if(true, 0) ) THREW exception: "0" =============================================================================== @@ -248,6 +252,6 @@ assertion_macros.cpp(0): ERROR: CHECK_THROWS_WITH( throw_if(true, 2), "1" ) thre =============================================================================== [doctest] test cases: 23 | 4 passed | 19 failed | -[doctest] assertions: 92 | 44 passed | 48 failed | +[doctest] assertions: 98 | 48 passed | 50 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 bcc119c33..3802a4e6b 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): @@ -35,6 +35,11 @@ CHECK_THROWS_AS( throw_if(false, 0), int ) did NOT throw at all! assertion_macros.cpp(0): CHECK_THROWS_WITH( throw_if(true, "whops!"), "whops! no match!" ) threw a DIFFERENT exception: "whops!" + + +assertion_macros.cpp(0): +CHECK_THROWS_WITH( throw_if(true, "whops! does it match?"), "whops! no match!" ) threw a DIFFERENT exception: "whops! does it match?" + assertion_macros.cpp(0): @@ -45,6 +50,11 @@ CHECK_THROWS_WITH_AS( throw_if(true, "whops!"), "whops! no match!", bool ) threw assertion_macros.cpp(0): CHECK_THROWS_WITH_AS( throw_if(true, "whops!"), "whops!", int ) threw a DIFFERENT exception! (contents: "whops!") + + +assertion_macros.cpp(0): +CHECK_THROWS_WITH_AS( throw_if(true, "whops! does it match?"), "whops! no match!", int ) threw a DIFFERENT exception! (contents: "whops! does it match?") + assertion_macros.cpp(0): 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 28e10330d..b67c33aad 100644 --- a/examples/all_features/test_output/assertion_macros.cpp_xml.txt +++ b/examples/all_features/test_output/assertion_macros.cpp_xml.txt @@ -60,6 +60,17 @@ whops! no match! + + + throw_if(true, "whops! does it match?") + + + "whops! does it match?" + + + whops! no match! + + throw_if(true, "whops!") @@ -88,6 +99,20 @@ whops! + + + throw_if(true, "whops! does it match?") + + + "whops! does it match?" + + + int + + + whops! no match! + + throw_if(true, 0) @@ -96,7 +121,7 @@ "0" - + @@ -359,7 +384,7 @@ reached! - + @@ -659,7 +684,7 @@ - + Program code. diff --git a/examples/all_features/test_output/stringification.cpp.txt b/examples/all_features/test_output/stringification.cpp.txt index 234e806a7..650063ec0 100644 --- a/examples/all_features/test_output/stringification.cpp.txt +++ b/examples/all_features/test_output/stringification.cpp.txt @@ -33,6 +33,9 @@ stringification.cpp(0): ERROR: CHECK( doctest::IsNaN(0.5) ) is NOT corre stringification.cpp(0): ERROR: CHECK( doctest::IsNaN(std::numeric_limits::infinity()) ) is NOT correct! values: CHECK( inf ) +stringification.cpp(0): ERROR: CHECK( "a" == doctest::Contains("aaa") ) is NOT correct! + values: CHECK( a == Contains( aaa ) ) + stringification.cpp(0): ERROR: test case THREW exception: MyTypeInherited(5, 4) =============================================================================== @@ -42,7 +45,7 @@ TEST CASE: a test case that registers an exception translator for int and then stringification.cpp(0): ERROR: test case THREW exception: 5 =============================================================================== -[doctest] test cases: 2 | 0 passed | 2 failed | -[doctest] assertions: 9 | 0 passed | 9 failed | +[doctest] test cases: 2 | 0 passed | 2 failed | +[doctest] assertions: 10 | 0 passed | 10 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 a5e39dc2d..eac29e124 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): @@ -58,6 +58,12 @@ stringification.cpp(0): CHECK( doctest::IsNaN<float>(std::numeric_limits<float>::infinity()) ) is NOT correct! values: CHECK( inf ) + + +stringification.cpp(0): +CHECK( "a" == doctest::Contains("aaa") ) is NOT correct! + values: CHECK( a == Contains( aaa ) ) + 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 67f6c96c4..066df99f9 100644 --- a/examples/all_features/test_output/stringification.cpp_xml.txt +++ b/examples/all_features/test_output/stringification.cpp_xml.txt @@ -84,10 +84,18 @@ inf + + + "a" == doctest::Contains("aaa") + + + a == Contains( aaa ) + + MyTypeInherited<int>(5, 4) - + @@ -96,7 +104,7 @@ - + Program code.