Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
4a5330d3
Commit
4a5330d3
authored
Feb 19, 2009
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implements custom description string for MATCHER*.
parent
e0d051ea
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
422 additions
and
82 deletions
+422
-82
gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+0
-0
gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+109
-32
gmock-printers.h
include/gmock/gmock-printers.h
+74
-22
gmock-matchers.cc
src/gmock-matchers.cc
+143
-2
gmock-generated-matchers_test.cc
test/gmock-generated-matchers_test.cc
+44
-17
gmock-matchers_test.cc
test/gmock-matchers_test.cc
+0
-0
gmock-printers_test.cc
test/gmock-printers_test.cc
+52
-9
No files found.
include/gmock/gmock-generated-matchers.h
View file @
4a5330d3
This diff is collapsed.
Click to expand it.
include/gmock/gmock-generated-matchers.h.pump
View file @
4a5330d3
...
...
@@ -43,18 +43,11 @@ $var n = 10 $$ The maximum arity we support.
#include <string>
#include <vector>
#include <gmock/gmock-matchers.h>
#include <gmock/gmock-printers.h>
namespace
testing
{
namespace
internal
{
// Generates a non-fatal failure iff 'description' is not a valid
// matcher description.
inline
void
ValidateMatcherDescription
(
const
char
*
description
)
{
EXPECT_STREQ
(
""
,
description
)
<<
"The description string in a MATCHER*() macro must be
\"\"
"
"at this moment. We will implement custom description string soon."
;
}
// Implements ElementsAre() and ElementsAreArray().
template
<
typename
Container
>
class
ElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
{
...
...
@@ -310,6 +303,9 @@ ElementsAreArray(const T (&array)[N]) {
}
}
// namespace testing
$$
}
// This Pump meta comment fixes auto-indentation in Emacs. It will not
$$
// show up in the generated code.
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax:
...
...
@@ -318,10 +314,18 @@ ElementsAreArray(const T (&array)[N]) {
//
// will define a matcher with the given name that executes the
// statements, which must return a bool to indicate if the match
// succeeds. For now, the description_string must be "", but we'll
// allow other values soon. Inside the statements, you can refer to
// the value being matched by 'arg', and refer to its type by
// 'arg_type'. For example:
// succeeds. Inside the statements, you can refer to the value being
// matched by 'arg', and refer to its type by 'arg_type'.
//
// The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a
// MATCHER() is usually defined in a header file shared by multiple
// C++ source files, we require the description to be a C-string
// literal to avoid possible side effects. It can be empty, in which
// case we'll use the sequence of words in the matcher name as the
// description.
//
// For example:
//
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
//
...
...
@@ -384,6 +388,38 @@ ElementsAreArray(const T (&array)[N]) {
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
// support multi-parameter matchers.
//
// When defining a parameterized matcher, you can use Python-style
// interpolations in the description string to refer to the parameter
// values. We support the following syntax currently:
//
// %% a single '%' character
// %(*)s all parameters of the matcher printed as a tuple
// %(foo)s value of the matcher parameter named 'foo'
//
// For example,
//
// MATCHER_P2(InClosedRange, low, hi, "is in range [%(low)s, %(hi)s]") {
// return low <= arg && arg <= hi;
// }
// ...
// EXPECT_THAT(3, InClosedRange(4, 6));
//
// would generate a failure that contains the message:
//
// Expected: is in range [4, 6]
//
// If you specify "" as the description, the failure message will
// contain the sequence of words in the matcher name followed by the
// parameter values printed as a tuple. For example,
//
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
// ...
// EXPECT_THAT(3, InClosedRange(4, 6));
//
// would generate a failure that contains the text:
//
// Expected: in closed range (4, 6)
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
...
...
@@ -440,6 +476,48 @@ ElementsAreArray(const T (&array)[N]) {
// To learn more about using these macros, please search for 'MATCHER'
// 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
$
for
i
...
...
@@ -454,7 +532,11 @@ $var template = [[$if i==0 [[]] $else [[
template
<
$
for
j
,
[[
typename
p
$
j
##
_type
]]
>
\
]]]]
$
var
ctor_param_list
=
[[
$
for
j
,
[[
p
$
j
##
_type
gmock_p
$
j
]]]]
$
var
impl_ctor_param_list
=
[[
$
for
j
[[
p
$
j
##
_type
gmock_p
$
j
,
]]
const
::
testing
::
internal
::
Interpolations
&
gmock_interp
]]
$
var
impl_inits
=
[[
:
$
for
j
[[
p
$
j
(
gmock_p
$
j
),
]]
gmock_interp_
(
gmock_interp
)]]
$
var
inits
=
[[
$
if
i
==
0
[[]]
$
else
[[
:
$
for
j
,
[[
p
$
j
(
gmock_p
$
j
)]]]]]]
$
var
params_and_interp
=
[[
$
for
j
[[
p
$
j
,
]]
gmock_interp_
]]
$
var
params
=
[[
$
for
j
,
[[
p
$
j
]]]]
$
var
param_types
=
[[
$
if
i
==
0
[[]]
$
else
[[
<
$
for
j
,
[[
p
$
j
##
_type
]]
>
]]]]
$
var
param_types_and_names
=
[[
$
for
j
,
[[
p
$
j
##
_type
p
$
j
]]]]
...
...
@@ -475,34 +557,29 @@ $var param_field_decls2 = [[$for j
template
<
typename
arg_type
>
\
class
gmock_Impl
:
public
::
testing
::
MatcherInterface
<
arg_type
>
{
\
public
:
\
[[
$
if
i
==
1
[[
explicit
]]]]
gmock_Impl
(
$
ctor_param_list
)
$
inits
{}
\
[[
$
if
i
==
1
[[
explicit
]]]]
gmock_Impl
(
$
impl_ctor_param_list
)
\
$
impl_inits
{}
\
virtual
bool
Matches
(
arg_type
arg
)
const
;
\
virtual
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
\
*
os
<<
::
testing
::
internal
::
ConvertIdentifierNameToWords
(
#
name
);
\
[[
$
if
i
==
1
[[
*
os
<<
" "
;
\
::
testing
::
internal
::
UniversalPrint
(
p0
,
os
);
\
]]
$
elif
i
>=
2
[[
*
os
<<
" ("
;
\
::
testing
::
internal
::
UniversalPrint
(
p0
,
os
);
\
$
range
k
1.
.
i
-
1
$
for
k
[[
*
os
<<
", "
;
\
::
testing
::
internal
::
UniversalPrint
(
p
$
k
,
os
);
\
]]
*
os
<<
")"
;
\
]]]]
virtual
void
DescribeTo
(
::
std
::
ostream
*
gmock_os
)
const
{
\
const
::
testing
::
internal
::
Strings
&
gmock_printed_params
=
\
::
testing
::
internal
::
UniversalTersePrintTupleFieldsToStrings
(
\
::
std
::
tr1
::
tuple
<
$
for
j
,
[[
p
$
j
##
_type
]]
>
(
$
for
j
,
[[
p
$
j
]]));
\
*
gmock_os
<<
::
testing
::
internal
::
FormatMatcherDescription
(
\
#
name
,
description
,
gmock_interp_
,
gmock_printed_params
);
\
}
\$
param_field_decls
const
::
testing
::
internal
::
Interpolations
gmock_interp_
;
\
};
\
template
<
typename
arg_type
>
\
operator
::
testing
::
Matcher
<
arg_type
>
()
const
{
\
return
::
testing
::
Matcher
<
arg_type
>
(
new
gmock_Impl
<
arg_type
>
(
$
params
));
\
return
::
testing
::
Matcher
<
arg_type
>
(
\
new
gmock_Impl
<
arg_type
>
(
$
params_and_interp
));
\
}
\
$
class_name
(
$
ctor_param_list
)
$
inits
{
\
::
testing
::
internal
::
ValidateMatcherDescription
(
description
);
\
const
char
*
gmock_param_names
[]
=
{
$
for
j
[[
#
p
$
j
,
]]
NULL
};
\
gmock_interp_
=
::
testing
::
internal
::
ValidateMatcherDescription
(
\
gmock_param_names
,
(
""
description
""
));
\
}
\$
param_field_decls2
::
testing
::
internal
::
Interpolations
gmock_interp_
;
\
};
\$
template
inline
$
class_name
$
param_types
name
(
$
param_types_and_names
)
{
\
return
$
class_name
$
param_types
(
$
params
);
\
...
...
include/gmock/gmock-printers.h
View file @
4a5330d3
...
...
@@ -41,22 +41,36 @@
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
// defines Foo. If both are defined, PrintTo() takes precedence.
// When T is a reference type, the address of the value is also
//
// To aid debugging: when T is a reference type, the address of the
// value is also printed; when T is a (const) char pointer, both the
// pointer value and the NUL-terminated string it points to are
// printed.
//
// We also provide some convenient wrappers:
//
// // Prints to a string.
// string ::testing::internal::UniversalPrinter<T>::PrintAsString(value);
// // Prints a value using its inferred type.
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
// // Prints a value as the given type to a string.
// string ::testing::internal::UniversalPrinter<T>::PrintToString(value);
//
// // Prints a value tersely: for a reference type, the referenced
// // value (but not the address) is printed; for a (const) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
//
// // Prints the fields of a tuple tersely to a string vector, one
// // element for each field.
// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
// const Tuple& value);
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
#include <ostream> // NOLINT
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <gmock/internal/gmock-internal-utils.h>
#include <gmock/internal/gmock-port.h>
...
...
@@ -350,13 +364,19 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
// Overload for ::std::tr1::tuple. Needed for printing function
// arguments, which are packed as tuples.
// This helper template allows PrintTo() for tuples to be defined by
typedef
::
std
::
vector
<
string
>
Strings
;
// This helper template allows PrintTo() for tuples and
// UniversalTersePrintTupleFieldsToStrings() to be defined by
// induction on the number of tuple fields. The idea is that
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
// fields in tuple t, and can be defined in terms of
// TuplePrefixPrinter<N - 1>.
// The inductive case.
template
<
size_t
N
>
struct
TuplePrefixPrinter
{
// Prints the first N fields of a tuple.
template
<
typename
Tuple
>
static
void
PrintPrefixTo
(
const
Tuple
&
t
,
::
std
::
ostream
*
os
)
{
TuplePrefixPrinter
<
N
-
1
>::
PrintPrefixTo
(
t
,
os
);
...
...
@@ -364,20 +384,33 @@ struct TuplePrefixPrinter {
UniversalPrinter
<
typename
::
std
::
tr1
::
tuple_element
<
N
-
1
,
Tuple
>::
type
>
::
Print
(
::
std
::
tr1
::
get
<
N
-
1
>
(
t
),
os
);
}
// Tersely prints the first N fields of a tuple to a string vector,
// one element for each field.
template
<
typename
Tuple
>
static
void
TersePrintPrefixToStrings
(
const
Tuple
&
t
,
Strings
*
strings
)
{
TuplePrefixPrinter
<
N
-
1
>::
TersePrintPrefixToStrings
(
t
,
strings
);
::
std
::
stringstream
ss
;
UniversalTersePrint
(
::
std
::
tr1
::
get
<
N
-
1
>
(
t
),
&
ss
);
strings
->
push_back
(
ss
.
str
());
}
};
// Base cases.
template
<>
struct
TuplePrefixPrinter
<
0
>
{
template
<
typename
Tuple
>
static
void
PrintPrefixTo
(
const
Tuple
&
,
::
std
::
ostream
*
)
{}
};
template
<>
struct
TuplePrefixPrinter
<
1
>
{
template
<
typename
Tuple
>
static
void
PrintPrefixTo
(
const
Tuple
&
t
,
::
std
::
ostream
*
os
)
{
UniversalPrinter
<
typename
::
std
::
tr1
::
tuple_element
<
0
,
Tuple
>::
type
>::
Print
(
::
std
::
tr1
::
get
<
0
>
(
t
),
os
);
}
static
void
TersePrintPrefixToStrings
(
const
Tuple
&
,
Strings
*
)
{}
};
template
<>
template
<
typename
Tuple
>
void
TuplePrefixPrinter
<
1
>::
PrintPrefixTo
(
const
Tuple
&
t
,
::
std
::
ostream
*
os
)
{
UniversalPrinter
<
typename
::
std
::
tr1
::
tuple_element
<
0
,
Tuple
>::
type
>::
Print
(
::
std
::
tr1
::
get
<
0
>
(
t
),
os
);
}
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
...
...
@@ -499,7 +532,7 @@ class UniversalPrinter {
// A convenient wrapper for Print() that returns the print-out as a
// string.
static
string
Print
As
String
(
const
T
&
value
)
{
static
string
Print
To
String
(
const
T
&
value
)
{
::
std
::
stringstream
ss
;
Print
(
value
,
&
ss
);
return
ss
.
str
();
...
...
@@ -548,7 +581,7 @@ class UniversalPrinter<T[N]> {
// A convenient wrapper for Print() that returns the print-out as a
// string.
static
string
Print
As
String
(
const
T
(
&
a
)[
N
])
{
static
string
Print
To
String
(
const
T
(
&
a
)[
N
])
{
::
std
::
stringstream
ss
;
Print
(
a
,
&
ss
);
return
ss
.
str
();
...
...
@@ -577,7 +610,7 @@ class UniversalPrinter<T&> {
// A convenient wrapper for Print() that returns the print-out as a
// string.
static
string
Print
As
String
(
const
T
&
value
)
{
static
string
Print
To
String
(
const
T
&
value
)
{
::
std
::
stringstream
ss
;
Print
(
value
,
&
ss
);
return
ss
.
str
();
...
...
@@ -588,15 +621,34 @@ class UniversalPrinter<T&> {
#endif // _MSC_VER
};
// Prints a value using its inferred type. In particular, if the
// original type of the value is a reference, the *referenced* type
// (as opposed to the reference type) will be used, as C++ doesn't
// infer reference types. This is useful when you just want to know
// what the value is and don't care if it's a reference or not.
// Prints a value tersely: for a reference type, the referenced value
// (but not the address) is printed; for a (const) char pointer, the
// NUL-terminated string (but not the pointer) is printed.
template
<
typename
T
>
void
UniversalPrint
(
const
T
&
value
,
::
std
::
ostream
*
os
)
{
void
Universal
Terse
Print
(
const
T
&
value
,
::
std
::
ostream
*
os
)
{
UniversalPrinter
<
T
>::
Print
(
value
,
os
);
}
inline
void
UniversalTersePrint
(
const
char
*
str
,
::
std
::
ostream
*
os
)
{
if
(
str
==
NULL
)
{
*
os
<<
"NULL"
;
}
else
{
UniversalPrinter
<
string
>::
Print
(
string
(
str
),
os
);
}
}
inline
void
UniversalTersePrint
(
char
*
str
,
::
std
::
ostream
*
os
)
{
UniversalTersePrint
(
static_cast
<
const
char
*>
(
str
),
os
);
}
// Prints the fields of a tuple tersely to a string vector, one
// element for each field. See the comment before
// UniversalTersePrint() for how we define "tersely".
template
<
typename
Tuple
>
Strings
UniversalTersePrintTupleFieldsToStrings
(
const
Tuple
&
value
)
{
Strings
result
;
TuplePrefixPrinter
<
::
std
::
tr1
::
tuple_size
<
Tuple
>::
value
>::
TersePrintPrefixToStrings
(
value
,
&
result
);
return
result
;
}
}
// namespace internal
}
// namespace testing
...
...
src/gmock-matchers.cc
View file @
4a5330d3
...
...
@@ -31,10 +31,15 @@
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements
the Matcher<const string&>
and
//
Matcher<string>
.
// This file implements
Matcher<const string&>, Matcher<string>,
and
//
utilities for defining matchers
.
#include <gmock/gmock-matchers.h>
#include <gmock/gmock-generated-matchers.h>
#include <string.h>
#include <sstream>
#include <string>
namespace
testing
{
...
...
@@ -58,4 +63,140 @@ Matcher<internal::string>::Matcher(const char* s) {
*
this
=
Eq
(
internal
::
string
(
s
));
}
namespace
internal
{
// Utilities for validating and formatting description strings in the
// MATCHER*() macros.
// Returns the 0-based index of the given parameter in the
// NULL-terminated parameter array; if the parameter is "*", returns
// kTupleInterpolation; if it's not found in the list, returns
// kInvalidInterpolation.
int
GetParamIndex
(
const
char
*
param_names
[],
const
string
&
param_name
)
{
if
(
param_name
==
"*"
)
return
kTupleInterpolation
;
for
(
int
i
=
0
;
param_names
[
i
]
!=
NULL
;
i
++
)
{
if
(
param_name
==
param_names
[
i
])
return
i
;
}
return
kInvalidInterpolation
;
}
// If *pstr starts with the given prefix, modifies *pstr to be right
// past the prefix and returns true; otherwise leaves *pstr unchanged
// and returns false. None of pstr, *pstr, and prefix can be NULL.
bool
SkipPrefix
(
const
char
*
prefix
,
const
char
**
pstr
)
{
const
size_t
prefix_len
=
strlen
(
prefix
);
if
(
strncmp
(
*
pstr
,
prefix
,
prefix_len
)
==
0
)
{
*
pstr
+=
prefix_len
;
return
true
;
}
return
false
;
}
// Helper function used by ValidateMatcherDescription() to format
// error messages.
string
FormatMatcherDescriptionSyntaxError
(
const
char
*
description
,
const
char
*
error_pos
)
{
::
std
::
stringstream
ss
;
ss
<<
"Syntax error at index "
<<
(
error_pos
-
description
)
<<
" in matcher description
\"
"
<<
description
<<
"
\"
: "
;
return
ss
.
str
();
}
// 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
)
{
Interpolations
interps
;
for
(
const
char
*
p
=
description
;
*
p
!=
'\0'
;)
{
if
(
SkipPrefix
(
"%%"
,
&
p
))
{
interps
.
push_back
(
Interpolation
(
p
-
2
,
p
,
kPercentInterpolation
));
}
else
if
(
SkipPrefix
(
"%("
,
&
p
))
{
const
char
*
const
q
=
strstr
(
p
,
")s"
);
if
(
q
==
NULL
)
{
// TODO(wan@google.com): change the source file location in
// the failure to point to where the MATCHER*() macro is used.
ADD_FAILURE
()
<<
FormatMatcherDescriptionSyntaxError
(
description
,
p
-
2
)
<<
"an interpolation must end with
\"
)s
\"
, "
<<
"but
\"
"
<<
(
p
-
2
)
<<
"
\"
does not."
;
}
else
{
const
string
param_name
(
p
,
q
);
const
int
param_index
=
GetParamIndex
(
param_names
,
param_name
);
if
(
param_index
==
kInvalidInterpolation
)
{
ADD_FAILURE
()
<<
FormatMatcherDescriptionSyntaxError
(
description
,
p
)
<<
"
\"
"
<<
param_name
<<
"
\"
is an invalid parameter name."
;
}
else
{
interps
.
push_back
(
Interpolation
(
p
-
2
,
q
+
2
,
param_index
));
p
=
q
+
2
;
}
}
}
else
{
EXPECT_NE
(
*
p
,
'%'
)
<<
FormatMatcherDescriptionSyntaxError
(
description
,
p
)
<<
"use
\"
%%
\"
instead of
\"
%
\"
to print
\"
%
\"
."
;
++
p
;
}
}
return
interps
;
}
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
string
JoinAsTuple
(
const
Strings
&
fields
)
{
switch
(
fields
.
size
())
{
case
0
:
return
""
;
case
1
:
return
fields
[
0
];
default
:
string
result
=
"("
+
fields
[
0
];
for
(
size_t
i
=
1
;
i
<
fields
.
size
();
i
++
)
{
result
+=
", "
;
result
+=
fields
[
i
];
}
result
+=
")"
;
return
result
;
}
}
// 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
)
{
string
result
;
if
(
*
description
==
'\0'
)
{
// When the user supplies an empty description, we calculate one
// from the matcher name.
result
=
ConvertIdentifierNameToWords
(
matcher_name
);
if
(
param_values
.
size
()
>=
1
)
result
+=
" "
+
JoinAsTuple
(
param_values
);
}
else
{
// The end position of the last interpolation.
const
char
*
last_interp_end
=
description
;
for
(
size_t
i
=
0
;
i
<
interp
.
size
();
i
++
)
{
result
.
append
(
last_interp_end
,
interp
[
i
].
start_pos
);
const
int
param_index
=
interp
[
i
].
param_index
;
if
(
param_index
==
kTupleInterpolation
)
{
result
+=
JoinAsTuple
(
param_values
);
}
else
if
(
param_index
==
kPercentInterpolation
)
{
result
+=
'%'
;
}
else
if
(
param_index
!=
kInvalidInterpolation
)
{
result
+=
param_values
[
param_index
];
}
last_interp_end
=
interp
[
i
].
end_pos
;
}
result
+=
last_interp_end
;
}
return
result
;
}
}
// namespace internal
}
// namespace testing
test/gmock-generated-matchers_test.cc
View file @
4a5330d3
...
...
@@ -390,17 +390,23 @@ TEST(MatcherMacroTest, Works) {
}
// Tests that the description string supplied to MATCHER() must be
//
empty
.
//
valid
.
MATCHER
(
HasBadDescription
,
"not empty?"
)
{
return
true
;
}
MATCHER
(
HasBadDescription
,
"Invalid%"
)
{
return
true
;
}
TEST
(
MatcherMacroTest
,
CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure
)
{
EXPECT_NONFATAL_FAILURE
(
HasBadDescription
(),
"The description string in a MATCHER*() macro "
"must be
\"\"
at this moment"
);
EXPECT_NONFATAL_FAILURE
(
HasBadDescription
(),
"Syntax error at index 7 in matcher description
\"
Invalid%
\"
: "
"use
\"
%%
\"
instead of
\"
%
\"
to print
\"
%
\"
."
);
}
MATCHER
(
HasGoodDescription
,
"good"
)
{
return
true
;
}
TEST
(
MatcherMacroTest
,
AcceptsValidDescription
)
{
const
Matcher
<
int
>
m
=
HasGoodDescription
();
EXPECT_EQ
(
"good"
,
Describe
(
m
));
}
// Tests that the body of MATCHER() can reference the type of the
...
...
@@ -452,17 +458,26 @@ TEST(MatcherPMacroTest, Works) {
}
// Tests that the description string supplied to MATCHER_P() must be
//
empty
.
//
valid
.
MATCHER_P
(
HasBadDescription1
,
n
,
"not
empty?
"
)
{
MATCHER_P
(
HasBadDescription1
,
n
,
"not
%(m)s good
"
)
{
return
arg
>
n
;
}
TEST
(
MatcherPMacroTest
,
CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure
)
{
EXPECT_NONFATAL_FAILURE
(
HasBadDescription1
(
2
),
"The description string in a MATCHER*() macro "
"must be
\"\"
at this moment"
);
EXPECT_NONFATAL_FAILURE
(
HasBadDescription1
(
2
),
"Syntax error at index 6 in matcher description
\"
not %(m)s good
\"
: "
"
\"
m
\"
is an invalid parameter name."
);
}
MATCHER_P
(
HasGoodDescription1
,
n
,
"good %(n)s"
)
{
return
true
;
}
TEST
(
MatcherPMacroTest
,
AcceptsValidDescription
)
{
const
Matcher
<
int
>
m
=
HasGoodDescription1
(
5
);
EXPECT_EQ
(
"good 5"
,
Describe
(
m
));
}
// Tests that the description is calculated correctly from the matcher name.
...
...
@@ -509,17 +524,29 @@ TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) {
// Tests that the description string supplied to MATCHER_Pn() must be
//
empty
.
//
valid
.
MATCHER_P2
(
HasBadDescription2
,
m
,
n
,
"not
empty?
"
)
{
MATCHER_P2
(
HasBadDescription2
,
m
,
n
,
"not
%(good
"
)
{
return
arg
>
m
+
n
;
}
TEST
(
MatcherPnMacroTest
,
CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure
)
{
EXPECT_NONFATAL_FAILURE
(
HasBadDescription2
(
3
,
4
),
"The description string in a MATCHER*() macro "
"must be
\"\"
at this moment"
);
EXPECT_NONFATAL_FAILURE
(
HasBadDescription2
(
3
,
4
),
"Syntax error at index 4 in matcher description
\"
not %(good
\"
: "
"an interpolation must end with
\"
)s
\"
, but
\"
%(good
\"
does not."
);
}
MATCHER_P2
(
HasComplexDescription
,
foo
,
bar
,
"is as complex as %(foo)s %(bar)s (i.e. %(*)s or %%%(foo)s!)"
)
{
return
true
;
}
TEST
(
MatcherPnMacroTest
,
AcceptsValidDescription
)
{
Matcher
<
int
>
m
=
HasComplexDescription
(
100
,
"ducks"
);
EXPECT_EQ
(
"is as complex as 100
\"
ducks
\"
(i.e. (100,
\"
ducks
\"
) or %100!)"
,
Describe
(
m
));
}
// Tests that the body of MATCHER_Pn() can reference the parameter
...
...
test/gmock-matchers_test.cc
View file @
4a5330d3
This diff is collapsed.
Click to expand it.
test/gmock-printers_test.cc
View file @
4a5330d3
...
...
@@ -47,6 +47,7 @@
#include <string>
#include <utility>
#include <vector>
#include <gmock/gmock-generated-matchers.h>
#include <gmock/gmock-matchers.h>
#include <gmock/internal/gmock-port.h>
#include <gtest/gtest.h>
...
...
@@ -151,8 +152,11 @@ using ::std::set;
using
::
std
::
tr1
::
make_tuple
;
using
::
std
::
tr1
::
tuple
;
using
::
std
::
vector
;
using
::
testing
::
ElementsAre
;
using
::
testing
::
StartsWith
;
using
::
testing
::
internal
::
UniversalPrint
;
using
::
testing
::
internal
::
Strings
;
using
::
testing
::
internal
::
UniversalTersePrint
;
using
::
testing
::
internal
::
UniversalTersePrintTupleFieldsToStrings
;
using
::
testing
::
internal
::
UniversalPrinter
;
using
::
testing
::
internal
::
string
;
...
...
@@ -981,28 +985,67 @@ TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
+
" "
+
Print
(
sizeof
(
p
))
+
"-byte object "
));
}
TEST
(
Print
As
StringTest
,
WorksForNonReference
)
{
EXPECT_EQ
(
"123"
,
UniversalPrinter
<
int
>::
Print
As
String
(
123
));
TEST
(
Print
To
StringTest
,
WorksForNonReference
)
{
EXPECT_EQ
(
"123"
,
UniversalPrinter
<
int
>::
Print
To
String
(
123
));
}
TEST
(
Print
As
StringTest
,
WorksForReference
)
{
TEST
(
Print
To
StringTest
,
WorksForReference
)
{
int
n
=
123
;
EXPECT_EQ
(
"@"
+
PrintPointer
(
&
n
)
+
" 123"
,
UniversalPrinter
<
const
int
&>::
Print
As
String
(
n
));
UniversalPrinter
<
const
int
&>::
Print
To
String
(
n
));
}
TEST
(
UniversalPrintTest
,
WorksForNonReference
)
{
TEST
(
Universal
Terse
PrintTest
,
WorksForNonReference
)
{
::
std
::
stringstream
ss
;
UniversalPrint
(
123
,
&
ss
);
Universal
Terse
Print
(
123
,
&
ss
);
EXPECT_EQ
(
"123"
,
ss
.
str
());
}
TEST
(
UniversalPrintTest
,
WorksForReference
)
{
TEST
(
Universal
Terse
PrintTest
,
WorksForReference
)
{
const
int
&
n
=
123
;
::
std
::
stringstream
ss
;
UniversalPrint
(
n
,
&
ss
);
Universal
Terse
Print
(
n
,
&
ss
);
EXPECT_EQ
(
"123"
,
ss
.
str
());
}
TEST
(
UniversalTersePrintTest
,
WorksForCString
)
{
const
char
*
s1
=
"abc"
;
::
std
::
stringstream
ss1
;
UniversalTersePrint
(
s1
,
&
ss1
);
EXPECT_EQ
(
"
\"
abc
\"
"
,
ss1
.
str
());
char
*
s2
=
const_cast
<
char
*>
(
s1
);
::
std
::
stringstream
ss2
;
UniversalTersePrint
(
s2
,
&
ss2
);
EXPECT_EQ
(
"
\"
abc
\"
"
,
ss2
.
str
());
const
char
*
s3
=
NULL
;
::
std
::
stringstream
ss3
;
UniversalTersePrint
(
s3
,
&
ss3
);
EXPECT_EQ
(
"NULL"
,
ss3
.
str
());
}
TEST
(
UniversalTersePrintTupleFieldsToStringsTest
,
PrintsEmptyTuple
)
{
EXPECT_THAT
(
UniversalTersePrintTupleFieldsToStrings
(
make_tuple
()),
ElementsAre
());
}
TEST
(
UniversalTersePrintTupleFieldsToStringsTest
,
PrintsOneTuple
)
{
EXPECT_THAT
(
UniversalTersePrintTupleFieldsToStrings
(
make_tuple
(
1
)),
ElementsAre
(
"1"
));
}
TEST
(
UniversalTersePrintTupleFieldsToStringsTest
,
PrintsTwoTuple
)
{
EXPECT_THAT
(
UniversalTersePrintTupleFieldsToStrings
(
make_tuple
(
1
,
'a'
)),
ElementsAre
(
"1"
,
"'a' (97)"
));
}
TEST
(
UniversalTersePrintTupleFieldsToStringsTest
,
PrintsTersely
)
{
const
int
n
=
1
;
EXPECT_THAT
(
UniversalTersePrintTupleFieldsToStrings
(
tuple
<
const
int
&
,
const
char
*>
(
n
,
"a"
)),
ElementsAre
(
"1"
,
"
\"
a
\"
"
));
}
}
// namespace gmock_printers_test
}
// namespace testing
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