diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h index f24512a9..99129a53 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -235,8 +235,9 @@ struct ProtobufPrinter { // DebugString() for better readability. static const size_t kProtobufOneLinerMaxLength = 50; - template ::value>::type> + template ::value>::type> static void PrintValue(const T& value, ::std::ostream* os) { std::string pretty_str = value.ShortDebugString(); if (pretty_str.length() > kProtobufOneLinerMaxLength) { diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 233724cc..bd4e4198 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -892,11 +892,34 @@ class GTEST_API_ Random { #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ typename std::remove_const::type>::type -// IsAProtocolMessage::value is a compile-time bool constant that's -// true if and only if T is type proto2::MessageLite or a subclass of it. +// HasDebugStringAndShortDebugString::value is a compile-time bool constant +// that's true if and only if T has methods DebugString() and ShortDebugString() +// that return std::string. template -struct IsAProtocolMessage - : public std::is_convertible {}; +class HasDebugStringAndShortDebugString { + private: + template + static constexpr auto CheckDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval().DebugString())>::type; + template + static constexpr std::false_type CheckDebugString(...); + + template + static constexpr auto CheckShortDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval().ShortDebugString())>::type; + template + static constexpr std::false_type CheckShortDebugString(...); + + using HasDebugStringType = decltype(CheckDebugString(nullptr)); + using HasShortDebugStringType = decltype(CheckShortDebugString(nullptr)); + + public: + static constexpr bool value = + HasDebugStringType::value && HasShortDebugStringType::value; +}; + +template +constexpr bool HasDebugStringAndShortDebugString::value; // When the compiler sees expression IsContainerTest(0), if C is an // STL-style container class, the first overload of IsContainerTest diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 7aa884a0..4995d07b 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -254,8 +254,8 @@ using testing::internal::GetTimeInMillis; using testing::internal::GetTypeId; using testing::internal::GetUnitTestImpl; using testing::internal::GTestFlagSaver; +using testing::internal::HasDebugStringAndShortDebugString; using testing::internal::Int32FromEnvOrDie; -using testing::internal::IsAProtocolMessage; using testing::internal::IsContainer; using testing::internal::IsContainerTest; using testing::internal::IsNotContainer; @@ -7185,24 +7185,71 @@ GTEST_TEST(AlternativeNameTest, Works) { // GTEST_TEST is the same as TEST. class ConversionHelperBase {}; class ConversionHelperDerived : public ConversionHelperBase {}; -// Tests that IsAProtocolMessage::value is a compile-time constant. -TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) { - GTEST_COMPILE_ASSERT_(IsAProtocolMessage<::proto2::MessageLite>::value, +struct HasDebugStringMethods { + std::string DebugString() const { return ""; } + std::string ShortDebugString() const { return ""; } +}; + +struct InheritsDebugStringMethods : public HasDebugStringMethods {}; + +struct WrongTypeDebugStringMethod { + std::string DebugString() const { return ""; } + int ShortDebugString() const { return 1; } +}; + +struct NotConstDebugStringMethod { + std::string DebugString() { return ""; } + std::string ShortDebugString() const { return ""; } +}; + +struct MissingDebugStringMethod { + std::string DebugString() { return ""; } +}; + +struct IncompleteType; + +// Tests that HasDebugStringAndShortDebugString::value is a compile-time +// constant. +TEST(HasDebugStringAndShortDebugStringTest, ValueIsCompileTimeConstant) { + GTEST_COMPILE_ASSERT_( + HasDebugStringAndShortDebugString::value, + const_true); + GTEST_COMPILE_ASSERT_( + HasDebugStringAndShortDebugString::value, + const_true); + GTEST_COMPILE_ASSERT_(HasDebugStringAndShortDebugString< + const InheritsDebugStringMethods>::value, const_true); - GTEST_COMPILE_ASSERT_(!IsAProtocolMessage::value, const_false); + GTEST_COMPILE_ASSERT_( + !HasDebugStringAndShortDebugString::value, + const_false); + GTEST_COMPILE_ASSERT_( + !HasDebugStringAndShortDebugString::value, + const_false); + GTEST_COMPILE_ASSERT_( + !HasDebugStringAndShortDebugString::value, + const_false); + GTEST_COMPILE_ASSERT_( + !HasDebugStringAndShortDebugString::value, const_false); + GTEST_COMPILE_ASSERT_(!HasDebugStringAndShortDebugString::value, + const_false); } -// Tests that IsAProtocolMessage::value is true when T is -// proto2::Message or a sub-class of it. -TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) { - EXPECT_TRUE(IsAProtocolMessage<::proto2::MessageLite>::value); +// Tests that HasDebugStringAndShortDebugString::value is true when T has +// needed methods. +TEST(HasDebugStringAndShortDebugStringTest, + ValueIsTrueWhenTypeHasDebugStringAndShortDebugString) { + EXPECT_TRUE( + HasDebugStringAndShortDebugString::value); } -// Tests that IsAProtocolMessage::value is false when T is neither -// ::proto2::Message nor a sub-class of it. -TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) { - EXPECT_FALSE(IsAProtocolMessage::value); - EXPECT_FALSE(IsAProtocolMessage::value); +// Tests that HasDebugStringAndShortDebugString::value is false when T +// doesn't have needed methods. +TEST(HasDebugStringAndShortDebugStringTest, + ValueIsFalseWhenTypeIsNotAProtocolMessage) { + EXPECT_FALSE(HasDebugStringAndShortDebugString::value); + EXPECT_FALSE( + HasDebugStringAndShortDebugString::value); } // Tests GTEST_REMOVE_REFERENCE_AND_CONST_.