mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Allow CHECK_<OP> variants to be used with unprintable types.
PiperOrigin-RevId: 786406173 Change-Id: Ifc362a702f82a6b3ad33210980dda6f40f14fca4
This commit is contained in:
committed by
Copybara-Service
parent
63d67e9593
commit
57bc7edd87
@@ -265,6 +265,26 @@ TEST(CHECKTest, TestBinaryChecksWithNullptr) {
|
||||
ABSL_TEST_CHECK_NE(nullptr, p_not_null);
|
||||
}
|
||||
|
||||
struct ExampleTypeThatHasNoStreamOperator {
|
||||
bool x;
|
||||
|
||||
bool operator==(const ExampleTypeThatHasNoStreamOperator& other) const {
|
||||
return x == other.x;
|
||||
}
|
||||
bool operator==(const bool& other) const { return x == other; }
|
||||
};
|
||||
|
||||
TEST(CHECKDeathTest, TestBinaryChecksWithUnprintable) {
|
||||
ExampleTypeThatHasNoStreamOperator a{true};
|
||||
ExampleTypeThatHasNoStreamOperator b{false};
|
||||
ABSL_TEST_CHECK_EQ(a, a);
|
||||
EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),
|
||||
"Check failed: a == b \\(UNPRINTABLE vs. UNPRINTABLE\\)");
|
||||
ABSL_TEST_CHECK_EQ(a, true);
|
||||
EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, false),
|
||||
"Check failed: a == false \\(UNPRINTABLE vs. 0\\)");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// Test logging of various char-typed values by failing CHECK*().
|
||||
|
||||
@@ -101,6 +101,8 @@ void MakeCheckOpValueString(std::ostream& os, const void* p) {
|
||||
}
|
||||
}
|
||||
|
||||
void MakeCheckOpUnprintableString(std::ostream& os) { os << "UNPRINTABLE"; }
|
||||
|
||||
// Helper functions for string comparisons.
|
||||
#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
|
||||
const char* absl_nullable Check##func##expected##Impl( \
|
||||
|
||||
@@ -224,6 +224,19 @@ void MakeCheckOpValueString(std::ostream& os, signed char v);
|
||||
void MakeCheckOpValueString(std::ostream& os, unsigned char v);
|
||||
void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p);
|
||||
|
||||
void MakeCheckOpUnprintableString(std::ostream& os);
|
||||
|
||||
// A wrapper for types that have no operator<<.
|
||||
struct UnprintableWrapper {
|
||||
template <typename T>
|
||||
explicit UnprintableWrapper(const T&) {}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const UnprintableWrapper&) {
|
||||
MakeCheckOpUnprintableString(os);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detect_specialization {
|
||||
|
||||
// MakeCheckOpString is being specialized for every T and U pair that is being
|
||||
@@ -353,6 +366,15 @@ struct is_streamable<T, std::void_t<decltype(std::declval<std::ostream&>()
|
||||
<< std::declval<T>())>>
|
||||
: std::true_type {};
|
||||
|
||||
// This overload triggers when T is neither possible to print nor an enum.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::negation_v<std::disjunction<
|
||||
std::is_convertible<T, int>, std::is_enum<T>,
|
||||
std::is_pointer<T>, std::is_same<T, std::nullptr_t>,
|
||||
is_streamable<T>, HasAbslStringify<T>>>,
|
||||
UnprintableWrapper>
|
||||
Detect(...);
|
||||
|
||||
// This overload triggers when T is a scoped enum that has not defined an output
|
||||
// stream operator (operator<<) or AbslStringify. It causes the enum value to be
|
||||
// converted to a type that can be streamed. For consistency with other enums, a
|
||||
|
||||
Reference in New Issue
Block a user