summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2020-12-07 16:17:26 -0500
committerAndy Getz <durandal@google.com>2020-12-07 18:04:12 -0500
commita02a591605dfef9addde49634bf010dbe8f95c50 (patch)
tree6258f1a86109731e61e328b5eac6cdce89146f85
parent7bf5057a04eebb12cb731bfd6b3a19c510dc5087 (diff)
downloadgoogletest-a02a591605dfef9addde49634bf010dbe8f95c50.tar.gz
googletest-a02a591605dfef9addde49634bf010dbe8f95c50.zip
Googletest export
Add a `Pointer` matcher as an analog to `Pointee`. Similar to `Pointee`, `Pointer` works with either raw or smart pointers and allows creating a matcher like Pointer(Eq(foo)) for smart pointers. PiperOrigin-RevId: 346164768
-rw-r--r--googlemock/docs/cheat_sheet.md1
-rw-r--r--googlemock/include/gmock/gmock-matchers.h71
-rw-r--r--googlemock/include/gmock/internal/gmock-internal-utils.h17
-rw-r--r--googlemock/test/gmock-internal-utils_test.cc14
-rw-r--r--googlemock/test/gmock-matchers_test.cc59
5 files changed, 131 insertions, 31 deletions
diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md
index bcb4ce94..fcb9201a 100644
--- a/googlemock/docs/cheat_sheet.md
+++ b/googlemock/docs/cheat_sheet.md
@@ -421,6 +421,7 @@ messages, you can use:
| Matcher | Description |
| :------------------------ | :---------------------------------------------- |
| `Pointee(m)` | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. |
+| `Pointer(m)` | `argument` (either a smart pointer or a raw pointer) contains a pointer that matches `m`. `m` will match against the raw pointer regardless of the type of `argument`. |
| `WhenDynamicCastTo<T>(m)` | when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`. |
<!-- mdformat on -->
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index d12d7bf7..ae064b5d 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -1841,8 +1841,9 @@ class PointeeMatcher {
template <typename Pointer>
class Impl : public MatcherInterface<Pointer> {
public:
- typedef typename PointeeOf<GTEST_REMOVE_REFERENCE_AND_CONST_(Pointer)>::type
- Pointee;
+ using Pointee =
+ typename std::pointer_traits<GTEST_REMOVE_REFERENCE_AND_CONST_(
+ Pointer)>::element_type;
explicit Impl(const InnerMatcher& matcher)
: matcher_(MatcherCast<const Pointee&>(matcher)) {}
@@ -1872,6 +1873,64 @@ class PointeeMatcher {
const InnerMatcher matcher_;
};
+// Implements the Pointer(m) matcher
+// Implements the Pointer(m) matcher for matching a pointer that matches matcher
+// m. The pointer can be either raw or smart, and will match `m` against the
+// raw pointer.
+template <typename InnerMatcher>
+class PointerMatcher {
+ public:
+ explicit PointerMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
+
+ // This type conversion operator template allows Pointer(m) to be
+ // used as a matcher for any pointer type whose pointer type is
+ // compatible with the inner matcher, where type PointerType can be
+ // either a raw pointer or a smart pointer.
+ //
+ // The reason we do this instead of relying on
+ // MakePolymorphicMatcher() is that the latter is not flexible
+ // enough for implementing the DescribeTo() method of Pointer().
+ template <typename PointerType>
+ operator Matcher<PointerType>() const { // NOLINT
+ return Matcher<PointerType>(new Impl<const PointerType&>(matcher_));
+ }
+
+ private:
+ // The monomorphic implementation that works for a particular pointer type.
+ template <typename PointerType>
+ class Impl : public MatcherInterface<PointerType> {
+ public:
+ using Pointer =
+ const typename std::pointer_traits<GTEST_REMOVE_REFERENCE_AND_CONST_(
+ PointerType)>::element_type*;
+
+ explicit Impl(const InnerMatcher& matcher)
+ : matcher_(MatcherCast<Pointer>(matcher)) {}
+
+ void DescribeTo(::std::ostream* os) const override {
+ *os << "is a pointer that ";
+ matcher_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(::std::ostream* os) const override {
+ *os << "is not a pointer that ";
+ matcher_.DescribeTo(os);
+ }
+
+ bool MatchAndExplain(PointerType pointer,
+ MatchResultListener* listener) const override {
+ *listener << "which is a pointer that ";
+ Pointer p = GetRawPointer(pointer);
+ return MatchPrintAndExplain(p, matcher_, listener);
+ }
+
+ private:
+ Matcher<Pointer> matcher_;
+ };
+
+ const InnerMatcher matcher_;
+};
+
#if GTEST_HAS_RTTI
// Implements the WhenDynamicCastTo<T>(m) matcher that matches a pointer or
// reference that matches inner_matcher when dynamic_cast<T> is applied.
@@ -4720,6 +4779,14 @@ internal::FieldsAreMatcher<typename std::decay<M>::type...> FieldsAre(
return internal::FieldsAreMatcher<typename std::decay<M>::type...>(
std::forward<M>(matchers)...);
}
+
+// Creates a matcher that matches a pointer (raw or smart) that matches
+// inner_matcher.
+template <typename InnerMatcher>
+inline internal::PointerMatcher<InnerMatcher> Pointer(
+ const InnerMatcher& inner_matcher) {
+ return internal::PointerMatcher<InnerMatcher>(inner_matcher);
+}
} // namespace no_adl
// Returns a predicate that is satisfied by anything that matches the
diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h
index 5580dcb3..200c30e4 100644
--- a/googlemock/include/gmock/internal/gmock-internal-utils.h
+++ b/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -71,20 +71,6 @@ GTEST_API_ std::string JoinAsTuple(const Strings& fields);
// "foo_bar_123" are converted to "foo bar 123".
GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name);
-// PointeeOf<Pointer>::type is the type of a value pointed to by a
-// Pointer, which can be either a smart pointer or a raw pointer. The
-// following default implementation is for the case where Pointer is a
-// smart pointer.
-template <typename Pointer>
-struct PointeeOf {
- // Smart pointer classes define type element_type as the type of
- // their pointees.
- typedef typename Pointer::element_type type;
-};
-// This specialization is for the raw pointer case.
-template <typename T>
-struct PointeeOf<T*> { typedef T type; }; // NOLINT
-
// GetRawPointer(p) returns the raw pointer underlying p when p is a
// smart pointer, or returns p itself when p is already a raw pointer.
// The following default implementation is for the smart pointer case.
@@ -378,7 +364,8 @@ template <typename ElementPointer, typename Size>
class StlContainerView< ::std::tuple<ElementPointer, Size> > {
public:
typedef typename std::remove_const<
- typename internal::PointeeOf<ElementPointer>::type>::type RawElement;
+ typename std::pointer_traits<ElementPointer>::element_type>::type
+ RawElement;
typedef internal::NativeArray<RawElement> type;
typedef const type const_reference;
diff --git a/googlemock/test/gmock-internal-utils_test.cc b/googlemock/test/gmock-internal-utils_test.cc
index 8019f4a3..0d15e8f4 100644
--- a/googlemock/test/gmock-internal-utils_test.cc
+++ b/googlemock/test/gmock-internal-utils_test.cc
@@ -124,20 +124,6 @@ TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameIsMixture) {
ConvertIdentifierNameToWords("_Chapter11Section_1_"));
}
-TEST(PointeeOfTest, WorksForSmartPointers) {
- EXPECT_TRUE(
- (std::is_same<int, PointeeOf<std::unique_ptr<int>>::type>::value));
- EXPECT_TRUE(
- (std::is_same<std::string,
- PointeeOf<std::shared_ptr<std::string>>::type>::value));
-}
-
-TEST(PointeeOfTest, WorksForRawPointers) {
- EXPECT_TRUE((std::is_same<int, PointeeOf<int*>::type>::value));
- EXPECT_TRUE((std::is_same<const char, PointeeOf<const char*>::type>::value));
- EXPECT_TRUE((std::is_void<PointeeOf<void*>::type>::value));
-}
-
TEST(GetRawPointerTest, WorksForSmartPointers) {
const char* const raw_p1 = new const char('a'); // NOLINT
const std::unique_ptr<const char> p1(raw_p1);
diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc
index e6923195..8084e29f 100644
--- a/googlemock/test/gmock-matchers_test.cc
+++ b/googlemock/test/gmock-matchers_test.cc
@@ -3728,6 +3728,65 @@ TEST(PointeeTest, ReferenceToNonConstRawPointer) {
EXPECT_FALSE(m.Matches(p));
}
+TEST(PointeeTest, SmartPointer) {
+ const Matcher<std::unique_ptr<int>> m = Pointee(Ge(0));
+
+ std::unique_ptr<int> n(new int(1));
+ EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(PointeeTest, SmartPointerToConst) {
+ const Matcher<std::unique_ptr<const int>> m = Pointee(Ge(0));
+
+ // There's no implicit conversion from unique_ptr<int> to const
+ // unique_ptr<const int>, so we must pass a unique_ptr<const int> into the
+ // matcher.
+ std::unique_ptr<const int> n(new int(1));
+ EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(PointerTest, RawPointer) {
+ int n = 1;
+ const Matcher<int*> m = Pointer(Eq(&n));
+
+ EXPECT_TRUE(m.Matches(&n));
+
+ int* p = nullptr;
+ EXPECT_FALSE(m.Matches(p));
+ EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointerTest, RawPointerToConst) {
+ int n = 1;
+ const Matcher<const int*> m = Pointer(Eq(&n));
+
+ EXPECT_TRUE(m.Matches(&n));
+
+ int* p = nullptr;
+ EXPECT_FALSE(m.Matches(p));
+ EXPECT_FALSE(m.Matches(nullptr));
+}
+
+TEST(PointerTest, SmartPointer) {
+ std::unique_ptr<int> n(new int(10));
+ int* raw_n = n.get();
+ const Matcher<std::unique_ptr<int>> m = Pointer(Eq(raw_n));
+
+ EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(PointerTest, SmartPointerToConst) {
+ std::unique_ptr<const int> n(new int(10));
+ const int* raw_n = n.get();
+ const Matcher<std::unique_ptr<const int>> m = Pointer(Eq(raw_n));
+
+ // There's no implicit conversion from unique_ptr<int> to const
+ // unique_ptr<const int>, so we must pass a unique_ptr<const int> into the
+ // matcher.
+ std::unique_ptr<const int> p(new int(10));
+ EXPECT_FALSE(m.Matches(p));
+}
+
MATCHER_P(FieldIIs, inner_matcher, "") {
return ExplainMatchResult(inner_matcher, arg.i, result_listener);
}
OpenPOWER on IntegriCloud