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
1afe1c79
Commit
1afe1c79
authored
Jul 21, 2009
by
zhanyong.wan
Browse files
Adds the ReturnArg<k>() action (by Tim Hockin); refactors gmock-matchers.h (by Zhanyong Wan).
parent
387bdd55
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
249 additions
and
444 deletions
+249
-444
include/gmock/gmock-generated-actions.h
include/gmock/gmock-generated-actions.h
+7
-0
include/gmock/gmock-generated-actions.h.pump
include/gmock/gmock-generated-actions.h.pump
+8
-1
include/gmock/gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+1
-221
include/gmock/gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+2
-222
include/gmock/gmock-matchers.h
include/gmock/gmock-matchers.h
+215
-0
test/gmock-generated-actions_test.cc
test/gmock-generated-actions_test.cc
+16
-0
No files found.
include/gmock/gmock-generated-actions.h
View file @
1afe1c79
...
@@ -2441,6 +2441,13 @@ ACTION_TEMPLATE(InvokeArgument,
...
@@ -2441,6 +2441,13 @@ ACTION_TEMPLATE(InvokeArgument,
::
std
::
tr1
::
get
<
k
>
(
args
),
p0
,
p1
,
p2
,
p3
,
p4
,
p5
,
p6
,
p7
,
p8
,
p9
);
::
std
::
tr1
::
get
<
k
>
(
args
),
p0
,
p1
,
p2
,
p3
,
p4
,
p5
,
p6
,
p7
,
p8
,
p9
);
}
}
// Action ReturnArg<k>() returns the k-th argument of the mock function.
ACTION_TEMPLATE
(
ReturnArg
,
HAS_1_TEMPLATE_PARAMS
(
int
,
k
),
AND_0_VALUE_PARAMS
())
{
return
std
::
tr1
::
get
<
k
>
(
args
);
}
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
// mock function to *pointer.
// mock function to *pointer.
ACTION_TEMPLATE
(
SaveArg
,
ACTION_TEMPLATE
(
SaveArg
,
...
...
include/gmock/gmock-generated-actions.h.pump
View file @
1afe1c79
$$
-*-
mode
:
c
++
;
-*-
$$
-*-
mode
:
c
++
;
-*-
$$
This
is
a
Pump
source
file
.
Please
use
Pump
to
convert
it
to
$$
This
is
a
Pump
source
file
.
Please
use
Pump
to
convert
it
to
$$
gmock
-
generated
-
variadic
-
actions
.
h
.
$$
gmock
-
generated
-
actions
.
h
.
$$
$$
$
var
n
=
10
$$
The
maximum
arity
we
support
.
$
var
n
=
10
$$
The
maximum
arity
we
support
.
$$}}
This
meta
comment
fixes
auto
-
indentation
in
editors
.
$$}}
This
meta
comment
fixes
auto
-
indentation
in
editors
.
...
@@ -940,6 +940,13 @@ ACTION_TEMPLATE(InvokeArgument,
...
@@ -940,6 +940,13 @@ ACTION_TEMPLATE(InvokeArgument,
]]
]]
// Action ReturnArg<k>() returns the k-th argument of the mock function.
ACTION_TEMPLATE
(
ReturnArg
,
HAS_1_TEMPLATE_PARAMS
(
int
,
k
),
AND_0_VALUE_PARAMS
())
{
return
std
::
tr1
::
get
<
k
>
(
args
);
}
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
// mock function to *pointer.
// mock function to *pointer.
ACTION_TEMPLATE
(
SaveArg
,
ACTION_TEMPLATE
(
SaveArg
,
...
...
include/gmock/gmock-generated-matchers.h
View file @
1afe1c79
...
@@ -290,163 +290,7 @@ class ArgsMatcher {
...
@@ -290,163 +290,7 @@ class ArgsMatcher {
const
InnerMatcher
inner_matcher_
;
const
InnerMatcher
inner_matcher_
;
};
};
// Implements ElementsAre() and ElementsAreArray().
// Implements ElementsAre() of 1-10 arguments.
template
<
typename
Container
>
class
ElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
{
public:
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
internal
::
StlContainerView
<
RawContainer
>
View
;
typedef
typename
View
::
type
StlContainer
;
typedef
typename
View
::
const_reference
StlContainerReference
;
typedef
typename
StlContainer
::
value_type
Element
;
// Constructs the matcher from a sequence of element values or
// element matchers.
template
<
typename
InputIter
>
ElementsAreMatcherImpl
(
InputIter
first
,
size_t
count
)
{
matchers_
.
reserve
(
count
);
InputIter
it
=
first
;
for
(
size_t
i
=
0
;
i
!=
count
;
++
i
,
++
it
)
{
matchers_
.
push_back
(
MatcherCast
<
const
Element
&>
(
*
it
));
}
}
// Returns true iff 'container' matches.
virtual
bool
Matches
(
Container
container
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
stl_container
.
size
()
!=
count
())
return
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
!
matchers_
[
i
].
Matches
(
*
it
))
return
false
;
}
return
true
;
}
// Describes what this matcher does.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
*
os
<<
"is empty"
;
}
else
if
(
count
()
==
1
)
{
*
os
<<
"has 1 element that "
;
matchers_
[
0
].
DescribeTo
(
os
);
}
else
{
*
os
<<
"has "
<<
Elements
(
count
())
<<
" where
\n
"
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
*
os
<<
"element "
<<
i
<<
" "
;
matchers_
[
i
].
DescribeTo
(
os
);
if
(
i
+
1
<
count
())
{
*
os
<<
",
\n
"
;
}
}
}
}
// Describes what the negation of this matcher does.
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
*
os
<<
"is not empty"
;
return
;
}
*
os
<<
"does not have "
<<
Elements
(
count
())
<<
", or
\n
"
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
*
os
<<
"element "
<<
i
<<
" "
;
matchers_
[
i
].
DescribeNegationTo
(
os
);
if
(
i
+
1
<
count
())
{
*
os
<<
", or
\n
"
;
}
}
}
// Explains why 'container' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
Container
container
,
::
std
::
ostream
*
os
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
Matches
(
container
))
{
// We need to explain why *each* element matches (the obvious
// ones can be skipped).
bool
reason_printed
=
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
if
(
reason_printed
)
{
*
os
<<
",
\n
"
;
}
*
os
<<
"element "
<<
i
<<
" "
<<
s
;
reason_printed
=
true
;
}
}
}
else
{
// We need to explain why the container doesn't match.
const
size_t
actual_count
=
stl_container
.
size
();
if
(
actual_count
!=
count
())
{
// The element count doesn't match. If the container is
// empty, there's no need to explain anything as Google Mock
// already prints the empty container. Otherwise we just need
// to show how many elements there actually are.
if
(
actual_count
!=
0
)
{
*
os
<<
"has "
<<
Elements
(
actual_count
);
}
return
;
}
// The container has the right size but at least one element
// doesn't match expectation. We need to find this element and
// explain why it doesn't match.
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
matchers_
[
i
].
Matches
(
*
it
))
{
continue
;
}
*
os
<<
"element "
<<
i
<<
" doesn't match"
;
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
*
os
<<
" ("
<<
s
<<
")"
;
}
return
;
}
}
}
private:
static
Message
Elements
(
size_t
count
)
{
return
Message
()
<<
count
<<
(
count
==
1
?
" element"
:
" elements"
);
}
size_t
count
()
const
{
return
matchers_
.
size
();
}
std
::
vector
<
Matcher
<
const
Element
&>
>
matchers_
;
};
// Implements ElementsAre() of 0-10 arguments.
class
ElementsAreMatcher0
{
public:
ElementsAreMatcher0
()
{}
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
::
value_type
Element
;
const
Matcher
<
const
Element
&>*
const
matchers
=
NULL
;
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
matchers
,
0
));
}
};
template
<
typename
T1
>
template
<
typename
T1
>
class
ElementsAreMatcher1
{
class
ElementsAreMatcher1
{
...
@@ -788,28 +632,6 @@ class ElementsAreMatcher10 {
...
@@ -788,28 +632,6 @@ class ElementsAreMatcher10 {
const
T10
&
e10_
;
const
T10
&
e10_
;
};
};
// Implements ElementsAreArray().
template
<
typename
T
>
class
ElementsAreArrayMatcher
{
public:
ElementsAreArrayMatcher
(
const
T
*
first
,
size_t
count
)
:
first_
(
first
),
count_
(
count
)
{}
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
::
value_type
Element
;
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
first_
,
count_
));
}
private:
const
T
*
const
first_
;
const
size_t
count_
;
};
}
// namespace internal
}
// namespace internal
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
...
@@ -1169,48 +991,6 @@ ElementsAreArray(const T (&array)[N]) {
...
@@ -1169,48 +991,6 @@ ElementsAreArray(const T (&array)[N]) {
// To learn more about using these macros, please search for 'MATCHER'
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
// on http://code.google.com/p/googlemock/wiki/CookBook.
namespace
testing
{
namespace
internal
{
// Constants denoting interpolations in a matcher description string.
const
int
kTupleInterpolation
=
-
1
;
// "%(*)s"
const
int
kPercentInterpolation
=
-
2
;
// "%%"
const
int
kInvalidInterpolation
=
-
3
;
// "%" followed by invalid text
// Records the location and content of an interpolation.
struct
Interpolation
{
Interpolation
(
const
char
*
start
,
const
char
*
end
,
int
param
)
:
start_pos
(
start
),
end_pos
(
end
),
param_index
(
param
)
{}
// Points to the start of the interpolation (the '%' character).
const
char
*
start_pos
;
// Points to the first character after the interpolation.
const
char
*
end_pos
;
// 0-based index of the interpolated matcher parameter;
// kTupleInterpolation for "%(*)s"; kPercentInterpolation for "%%".
int
param_index
;
};
typedef
::
std
::
vector
<
Interpolation
>
Interpolations
;
// Parses a matcher description string and returns a vector of
// interpolations that appear in the string; generates non-fatal
// failures iff 'description' is an invalid matcher description.
// 'param_names' is a NULL-terminated array of parameter names in the
// order they appear in the MATCHER_P*() parameter list.
Interpolations
ValidateMatcherDescription
(
const
char
*
param_names
[],
const
char
*
description
);
// Returns the actual matcher description, given the matcher name,
// user-supplied description template string, interpolations in the
// string, and the printed values of the matcher parameters.
string
FormatMatcherDescription
(
const
char
*
matcher_name
,
const
char
*
description
,
const
Interpolations
&
interp
,
const
Strings
&
param_values
);
}
// namespace internal
}
// namespace testing
#define MATCHER(name, description)\
#define MATCHER(name, description)\
class name##Matcher {\
class name##Matcher {\
public:\
public:\
...
...
include/gmock/gmock-generated-matchers.h.pump
View file @
1afe1c79
$$
-*-
mode
:
c
++
;
-*-
$$
-*-
mode
:
c
++
;
-*-
$$
This
is
a
Pump
source
file
.
Please
use
Pump
to
convert
it
to
$$
This
is
a
Pump
source
file
.
Please
use
Pump
to
convert
it
to
$$
gmock
-
generated
-
variadic
-
actions
.
h
.
$$
gmock
-
generated
-
actions
.
h
.
$$
$$
$
var
n
=
10
$$
The
maximum
arity
we
support
.
$
var
n
=
10
$$
The
maximum
arity
we
support
.
$$
}}
This
line
fixes
auto
-
indentation
of
the
following
code
in
Emacs
.
$$
}}
This
line
fixes
auto
-
indentation
of
the
following
code
in
Emacs
.
...
@@ -173,163 +173,7 @@ class ArgsMatcher {
...
@@ -173,163 +173,7 @@ class ArgsMatcher {
const
InnerMatcher
inner_matcher_
;
const
InnerMatcher
inner_matcher_
;
};
};
// Implements ElementsAre() and ElementsAreArray().
// Implements ElementsAre() of 1-$n arguments.
template
<
typename
Container
>
class
ElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
{
public:
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
internal
::
StlContainerView
<
RawContainer
>
View
;
typedef
typename
View
::
type
StlContainer
;
typedef
typename
View
::
const_reference
StlContainerReference
;
typedef
typename
StlContainer
::
value_type
Element
;
// Constructs the matcher from a sequence of element values or
// element matchers.
template
<
typename
InputIter
>
ElementsAreMatcherImpl
(
InputIter
first
,
size_t
count
)
{
matchers_
.
reserve
(
count
);
InputIter
it
=
first
;
for
(
size_t
i
=
0
;
i
!=
count
;
++
i
,
++
it
)
{
matchers_
.
push_back
(
MatcherCast
<
const
Element
&>
(
*
it
));
}
}
// Returns true iff 'container' matches.
virtual
bool
Matches
(
Container
container
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
stl_container
.
size
()
!=
count
())
return
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
!
matchers_
[
i
].
Matches
(
*
it
))
return
false
;
}
return
true
;
}
// Describes what this matcher does.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
*
os
<<
"is empty"
;
}
else
if
(
count
()
==
1
)
{
*
os
<<
"has 1 element that "
;
matchers_
[
0
].
DescribeTo
(
os
);
}
else
{
*
os
<<
"has "
<<
Elements
(
count
())
<<
" where
\n
"
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
*
os
<<
"element "
<<
i
<<
" "
;
matchers_
[
i
].
DescribeTo
(
os
);
if
(
i
+
1
<
count
())
{
*
os
<<
",
\n
"
;
}
}
}
}
// Describes what the negation of this matcher does.
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
*
os
<<
"is not empty"
;
return
;
}
*
os
<<
"does not have "
<<
Elements
(
count
())
<<
", or
\n
"
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
*
os
<<
"element "
<<
i
<<
" "
;
matchers_
[
i
].
DescribeNegationTo
(
os
);
if
(
i
+
1
<
count
())
{
*
os
<<
", or
\n
"
;
}
}
}
// Explains why 'container' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
Container
container
,
::
std
::
ostream
*
os
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
Matches
(
container
))
{
// We need to explain why *each* element matches (the obvious
// ones can be skipped).
bool
reason_printed
=
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
if
(
reason_printed
)
{
*
os
<<
",
\n
"
;
}
*
os
<<
"element "
<<
i
<<
" "
<<
s
;
reason_printed
=
true
;
}
}
}
else
{
// We need to explain why the container doesn't match.
const
size_t
actual_count
=
stl_container
.
size
();
if
(
actual_count
!=
count
())
{
// The element count doesn't match. If the container is
// empty, there's no need to explain anything as Google Mock
// already prints the empty container. Otherwise we just need
// to show how many elements there actually are.
if
(
actual_count
!=
0
)
{
*
os
<<
"has "
<<
Elements
(
actual_count
);
}
return
;
}
// The container has the right size but at least one element
// doesn't match expectation. We need to find this element and
// explain why it doesn't match.
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
matchers_
[
i
].
Matches
(
*
it
))
{
continue
;
}
*
os
<<
"element "
<<
i
<<
" doesn't match"
;
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
*
os
<<
" ("
<<
s
<<
")"
;
}
return
;
}
}
}
private:
static
Message
Elements
(
size_t
count
)
{
return
Message
()
<<
count
<<
(
count
==
1
?
" element"
:
" elements"
);
}
size_t
count
()
const
{
return
matchers_
.
size
();
}
std
::
vector
<
Matcher
<
const
Element
&>
>
matchers_
;
};
// Implements ElementsAre() of 0-10 arguments.
class
ElementsAreMatcher0
{
public:
ElementsAreMatcher0
()
{}
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
::
value_type
Element
;
const
Matcher
<
const
Element
&>*
const
matchers
=
NULL
;
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
matchers
,
0
));
}
};
$
range
i
1.
.
n
$
range
i
1.
.
n
...
@@ -369,28 +213,6 @@ $for j [[
...
@@ -369,28 +213,6 @@ $for j [[
]]
]]
// Implements ElementsAreArray().
template
<
typename
T
>
class
ElementsAreArrayMatcher
{
public:
ElementsAreArrayMatcher
(
const
T
*
first
,
size_t
count
)
:
first_
(
first
),
count_
(
count
)
{}
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
::
value_type
Element
;
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
first_
,
count_
));
}
private:
const
T
*
const
first_
;
const
size_t
count_
;
};
}
// namespace internal
}
// namespace internal
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
...
@@ -625,48 +447,6 @@ $$ // show up in the generated code.
...
@@ -625,48 +447,6 @@ $$ // show up in the generated code.
// To learn more about using these macros, please search for 'MATCHER'
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
// on http://code.google.com/p/googlemock/wiki/CookBook.
namespace
testing
{
namespace
internal
{
// Constants denoting interpolations in a matcher description string.
const
int
kTupleInterpolation
=
-
1
;
// "%(*)s"
const
int
kPercentInterpolation
=
-
2
;
// "%%"
const
int
kInvalidInterpolation
=
-
3
;
// "%" followed by invalid text
// Records the location and content of an interpolation.
struct
Interpolation
{
Interpolation
(
const
char
*
start
,
const
char
*
end
,
int
param
)
:
start_pos
(
start
),
end_pos
(
end
),
param_index
(
param
)
{}
// Points to the start of the interpolation (the '%' character).
const
char
*
start_pos
;
// Points to the first character after the interpolation.
const
char
*
end_pos
;
// 0-based index of the interpolated matcher parameter;
// kTupleInterpolation for "%(*)s"; kPercentInterpolation for "%%".
int
param_index
;
};
typedef
::
std
::
vector
<
Interpolation
>
Interpolations
;
// Parses a matcher description string and returns a vector of
// interpolations that appear in the string; generates non-fatal
// failures iff 'description' is an invalid matcher description.
// 'param_names' is a NULL-terminated array of parameter names in the
// order they appear in the MATCHER_P*() parameter list.
Interpolations
ValidateMatcherDescription
(
const
char
*
param_names
[],
const
char
*
description
);
// Returns the actual matcher description, given the matcher name,
// user-supplied description template string, interpolations in the
// string, and the printed values of the matcher parameters.
string
FormatMatcherDescription
(
const
char
*
matcher_name
,
const
char
*
description
,
const
Interpolations
&
interp
,
const
Strings
&
param_values
);
}
// namespace internal
}
// namespace testing
$
range
i
0.
.
n
$
range
i
0.
.
n
$
for
i
$
for
i
...
...
include/gmock/gmock-matchers.h
View file @
1afe1c79
...
@@ -1925,6 +1925,221 @@ class KeyMatcher {
...
@@ -1925,6 +1925,221 @@ class KeyMatcher {
const
M
matcher_for_key_
;
const
M
matcher_for_key_
;
};
};
// Implements ElementsAre() and ElementsAreArray().
template
<
typename
Container
>
class
ElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
{
public:
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
internal
::
StlContainerView
<
RawContainer
>
View
;
typedef
typename
View
::
type
StlContainer
;
typedef
typename
View
::
const_reference
StlContainerReference
;
typedef
typename
StlContainer
::
value_type
Element
;
// Constructs the matcher from a sequence of element values or
// element matchers.
template
<
typename
InputIter
>
ElementsAreMatcherImpl
(
InputIter
first
,
size_t
count
)
{
matchers_
.
reserve
(
count
);
InputIter
it
=
first
;
for
(
size_t
i
=
0
;
i
!=
count
;
++
i
,
++
it
)
{
matchers_
.
push_back
(
MatcherCast
<
const
Element
&>
(
*
it
));
}
}
// Returns true iff 'container' matches.
virtual
bool
Matches
(
Container
container
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
stl_container
.
size
()
!=
count
())
return
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
!
matchers_
[
i
].
Matches
(
*
it
))
return
false
;
}
return
true
;
}
// Describes what this matcher does.
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
*
os
<<
"is empty"
;
}
else
if
(
count
()
==
1
)
{
*
os
<<
"has 1 element that "
;
matchers_
[
0
].
DescribeTo
(
os
);
}
else
{
*
os
<<
"has "
<<
Elements
(
count
())
<<
" where
\n
"
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
*
os
<<
"element "
<<
i
<<
" "
;
matchers_
[
i
].
DescribeTo
(
os
);
if
(
i
+
1
<
count
())
{
*
os
<<
",
\n
"
;
}
}
}
}
// Describes what the negation of this matcher does.
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
if
(
count
()
==
0
)
{
*
os
<<
"is not empty"
;
return
;
}
*
os
<<
"does not have "
<<
Elements
(
count
())
<<
", or
\n
"
;
for
(
size_t
i
=
0
;
i
!=
count
();
++
i
)
{
*
os
<<
"element "
<<
i
<<
" "
;
matchers_
[
i
].
DescribeNegationTo
(
os
);
if
(
i
+
1
<
count
())
{
*
os
<<
", or
\n
"
;
}
}
}
// Explains why 'container' matches, or doesn't match, this matcher.
virtual
void
ExplainMatchResultTo
(
Container
container
,
::
std
::
ostream
*
os
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
if
(
Matches
(
container
))
{
// We need to explain why *each* element matches (the obvious
// ones can be skipped).
bool
reason_printed
=
false
;
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
if
(
reason_printed
)
{
*
os
<<
",
\n
"
;
}
*
os
<<
"element "
<<
i
<<
" "
<<
s
;
reason_printed
=
true
;
}
}
}
else
{
// We need to explain why the container doesn't match.
const
size_t
actual_count
=
stl_container
.
size
();
if
(
actual_count
!=
count
())
{
// The element count doesn't match. If the container is
// empty, there's no need to explain anything as Google Mock
// already prints the empty container. Otherwise we just need
// to show how many elements there actually are.
if
(
actual_count
!=
0
)
{
*
os
<<
"has "
<<
Elements
(
actual_count
);
}
return
;
}
// The container has the right size but at least one element
// doesn't match expectation. We need to find this element and
// explain why it doesn't match.
typename
StlContainer
::
const_iterator
it
=
stl_container
.
begin
();
for
(
size_t
i
=
0
;
i
!=
count
();
++
it
,
++
i
)
{
if
(
matchers_
[
i
].
Matches
(
*
it
))
{
continue
;
}
*
os
<<
"element "
<<
i
<<
" doesn't match"
;
::
std
::
stringstream
ss
;
matchers_
[
i
].
ExplainMatchResultTo
(
*
it
,
&
ss
);
const
string
s
=
ss
.
str
();
if
(
!
s
.
empty
())
{
*
os
<<
" ("
<<
s
<<
")"
;
}
return
;
}
}
}
private:
static
Message
Elements
(
size_t
count
)
{
return
Message
()
<<
count
<<
(
count
==
1
?
" element"
:
" elements"
);
}
size_t
count
()
const
{
return
matchers_
.
size
();
}
std
::
vector
<
Matcher
<
const
Element
&>
>
matchers_
;
};
// Implements ElementsAre() of 0 arguments.
class
ElementsAreMatcher0
{
public:
ElementsAreMatcher0
()
{}
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
::
value_type
Element
;
const
Matcher
<
const
Element
&>*
const
matchers
=
NULL
;
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
matchers
,
0
));
}
};
// Implements ElementsAreArray().
template
<
typename
T
>
class
ElementsAreArrayMatcher
{
public:
ElementsAreArrayMatcher
(
const
T
*
first
,
size_t
count
)
:
first_
(
first
),
count_
(
count
)
{}
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
typedef
GMOCK_REMOVE_CONST_
(
GMOCK_REMOVE_REFERENCE_
(
Container
))
RawContainer
;
typedef
typename
internal
::
StlContainerView
<
RawContainer
>::
type
::
value_type
Element
;
return
MakeMatcher
(
new
ElementsAreMatcherImpl
<
Container
>
(
first_
,
count_
));
}
private:
const
T
*
const
first_
;
const
size_t
count_
;
};
// Constants denoting interpolations in a matcher description string.
const
int
kTupleInterpolation
=
-
1
;
// "%(*)s"
const
int
kPercentInterpolation
=
-
2
;
// "%%"
const
int
kInvalidInterpolation
=
-
3
;
// "%" followed by invalid text
// Records the location and content of an interpolation.
struct
Interpolation
{
Interpolation
(
const
char
*
start
,
const
char
*
end
,
int
param
)
:
start_pos
(
start
),
end_pos
(
end
),
param_index
(
param
)
{}
// Points to the start of the interpolation (the '%' character).
const
char
*
start_pos
;
// Points to the first character after the interpolation.
const
char
*
end_pos
;
// 0-based index of the interpolated matcher parameter;
// kTupleInterpolation for "%(*)s"; kPercentInterpolation for "%%".
int
param_index
;
};
typedef
::
std
::
vector
<
Interpolation
>
Interpolations
;
// Parses a matcher description string and returns a vector of
// interpolations that appear in the string; generates non-fatal
// failures iff 'description' is an invalid matcher description.
// 'param_names' is a NULL-terminated array of parameter names in the
// order they appear in the MATCHER_P*() parameter list.
Interpolations
ValidateMatcherDescription
(
const
char
*
param_names
[],
const
char
*
description
);
// Returns the actual matcher description, given the matcher name,
// user-supplied description template string, interpolations in the
// string, and the printed values of the matcher parameters.
string
FormatMatcherDescription
(
const
char
*
matcher_name
,
const
char
*
description
,
const
Interpolations
&
interp
,
const
Strings
&
param_values
);
}
// namespace internal
}
// namespace internal
// Implements MatcherCast().
// Implements MatcherCast().
...
...
test/gmock-generated-actions_test.cc
View file @
1afe1c79
...
@@ -59,6 +59,7 @@ using testing::DoAll;
...
@@ -59,6 +59,7 @@ using testing::DoAll;
using
testing
::
Invoke
;
using
testing
::
Invoke
;
using
testing
::
InvokeArgument
;
using
testing
::
InvokeArgument
;
using
testing
::
Return
;
using
testing
::
Return
;
using
testing
::
ReturnArg
;
using
testing
::
ReturnNew
;
using
testing
::
ReturnNew
;
using
testing
::
SaveArg
;
using
testing
::
SaveArg
;
using
testing
::
SetArgReferee
;
using
testing
::
SetArgReferee
;
...
@@ -1382,6 +1383,21 @@ TEST(ActionPnMacroTest, CanExplicitlyInstantiateWithReferenceTypes) {
...
@@ -1382,6 +1383,21 @@ TEST(ActionPnMacroTest, CanExplicitlyInstantiateWithReferenceTypes) {
EXPECT_EQ
(
55
,
a
.
Perform
(
empty
));
EXPECT_EQ
(
55
,
a
.
Perform
(
empty
));
}
}
TEST
(
ReturnArgActionTest
,
WorksForOneArgIntArg0
)
{
const
Action
<
int
(
int
)
>
a
=
ReturnArg
<
0
>
();
EXPECT_EQ
(
5
,
a
.
Perform
(
make_tuple
(
5
)));
}
TEST
(
ReturnArgActionTest
,
WorksForMultiArgBoolArg0
)
{
const
Action
<
bool
(
bool
,
bool
,
bool
)
>
a
=
ReturnArg
<
0
>
();
EXPECT_TRUE
(
a
.
Perform
(
make_tuple
(
true
,
false
,
false
)));
}
TEST
(
ReturnArgActionTest
,
WorksForMultiArgStringArg2
)
{
const
Action
<
string
(
int
,
int
,
string
,
int
)
>
a
=
ReturnArg
<
2
>
();
EXPECT_EQ
(
"seven"
,
a
.
Perform
(
make_tuple
(
5
,
6
,
string
(
"seven"
),
8
)));
}
TEST
(
SaveArgActionTest
,
WorksForSameType
)
{
TEST
(
SaveArgActionTest
,
WorksForSameType
)
{
int
result
=
0
;
int
result
=
0
;
const
Action
<
void
(
int
n
)
>
a1
=
SaveArg
<
0
>
(
&
result
);
const
Action
<
void
(
int
n
)
>
a1
=
SaveArg
<
0
>
(
&
result
);
...
...
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