From e5644f5f12ff3d5b2232dabc1c5ea272a52e8155 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 8 Dec 2020 12:37:32 -0500 Subject: [PATCH] Googletest export Introduce a new `Address` matcher to gmock. PiperOrigin-RevId: 346344591 --- googlemock/docs/cheat_sheet.md | 1 + googlemock/include/gmock/gmock-matchers.h | 51 +++++++++++++++++++++++ googlemock/test/gmock-matchers_test.cc | 40 ++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md index fcb9201a1e..dc2428efea 100644 --- a/googlemock/docs/cheat_sheet.md +++ b/googlemock/docs/cheat_sheet.md @@ -420,6 +420,7 @@ messages, you can use: | Matcher | Description | | :------------------------ | :---------------------------------------------- | +| `Address(m)` | the result of `std::addressof(argument)` matches `m`. | | `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(m)` | when `argument` is passed through `dynamic_cast()`, it matches matcher `m`. | diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index ae064b5da5..9641ed4264 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -2833,6 +2833,49 @@ class KeyMatcher { const M matcher_for_key_; }; +// Implements polymorphic Address(matcher_for_address). +template +class AddressMatcher { + public: + explicit AddressMatcher(InnerMatcher m) : matcher_(m) {} + + template + operator Matcher() const { // NOLINT + return Matcher(new Impl(matcher_)); + } + + private: + // The monomorphic implementation that works for a particular object type. + template + class Impl : public MatcherInterface { + public: + using Address = const GTEST_REMOVE_REFERENCE_AND_CONST_(Type) *; + explicit Impl(const InnerMatcher& matcher) + : matcher_(MatcherCast
(matcher)) {} + + void DescribeTo(::std::ostream* os) const override { + *os << "has address that "; + matcher_.DescribeTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "does not have address that "; + matcher_.DescribeTo(os); + } + + bool MatchAndExplain(Type object, + MatchResultListener* listener) const override { + *listener << "which has address "; + Address address = std::addressof(object); + return MatchPrintAndExplain(address, matcher_, listener); + } + + private: + const Matcher
matcher_; + }; + const InnerMatcher matcher_; +}; + // Implements Pair(first_matcher, second_matcher) for the given argument pair // type with its two matchers. See Pair() function below. template @@ -4787,6 +4830,14 @@ inline internal::PointerMatcher Pointer( const InnerMatcher& inner_matcher) { return internal::PointerMatcher(inner_matcher); } + +// Creates a matcher that matches an object that has an address that matches +// inner_matcher. +template +inline internal::AddressMatcher Address( + const InnerMatcher& inner_matcher) { + return internal::AddressMatcher(inner_matcher); +} } // namespace no_adl // Returns a predicate that is satisfied by anything that matches the diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 8084e29f1a..3ac166827c 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -3787,6 +3787,46 @@ TEST(PointerTest, SmartPointerToConst) { EXPECT_FALSE(m.Matches(p)); } +TEST(AddressTest, NonConst) { + int n = 1; + const Matcher m = Address(Eq(&n)); + + EXPECT_TRUE(m.Matches(n)); + + int other = 5; + + EXPECT_FALSE(m.Matches(other)); + + int& n_ref = n; + + EXPECT_TRUE(m.Matches(n_ref)); +} + +TEST(AddressTest, Const) { + const int n = 1; + const Matcher m = Address(Eq(&n)); + + EXPECT_TRUE(m.Matches(n)); + + int other = 5; + + EXPECT_FALSE(m.Matches(other)); +} + +TEST(AddressTest, MatcherDoesntCopy) { + std::unique_ptr n(new int(1)); + const Matcher> m = Address(Eq(&n)); + + EXPECT_TRUE(m.Matches(n)); +} + +TEST(AddressTest, Describe) { + Matcher matcher = Address(_); + EXPECT_EQ("has address that is anything", Describe(matcher)); + EXPECT_EQ("does not have address that is anything", + DescribeNegation(matcher)); +} + MATCHER_P(FieldIIs, inner_matcher, "") { return ExplainMatchResult(inner_matcher, arg.i, result_listener); }