Add a 3-arg overload for ResultOf() matcher that takes a description string for better error messages.
PiperOrigin-RevId: 427598749 Change-Id: I8c7a5d7b2dde017641534f1c7eed8dd56c33e845
This commit is contained in:
parent
06519cedc3
commit
0e402173c9
@ -194,6 +194,7 @@ messages, you can use:
|
|||||||
| Matcher | Description |
|
| Matcher | Description |
|
||||||
| :--------------- | :------------------------------------------------ |
|
| :--------------- | :------------------------------------------------ |
|
||||||
| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. |
|
| `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
|
## Pointer Matchers
|
||||||
|
|
||||||
|
@ -2206,13 +2206,21 @@ template <typename Callable, typename InnerMatcher>
|
|||||||
class ResultOfMatcher {
|
class ResultOfMatcher {
|
||||||
public:
|
public:
|
||||||
ResultOfMatcher(Callable callable, InnerMatcher matcher)
|
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_);
|
CallableTraits<Callable>::CheckIsValid(callable_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
operator Matcher<T>() const {
|
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:
|
private:
|
||||||
@ -2225,16 +2233,27 @@ class ResultOfMatcher {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename M>
|
template <typename M>
|
||||||
Impl(const CallableStorageType& callable, const M& matcher)
|
Impl(const std::string& result_description,
|
||||||
: callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {}
|
const CallableStorageType& callable, const M& matcher)
|
||||||
|
: result_description_(result_description),
|
||||||
|
callable_(callable),
|
||||||
|
matcher_(MatcherCast<ResultType>(matcher)) {}
|
||||||
|
|
||||||
void DescribeTo(::std::ostream* os) const override {
|
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);
|
matcher_.DescribeTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescribeNegationTo(::std::ostream* os) const override {
|
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);
|
matcher_.DescribeNegationTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2250,6 +2269,7 @@ class ResultOfMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const std::string result_description_;
|
||||||
// Functors often define operator() as non-const method even though
|
// Functors often define operator() as non-const method even though
|
||||||
// they are actually stateless. But we need to use them even when
|
// 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
|
// 'this' is a const pointer. It's the user's responsibility not to
|
||||||
@ -2259,6 +2279,7 @@ class ResultOfMatcher {
|
|||||||
const Matcher<ResultType> matcher_;
|
const Matcher<ResultType> matcher_;
|
||||||
}; // class Impl
|
}; // class Impl
|
||||||
|
|
||||||
|
const std::string result_description_;
|
||||||
const CallableStorageType callable_;
|
const CallableStorageType callable_;
|
||||||
const InnerMatcher matcher_;
|
const InnerMatcher matcher_;
|
||||||
};
|
};
|
||||||
@ -4422,6 +4443,16 @@ internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
|
|||||||
std::move(matcher));
|
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.
|
// String matchers.
|
||||||
|
|
||||||
// Matches a string equal to str.
|
// Matches a string equal to str.
|
||||||
|
@ -4643,6 +4643,16 @@ TEST(ResultOfTest, CanDescribeItself) {
|
|||||||
"isn't equal to \"foo\"", DescribeNegation(matcher));
|
"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.
|
// Tests that ResultOf() can explain the match result.
|
||||||
int IntFunction(int input) { return input == 42 ? 80 : 90; }
|
int IntFunction(int input) { return input == 42 ? 80 : 90; }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user