diff options
author | Abseil Team <absl-team@google.com> | 2022-02-10 00:19:22 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-02-10 00:20:06 (GMT) |
commit | 0e402173c97aea7a00749e825b194bfede4f2e45 (patch) | |
tree | 17a54c2ff3dc4712c1bda8cf53db4c42bcdf26a7 | |
parent | 06519cedc3159de8b36a504766ad6b7966555f10 (diff) | |
download | googletest-0e402173c97aea7a00749e825b194bfede4f2e45.zip googletest-0e402173c97aea7a00749e825b194bfede4f2e45.tar.gz googletest-0e402173c97aea7a00749e825b194bfede4f2e45.tar.bz2 |
Add a 3-arg overload for ResultOf() matcher that takes a description string for better error messages.
PiperOrigin-RevId: 427598749
Change-Id: I8c7a5d7b2dde017641534f1c7eed8dd56c33e845
-rw-r--r-- | docs/reference/matchers.md | 1 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 43 | ||||
-rw-r--r-- | 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 47d2808..0f57db4 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 5cf5019..9584586 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -2206,13 +2206,21 @@ template <typename Callable, typename InnerMatcher> 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<Callable>::CheckIsValid(callable_); } template <typename T> operator Matcher<T>() const { - return Matcher<T>(new Impl<const T&>(callable_, matcher_)); + return Matcher<T>( + new Impl<const T&>(result_description_, callable_, matcher_)); } private: @@ -2225,16 +2233,27 @@ class ResultOfMatcher { public: template <typename M> - Impl(const CallableStorageType& callable, const M& matcher) - : callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {} + Impl(const std::string& result_description, + const CallableStorageType& callable, const M& matcher) + : result_description_(result_description), + callable_(callable), + matcher_(MatcherCast<ResultType>(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<ResultType> matcher_; }; // class Impl + const std::string result_description_; const CallableStorageType callable_; const InnerMatcher matcher_; }; @@ -4422,6 +4443,16 @@ internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf( std::move(matcher)); } +// Same as ResultOf() above, but also takes a description of the `callable` +// result to provide better error messages. +template <typename Callable, typename InnerMatcher> +internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf( + const std::string& result_description, Callable callable, + InnerMatcher matcher) { + return internal::ResultOfMatcher<Callable, InnerMatcher>( + 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 34282e6..6d480e0 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<int> 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; } |