diff --git a/include/GUnit/GAssert.h b/include/GUnit/GAssert.h index 6f0743a..f187ca0 100644 --- a/include/GUnit/GAssert.h +++ b/include/GUnit/GAssert.h @@ -17,6 +17,36 @@ namespace testing { inline namespace v1 { namespace detail { +template +AssertionResult CmpHelperAnd(const char* lhs_expression, + const char* rhs_expression, + const T1& lhs, const T2& rhs) { + if (lhs and rhs) { + return AssertionSuccess(); + } + return internal::CmpHelperOpFailure(lhs_expression, rhs_expression, lhs, rhs, "and"); +}; + +template +AssertionResult CmpHelperOr(const char* lhs_expression, + const char* rhs_expression, + const T1& lhs, const T2& rhs) { + if (lhs or rhs) { + return AssertionSuccess(); + } + return internal::CmpHelperOpFailure(lhs_expression, rhs_expression, lhs, rhs, "or"); +}; + +template +AssertionResult CmpHelperXor(const char* lhs_expression, + const char* rhs_expression, + const T1& lhs, const T2& rhs) { + if (lhs xor rhs) { + return AssertionSuccess(); + } + return internal::CmpHelperOpFailure(lhs_expression, rhs_expression, lhs, rhs, "xor"); +}; + struct info { const char* file{}; unsigned long line{}; @@ -127,6 +157,27 @@ class op { info_, "<", lhs_, rhs}; } + template + auto operator&&(const TRhs& rhs) const { + followed_ = true; + return msg{ + info_, "and", lhs_, rhs}; + } + + template + auto operator||(const TRhs& rhs) const { + followed_ = true; + return msg{ + info_, "or", lhs_, rhs}; + } + + template + auto operator^(const TRhs& rhs) const { + followed_ = true; + return msg{ + info_, "xor", lhs_, rhs}; + } + operator bool() const { return result_; } private: @@ -213,7 +264,7 @@ void prevent_commas(T&&) {} (::testing::detail::op{ \ ::testing::detail::info{__FILE__, __LINE__, #__VA_ARGS__, \ ::testing::TestPartResult::kNonFatalFailure}} \ - << (__VA_ARGS__)) + << __VA_ARGS__) #define EXPECT(...) \ GUNIT_PREVENT_COMMAS(__VA_ARGS__); \ @@ -223,14 +274,14 @@ void prevent_commas(T&&) {} if (::testing::detail::op{ \ ::testing::detail::info{__FILE__, __LINE__, #__VA_ARGS__, \ ::testing::TestPartResult::kFatalFailure}} \ - << (__VA_ARGS__)) \ + << __VA_ARGS__) \ void(::testing::detail::drop{}); \ else \ return ::testing::detail::ret_void{} == \ (::testing::detail::op{::testing::detail::info{ \ __FILE__, __LINE__, #__VA_ARGS__, \ ::testing::TestPartResult::kFatalFailure}} \ - << (__VA_ARGS__)) + << __VA_ARGS__) #define ASSERT(...) \ GUNIT_PREVENT_COMMAS(__VA_ARGS__); \ diff --git a/test/GAssert.cpp b/test/GAssert.cpp index 2cdff3c..9f85b9e 100644 --- a/test/GAssert.cpp +++ b/test/GAssert.cpp @@ -8,6 +8,20 @@ #include #include "GUnit/GAssert.h" +struct call_only_once { + int a{42}; + bool called{false}; + + auto value() -> int { + if (called) { + throw std::runtime_error("Called twice, should only evaluate once."); + } + + called = true; + return a; + } +}; + TEST(GAssert, ShouldSupportExpect) { auto i = 42; const auto b = true; @@ -16,6 +30,10 @@ TEST(GAssert, ShouldSupportExpect) { EXPECT(!false) << "message"; EXPECT(b); + call_only_once once{}; + EXPECT(once.value() == 42); + EXPECT_THROW(once.value(), std::runtime_error); + EXPECT(i == 42); EXPECT(42 == i); EXPECT(42 == i);