Skip to content

Commit

Permalink
Googletest export
Browse files Browse the repository at this point in the history
Introduce a new `Address` matcher to gmock.

PiperOrigin-RevId: 346344591
  • Loading branch information
Abseil Team authored and suertreus committed Dec 9, 2020
1 parent 8779937 commit e5644f5
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions googlemock/docs/cheat_sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ messages, you can use:
<!-- mdformat off(no multiline tables) -->
| 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<T>(m)` | when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`. |
Expand Down
51 changes: 51 additions & 0 deletions googlemock/include/gmock/gmock-matchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2833,6 +2833,49 @@ class KeyMatcher {
const M matcher_for_key_;
};

// Implements polymorphic Address(matcher_for_address).
template <typename InnerMatcher>
class AddressMatcher {
public:
explicit AddressMatcher(InnerMatcher m) : matcher_(m) {}

template <typename Type>
operator Matcher<Type>() const { // NOLINT
return Matcher<Type>(new Impl<const Type&>(matcher_));
}

private:
// The monomorphic implementation that works for a particular object type.
template <typename Type>
class Impl : public MatcherInterface<Type> {
public:
using Address = const GTEST_REMOVE_REFERENCE_AND_CONST_(Type) *;
explicit Impl(const InnerMatcher& matcher)
: matcher_(MatcherCast<Address>(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<Address> 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 <typename PairType>
Expand Down Expand Up @@ -4787,6 +4830,14 @@ inline internal::PointerMatcher<InnerMatcher> Pointer(
const InnerMatcher& inner_matcher) {
return internal::PointerMatcher<InnerMatcher>(inner_matcher);
}

// Creates a matcher that matches an object that has an address that matches
// inner_matcher.
template <typename InnerMatcher>
inline internal::AddressMatcher<InnerMatcher> Address(
const InnerMatcher& inner_matcher) {
return internal::AddressMatcher<InnerMatcher>(inner_matcher);
}
} // namespace no_adl

// Returns a predicate that is satisfied by anything that matches the
Expand Down
40 changes: 40 additions & 0 deletions googlemock/test/gmock-matchers_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3787,6 +3787,46 @@ TEST(PointerTest, SmartPointerToConst) {
EXPECT_FALSE(m.Matches(p));
}

TEST(AddressTest, NonConst) {
int n = 1;
const Matcher<int> 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<int> m = Address(Eq(&n));

EXPECT_TRUE(m.Matches(n));

int other = 5;

EXPECT_FALSE(m.Matches(other));
}

TEST(AddressTest, MatcherDoesntCopy) {
std::unique_ptr<int> n(new int(1));
const Matcher<std::unique_ptr<int>> m = Address(Eq(&n));

EXPECT_TRUE(m.Matches(n));
}

TEST(AddressTest, Describe) {
Matcher<int> 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);
}
Expand Down

0 comments on commit e5644f5

Please sign in to comment.