Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
82113318
Commit
82113318
authored
Jan 08, 2010
by
zhanyong.wan
Browse files
Implements the new matcher API.
parent
7f8eb725
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
763 additions
and
425 deletions
+763
-425
include/gmock/gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+132
-57
include/gmock/gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+65
-27
include/gmock/gmock-matchers.h
include/gmock/gmock-matchers.h
+382
-322
include/gmock/gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+3
-3
test/gmock-generated-matchers_test.cc
test/gmock-generated-matchers_test.cc
+52
-0
test/gmock-matchers_test.cc
test/gmock-matchers_test.cc
+129
-16
No files found.
include/gmock/gmock-generated-matchers.h
View file @
82113318
...
...
@@ -229,8 +229,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
explicit
ArgsMatcherImpl
(
const
InnerMatcher
&
inner_matcher
)
:
inner_matcher_
(
SafeMatcherCast
<
const
SelectedArgs
&>
(
inner_matcher
))
{}
virtual
bool
Matches
(
ArgsTuple
args
)
const
{
return
inner_matcher_
.
Matches
(
GetSelectedArgs
(
args
));
virtual
bool
MatchAndExplain
(
ArgsTuple
args
,
MatchResultListener
*
listener
)
const
{
return
inner_matcher_
.
MatchAndExplain
(
GetSelectedArgs
(
args
),
listener
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
...
...
@@ -243,11 +244,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
inner_matcher_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
ArgsTuple
args
,
::
std
::
ostream
*
os
)
const
{
inner_matcher_
.
ExplainMatchResultTo
(
GetSelectedArgs
(
args
),
os
);
}
private:
static
SelectedArgs
GetSelectedArgs
(
ArgsTuple
args
)
{
return
TupleFields
<
RawArgsTuple
,
k0
,
k1
,
k2
,
k3
,
k4
,
k5
,
k6
,
k7
,
k8
,
...
...
@@ -852,14 +848,19 @@ ElementsAreArray(const T (&array)[N]) {
}
// namespace testing
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax:
// define custom matchers easily.
//
// Basic Usage
// ===========
//
// The syntax
//
// MATCHER(name, description_string) { statements; }
//
//
will
define a matcher with the given name that executes the
//
statements,
which must return a bool to indicate if the match
//
succeeds. Inside
the statements, you can refer to the value being
//
matched by 'arg',
and refer to its type by 'arg_type'.
// define
s
a matcher with the given name that executes the
statements,
// which must return a bool to indicate if the match
succeeds. Inside
// the statements, you can refer to the value being
matched by 'arg',
// and refer to its type by 'arg_type'.
//
// The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a
...
...
@@ -892,6 +893,9 @@ ElementsAreArray(const T (&array)[N]) {
// where the description "is even" is automatically calculated from the
// matcher name IsEven.
//
// Argument Type
// =============
//
// Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about
...
...
@@ -902,6 +906,9 @@ ElementsAreArray(const T (&array)[N]) {
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on.
//
// Parameterizing Matchers
// =======================
//
// Sometimes you'll want to parameterize the matcher. For that you
// can use another macro:
//
...
...
@@ -932,6 +939,9 @@ ElementsAreArray(const T (&array)[N]) {
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to
// support multi-parameter matchers.
//
// Describing Parameterized Matchers
// =================================
//
// When defining a parameterized matcher, you can use Python-style
// interpolations in the description string to refer to the parameter
// values. We support the following syntax currently:
...
...
@@ -964,6 +974,9 @@ ElementsAreArray(const T (&array)[N]) {
//
// Expected: in closed range (4, 6)
//
// Types of Matcher Parameters
// ===========================
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
...
...
@@ -991,23 +1004,44 @@ ElementsAreArray(const T (&array)[N]) {
// matcher you will see the value of the referenced object but not its
// address.
//
// Explaining Match Results
// ========================
//
// Sometimes the matcher description alone isn't enough to explain why
// the match has failed or succeeded. For example, when expecting a
// long string, it can be very helpful to also print the diff between
// the expected string and the actual one. To achieve that, you can
// optionally stream additional information to a special variable
// named result_listener, whose type is a pointer to class
// MatchResultListener:
//
// MATCHER_P(EqualsLongString, str, "") {
// if (arg == str) return true;
//
// *result_listener << "the difference: "
/// << DiffStrings(str, arg);
// return false;
// }
//
// Overloading Matchers
// ====================
//
// You can overload matchers with different numbers of parameters:
//
// MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... }
//
// While it's tempting to always use the MATCHER* macros when defining
// a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher() instead,
// especially if you need to use the matcher a lot. While these
// approaches require more work, they give you more control on the
// types of the value being matched and the matcher parameters, which
// in general leads to better compiler error messages that pay off in
// the long run. They also allow overloading matchers based on
// parameter types (as opposed to just based on the number of
// parameters).
// Caveats
// =======
//
// CAVEAT:
// When defining a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher(). These
// approaches require more work than the MATCHER* macros, but also
// give you more control on the types of the value being matched and
// the matcher parameters, which may leads to better compiler error
// messages when the matcher is used wrong. They also allow
// overloading matchers based on parameter types (as opposed to just
// based on the number of parameters).
//
// MATCHER*() can only be used in a namespace scope. The reason is
// that C++ doesn't yet allow function-local types to be used to
...
...
@@ -1015,7 +1049,8 @@ ElementsAreArray(const T (&array)[N]) {
// Once that's done, we'll consider supporting using MATCHER*() inside
// a function.
//
// MORE INFORMATION:
// More Information
// ================
//
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
...
...
@@ -1028,7 +1063,8 @@ ElementsAreArray(const T (&array)[N]) {
public:\
gmock_Impl(const ::testing::internal::Interpolations& gmock_interp)\
: gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1058,8 +1094,10 @@ ElementsAreArray(const T (&array)[N]) {
return name##Matcher();\
}\
template <typename arg_type>\
bool name##Matcher::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P(name, p0, description)\
template <typename p0##_type>\
...
...
@@ -1071,7 +1109,8 @@ ElementsAreArray(const T (&array)[N]) {
explicit gmock_Impl(p0##_type gmock_p0, \
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1105,8 +1144,10 @@ ElementsAreArray(const T (&array)[N]) {
}\
template <typename p0##_type>\
template <typename arg_type>\
bool name##MatcherP<p0##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P2(name, p0, p1, description)\
template <typename p0##_type, typename p1##_type>\
...
...
@@ -1118,7 +1159,8 @@ ElementsAreArray(const T (&array)[N]) {
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1156,8 +1198,11 @@ ElementsAreArray(const T (&array)[N]) {
}\
template <typename p0##_type, typename p1##_type>\
template <typename arg_type>\
bool name##MatcherP2<p0##_type, p1##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP2<p0##_type, \
p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P3(name, p0, p1, p2, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type>\
...
...
@@ -1170,7 +1215,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1211,8 +1257,11 @@ ElementsAreArray(const T (&array)[N]) {
}\
template <typename p0##_type, typename p1##_type, typename p2##_type>\
template <typename arg_type>\
bool name##MatcherP3<p0##_type, p1##_type, p2##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP3<p0##_type, p1##_type, \
p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P4(name, p0, p1, p2, p3, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1227,7 +1276,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1275,8 +1325,11 @@ ElementsAreArray(const T (&array)[N]) {
template <typename p0##_type, typename p1##_type, typename p2##_type, \
typename p3##_type>\
template <typename arg_type>\
bool name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \
p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1291,7 +1344,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1342,8 +1396,11 @@ ElementsAreArray(const T (&array)[N]) {
template <typename p0##_type, typename p1##_type, typename p2##_type, \
typename p3##_type, typename p4##_type>\
template <typename arg_type>\
bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1358,7 +1415,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1412,8 +1470,10 @@ ElementsAreArray(const T (&array)[N]) {
typename p3##_type, typename p4##_type, typename p5##_type>\
template <typename arg_type>\
bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1431,7 +1491,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1493,8 +1554,10 @@ ElementsAreArray(const T (&array)[N]) {
typename p6##_type>\
template <typename arg_type>\
bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type, p6##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1512,7 +1575,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1579,8 +1643,11 @@ ElementsAreArray(const T (&array)[N]) {
typename p6##_type, typename p7##_type>\
template <typename arg_type>\
bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type, p6##_type, p7##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type, p6##_type, \
p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1598,7 +1665,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
p8(gmock_p8), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1668,8 +1736,11 @@ ElementsAreArray(const T (&array)[N]) {
typename p6##_type, typename p7##_type, typename p8##_type>\
template <typename arg_type>\
bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type, p6##_type, p7##_type, p8##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type, p6##_type, p7##_type, \
p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1689,7 +1760,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
p8(gmock_p8), p9(gmock_p9), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1763,7 +1835,10 @@ ElementsAreArray(const T (&array)[N]) {
typename p9##_type>\
template <typename arg_type>\
bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
include/gmock/gmock-generated-matchers.h.pump
View file @
82113318
...
...
@@ -116,8 +116,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
explicit
ArgsMatcherImpl
(
const
InnerMatcher
&
inner_matcher
)
:
inner_matcher_
(
SafeMatcherCast
<
const
SelectedArgs
&>
(
inner_matcher
))
{}
virtual
bool
Matches
(
ArgsTuple
args
)
const
{
return
inner_matcher_
.
Matches
(
GetSelectedArgs
(
args
));
virtual
bool
MatchAndExplain
(
ArgsTuple
args
,
MatchResultListener
*
listener
)
const
{
return
inner_matcher_
.
MatchAndExplain
(
GetSelectedArgs
(
args
),
listener
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
...
...
@@ -130,11 +131,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
inner_matcher_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
ArgsTuple
args
,
::
std
::
ostream
*
os
)
const
{
inner_matcher_
.
ExplainMatchResultTo
(
GetSelectedArgs
(
args
),
os
);
}
private:
static
SelectedArgs
GetSelectedArgs
(
ArgsTuple
args
)
{
return
TupleFields
<
RawArgsTuple
,
$
ks
>::
GetSelectedFields
(
args
);
...
...
@@ -301,14 +297,19 @@ $$ // show up in the generated code.
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax:
// define custom matchers easily.
//
// Basic Usage
// ===========
//
// The syntax
//
// MATCHER(name, description_string) { statements; }
//
//
will
define a matcher with the given name that executes the
//
statements,
which must return a bool to indicate if the match
//
succeeds. Inside
the statements, you can refer to the value being
//
matched by 'arg',
and refer to its type by 'arg_type'.
// define
s
a matcher with the given name that executes the
statements,
// which must return a bool to indicate if the match
succeeds. Inside
// the statements, you can refer to the value being
matched by 'arg',
// and refer to its type by 'arg_type'.
//
// The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a
...
...
@@ -341,6 +342,9 @@ $$ // show up in the generated code.
// where the description "is even" is automatically calculated from the
// matcher name IsEven.
//
// Argument Type
// =============
//
// Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about
...
...
@@ -351,6 +355,9 @@ $$ // show up in the generated code.
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on.
//
// Parameterizing Matchers
// =======================
//
// Sometimes you'll want to parameterize the matcher. For that you
// can use another macro:
//
...
...
@@ -381,6 +388,9 @@ $$ // show up in the generated code.
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
// support multi-parameter matchers.
//
// Describing Parameterized Matchers
// =================================
//
// When defining a parameterized matcher, you can use Python-style
// interpolations in the description string to refer to the parameter
// values. We support the following syntax currently:
...
...
@@ -413,6 +423,9 @@ $$ // show up in the generated code.
//
// Expected: in closed range (4, 6)
//
// Types of Matcher Parameters
// ===========================
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
...
...
@@ -440,23 +453,44 @@ $$ // show up in the generated code.
// matcher you will see the value of the referenced object but not its
// address.
//
// Explaining Match Results
// ========================
//
// Sometimes the matcher description alone isn't enough to explain why
// the match has failed or succeeded. For example, when expecting a
// long string, it can be very helpful to also print the diff between
// the expected string and the actual one. To achieve that, you can
// optionally stream additional information to a special variable
// named result_listener, whose type is a pointer to class
// MatchResultListener:
//
// MATCHER_P(EqualsLongString, str, "") {
// if (arg == str) return true;
//
// *result_listener << "the difference: "
/// << DiffStrings(str, arg);
// return false;
// }
//
// Overloading Matchers
// ====================
//
// You can overload matchers with different numbers of parameters:
//
// MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... }
//
// While it's tempting to always use the MATCHER* macros when defining
// a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher() instead,
// especially if you need to use the matcher a lot. While these
// approaches require more work, they give you more control on the
// types of the value being matched and the matcher parameters, which
// in general leads to better compiler error messages that pay off in
// the long run. They also allow overloading matchers based on
// parameter types (as opposed to just based on the number of
// parameters).
// Caveats
// =======
//
// CAVEAT:
// When defining a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher(). These
// approaches require more work than the MATCHER* macros, but also
// give you more control on the types of the value being matched and
// the matcher parameters, which may leads to better compiler error
// messages when the matcher is used wrong. They also allow
// overloading matchers based on parameter types (as opposed to just
// based on the number of parameters).
//
// MATCHER*() can only be used in a namespace scope. The reason is
// that C++ doesn't yet allow function-local types to be used to
...
...
@@ -464,7 +498,8 @@ $$ // show up in the generated code.
// Once that's done, we'll consider supporting using MATCHER*() inside
// a function.
//
// MORE INFORMATION:
// More Information
// ================
//
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
...
...
@@ -510,7 +545,8 @@ $var param_field_decls2 = [[$for j
public
:
\
[[
$
if
i
==
1
[[
explicit
]]]]
gmock_Impl
(
$
impl_ctor_param_list
)
\
$
impl_inits
{}
\
virtual
bool
Matches
(
arg_type
arg
)
const
;
\
virtual
bool
MatchAndExplain
(
\
arg_type
arg
,
::
testing
::
MatchResultListener
*
result_listener
)
const
;
\
virtual
void
DescribeTo
(
::
std
::
ostream
*
gmock_os
)
const
{
\
const
::
testing
::
internal
::
Strings
&
gmock_printed_params
=
\
::
testing
::
internal
::
UniversalTersePrintTupleFieldsToStrings
(
\
...
...
@@ -540,8 +576,10 @@ $var param_field_decls2 = [[$for j
return
$
class_name
$
param_types
(
$
params
);
\
}\$
template
template
<
typename
arg_type
>
\
bool
$
class_name
$
param_types
::
\
gmock_Impl
<
arg_type
>
::
Matches
(
arg_type
arg
)
const
bool
$
class_name
$
param_types
::
gmock_Impl
<
arg_type
>
::
MatchAndExplain
(
\
arg_type
arg
,
\
::
testing
::
MatchResultListener
*
result_listener
GTEST_ATTRIBUTE_UNUSED_
)
\
const
]]
...
...
include/gmock/gmock-matchers.h
View file @
82113318
...
...
@@ -64,14 +64,74 @@ namespace testing {
// ownership management as Matcher objects can now be copied like
// plain values.
// MatchResultListener is an abstract class. Its << operator can be
// used by a matcher to explain why a value matches or doesn't match.
//
// TODO(wan@google.com): add method
// bool InterestedInWhy(bool result) const;
// to indicate whether the listener is interested in why the match
// result is 'result'.
class
MatchResultListener
{
public:
// Creates a listener object with the given underlying ostream. The
// listener does not own the ostream.
explicit
MatchResultListener
(
::
std
::
ostream
*
os
)
:
stream_
(
os
)
{}
virtual
~
MatchResultListener
()
=
0
;
// Makes this class abstract.
// Streams x to the underlying ostream; does nothing if the ostream
// is NULL.
template
<
typename
T
>
MatchResultListener
&
operator
<<
(
const
T
&
x
)
{
if
(
stream_
!=
NULL
)
*
stream_
<<
x
;
return
*
this
;
}
// Returns the underlying ostream.
::
std
::
ostream
*
stream
()
{
return
stream_
;
}
private:
::
std
::
ostream
*
const
stream_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
MatchResultListener
);
};
inline
MatchResultListener
::~
MatchResultListener
()
{
}
// The implementation of a matcher.
template
<
typename
T
>
class
MatcherInterface
{
public:
virtual
~
MatcherInterface
()
{}
// Returns true iff the matcher matches x; also explains the match
// result to 'listener'.
//
// You should override this method when defining a new matcher. For
// backward compatibility, we provide a default implementation that
// just forwards to the old, deprecated matcher API (Matches() and
// ExplainMatchResultTo()).
//
// It's the responsibility of the caller (Google Mock) to guarantee
// that 'listener' is not NULL. This helps to simplify a matcher's
// implementation when it doesn't care about the performance, as it
// can talk to 'listener' without checking its validity first.
// However, in order to implement dummy listeners efficiently,
// listener->stream() may be NULL.
virtual
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
const
bool
match
=
Matches
(
x
);
if
(
listener
->
stream
()
!=
NULL
)
{
ExplainMatchResultTo
(
x
,
listener
->
stream
());
}
return
match
;
}
// DEPRECATED. This method will be removed. Override
// MatchAndExplain() instead.
//
// Returns true iff the matcher matches x.
virtual
bool
Matches
(
T
x
)
const
=
0
;
virtual
bool
Matches
(
T
/* x */
)
const
{
return
false
;
}
// Describes this matcher to an ostream.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
=
0
;
...
...
@@ -88,6 +148,9 @@ class MatcherInterface {
*
os
<<
")"
;
}
// DEPRECATED. This method will be removed. Override
// MatchAndExplain() instead.
//
// Explains why x matches, or doesn't match, the matcher. Override
// this to provide any additional information that helps a user
// understand the match result.
...
...
@@ -100,14 +163,58 @@ class MatcherInterface {
namespace
internal
{
// A match result listener that ignores the explanation.
class
DummyMatchResultListener
:
public
MatchResultListener
{
public:
DummyMatchResultListener
()
:
MatchResultListener
(
NULL
)
{}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
DummyMatchResultListener
);
};
// A match result listener that forwards the explanation to a given
// ostream. The difference between this and MatchResultListener is
// that the former is concrete.
class
StreamMatchResultListener
:
public
MatchResultListener
{
public:
explicit
StreamMatchResultListener
(
::
std
::
ostream
*
os
)
:
MatchResultListener
(
os
)
{}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
StreamMatchResultListener
);
};
// A match result listener that stores the explanation in a string.
class
StringMatchResultListener
:
public
MatchResultListener
{
public:
StringMatchResultListener
()
:
MatchResultListener
(
&
ss_
)
{}
// Returns the explanation heard so far.
internal
::
string
str
()
const
{
return
ss_
.
str
();
}
private:
::
std
::
stringstream
ss_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
StringMatchResultListener
);
};
// An internal class for implementing Matcher<T>, which will derive
// from it. We put functionalities common to all Matcher<T>
// specializations here to avoid code duplication.
template
<
typename
T
>
class
MatcherBase
{
public:
// Returns true iff the matcher matches x; also explains the match
// result to 'listener'.
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
return
impl_
->
MatchAndExplain
(
x
,
listener
);
}
// Returns true iff this matcher matches x.
bool
Matches
(
T
x
)
const
{
return
impl_
->
Matches
(
x
);
}
bool
Matches
(
T
x
)
const
{
DummyMatchResultListener
dummy
;
return
MatchAndExplain
(
x
,
&
dummy
);
}
// Describes this matcher to an ostream.
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
impl_
->
DescribeTo
(
os
);
}
...
...
@@ -119,7 +226,8 @@ class MatcherBase {
// Explains why x matches, or doesn't match, the matcher.
void
ExplainMatchResultTo
(
T
x
,
::
std
::
ostream
*
os
)
const
{
impl_
->
ExplainMatchResultTo
(
x
,
os
);
StreamMatchResultListener
listener
(
os
);
MatchAndExplain
(
x
,
&
listener
);
}
protected:
...
...
@@ -156,6 +264,27 @@ inline void ExplainMatchResultTo(const PolymorphicMatcherImpl& /* impl */,
// prints the value of x elsewhere.
}
// The default implementation of MatchAndExplain() for polymorphic
// matchers.
template
<
typename
PolymorphicMatcherImpl
,
typename
T
>
inline
bool
MatchAndExplain
(
const
PolymorphicMatcherImpl
&
impl
,
const
T
&
x
,
MatchResultListener
*
listener
)
{
const
bool
match
=
impl
.
Matches
(
x
);
::
std
::
ostream
*
const
os
=
listener
->
stream
();
if
(
os
!=
NULL
)
{
using
::
testing
::
internal
::
ExplainMatchResultTo
;
// When resolving the following call, both
// ::testing::internal::ExplainMatchResultTo() and
// foo::ExplainMatchResultTo() are considered, where foo is the
// namespace where class PolymorphicMatcherImpl is defined.
ExplainMatchResultTo
(
impl
,
x
,
os
);
}
return
match
;
}
}
// namespace internal
// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
...
...
@@ -220,19 +349,31 @@ class Matcher<internal::string>
// polymorphic matcher (i.e. a matcher that can match values of more
// than one type, e.g. Eq(n) and NotNull()).
//
// To define a polymorphic matcher, a user first provides a Impl class
// that has a Matches() method, a DescribeTo() method, and a
// DescribeNegationTo() method. The Matches() method is usually a
// method template (such that it works with multiple types). Then the
// user creates the polymorphic matcher using
// MakePolymorphicMatcher(). To provide additional explanation to the
// match result, define a FREE function (or function template)
// To define a polymorphic matcher in the old, deprecated way, a user
// first provides an Impl class that has a Matches() method, a
// DescribeTo() method, and a DescribeNegationTo() method. The
// Matches() method is usually a method template (such that it works
// with multiple types). Then the user creates the polymorphic
// matcher using MakePolymorphicMatcher(). To provide additional
// explanation to the match result, define a FREE function (or
// function template)
//
// void ExplainMatchResultTo(const Impl& matcher, const Value& value,
// ::std::ostream* os);
//
// in the SAME NAME SPACE where Impl is defined. See the definition
// of NotNull() for a complete example.
// in the SAME NAME SPACE where Impl is defined.
//
// The new, recommended way to define a polymorphic matcher is to
// provide an Impl class that has a DescribeTo() method and a
// DescribeNegationTo() method, and define a FREE function (or
// function template)
//
// bool MatchAndExplain(const Impl& matcher, const Value& value,
// MatchResultListener* listener);
//
// in the SAME NAME SPACE where Impl is defined.
//
// See the definition of NotNull() for a complete example.
template
<
class
Impl
>
class
PolymorphicMatcher
{
public:
...
...
@@ -257,8 +398,6 @@ class PolymorphicMatcher {
public:
explicit
MonomorphicImpl
(
const
Impl
&
impl
)
:
impl_
(
impl
)
{}
virtual
bool
Matches
(
T
x
)
const
{
return
impl_
.
Matches
(
x
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
impl_
.
DescribeTo
(
os
);
}
...
...
@@ -267,22 +406,15 @@ class PolymorphicMatcher {
impl_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
T
x
,
::
std
::
ostream
*
os
)
const
{
using
::
testing
::
internal
::
ExplainMatchResultTo
;
virtual
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
// C++ uses Argument-Dependent Look-up (aka Koenig Look-up) to
// resolve the call to ExplainMatchResultTo() here. This
// means that if there's a ExplainMatchResultTo() function
// defined in the name space where class Impl is defined, it
// will be picked by the compiler as the better match.
// Otherwise the default implementation of it in
// ::testing::internal will be picked.
//
// This look-up rule lets a writer of a polymorphic matcher
// customize the behavior of ExplainMatchResultTo() when he
// cares to. Nothing needs to be done by the writer if he
// doesn't need to customize it.
ExplainMatchResultTo
(
impl_
,
x
,
os
);
// resolve the call to MatchAndExplain() here. This means that
// if there's a MatchAndExplain() function defined in the name
// space where class Impl is defined, it will be picked by the
// compiler as the better match. Otherwise the default
// implementation of it in ::testing::internal will be picked.
using
::
testing
::
internal
::
MatchAndExplain
;
return
MatchAndExplain
(
impl_
,
x
,
listener
);
}
private:
...
...
@@ -390,16 +522,12 @@ Matcher<T> A();
// and MUST NOT BE USED IN USER CODE!!!
namespace
internal
{
// Appends the explanation on the result of matcher.Matches(value) to
// os iff the explanation is not empty.
template
<
typename
T
>
void
ExplainMatchResultAsNeededTo
(
const
Matcher
<
T
>&
matcher
,
T
value
,
::
std
::
ostream
*
os
)
{
::
std
::
stringstream
reason
;
matcher
.
ExplainMatchResultTo
(
value
,
&
reason
);
const
internal
::
string
s
=
reason
.
str
();
if
(
s
!=
""
)
{
*
os
<<
" ("
<<
s
<<
")"
;
// 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
,
::
std
::
ostream
*
os
)
{
if
(
!
str
.
empty
()
&&
os
!=
NULL
)
{
*
os
<<
" ("
<<
str
<<
")"
;
}
}
...
...
@@ -439,7 +567,8 @@ class TuplePrefix {
get
<
N
-
1
>
(
matchers
);
typedef
typename
tuple_element
<
N
-
1
,
ValueTuple
>::
type
Value
;
Value
value
=
get
<
N
-
1
>
(
values
);
if
(
!
matcher
.
Matches
(
value
))
{
StringMatchResultListener
listener
;
if
(
!
matcher
.
MatchAndExplain
(
value
,
&
listener
))
{
// TODO(wan): include in the message the name of the parameter
// as used in MOCK_METHOD*() when possible.
*
os
<<
" Expected arg #"
<<
N
-
1
<<
": "
;
...
...
@@ -452,7 +581,8 @@ class TuplePrefix {
// the address is interesting.
internal
::
UniversalPrinter
<
GMOCK_REMOVE_REFERENCE_
(
Value
)
>::
Print
(
value
,
os
);
ExplainMatchResultAsNeededTo
<
Value
>
(
matcher
,
value
,
os
);
StreamInParensAsNeeded
(
listener
.
str
(),
os
);
*
os
<<
"
\n
"
;
}
}
...
...
@@ -537,8 +667,8 @@ class MatcherCastImpl<T, Matcher<U> > {
:
source_matcher_
(
source_matcher
)
{}
// We delegate the matching logic to the source matcher.
virtual
bool
Match
es
(
T
x
)
const
{
return
source_matcher_
.
Match
es
(
static_cast
<
U
>
(
x
));
virtual
bool
Match
AndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
return
source_matcher_
.
Match
AndExplain
(
static_cast
<
U
>
(
x
)
,
listener
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
...
...
@@ -549,10 +679,6 @@ class MatcherCastImpl<T, Matcher<U> > {
source_matcher_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
T
x
,
::
std
::
ostream
*
os
)
const
{
source_matcher_
.
ExplainMatchResultTo
(
static_cast
<
U
>
(
x
),
os
);
}
private:
const
Matcher
<
U
>
source_matcher_
;
...
...
@@ -572,7 +698,8 @@ class MatcherCastImpl<T, Matcher<T> > {
template
<
typename
T
>
class
AnyMatcherImpl
:
public
MatcherInterface
<
T
>
{
public:
virtual
bool
Matches
(
T
/* x */
)
const
{
return
true
;
}
virtual
bool
MatchAndExplain
(
T
/* x */
,
MatchResultListener
*
/* listener */
)
const
{
return
true
;
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is anything"
;
}
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
// This is mostly for completeness' safe, as it's not very useful
...
...
@@ -618,7 +745,10 @@ class AnythingMatcher {
class Impl : public MatcherInterface<Lhs> { \
public: \
explicit Impl(const Rhs& rhs) : rhs_(rhs) {} \
virtual bool Matches(Lhs lhs) const { return lhs op rhs_; } \
virtual bool MatchAndExplain(\
Lhs lhs, MatchResultListener*
/* listener */
) const { \
return lhs op rhs_; \
} \
virtual void DescribeTo(::std::ostream* os) const { \
*os << "is " relation " "; \
UniversalPrinter<Rhs>::Print(rhs_, os); \
...
...
@@ -719,7 +849,11 @@ class RefMatcher<T&> {
// Matches() takes a Super& (as opposed to const Super&) in
// order to match the interface MatcherInterface<Super&>.
virtual
bool
Matches
(
Super
&
x
)
const
{
return
&
x
==
&
object_
;
}
// NOLINT
virtual
bool
MatchAndExplain
(
Super
&
x
,
MatchResultListener
*
listener
)
const
{
*
listener
<<
"is located @"
<<
static_cast
<
const
void
*>
(
&
x
);
return
&
x
==
&
object_
;
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"references the variable "
;
...
...
@@ -731,11 +865,6 @@ class RefMatcher<T&> {
UniversalPrinter
<
Super
&>::
Print
(
object_
,
os
);
}
virtual
void
ExplainMatchResultTo
(
Super
&
x
,
// NOLINT
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is located @"
<<
static_cast
<
const
void
*>
(
&
x
);
}
private:
const
Super
&
object_
;
...
...
@@ -1017,7 +1146,9 @@ class MatchesRegexMatcher {
template <typename T1, typename T2> \
class Impl : public MatcherInterface<const ::std::tr1::tuple<T1, T2>&> { \
public: \
virtual bool Matches(const ::std::tr1::tuple<T1, T2>& args) const { \
virtual bool MatchAndExplain( \
const ::std::tr1::tuple<T1, T2>& args, \
MatchResultListener*
/* listener */
) const { \
return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \
} \
virtual void DescribeTo(::std::ostream* os) const { \
...
...
@@ -1049,8 +1180,8 @@ class NotMatcherImpl : public MatcherInterface<T> {
explicit
NotMatcherImpl
(
const
Matcher
<
T
>&
matcher
)
:
matcher_
(
matcher
)
{}
virtual
bool
Match
es
(
T
x
)
const
{
return
!
matcher_
.
Match
es
(
x
);
virtual
bool
Match
AndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
return
!
matcher_
.
Match
AndExplain
(
x
,
listener
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
...
...
@@ -1061,10 +1192,6 @@ class NotMatcherImpl : public MatcherInterface<T> {
matcher_
.
DescribeTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
T
x
,
::
std
::
ostream
*
os
)
const
{
matcher_
.
ExplainMatchResultTo
(
x
,
os
);
}
private:
const
Matcher
<
T
>
matcher_
;
...
...
@@ -1101,10 +1228,6 @@ class BothOfMatcherImpl : public MatcherInterface<T> {
BothOfMatcherImpl
(
const
Matcher
<
T
>&
matcher1
,
const
Matcher
<
T
>&
matcher2
)
:
matcher1_
(
matcher1
),
matcher2_
(
matcher2
)
{}
virtual
bool
Matches
(
T
x
)
const
{
return
matcher1_
.
Matches
(
x
)
&&
matcher2_
.
Matches
(
x
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"("
;
matcher1_
.
DescribeTo
(
os
);
...
...
@@ -1118,35 +1241,34 @@ class BothOfMatcherImpl : public MatcherInterface<T> {
DescribeTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
T
x
,
::
std
::
ostream
*
os
)
const
{
if
(
Matches
(
x
))
{
// When both matcher1_ and matcher2_ match x, we need to
// explain why *both* of them match.
::
std
::
stringstream
ss1
;
matcher1_
.
ExplainMatchResultTo
(
x
,
&
ss1
);
const
internal
::
string
s1
=
ss1
.
str
();
virtual
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
// If either matcher1_ or matcher2_ doesn't match x, we only need
// to explain why one of them fails.
StringMatchResultListener
listener1
;
if
(
!
matcher1_
.
MatchAndExplain
(
x
,
&
listener1
))
{
*
listener
<<
listener1
.
str
();
return
false
;
}
StringMatchResultListener
listener2
;
if
(
!
matcher2_
.
MatchAndExplain
(
x
,
&
listener2
))
{
*
listener
<<
listener2
.
str
();
return
false
;
}
::
std
::
stringstream
ss2
;
matcher2_
.
ExplainMatchResultTo
(
x
,
&
ss2
);
const
internal
::
string
s2
=
ss
2
.
str
();
// Otherwise we need to explain why *both* of them match.
const
internal
::
string
s1
=
listener1
.
str
(
);
const
internal
::
string
s2
=
listener
2
.
str
();
if
(
s1
==
""
)
{
*
os
<<
s2
;
}
else
{
*
os
<<
s1
;
if
(
s2
!=
""
)
{
*
os
<<
"; "
<<
s2
;
}
}
if
(
s1
==
""
)
{
*
listener
<<
s2
;
}
else
{
// Otherwise we only need to explain why *one* of them fails
// to match.
if
(
!
matcher1_
.
Matches
(
x
))
{
matcher1_
.
ExplainMatchResultTo
(
x
,
os
);
}
else
{
matcher2_
.
ExplainMatchResultTo
(
x
,
os
);
*
listener
<<
s1
;
if
(
s2
!=
""
)
{
*
listener
<<
"; "
<<
s2
;
}
}
return
true
;
}
private:
...
...
@@ -1190,10 +1312,6 @@ class EitherOfMatcherImpl : public MatcherInterface<T> {
EitherOfMatcherImpl
(
const
Matcher
<
T
>&
matcher1
,
const
Matcher
<
T
>&
matcher2
)
:
matcher1_
(
matcher1
),
matcher2_
(
matcher2
)
{}
virtual
bool
Matches
(
T
x
)
const
{
return
matcher1_
.
Matches
(
x
)
||
matcher2_
.
Matches
(
x
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"("
;
matcher1_
.
DescribeTo
(
os
);
...
...
@@ -1207,34 +1325,34 @@ class EitherOfMatcherImpl : public MatcherInterface<T> {
DescribeTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
T
x
,
::
std
::
ostream
*
os
)
const
{
if
(
Matches
(
x
))
{
// If either matcher1_ or matcher2_ matches x, we just need
// to explain why *one* of them matches.
if
(
matcher1_
.
Matches
(
x
))
{
matcher1_
.
ExplainMatchResultTo
(
x
,
os
);
}
else
{
matcher2_
.
ExplainMatchResultTo
(
x
,
os
);
}
}
else
{
// Otherwise we need to explain why *neither* matches.
::
std
::
stringstream
ss1
;
matcher1_
.
ExplainMatchResultTo
(
x
,
&
ss1
);
const
internal
::
string
s1
=
ss1
.
str
();
virtual
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
// If either matcher1_ or matcher2_ matches x, we just need to
// explain why *one* of them matches.
StringMatchResultListener
listener1
;
if
(
matcher1_
.
MatchAndExplain
(
x
,
&
listener1
))
{
*
listener
<<
listener1
.
str
();
return
true
;
}
::
std
::
stringstream
ss2
;
matcher2_
.
ExplainMatchResultTo
(
x
,
&
ss2
);
const
internal
::
string
s2
=
ss2
.
str
();
StringMatchResultListener
listener2
;
if
(
matcher2_
.
MatchAndExplain
(
x
,
&
listener2
))
{
*
listener
<<
listener2
.
str
();
return
true
;
}
if
(
s1
==
""
)
{
*
os
<<
s2
;
}
else
{
*
os
<<
s1
;
if
(
s2
!=
""
)
{
*
os
<<
"; "
<<
s2
;
}
// Otherwise we need to explain why *both* of them fail.
const
internal
::
string
s1
=
listener1
.
str
();
const
internal
::
string
s2
=
listener2
.
str
();
if
(
s1
==
""
)
{
*
listener
<<
s2
;
}
else
{
*
listener
<<
s1
;
if
(
s2
!=
""
)
{
*
listener
<<
"; "
<<
s2
;
}
}
return
false
;
}
private:
...
...
@@ -1367,7 +1485,8 @@ class PredicateFormatterFromMatcher {
// Matcher<const T&>(matcher_), as the latter won't compile when
// matcher_ has type Matcher<T> (e.g. An<int>()).
const
Matcher
<
const
T
&>
matcher
=
MatcherCast
<
const
T
&>
(
matcher_
);
if
(
matcher
.
Matches
(
x
))
{
StringMatchResultListener
listener
;
if
(
matcher
.
MatchAndExplain
(
x
,
&
listener
))
{
return
AssertionSuccess
();
}
else
{
::
std
::
stringstream
ss
;
...
...
@@ -1376,7 +1495,7 @@ class PredicateFormatterFromMatcher {
matcher
.
DescribeTo
(
&
ss
);
ss
<<
"
\n
Actual: "
;
UniversalPrinter
<
T
>::
Print
(
x
,
&
ss
);
ExplainMatchResultAsNeededTo
<
const
T
&>
(
matcher
,
x
,
&
ss
);
StreamInParensAsNeeded
(
listener
.
str
()
,
&
ss
);
return
AssertionFailure
(
Message
()
<<
ss
.
str
());
}
}
...
...
@@ -1417,7 +1536,8 @@ class FloatingEqMatcher {
Impl
(
FloatType
rhs
,
bool
nan_eq_nan
)
:
rhs_
(
rhs
),
nan_eq_nan_
(
nan_eq_nan
)
{}
virtual
bool
Matches
(
T
value
)
const
{
virtual
bool
MatchAndExplain
(
T
value
,
MatchResultListener
*
/* listener */
)
const
{
const
FloatingPoint
<
FloatType
>
lhs
(
value
),
rhs
(
rhs_
);
// Compares NaNs first, if nan_eq_nan_ is true.
...
...
@@ -1525,10 +1645,6 @@ class PointeeMatcher {
explicit
Impl
(
const
InnerMatcher
&
matcher
)
:
matcher_
(
MatcherCast
<
const
Pointee
&>
(
matcher
))
{}
virtual
bool
Matches
(
Pointer
p
)
const
{
return
GetRawPointer
(
p
)
!=
NULL
&&
matcher_
.
Matches
(
*
p
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"points to a value that "
;
matcher_
.
DescribeTo
(
os
);
...
...
@@ -1539,17 +1655,18 @@ class PointeeMatcher {
matcher_
.
DescribeTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
Pointer
pointer
,
::
std
::
ostream
*
os
)
const
{
virtual
bool
MatchAndExplain
(
Pointer
pointer
,
MatchResultListener
*
listener
)
const
{
if
(
GetRawPointer
(
pointer
)
==
NULL
)
return
;
return
false
;
::
std
::
stringstream
ss
;
matcher_
.
ExplainMatchResultTo
(
*
pointer
,
&
ss
);
const
internal
::
string
s
=
ss
.
str
();
StringMatchResultListener
inner_listener
;
const
bool
match
=
matcher_
.
MatchAndExplain
(
*
pointer
,
&
inner_listener
);
const
internal
::
string
s
=
inner_listener
.
str
();
if
(
s
!=
""
)
{
*
os
<<
"points to a value that "
<<
s
;
*
listener
<<
"points to a value that "
<<
s
;
}
return
match
;
}
private:
...
...
@@ -1572,16 +1689,6 @@ class FieldMatcher {
const
Matcher
<
const
FieldType
&>&
matcher
)
:
field_
(
field
),
matcher_
(
matcher
)
{}
// Returns true iff the inner matcher matches obj.field.
bool
Matches
(
const
Class
&
obj
)
const
{
return
matcher_
.
Matches
(
obj
.
*
field_
);
}
// Returns true iff the inner matcher matches obj->field.
bool
Matches
(
const
Class
*
p
)
const
{
return
(
p
!=
NULL
)
&&
matcher_
.
Matches
(
p
->*
field_
);
}
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"the given field "
;
matcher_
.
DescribeTo
(
os
);
...
...
@@ -1592,27 +1699,29 @@ class FieldMatcher {
matcher_
.
DescribeNegationTo
(
os
);
}
// The first argument of
ExplainMatchResultTo
() is needed to help
// The first argument of
MatchAndExplain
() is needed to help
// Symbian's C++ compiler choose which overload to use. Its type is
// true_type iff the Field() matcher is used to match a pointer.
void
ExplainMatchResultTo
(
false_type
/* is_not_pointer */
,
const
Class
&
obj
,
::
std
::
ostream
*
os
)
const
{
::
std
::
stringstream
ss
;
matcher_
.
ExplainMatchResultTo
(
obj
.
*
field_
,
&
ss
);
const
internal
::
string
s
=
ss
.
str
();
bool
MatchAndExplain
(
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
!=
""
)
{
*
os
<<
"the given field "
<<
s
;
*
listener
<<
"the given field "
<<
s
;
}
return
match
;
}
void
ExplainMatchResultTo
(
true_type
/* is_pointer */
,
const
Class
*
p
,
::
std
::
ostream
*
os
)
const
{
if
(
p
!=
NULL
)
{
// 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.
ExplainMatchResultTo
(
false_type
(),
*
p
,
os
);
}
bool
MatchAndExplain
(
true_type
/* is_pointer */
,
const
Class
*
p
,
MatchResultListener
*
listener
)
const
{
if
(
p
==
NULL
)
return
false
;
// 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.
return
MatchAndExplain
(
false_type
(),
*
p
,
listener
);
}
private:
...
...
@@ -1622,12 +1731,11 @@ class FieldMatcher {
GTEST_DISALLOW_ASSIGN_
(
FieldMatcher
);
};
// Explains the result of matching an object or pointer against a field matcher.
template
<
typename
Class
,
typename
FieldType
,
typename
T
>
void
ExplainMatchResultTo
(
const
FieldMatcher
<
Class
,
FieldType
>&
matcher
,
const
T
&
value
,
::
std
::
ostream
*
os
)
{
matcher
.
ExplainMatchResultTo
(
typename
::
testing
::
internal
::
is_pointer
<
T
>::
type
(),
value
,
os
);
bool
MatchAndExplain
(
const
FieldMatcher
<
Class
,
FieldType
>&
matcher
,
const
T
&
value
,
MatchResultListener
*
listener
)
{
return
matcher
.
MatchAndExplain
(
typename
::
testing
::
internal
::
is_pointer
<
T
>::
type
(),
value
,
listener
);
}
// Implements the Property() matcher for matching a property
...
...
@@ -1645,16 +1753,6 @@ class PropertyMatcher {
const
Matcher
<
RefToConstProperty
>&
matcher
)
:
property_
(
property
),
matcher_
(
matcher
)
{}
// Returns true iff obj.property() matches the inner matcher.
bool
Matches
(
const
Class
&
obj
)
const
{
return
matcher_
.
Matches
((
obj
.
*
property_
)());
}
// Returns true iff p->property() matches the inner matcher.
bool
Matches
(
const
Class
*
p
)
const
{
return
(
p
!=
NULL
)
&&
matcher_
.
Matches
((
p
->*
property_
)());
}
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"the given property "
;
matcher_
.
DescribeTo
(
os
);
...
...
@@ -1665,27 +1763,30 @@ class PropertyMatcher {
matcher_
.
DescribeNegationTo
(
os
);
}
// The first argument of
ExplainMatchResultTo
() is needed to help
// The first argument of
MatchAndExplain
() is needed to help
// Symbian's C++ compiler choose which overload to use. Its type is
// true_type iff the Property() matcher is used to match a pointer.
void
ExplainMatchResultTo
(
false_type
/* is_not_pointer */
,
const
Class
&
obj
,
::
std
::
ostream
*
os
)
const
{
::
std
::
stringstream
ss
;
matcher_
.
ExplainMatchResultTo
((
obj
.
*
property_
)(),
&
ss
);
const
internal
::
string
s
=
ss
.
str
();
bool
MatchAndExplain
(
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
!=
""
)
{
*
os
<<
"the given property "
<<
s
;
*
listener
<<
"the given property "
<<
s
;
}
return
match
;
}
void
ExplainMatchResultTo
(
true_type
/* is_pointer */
,
const
Class
*
p
,
::
std
::
ostream
*
os
)
const
{
if
(
p
!=
NULL
)
{
// 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.
ExplainMatchResultTo
(
false_type
(),
*
p
,
os
);
}
bool
MatchAndExplain
(
true_type
/* is_pointer */
,
const
Class
*
p
,
MatchResultListener
*
listener
)
const
{
if
(
p
==
NULL
)
return
false
;
// 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.
return
MatchAndExplain
(
false_type
(),
*
p
,
listener
);
}
private:
...
...
@@ -1695,13 +1796,11 @@ class PropertyMatcher {
GTEST_DISALLOW_ASSIGN_
(
PropertyMatcher
);
};
// Explains the result of matching an object or pointer against a
// property matcher.
template
<
typename
Class
,
typename
PropertyType
,
typename
T
>
void
ExplainMatchResultTo
(
const
PropertyMatcher
<
Class
,
PropertyType
>&
matcher
,
const
T
&
value
,
::
std
::
ostream
*
os
)
{
matcher
.
ExplainMatchResultTo
(
typename
::
testing
::
internal
::
is_pointer
<
T
>::
type
(),
value
,
os
);
template
<
typename
Class
,
typename
PropertyType
,
typename
T
>
bool
MatchAndExplain
(
const
PropertyMatcher
<
Class
,
PropertyType
>&
matcher
,
const
T
&
value
,
MatchResultListener
*
listener
)
{
return
matcher
.
MatchAndExplain
(
typename
::
testing
::
internal
::
is_pointer
<
T
>::
type
(),
value
,
listener
);
}
// Type traits specifying various features of different functors for ResultOf.
...
...
@@ -1759,13 +1858,6 @@ class ResultOfMatcher {
public:
Impl
(
CallableStorageType
callable
,
const
Matcher
<
ResultType
>&
matcher
)
:
callable_
(
callable
),
matcher_
(
matcher
)
{}
// Returns true iff callable_(obj) matches the inner matcher.
// The calling syntax is different for different types of callables
// so we abstract it in CallableTraits<Callable>::Invoke().
virtual
bool
Matches
(
T
obj
)
const
{
return
matcher_
.
Matches
(
CallableTraits
<
Callable
>::
template
Invoke
<
T
>
(
callable_
,
obj
));
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"result of the given callable "
;
...
...
@@ -1777,14 +1869,17 @@ class ResultOfMatcher {
matcher_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
T
obj
,
::
std
::
ostream
*
os
)
const
{
::
std
::
stringstream
ss
;
matcher_
.
ExplainMatchResultTo
(
virtual
bool
MatchAndExplain
(
T
obj
,
MatchResultListener
*
listener
)
const
{
StringMatchResultListener
inner_listener
;
const
bool
match
=
matcher_
.
MatchAndExplain
(
CallableTraits
<
Callable
>::
template
Invoke
<
T
>
(
callable_
,
obj
),
&
ss
);
const
internal
::
string
s
=
ss
.
str
();
&
inner_listener
);
const
internal
::
string
s
=
inner_listener
.
str
();
if
(
s
!=
""
)
*
os
<<
"result of the given callable "
<<
s
;
*
listener
<<
"result of the given callable "
<<
s
;
return
match
;
}
private:
...
...
@@ -1929,17 +2024,6 @@ class ContainsMatcherImpl : public MatcherInterface<Container> {
:
inner_matcher_
(
testing
::
SafeMatcherCast
<
const
Element
&>
(
inner_matcher
))
{}
// Returns true iff 'container' matches.
virtual
bool
Matches
(
Container
container
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
for
(
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
it
!=
stl_container
.
end
();
++
it
)
{
if
(
inner_matcher_
.
Matches
(
*
it
))
return
true
;
}
return
false
;
}
// Describes what this matcher does.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"contains at least one element that "
;
...
...
@@ -1952,19 +2036,18 @@ class ContainsMatcherImpl : public MatcherInterface<Container> {
inner_matcher_
.
DescribeTo
(
os
);
}
// Explains why 'container' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
Container
container
,
::
std
::
ostream
*
os
)
const
{
virtual
bool
MatchAndExplain
(
Container
container
,
MatchResultListener
*
listener
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
// We need to explain which (if any) element matches inner_matcher_.
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
it
!=
stl_container
.
end
();
++
it
,
++
i
)
{
size_t
i
=
0
;
for
(
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
it
!=
stl_container
.
end
();
++
it
,
++
i
)
{
if
(
inner_matcher_
.
Matches
(
*
it
))
{
*
os
<<
"element "
<<
i
<<
" matches"
;
return
;
*
listener
<<
"element "
<<
i
<<
" matches"
;
return
true
;
}
}
return
false
;
}
private:
...
...
@@ -2007,8 +2090,9 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
}
// Returns true iff 'key_value.first' (the key) matches the inner matcher.
virtual
bool
Matches
(
PairType
key_value
)
const
{
return
inner_matcher_
.
Matches
(
key_value
.
first
);
virtual
bool
MatchAndExplain
(
PairType
key_value
,
MatchResultListener
*
listener
)
const
{
return
inner_matcher_
.
MatchAndExplain
(
key_value
.
first
,
listener
);
}
// Describes what this matcher does.
...
...
@@ -2023,12 +2107,6 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
inner_matcher_
.
DescribeTo
(
os
);
}
// Explains why 'key_value' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
PairType
key_value
,
::
std
::
ostream
*
os
)
const
{
inner_matcher_
.
ExplainMatchResultTo
(
key_value
.
first
,
os
);
}
private:
const
Matcher
<
const
KeyType
&>
inner_matcher_
;
...
...
@@ -2069,13 +2147,6 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
testing
::
SafeMatcherCast
<
const
SecondType
&>
(
second_matcher
))
{
}
// Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
// matches second_matcher.
virtual
bool
Matches
(
PairType
a_pair
)
const
{
return
first_matcher_
.
Matches
(
a_pair
.
first
)
&&
second_matcher_
.
Matches
(
a_pair
.
second
);
}
// Describes what this matcher does.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"has a first field that "
;
...
...
@@ -2092,28 +2163,40 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
second_matcher_
.
DescribeNegationTo
(
os
);
}
// Explains why 'a_pair' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
PairType
a_pair
,
::
std
::
ostream
*
os
)
const
{
::
std
::
stringstream
ss1
;
first_matcher_
.
ExplainMatchResultTo
(
a_pair
.
first
,
&
ss1
);
internal
::
string
s1
=
ss1
.
str
();
// Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
// 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
;
s1
=
"the first field "
+
s1
;
}
if
(
!
match1
)
{
*
listener
<<
s1
;
return
false
;
}
::
std
::
stringstream
ss2
;
second_matcher_
.
ExplainMatchResultTo
(
a_pair
.
second
,
&
ss2
);
internal
::
string
s2
=
ss2
.
str
();
StringMatchResultListener
listener2
;
const
bool
match2
=
second_matcher_
.
MatchAndExplain
(
a_pair
.
second
,
&
listener2
);
internal
::
string
s2
=
listener2
.
str
();
if
(
s2
!=
""
)
{
s2
=
"the second field "
+
s2
;
s2
=
"the second field "
+
s2
;
}
if
(
!
match2
)
{
*
listener
<<
s2
;
return
false
;
}
*
os
<<
s1
;
*
listener
<<
s1
;
if
(
s1
!=
""
&&
s2
!=
""
)
{
*
os
<<
", and "
;
*
listener
<<
", and "
;
}
*
os
<<
s2
;
*
listener
<<
s2
;
return
true
;
}
private:
...
...
@@ -2165,21 +2248,6 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
}
}
// Returns true iff 'container' matches.
virtual
bool
Matches
(
Container
container
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
stl_container
.
size
()
!=
count
())
return
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
!
matchers_
[
i
].
Matches
(
*
it
))
return
false
;
}
return
true
;
}
// Describes what this matcher does.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
...
...
@@ -2216,63 +2284,54 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
}
}
// Explains why 'container' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
Container
container
,
::
std
::
ostream
*
os
)
const
{
virtual
bool
MatchAndExplain
(
Container
container
,
MatchResultListener
*
listener
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
Matches
(
container
))
{
// We need to explain why *each* element matches (the obvious
// ones can be skipped).
bool
reason_printed
=
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
if
(
reason_printed
)
{
*
os
<<
",
\n
"
;
}
*
os
<<
"element "
<<
i
<<
" "
<<
s
;
reason_printed
=
true
;
}
}
}
else
{
// We need to explain why the container doesn't match.
const
size_t
actual_count
=
stl_container
.
size
();
if
(
actual_count
!=
count
())
{
// The element count doesn't match. If the container is
// empty, there's no need to explain anything as Google Mock
// already prints the empty container. Otherwise we just need
// to show how many elements there actually are.
if
(
actual_count
!=
0
)
{
*
os
<<
"has "
<<
Elements
(
actual_count
);
}
return
;
const
size_t
actual_count
=
stl_container
.
size
();
if
(
actual_count
!=
count
())
{
// The element count doesn't match. If the container is empty,
// there's no need to explain anything as Google Mock already
// prints the empty container. Otherwise we just need to show
// how many elements there actually are.
if
(
actual_count
!=
0
)
{
*
listener
<<
"has "
<<
Elements
(
actual_count
);
}
return
false
;
}
// The container has the right size but at least one element
// doesn't match expectation. We need to find this element and
// explain why it doesn't match.
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
matchers_
[
i
].
Matches
(
*
it
))
{
continue
;
}
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
// explanations[i] is the explanation of the element at index i.
std
::
vector
<
internal
::
string
>
explanations
(
count
());
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
StringMatchResultListener
s
;
if
(
matchers_
[
i
].
MatchAndExplain
(
*
it
,
&
s
))
{
explanations
[
i
]
=
s
.
str
();
}
else
{
// The container has the right size but the i-th element
// doesn't match its expectation.
*
listener
<<
"element "
<<
i
<<
" doesn't match"
;
StreamInParensAsNeeded
(
s
.
str
(),
listener
->
stream
());
return
false
;
}
}
*
os
<<
"element "
<<
i
<<
" doesn't match"
;
// Every element matches its expectation. We need to explain why
// (the obvious ones can be skipped).
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
*
os
<<
" ("
<<
s
<<
")"
;
bool
reason_printed
=
false
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
const
internal
::
string
&
s
=
explanations
[
i
];
if
(
!
s
.
empty
())
{
if
(
reason_printed
)
{
*
listener
<<
",
\n
"
;
}
return
;
*
listener
<<
"element "
<<
i
<<
" "
<<
s
;
reason_printed
=
true
;
}
}
return
true
;
}
private:
...
...
@@ -2811,13 +2870,14 @@ Truly(Predicate pred) {
// values that are included in one container but not the other. (Duplicate
// values and order differences are not explained.)
template
<
typename
Container
>
inline
PolymorphicMatcher
<
internal
::
ContainerEqMatcher
<
inline
PolymorphicMatcher
<
internal
::
ContainerEqMatcher
<
// NOLINT
GMOCK_REMOVE_CONST_
(
Container
)
>
>
ContainerEq
(
const
Container
&
rhs
)
{
// This following line is for working around a bug in MSVC 8.0,
// which causes Container to be a const type sometimes.
typedef
GMOCK_REMOVE_CONST_
(
Container
)
RawContainer
;
return
MakePolymorphicMatcher
(
internal
::
ContainerEqMatcher
<
RawContainer
>
(
rhs
));
return
MakePolymorphicMatcher
(
internal
::
ContainerEqMatcher
<
RawContainer
>
(
rhs
));
}
// Matches an STL-style container or a native array that contains at
...
...
include/gmock/gmock-spec-builders.h
View file @
82113318
...
...
@@ -1004,13 +1004,13 @@ class TypedExpectation : public ExpectationBase {
if
(
!
TupleMatches
(
matchers_
,
args
))
{
DescribeMatchFailureTupleTo
(
matchers_
,
args
,
os
);
}
if
(
!
extra_matcher_
.
Matches
(
args
))
{
StringMatchResultListener
listener
;
if
(
!
extra_matcher_
.
MatchAndExplain
(
args
,
&
listener
))
{
*
os
<<
" Expected args: "
;
extra_matcher_
.
DescribeTo
(
os
);
*
os
<<
"
\n
Actual: don't match"
;
internal
::
ExplainMatchResultAsNeededTo
<
const
ArgumentTuple
&>
(
extra_matcher_
,
args
,
os
);
internal
::
StreamInParensAsNeeded
(
listener
.
str
(),
os
);
*
os
<<
"
\n
"
;
}
}
else
if
(
!
AllPrerequisitesAreSatisfied
())
{
...
...
test/gmock-generated-matchers_test.cc
View file @
82113318
...
...
@@ -136,6 +136,16 @@ TEST(ArgsTest, AcceptsDecreasingTemplateArgs) {
EXPECT_THAT
(
t
,
Not
(
Args
<
2
,
1
>
(
Lt
())));
}
// The MATCHER*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4100)
#endif
MATCHER
(
SumIsZero
,
""
)
{
return
get
<
0
>
(
arg
)
+
get
<
1
>
(
arg
)
+
get
<
2
>
(
arg
)
==
0
;
}
...
...
@@ -553,6 +563,44 @@ TEST(MatcherMacroTest, Works) {
EXPECT_EQ
(
""
,
Explain
(
m
,
7
));
}
// Tests explaining match result in a MATCHER* macro.
MATCHER
(
IsEven2
,
"is even"
)
{
if
((
arg
%
2
)
==
0
)
{
// Verifies that we can stream to result_listener, a listener
// supplied by the MATCHER macro implicitly.
*
result_listener
<<
"OK"
;
return
true
;
}
else
{
*
result_listener
<<
"% 2 == "
<<
(
arg
%
2
);
return
false
;
}
}
MATCHER_P2
(
EqSumOf
,
x
,
y
,
""
)
{
if
(
arg
==
(
x
+
y
))
{
*
result_listener
<<
"OK"
;
return
true
;
}
else
{
// Verifies that we can stream to the underlying stream of
// result_listener.
if
(
result_listener
->
stream
()
!=
NULL
)
{
*
result_listener
->
stream
()
<<
"diff == "
<<
(
x
+
y
-
arg
);
}
return
false
;
}
}
TEST
(
MatcherMacroTest
,
CanExplainMatchResult
)
{
const
Matcher
<
int
>
m1
=
IsEven2
();
EXPECT_EQ
(
"OK"
,
Explain
(
m1
,
4
));
EXPECT_EQ
(
"% 2 == 1"
,
Explain
(
m1
,
5
));
const
Matcher
<
int
>
m2
=
EqSumOf
(
1
,
2
);
EXPECT_EQ
(
"OK"
,
Explain
(
m2
,
3
));
EXPECT_EQ
(
"diff == -1"
,
Explain
(
m2
,
4
));
}
// Tests that the description string supplied to MATCHER() must be
// valid.
...
...
@@ -1052,4 +1100,8 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
EXPECT_THAT
(
a
,
Contains
(
Not
(
Contains
(
5
))));
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
// namespace
test/gmock-matchers_test.cc
View file @
82113318
...
...
@@ -88,6 +88,7 @@ using testing::Matcher;
using
testing
::
MatcherCast
;
using
testing
::
MatcherInterface
;
using
testing
::
Matches
;
using
testing
::
MatchResultListener
;
using
testing
::
NanSensitiveDoubleEq
;
using
testing
::
NanSensitiveFloatEq
;
using
testing
::
Ne
;
...
...
@@ -200,10 +201,39 @@ class EvenMatcherImpl : public MatcherInterface<int> {
// two methods is optional.
};
TEST
(
MatcherInterfaceTest
,
CanBeImplemented
)
{
TEST
(
MatcherInterfaceTest
,
CanBeImplemented
UsingDeprecatedAPI
)
{
EvenMatcherImpl
m
;
}
// Tests implementing a monomorphic matcher using MatchAndExplain().
class
NewEvenMatcherImpl
:
public
MatcherInterface
<
int
>
{
public:
virtual
bool
MatchAndExplain
(
int
x
,
MatchResultListener
*
listener
)
const
{
const
bool
match
=
x
%
2
==
0
;
// Verifies that we can stream to a listener directly.
*
listener
<<
"value % "
<<
2
;
if
(
listener
->
stream
()
!=
NULL
)
{
// Verifies that we can stream to a listener's underlying stream
// too.
*
listener
->
stream
()
<<
" == "
<<
(
x
%
2
);
}
return
match
;
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is an even number"
;
}
};
TEST
(
MatcherInterfaceTest
,
CanBeImplementedUsingNewAPI
)
{
Matcher
<
int
>
m
=
MakeMatcher
(
new
NewEvenMatcherImpl
);
EXPECT_TRUE
(
m
.
Matches
(
2
));
EXPECT_FALSE
(
m
.
Matches
(
3
));
EXPECT_EQ
(
"value % 2 == 0"
,
Explain
(
m
,
2
));
EXPECT_EQ
(
"value % 2 == 1"
,
Explain
(
m
,
3
));
}
// Tests default-constructing a matcher.
TEST
(
MatcherTest
,
CanBeDefaultConstructed
)
{
Matcher
<
double
>
m
;
...
...
@@ -252,6 +282,18 @@ TEST(MatcherTest, CanDescribeItself) {
Describe
(
Matcher
<
int
>
(
new
EvenMatcherImpl
)));
}
// Tests Matcher<T>::MatchAndExplain().
TEST
(
MatcherTest
,
MatchAndExplain
)
{
Matcher
<
int
>
m
=
GreaterThan
(
0
);
::
testing
::
internal
::
StringMatchResultListener
listener1
;
EXPECT_TRUE
(
m
.
MatchAndExplain
(
42
,
&
listener1
));
EXPECT_EQ
(
"is 42 more than 0"
,
listener1
.
str
());
::
testing
::
internal
::
StringMatchResultListener
listener2
;
EXPECT_FALSE
(
m
.
MatchAndExplain
(
-
9
,
&
listener2
));
EXPECT_EQ
(
"is 9 less than 0"
,
listener2
.
str
());
}
// Tests that a C-string literal can be implicitly converted to a
// Matcher<string> or Matcher<const string&>.
TEST
(
StringMatcherTest
,
CanBeImplicitlyConstructedFromCStringLiteral
)
{
...
...
@@ -284,8 +326,8 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
Matcher
<
int
>
m
=
MakeMatcher
(
dummy_impl
);
}
// Tests that MakePolymorphicMatcher() construct
s
a polymorphic
// matcher from its implementation.
// Tests that MakePolymorphicMatcher()
can
construct a polymorphic
// matcher from its implementation
using the old API
.
const
int
bar
=
1
;
class
ReferencesBarOrIsZeroImpl
{
public:
...
...
@@ -308,7 +350,7 @@ PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() {
return
MakePolymorphicMatcher
(
ReferencesBarOrIsZeroImpl
());
}
TEST
(
MakePolymorphicMatcherTest
,
ConstructsMatcher
FromImpl
)
{
TEST
(
MakePolymorphicMatcherTest
,
ConstructsMatcher
UsingOldAPI
)
{
// Using a polymorphic matcher to match a reference type.
Matcher
<
const
int
&>
m1
=
ReferencesBarOrIsZero
();
EXPECT_TRUE
(
m1
.
Matches
(
0
));
...
...
@@ -324,6 +366,58 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) {
EXPECT_EQ
(
"bar or zero"
,
Describe
(
m2
));
}
// Tests implementing a polymorphic matcher using MatchAndExplain().
class
PolymorphicIsEvenImpl
{
public:
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is even"
;
}
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is odd"
;
}
};
template
<
typename
T
>
bool
MatchAndExplain
(
const
PolymorphicIsEvenImpl
&
/* impl */
,
T
x
,
MatchResultListener
*
listener
)
{
// Verifies that we can stream to the listener directly.
*
listener
<<
"% "
<<
2
;
if
(
listener
->
stream
()
!=
NULL
)
{
// Verifies that we can stream to the listener's underlying stream
// too.
*
listener
->
stream
()
<<
" == "
<<
(
x
%
2
);
}
return
(
x
%
2
)
==
0
;
}
PolymorphicMatcher
<
PolymorphicIsEvenImpl
>
PolymorphicIsEven
()
{
return
MakePolymorphicMatcher
(
PolymorphicIsEvenImpl
());
}
TEST
(
MakePolymorphicMatcherTest
,
ConstructsMatcherUsingNewAPI
)
{
// Using PolymorphicIsEven() as a Matcher<int>.
const
Matcher
<
int
>
m1
=
PolymorphicIsEven
();
EXPECT_TRUE
(
m1
.
Matches
(
42
));
EXPECT_FALSE
(
m1
.
Matches
(
43
));
EXPECT_EQ
(
"is even"
,
Describe
(
m1
));
const
Matcher
<
int
>
not_m1
=
Not
(
m1
);
EXPECT_EQ
(
"is odd"
,
Describe
(
not_m1
));
EXPECT_EQ
(
"% 2 == 0"
,
Explain
(
m1
,
42
));
// Using PolymorphicIsEven() as a Matcher<char>.
const
Matcher
<
char
>
m2
=
PolymorphicIsEven
();
EXPECT_TRUE
(
m2
.
Matches
(
'\x42'
));
EXPECT_FALSE
(
m2
.
Matches
(
'\x43'
));
EXPECT_EQ
(
"is even"
,
Describe
(
m2
));
const
Matcher
<
char
>
not_m2
=
Not
(
m2
);
EXPECT_EQ
(
"is odd"
,
Describe
(
not_m2
));
EXPECT_EQ
(
"% 2 == 0"
,
Explain
(
m2
,
'\x42'
));
}
// Tests that MatcherCast<T>(m) works when m is a polymorphic matcher.
TEST
(
MatcherCastTest
,
FromPolymorphicMatcher
)
{
Matcher
<
int
>
m
=
MatcherCast
<
int
>
(
Eq
(
5
));
...
...
@@ -1050,21 +1144,26 @@ TEST(PairTest, CanDescribeSelf) {
}
TEST
(
PairTest
,
CanExplainMatchResultTo
)
{
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m0
=
Pair
(
0
,
0
);
EXPECT_EQ
(
""
,
Explain
(
m0
,
std
::
make_pair
(
25
,
42
)));
// If neither field matches, Pair() should explain about the first
// field.
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m
=
Pair
(
GreaterThan
(
0
),
GreaterThan
(
0
));
EXPECT_EQ
(
"the first field is 1 less than 0"
,
Explain
(
m
,
std
::
make_pair
(
-
1
,
-
2
)));
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m1
=
Pair
(
GreaterThan
(
0
),
0
);
EXPECT_EQ
(
"the first field is 25 more than 0"
,
Explain
(
m1
,
std
::
make_pair
(
25
,
42
)));
// If the first field matches but the second doesn't, Pair() should
// explain about the second field.
EXPECT_EQ
(
"the second field is 2 less than 0"
,
Explain
(
m
,
std
::
make_pair
(
1
,
-
2
)));
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m2
=
Pair
(
0
,
GreaterThan
(
0
));
EXPECT_EQ
(
"the second field is 42 more than 0"
,
Explain
(
m2
,
std
::
make_pair
(
25
,
42
)));
// If the first field doesn't match but the second does, Pair()
// should explain about the first field.
EXPECT_EQ
(
"the first field is 1 less than 0"
,
Explain
(
m
,
std
::
make_pair
(
-
1
,
2
)));
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m3
=
Pair
(
GreaterThan
(
0
),
GreaterThan
(
0
));
EXPECT_EQ
(
"the first field is
25
more than 0"
", and the second field is
4
2 more than 0"
,
Explain
(
m
3
,
std
::
make_pair
(
25
,
4
2
)));
// If both fields match, Pair() should explain about them both.
EXPECT_EQ
(
"the first field is
1
more than 0"
", and the second field is 2 more than 0"
,
Explain
(
m
,
std
::
make_pair
(
1
,
2
)));
}
TEST
(
PairTest
,
MatchesCorrectly
)
{
...
...
@@ -3335,6 +3434,16 @@ TEST(ValidateMatcherDescriptionTest,
ElementsAre
());
}
// The MATCHER*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4100)
#endif
// We use MATCHER_P3() to define a matcher for testing
// ValidateMatcherDescription(); otherwise we'll end up with much
// plumbing code. This is not circular as
...
...
@@ -3345,6 +3454,10 @@ MATCHER_P3(EqInterpolation, start, end, index, "equals Interpolation%(*)s") {
arg
.
param_index
==
index
;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsPercentInterpolation
)
{
const
char
*
params
[]
=
{
"foo"
,
NULL
};
const
char
*
const
desc
=
"one %%"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment