Skip to content

Commit 1a4f16d

Browse files
committed
🐛 Fix printing variables when expect or assert fails
Problem: - EXPECT and ASSERT macros only print whether the expression is true or false when the test expectations fail - GUnit stopped printing out the values of the variables used in the expressiong passed to the EXPECT or ASSERT macros - Fix for logical expression broke variable printing Solution: - Remove extra parenthesis in macros that resulted in full evaluation of the expression before the op and cmp objects could be initialized. - Add CmpHelperAnd/Or/Xor with corresponding and/or/xor overloads to allow evaluating logical expressions. - Added test to verify tested expressions are only evaluated once.
1 parent 8f5e27c commit 1a4f16d

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

include/GUnit/GAssert.h

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,36 @@ namespace testing {
1717
inline namespace v1 {
1818
namespace detail {
1919

20+
template <typename T1, typename T2>
21+
AssertionResult CmpHelperAnd(const char* lhs_expression,
22+
const char* rhs_expression,
23+
const T1& lhs, const T2& rhs) {
24+
if (lhs and rhs) {
25+
return AssertionSuccess();
26+
}
27+
return internal::CmpHelperOpFailure(lhs_expression, rhs_expression, lhs, rhs, "and");
28+
};
29+
30+
template <typename T1, typename T2>
31+
AssertionResult CmpHelperOr(const char* lhs_expression,
32+
const char* rhs_expression,
33+
const T1& lhs, const T2& rhs) {
34+
if (lhs or rhs) {
35+
return AssertionSuccess();
36+
}
37+
return internal::CmpHelperOpFailure(lhs_expression, rhs_expression, lhs, rhs, "or");
38+
};
39+
40+
template <typename T1, typename T2>
41+
AssertionResult CmpHelperXor(const char* lhs_expression,
42+
const char* rhs_expression,
43+
const T1& lhs, const T2& rhs) {
44+
if (lhs xor rhs) {
45+
return AssertionSuccess();
46+
}
47+
return internal::CmpHelperOpFailure(lhs_expression, rhs_expression, lhs, rhs, "xor");
48+
};
49+
2050
struct info {
2151
const char* file{};
2252
unsigned long line{};
@@ -127,6 +157,27 @@ class op {
127157
info_, "<", lhs_, rhs};
128158
}
129159

160+
template <class TRhs>
161+
auto operator&&(const TRhs& rhs) const {
162+
followed_ = true;
163+
return msg<TShouldError, const TLhs&, const TRhs&, CmpHelperAnd>{
164+
info_, "and", lhs_, rhs};
165+
}
166+
167+
template <class TRhs>
168+
auto operator||(const TRhs& rhs) const {
169+
followed_ = true;
170+
return msg<TShouldError, const TLhs&, const TRhs&, CmpHelperOr>{
171+
info_, "or", lhs_, rhs};
172+
}
173+
174+
template <class TRhs>
175+
auto operator^(const TRhs& rhs) const {
176+
followed_ = true;
177+
return msg<TShouldError, const TLhs&, const TRhs&, CmpHelperXor>{
178+
info_, "xor", lhs_, rhs};
179+
}
180+
130181
operator bool() const { return result_; }
131182

132183
private:
@@ -213,7 +264,7 @@ void prevent_commas(T&&) {}
213264
(::testing::detail::op<std::true_type>{ \
214265
::testing::detail::info{__FILE__, __LINE__, #__VA_ARGS__, \
215266
::testing::TestPartResult::kNonFatalFailure}} \
216-
<< (__VA_ARGS__))
267+
<< __VA_ARGS__)
217268

218269
#define EXPECT(...) \
219270
GUNIT_PREVENT_COMMAS(__VA_ARGS__); \
@@ -223,14 +274,14 @@ void prevent_commas(T&&) {}
223274
if (::testing::detail::op<std::false_type>{ \
224275
::testing::detail::info{__FILE__, __LINE__, #__VA_ARGS__, \
225276
::testing::TestPartResult::kFatalFailure}} \
226-
<< (__VA_ARGS__)) \
277+
<< __VA_ARGS__) \
227278
void(::testing::detail::drop{}); \
228279
else \
229280
return ::testing::detail::ret_void{} == \
230281
(::testing::detail::op<std::true_type>{::testing::detail::info{ \
231282
__FILE__, __LINE__, #__VA_ARGS__, \
232283
::testing::TestPartResult::kFatalFailure}} \
233-
<< (__VA_ARGS__))
284+
<< __VA_ARGS__)
234285

235286
#define ASSERT(...) \
236287
GUNIT_PREVENT_COMMAS(__VA_ARGS__); \

test/GAssert.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@
88
#include <gtest/gtest.h>
99
#include "GUnit/GAssert.h"
1010

11+
struct call_only_once {
12+
int a{42};
13+
bool called{false};
14+
15+
auto value() -> int {
16+
if (called) {
17+
throw std::runtime_error("Called twice, should only evaluate once.");
18+
}
19+
20+
called = true;
21+
return a;
22+
}
23+
};
24+
1125
TEST(GAssert, ShouldSupportExpect) {
1226
auto i = 42;
1327
const auto b = true;
@@ -16,6 +30,10 @@ TEST(GAssert, ShouldSupportExpect) {
1630
EXPECT(!false) << "message";
1731
EXPECT(b);
1832

33+
call_only_once once{};
34+
EXPECT(once.value() == 42);
35+
EXPECT_THROW(once.value(), std::runtime_error);
36+
1937
EXPECT(i == 42);
2038
EXPECT(42 == i);
2139
EXPECT(42 == i);

0 commit comments

Comments
 (0)