summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--googletest/include/gtest/internal/gtest-internal.h31
-rw-r--r--googletest/test/gtest_unittest.cc46
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);