From 0e402173c97aea7a00749e825b194bfede4f2e45 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 9 Feb 2022 16:19:22 -0800 Subject: [PATCH] Add a 3-arg overload for ResultOf() matcher that takes a description string for better error messages. PiperOrigin-RevId: 427598749 Change-Id: I8c7a5d7b2dde017641534f1c7eed8dd56c33e845 --- docs/reference/matchers.md | 1 + googlemock/include/gmock/gmock-matchers.h | 43 +++++++++++++++++++---- googlemock/test/gmock-matchers_test.cc | 10 ++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/docs/reference/matchers.md b/docs/reference/matchers.md index 47d2808c3b..0f57db4718 100644 --- a/docs/reference/matchers.md +++ b/docs/reference/matchers.md @@ -194,6 +194,7 @@ messages, you can use: | Matcher | Description | | :--------------- | :------------------------------------------------ | | `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. | +| `ResultOf(result_description, f, m)` | The same as the two-parameter version, but provides a better error message. ## Pointer Matchers diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 5cf5019d52..9584586481 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -2206,13 +2206,21 @@ template class ResultOfMatcher { public: ResultOfMatcher(Callable callable, InnerMatcher matcher) - : callable_(std::move(callable)), matcher_(std::move(matcher)) { + : ResultOfMatcher(/*result_description=*/"", std::move(callable), + std::move(matcher)) {} + + ResultOfMatcher(const std::string& result_description, Callable callable, + InnerMatcher matcher) + : result_description_(result_description), + callable_(std::move(callable)), + matcher_(std::move(matcher)) { CallableTraits::CheckIsValid(callable_); } template operator Matcher() const { - return Matcher(new Impl(callable_, matcher_)); + return Matcher( + new Impl(result_description_, callable_, matcher_)); } private: @@ -2225,16 +2233,27 @@ class ResultOfMatcher { public: template - Impl(const CallableStorageType& callable, const M& matcher) - : callable_(callable), matcher_(MatcherCast(matcher)) {} + Impl(const std::string& result_description, + const CallableStorageType& callable, const M& matcher) + : result_description_(result_description), + callable_(callable), + matcher_(MatcherCast(matcher)) {} void DescribeTo(::std::ostream* os) const override { - *os << "is mapped by the given callable to a value that "; + if (result_description_.empty()) { + *os << "is mapped by the given callable to a value that "; + } else { + *os << "whose " << result_description_ << " "; + } matcher_.DescribeTo(os); } void DescribeNegationTo(::std::ostream* os) const override { - *os << "is mapped by the given callable to a value that "; + if (result_description_.empty()) { + *os << "is mapped by the given callable to a value that "; + } else { + *os << "whose " << result_description_ << " "; + } matcher_.DescribeNegationTo(os); } @@ -2250,6 +2269,7 @@ class ResultOfMatcher { } private: + const std::string result_description_; // Functors often define operator() as non-const method even though // they are actually stateless. But we need to use them even when // 'this' is a const pointer. It's the user's responsibility not to @@ -2259,6 +2279,7 @@ class ResultOfMatcher { const Matcher matcher_; }; // class Impl + const std::string result_description_; const CallableStorageType callable_; const InnerMatcher matcher_; }; @@ -4422,6 +4443,16 @@ internal::ResultOfMatcher ResultOf( std::move(matcher)); } +// Same as ResultOf() above, but also takes a description of the `callable` +// result to provide better error messages. +template +internal::ResultOfMatcher ResultOf( + const std::string& result_description, Callable callable, + InnerMatcher matcher) { + return internal::ResultOfMatcher( + result_description, std::move(callable), std::move(matcher)); +} + // String matchers. // Matches a string equal to str. diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 34282e6fe7..6d480e0e3c 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -4643,6 +4643,16 @@ TEST(ResultOfTest, CanDescribeItself) { "isn't equal to \"foo\"", DescribeNegation(matcher)); } +// Tests that ResultOf() can describe itself when provided a result description. +TEST(ResultOfTest, CanDescribeItselfWithResultDescription) { + Matcher matcher = + ResultOf("string conversion", &IntToStringFunction, StrEq("foo")); + + EXPECT_EQ("whose string conversion is equal to \"foo\"", Describe(matcher)); + EXPECT_EQ("whose string conversion isn't equal to \"foo\"", + DescribeNegation(matcher)); +} + // Tests that ResultOf() can explain the match result. int IntFunction(int input) { return input == 42 ? 80 : 90; }