Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
82113318
Commit
82113318
authored
Jan 08, 2010
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implements the new matcher API.
parent
7f8eb725
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
763 additions
and
425 deletions
+763
-425
gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+132
-57
gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+65
-27
gmock-matchers.h
include/gmock/gmock-matchers.h
+382
-322
gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+3
-3
gmock-generated-matchers_test.cc
test/gmock-generated-matchers_test.cc
+52
-0
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'.
//
defines 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'.
//
defines 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() c
onstructs
a polymorphic
// matcher from its implementation.
// Tests that MakePolymorphicMatcher() c
an 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