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
78579756
Unverified
Commit
78579756
authored
Mar 26, 2018
by
Gennadiy Civil
Committed by
GitHub
Mar 26, 2018
Browse files
Merge pull request #1512 from gennadiycivil/master
merges, gmock - 1
parents
dfa853b6
6aae206b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
662 additions
and
119 deletions
+662
-119
googlemock/include/gmock/gmock-matchers.h
googlemock/include/gmock/gmock-matchers.h
+587
-83
googlemock/src/gmock-matchers.cc
googlemock/src/gmock-matchers.cc
+42
-35
googlemock/test/gmock-internal-utils_test.cc
googlemock/test/gmock-internal-utils_test.cc
+28
-0
googlemock/test/gmock_output_test_.cc
googlemock/test/gmock_output_test_.cc
+5
-1
No files found.
googlemock/include/gmock/gmock-matchers.h
View file @
78579756
...
@@ -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:
...
@@ -252,7 +281,8 @@ class MatcherBase {
...
@@ -252,7 +281,8 @@ class MatcherBase {
public:
public:
// Returns true iff the matcher matches x; also explains the match
// Returns true iff the matcher matches x; also explains the match
// result to 'listener'.
// result to 'listener'.
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
bool
MatchAndExplain
(
GTEST_REFERENCE_TO_CONST_
(
T
)
x
,
MatchResultListener
*
listener
)
const
{
return
impl_
->
MatchAndExplain
(
x
,
listener
);
return
impl_
->
MatchAndExplain
(
x
,
listener
);
}
}
...
@@ -290,6 +320,14 @@ class MatcherBase {
...
@@ -290,6 +320,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:
...
@@ -323,7 +361,13 @@ class Matcher : public internal::MatcherBase<T> {
...
@@ -323,7 +361,13 @@ class Matcher : public internal::MatcherBase<T> {
explicit
Matcher
()
{}
// NOLINT
explicit
Matcher
()
{}
// NOLINT
// Constructs a matcher from its implementation.
// Constructs a matcher from its implementation.
explicit
Matcher
(
const
MatcherInterface
<
T
>*
impl
)
explicit
Matcher
(
const
MatcherInterface
<
GTEST_REFERENCE_TO_CONST_
(
T
)
>*
impl
)
:
internal
::
MatcherBase
<
T
>
(
impl
)
{}
template
<
typename
U
>
explicit
Matcher
(
const
MatcherInterface
<
U
>*
impl
,
typename
internal
::
EnableIf
<!
internal
::
IsSame
<
U
,
GTEST_REFERENCE_TO_CONST_
(
U
)
>::
value
>::
type
*
=
NULL
)
:
internal
::
MatcherBase
<
T
>
(
impl
)
{}
:
internal
::
MatcherBase
<
T
>
(
impl
)
{}
// Implicit constructor here allows people to write
// Implicit constructor here allows people to write
...
@@ -332,64 +376,79 @@ class Matcher : public internal::MatcherBase<T> {
...
@@ -332,64 +376,79 @@ class Matcher : public internal::MatcherBase<T> {
};
};
// The following two specializations allow the user to write str
// The following two specializations allow the user to write str
// instead of Eq(str) and "foo" instead of Eq("foo") when a string
// instead of Eq(str) and "foo" instead of Eq("foo") when a
std::
string
// matcher is expected.
// matcher is expected.
template
<>
template
<>
class
GTEST_API_
Matcher
<
const
internal
::
string
&>
class
GTEST_API_
Matcher
<
const
std
::
string
&>
:
public
internal
::
MatcherBase
<
const
internal
::
string
&>
{
:
public
internal
::
MatcherBase
<
const
std
::
string
&>
{
public:
public:
Matcher
()
{}
Matcher
()
{}
explicit
Matcher
(
const
MatcherInterface
<
const
internal
::
string
&>*
impl
)
explicit
Matcher
(
const
MatcherInterface
<
const
std
::
string
&>*
impl
)
:
internal
::
MatcherBase
<
const
internal
::
string
&>
(
impl
)
{}
:
internal
::
MatcherBase
<
const
std
::
string
&>
(
impl
)
{}
// Allows the user to write str instead of Eq(str) sometimes, where
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a string object.
// str is a std::string object.
Matcher
(
const
internal
::
string
&
s
);
// NOLINT
Matcher
(
const
std
::
string
&
s
);
// NOLINT
#if GTEST_HAS_GLOBAL_STRING
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a ::string object.
Matcher
(
const
::
string
&
s
);
// NOLINT
#endif // GTEST_HAS_GLOBAL_STRING
// Allows the user to write "foo" instead of Eq("foo") sometimes.
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher
(
const
char
*
s
);
// NOLINT
Matcher
(
const
char
*
s
);
// NOLINT
};
};
template
<>
template
<>
class
GTEST_API_
Matcher
<
internal
::
string
>
class
GTEST_API_
Matcher
<
std
::
string
>
:
public
internal
::
MatcherBase
<
internal
::
string
>
{
:
public
internal
::
MatcherBase
<
std
::
string
>
{
public:
public:
Matcher
()
{}
Matcher
()
{}
explicit
Matcher
(
const
MatcherInterface
<
internal
::
string
>*
impl
)
explicit
Matcher
(
const
MatcherInterface
<
std
::
string
>*
impl
)
:
internal
::
MatcherBase
<
internal
::
string
>
(
impl
)
{}
:
internal
::
MatcherBase
<
std
::
string
>
(
impl
)
{}
// Allows the user to write str instead of Eq(str) sometimes, where
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a string object.
// str is a string object.
Matcher
(
const
internal
::
string
&
s
);
// NOLINT
Matcher
(
const
std
::
string
&
s
);
// NOLINT
#if GTEST_HAS_GLOBAL_STRING
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a ::string object.
Matcher
(
const
::
string
&
s
);
// NOLINT
#endif // GTEST_HAS_GLOBAL_STRING
// Allows the user to write "foo" instead of Eq("foo") sometimes.
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher
(
const
char
*
s
);
// NOLINT
Matcher
(
const
char
*
s
);
// NOLINT
};
};
#if GTEST_HAS_
STRING_PIECE_
#if GTEST_HAS_
GLOBAL_STRING
// The following two specializations allow the user to write str
// The following two specializations allow the user to write str
// instead of Eq(str) and "foo" instead of Eq("foo") when a
S
tring
Piece
// instead of Eq(str) and "foo" instead of Eq("foo") when a
::s
tring
// matcher is expected.
// matcher is expected.
template
<>
template
<>
class
GTEST_API_
Matcher
<
const
S
tring
Piece
&>
class
GTEST_API_
Matcher
<
const
::
s
tring
&>
:
public
internal
::
MatcherBase
<
const
S
tring
Piece
&>
{
:
public
internal
::
MatcherBase
<
const
::
s
tring
&>
{
public:
public:
Matcher
()
{}
Matcher
()
{}
explicit
Matcher
(
const
MatcherInterface
<
const
S
tring
Piece
&>*
impl
)
explicit
Matcher
(
const
MatcherInterface
<
const
::
s
tring
&>*
impl
)
:
internal
::
MatcherBase
<
const
S
tring
Piece
&>
(
impl
)
{}
:
internal
::
MatcherBase
<
const
::
s
tring
&>
(
impl
)
{}
// Allows the user to write str instead of Eq(str) sometimes, where
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a string object.
// str is a std::string object.
Matcher
(
const
internal
::
string
&
s
);
// NOLINT
Matcher
(
const
std
::
string
&
s
);
// NOLINT
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a ::string object.
Matcher
(
const
::
string
&
s
);
// NOLINT
// Allows the user to write "foo" instead of Eq("foo") sometimes.
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher
(
const
char
*
s
);
// NOLINT
Matcher
(
const
char
*
s
);
// NOLINT
};
// Allows the user to pass StringPieces directly.
Matcher
(
StringPiece
s
);
// NOLINT
};
};
template
<>
template
<>
...
@@ -530,21 +589,18 @@ class MatcherCastImpl {
...
@@ -530,21 +589,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.
//
//
...
@@ -553,6 +609,29 @@ class MatcherCastImpl {
...
@@ -553,6 +609,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
...
@@ -573,6 +652,22 @@ class MatcherCastImpl<T, Matcher<U> > {
...
@@ -573,6 +652,22 @@ class MatcherCastImpl<T, Matcher<U> > {
// We delegate the matching logic to the source matcher.
// We delegate the matching logic to the source matcher.
virtual
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
virtual
bool
MatchAndExplain
(
T
x
,
MatchResultListener
*
listener
)
const
{
#if GTEST_LANG_CXX11
using
FromType
=
typename
std
::
remove_cv
<
typename
std
::
remove_pointer
<
typename
std
::
remove_reference
<
T
>::
type
>::
type
>::
type
;
using
ToType
=
typename
std
::
remove_cv
<
typename
std
::
remove_pointer
<
typename
std
::
remove_reference
<
U
>::
type
>::
type
>::
type
;
// Do not allow implicitly converting base*/& to derived*/&.
static_assert
(
// Do not trigger if only one of them is a pointer. That implies a
// regular conversion and not a down_cast.
(
std
::
is_pointer
<
typename
std
::
remove_reference
<
T
>::
type
>::
value
!=
std
::
is_pointer
<
typename
std
::
remove_reference
<
U
>::
type
>::
value
)
||
std
::
is_same
<
FromType
,
ToType
>::
value
||
!
std
::
is_base_of
<
FromType
,
ToType
>::
value
,
"Can't implicitly convert from <base> to <derived>"
);
#endif // GTEST_LANG_CXX11
return
source_matcher_
.
MatchAndExplain
(
static_cast
<
U
>
(
x
),
listener
);
return
source_matcher_
.
MatchAndExplain
(
static_cast
<
U
>
(
x
),
listener
);
}
}
...
@@ -1340,7 +1435,7 @@ class MatchesRegexMatcher {
...
@@ -1340,7 +1435,7 @@ class MatchesRegexMatcher {
// Matches anything that can convert to std::string.
// Matches anything that can convert to std::string.
//
//
// This is a template, not just a plain function with const std::string&,
// This is a template, not just a plain function with const std::string&,
// because
StringPiece
has some interfering non-explicit constructors.
// because
absl::string_view
has some interfering non-explicit constructors.
template
<
class
MatcheeStringType
>
template
<
class
MatcheeStringType
>
bool
MatchAndExplain
(
const
MatcheeStringType
&
s
,
bool
MatchAndExplain
(
const
MatcheeStringType
&
s
,
MatchResultListener
*
/* listener */
)
const
{
MatchResultListener
*
/* listener */
)
const
{
...
@@ -2036,6 +2131,82 @@ class FloatingEqMatcher {
...
@@ -2036,6 +2131,82 @@ 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
()
{
Init
(
-
1
,
false
);
}
explicit
FloatingEq2Matcher
(
bool
nan_eq_nan
)
{
Init
(
-
1
,
nan_eq_nan
);
}
explicit
FloatingEq2Matcher
(
FloatType
max_abs_error
)
{
Init
(
max_abs_error
,
false
);
}
FloatingEq2Matcher
(
FloatType
max_abs_error
,
bool
nan_eq_nan
)
{
Init
(
max_abs_error
,
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_
;
};
void
Init
(
FloatType
max_abs_error_val
,
bool
nan_eq_nan_val
)
{
max_abs_error_
=
max_abs_error_val
;
nan_eq_nan_
=
nan_eq_nan_val
;
}
FloatType
max_abs_error_
;
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
>
...
@@ -2181,15 +2352,21 @@ class FieldMatcher {
...
@@ -2181,15 +2352,21 @@ class FieldMatcher {
public:
public:
FieldMatcher
(
FieldType
Class
::*
field
,
FieldMatcher
(
FieldType
Class
::*
field
,
const
Matcher
<
const
FieldType
&>&
matcher
)
const
Matcher
<
const
FieldType
&>&
matcher
)
:
field_
(
field
),
matcher_
(
matcher
)
{}
:
field_
(
field
),
matcher_
(
matcher
),
whose_field_
(
"whose given field "
)
{}
FieldMatcher
(
const
std
::
string
&
field_name
,
FieldType
Class
::*
field
,
const
Matcher
<
const
FieldType
&>&
matcher
)
:
field_
(
field
),
matcher_
(
matcher
),
whose_field_
(
"whose field `"
+
field_name
+
"` "
)
{}
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is an object
whose given
field
"
;
*
os
<<
"is an object
"
<<
whose_
field
_
;
matcher_
.
DescribeTo
(
os
);
matcher_
.
DescribeTo
(
os
);
}
}
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is an object
whose given
field
"
;
*
os
<<
"is an object
"
<<
whose_
field
_
;
matcher_
.
DescribeNegationTo
(
os
);
matcher_
.
DescribeNegationTo
(
os
);
}
}
...
@@ -2207,7 +2384,7 @@ class FieldMatcher {
...
@@ -2207,7 +2384,7 @@ class FieldMatcher {
// true_type iff the Field() matcher is used to match a pointer.
// true_type iff the Field() matcher is used to match a pointer.
bool
MatchAndExplainImpl
(
false_type
/* is_not_pointer */
,
const
Class
&
obj
,
bool
MatchAndExplainImpl
(
false_type
/* is_not_pointer */
,
const
Class
&
obj
,
MatchResultListener
*
listener
)
const
{
MatchResultListener
*
listener
)
const
{
*
listener
<<
"
whose
given field
is "
;
*
listener
<<
whose
_field_
<<
"
is "
;
return
MatchPrintAndExplain
(
obj
.
*
field_
,
matcher_
,
listener
);
return
MatchPrintAndExplain
(
obj
.
*
field_
,
matcher_
,
listener
);
}
}
...
@@ -2226,6 +2403,10 @@ class FieldMatcher {
...
@@ -2226,6 +2403,10 @@ class FieldMatcher {
const
FieldType
Class
::*
field_
;
const
FieldType
Class
::*
field_
;
const
Matcher
<
const
FieldType
&>
matcher_
;
const
Matcher
<
const
FieldType
&>
matcher_
;
// Contains either "whose given field " if the name of the field is unknown
// or "whose field `name_of_field` " if the name is known.
const
std
::
string
whose_field_
;
GTEST_DISALLOW_ASSIGN_
(
FieldMatcher
);
GTEST_DISALLOW_ASSIGN_
(
FieldMatcher
);
};
};
...
@@ -2244,15 +2425,23 @@ class PropertyMatcher {
...
@@ -2244,15 +2425,23 @@ class PropertyMatcher {
typedef
GTEST_REFERENCE_TO_CONST_
(
PropertyType
)
RefToConstProperty
;
typedef
GTEST_REFERENCE_TO_CONST_
(
PropertyType
)
RefToConstProperty
;
PropertyMatcher
(
Property
property
,
const
Matcher
<
RefToConstProperty
>&
matcher
)
PropertyMatcher
(
Property
property
,
const
Matcher
<
RefToConstProperty
>&
matcher
)
:
property_
(
property
),
matcher_
(
matcher
)
{}
:
property_
(
property
),
matcher_
(
matcher
),
whose_property_
(
"whose given property "
)
{}
PropertyMatcher
(
const
std
::
string
&
property_name
,
Property
property
,
const
Matcher
<
RefToConstProperty
>&
matcher
)
:
property_
(
property
),
matcher_
(
matcher
),
whose_property_
(
"whose property `"
+
property_name
+
"` "
)
{}
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is an object
whose given
property
"
;
*
os
<<
"is an object
"
<<
whose_
property
_
;
matcher_
.
DescribeTo
(
os
);
matcher_
.
DescribeTo
(
os
);
}
}
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"is an object
whose given
property
"
;
*
os
<<
"is an object
"
<<
whose_
property
_
;
matcher_
.
DescribeNegationTo
(
os
);
matcher_
.
DescribeNegationTo
(
os
);
}
}
...
@@ -2270,7 +2459,7 @@ class PropertyMatcher {
...
@@ -2270,7 +2459,7 @@ class PropertyMatcher {
// true_type iff the Property() matcher is used to match a pointer.
// true_type iff the Property() matcher is used to match a pointer.
bool
MatchAndExplainImpl
(
false_type
/* is_not_pointer */
,
const
Class
&
obj
,
bool
MatchAndExplainImpl
(
false_type
/* is_not_pointer */
,
const
Class
&
obj
,
MatchResultListener
*
listener
)
const
{
MatchResultListener
*
listener
)
const
{
*
listener
<<
"
whose
given
property
is "
;
*
listener
<<
whose
_
property
_
<<
"
is "
;
// Cannot pass the return value (for example, int) to MatchPrintAndExplain,
// Cannot pass the return value (for example, int) to MatchPrintAndExplain,
// which takes a non-const reference as argument.
// which takes a non-const reference as argument.
#if defined(_PREFAST_ ) && _MSC_VER == 1800
#if defined(_PREFAST_ ) && _MSC_VER == 1800
...
@@ -2299,6 +2488,10 @@ class PropertyMatcher {
...
@@ -2299,6 +2488,10 @@ class PropertyMatcher {
Property
property_
;
Property
property_
;
const
Matcher
<
RefToConstProperty
>
matcher_
;
const
Matcher
<
RefToConstProperty
>
matcher_
;
// Contains either "whose given property " if the name of the property is
// unknown or "whose property `name_of_property` " if the name is known.
const
std
::
string
whose_property_
;
GTEST_DISALLOW_ASSIGN_
(
PropertyMatcher
);
GTEST_DISALLOW_ASSIGN_
(
PropertyMatcher
);
};
};
...
@@ -2692,6 +2885,10 @@ class WhenSortedByMatcher {
...
@@ -2692,6 +2885,10 @@ class WhenSortedByMatcher {
// container and the RHS container respectively.
// container and the RHS container respectively.
template
<
typename
TupleMatcher
,
typename
RhsContainer
>
template
<
typename
TupleMatcher
,
typename
RhsContainer
>
class
PointwiseMatcher
{
class
PointwiseMatcher
{
GTEST_COMPILE_ASSERT_
(
!
IsHashTable
<
GTEST_REMOVE_REFERENCE_AND_CONST_
(
RhsContainer
)
>::
value
,
use_UnorderedPointwise_with_hash_tables
);
public:
public:
typedef
internal
::
StlContainerView
<
RhsContainer
>
RhsView
;
typedef
internal
::
StlContainerView
<
RhsContainer
>
RhsView
;
typedef
typename
RhsView
::
type
RhsStlContainer
;
typedef
typename
RhsView
::
type
RhsStlContainer
;
...
@@ -2709,6 +2906,10 @@ class PointwiseMatcher {
...
@@ -2709,6 +2906,10 @@ class PointwiseMatcher {
template
<
typename
LhsContainer
>
template
<
typename
LhsContainer
>
operator
Matcher
<
LhsContainer
>
()
const
{
operator
Matcher
<
LhsContainer
>
()
const
{
GTEST_COMPILE_ASSERT_
(
!
IsHashTable
<
GTEST_REMOVE_REFERENCE_AND_CONST_
(
LhsContainer
)
>::
value
,
use_UnorderedPointwise_with_hash_tables
);
return
MakeMatcher
(
new
Impl
<
LhsContainer
>
(
tuple_matcher_
,
rhs_
));
return
MakeMatcher
(
new
Impl
<
LhsContainer
>
(
tuple_matcher_
,
rhs_
));
}
}
...
@@ -2759,12 +2960,15 @@ class PointwiseMatcher {
...
@@ -2759,12 +2960,15 @@ class PointwiseMatcher {
typename
LhsStlContainer
::
const_iterator
left
=
lhs_stl_container
.
begin
();
typename
LhsStlContainer
::
const_iterator
left
=
lhs_stl_container
.
begin
();
typename
RhsStlContainer
::
const_iterator
right
=
rhs_
.
begin
();
typename
RhsStlContainer
::
const_iterator
right
=
rhs_
.
begin
();
for
(
size_t
i
=
0
;
i
!=
actual_size
;
++
i
,
++
left
,
++
right
)
{
for
(
size_t
i
=
0
;
i
!=
actual_size
;
++
i
,
++
left
,
++
right
)
{
const
InnerMatcherArg
value_pair
(
*
left
,
*
right
);
if
(
listener
->
IsInterested
())
{
if
(
listener
->
IsInterested
())
{
StringMatchResultListener
inner_listener
;
StringMatchResultListener
inner_listener
;
// Create InnerMatcherArg as a temporarily object to avoid it outlives
// *left and *right. Dereference or the conversion to `const T&` may
// return temp objects, e.g for vector<bool>.
if
(
!
mono_tuple_matcher_
.
MatchAndExplain
(
if
(
!
mono_tuple_matcher_
.
MatchAndExplain
(
value_pair
,
&
inner_listener
))
{
InnerMatcherArg
(
ImplicitCast_
<
const
LhsValue
&>
(
*
left
),
ImplicitCast_
<
const
RhsValue
&>
(
*
right
)),
&
inner_listener
))
{
*
listener
<<
"where the value pair ("
;
*
listener
<<
"where the value pair ("
;
UniversalPrint
(
*
left
,
listener
->
stream
());
UniversalPrint
(
*
left
,
listener
->
stream
());
*
listener
<<
", "
;
*
listener
<<
", "
;
...
@@ -2774,7 +2978,9 @@ class PointwiseMatcher {
...
@@ -2774,7 +2978,9 @@ class PointwiseMatcher {
return
false
;
return
false
;
}
}
}
else
{
}
else
{
if
(
!
mono_tuple_matcher_
.
Matches
(
value_pair
))
if
(
!
mono_tuple_matcher_
.
Matches
(
InnerMatcherArg
(
ImplicitCast_
<
const
LhsValue
&>
(
*
left
),
ImplicitCast_
<
const
RhsValue
&>
(
*
right
))))
return
false
;
return
false
;
}
}
}
}
...
@@ -2932,6 +3138,50 @@ class EachMatcher {
...
@@ -2932,6 +3138,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
...
@@ -2952,8 +3202,8 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
...
@@ -2952,8 +3202,8 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
virtual
bool
MatchAndExplain
(
PairType
key_value
,
virtual
bool
MatchAndExplain
(
PairType
key_value
,
MatchResultListener
*
listener
)
const
{
MatchResultListener
*
listener
)
const
{
StringMatchResultListener
inner_listener
;
StringMatchResultListener
inner_listener
;
const
bool
match
=
inner_matcher_
.
MatchAndExplain
(
key_value
.
first
,
const
bool
match
=
inner_matcher_
.
MatchAndExplain
(
&
inner_listener
);
pair_getters
::
First
(
key_value
,
Rank0
()),
&
inner_listener
);
const
std
::
string
explanation
=
inner_listener
.
str
();
const
std
::
string
explanation
=
inner_listener
.
str
();
if
(
explanation
!=
""
)
{
if
(
explanation
!=
""
)
{
*
listener
<<
"whose first field is a value "
<<
explanation
;
*
listener
<<
"whose first field is a value "
<<
explanation
;
...
@@ -3036,18 +3286,18 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
...
@@ -3036,18 +3286,18 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
if
(
!
listener
->
IsInterested
())
{
if
(
!
listener
->
IsInterested
())
{
// If the listener is not interested, we don't need to construct the
// If the listener is not interested, we don't need to construct the
// explanation.
// explanation.
return
first_matcher_
.
Matches
(
a_
pair
.
first
)
&&
return
first_matcher_
.
Matches
(
pair
_getters
::
First
(
a_pair
,
Rank0
())
)
&&
second_matcher_
.
Matches
(
a_
pair
.
second
);
second_matcher_
.
Matches
(
pair
_getters
::
Second
(
a_pair
,
Rank0
())
);
}
}
StringMatchResultListener
first_inner_listener
;
StringMatchResultListener
first_inner_listener
;
if
(
!
first_matcher_
.
MatchAndExplain
(
a_
pair
.
first
,
if
(
!
first_matcher_
.
MatchAndExplain
(
pair
_getters
::
First
(
a_pair
,
Rank0
())
,
&
first_inner_listener
))
{
&
first_inner_listener
))
{
*
listener
<<
"whose first field does not match"
;
*
listener
<<
"whose first field does not match"
;
PrintIfNotEmpty
(
first_inner_listener
.
str
(),
listener
->
stream
());
PrintIfNotEmpty
(
first_inner_listener
.
str
(),
listener
->
stream
());
return
false
;
return
false
;
}
}
StringMatchResultListener
second_inner_listener
;
StringMatchResultListener
second_inner_listener
;
if
(
!
second_matcher_
.
MatchAndExplain
(
a_
pair
.
second
,
if
(
!
second_matcher_
.
MatchAndExplain
(
pair
_getters
::
Second
(
a_pair
,
Rank0
())
,
&
second_inner_listener
))
{
&
second_inner_listener
))
{
*
listener
<<
"whose second field does not match"
;
*
listener
<<
"whose second field does not match"
;
PrintIfNotEmpty
(
second_inner_listener
.
str
(),
listener
->
stream
());
PrintIfNotEmpty
(
second_inner_listener
.
str
(),
listener
->
stream
());
...
@@ -3494,6 +3744,11 @@ class ElementsAreMatcher {
...
@@ -3494,6 +3744,11 @@ class ElementsAreMatcher {
template
<
typename
Container
>
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
operator
Matcher
<
Container
>
()
const
{
GTEST_COMPILE_ASSERT_
(
!
IsHashTable
<
GTEST_REMOVE_REFERENCE_AND_CONST_
(
Container
)
>::
value
||
::
testing
::
tuple_size
<
MatcherTuple
>::
value
<
2
,
use_UnorderedElementsAre_with_hash_tables
);
typedef
GTEST_REMOVE_REFERENCE_AND_CONST_
(
Container
)
RawContainer
;
typedef
GTEST_REMOVE_REFERENCE_AND_CONST_
(
Container
)
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
View
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
View
;
typedef
typename
View
::
value_type
Element
;
typedef
typename
View
::
value_type
Element
;
...
@@ -3542,6 +3797,10 @@ class ElementsAreArrayMatcher {
...
@@ -3542,6 +3797,10 @@ class ElementsAreArrayMatcher {
template
<
typename
Container
>
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
operator
Matcher
<
Container
>
()
const
{
GTEST_COMPILE_ASSERT_
(
!
IsHashTable
<
GTEST_REMOVE_REFERENCE_AND_CONST_
(
Container
)
>::
value
,
use_UnorderedElementsAreArray_with_hash_tables
);
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
matchers_
.
begin
(),
matchers_
.
end
()));
matchers_
.
begin
(),
matchers_
.
end
()));
}
}
...
@@ -3636,6 +3895,61 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
...
@@ -3636,6 +3895,61 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
const
char
*
matcher_name
,
const
char
*
matcher_name
,
const
Strings
&
param_values
);
const
Strings
&
param_values
);
// Implements a matcher that checks the value of a optional<> type variable.
template
<
typename
ValueMatcher
>
class
OptionalMatcher
{
public:
explicit
OptionalMatcher
(
const
ValueMatcher
&
value_matcher
)
:
value_matcher_
(
value_matcher
)
{}
template
<
typename
Optional
>
operator
Matcher
<
Optional
>
()
const
{
return
MakeMatcher
(
new
Impl
<
Optional
>
(
value_matcher_
));
}
template
<
typename
Optional
>
class
Impl
:
public
MatcherInterface
<
Optional
>
{
public:
typedef
GTEST_REMOVE_REFERENCE_AND_CONST_
(
Optional
)
OptionalView
;
typedef
typename
OptionalView
::
value_type
ValueType
;
explicit
Impl
(
const
ValueMatcher
&
value_matcher
)
:
value_matcher_
(
MatcherCast
<
ValueType
>
(
value_matcher
))
{}
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"value "
;
value_matcher_
.
DescribeTo
(
os
);
}
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"value "
;
value_matcher_
.
DescribeNegationTo
(
os
);
}
virtual
bool
MatchAndExplain
(
Optional
optional
,
MatchResultListener
*
listener
)
const
{
if
(
!
optional
)
{
*
listener
<<
"which is not engaged"
;
return
false
;
}
const
ValueType
&
value
=
*
optional
;
StringMatchResultListener
value_listener
;
const
bool
match
=
value_matcher_
.
MatchAndExplain
(
value
,
&
value_listener
);
*
listener
<<
"whose value "
<<
PrintToString
(
value
)
<<
(
match
?
" matches"
:
" doesn't match"
);
PrintIfNotEmpty
(
value_listener
.
str
(),
listener
->
stream
());
return
match
;
}
private:
const
Matcher
<
ValueType
>
value_matcher_
;
GTEST_DISALLOW_ASSIGN_
(
Impl
);
};
private:
const
ValueMatcher
value_matcher_
;
GTEST_DISALLOW_ASSIGN_
(
OptionalMatcher
);
};
namespace
variant_matcher
{
namespace
variant_matcher
{
// Overloads to allow VariantMatcher to do proper ADL lookup.
// Overloads to allow VariantMatcher to do proper ADL lookup.
template
<
typename
T
>
template
<
typename
T
>
...
@@ -3684,7 +3998,7 @@ class VariantMatcher {
...
@@ -3684,7 +3998,7 @@ class VariantMatcher {
}
}
private:
private:
static
string
GetTypeName
()
{
static
std
::
string
GetTypeName
()
{
#if GTEST_HAS_RTTI
#if GTEST_HAS_RTTI
return
internal
::
GetTypeName
<
T
>
();
return
internal
::
GetTypeName
<
T
>
();
#endif
#endif
...
@@ -3696,6 +4010,65 @@ class VariantMatcher {
...
@@ -3696,6 +4010,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)
...
@@ -3827,6 +4200,14 @@ inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
...
@@ -3827,6 +4200,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.
...
@@ -3985,6 +4366,16 @@ inline PolymorphicMatcher<
...
@@ -3985,6 +4366,16 @@ inline PolymorphicMatcher<
// to compile where bar is an int32 and m is a matcher for int64.
// to compile where bar is an int32 and m is a matcher for int64.
}
}
// Same as Field() but also takes the name of the field to provide better error
// messages.
template
<
typename
Class
,
typename
FieldType
,
typename
FieldMatcher
>
inline
PolymorphicMatcher
<
internal
::
FieldMatcher
<
Class
,
FieldType
>
>
Field
(
const
std
::
string
&
field_name
,
FieldType
Class
::*
field
,
const
FieldMatcher
&
matcher
)
{
return
MakePolymorphicMatcher
(
internal
::
FieldMatcher
<
Class
,
FieldType
>
(
field_name
,
field
,
MatcherCast
<
const
FieldType
&>
(
matcher
)));
}
// Creates a matcher that matches an object whose given property
// Creates a matcher that matches an object whose given property
// matches 'matcher'. For example,
// matches 'matcher'. For example,
// Property(&Foo::str, StartsWith("hi"))
// Property(&Foo::str, StartsWith("hi"))
...
@@ -4005,6 +4396,21 @@ Property(PropertyType (Class::*property)() const,
...
@@ -4005,6 +4396,21 @@ Property(PropertyType (Class::*property)() const,
// to compile where bar() returns an int32 and m is a matcher for int64.
// to compile where bar() returns an int32 and m is a matcher for int64.
}
}
// Same as Property() above, but also takes the name of the property to provide
// better error messages.
template
<
typename
Class
,
typename
PropertyType
,
typename
PropertyMatcher
>
inline
PolymorphicMatcher
<
internal
::
PropertyMatcher
<
Class
,
PropertyType
,
PropertyType
(
Class
::*
)()
const
>
>
Property
(
const
std
::
string
&
property_name
,
PropertyType
(
Class
::*
property
)()
const
,
const
PropertyMatcher
&
matcher
)
{
return
MakePolymorphicMatcher
(
internal
::
PropertyMatcher
<
Class
,
PropertyType
,
PropertyType
(
Class
::*
)()
const
>
(
property_name
,
property
,
MatcherCast
<
GTEST_REFERENCE_TO_CONST_
(
PropertyType
)
>
(
matcher
)));
}
#if GTEST_LANG_CXX11
#if GTEST_LANG_CXX11
// The same as above but for reference-qualified member functions.
// The same as above but for reference-qualified member functions.
template
<
typename
Class
,
typename
PropertyType
,
typename
PropertyMatcher
>
template
<
typename
Class
,
typename
PropertyType
,
typename
PropertyMatcher
>
...
@@ -4033,6 +4439,7 @@ Property(PropertyType (Class::*property)() const &,
...
@@ -4033,6 +4439,7 @@ Property(PropertyType (Class::*property)() const &,
// concurrent access.
// concurrent access.
// * If it is a function object, it has to define type result_type.
// * If it is a function object, it has to define type result_type.
// We recommend deriving your functor classes from std::unary_function.
// We recommend deriving your functor classes from std::unary_function.
//
template
<
typename
Callable
,
typename
ResultOfMatcher
>
template
<
typename
Callable
,
typename
ResultOfMatcher
>
internal
::
ResultOfMatcher
<
Callable
>
ResultOf
(
internal
::
ResultOfMatcher
<
Callable
>
ResultOf
(
Callable
callable
,
const
ResultOfMatcher
&
matcher
)
{
Callable
callable
,
const
ResultOfMatcher
&
matcher
)
{
...
@@ -4123,53 +4530,53 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
...
@@ -4123,53 +4530,53 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
// Wide string matchers.
// Wide string matchers.
// Matches a string equal to str.
// Matches a string equal to str.
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
std
::
wstring
>
>
StrEq
(
StrEq
(
const
internal
::
wstring
&
str
)
{
const
std
::
wstring
&
str
)
{
return
MakePolymorphicMatcher
(
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
str
,
true
,
true
));
internal
::
StrEqualityMatcher
<
std
::
wstring
>
(
str
,
true
,
true
));
}
}
// Matches a string not equal to str.
// Matches a string not equal to str.
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
std
::
wstring
>
>
StrNe
(
StrNe
(
const
internal
::
wstring
&
str
)
{
const
std
::
wstring
&
str
)
{
return
MakePolymorphicMatcher
(
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
str
,
false
,
true
));
internal
::
StrEqualityMatcher
<
std
::
wstring
>
(
str
,
false
,
true
));
}
}
// Matches a string equal to str, ignoring case.
// Matches a string equal to str, ignoring case.
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
std
::
wstring
>
>
StrCaseEq
(
const
internal
::
wstring
&
str
)
{
StrCaseEq
(
const
std
::
wstring
&
str
)
{
return
MakePolymorphicMatcher
(
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
str
,
true
,
false
));
internal
::
StrEqualityMatcher
<
std
::
wstring
>
(
str
,
true
,
false
));
}
}
// Matches a string not equal to str, ignoring case.
// Matches a string not equal to str, ignoring case.
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
StrEqualityMatcher
<
std
::
wstring
>
>
StrCaseNe
(
const
internal
::
wstring
&
str
)
{
StrCaseNe
(
const
std
::
wstring
&
str
)
{
return
MakePolymorphicMatcher
(
internal
::
StrEqualityMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
str
,
false
,
false
));
internal
::
StrEqualityMatcher
<
std
::
wstring
>
(
str
,
false
,
false
));
}
}
// Creates a matcher that matches any wstring, std::wstring, or C wide string
// Creates a matcher that matches any
::
wstring, std::wstring, or C wide string
// that contains the given substring.
// that contains the given substring.
inline
PolymorphicMatcher
<
internal
::
HasSubstrMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
HasSubstrMatcher
<
std
::
wstring
>
>
HasSubstr
(
HasSubstr
(
const
internal
::
wstring
&
substring
)
{
const
std
::
wstring
&
substring
)
{
return
MakePolymorphicMatcher
(
internal
::
HasSubstrMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
substring
));
internal
::
HasSubstrMatcher
<
std
::
wstring
>
(
substring
));
}
}
// Matches a string that starts with 'prefix' (case-sensitive).
// Matches a string that starts with 'prefix' (case-sensitive).
inline
PolymorphicMatcher
<
internal
::
StartsWithMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
StartsWithMatcher
<
std
::
wstring
>
>
StartsWith
(
const
internal
::
wstring
&
prefix
)
{
StartsWith
(
const
std
::
wstring
&
prefix
)
{
return
MakePolymorphicMatcher
(
internal
::
StartsWithMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
prefix
));
internal
::
StartsWithMatcher
<
std
::
wstring
>
(
prefix
));
}
}
// Matches a string that ends with 'suffix' (case-sensitive).
// Matches a string that ends with 'suffix' (case-sensitive).
inline
PolymorphicMatcher
<
internal
::
EndsWithMatcher
<
internal
::
wstring
>
>
inline
PolymorphicMatcher
<
internal
::
EndsWithMatcher
<
std
::
wstring
>
>
EndsWith
(
EndsWith
(
const
internal
::
wstring
&
suffix
)
{
const
std
::
wstring
&
suffix
)
{
return
MakePolymorphicMatcher
(
internal
::
EndsWithMatcher
<
internal
::
wstring
>
(
return
MakePolymorphicMatcher
(
suffix
));
internal
::
EndsWithMatcher
<
std
::
wstring
>
(
suffix
));
}
}
#endif // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
#endif // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
...
@@ -4198,6 +4605,58 @@ inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
...
@@ -4198,6 +4605,58 @@ inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
// first field != the second field.
// first field != the second field.
inline
internal
::
Ne2Matcher
Ne
()
{
return
internal
::
Ne2Matcher
();
}
inline
internal
::
Ne2Matcher
Ne
()
{
return
internal
::
Ne2Matcher
();
}
// Creates a polymorphic matcher that matches a 2-tuple where
// FloatEq(first field) matches the second field.
inline
internal
::
FloatingEq2Matcher
<
float
>
FloatEq
()
{
return
internal
::
FloatingEq2Matcher
<
float
>
();
}
// Creates a polymorphic matcher that matches a 2-tuple where
// DoubleEq(first field) matches the second field.
inline
internal
::
FloatingEq2Matcher
<
double
>
DoubleEq
()
{
return
internal
::
FloatingEq2Matcher
<
double
>
();
}
// Creates a polymorphic matcher that matches a 2-tuple where
// FloatEq(first field) matches the second field with NaN equality.
inline
internal
::
FloatingEq2Matcher
<
float
>
NanSensitiveFloatEq
()
{
return
internal
::
FloatingEq2Matcher
<
float
>
(
true
);
}
// Creates a polymorphic matcher that matches a 2-tuple where
// DoubleEq(first field) matches the second field with NaN equality.
inline
internal
::
FloatingEq2Matcher
<
double
>
NanSensitiveDoubleEq
()
{
return
internal
::
FloatingEq2Matcher
<
double
>
(
true
);
}
// Creates a polymorphic matcher that matches a 2-tuple where
// FloatNear(first field, max_abs_error) matches the second field.
inline
internal
::
FloatingEq2Matcher
<
float
>
FloatNear
(
float
max_abs_error
)
{
return
internal
::
FloatingEq2Matcher
<
float
>
(
max_abs_error
);
}
// Creates a polymorphic matcher that matches a 2-tuple where
// DoubleNear(first field, max_abs_error) matches the second field.
inline
internal
::
FloatingEq2Matcher
<
double
>
DoubleNear
(
double
max_abs_error
)
{
return
internal
::
FloatingEq2Matcher
<
double
>
(
max_abs_error
);
}
// Creates a polymorphic matcher that matches a 2-tuple where
// FloatNear(first field, max_abs_error) matches the second field with NaN
// equality.
inline
internal
::
FloatingEq2Matcher
<
float
>
NanSensitiveFloatNear
(
float
max_abs_error
)
{
return
internal
::
FloatingEq2Matcher
<
float
>
(
max_abs_error
,
true
);
}
// Creates a polymorphic matcher that matches a 2-tuple where
// DoubleNear(first field, max_abs_error) matches the second field with NaN
// equality.
inline
internal
::
FloatingEq2Matcher
<
double
>
NanSensitiveDoubleNear
(
double
max_abs_error
)
{
return
internal
::
FloatingEq2Matcher
<
double
>
(
max_abs_error
,
true
);
}
// Creates a matcher that matches any value of type T that m doesn't
// Creates a matcher that matches any value of type T that m doesn't
// match.
// match.
template
<
typename
InnerMatcher
>
template
<
typename
InnerMatcher
>
...
@@ -4575,6 +5034,28 @@ inline bool ExplainMatchResult(
...
@@ -4575,6 +5034,28 @@ inline bool ExplainMatchResult(
return
SafeMatcherCast
<
const
T
&>
(
matcher
).
MatchAndExplain
(
value
,
listener
);
return
SafeMatcherCast
<
const
T
&>
(
matcher
).
MatchAndExplain
(
value
,
listener
);
}
}
// Returns a string representation of the given matcher. Useful for description
// strings of matchers defined using MATCHER_P* macros that accept matchers as
// their arguments. For example:
//
// MATCHER_P(XAndYThat, matcher,
// "X that " + DescribeMatcher<int>(matcher, negation) +
// " and Y that " + DescribeMatcher<double>(matcher, negation)) {
// return ExplainMatchResult(matcher, arg.x(), result_listener) &&
// ExplainMatchResult(matcher, arg.y(), result_listener);
// }
template
<
typename
T
,
typename
M
>
std
::
string
DescribeMatcher
(
const
M
&
matcher
,
bool
negation
=
false
)
{
::
std
::
stringstream
ss
;
Matcher
<
T
>
monomorphic_matcher
=
SafeMatcherCast
<
T
>
(
matcher
);
if
(
negation
)
{
monomorphic_matcher
.
DescribeNegationTo
(
&
ss
);
}
else
{
monomorphic_matcher
.
DescribeTo
(
&
ss
);
}
return
ss
.
str
();
}
#if GTEST_LANG_CXX11
#if GTEST_LANG_CXX11
// Define variadic matcher versions. They are overloaded in
// Define variadic matcher versions. They are overloaded in
// gmock-generated-matchers.h for the cases supported by pre C++11 compilers.
// gmock-generated-matchers.h for the cases supported by pre C++11 compilers.
...
@@ -4600,6 +5081,28 @@ inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {
...
@@ -4600,6 +5081,28 @@ inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {
template
<
typename
InnerMatcher
>
template
<
typename
InnerMatcher
>
inline
InnerMatcher
AllArgs
(
const
InnerMatcher
&
matcher
)
{
return
matcher
;
}
inline
InnerMatcher
AllArgs
(
const
InnerMatcher
&
matcher
)
{
return
matcher
;
}
// Returns a matcher that matches the value of an optional<> type variable.
// The matcher implementation only uses '!arg' and requires that the optional<>
// type has a 'value_type' member type and that '*arg' is of type 'value_type'
// and is printable using 'PrintToString'. It is compatible with
// std::optional/std::experimental::optional.
// Note that to compare an optional type variable against nullopt you should
// use Eq(nullopt) and not Optional(Eq(nullopt)). The latter implies that the
// optional value contains an optional itself.
template
<
typename
ValueMatcher
>
inline
internal
::
OptionalMatcher
<
ValueMatcher
>
Optional
(
const
ValueMatcher
&
value_matcher
)
{
return
internal
::
OptionalMatcher
<
ValueMatcher
>
(
value_matcher
);
}
// Returns a matcher that matches the value of a absl::any type variable.
template
<
typename
T
>
PolymorphicMatcher
<
internal
::
any_cast_matcher
::
AnyCastMatcher
<
T
>
>
AnyWith
(
const
Matcher
<
const
T
&>&
matcher
)
{
return
MakePolymorphicMatcher
(
internal
::
any_cast_matcher
::
AnyCastMatcher
<
T
>
(
matcher
));
}
// Returns a matcher that matches the value of a variant<> type variable.
// Returns a matcher that matches the value of a variant<> type variable.
// The matcher implementation uses ADL to find the holds_alternative and get
// The matcher implementation uses ADL to find the holds_alternative and get
// functions.
// functions.
...
@@ -4626,4 +5129,5 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
...
@@ -4626,4 +5129,5 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
// We must include this header at the end to make sure it can use the
// We must include this header at the end to make sure it can use the
// declarations from this file.
// declarations from this file.
#include "gmock/internal/custom/gmock-matchers.h"
#include "gmock/internal/custom/gmock-matchers.h"
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
googlemock/src/gmock-matchers.cc
View file @
78579756
...
@@ -44,60 +44,67 @@
...
@@ -44,60 +44,67 @@
namespace
testing
{
namespace
testing
{
// Constructs a matcher that matches a const string& whose value is
// Constructs a matcher that matches a const
std::
string& whose value is
// equal to s.
// equal to s.
Matcher
<
const
internal
::
string
&>::
Matcher
(
const
internal
::
string
&
s
)
{
Matcher
<
const
std
::
string
&>::
Matcher
(
const
std
::
string
&
s
)
{
*
this
=
Eq
(
s
);
}
*
this
=
Eq
(
s
);
#if GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a const std::string& whose value is
// equal to s.
Matcher
<
const
std
::
string
&>::
Matcher
(
const
::
string
&
s
)
{
*
this
=
Eq
(
static_cast
<
std
::
string
>
(
s
));
}
}
#endif // GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a const string& whose value is
// Constructs a matcher that matches a const
std::
string& whose value is
// equal to s.
// equal to s.
Matcher
<
const
internal
::
string
&>::
Matcher
(
const
char
*
s
)
{
Matcher
<
const
std
::
string
&>::
Matcher
(
const
char
*
s
)
{
*
this
=
Eq
(
internal
::
string
(
s
));
*
this
=
Eq
(
std
::
string
(
s
));
}
}
// Constructs a matcher that matches a string whose value is equal to s.
// Constructs a matcher that matches a std::string whose value is equal to
Matcher
<
internal
::
string
>::
Matcher
(
const
internal
::
string
&
s
)
{
*
this
=
Eq
(
s
);
}
// s.
Matcher
<
std
::
string
>::
Matcher
(
const
std
::
string
&
s
)
{
*
this
=
Eq
(
s
);
}
// Constructs a matcher that matches a string whose value is equal to s.
#if GTEST_HAS_GLOBAL_STRING
Matcher
<
internal
::
string
>::
Matcher
(
const
char
*
s
)
{
// Constructs a matcher that matches a std::string whose value is equal to
*
this
=
Eq
(
internal
::
string
(
s
));
// s.
Matcher
<
std
::
string
>::
Matcher
(
const
::
string
&
s
)
{
*
this
=
Eq
(
static_cast
<
std
::
string
>
(
s
));
}
}
#endif // GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a std::string whose value is equal to
// s.
Matcher
<
std
::
string
>::
Matcher
(
const
char
*
s
)
{
*
this
=
Eq
(
std
::
string
(
s
));
}
#if GTEST_HAS_
STRING_PIECE_
#if GTEST_HAS_
GLOBAL_STRING
// Constructs a matcher that matches a const
S
tring
Piece
& whose value is
// Constructs a matcher that matches a const
::s
tring& whose value is
// equal to s.
// equal to s.
Matcher
<
const
S
tring
Piece
&>::
Matcher
(
const
internal
::
string
&
s
)
{
Matcher
<
const
::
s
tring
&>::
Matcher
(
const
std
::
string
&
s
)
{
*
this
=
Eq
(
s
);
*
this
=
Eq
(
s
tatic_cast
<::
string
>
(
s
)
);
}
}
// Constructs a matcher that matches a const
S
tring
Piece
& whose value is
// Constructs a matcher that matches a const
::s
tring& whose value is
// equal to s.
// equal to s.
Matcher
<
const
StringPiece
&>::
Matcher
(
const
char
*
s
)
{
Matcher
<
const
::
string
&>::
Matcher
(
const
::
string
&
s
)
{
*
this
=
Eq
(
s
);
}
*
this
=
Eq
(
internal
::
string
(
s
));
}
// Constructs a matcher that matches a const
S
tring
Piece
& whose value is
// Constructs a matcher that matches a const
::s
tring& whose value is
// equal to s.
// equal to s.
Matcher
<
const
StringPiece
&>::
Matcher
(
StringPiece
s
)
{
Matcher
<
const
::
string
&>::
Matcher
(
const
char
*
s
)
{
*
this
=
Eq
(
::
string
(
s
));
}
*
this
=
Eq
(
s
.
ToString
());
}
// Constructs a matcher that matches a
S
tring
Piece
whose value is equal to s.
// Constructs a matcher that matches a
::s
tring whose value is equal to s.
Matcher
<
S
tring
Piece
>::
Matcher
(
const
internal
::
string
&
s
)
{
Matcher
<
::
s
tring
>::
Matcher
(
const
std
::
string
&
s
)
{
*
this
=
Eq
(
s
);
*
this
=
Eq
(
s
tatic_cast
<::
string
>
(
s
)
);
}
}
// Constructs a matcher that matches a StringPiece whose value is equal to s.
// Constructs a matcher that matches a ::string whose value is equal to s.
Matcher
<
StringPiece
>::
Matcher
(
const
char
*
s
)
{
Matcher
<::
string
>::
Matcher
(
const
::
string
&
s
)
{
*
this
=
Eq
(
s
);
}
*
this
=
Eq
(
internal
::
string
(
s
));
}
// Constructs a matcher that matches a string whose value is equal to s.
Matcher
<::
string
>::
Matcher
(
const
char
*
s
)
{
*
this
=
Eq
(
::
string
(
s
));
}
#endif // GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a StringPiece whose value is equal to s.
Matcher
<
StringPiece
>::
Matcher
(
StringPiece
s
)
{
*
this
=
Eq
(
s
.
ToString
());
}
#endif // GTEST_HAS_STRING_PIECE_
namespace
internal
{
namespace
internal
{
...
...
googlemock/test/gmock-internal-utils_test.cc
View file @
78579756
...
@@ -44,7 +44,15 @@
...
@@ -44,7 +44,15 @@
#include "gmock/internal/gmock-port.h"
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"
#include "gtest/gtest-spi.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
// prevent a user from accidentally including gtest-internal-inl.h in
// their code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h"
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_CYGWIN
#if GTEST_OS_CYGWIN
# include <sys/types.h> // For ssize_t. NOLINT
# include <sys/types.h> // For ssize_t. NOLINT
...
@@ -61,6 +69,26 @@ namespace internal {
...
@@ -61,6 +69,26 @@ namespace internal {
namespace
{
namespace
{
TEST
(
JoinAsTupleTest
,
JoinsEmptyTuple
)
{
EXPECT_EQ
(
""
,
JoinAsTuple
(
Strings
()));
}
TEST
(
JoinAsTupleTest
,
JoinsOneTuple
)
{
const
char
*
fields
[]
=
{
"1"
};
EXPECT_EQ
(
"1"
,
JoinAsTuple
(
Strings
(
fields
,
fields
+
1
)));
}
TEST
(
JoinAsTupleTest
,
JoinsTwoTuple
)
{
const
char
*
fields
[]
=
{
"1"
,
"a"
};
EXPECT_EQ
(
"(1, a)"
,
JoinAsTuple
(
Strings
(
fields
,
fields
+
2
)));
}
TEST
(
JoinAsTupleTest
,
JoinsTenTuple
)
{
const
char
*
fields
[]
=
{
"1"
,
"2"
,
"3"
,
"4"
,
"5"
,
"6"
,
"7"
,
"8"
,
"9"
,
"10"
};
EXPECT_EQ
(
"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)"
,
JoinAsTuple
(
Strings
(
fields
,
fields
+
10
)));
}
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameContainsNoWord
)
{
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameContainsNoWord
)
{
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
""
));
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
""
));
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
"_"
));
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
"_"
));
...
...
googlemock/test/gmock_output_test_.cc
View file @
78579756
...
@@ -47,6 +47,7 @@ using testing::NaggyMock;
...
@@ -47,6 +47,7 @@ using testing::NaggyMock;
using
testing
::
Ref
;
using
testing
::
Ref
;
using
testing
::
Return
;
using
testing
::
Return
;
using
testing
::
Sequence
;
using
testing
::
Sequence
;
using
testing
::
Value
;
class
MockFoo
{
class
MockFoo
{
public:
public:
...
@@ -268,6 +269,10 @@ TEST_F(GMockOutputTest, CatchesLeakedMocks) {
...
@@ -268,6 +269,10 @@ TEST_F(GMockOutputTest, CatchesLeakedMocks) {
// Both foo1 and foo2 are deliberately leaked.
// Both foo1 and foo2 are deliberately leaked.
}
}
MATCHER_P2
(
IsPair
,
first
,
second
,
""
)
{
return
Value
(
arg
.
first
,
first
)
&&
Value
(
arg
.
second
,
second
);
}
void
TestCatchesLeakedMocksInAdHocTests
()
{
void
TestCatchesLeakedMocksInAdHocTests
()
{
MockFoo
*
foo
=
new
MockFoo
;
MockFoo
*
foo
=
new
MockFoo
;
...
@@ -280,7 +285,6 @@ void TestCatchesLeakedMocksInAdHocTests() {
...
@@ -280,7 +285,6 @@ void TestCatchesLeakedMocksInAdHocTests() {
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleMock
(
&
argc
,
argv
);
testing
::
InitGoogleMock
(
&
argc
,
argv
);
// Ensures that the tests pass no matter what value of
// Ensures that the tests pass no matter what value of
// --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
// --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
testing
::
GMOCK_FLAG
(
catch_leaked_mocks
)
=
true
;
testing
::
GMOCK_FLAG
(
catch_leaked_mocks
)
=
true
;
...
...
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