Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
82113318
Commit
82113318
authored
Jan 08, 2010
by
zhanyong.wan
Browse files
Implements the new matcher API.
parent
7f8eb725
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
763 additions
and
425 deletions
+763
-425
include/gmock/gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+132
-57
include/gmock/gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+65
-27
include/gmock/gmock-matchers.h
include/gmock/gmock-matchers.h
+382
-322
include/gmock/gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+3
-3
test/gmock-generated-matchers_test.cc
test/gmock-generated-matchers_test.cc
+52
-0
test/gmock-matchers_test.cc
test/gmock-matchers_test.cc
+129
-16
No files found.
include/gmock/gmock-generated-matchers.h
View file @
82113318
...
...
@@ -229,8 +229,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
explicit
ArgsMatcherImpl
(
const
InnerMatcher
&
inner_matcher
)
:
inner_matcher_
(
SafeMatcherCast
<
const
SelectedArgs
&>
(
inner_matcher
))
{}
virtual
bool
Matches
(
ArgsTuple
args
)
const
{
return
inner_matcher_
.
Matches
(
GetSelectedArgs
(
args
));
virtual
bool
MatchAndExplain
(
ArgsTuple
args
,
MatchResultListener
*
listener
)
const
{
return
inner_matcher_
.
MatchAndExplain
(
GetSelectedArgs
(
args
),
listener
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
...
...
@@ -243,11 +244,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
inner_matcher_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
ArgsTuple
args
,
::
std
::
ostream
*
os
)
const
{
inner_matcher_
.
ExplainMatchResultTo
(
GetSelectedArgs
(
args
),
os
);
}
private:
static
SelectedArgs
GetSelectedArgs
(
ArgsTuple
args
)
{
return
TupleFields
<
RawArgsTuple
,
k0
,
k1
,
k2
,
k3
,
k4
,
k5
,
k6
,
k7
,
k8
,
...
...
@@ -852,14 +848,19 @@ ElementsAreArray(const T (&array)[N]) {
}
// namespace testing
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax:
// define custom matchers easily.
//
// Basic Usage
// ===========
//
// The syntax
//
// MATCHER(name, description_string) { statements; }
//
//
will
define a matcher with the given name that executes the
//
statements,
which must return a bool to indicate if the match
//
succeeds. Inside
the statements, you can refer to the value being
//
matched by 'arg',
and refer to its type by 'arg_type'.
// define
s
a matcher with the given name that executes the
statements,
// which must return a bool to indicate if the match
succeeds. Inside
// the statements, you can refer to the value being
matched by 'arg',
// and refer to its type by 'arg_type'.
//
// The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a
...
...
@@ -892,6 +893,9 @@ ElementsAreArray(const T (&array)[N]) {
// where the description "is even" is automatically calculated from the
// matcher name IsEven.
//
// Argument Type
// =============
//
// Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about
...
...
@@ -902,6 +906,9 @@ ElementsAreArray(const T (&array)[N]) {
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on.
//
// Parameterizing Matchers
// =======================
//
// Sometimes you'll want to parameterize the matcher. For that you
// can use another macro:
//
...
...
@@ -932,6 +939,9 @@ ElementsAreArray(const T (&array)[N]) {
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to
// support multi-parameter matchers.
//
// Describing Parameterized Matchers
// =================================
//
// When defining a parameterized matcher, you can use Python-style
// interpolations in the description string to refer to the parameter
// values. We support the following syntax currently:
...
...
@@ -964,6 +974,9 @@ ElementsAreArray(const T (&array)[N]) {
//
// Expected: in closed range (4, 6)
//
// Types of Matcher Parameters
// ===========================
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
...
...
@@ -991,23 +1004,44 @@ ElementsAreArray(const T (&array)[N]) {
// matcher you will see the value of the referenced object but not its
// address.
//
// Explaining Match Results
// ========================
//
// Sometimes the matcher description alone isn't enough to explain why
// the match has failed or succeeded. For example, when expecting a
// long string, it can be very helpful to also print the diff between
// the expected string and the actual one. To achieve that, you can
// optionally stream additional information to a special variable
// named result_listener, whose type is a pointer to class
// MatchResultListener:
//
// MATCHER_P(EqualsLongString, str, "") {
// if (arg == str) return true;
//
// *result_listener << "the difference: "
/// << DiffStrings(str, arg);
// return false;
// }
//
// Overloading Matchers
// ====================
//
// You can overload matchers with different numbers of parameters:
//
// MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... }
//
// While it's tempting to always use the MATCHER* macros when defining
// a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher() instead,
// especially if you need to use the matcher a lot. While these
// approaches require more work, they give you more control on the
// types of the value being matched and the matcher parameters, which
// in general leads to better compiler error messages that pay off in
// the long run. They also allow overloading matchers based on
// parameter types (as opposed to just based on the number of
// parameters).
// Caveats
// =======
//
// CAVEAT:
// When defining a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher(). These
// approaches require more work than the MATCHER* macros, but also
// give you more control on the types of the value being matched and
// the matcher parameters, which may leads to better compiler error
// messages when the matcher is used wrong. They also allow
// overloading matchers based on parameter types (as opposed to just
// based on the number of parameters).
//
// MATCHER*() can only be used in a namespace scope. The reason is
// that C++ doesn't yet allow function-local types to be used to
...
...
@@ -1015,7 +1049,8 @@ ElementsAreArray(const T (&array)[N]) {
// Once that's done, we'll consider supporting using MATCHER*() inside
// a function.
//
// MORE INFORMATION:
// More Information
// ================
//
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
...
...
@@ -1028,7 +1063,8 @@ ElementsAreArray(const T (&array)[N]) {
public:\
gmock_Impl(const ::testing::internal::Interpolations& gmock_interp)\
: gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1058,8 +1094,10 @@ ElementsAreArray(const T (&array)[N]) {
return name##Matcher();\
}\
template <typename arg_type>\
bool name##Matcher::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P(name, p0, description)\
template <typename p0##_type>\
...
...
@@ -1071,7 +1109,8 @@ ElementsAreArray(const T (&array)[N]) {
explicit gmock_Impl(p0##_type gmock_p0, \
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1105,8 +1144,10 @@ ElementsAreArray(const T (&array)[N]) {
}\
template <typename p0##_type>\
template <typename arg_type>\
bool name##MatcherP<p0##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P2(name, p0, p1, description)\
template <typename p0##_type, typename p1##_type>\
...
...
@@ -1118,7 +1159,8 @@ ElementsAreArray(const T (&array)[N]) {
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1156,8 +1198,11 @@ ElementsAreArray(const T (&array)[N]) {
}\
template <typename p0##_type, typename p1##_type>\
template <typename arg_type>\
bool name##MatcherP2<p0##_type, p1##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP2<p0##_type, \
p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P3(name, p0, p1, p2, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type>\
...
...
@@ -1170,7 +1215,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1211,8 +1257,11 @@ ElementsAreArray(const T (&array)[N]) {
}\
template <typename p0##_type, typename p1##_type, typename p2##_type>\
template <typename arg_type>\
bool name##MatcherP3<p0##_type, p1##_type, p2##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP3<p0##_type, p1##_type, \
p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P4(name, p0, p1, p2, p3, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1227,7 +1276,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1275,8 +1325,11 @@ ElementsAreArray(const T (&array)[N]) {
template <typename p0##_type, typename p1##_type, typename p2##_type, \
typename p3##_type>\
template <typename arg_type>\
bool name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \
p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1291,7 +1344,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1342,8 +1396,11 @@ ElementsAreArray(const T (&array)[N]) {
template <typename p0##_type, typename p1##_type, typename p2##_type, \
typename p3##_type, typename p4##_type>\
template <typename arg_type>\
bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1358,7 +1415,8 @@ ElementsAreArray(const T (&array)[N]) {
const ::testing::internal::Interpolations& gmock_interp)\
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1412,8 +1470,10 @@ ElementsAreArray(const T (&array)[N]) {
typename p3##_type, typename p4##_type, typename p5##_type>\
template <typename arg_type>\
bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1431,7 +1491,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1493,8 +1554,10 @@ ElementsAreArray(const T (&array)[N]) {
typename p6##_type>\
template <typename arg_type>\
bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type, p6##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1512,7 +1575,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1579,8 +1643,11 @@ ElementsAreArray(const T (&array)[N]) {
typename p6##_type, typename p7##_type>\
template <typename arg_type>\
bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type, p6##_type, p7##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type, p6##_type, \
p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1598,7 +1665,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
p8(gmock_p8), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1668,8 +1736,11 @@ ElementsAreArray(const T (&array)[N]) {
typename p6##_type, typename p7##_type, typename p8##_type>\
template <typename arg_type>\
bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
p5##_type, p6##_type, p7##_type, p8##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p5##_type, p6##_type, p7##_type, \
p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\
template <typename p0##_type, typename p1##_type, typename p2##_type, \
...
...
@@ -1689,7 +1760,8 @@ ElementsAreArray(const T (&array)[N]) {
: p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
p8(gmock_p8), p9(gmock_p9), gmock_interp_(gmock_interp) {}\
virtual bool Matches(arg_type arg) const;\
virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...
...
@@ -1763,7 +1835,10 @@ ElementsAreArray(const T (&array)[N]) {
typename p9##_type>\
template <typename arg_type>\
bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>::\
gmock_Impl<arg_type>::Matches(arg_type arg) const
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
include/gmock/gmock-generated-matchers.h.pump
View file @
82113318
...
...
@@ -116,8 +116,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
explicit
ArgsMatcherImpl
(
const
InnerMatcher
&
inner_matcher
)
:
inner_matcher_
(
SafeMatcherCast
<
const
SelectedArgs
&>
(
inner_matcher
))
{}
virtual
bool
Matches
(
ArgsTuple
args
)
const
{
return
inner_matcher_
.
Matches
(
GetSelectedArgs
(
args
));
virtual
bool
MatchAndExplain
(
ArgsTuple
args
,
MatchResultListener
*
listener
)
const
{
return
inner_matcher_
.
MatchAndExplain
(
GetSelectedArgs
(
args
),
listener
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
...
...
@@ -130,11 +131,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
inner_matcher_
.
DescribeNegationTo
(
os
);
}
virtual
void
ExplainMatchResultTo
(
ArgsTuple
args
,
::
std
::
ostream
*
os
)
const
{
inner_matcher_
.
ExplainMatchResultTo
(
GetSelectedArgs
(
args
),
os
);
}
private:
static
SelectedArgs
GetSelectedArgs
(
ArgsTuple
args
)
{
return
TupleFields
<
RawArgsTuple
,
$
ks
>::
GetSelectedFields
(
args
);
...
...
@@ -301,14 +297,19 @@ $$ // show up in the generated code.
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax:
// define custom matchers easily.
//
// Basic Usage
// ===========
//
// The syntax
//
// MATCHER(name, description_string) { statements; }
//
//
will
define a matcher with the given name that executes the
//
statements,
which must return a bool to indicate if the match
//
succeeds. Inside
the statements, you can refer to the value being
//
matched by 'arg',
and refer to its type by 'arg_type'.
// define
s
a matcher with the given name that executes the
statements,
// which must return a bool to indicate if the match
succeeds. Inside
// the statements, you can refer to the value being
matched by 'arg',
// and refer to its type by 'arg_type'.
//
// The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a
...
...
@@ -341,6 +342,9 @@ $$ // show up in the generated code.
// where the description "is even" is automatically calculated from the
// matcher name IsEven.
//
// Argument Type
// =============
//
// Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about
...
...
@@ -351,6 +355,9 @@ $$ // show up in the generated code.
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on.
//
// Parameterizing Matchers
// =======================
//
// Sometimes you'll want to parameterize the matcher. For that you
// can use another macro:
//
...
...
@@ -381,6 +388,9 @@ $$ // show up in the generated code.
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
// support multi-parameter matchers.
//
// Describing Parameterized Matchers
// =================================
//
// When defining a parameterized matcher, you can use Python-style
// interpolations in the description string to refer to the parameter
// values. We support the following syntax currently:
...
...
@@ -413,6 +423,9 @@ $$ // show up in the generated code.
//
// Expected: in closed range (4, 6)
//
// Types of Matcher Parameters
// ===========================
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
...
...
@@ -440,23 +453,44 @@ $$ // show up in the generated code.
// matcher you will see the value of the referenced object but not its
// address.
//
// Explaining Match Results
// ========================
//
// Sometimes the matcher description alone isn't enough to explain why
// the match has failed or succeeded. For example, when expecting a
// long string, it can be very helpful to also print the diff between
// the expected string and the actual one. To achieve that, you can
// optionally stream additional information to a special variable
// named result_listener, whose type is a pointer to class
// MatchResultListener:
//
// MATCHER_P(EqualsLongString, str, "") {
// if (arg == str) return true;
//
// *result_listener << "the difference: "
/// << DiffStrings(str, arg);
// return false;
// }
//
// Overloading Matchers
// ====================
//
// You can overload matchers with different numbers of parameters:
//
// MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... }
//
// While it's tempting to always use the MATCHER* macros when defining
// a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher() instead,
// especially if you need to use the matcher a lot. While these
// approaches require more work, they give you more control on the
// types of the value being matched and the matcher parameters, which
// in general leads to better compiler error messages that pay off in
// the long run. They also allow overloading matchers based on
// parameter types (as opposed to just based on the number of
// parameters).
// Caveats
// =======
//
// CAVEAT:
// When defining a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher(). These
// approaches require more work than the MATCHER* macros, but also
// give you more control on the types of the value being matched and
// the matcher parameters, which may leads to better compiler error
// messages when the matcher is used wrong. They also allow
// overloading matchers based on parameter types (as opposed to just
// based on the number of parameters).
//
// MATCHER*() can only be used in a namespace scope. The reason is
// that C++ doesn't yet allow function-local types to be used to
...
...
@@ -464,7 +498,8 @@ $$ // show up in the generated code.
// Once that's done, we'll consider supporting using MATCHER*() inside
// a function.
//
// MORE INFORMATION:
// More Information
// ================
//
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
...
...
@@ -510,7 +545,8 @@ $var param_field_decls2 = [[$for j
public
:
\
[[
$
if
i
==
1
[[
explicit
]]]]
gmock_Impl
(
$
impl_ctor_param_list
)
\
$
impl_inits
{}
\
virtual
bool
Matches
(
arg_type
arg
)
const
;
\
virtual
bool
MatchAndExplain
(
\
arg_type
arg
,
::
testing
::
MatchResultListener
*
result_listener
)
const
;
\
virtual
void
DescribeTo
(
::
std
::
ostream
*
gmock_os
)
const
{
\
const
::
testing
::
internal
::
Strings
&
gmock_printed_params
=
\
::
testing
::
internal
::
UniversalTersePrintTupleFieldsToStrings
(
\
...
...
@@ -540,8 +576,10 @@ $var param_field_decls2 = [[$for j
return
$
class_name
$
param_types
(
$
params
);
\
}\$
template
template
<
typename
arg_type
>
\
bool
$
class_name
$
param_types
::
\
gmock_Impl
<
arg_type
>
::
Matches
(
arg_type
arg
)
const
bool
$
class_name
$
param_types
::
gmock_Impl
<
arg_type
>
::
MatchAndExplain
(
\
arg_type
arg
,
\
::
testing
::
MatchResultListener
*
result_listener
GTEST_ATTRIBUTE_UNUSED_
)
\
const
]]
...
...
include/gmock/gmock-matchers.h
View file @
82113318
This diff is collapsed.
Click to expand it.
include/gmock/gmock-spec-builders.h
View file @
82113318
...
...
@@ -1004,13 +1004,13 @@ class TypedExpectation : public ExpectationBase {
if
(
!
TupleMatches
(
matchers_
,
args
))
{
DescribeMatchFailureTupleTo
(
matchers_
,
args
,
os
);
}
if
(
!
extra_matcher_
.
Matches
(
args
))
{
StringMatchResultListener
listener
;
if
(
!
extra_matcher_
.
MatchAndExplain
(
args
,
&
listener
))
{
*
os
<<
" Expected args: "
;
extra_matcher_
.
DescribeTo
(
os
);
*
os
<<
"
\n
Actual: don't match"
;
internal
::
ExplainMatchResultAsNeededTo
<
const
ArgumentTuple
&>
(
extra_matcher_
,
args
,
os
);
internal
::
StreamInParensAsNeeded
(
listener
.
str
(),
os
);
*
os
<<
"
\n
"
;
}
}
else
if
(
!
AllPrerequisitesAreSatisfied
())
{
...
...
test/gmock-generated-matchers_test.cc
View file @
82113318
...
...
@@ -136,6 +136,16 @@ TEST(ArgsTest, AcceptsDecreasingTemplateArgs) {
EXPECT_THAT
(
t
,
Not
(
Args
<
2
,
1
>
(
Lt
())));
}
// The MATCHER*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4100)
#endif
MATCHER
(
SumIsZero
,
""
)
{
return
get
<
0
>
(
arg
)
+
get
<
1
>
(
arg
)
+
get
<
2
>
(
arg
)
==
0
;
}
...
...
@@ -553,6 +563,44 @@ TEST(MatcherMacroTest, Works) {
EXPECT_EQ
(
""
,
Explain
(
m
,
7
));
}
// Tests explaining match result in a MATCHER* macro.
MATCHER
(
IsEven2
,
"is even"
)
{
if
((
arg
%
2
)
==
0
)
{
// Verifies that we can stream to result_listener, a listener
// supplied by the MATCHER macro implicitly.
*
result_listener
<<
"OK"
;
return
true
;
}
else
{
*
result_listener
<<
"% 2 == "
<<
(
arg
%
2
);
return
false
;
}
}
MATCHER_P2
(
EqSumOf
,
x
,
y
,
""
)
{
if
(
arg
==
(
x
+
y
))
{
*
result_listener
<<
"OK"
;
return
true
;
}
else
{
// Verifies that we can stream to the underlying stream of
// result_listener.
if
(
result_listener
->
stream
()
!=
NULL
)
{
*
result_listener
->
stream
()
<<
"diff == "
<<
(
x
+
y
-
arg
);
}
return
false
;
}
}
TEST
(
MatcherMacroTest
,
CanExplainMatchResult
)
{
const
Matcher
<
int
>
m1
=
IsEven2
();
EXPECT_EQ
(
"OK"
,
Explain
(
m1
,
4
));
EXPECT_EQ
(
"% 2 == 1"
,
Explain
(
m1
,
5
));
const
Matcher
<
int
>
m2
=
EqSumOf
(
1
,
2
);
EXPECT_EQ
(
"OK"
,
Explain
(
m2
,
3
));
EXPECT_EQ
(
"diff == -1"
,
Explain
(
m2
,
4
));
}
// Tests that the description string supplied to MATCHER() must be
// valid.
...
...
@@ -1052,4 +1100,8 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
EXPECT_THAT
(
a
,
Contains
(
Not
(
Contains
(
5
))));
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
// namespace
test/gmock-matchers_test.cc
View file @
82113318
...
...
@@ -88,6 +88,7 @@ using testing::Matcher;
using
testing
::
MatcherCast
;
using
testing
::
MatcherInterface
;
using
testing
::
Matches
;
using
testing
::
MatchResultListener
;
using
testing
::
NanSensitiveDoubleEq
;
using
testing
::
NanSensitiveFloatEq
;
using
testing
::
Ne
;
...
...
@@ -200,10 +201,39 @@ class EvenMatcherImpl : public MatcherInterface<int> {
// two methods is optional.
};
TEST
(
MatcherInterfaceTest
,
CanBeImplemented
)
{
TEST
(
MatcherInterfaceTest
,
CanBeImplemented
UsingDeprecatedAPI
)
{
EvenMatcherImpl
m
;
}
// Tests implementing a monomorphic matcher using MatchAndExplain().
class
NewEvenMatcherImpl
:
public
MatcherInterface
<
int
>
{
public:
virtual
bool
MatchAndExplain
(
int
x
,
MatchResultListener
*
listener
)
const
{
const
bool
match
=
x
%
2
==
0
;
// Verifies that we can stream to a listener directly.
*
listener
<<
"value % "
<<
2
;
if
(
listener
->
stream
()
!=
NULL
)
{
// Verifies that we can stream to a listener's underlying stream
// too.
*
listener
->
stream
()
<<
" == "
<<
(
x
%
2
);
}
return
match
;
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is an even number"
;
}
};
TEST
(
MatcherInterfaceTest
,
CanBeImplementedUsingNewAPI
)
{
Matcher
<
int
>
m
=
MakeMatcher
(
new
NewEvenMatcherImpl
);
EXPECT_TRUE
(
m
.
Matches
(
2
));
EXPECT_FALSE
(
m
.
Matches
(
3
));
EXPECT_EQ
(
"value % 2 == 0"
,
Explain
(
m
,
2
));
EXPECT_EQ
(
"value % 2 == 1"
,
Explain
(
m
,
3
));
}
// Tests default-constructing a matcher.
TEST
(
MatcherTest
,
CanBeDefaultConstructed
)
{
Matcher
<
double
>
m
;
...
...
@@ -252,6 +282,18 @@ TEST(MatcherTest, CanDescribeItself) {
Describe
(
Matcher
<
int
>
(
new
EvenMatcherImpl
)));
}
// Tests Matcher<T>::MatchAndExplain().
TEST
(
MatcherTest
,
MatchAndExplain
)
{
Matcher
<
int
>
m
=
GreaterThan
(
0
);
::
testing
::
internal
::
StringMatchResultListener
listener1
;
EXPECT_TRUE
(
m
.
MatchAndExplain
(
42
,
&
listener1
));
EXPECT_EQ
(
"is 42 more than 0"
,
listener1
.
str
());
::
testing
::
internal
::
StringMatchResultListener
listener2
;
EXPECT_FALSE
(
m
.
MatchAndExplain
(
-
9
,
&
listener2
));
EXPECT_EQ
(
"is 9 less than 0"
,
listener2
.
str
());
}
// Tests that a C-string literal can be implicitly converted to a
// Matcher<string> or Matcher<const string&>.
TEST
(
StringMatcherTest
,
CanBeImplicitlyConstructedFromCStringLiteral
)
{
...
...
@@ -284,8 +326,8 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
Matcher
<
int
>
m
=
MakeMatcher
(
dummy_impl
);
}
// Tests that MakePolymorphicMatcher() construct
s
a polymorphic
// matcher from its implementation.
// Tests that MakePolymorphicMatcher()
can
construct a polymorphic
// matcher from its implementation
using the old API
.
const
int
bar
=
1
;
class
ReferencesBarOrIsZeroImpl
{
public:
...
...
@@ -308,7 +350,7 @@ PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() {
return
MakePolymorphicMatcher
(
ReferencesBarOrIsZeroImpl
());
}
TEST
(
MakePolymorphicMatcherTest
,
ConstructsMatcher
FromImpl
)
{
TEST
(
MakePolymorphicMatcherTest
,
ConstructsMatcher
UsingOldAPI
)
{
// Using a polymorphic matcher to match a reference type.
Matcher
<
const
int
&>
m1
=
ReferencesBarOrIsZero
();
EXPECT_TRUE
(
m1
.
Matches
(
0
));
...
...
@@ -324,6 +366,58 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) {
EXPECT_EQ
(
"bar or zero"
,
Describe
(
m2
));
}
// Tests implementing a polymorphic matcher using MatchAndExplain().
class
PolymorphicIsEvenImpl
{
public:
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is even"
;
}
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is odd"
;
}
};
template
<
typename
T
>
bool
MatchAndExplain
(
const
PolymorphicIsEvenImpl
&
/* impl */
,
T
x
,
MatchResultListener
*
listener
)
{
// Verifies that we can stream to the listener directly.
*
listener
<<
"% "
<<
2
;
if
(
listener
->
stream
()
!=
NULL
)
{
// Verifies that we can stream to the listener's underlying stream
// too.
*
listener
->
stream
()
<<
" == "
<<
(
x
%
2
);
}
return
(
x
%
2
)
==
0
;
}
PolymorphicMatcher
<
PolymorphicIsEvenImpl
>
PolymorphicIsEven
()
{
return
MakePolymorphicMatcher
(
PolymorphicIsEvenImpl
());
}
TEST
(
MakePolymorphicMatcherTest
,
ConstructsMatcherUsingNewAPI
)
{
// Using PolymorphicIsEven() as a Matcher<int>.
const
Matcher
<
int
>
m1
=
PolymorphicIsEven
();
EXPECT_TRUE
(
m1
.
Matches
(
42
));
EXPECT_FALSE
(
m1
.
Matches
(
43
));
EXPECT_EQ
(
"is even"
,
Describe
(
m1
));
const
Matcher
<
int
>
not_m1
=
Not
(
m1
);
EXPECT_EQ
(
"is odd"
,
Describe
(
not_m1
));
EXPECT_EQ
(
"% 2 == 0"
,
Explain
(
m1
,
42
));
// Using PolymorphicIsEven() as a Matcher<char>.
const
Matcher
<
char
>
m2
=
PolymorphicIsEven
();
EXPECT_TRUE
(
m2
.
Matches
(
'\x42'
));
EXPECT_FALSE
(
m2
.
Matches
(
'\x43'
));
EXPECT_EQ
(
"is even"
,
Describe
(
m2
));
const
Matcher
<
char
>
not_m2
=
Not
(
m2
);
EXPECT_EQ
(
"is odd"
,
Describe
(
not_m2
));
EXPECT_EQ
(
"% 2 == 0"
,
Explain
(
m2
,
'\x42'
));
}
// Tests that MatcherCast<T>(m) works when m is a polymorphic matcher.
TEST
(
MatcherCastTest
,
FromPolymorphicMatcher
)
{
Matcher
<
int
>
m
=
MatcherCast
<
int
>
(
Eq
(
5
));
...
...
@@ -1050,21 +1144,26 @@ TEST(PairTest, CanDescribeSelf) {
}
TEST
(
PairTest
,
CanExplainMatchResultTo
)
{
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m0
=
Pair
(
0
,
0
);
EXPECT_EQ
(
""
,
Explain
(
m0
,
std
::
make_pair
(
25
,
42
)));
// If neither field matches, Pair() should explain about the first
// field.
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m
=
Pair
(
GreaterThan
(
0
),
GreaterThan
(
0
));
EXPECT_EQ
(
"the first field is 1 less than 0"
,
Explain
(
m
,
std
::
make_pair
(
-
1
,
-
2
)));
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m1
=
Pair
(
GreaterThan
(
0
),
0
);
EXPECT_EQ
(
"the first field is 25 more than 0"
,
Explain
(
m1
,
std
::
make_pair
(
25
,
42
)));
// If the first field matches but the second doesn't, Pair() should
// explain about the second field.
EXPECT_EQ
(
"the second field is 2 less than 0"
,
Explain
(
m
,
std
::
make_pair
(
1
,
-
2
)));
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m2
=
Pair
(
0
,
GreaterThan
(
0
));
EXPECT_EQ
(
"the second field is 42 more than 0"
,
Explain
(
m2
,
std
::
make_pair
(
25
,
42
)));
// If the first field doesn't match but the second does, Pair()
// should explain about the first field.
EXPECT_EQ
(
"the first field is 1 less than 0"
,
Explain
(
m
,
std
::
make_pair
(
-
1
,
2
)));
const
Matcher
<
std
::
pair
<
int
,
int
>
>
m3
=
Pair
(
GreaterThan
(
0
),
GreaterThan
(
0
));
EXPECT_EQ
(
"the first field is
25
more than 0"
", and the second field is
4
2 more than 0"
,
Explain
(
m
3
,
std
::
make_pair
(
25
,
4
2
)));
// If both fields match, Pair() should explain about them both.
EXPECT_EQ
(
"the first field is
1
more than 0"
", and the second field is 2 more than 0"
,
Explain
(
m
,
std
::
make_pair
(
1
,
2
)));
}
TEST
(
PairTest
,
MatchesCorrectly
)
{
...
...
@@ -3335,6 +3434,16 @@ TEST(ValidateMatcherDescriptionTest,
ElementsAre
());
}
// The MATCHER*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4100)
#endif
// We use MATCHER_P3() to define a matcher for testing
// ValidateMatcherDescription(); otherwise we'll end up with much
// plumbing code. This is not circular as
...
...
@@ -3345,6 +3454,10 @@ MATCHER_P3(EqInterpolation, start, end, index, "equals Interpolation%(*)s") {
arg
.
param_index
==
index
;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsPercentInterpolation
)
{
const
char
*
params
[]
=
{
"foo"
,
NULL
};
const
char
*
const
desc
=
"one %%"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment