From 4c9ad191e14e5926ce0213d7dddb7a35529c2756 Mon Sep 17 00:00:00 2001 From: Igor Nazarenko Date: Tue, 5 May 2020 11:06:33 -0700 Subject: [PATCH] Detect proto messages based on presense of DebugString. --- .../include/gtest/internal/gtest-internal.h | 31 +++++++++++-- googletest/test/gtest_unittest.cc | 46 ++++++++++++++++--- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index fabc8042..6da1d910 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -880,11 +880,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. +// IsAProtocolMessage::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 IsAProtocolMessage { + private: + template + static constexpr auto CheckDebugString(C*) -> + typename std::is_same().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 IsAProtocolMessage::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 005a2d40..ed8e89c5 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -7102,21 +7102,55 @@ GTEST_TEST(AlternativeNameTest, Works) { // GTEST_TEST is the same as TEST. class ConversionHelperBase {}; class ConversionHelperDerived : public ConversionHelperBase {}; +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 IsAProtocolMessage::value is a compile-time constant. TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) { - GTEST_COMPILE_ASSERT_(IsAProtocolMessage<::proto2::MessageLite>::value, + GTEST_COMPILE_ASSERT_(IsAProtocolMessage::value, const_true); + GTEST_COMPILE_ASSERT_(IsAProtocolMessage::value, + const_true); + GTEST_COMPILE_ASSERT_( + IsAProtocolMessage::value, const_true); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage::value, + const_false); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage::value, + const_false); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage::value, + const_false); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage::value, + const_false); GTEST_COMPILE_ASSERT_(!IsAProtocolMessage::value, const_false); } -// Tests that IsAProtocolMessage::value is true when T is -// proto2::Message or a sub-class of it. +// Tests that IsAProtocolMessage::value is true when T has needed methods. TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) { - EXPECT_TRUE(IsAProtocolMessage<::proto2::MessageLite>::value); + EXPECT_TRUE(IsAProtocolMessage::value); } -// Tests that IsAProtocolMessage::value is false when T is neither -// ::proto2::Message nor a sub-class of it. +// Tests that IsAProtocolMessage::value is false when T doesn't have needed +// methods. TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) { EXPECT_FALSE(IsAProtocolMessage::value); EXPECT_FALSE(IsAProtocolMessage::value);