aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/gmock/gmock-matchers.h152
-rw-r--r--include/gmock/gmock-printers.h48
2 files changed, 104 insertions, 96 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 8dba440a..9a1bab24 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -453,6 +453,38 @@ Matcher<T> A();
// and MUST NOT BE USED IN USER CODE!!!
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
// string inside a pair of parentheses and streams the result to os.
inline void StreamInParensAsNeeded(const internal::string& str,
@@ -1604,13 +1636,8 @@ class PointeeMatcher {
if (GetRawPointer(pointer) == NULL)
return false;
- StringMatchResultListener inner_listener;
- const bool match = matcher_.MatchAndExplain(*pointer, &inner_listener);
- const internal::string s = inner_listener.str();
- if (s != "") {
- *listener << "points to a value that " << s;
- }
- return match;
+ *listener << "which points to ";
+ return MatchPrintAndExplain(*pointer, matcher_, listener);
}
private:
@@ -1634,12 +1661,12 @@ class FieldMatcher {
: field_(field), matcher_(matcher) {}
void DescribeTo(::std::ostream* os) const {
- *os << "the given field ";
+ *os << "is an object whose given field ";
matcher_.DescribeTo(os);
}
void DescribeNegationTo(::std::ostream* os) const {
- *os << "the given field ";
+ *os << "is an object whose given field ";
matcher_.DescribeNegationTo(os);
}
@@ -1657,13 +1684,8 @@ class FieldMatcher {
// true_type iff the Field() matcher is used to match a pointer.
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
MatchResultListener* listener) const {
- StringMatchResultListener inner_listener;
- const bool match = matcher_.MatchAndExplain(obj.*field_, &inner_listener);
- const internal::string s = inner_listener.str();
- if (s != "") {
- *listener << "the given field " << s;
- }
- return match;
+ *listener << "whose given field is ";
+ return MatchPrintAndExplain(obj.*field_, matcher_, listener);
}
bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
@@ -1671,6 +1693,7 @@ class FieldMatcher {
if (p == NULL)
return false;
+ *listener << "which points to an object ";
// 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
// the first argument.
@@ -1699,12 +1722,12 @@ class PropertyMatcher {
: property_(property), matcher_(matcher) {}
void DescribeTo(::std::ostream* os) const {
- *os << "the given property ";
+ *os << "is an object whose given property ";
matcher_.DescribeTo(os);
}
void DescribeNegationTo(::std::ostream* os) const {
- *os << "the given property ";
+ *os << "is an object whose given property ";
matcher_.DescribeNegationTo(os);
}
@@ -1722,14 +1745,11 @@ class PropertyMatcher {
// true_type iff the Property() matcher is used to match a pointer.
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
MatchResultListener* listener) const {
- StringMatchResultListener inner_listener;
- const bool match = matcher_.MatchAndExplain((obj.*property_)(),
- &inner_listener);
- const internal::string s = inner_listener.str();
- if (s != "") {
- *listener << "the given property " << s;
- }
- return match;
+ *listener << "whose given property is ";
+ // Cannot pass the return value (for example, int) to MatchPrintAndExplain,
+ // which takes a non-const reference as argument.
+ RefToConstProperty result = (obj.*property_)();
+ return MatchPrintAndExplain(result, matcher_, listener);
}
bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
@@ -1737,6 +1757,7 @@ class PropertyMatcher {
if (p == NULL)
return false;
+ *listener << "which points to an object ";
// Since *p has a property method, it must be a class/struct/union
// type and thus cannot be a pointer. Therefore we pass
// false_type() as the first argument.
@@ -1806,26 +1827,22 @@ class ResultOfMatcher {
: callable_(callable), matcher_(matcher) {}
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);
}
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);
}
virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
- StringMatchResultListener inner_listener;
- const bool match = matcher_.MatchAndExplain(
- CallableTraits<Callable>::template Invoke<T>(callable_, obj),
- &inner_listener);
-
- const internal::string s = inner_listener.str();
- if (s != "")
- *listener << "result of the given callable " << s;
-
- return match;
+ *listener << "which is mapped by the given callable to ";
+ // Cannot pass the return value (for example, int) to
+ // MatchPrintAndExplain, which takes a non-const reference as argument.
+ ResultType result =
+ CallableTraits<Callable>::template Invoke<T>(callable_, obj);
+ return MatchPrintAndExplain(result, matcher_, listener);
}
private:
@@ -2098,39 +2115,50 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
// matches second_matcher.
virtual bool MatchAndExplain(PairType a_pair,
MatchResultListener* listener) const {
- StringMatchResultListener listener1;
- const bool match1 = first_matcher_.MatchAndExplain(a_pair.first,
- &listener1);
- internal::string s1 = listener1.str();
- if (s1 != "") {
- s1 = "the first field " + s1;
+ if (!listener->IsInterested()) {
+ // If the listener is not interested, we don't need to construct the
+ // explanation.
+ return first_matcher_.Matches(a_pair.first) &&
+ second_matcher_.Matches(a_pair.second);
}
- if (!match1) {
- *listener << s1;
+ StringMatchResultListener first_inner_listener;
+ 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;
}
-
- StringMatchResultListener listener2;
- const bool match2 = second_matcher_.MatchAndExplain(a_pair.second,
- &listener2);
- internal::string s2 = listener2.str();
- if (s2 != "") {
- s2 = "the second field " + s2;
- }
- if (!match2) {
- *listener << s2;
+ StringMatchResultListener second_inner_listener;
+ if (!second_matcher_.MatchAndExplain(a_pair.second,
+ &second_inner_listener)) {
+ *listener << "whose second field does not match";
+ PrintIfNotEmpty(second_inner_listener.str(), listener);
return false;
}
-
- *listener << s1;
- if (s1 != "" && s2 != "") {
- *listener << ", and ";
- }
- *listener << s2;
+ ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(),
+ listener);
return true;
}
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 SecondType&> second_matcher_;
diff --git a/include/gmock/gmock-printers.h b/include/gmock/gmock-printers.h
index cda3545a..d1cd03ca 100644
--- a/include/gmock/gmock-printers.h
+++ b/include/gmock/gmock-printers.h
@@ -57,18 +57,20 @@
//
// We also provide some convenient wrappers:
//
-// // Prints a value as the given type to a string.
-// string ::testing::internal::UniversalPrinter<T>::PrintToString(value);
+// // Prints a value to a string. For a (const or not) char
+// // 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
-// // 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
// // printed.
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
//
// // Prints value using the type inferred by the compiler. The difference
// // 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*);
//
// // Prints the fields of a tuple tersely to a string vector, one
@@ -545,14 +547,6 @@ class UniversalPrinter {
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
#pragma warning(pop) // Restores the warning state.
#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.
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].
template <typename T, size_t N>
class UniversalPrinter<T[N]> {
@@ -602,12 +588,6 @@ class UniversalPrinter<T[N]> {
static void Print(const T (&a)[N], ::std::ostream* 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&.
@@ -630,14 +610,6 @@ class UniversalPrinter<T&> {
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
#pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
@@ -740,6 +712,14 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
}
} // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+ ::std::stringstream ss;
+ internal::UniversalTersePrint(value, &ss);
+ return ss.str();
+}
+
} // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_