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
466a49ae
Commit
466a49ae
authored
Mar 23, 2018
by
Gennadiy Civil
Browse files
gmock-matchers merging -2
parent
a28a7eb5
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
250 additions
and
10 deletions
+250
-10
googlemock/include/gmock/gmock-matchers.h
googlemock/include/gmock/gmock-matchers.h
+250
-10
No files found.
googlemock/include/gmock/gmock-matchers.h
View file @
466a49ae
...
@@ -179,6 +179,35 @@ class MatcherInterface : public MatcherDescriberInterface {
...
@@ -179,6 +179,35 @@ class MatcherInterface : public MatcherDescriberInterface {
// virtual void DescribeNegationTo(::std::ostream* os) const;
// virtual void DescribeNegationTo(::std::ostream* os) const;
};
};
namespace
internal
{
// Converts a MatcherInterface<T> to a MatcherInterface<const T&>.
template
<
typename
T
>
class
MatcherInterfaceAdapter
:
public
MatcherInterface
<
const
T
&>
{
public:
explicit
MatcherInterfaceAdapter
(
const
MatcherInterface
<
T
>*
impl
)
:
impl_
(
impl
)
{}
virtual
~
MatcherInterfaceAdapter
()
{
delete
impl_
;
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
impl_
->
DescribeTo
(
os
);
}
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
impl_
->
DescribeNegationTo
(
os
);
}
virtual
bool
MatchAndExplain
(
const
T
&
x
,
MatchResultListener
*
listener
)
const
{
return
impl_
->
MatchAndExplain
(
x
,
listener
);
}
private:
const
MatcherInterface
<
T
>*
const
impl_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
MatcherInterfaceAdapter
);
};
}
// namespace internal
// A match result listener that stores the explanation in a string.
// A match result listener that stores the explanation in a string.
class
StringMatchResultListener
:
public
MatchResultListener
{
class
StringMatchResultListener
:
public
MatchResultListener
{
public:
public:
...
@@ -290,6 +319,14 @@ class MatcherBase {
...
@@ -290,6 +319,14 @@ class MatcherBase {
explicit
MatcherBase
(
const
MatcherInterface
<
T
>*
impl
)
explicit
MatcherBase
(
const
MatcherInterface
<
T
>*
impl
)
:
impl_
(
impl
)
{}
:
impl_
(
impl
)
{}
template
<
typename
U
>
explicit
MatcherBase
(
const
MatcherInterface
<
U
>*
impl
,
typename
internal
::
EnableIf
<
!
internal
::
IsSame
<
U
,
GTEST_REFERENCE_TO_CONST_
(
U
)
>::
value
>::
type
*
=
NULL
)
:
impl_
(
new
internal
::
MatcherInterfaceAdapter
<
U
>
(
impl
))
{}
virtual
~
MatcherBase
()
{}
virtual
~
MatcherBase
()
{}
private:
private:
...
@@ -551,21 +588,18 @@ class MatcherCastImpl {
...
@@ -551,21 +588,18 @@ class MatcherCastImpl {
return
CastImpl
(
return
CastImpl
(
polymorphic_matcher_or_value
,
polymorphic_matcher_or_value
,
BooleanConstant
<
BooleanConstant
<
internal
::
ImplicitlyConvertible
<
M
,
Matcher
<
T
>
>::
value
>
());
internal
::
ImplicitlyConvertible
<
M
,
Matcher
<
T
>
>::
value
>
(),
BooleanConstant
<
internal
::
ImplicitlyConvertible
<
M
,
T
>::
value
>
());
}
}
private:
private:
static
Matcher
<
T
>
CastImpl
(
const
M
&
value
,
BooleanConstant
<
false
>
)
{
template
<
bool
Ignore
>
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
// matcher. It must be a value then. Use direct initialization to create
// a matcher.
return
Matcher
<
T
>
(
ImplicitCast_
<
T
>
(
value
));
}
static
Matcher
<
T
>
CastImpl
(
const
M
&
polymorphic_matcher_or_value
,
static
Matcher
<
T
>
CastImpl
(
const
M
&
polymorphic_matcher_or_value
,
BooleanConstant
<
true
>
)
{
BooleanConstant
<
true
>
/* convertible_to_matcher */
,
BooleanConstant
<
Ignore
>
)
{
// M is implicitly convertible to Matcher<T>, which means that either
// M is implicitly convertible to Matcher<T>, which means that either
// M is a polymor
h
pic matcher or Matcher<T> has an implicit constructor
// M is a polymorp
h
ic matcher or Matcher<T> has an implicit constructor
// from M. In both cases using the implicit conversion will produce a
// from M. In both cases using the implicit conversion will produce a
// matcher.
// matcher.
//
//
...
@@ -574,6 +608,29 @@ class MatcherCastImpl {
...
@@ -574,6 +608,29 @@ class MatcherCastImpl {
// (first to create T from M and then to create Matcher<T> from T).
// (first to create T from M and then to create Matcher<T> from T).
return
polymorphic_matcher_or_value
;
return
polymorphic_matcher_or_value
;
}
}
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
// matcher. It's a value of a type implicitly convertible to T. Use direct
// initialization to create a matcher.
static
Matcher
<
T
>
CastImpl
(
const
M
&
value
,
BooleanConstant
<
false
>
/* convertible_to_matcher */
,
BooleanConstant
<
true
>
/* convertible_to_T */
)
{
return
Matcher
<
T
>
(
ImplicitCast_
<
T
>
(
value
));
}
// M can't be implicitly converted to either Matcher<T> or T. Attempt to use
// polymorphic matcher Eq(value) in this case.
//
// Note that we first attempt to perform an implicit cast on the value and
// only fall back to the polymorphic Eq() matcher afterwards because the
// latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end
// which might be undefined even when Rhs is implicitly convertible to Lhs
// (e.g. std::pair<const int, int> vs. std::pair<int, int>).
//
// We don't define this method inline as we need the declaration of Eq().
static
Matcher
<
T
>
CastImpl
(
const
M
&
value
,
BooleanConstant
<
false
>
/* convertible_to_matcher */
,
BooleanConstant
<
false
>
/* convertible_to_T */
);
};
};
// This more specialized version is used when MatcherCast()'s argument
// This more specialized version is used when MatcherCast()'s argument
...
@@ -2057,6 +2114,78 @@ class FloatingEqMatcher {
...
@@ -2057,6 +2114,78 @@ class FloatingEqMatcher {
GTEST_DISALLOW_ASSIGN_
(
FloatingEqMatcher
);
GTEST_DISALLOW_ASSIGN_
(
FloatingEqMatcher
);
};
};
// A 2-tuple ("binary") wrapper around FloatingEqMatcher:
// FloatingEq2Matcher() matches (x, y) by matching FloatingEqMatcher(x, false)
// against y, and FloatingEq2Matcher(e) matches FloatingEqMatcher(x, false, e)
// against y. The former implements "Eq", the latter "Near". At present, there
// is no version that compares NaNs as equal.
template
<
typename
FloatType
>
class
FloatingEq2Matcher
{
public:
FloatingEq2Matcher
()
:
FloatingEq2Matcher
(
-
1
,
false
)
{}
explicit
FloatingEq2Matcher
(
bool
nan_eq_nan
)
:
FloatingEq2Matcher
(
-
1
,
nan_eq_nan
)
{}
explicit
FloatingEq2Matcher
(
FloatType
max_abs_error
)
:
FloatingEq2Matcher
(
max_abs_error
,
false
)
{}
FloatingEq2Matcher
(
FloatType
max_abs_error
,
bool
nan_eq_nan
)
:
max_abs_error_
(
max_abs_error
),
nan_eq_nan_
(
nan_eq_nan
)
{}
template
<
typename
T1
,
typename
T2
>
operator
Matcher
<
::
testing
::
tuple
<
T1
,
T2
>
>
()
const
{
return
MakeMatcher
(
new
Impl
<
::
testing
::
tuple
<
T1
,
T2
>
>
(
max_abs_error_
,
nan_eq_nan_
));
}
template
<
typename
T1
,
typename
T2
>
operator
Matcher
<
const
::
testing
::
tuple
<
T1
,
T2
>&>
()
const
{
return
MakeMatcher
(
new
Impl
<
const
::
testing
::
tuple
<
T1
,
T2
>&>
(
max_abs_error_
,
nan_eq_nan_
));
}
private:
static
::
std
::
ostream
&
GetDesc
(
::
std
::
ostream
&
os
)
{
// NOLINT
return
os
<<
"an almost-equal pair"
;
}
template
<
typename
Tuple
>
class
Impl
:
public
MatcherInterface
<
Tuple
>
{
public:
Impl
(
FloatType
max_abs_error
,
bool
nan_eq_nan
)
:
max_abs_error_
(
max_abs_error
),
nan_eq_nan_
(
nan_eq_nan
)
{}
virtual
bool
MatchAndExplain
(
Tuple
args
,
MatchResultListener
*
listener
)
const
{
if
(
max_abs_error_
==
-
1
)
{
FloatingEqMatcher
<
FloatType
>
fm
(
::
testing
::
get
<
0
>
(
args
),
nan_eq_nan_
);
return
static_cast
<
Matcher
<
FloatType
>
>
(
fm
).
MatchAndExplain
(
::
testing
::
get
<
1
>
(
args
),
listener
);
}
else
{
FloatingEqMatcher
<
FloatType
>
fm
(
::
testing
::
get
<
0
>
(
args
),
nan_eq_nan_
,
max_abs_error_
);
return
static_cast
<
Matcher
<
FloatType
>
>
(
fm
).
MatchAndExplain
(
::
testing
::
get
<
1
>
(
args
),
listener
);
}
}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"are "
<<
GetDesc
;
}
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"aren't "
<<
GetDesc
;
}
private:
FloatType
max_abs_error_
;
const
bool
nan_eq_nan_
;
};
FloatType
max_abs_error_
;
const
bool
nan_eq_nan_
;
};
// Implements the Pointee(m) matcher for matching a pointer whose
// Implements the Pointee(m) matcher for matching a pointer whose
// pointee matches matcher m. The pointer can be either raw or smart.
// pointee matches matcher m. The pointer can be either raw or smart.
template
<
typename
InnerMatcher
>
template
<
typename
InnerMatcher
>
...
@@ -2953,6 +3082,50 @@ class EachMatcher {
...
@@ -2953,6 +3082,50 @@ class EachMatcher {
GTEST_DISALLOW_ASSIGN_
(
EachMatcher
);
GTEST_DISALLOW_ASSIGN_
(
EachMatcher
);
};
};
struct
Rank1
{};
struct
Rank0
:
Rank1
{};
namespace
pair_getters
{
#if GTEST_LANG_CXX11
using
std
::
get
;
template
<
typename
T
>
auto
First
(
T
&
x
,
Rank1
)
->
decltype
(
get
<
0
>
(
x
))
{
// NOLINT
return
get
<
0
>
(
x
);
}
template
<
typename
T
>
auto
First
(
T
&
x
,
Rank0
)
->
decltype
((
x
.
first
))
{
// NOLINT
return
x
.
first
;
}
template
<
typename
T
>
auto
Second
(
T
&
x
,
Rank1
)
->
decltype
(
get
<
1
>
(
x
))
{
// NOLINT
return
get
<
1
>
(
x
);
}
template
<
typename
T
>
auto
Second
(
T
&
x
,
Rank0
)
->
decltype
((
x
.
second
))
{
// NOLINT
return
x
.
second
;
}
#else
template
<
typename
T
>
typename
T
::
first_type
&
First
(
T
&
x
,
Rank0
)
{
// NOLINT
return
x
.
first
;
}
template
<
typename
T
>
const
typename
T
::
first_type
&
First
(
const
T
&
x
,
Rank0
)
{
return
x
.
first
;
}
template
<
typename
T
>
typename
T
::
second_type
&
Second
(
T
&
x
,
Rank0
)
{
// NOLINT
return
x
.
second
;
}
template
<
typename
T
>
const
typename
T
::
second_type
&
Second
(
const
T
&
x
,
Rank0
)
{
return
x
.
second
;
}
#endif // GTEST_LANG_CXX11
}
// namespace pair_getters
// Implements Key(inner_matcher) for the given argument pair type.
// Implements Key(inner_matcher) for the given argument pair type.
// Key(inner_matcher) matches an std::pair whose 'first' field matches
// Key(inner_matcher) matches an std::pair whose 'first' field matches
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
...
@@ -3717,6 +3890,65 @@ class VariantMatcher {
...
@@ -3717,6 +3890,65 @@ class VariantMatcher {
}
// namespace variant_matcher
}
// namespace variant_matcher
namespace
any_cast_matcher
{
// Overloads to allow AnyCastMatcher to do proper ADL lookup.
template
<
typename
T
>
void
any_cast
()
{}
// Implements a matcher that any_casts the value.
template
<
typename
T
>
class
AnyCastMatcher
{
public:
explicit
AnyCastMatcher
(
const
::
testing
::
Matcher
<
const
T
&>&
matcher
)
:
matcher_
(
matcher
)
{}
template
<
typename
AnyType
>
bool
MatchAndExplain
(
const
AnyType
&
value
,
::
testing
::
MatchResultListener
*
listener
)
const
{
if
(
!
listener
->
IsInterested
())
{
const
T
*
ptr
=
any_cast
<
T
>
(
&
value
);
return
ptr
!=
NULL
&&
matcher_
.
Matches
(
*
ptr
);
}
const
T
*
elem
=
any_cast
<
T
>
(
&
value
);
if
(
elem
==
NULL
)
{
*
listener
<<
"whose value is not of type '"
<<
GetTypeName
()
<<
"'"
;
return
false
;
}
StringMatchResultListener
elem_listener
;
const
bool
match
=
matcher_
.
MatchAndExplain
(
*
elem
,
&
elem_listener
);
*
listener
<<
"whose value "
<<
PrintToString
(
*
elem
)
<<
(
match
?
" matches"
:
" doesn't match"
);
PrintIfNotEmpty
(
elem_listener
.
str
(),
listener
->
stream
());
return
match
;
}
void
DescribeTo
(
std
::
ostream
*
os
)
const
{
*
os
<<
"is an 'any' type with value of type '"
<<
GetTypeName
()
<<
"' and the value "
;
matcher_
.
DescribeTo
(
os
);
}
void
DescribeNegationTo
(
std
::
ostream
*
os
)
const
{
*
os
<<
"is an 'any' type with value of type other than '"
<<
GetTypeName
()
<<
"' or the value "
;
matcher_
.
DescribeNegationTo
(
os
);
}
private:
static
std
::
string
GetTypeName
()
{
#if GTEST_HAS_RTTI
return
internal
::
GetTypeName
<
T
>
();
#endif
return
"the element type"
;
}
const
::
testing
::
Matcher
<
const
T
&>
matcher_
;
};
}
// namespace any_cast_matcher
}
// namespace internal
}
// namespace internal
// ElementsAreArray(iterator_first, iterator_last)
// ElementsAreArray(iterator_first, iterator_last)
...
@@ -3848,6 +4080,14 @@ inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
...
@@ -3848,6 +4080,14 @@ inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
template
<
typename
T
>
template
<
typename
T
>
Matcher
<
T
>::
Matcher
(
T
value
)
{
*
this
=
Eq
(
value
);
}
Matcher
<
T
>::
Matcher
(
T
value
)
{
*
this
=
Eq
(
value
);
}
template
<
typename
T
,
typename
M
>
Matcher
<
T
>
internal
::
MatcherCastImpl
<
T
,
M
>::
CastImpl
(
const
M
&
value
,
internal
::
BooleanConstant
<
false
>
/* convertible_to_matcher */
,
internal
::
BooleanConstant
<
false
>
/* convertible_to_T */
)
{
return
Eq
(
value
);
}
// Creates a monomorphic matcher that matches anything with type Lhs
// Creates a monomorphic matcher that matches anything with type Lhs
// and equal to rhs. A user may need to use this instead of Eq(...)
// and equal to rhs. A user may need to use this instead of Eq(...)
// in order to resolve an overloading ambiguity.
// in order to resolve an overloading ambiguity.
...
...
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