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