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
506340a6
Commit
506340a6
authored
Nov 17, 2014
by
kosak
Browse files
Generate relational matchers (Eq,Lt, etc) with CRTP instead of macro.
parent
d370f85b
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
166 additions
and
93 deletions
+166
-93
include/gmock/gmock-matchers.h
include/gmock/gmock-matchers.h
+164
-91
test/gmock-matchers_test.cc
test/gmock-matchers_test.cc
+2
-2
No files found.
include/gmock/gmock-matchers.h
View file @
506340a6
...
...
@@ -199,6 +199,31 @@ class StringMatchResultListener : public MatchResultListener {
namespace
internal
{
struct
AnyEq
{
template
<
typename
A
,
typename
B
>
bool
operator
()(
const
A
&
a
,
const
B
&
b
)
const
{
return
a
==
b
;
}
};
struct
AnyNe
{
template
<
typename
A
,
typename
B
>
bool
operator
()(
const
A
&
a
,
const
B
&
b
)
const
{
return
a
!=
b
;
}
};
struct
AnyLt
{
template
<
typename
A
,
typename
B
>
bool
operator
()(
const
A
&
a
,
const
B
&
b
)
const
{
return
a
<
b
;
}
};
struct
AnyGt
{
template
<
typename
A
,
typename
B
>
bool
operator
()(
const
A
&
a
,
const
B
&
b
)
const
{
return
a
>
b
;
}
};
struct
AnyLe
{
template
<
typename
A
,
typename
B
>
bool
operator
()(
const
A
&
a
,
const
B
&
b
)
const
{
return
a
<=
b
;
}
};
struct
AnyGe
{
template
<
typename
A
,
typename
B
>
bool
operator
()(
const
A
&
a
,
const
B
&
b
)
const
{
return
a
>=
b
;
}
};
// A match result listener that ignores the explanation.
class
DummyMatchResultListener
:
public
MatchResultListener
{
public:
...
...
@@ -862,55 +887,90 @@ class AnythingMatcher {
// used to match an int, a short, a double, etc). Therefore we use
// a template type conversion operator in the implementation.
//
// We define this as a macro in order to eliminate duplicated source
// code.
//
// The following template definition assumes that the Rhs parameter is
// a "bare" type (i.e. neither 'const T' nor 'T&').
#define GMOCK_IMPLEMENT_COMPARISON_MATCHER_( \
name, op, relation, negated_relation) \
template <typename Rhs> class name##Matcher { \
public: \
explicit name##Matcher(const Rhs& rhs) : rhs_(rhs) {} \
template <typename Lhs> \
operator Matcher<Lhs>() const { \
return MakeMatcher(new Impl<Lhs>(rhs_)); \
} \
private: \
template <typename Lhs> \
class Impl : public MatcherInterface<Lhs> { \
public: \
explicit Impl(const Rhs& rhs) : rhs_(rhs) {} \
virtual bool MatchAndExplain(\
Lhs lhs, MatchResultListener*
/* listener */
) const { \
return lhs op rhs_; \
} \
virtual void DescribeTo(::std::ostream* os) const { \
*os << relation " "; \
UniversalPrint(rhs_, os); \
} \
virtual void DescribeNegationTo(::std::ostream* os) const { \
*os << negated_relation " "; \
UniversalPrint(rhs_, os); \
} \
private: \
Rhs rhs_; \
GTEST_DISALLOW_ASSIGN_(Impl); \
}; \
Rhs rhs_; \
GTEST_DISALLOW_ASSIGN_(name##Matcher); \
}
// Implements Eq(v), Ge(v), Gt(v), Le(v), Lt(v), and Ne(v)
// respectively.
GMOCK_IMPLEMENT_COMPARISON_MATCHER_
(
Eq
,
==
,
"is equal to"
,
"isn't equal to"
);
GMOCK_IMPLEMENT_COMPARISON_MATCHER_
(
Ge
,
>=
,
"is >="
,
"isn't >="
);
GMOCK_IMPLEMENT_COMPARISON_MATCHER_
(
Gt
,
>
,
"is >"
,
"isn't >"
);
GMOCK_IMPLEMENT_COMPARISON_MATCHER_
(
Le
,
<=
,
"is <="
,
"isn't <="
);
GMOCK_IMPLEMENT_COMPARISON_MATCHER_
(
Lt
,
<
,
"is <"
,
"isn't <"
);
GMOCK_IMPLEMENT_COMPARISON_MATCHER_
(
Ne
,
!=
,
"isn't equal to"
,
"is equal to"
);
template
<
typename
D
,
typename
Rhs
,
typename
Op
>
class
ComparisonBase
{
public:
explicit
ComparisonBase
(
const
Rhs
&
rhs
)
:
rhs_
(
rhs
)
{}
template
<
typename
Lhs
>
operator
Matcher
<
Lhs
>
()
const
{
return
MakeMatcher
(
new
Impl
<
Lhs
>
(
rhs_
));
}
#undef GMOCK_IMPLEMENT_COMPARISON_MATCHER_
private:
template
<
typename
Lhs
>
class
Impl
:
public
MatcherInterface
<
Lhs
>
{
public:
explicit
Impl
(
const
Rhs
&
rhs
)
:
rhs_
(
rhs
)
{}
virtual
bool
MatchAndExplain
(
Lhs
lhs
,
MatchResultListener
*
/* listener */
)
const
{
return
Op
()(
lhs
,
rhs_
);
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
D
::
Desc
()
<<
" "
;
UniversalPrint
(
rhs_
,
os
);
}
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
D
::
NegatedDesc
()
<<
" "
;
UniversalPrint
(
rhs_
,
os
);
}
private:
Rhs
rhs_
;
GTEST_DISALLOW_ASSIGN_
(
Impl
);
};
Rhs
rhs_
;
GTEST_DISALLOW_ASSIGN_
(
ComparisonBase
);
};
template
<
typename
Rhs
>
class
EqMatcher
:
public
ComparisonBase
<
EqMatcher
<
Rhs
>
,
Rhs
,
AnyEq
>
{
public:
explicit
EqMatcher
(
const
Rhs
&
rhs
)
:
ComparisonBase
<
EqMatcher
<
Rhs
>
,
Rhs
,
AnyEq
>
(
rhs
)
{
}
static
const
char
*
Desc
()
{
return
"is equal to"
;
}
static
const
char
*
NegatedDesc
()
{
return
"isn't equal to"
;
}
};
template
<
typename
Rhs
>
class
NeMatcher
:
public
ComparisonBase
<
NeMatcher
<
Rhs
>
,
Rhs
,
AnyNe
>
{
public:
explicit
NeMatcher
(
const
Rhs
&
rhs
)
:
ComparisonBase
<
NeMatcher
<
Rhs
>
,
Rhs
,
AnyNe
>
(
rhs
)
{
}
static
const
char
*
Desc
()
{
return
"isn't equal to"
;
}
static
const
char
*
NegatedDesc
()
{
return
"is equal to"
;
}
};
template
<
typename
Rhs
>
class
LtMatcher
:
public
ComparisonBase
<
LtMatcher
<
Rhs
>
,
Rhs
,
AnyLt
>
{
public:
explicit
LtMatcher
(
const
Rhs
&
rhs
)
:
ComparisonBase
<
LtMatcher
<
Rhs
>
,
Rhs
,
AnyLt
>
(
rhs
)
{
}
static
const
char
*
Desc
()
{
return
"is <"
;
}
static
const
char
*
NegatedDesc
()
{
return
"isn't <"
;
}
};
template
<
typename
Rhs
>
class
GtMatcher
:
public
ComparisonBase
<
GtMatcher
<
Rhs
>
,
Rhs
,
AnyGt
>
{
public:
explicit
GtMatcher
(
const
Rhs
&
rhs
)
:
ComparisonBase
<
GtMatcher
<
Rhs
>
,
Rhs
,
AnyGt
>
(
rhs
)
{
}
static
const
char
*
Desc
()
{
return
"is >"
;
}
static
const
char
*
NegatedDesc
()
{
return
"isn't >"
;
}
};
template
<
typename
Rhs
>
class
LeMatcher
:
public
ComparisonBase
<
LeMatcher
<
Rhs
>
,
Rhs
,
AnyLe
>
{
public:
explicit
LeMatcher
(
const
Rhs
&
rhs
)
:
ComparisonBase
<
LeMatcher
<
Rhs
>
,
Rhs
,
AnyLe
>
(
rhs
)
{
}
static
const
char
*
Desc
()
{
return
"is <="
;
}
static
const
char
*
NegatedDesc
()
{
return
"isn't <="
;
}
};
template
<
typename
Rhs
>
class
GeMatcher
:
public
ComparisonBase
<
GeMatcher
<
Rhs
>
,
Rhs
,
AnyGe
>
{
public:
explicit
GeMatcher
(
const
Rhs
&
rhs
)
:
ComparisonBase
<
GeMatcher
<
Rhs
>
,
Rhs
,
AnyGe
>
(
rhs
)
{
}
static
const
char
*
Desc
()
{
return
"is >="
;
}
static
const
char
*
NegatedDesc
()
{
return
"isn't >="
;
}
};
// Implements the polymorphic IsNull() matcher, which matches any raw or smart
// pointer that is NULL.
...
...
@@ -1309,51 +1369,64 @@ class MatchesRegexMatcher {
// used to match a tuple<int, short>, a tuple<const long&, double>,
// etc). Therefore we use a template type conversion operator in the
// implementation.
//
// We define this as a macro in order to eliminate duplicated source
// code.
#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op, relation) \
class name##2Matcher { \
public: \
template <typename T1, typename T2> \
operator Matcher< ::testing::tuple<T1, T2> >() const { \
return MakeMatcher(new Impl< ::testing::tuple<T1, T2> >); \
} \
template <typename T1, typename T2> \
operator Matcher<const ::testing::tuple<T1, T2>&>() const { \
return MakeMatcher(new Impl<const ::testing::tuple<T1, T2>&>); \
} \
private: \
template <typename Tuple> \
class Impl : public MatcherInterface<Tuple> { \
public: \
virtual bool MatchAndExplain( \
Tuple args, \
MatchResultListener*
/* listener */
) const { \
return ::testing::get<0>(args) op ::testing::get<1>(args); \
} \
virtual void DescribeTo(::std::ostream* os) const { \
*os << "are " relation; \
} \
virtual void DescribeNegationTo(::std::ostream* os) const { \
*os << "aren't " relation; \
} \
}; \
}
// Implements Eq(), Ge(), Gt(), Le(), Lt(), and Ne() respectively.
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
(
Eq
,
==
,
"an equal pair"
);
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
(
Ge
,
>=
,
"a pair where the first >= the second"
);
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
(
Gt
,
>
,
"a pair where the first > the second"
);
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
(
Le
,
<=
,
"a pair where the first <= the second"
);
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
(
Lt
,
<
,
"a pair where the first < the second"
);
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
(
Ne
,
!=
,
"an unequal pair"
);
#undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
template
<
typename
D
,
typename
Op
>
class
PairMatchBase
{
public:
template
<
typename
T1
,
typename
T2
>
operator
Matcher
<
::
testing
::
tuple
<
T1
,
T2
>
>
()
const
{
return
MakeMatcher
(
new
Impl
<
::
testing
::
tuple
<
T1
,
T2
>
>
);
}
template
<
typename
T1
,
typename
T2
>
operator
Matcher
<
const
::
testing
::
tuple
<
T1
,
T2
>&>
()
const
{
return
MakeMatcher
(
new
Impl
<
const
::
testing
::
tuple
<
T1
,
T2
>&>
);
}
private:
static
::
std
::
ostream
&
GetDesc
(
::
std
::
ostream
&
os
)
{
// NOLINT
return
os
<<
D
::
Desc
();
}
template
<
typename
Tuple
>
class
Impl
:
public
MatcherInterface
<
Tuple
>
{
public:
virtual
bool
MatchAndExplain
(
Tuple
args
,
MatchResultListener
*
/* listener */
)
const
{
return
Op
()(
::
testing
::
get
<
0
>
(
args
),
::
testing
::
get
<
1
>
(
args
));
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"are "
<<
GetDesc
;
}
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"aren't "
<<
GetDesc
;
}
};
};
class
Eq2Matcher
:
public
PairMatchBase
<
Eq2Matcher
,
AnyEq
>
{
public:
static
const
char
*
Desc
()
{
return
"an equal pair"
;
}
};
class
Ne2Matcher
:
public
PairMatchBase
<
Ne2Matcher
,
AnyNe
>
{
public:
static
const
char
*
Desc
()
{
return
"an unequal pair"
;
}
};
class
Lt2Matcher
:
public
PairMatchBase
<
Lt2Matcher
,
AnyLt
>
{
public:
static
const
char
*
Desc
()
{
return
"a pair where the first < the second"
;
}
};
class
Gt2Matcher
:
public
PairMatchBase
<
Gt2Matcher
,
AnyGt
>
{
public:
static
const
char
*
Desc
()
{
return
"a pair where the first > the second"
;
}
};
class
Le2Matcher
:
public
PairMatchBase
<
Le2Matcher
,
AnyLe
>
{
public:
static
const
char
*
Desc
()
{
return
"a pair where the first <= the second"
;
}
};
class
Ge2Matcher
:
public
PairMatchBase
<
Ge2Matcher
,
AnyGe
>
{
public:
static
const
char
*
Desc
()
{
return
"a pair where the first >= the second"
;
}
};
// Implements the Not(...) matcher for a particular argument type T.
// We do not nest it inside the NotMatcher class template, as that
...
...
test/gmock-matchers_test.cc
View file @
506340a6
...
...
@@ -607,11 +607,11 @@ TEST(MatcherCastTest, FromSameType) {
EXPECT_FALSE
(
m2
.
Matches
(
1
));
}
// Implicitly convertible f
o
rm any type.
// Implicitly convertible fr
o
m any type.
struct
ConvertibleFromAny
{
ConvertibleFromAny
(
int
a_value
)
:
value
(
a_value
)
{}
template
<
typename
T
>
ConvertibleFromAny
(
const
T
&
a_value
)
:
value
(
-
1
)
{
ConvertibleFromAny
(
const
T
&
/*
a_value
*/
)
:
value
(
-
1
)
{
ADD_FAILURE
()
<<
"Conversion constructor called"
;
}
int
value
;
...
...
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