summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2022-02-10 00:19:22 (GMT)
committerCopybara-Service <copybara-worker@google.com>2022-02-10 00:20:06 (GMT)
commit0e402173c97aea7a00749e825b194bfede4f2e45 (patch)
tree17a54c2ff3dc4712c1bda8cf53db4c42bcdf26a7
parent06519cedc3159de8b36a504766ad6b7966555f10 (diff)
downloadgoogletest-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.md1
-rw-r--r--googlemock/include/gmock/gmock-matchers.h43
-rw-r--r--googlemock/test/gmock-matchers_test.cc10
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; }