Fixes the explanation generated by many composite matchers (by Manuel Klimek); publishes the gmock value printer as testing::PrintToString() (by Zhanyong Wan).
This commit is contained in:
parent
a862f1de30
commit
676e8cc609
|
@ -453,6 +453,38 @@ Matcher<T> A();
|
||||||
// and MUST NOT BE USED IN USER CODE!!!
|
// and MUST NOT BE USED IN USER CODE!!!
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
// If the explanation is not empty, prints it to the listener.
|
||||||
|
// 'listener' must not be NULL.
|
||||||
|
inline void PrintIfNotEmpty(
|
||||||
|
const internal::string& explanation, MatchResultListener* listener) {
|
||||||
|
if (explanation != "") {
|
||||||
|
*listener << ", " << explanation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches the value against the given matcher, prints the value and explains
|
||||||
|
// the match result to the listener. Returns the match result.
|
||||||
|
// 'listener' must not be NULL.
|
||||||
|
// Value cannot be passed by const reference, because some matchers take a
|
||||||
|
// non-const argument.
|
||||||
|
template <typename Value, typename T>
|
||||||
|
bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher,
|
||||||
|
MatchResultListener* listener) {
|
||||||
|
if (!listener->IsInterested()) {
|
||||||
|
// If the listener is not interested, we do not need to construct the
|
||||||
|
// inner explanation.
|
||||||
|
return matcher.Matches(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringMatchResultListener inner_listener;
|
||||||
|
const bool match = matcher.MatchAndExplain(value, &inner_listener);
|
||||||
|
|
||||||
|
UniversalPrint(value, listener->stream());
|
||||||
|
PrintIfNotEmpty(inner_listener.str(), listener);
|
||||||
|
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
// If the given string is not empty and os is not NULL, wraps the
|
// If the given string is not empty and os is not NULL, wraps the
|
||||||
// string inside a pair of parentheses and streams the result to os.
|
// string inside a pair of parentheses and streams the result to os.
|
||||||
inline void StreamInParensAsNeeded(const internal::string& str,
|
inline void StreamInParensAsNeeded(const internal::string& str,
|
||||||
|
@ -1604,13 +1636,8 @@ class PointeeMatcher {
|
||||||
if (GetRawPointer(pointer) == NULL)
|
if (GetRawPointer(pointer) == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
StringMatchResultListener inner_listener;
|
*listener << "which points to ";
|
||||||
const bool match = matcher_.MatchAndExplain(*pointer, &inner_listener);
|
return MatchPrintAndExplain(*pointer, matcher_, listener);
|
||||||
const internal::string s = inner_listener.str();
|
|
||||||
if (s != "") {
|
|
||||||
*listener << "points to a value that " << s;
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1634,12 +1661,12 @@ class FieldMatcher {
|
||||||
: field_(field), matcher_(matcher) {}
|
: field_(field), matcher_(matcher) {}
|
||||||
|
|
||||||
void DescribeTo(::std::ostream* os) const {
|
void DescribeTo(::std::ostream* os) const {
|
||||||
*os << "the given field ";
|
*os << "is an object whose given field ";
|
||||||
matcher_.DescribeTo(os);
|
matcher_.DescribeTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescribeNegationTo(::std::ostream* os) const {
|
void DescribeNegationTo(::std::ostream* os) const {
|
||||||
*os << "the given field ";
|
*os << "is an object whose given field ";
|
||||||
matcher_.DescribeNegationTo(os);
|
matcher_.DescribeNegationTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1657,13 +1684,8 @@ class FieldMatcher {
|
||||||
// true_type iff the Field() matcher is used to match a pointer.
|
// true_type iff the Field() matcher is used to match a pointer.
|
||||||
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
StringMatchResultListener inner_listener;
|
*listener << "whose given field is ";
|
||||||
const bool match = matcher_.MatchAndExplain(obj.*field_, &inner_listener);
|
return MatchPrintAndExplain(obj.*field_, matcher_, listener);
|
||||||
const internal::string s = inner_listener.str();
|
|
||||||
if (s != "") {
|
|
||||||
*listener << "the given field " << s;
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
|
bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
|
||||||
|
@ -1671,6 +1693,7 @@ class FieldMatcher {
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
*listener << "which points to an object ";
|
||||||
// Since *p has a field, it must be a class/struct/union type and
|
// Since *p has a field, it must be a class/struct/union type and
|
||||||
// thus cannot be a pointer. Therefore we pass false_type() as
|
// thus cannot be a pointer. Therefore we pass false_type() as
|
||||||
// the first argument.
|
// the first argument.
|
||||||
|
@ -1699,12 +1722,12 @@ class PropertyMatcher {
|
||||||
: property_(property), matcher_(matcher) {}
|
: property_(property), matcher_(matcher) {}
|
||||||
|
|
||||||
void DescribeTo(::std::ostream* os) const {
|
void DescribeTo(::std::ostream* os) const {
|
||||||
*os << "the given property ";
|
*os << "is an object whose given property ";
|
||||||
matcher_.DescribeTo(os);
|
matcher_.DescribeTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescribeNegationTo(::std::ostream* os) const {
|
void DescribeNegationTo(::std::ostream* os) const {
|
||||||
*os << "the given property ";
|
*os << "is an object whose given property ";
|
||||||
matcher_.DescribeNegationTo(os);
|
matcher_.DescribeNegationTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1722,14 +1745,11 @@ class PropertyMatcher {
|
||||||
// true_type iff the Property() matcher is used to match a pointer.
|
// true_type iff the Property() matcher is used to match a pointer.
|
||||||
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
StringMatchResultListener inner_listener;
|
*listener << "whose given property is ";
|
||||||
const bool match = matcher_.MatchAndExplain((obj.*property_)(),
|
// Cannot pass the return value (for example, int) to MatchPrintAndExplain,
|
||||||
&inner_listener);
|
// which takes a non-const reference as argument.
|
||||||
const internal::string s = inner_listener.str();
|
RefToConstProperty result = (obj.*property_)();
|
||||||
if (s != "") {
|
return MatchPrintAndExplain(result, matcher_, listener);
|
||||||
*listener << "the given property " << s;
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
|
bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
|
||||||
|
@ -1737,6 +1757,7 @@ class PropertyMatcher {
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
*listener << "which points to an object ";
|
||||||
// Since *p has a property method, it must be a class/struct/union
|
// Since *p has a property method, it must be a class/struct/union
|
||||||
// type and thus cannot be a pointer. Therefore we pass
|
// type and thus cannot be a pointer. Therefore we pass
|
||||||
// false_type() as the first argument.
|
// false_type() as the first argument.
|
||||||
|
@ -1806,26 +1827,22 @@ class ResultOfMatcher {
|
||||||
: callable_(callable), matcher_(matcher) {}
|
: callable_(callable), matcher_(matcher) {}
|
||||||
|
|
||||||
virtual void DescribeTo(::std::ostream* os) const {
|
virtual void DescribeTo(::std::ostream* os) const {
|
||||||
*os << "result of the given callable ";
|
*os << "is mapped by the given callable to a value that ";
|
||||||
matcher_.DescribeTo(os);
|
matcher_.DescribeTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
*os << "result of the given callable ";
|
*os << "is mapped by the given callable to a value that ";
|
||||||
matcher_.DescribeNegationTo(os);
|
matcher_.DescribeNegationTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
|
virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
|
||||||
StringMatchResultListener inner_listener;
|
*listener << "which is mapped by the given callable to ";
|
||||||
const bool match = matcher_.MatchAndExplain(
|
// Cannot pass the return value (for example, int) to
|
||||||
CallableTraits<Callable>::template Invoke<T>(callable_, obj),
|
// MatchPrintAndExplain, which takes a non-const reference as argument.
|
||||||
&inner_listener);
|
ResultType result =
|
||||||
|
CallableTraits<Callable>::template Invoke<T>(callable_, obj);
|
||||||
const internal::string s = inner_listener.str();
|
return MatchPrintAndExplain(result, matcher_, listener);
|
||||||
if (s != "")
|
|
||||||
*listener << "result of the given callable " << s;
|
|
||||||
|
|
||||||
return match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -2098,39 +2115,50 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
|
||||||
// matches second_matcher.
|
// matches second_matcher.
|
||||||
virtual bool MatchAndExplain(PairType a_pair,
|
virtual bool MatchAndExplain(PairType a_pair,
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
StringMatchResultListener listener1;
|
if (!listener->IsInterested()) {
|
||||||
const bool match1 = first_matcher_.MatchAndExplain(a_pair.first,
|
// If the listener is not interested, we don't need to construct the
|
||||||
&listener1);
|
// explanation.
|
||||||
internal::string s1 = listener1.str();
|
return first_matcher_.Matches(a_pair.first) &&
|
||||||
if (s1 != "") {
|
second_matcher_.Matches(a_pair.second);
|
||||||
s1 = "the first field " + s1;
|
|
||||||
}
|
}
|
||||||
if (!match1) {
|
StringMatchResultListener first_inner_listener;
|
||||||
*listener << s1;
|
if (!first_matcher_.MatchAndExplain(a_pair.first,
|
||||||
|
&first_inner_listener)) {
|
||||||
|
*listener << "whose first field does not match";
|
||||||
|
PrintIfNotEmpty(first_inner_listener.str(), listener);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
StringMatchResultListener second_inner_listener;
|
||||||
StringMatchResultListener listener2;
|
if (!second_matcher_.MatchAndExplain(a_pair.second,
|
||||||
const bool match2 = second_matcher_.MatchAndExplain(a_pair.second,
|
&second_inner_listener)) {
|
||||||
&listener2);
|
*listener << "whose second field does not match";
|
||||||
internal::string s2 = listener2.str();
|
PrintIfNotEmpty(second_inner_listener.str(), listener);
|
||||||
if (s2 != "") {
|
|
||||||
s2 = "the second field " + s2;
|
|
||||||
}
|
|
||||||
if (!match2) {
|
|
||||||
*listener << s2;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(),
|
||||||
*listener << s1;
|
listener);
|
||||||
if (s1 != "" && s2 != "") {
|
|
||||||
*listener << ", and ";
|
|
||||||
}
|
|
||||||
*listener << s2;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ExplainSuccess(const internal::string& first_explanation,
|
||||||
|
const internal::string& second_explanation,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
*listener << "whose both fields match";
|
||||||
|
if (first_explanation != "") {
|
||||||
|
*listener << ", where the first field is a value " << first_explanation;
|
||||||
|
}
|
||||||
|
if (second_explanation != "") {
|
||||||
|
*listener << ", ";
|
||||||
|
if (first_explanation != "") {
|
||||||
|
*listener << "and ";
|
||||||
|
} else {
|
||||||
|
*listener << "where ";
|
||||||
|
}
|
||||||
|
*listener << "the second field is a value " << second_explanation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Matcher<const FirstType&> first_matcher_;
|
const Matcher<const FirstType&> first_matcher_;
|
||||||
const Matcher<const SecondType&> second_matcher_;
|
const Matcher<const SecondType&> second_matcher_;
|
||||||
|
|
||||||
|
|
|
@ -57,18 +57,20 @@
|
||||||
//
|
//
|
||||||
// We also provide some convenient wrappers:
|
// We also provide some convenient wrappers:
|
||||||
//
|
//
|
||||||
// // Prints a value as the given type to a string.
|
// // Prints a value to a string. For a (const or not) char
|
||||||
// string ::testing::internal::UniversalPrinter<T>::PrintToString(value);
|
// // pointer, the NUL-terminated string (but not the pointer) is
|
||||||
|
// // printed.
|
||||||
|
// std::string ::testing::PrintToString(const T& value);
|
||||||
//
|
//
|
||||||
// // Prints a value tersely: for a reference type, the referenced
|
// // Prints a value tersely: for a reference type, the referenced
|
||||||
// // value (but not the address) is printed; for a (const) char
|
// // value (but not the address) is printed; for a (const or not) char
|
||||||
// // pointer, the NUL-terminated string (but not the pointer) is
|
// // pointer, the NUL-terminated string (but not the pointer) is
|
||||||
// // printed.
|
// // printed.
|
||||||
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
|
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
|
||||||
//
|
//
|
||||||
// // Prints value using the type inferred by the compiler. The difference
|
// // Prints value using the type inferred by the compiler. The difference
|
||||||
// // from UniversalTersePrint() is that this function prints both the
|
// // from UniversalTersePrint() is that this function prints both the
|
||||||
// // pointer and the NUL-terminated string for a (const) char pointer.
|
// // pointer and the NUL-terminated string for a (const or not) char pointer.
|
||||||
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
|
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
|
||||||
//
|
//
|
||||||
// // Prints the fields of a tuple tersely to a string vector, one
|
// // Prints the fields of a tuple tersely to a string vector, one
|
||||||
|
@ -545,14 +547,6 @@ class UniversalPrinter {
|
||||||
PrintTo(value, os);
|
PrintTo(value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A convenient wrapper for Print() that returns the print-out as a
|
|
||||||
// string.
|
|
||||||
static string PrintToString(const T& value) {
|
|
||||||
::std::stringstream ss;
|
|
||||||
Print(value, &ss);
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop) // Restores the warning state.
|
#pragma warning(pop) // Restores the warning state.
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
@ -585,14 +579,6 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
|
||||||
// This overload prints a (const) char array compactly.
|
// This overload prints a (const) char array compactly.
|
||||||
void UniversalPrintArray(const char* begin, size_t len, ::std::ostream* os);
|
void UniversalPrintArray(const char* begin, size_t len, ::std::ostream* os);
|
||||||
|
|
||||||
// Prints an array of 'len' elements, starting at address 'begin', to a string.
|
|
||||||
template <typename T>
|
|
||||||
string UniversalPrintArrayToString(const T* begin, size_t len) {
|
|
||||||
::std::stringstream ss;
|
|
||||||
UniversalPrintArray(begin, len, &ss);
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements printing an array type T[N].
|
// Implements printing an array type T[N].
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
class UniversalPrinter<T[N]> {
|
class UniversalPrinter<T[N]> {
|
||||||
|
@ -602,12 +588,6 @@ class UniversalPrinter<T[N]> {
|
||||||
static void Print(const T (&a)[N], ::std::ostream* os) {
|
static void Print(const T (&a)[N], ::std::ostream* os) {
|
||||||
UniversalPrintArray(a, N, os);
|
UniversalPrintArray(a, N, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A convenient wrapper for Print() that returns the print-out as a
|
|
||||||
// string.
|
|
||||||
static string PrintToString(const T (&a)[N]) {
|
|
||||||
return UniversalPrintArrayToString(a, N);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements printing a reference type T&.
|
// Implements printing a reference type T&.
|
||||||
|
@ -630,14 +610,6 @@ class UniversalPrinter<T&> {
|
||||||
UniversalPrinter<T>::Print(value, os);
|
UniversalPrinter<T>::Print(value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A convenient wrapper for Print() that returns the print-out as a
|
|
||||||
// string.
|
|
||||||
static string PrintToString(const T& value) {
|
|
||||||
::std::stringstream ss;
|
|
||||||
Print(value, &ss);
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop) // Restores the warning state.
|
#pragma warning(pop) // Restores the warning state.
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
@ -740,6 +712,14 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
::std::string PrintToString(const T& value) {
|
||||||
|
::std::stringstream ss;
|
||||||
|
internal::UniversalTersePrint(value, &ss);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
||||||
|
|
|
@ -178,9 +178,7 @@ TEST(ArgsTest, CanMatchTupleByReference) {
|
||||||
|
|
||||||
// Validates that arg is printed as str.
|
// Validates that arg is printed as str.
|
||||||
MATCHER_P(PrintsAs, str, "") {
|
MATCHER_P(PrintsAs, str, "") {
|
||||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(arg_type)) RawTuple;
|
return testing::PrintToString(arg) == str;
|
||||||
return
|
|
||||||
testing::internal::UniversalPrinter<RawTuple>::PrintToString(arg) == str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ArgsTest, AcceptsTenTemplateArgs) {
|
TEST(ArgsTest, AcceptsTenTemplateArgs) {
|
||||||
|
|
|
@ -148,11 +148,11 @@ class GreaterThanMatcher : public MatcherInterface<int> {
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
const int diff = lhs - rhs_;
|
const int diff = lhs - rhs_;
|
||||||
if (diff > 0) {
|
if (diff > 0) {
|
||||||
*listener << "is " << diff << " more than " << rhs_;
|
*listener << "which is " << diff << " more than " << rhs_;
|
||||||
} else if (diff == 0) {
|
} else if (diff == 0) {
|
||||||
*listener << "is the same as " << rhs_;
|
*listener << "which is the same as " << rhs_;
|
||||||
} else {
|
} else {
|
||||||
*listener << "is " << -diff << " less than " << rhs_;
|
*listener << "which is " << -diff << " less than " << rhs_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lhs > rhs_;
|
return lhs > rhs_;
|
||||||
|
@ -320,11 +320,11 @@ TEST(MatcherTest, MatchAndExplain) {
|
||||||
Matcher<int> m = GreaterThan(0);
|
Matcher<int> m = GreaterThan(0);
|
||||||
StringMatchResultListener listener1;
|
StringMatchResultListener listener1;
|
||||||
EXPECT_TRUE(m.MatchAndExplain(42, &listener1));
|
EXPECT_TRUE(m.MatchAndExplain(42, &listener1));
|
||||||
EXPECT_EQ("is 42 more than 0", listener1.str());
|
EXPECT_EQ("which is 42 more than 0", listener1.str());
|
||||||
|
|
||||||
StringMatchResultListener listener2;
|
StringMatchResultListener listener2;
|
||||||
EXPECT_FALSE(m.MatchAndExplain(-9, &listener2));
|
EXPECT_FALSE(m.MatchAndExplain(-9, &listener2));
|
||||||
EXPECT_EQ("is 9 less than 0", listener2.str());
|
EXPECT_EQ("which is 9 less than 0", listener2.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that a C-string literal can be implicitly converted to a
|
// Tests that a C-string literal can be implicitly converted to a
|
||||||
|
@ -1180,23 +1180,38 @@ TEST(PairTest, CanExplainMatchResultTo) {
|
||||||
// If neither field matches, Pair() should explain about the first
|
// If neither field matches, Pair() should explain about the first
|
||||||
// field.
|
// field.
|
||||||
const Matcher<std::pair<int, int> > m = Pair(GreaterThan(0), GreaterThan(0));
|
const Matcher<std::pair<int, int> > m = Pair(GreaterThan(0), GreaterThan(0));
|
||||||
EXPECT_EQ("the first field is 1 less than 0",
|
EXPECT_EQ("whose first field does not match, which is 1 less than 0",
|
||||||
Explain(m, std::make_pair(-1, -2)));
|
Explain(m, std::make_pair(-1, -2)));
|
||||||
|
|
||||||
// If the first field matches but the second doesn't, Pair() should
|
// If the first field matches but the second doesn't, Pair() should
|
||||||
// explain about the second field.
|
// explain about the second field.
|
||||||
EXPECT_EQ("the second field is 2 less than 0",
|
EXPECT_EQ("whose second field does not match, which is 2 less than 0",
|
||||||
Explain(m, std::make_pair(1, -2)));
|
Explain(m, std::make_pair(1, -2)));
|
||||||
|
|
||||||
// If the first field doesn't match but the second does, Pair()
|
// If the first field doesn't match but the second does, Pair()
|
||||||
// should explain about the first field.
|
// should explain about the first field.
|
||||||
EXPECT_EQ("the first field is 1 less than 0",
|
EXPECT_EQ("whose first field does not match, which is 1 less than 0",
|
||||||
Explain(m, std::make_pair(-1, 2)));
|
Explain(m, std::make_pair(-1, 2)));
|
||||||
|
|
||||||
// If both fields match, Pair() should explain about them both.
|
// If both fields match, Pair() should explain about them both.
|
||||||
EXPECT_EQ("the first field is 1 more than 0"
|
EXPECT_EQ("whose both fields match, where the first field is a value "
|
||||||
", and the second field is 2 more than 0",
|
"which is 1 more than 0, and the second field is a value "
|
||||||
|
"which is 2 more than 0",
|
||||||
Explain(m, std::make_pair(1, 2)));
|
Explain(m, std::make_pair(1, 2)));
|
||||||
|
|
||||||
|
// If only the first match has an explanation, only this explanation should
|
||||||
|
// be printed.
|
||||||
|
const Matcher<std::pair<int, int> > explain_first = Pair(GreaterThan(0), 0);
|
||||||
|
EXPECT_EQ("whose both fields match, where the first field is a value "
|
||||||
|
"which is 1 more than 0",
|
||||||
|
Explain(explain_first, std::make_pair(1, 0)));
|
||||||
|
|
||||||
|
// If only the second match has an explanation, only this explanation should
|
||||||
|
// be printed.
|
||||||
|
const Matcher<std::pair<int, int> > explain_second = Pair(0, GreaterThan(0));
|
||||||
|
EXPECT_EQ("whose both fields match, where the second field is a value "
|
||||||
|
"which is 1 more than 0",
|
||||||
|
Explain(explain_second, std::make_pair(0, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PairTest, MatchesCorrectly) {
|
TEST(PairTest, MatchesCorrectly) {
|
||||||
|
@ -2544,7 +2559,14 @@ TEST(PointeeTest, CanExplainMatchResult) {
|
||||||
|
|
||||||
const Matcher<int*> m2 = Pointee(GreaterThan(1));
|
const Matcher<int*> m2 = Pointee(GreaterThan(1));
|
||||||
int n = 3;
|
int n = 3;
|
||||||
EXPECT_EQ("points to a value that is 2 more than 1", Explain(m2, &n));
|
EXPECT_EQ("which points to 3, which is 2 more than 1",
|
||||||
|
Explain(m2, &n));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(PointeeTest, AlwaysExplainsPointee) {
|
||||||
|
const Matcher<int*> m = Pointee(0);
|
||||||
|
int n = 42;
|
||||||
|
EXPECT_EQ("which points to 42", Explain(m, &n));
|
||||||
}
|
}
|
||||||
|
|
||||||
// An uncopyable class.
|
// An uncopyable class.
|
||||||
|
@ -2671,8 +2693,9 @@ TEST(FieldTest, WorksForCompatibleMatcherType) {
|
||||||
TEST(FieldTest, CanDescribeSelf) {
|
TEST(FieldTest, CanDescribeSelf) {
|
||||||
Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
|
Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
|
||||||
|
|
||||||
EXPECT_EQ("the given field is greater than or equal to 0", Describe(m));
|
EXPECT_EQ("is an object whose given field is greater than or equal to 0",
|
||||||
EXPECT_EQ("the given field is not greater than or equal to 0",
|
Describe(m));
|
||||||
|
EXPECT_EQ("is an object whose given field is not greater than or equal to 0",
|
||||||
DescribeNegation(m));
|
DescribeNegation(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2682,10 +2705,10 @@ TEST(FieldTest, CanExplainMatchResult) {
|
||||||
|
|
||||||
AStruct a;
|
AStruct a;
|
||||||
a.x = 1;
|
a.x = 1;
|
||||||
EXPECT_EQ("", Explain(m, a));
|
EXPECT_EQ("whose given field is 1", Explain(m, a));
|
||||||
|
|
||||||
m = Field(&AStruct::x, GreaterThan(0));
|
m = Field(&AStruct::x, GreaterThan(0));
|
||||||
EXPECT_EQ("the given field is 1 more than 0", Explain(m, a));
|
EXPECT_EQ("whose given field is 1, which is 1 more than 0", Explain(m, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that Field() works when the argument is a pointer to const.
|
// Tests that Field() works when the argument is a pointer to const.
|
||||||
|
@ -2741,8 +2764,9 @@ TEST(FieldForPointerTest, WorksForArgumentOfSubType) {
|
||||||
TEST(FieldForPointerTest, CanDescribeSelf) {
|
TEST(FieldForPointerTest, CanDescribeSelf) {
|
||||||
Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
|
Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
|
||||||
|
|
||||||
EXPECT_EQ("the given field is greater than or equal to 0", Describe(m));
|
EXPECT_EQ("is an object whose given field is greater than or equal to 0",
|
||||||
EXPECT_EQ("the given field is not greater than or equal to 0",
|
Describe(m));
|
||||||
|
EXPECT_EQ("is an object whose given field is not greater than or equal to 0",
|
||||||
DescribeNegation(m));
|
DescribeNegation(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2753,10 +2777,11 @@ TEST(FieldForPointerTest, CanExplainMatchResult) {
|
||||||
AStruct a;
|
AStruct a;
|
||||||
a.x = 1;
|
a.x = 1;
|
||||||
EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(NULL)));
|
EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(NULL)));
|
||||||
EXPECT_EQ("", Explain(m, &a));
|
EXPECT_EQ("which points to an object whose given field is 1", Explain(m, &a));
|
||||||
|
|
||||||
m = Field(&AStruct::x, GreaterThan(0));
|
m = Field(&AStruct::x, GreaterThan(0));
|
||||||
EXPECT_EQ("the given field is 1 more than 0", Explain(m, &a));
|
EXPECT_EQ("which points to an object whose given field is 1, "
|
||||||
|
"which is 1 more than 0", Explain(m, &a));
|
||||||
}
|
}
|
||||||
|
|
||||||
// A user-defined class for testing Property().
|
// A user-defined class for testing Property().
|
||||||
|
@ -2875,9 +2900,10 @@ TEST(PropertyTest, WorksForCompatibleMatcherType) {
|
||||||
TEST(PropertyTest, CanDescribeSelf) {
|
TEST(PropertyTest, CanDescribeSelf) {
|
||||||
Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
|
Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
|
||||||
|
|
||||||
EXPECT_EQ("the given property is greater than or equal to 0", Describe(m));
|
EXPECT_EQ("is an object whose given property is greater than or equal to 0",
|
||||||
EXPECT_EQ("the given property is not greater than or equal to 0",
|
Describe(m));
|
||||||
DescribeNegation(m));
|
EXPECT_EQ("is an object whose given property "
|
||||||
|
"is not greater than or equal to 0", DescribeNegation(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that Property() can explain the match result.
|
// Tests that Property() can explain the match result.
|
||||||
|
@ -2886,10 +2912,10 @@ TEST(PropertyTest, CanExplainMatchResult) {
|
||||||
|
|
||||||
AClass a;
|
AClass a;
|
||||||
a.set_n(1);
|
a.set_n(1);
|
||||||
EXPECT_EQ("", Explain(m, a));
|
EXPECT_EQ("whose given property is 1", Explain(m, a));
|
||||||
|
|
||||||
m = Property(&AClass::n, GreaterThan(0));
|
m = Property(&AClass::n, GreaterThan(0));
|
||||||
EXPECT_EQ("the given property is 1 more than 0", Explain(m, a));
|
EXPECT_EQ("whose given property is 1, which is 1 more than 0", Explain(m, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that Property() works when the argument is a pointer to const.
|
// Tests that Property() works when the argument is a pointer to const.
|
||||||
|
@ -2954,9 +2980,10 @@ TEST(PropertyForPointerTest, WorksForArgumentOfSubType) {
|
||||||
TEST(PropertyForPointerTest, CanDescribeSelf) {
|
TEST(PropertyForPointerTest, CanDescribeSelf) {
|
||||||
Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
|
Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
|
||||||
|
|
||||||
EXPECT_EQ("the given property is greater than or equal to 0", Describe(m));
|
EXPECT_EQ("is an object whose given property is greater than or equal to 0",
|
||||||
EXPECT_EQ("the given property is not greater than or equal to 0",
|
Describe(m));
|
||||||
DescribeNegation(m));
|
EXPECT_EQ("is an object whose given property "
|
||||||
|
"is not greater than or equal to 0", DescribeNegation(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that Property() can explain the result of matching a pointer.
|
// Tests that Property() can explain the result of matching a pointer.
|
||||||
|
@ -2966,10 +2993,12 @@ TEST(PropertyForPointerTest, CanExplainMatchResult) {
|
||||||
AClass a;
|
AClass a;
|
||||||
a.set_n(1);
|
a.set_n(1);
|
||||||
EXPECT_EQ("", Explain(m, static_cast<const AClass*>(NULL)));
|
EXPECT_EQ("", Explain(m, static_cast<const AClass*>(NULL)));
|
||||||
EXPECT_EQ("", Explain(m, &a));
|
EXPECT_EQ("which points to an object whose given property is 1",
|
||||||
|
Explain(m, &a));
|
||||||
|
|
||||||
m = Property(&AClass::n, GreaterThan(0));
|
m = Property(&AClass::n, GreaterThan(0));
|
||||||
EXPECT_EQ("the given property is 1 more than 0", Explain(m, &a));
|
EXPECT_EQ("which points to an object whose given property is 1, "
|
||||||
|
"which is 1 more than 0", Explain(m, &a));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests ResultOf.
|
// Tests ResultOf.
|
||||||
|
@ -2989,10 +3018,10 @@ TEST(ResultOfTest, WorksForFunctionPointers) {
|
||||||
TEST(ResultOfTest, CanDescribeItself) {
|
TEST(ResultOfTest, CanDescribeItself) {
|
||||||
Matcher<int> matcher = ResultOf(&IntToStringFunction, StrEq("foo"));
|
Matcher<int> matcher = ResultOf(&IntToStringFunction, StrEq("foo"));
|
||||||
|
|
||||||
EXPECT_EQ("result of the given callable is equal to \"foo\"",
|
EXPECT_EQ("is mapped by the given callable to a value that "
|
||||||
Describe(matcher));
|
"is equal to \"foo\"", Describe(matcher));
|
||||||
EXPECT_EQ("result of the given callable is not equal to \"foo\"",
|
EXPECT_EQ("is mapped by the given callable to a value that "
|
||||||
DescribeNegation(matcher));
|
"is not equal to \"foo\"", DescribeNegation(matcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that ResultOf() can explain the match result.
|
// Tests that ResultOf() can explain the match result.
|
||||||
|
@ -3000,11 +3029,12 @@ int IntFunction(int input) { return input == 42 ? 80 : 90; }
|
||||||
|
|
||||||
TEST(ResultOfTest, CanExplainMatchResult) {
|
TEST(ResultOfTest, CanExplainMatchResult) {
|
||||||
Matcher<int> matcher = ResultOf(&IntFunction, Ge(85));
|
Matcher<int> matcher = ResultOf(&IntFunction, Ge(85));
|
||||||
EXPECT_EQ("", Explain(matcher, 36));
|
EXPECT_EQ("which is mapped by the given callable to 90",
|
||||||
|
Explain(matcher, 36));
|
||||||
|
|
||||||
matcher = ResultOf(&IntFunction, GreaterThan(85));
|
matcher = ResultOf(&IntFunction, GreaterThan(85));
|
||||||
EXPECT_EQ("result of the given callable is 5 more than 85",
|
EXPECT_EQ("which is mapped by the given callable to 90, "
|
||||||
Explain(matcher, 36));
|
"which is 5 more than 85", Explain(matcher, 36));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
|
// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
|
||||||
|
@ -3202,7 +3232,7 @@ TEST(ExplainMatchResultTest, AllOf_True_True_2) {
|
||||||
|
|
||||||
TEST(ExplainmatcherResultTest, MonomorphicMatcher) {
|
TEST(ExplainmatcherResultTest, MonomorphicMatcher) {
|
||||||
const Matcher<int> m = GreaterThan(5);
|
const Matcher<int> m = GreaterThan(5);
|
||||||
EXPECT_EQ("is 1 more than 5", Explain(m, 6));
|
EXPECT_EQ("which is 1 more than 5", Explain(m, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following two tests verify that values without a public copy
|
// The following two tests verify that values without a public copy
|
||||||
|
|
|
@ -153,6 +153,7 @@ using ::std::tr1::make_tuple;
|
||||||
using ::std::tr1::tuple;
|
using ::std::tr1::tuple;
|
||||||
using ::std::vector;
|
using ::std::vector;
|
||||||
using ::testing::ElementsAre;
|
using ::testing::ElementsAre;
|
||||||
|
using ::testing::PrintToString;
|
||||||
using ::testing::StartsWith;
|
using ::testing::StartsWith;
|
||||||
using ::testing::internal::NativeArray;
|
using ::testing::internal::NativeArray;
|
||||||
using ::testing::internal::Strings;
|
using ::testing::internal::Strings;
|
||||||
|
@ -1010,19 +1011,24 @@ TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
|
||||||
+ " " + Print(sizeof(p)) + "-byte object "));
|
+ " " + Print(sizeof(p)) + "-byte object "));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintToStringTest, WorksForNonReference) {
|
TEST(PrintToStringTest, WorksForScalar) {
|
||||||
EXPECT_EQ("123", UniversalPrinter<int>::PrintToString(123));
|
EXPECT_EQ("123", PrintToString(123));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintToStringTest, WorksForReference) {
|
TEST(PrintToStringTest, WorksForPointerToConstChar) {
|
||||||
int n = 123;
|
const char* p = "hello";
|
||||||
EXPECT_EQ("@" + PrintPointer(&n) + " 123",
|
EXPECT_EQ("\"hello\"", PrintToString(p));
|
||||||
UniversalPrinter<const int&>::PrintToString(n));
|
}
|
||||||
|
|
||||||
|
TEST(PrintToStringTest, WorksForPointerToNonConstChar) {
|
||||||
|
char s[] = "hello";
|
||||||
|
char* p = s;
|
||||||
|
EXPECT_EQ("\"hello\"", PrintToString(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintToStringTest, WorksForArray) {
|
TEST(PrintToStringTest, WorksForArray) {
|
||||||
int n[3] = { 1, 2, 3 };
|
int n[3] = { 1, 2, 3 };
|
||||||
EXPECT_EQ("{ 1, 2, 3 }", UniversalPrinter<int[3]>::PrintToString(n));
|
EXPECT_EQ("{ 1, 2, 3 }", PrintToString(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UniversalTersePrintTest, WorksForNonReference) {
|
TEST(UniversalTersePrintTest, WorksForNonReference) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user