summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Mauro <dmauro@google.com>2020-10-14 18:25:04 -0400
committerDerek Mauro <dmauro@google.com>2020-10-14 18:25:04 -0400
commit4abb012c70a20500967fa88b55f552a4267258dd (patch)
treebb61f8303a42b2e25dfce279a8e351f67f9466fd
parent07f4869221012b16b7f9ee685d94856e1fc9f361 (diff)
parent4c9ad191e14e5926ce0213d7dddb7a35529c2756 (diff)
downloadgoogletest-4abb012c70a20500967fa88b55f552a4267258dd.tar.gz
googletest-4abb012c70a20500967fa88b55f552a4267258dd.zip
Merge pull request #2837 from inazarenko:duck_type_protos
PiperOrigin-RevId: 336087297
-rw-r--r--googletest/include/gtest/gtest-printers.h5
-rw-r--r--googletest/include/gtest/internal/gtest-internal.h31
-rw-r--r--googletest/test/gtest_unittest.cc79
3 files changed, 93 insertions, 22 deletions
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 <typename T, typename = typename std::enable_if<
- internal::IsAProtocolMessage<T>::value>::type>
+ template <typename T,
+ typename = typename std::enable_if<
+ internal::HasDebugStringAndShortDebugString<T>::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<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.
+// HasDebugStringAndShortDebugString<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 HasDebugStringAndShortDebugString {
+ 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 HasDebugStringAndShortDebugString<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 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<T>::value is a compile-time constant.
-TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) {
- GTEST_COMPILE_ASSERT_(IsAProtocolMessage<::proto2::MessageLite>::value,
- const_true);
- GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<int>::value, const_false);
-}
+struct HasDebugStringMethods {
+ std::string DebugString() const { return ""; }
+ std::string ShortDebugString() const { return ""; }
+};
+
+struct InheritsDebugStringMethods : public HasDebugStringMethods {};
-// Tests that IsAProtocolMessage<T>::value is true when T is
-// proto2::Message or a sub-class of it.
-TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) {
- EXPECT_TRUE(IsAProtocolMessage<::proto2::MessageLite>::value);
+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<T>::value is a compile-time
+// constant.
+TEST(HasDebugStringAndShortDebugStringTest, ValueIsCompileTimeConstant) {
+ GTEST_COMPILE_ASSERT_(
+ HasDebugStringAndShortDebugString<HasDebugStringMethods>::value,
+ const_true);
+ GTEST_COMPILE_ASSERT_(
+ HasDebugStringAndShortDebugString<InheritsDebugStringMethods>::value,
+ const_true);
+ GTEST_COMPILE_ASSERT_(HasDebugStringAndShortDebugString<
+ const InheritsDebugStringMethods>::value,
+ const_true);
+ GTEST_COMPILE_ASSERT_(
+ !HasDebugStringAndShortDebugString<WrongTypeDebugStringMethod>::value,
+ const_false);
+ GTEST_COMPILE_ASSERT_(
+ !HasDebugStringAndShortDebugString<NotConstDebugStringMethod>::value,
+ const_false);
+ GTEST_COMPILE_ASSERT_(
+ !HasDebugStringAndShortDebugString<MissingDebugStringMethod>::value,
+ const_false);
+ GTEST_COMPILE_ASSERT_(
+ !HasDebugStringAndShortDebugString<IncompleteType>::value, const_false);
+ GTEST_COMPILE_ASSERT_(!HasDebugStringAndShortDebugString<int>::value,
+ const_false);
+}
+
+// Tests that HasDebugStringAndShortDebugString<T>::value is true when T has
+// needed methods.
+TEST(HasDebugStringAndShortDebugStringTest,
+ ValueIsTrueWhenTypeHasDebugStringAndShortDebugString) {
+ EXPECT_TRUE(
+ HasDebugStringAndShortDebugString<InheritsDebugStringMethods>::value);
}
-// Tests that IsAProtocolMessage<T>::value is false when T is neither
-// ::proto2::Message nor a sub-class of it.
-TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) {
- EXPECT_FALSE(IsAProtocolMessage<int>::value);
- EXPECT_FALSE(IsAProtocolMessage<const ConversionHelperBase>::value);
+// Tests that HasDebugStringAndShortDebugString<T>::value is false when T
+// doesn't have needed methods.
+TEST(HasDebugStringAndShortDebugStringTest,
+ ValueIsFalseWhenTypeIsNotAProtocolMessage) {
+ EXPECT_FALSE(HasDebugStringAndShortDebugString<int>::value);
+ EXPECT_FALSE(
+ HasDebugStringAndShortDebugString<const ConversionHelperBase>::value);
}
// Tests GTEST_REMOVE_REFERENCE_AND_CONST_.
OpenPOWER on IntegriCloud