From 6568bd0acc03f3df8b52a8429d7225dcd1a77f1f Mon Sep 17 00:00:00 2001 From: "K. R. Walker" Date: Wed, 6 Sep 2023 14:42:45 -0600 Subject: [PATCH] Include negated assertion_result messages: Given a helper function `isEqualCaseInsensitive()` returning helpful detail in the resulting assertion_result message, negation of that result in a `BOOST_CHECK()` results in that detail being discarded. This feature preserves that detail in the negated case. For example: `BOOST_CHECK(isEqualCaseInsensitive('z', 'Z'))` included detail like `[z isEqualCaseInsensitiveTo Z]` `BOOST_CHECK(!isEqualCaseInsensitive('z', 'Z'))` discarded that detail until this revision, which now includes it: `NOT([z isEqualCaseInsensitiveTo Z])` --- include/boost/test/tools/assertion_result.hpp | 13 +++++++- .../assertion-construction-test.cpp | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/boost/test/tools/assertion_result.hpp b/include/boost/test/tools/assertion_result.hpp index 85eea741f7..cd910fecec 100644 --- a/include/boost/test/tools/assertion_result.hpp +++ b/include/boost/test/tools/assertion_result.hpp @@ -57,7 +57,12 @@ class BOOST_TEST_DECL assertion_result { assertion_result( BoolConvertable const& pv_ ) : p_predicate_value( !!pv_ ) {} // Access methods - bool operator!() const { return !p_predicate_value; } + assertion_result operator!() const + { + assertion_result negatedResult = !p_predicate_value; + negatedResult.message() << "NOT(" << ( !m_message ? std::string() : m_message->str() ) << ")"; + return negatedResult; + } void operator=( bool pv_ ) { p_predicate_value.value = pv_; } operator safe_bool() const { return !!p_predicate_value ? &dummy::nonnull : 0; } @@ -75,6 +80,12 @@ class BOOST_TEST_DECL assertion_result { } const_string message() const { return !m_message ? const_string() : const_string( m_message->str() ); } + // Operators + friend bool operator==(bool left, const assertion_result& right) { return left == static_cast(right); } + friend bool operator==(const assertion_result& left, bool right) { return static_cast(left) == right; } + friend bool operator!=(bool left, const assertion_result& right) { return left == static_cast(right); } + friend bool operator!=(const assertion_result& left, bool right) { return static_cast(left) == right; } + private: // Data members shared_ptr m_message; diff --git a/test/writing-test-ts/assertion-construction-test.cpp b/test/writing-test-ts/assertion-construction-test.cpp index ad791aea91..7537905848 100644 --- a/test/writing-test-ts/assertion-construction-test.cpp +++ b/test/writing-test-ts/assertion-construction-test.cpp @@ -20,6 +20,7 @@ #include +#include #include #include @@ -405,6 +406,15 @@ class NC : boost::noncopyable { } }; +boost::test_tools::predicate_result isEqualCaseInsensitive(char left, char right) +{ + boost::test_tools::predicate_result result( + std::tolower(left, std::locale::classic()) == std::tolower(right, std::locale::classic())); + result.message() << "[" << left << " isEqualCaseInsensitiveTo " << right << ']'; + return result; +} + + BOOST_AUTO_TEST_CASE( test_objects ) { using namespace boost::test_tools; @@ -469,6 +479,27 @@ BOOST_AUTO_TEST_CASE( test_objects ) BOOST_TEST( !res ); BOOST_TEST( res.message() == " [NC != NC]" ); } + + { + predicate_result const& res = EXPR_TYPE( isEqualCaseInsensitive('z', 'Z') ).evaluate(); + BOOST_TEST( res ); + BOOST_TEST( res.message() == "[z isEqualCaseInsensitiveTo Z]" ); + } + + { + predicate_result const& res = !EXPR_TYPE( isEqualCaseInsensitive('z', 'Z') ).evaluate(); + BOOST_TEST( !res ); + BOOST_TEST( res.message() == "NOT([z isEqualCaseInsensitiveTo Z])" ); + } + + { + NC nc1; + NC nc2; + + predicate_result const& res = !EXPR_TYPE( nc1 == nc2 ).evaluate(); + BOOST_TEST( res ); + BOOST_TEST( res.message() == "NOT( [NC != NC])" ); + } } //____________________________________________________________________________//