Skip to content

Commit

Permalink
Detect proto messages based on presense of DebugString.
Browse files Browse the repository at this point in the history
  • Loading branch information
inazarenko committed May 5, 2020
1 parent 0eea2e9 commit 4c9ad19
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 10 deletions.
31 changes: 27 additions & 4 deletions googletest/include/gtest/internal/gtest-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
46 changes: 40 additions & 6 deletions googletest/test/gtest_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4c9ad19

Please sign in to comment.