diff options
-rw-r--r-- | googletest/include/gtest/internal/gtest-internal.h | 31 | ||||
-rw-r--r-- | 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 fabc804..6da1d91 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<typename std::remove_reference<T>::type>::type -// IsAProtocolMessage<T>::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<T>::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 <typename T> -struct IsAProtocolMessage - : public std::is_convertible<const T*, const ::proto2::MessageLite*> {}; +class IsAProtocolMessage { + private: + template <typename C> + static constexpr auto CheckDebugString(C*) -> + typename std::is_same<std::string, + decltype(std::declval<const C>().DebugString())>::type; + template <typename> + static constexpr std::false_type CheckDebugString(...); + + template <typename C> + static constexpr auto CheckShortDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval<const C>().ShortDebugString())>::type; + template <typename> + static constexpr std::false_type CheckShortDebugString(...); + + using HasDebugStringType = decltype(CheckDebugString<T>(nullptr)); + using HasShortDebugStringType = decltype(CheckShortDebugString<T>(nullptr)); + + public: + static constexpr bool value = + HasDebugStringType::value && HasShortDebugStringType::value; +}; + +template <typename T> constexpr bool IsAProtocolMessage<T>::value; // When the compiler sees expression IsContainerTest<C>(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 005a2d4..ed8e89c 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<T>::value is a compile-time constant. TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) { - GTEST_COMPILE_ASSERT_(IsAProtocolMessage<::proto2::MessageLite>::value, + GTEST_COMPILE_ASSERT_(IsAProtocolMessage<HasDebugStringMethods>::value, + const_true); + GTEST_COMPILE_ASSERT_(IsAProtocolMessage<InheritsDebugStringMethods>::value, const_true); + GTEST_COMPILE_ASSERT_( + IsAProtocolMessage<const InheritsDebugStringMethods>::value, const_true); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<WrongTypeDebugStringMethod>::value, + const_false); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<NotConstDebugStringMethod>::value, + const_false); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<MissingDebugStringMethod>::value, + const_false); + GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<IncompleteType>::value, + const_false); GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<int>::value, const_false); } -// Tests that IsAProtocolMessage<T>::value is true when T is -// proto2::Message or a sub-class of it. +// Tests that IsAProtocolMessage<T>::value is true when T has needed methods. TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) { - EXPECT_TRUE(IsAProtocolMessage<::proto2::MessageLite>::value); + EXPECT_TRUE(IsAProtocolMessage<InheritsDebugStringMethods>::value); } -// Tests that IsAProtocolMessage<T>::value is false when T is neither -// ::proto2::Message nor a sub-class of it. +// Tests that IsAProtocolMessage<T>::value is false when T doesn't have needed +// methods. TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) { EXPECT_FALSE(IsAProtocolMessage<int>::value); EXPECT_FALSE(IsAProtocolMessage<const ConversionHelperBase>::value); |