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
b4140808
You need to sign in or sign up before continuing.
Commit
b4140808
authored
Jun 08, 2010
by
zhanyong.wan
Browse files
Replaces Python-style interpolation with arbitrary C++ string expression in MATCHER* descriptions.
parent
0a781df3
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
289 additions
and
713 deletions
+289
-713
include/gmock/gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+208
-189
include/gmock/gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+36
-28
include/gmock/gmock-matchers.h
include/gmock/gmock-matchers.h
+7
-35
src/gmock-matchers.cc
src/gmock-matchers.cc
+11
-100
test/gmock-generated-matchers_test.cc
test/gmock-generated-matchers_test.cc
+21
-76
test/gmock-matchers_test.cc
test/gmock-matchers_test.cc
+6
-285
No files found.
include/gmock/gmock-generated-matchers.h
View file @
b4140808
This diff is collapsed.
Click to expand it.
include/gmock/gmock-generated-matchers.h.pump
View file @
b4140808
...
...
@@ -402,25 +402,29 @@ $$ // show up in the generated code.
// Describing Parameterized 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]") {
// The last argument to MATCHER*() is a string-typed expression. The
// expression can reference all of the matcher's parameters and a
// special bool-typed variable named 'negation'. When 'negation' is
// false, the expression should evaluate to the matcher's description;
// otherwise it should evaluate to the description of the negation of
// the matcher. For example,
//
// using testing::PrintToString;
//
// MATCHER_P2(InClosedRange, low, hi,
// string(negation ? "is not" : "is") + " in range [" +
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
// return low <= arg && arg <= hi;
// }
// ...
// EXPECT_THAT(3, InClosedRange(4, 6));
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
//
// would generate
a
failure that contain
s
the
message
:
// would generate
two
failure
s
that contain the
text
:
//
// Expected: is in range [4, 6]
// ...
// Expected: is not in range [2, 4]
//
// If you specify "" as the description, the failure message will
// contain the sequence of words in the matcher name followed by the
...
...
@@ -429,10 +433,13 @@ $$ // show up in the generated code.
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
// ...
// EXPECT_THAT(3, InClosedRange(4, 6));
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
//
// would generate
a
failure that contain
s
the text:
// would generate
two
failure
s
that contain the text:
//
// Expected: in closed range (4, 6)
// ...
// Expected: not (in closed range (2, 4))
//
// Types of Matcher Parameters
// ===========================
...
...
@@ -529,11 +536,9 @@ $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
impl_ctor_param_list
=
[[
$
for
j
,
[[
p
$
j
##
_type
gmock_p
$
j
]]]]
$
var
impl_inits
=
[[
$
if
i
==
0
[[]]
$
else
[[
:
$
for
j
,
[[
p
$
j
(
gmock_p
$
j
)]]]]]]
$
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
]]]]
...
...
@@ -559,28 +564,31 @@ $var param_field_decls2 = [[$for j
virtual
bool
MatchAndExplain
(
\
arg_type
arg
,
::
testing
::
MatchResultListener
*
result_listener
)
const
;
\
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
);
\
*
gmock_os
<<
FormatDescription
(
false
);
\
}
\
virtual
void
DescribeNegationTo
(
::
std
::
ostream
*
gmock_os
)
const
{
\
*
gmock_os
<<
FormatDescription
(
true
);
\
}
\$
param_field_decls
const
::
testing
::
internal
::
Interpolations
gmock_interp_
;
\
private:
\
::
testing
::
internal
::
string
FormatDescription
(
bool
negation
)
const
{
\
const
::
testing
::
internal
::
string
gmock_description
=
(
description
);
\
if
(
!
gmock_description
.
empty
())
\
return
gmock_description
;
\
return
::
testing
::
internal
::
FormatMatcherDescription
(
\
negation
,
#
name
,
\
::
testing
::
internal
::
UniversalTersePrintTupleFieldsToStrings
(
\
::
std
::
tr1
::
tuple
<
$
for
j
,
[[
p
$
j
##
_type
]]
>
(
$
for
j
,
[[
p
$
j
]])));
\
}
\
GTEST_DISALLOW_ASSIGN_
(
gmock_Impl
);
\
};
\
template
<
typename
arg_type
>
\
operator
::
testing
::
Matcher
<
arg_type
>
()
const
{
\
return
::
testing
::
Matcher
<
arg_type
>
(
\
new
gmock_Impl
<
arg_type
>
(
$
params
_and_interp
));
\
new
gmock_Impl
<
arg_type
>
(
$
params
));
\
}
\
$
class_name
(
$
ctor_param_list
)
$
inits
{
\
const
char
*
gmock_param_names
[]
=
{
$
for
j
[[
#
p
$
j
,
]]
NULL
};
\
gmock_interp_
=
::
testing
::
internal
::
ValidateMatcherDescription
(
\
gmock_param_names
,
(
""
description
""
));
\
}
\$
param_field_decls2
private:
\
::
testing
::
internal
::
Interpolations
gmock_interp_
;
\
GTEST_DISALLOW_ASSIGN_
(
$
class_name
);
\
};
\$
template
inline
$
class_name
$
param_types
name
(
$
param_types_and_names
)
{
\
...
...
include/gmock/gmock-matchers.h
View file @
b4140808
...
...
@@ -2527,41 +2527,13 @@ class ElementsAreArrayMatcher {
GTEST_DISALLOW_ASSIGN_
(
ElementsAreArrayMatcher
);
};
// 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
);
// Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the
// negation of the matcher. 'param_values' contains a list of strings
// that are the print-out of the matcher's parameters.
string
FormatMatcherDescription
(
bool
negation
,
const
char
*
matcher_name
,
const
Strings
&
param_values
);
}
// namespace internal
...
...
src/gmock-matchers.cc
View file @
b4140808
...
...
@@ -65,74 +65,6 @@ Matcher<internal::string>::Matcher(const char* 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
;
}
// 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
)
{
...
...
@@ -152,38 +84,17 @@ string JoinAsTuple(const Strings& fields) {
}
}
// 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
);
// Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the
// negation of the matcher. 'param_values' contains a list of strings
// that are the print-out of the matcher's parameters.
string
FormatMatcherDescription
(
bool
negation
,
const
char
*
matcher_name
,
const
Strings
&
param_values
)
{
string
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
;
return
negation
?
"not ("
+
result
+
")"
:
result
;
}
}
// namespace internal
...
...
test/gmock-generated-matchers_test.cc
View file @
b4140808
...
...
@@ -72,6 +72,7 @@ using testing::MatchResultListener;
using
testing
::
Ne
;
using
testing
::
Not
;
using
testing
::
Pointee
;
using
testing
::
PrintToString
;
using
testing
::
Ref
;
using
testing
::
StaticAssertTypeEq
;
using
testing
::
StrEq
;
...
...
@@ -603,9 +604,8 @@ TEST(MatcherMacroTest, Works) {
EXPECT_EQ
(
""
,
Explain
(
m
,
7
));
}
// Tests explaining match result in a MATCHER* macro.
MATCHER
(
IsEven2
,
"is even"
)
{
// This also tests that the description string can reference 'negation'.
MATCHER
(
IsEven2
,
negation
?
"is odd"
:
"is even"
)
{
if
((
arg
%
2
)
==
0
)
{
// Verifies that we can stream to result_listener, a listener
// supplied by the MATCHER macro implicitly.
...
...
@@ -617,7 +617,11 @@ MATCHER(IsEven2, "is even") {
}
}
MATCHER_P2
(
EqSumOf
,
x
,
y
,
""
)
{
// This also tests that the description string can reference matcher
// parameters.
MATCHER_P2
(
EqSumOf
,
x
,
y
,
string
(
negation
?
"doesn't equal"
:
"equals"
)
+
" the sum of "
+
PrintToString
(
x
)
+
" and "
+
PrintToString
(
y
))
{
if
(
arg
==
(
x
+
y
))
{
*
result_listener
<<
"OK"
;
return
true
;
...
...
@@ -631,6 +635,19 @@ MATCHER_P2(EqSumOf, x, y, "") {
}
}
// Tests that the matcher description can reference 'negation' and the
// matcher parameters.
TEST
(
MatcherMacroTest
,
DescriptionCanReferenceNegationAndParameters
)
{
const
Matcher
<
int
>
m1
=
IsEven2
();
EXPECT_EQ
(
"is even"
,
Describe
(
m1
));
EXPECT_EQ
(
"is odd"
,
DescribeNegation
(
m1
));
const
Matcher
<
int
>
m2
=
EqSumOf
(
5
,
9
);
EXPECT_EQ
(
"equals the sum of 5 and 9"
,
Describe
(
m2
));
EXPECT_EQ
(
"doesn't equal the sum of 5 and 9"
,
DescribeNegation
(
m2
));
}
// Tests explaining match result in a MATCHER* macro.
TEST
(
MatcherMacroTest
,
CanExplainMatchResult
)
{
const
Matcher
<
int
>
m1
=
IsEven2
();
EXPECT_EQ
(
"OK"
,
Explain
(
m1
,
4
));
...
...
@@ -641,29 +658,6 @@ TEST(MatcherMacroTest, CanExplainMatchResult) {
EXPECT_EQ
(
"diff == -1"
,
Explain
(
m2
,
4
));
}
// Tests that the description string supplied to MATCHER() must be
// valid.
MATCHER
(
HasBadDescription
,
"Invalid%"
)
{
// Uses arg to suppress "unused parameter" warning.
return
arg
==
arg
;
}
TEST
(
MatcherMacroTest
,
CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure
)
{
EXPECT_NONFATAL_FAILURE
(
HasBadDescription
(),
"Syntax error at index 7 in matcher description
\"
Invalid%
\"
: "
"use
\"
%%
\"
instead of
\"
%
\"
to print
\"
%
\"
."
);
}
MATCHER
(
HasGoodDescription
,
"good"
)
{
return
arg
==
arg
;
}
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
// value being matched.
...
...
@@ -723,29 +717,6 @@ TEST(MatcherPMacroTest, Works) {
EXPECT_EQ
(
""
,
Explain
(
m
,
5
));
}
// Tests that the description string supplied to MATCHER_P() must be
// valid.
MATCHER_P
(
HasBadDescription1
,
n
,
"not %(m)s good"
)
{
return
arg
>
n
;
}
TEST
(
MatcherPMacroTest
,
CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure
)
{
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
arg
==
arg
;
}
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.
MATCHER_P
(
_is_Greater_Than32and_
,
n
,
""
)
{
return
arg
>
32
&&
arg
>
n
;
}
...
...
@@ -789,32 +760,6 @@ TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) {
}
// Tests that the description string supplied to MATCHER_Pn() must be
// valid.
MATCHER_P2
(
HasBadDescription2
,
m
,
n
,
"not %(good"
)
{
return
arg
>
m
+
n
;
}
TEST
(
MatcherPnMacroTest
,
CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure
)
{
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
arg
==
arg
;
}
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
// types.
...
...
test/gmock-matchers_test.cc
View file @
b4140808
...
...
@@ -52,11 +52,7 @@
namespace
testing
{
namespace
internal
{
string
FormatMatcherDescriptionSyntaxError
(
const
char
*
description
,
const
char
*
error_pos
);
int
GetParamIndex
(
const
char
*
param_names
[],
const
string
&
param_name
);
string
JoinAsTuple
(
const
Strings
&
fields
);
bool
SkipPrefix
(
const
char
*
prefix
,
const
char
**
pstr
);
}
// namespace internal
namespace
gmock_matchers_test
{
...
...
@@ -126,21 +122,13 @@ using testing::_;
using
testing
::
internal
::
DummyMatchResultListener
;
using
testing
::
internal
::
ExplainMatchFailureTupleTo
;
using
testing
::
internal
::
FloatingEqMatcher
;
using
testing
::
internal
::
FormatMatcherDescriptionSyntaxError
;
using
testing
::
internal
::
GetParamIndex
;
using
testing
::
internal
::
Interpolation
;
using
testing
::
internal
::
Interpolations
;
using
testing
::
internal
::
FormatMatcherDescription
;
using
testing
::
internal
::
JoinAsTuple
;
using
testing
::
internal
::
RE
;
using
testing
::
internal
::
SkipPrefix
;
using
testing
::
internal
::
StreamMatchResultListener
;
using
testing
::
internal
::
String
;
using
testing
::
internal
::
StringMatchResultListener
;
using
testing
::
internal
::
Strings
;
using
testing
::
internal
::
ValidateMatcherDescription
;
using
testing
::
internal
::
kInvalidInterpolation
;
using
testing
::
internal
::
kPercentInterpolation
;
using
testing
::
internal
::
kTupleInterpolation
;
using
testing
::
internal
::
linked_ptr
;
using
testing
::
internal
::
scoped_ptr
;
using
testing
::
internal
::
string
;
...
...
@@ -3643,176 +3631,6 @@ TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
EXPECT_THAT
(
a1
,
m
);
}
// Tests GetParamIndex().
TEST
(
GetParamIndexTest
,
WorksForEmptyParamList
)
{
const
char
*
params
[]
=
{
NULL
};
EXPECT_EQ
(
kTupleInterpolation
,
GetParamIndex
(
params
,
"*"
));
EXPECT_EQ
(
kInvalidInterpolation
,
GetParamIndex
(
params
,
"a"
));
}
TEST
(
GetParamIndexTest
,
RecognizesStar
)
{
const
char
*
params
[]
=
{
"a"
,
"b"
,
NULL
};
EXPECT_EQ
(
kTupleInterpolation
,
GetParamIndex
(
params
,
"*"
));
}
TEST
(
GetParamIndexTest
,
RecognizesKnownParam
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
NULL
};
EXPECT_EQ
(
0
,
GetParamIndex
(
params
,
"foo"
));
EXPECT_EQ
(
1
,
GetParamIndex
(
params
,
"bar"
));
}
TEST
(
GetParamIndexTest
,
RejectsUnknownParam
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
NULL
};
EXPECT_EQ
(
kInvalidInterpolation
,
GetParamIndex
(
params
,
"foobar"
));
}
// Tests SkipPrefix().
TEST
(
SkipPrefixTest
,
SkipsWhenPrefixMatches
)
{
const
char
*
const
str
=
"hello"
;
const
char
*
p
=
str
;
EXPECT_TRUE
(
SkipPrefix
(
""
,
&
p
));
EXPECT_EQ
(
str
,
p
);
p
=
str
;
EXPECT_TRUE
(
SkipPrefix
(
"hell"
,
&
p
));
EXPECT_EQ
(
str
+
4
,
p
);
}
TEST
(
SkipPrefixTest
,
DoesNotSkipWhenPrefixDoesNotMatch
)
{
const
char
*
const
str
=
"world"
;
const
char
*
p
=
str
;
EXPECT_FALSE
(
SkipPrefix
(
"W"
,
&
p
));
EXPECT_EQ
(
str
,
p
);
p
=
str
;
EXPECT_FALSE
(
SkipPrefix
(
"world!"
,
&
p
));
EXPECT_EQ
(
str
,
p
);
}
// Tests FormatMatcherDescriptionSyntaxError().
TEST
(
FormatMatcherDescriptionSyntaxErrorTest
,
FormatsCorrectly
)
{
const
char
*
const
description
=
"hello%world"
;
EXPECT_EQ
(
"Syntax error at index 5 in matcher description
\"
hello%world
\"
: "
,
FormatMatcherDescriptionSyntaxError
(
description
,
description
+
5
));
}
// Tests ValidateMatcherDescription().
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsEmptyDescription
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
NULL
};
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
""
),
ElementsAre
());
}
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsNonEmptyDescriptionWithNoInterpolation
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
NULL
};
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
"a simple description"
),
ElementsAre
());
}
// The MATCHER*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4100)
#endif
// We use MATCHER_P3() to define a matcher for testing
// ValidateMatcherDescription(); otherwise we'll end up with much
// plumbing code. This is not circular as
// ValidateMatcherDescription() doesn't affect whether the matcher
// matches a value or not.
MATCHER_P3
(
EqInterpolation
,
start
,
end
,
index
,
"equals Interpolation%(*)s"
)
{
return
arg
.
start_pos
==
start
&&
arg
.
end_pos
==
end
&&
arg
.
param_index
==
index
;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsPercentInterpolation
)
{
const
char
*
params
[]
=
{
"foo"
,
NULL
};
const
char
*
const
desc
=
"one %%"
;
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
desc
),
ElementsAre
(
EqInterpolation
(
desc
+
4
,
desc
+
6
,
kPercentInterpolation
)));
}
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsTupleInterpolation
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
"baz"
,
NULL
};
const
char
*
const
desc
=
"%(*)s after"
;
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
desc
),
ElementsAre
(
EqInterpolation
(
desc
,
desc
+
5
,
kTupleInterpolation
)));
}
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsParamInterpolation
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
"baz"
,
NULL
};
const
char
*
const
desc
=
"a %(bar)s."
;
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
desc
),
ElementsAre
(
EqInterpolation
(
desc
+
2
,
desc
+
9
,
1
)));
}
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsMultiplenterpolations
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
"baz"
,
NULL
};
const
char
*
const
desc
=
"%(baz)s %(foo)s %(bar)s"
;
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
desc
),
ElementsAre
(
EqInterpolation
(
desc
,
desc
+
7
,
2
),
EqInterpolation
(
desc
+
8
,
desc
+
15
,
0
),
EqInterpolation
(
desc
+
16
,
desc
+
23
,
1
)));
}
TEST
(
ValidateMatcherDescriptionTest
,
AcceptsRepeatedParams
)
{
const
char
*
params
[]
=
{
"foo"
,
"bar"
,
NULL
};
const
char
*
const
desc
=
"%(foo)s and %(foo)s"
;
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
desc
),
ElementsAre
(
EqInterpolation
(
desc
,
desc
+
7
,
0
),
EqInterpolation
(
desc
+
12
,
desc
+
19
,
0
)));
}
TEST
(
ValidateMatcherDescriptionTest
,
RejectsUnknownParam
)
{
const
char
*
params
[]
=
{
"a"
,
"bar"
,
NULL
};
EXPECT_NONFATAL_FAILURE
({
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
"%(foo)s"
),
ElementsAre
());
},
"Syntax error at index 2 in matcher description
\"
%(foo)s
\"
: "
"
\"
foo
\"
is an invalid parameter name."
);
}
TEST
(
ValidateMatcherDescriptionTest
,
RejectsUnfinishedParam
)
{
const
char
*
params
[]
=
{
"a"
,
"bar"
,
NULL
};
EXPECT_NONFATAL_FAILURE
({
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
"%(foo)"
),
ElementsAre
());
},
"Syntax error at index 0 in matcher description
\"
%(foo)
\"
: "
"an interpolation must end with
\"
)s
\"
, but
\"
%(foo)
\"
does not."
);
EXPECT_NONFATAL_FAILURE
({
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
"x%(a"
),
ElementsAre
());
},
"Syntax error at index 1 in matcher description
\"
x%(a
\"
: "
"an interpolation must end with
\"
)s
\"
, but
\"
%(a
\"
does not."
);
}
TEST
(
ValidateMatcherDescriptionTest
,
RejectsSinglePercent
)
{
const
char
*
params
[]
=
{
"a"
,
NULL
};
EXPECT_NONFATAL_FAILURE
({
EXPECT_THAT
(
ValidateMatcherDescription
(
params
,
"a %."
),
ElementsAre
());
},
"Syntax error at index 2 in matcher description
\"
a %.
\"
: "
"use
\"
%%
\"
instead of
\"
%
\"
to print
\"
%
\"
."
);
}
// Tests JoinAsTuple().
TEST
(
JoinAsTupleTest
,
JoinsEmptyTuple
)
{
...
...
@@ -3839,118 +3657,21 @@ TEST(JoinAsTupleTest, JoinsTenTuple) {
TEST
(
FormatMatcherDescriptionTest
,
WorksForEmptyDescription
)
{
EXPECT_EQ
(
"is even"
,
FormatMatcherDescription
(
"IsEven"
,
""
,
Interpolations
(),
Strings
()));
FormatMatcherDescription
(
false
,
"IsEven"
,
Strings
()));
EXPECT_EQ
(
"not (is even)"
,
FormatMatcherDescription
(
true
,
"IsEven"
,
Strings
()));
const
char
*
params
[]
=
{
"5"
};
EXPECT_EQ
(
"equals 5"
,
FormatMatcherDescription
(
"Equals"
,
""
,
Interpolations
(),
FormatMatcherDescription
(
false
,
"Equals"
,
Strings
(
params
,
params
+
1
)));
const
char
*
params2
[]
=
{
"5"
,
"8"
};
EXPECT_EQ
(
"is in range (5, 8)"
,
FormatMatcherDescription
(
"IsInRange"
,
""
,
Interpolations
(),
FormatMatcherDescription
(
false
,
"IsInRange"
,
Strings
(
params2
,
params2
+
2
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksForDescriptionWithNoInterpolation
)
{
EXPECT_EQ
(
"is positive"
,
FormatMatcherDescription
(
"Gt0"
,
"is positive"
,
Interpolations
(),
Strings
()));
const
char
*
params
[]
=
{
"5"
,
"6"
};
EXPECT_EQ
(
"is negative"
,
FormatMatcherDescription
(
"Lt0"
,
"is negative"
,
Interpolations
(),
Strings
(
params
,
params
+
2
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksWhenDescriptionStartsWithInterpolation
)
{
const
char
*
params
[]
=
{
"5"
};
const
char
*
const
desc
=
"%(num)s times bigger"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
,
desc
+
7
,
0
)
};
EXPECT_EQ
(
"5 times bigger"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
1
),
Strings
(
params
,
params
+
1
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksWhenDescriptionEndsWithInterpolation
)
{
const
char
*
params
[]
=
{
"5"
,
"6"
};
const
char
*
const
desc
=
"is bigger than %(y)s"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
+
15
,
desc
+
20
,
1
)
};
EXPECT_EQ
(
"is bigger than 6"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
1
),
Strings
(
params
,
params
+
2
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksWhenDescriptionStartsAndEndsWithInterpolation
)
{
const
char
*
params
[]
=
{
"5"
,
"6"
};
const
char
*
const
desc
=
"%(x)s <= arg <= %(y)s"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
,
desc
+
5
,
0
),
Interpolation
(
desc
+
16
,
desc
+
21
,
1
)
};
EXPECT_EQ
(
"5 <= arg <= 6"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
2
),
Strings
(
params
,
params
+
2
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksWhenDescriptionDoesNotStartOrEndWithInterpolation
)
{
const
char
*
params
[]
=
{
"5.2"
};
const
char
*
const
desc
=
"has %(x)s cents"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
+
4
,
desc
+
9
,
0
)
};
EXPECT_EQ
(
"has 5.2 cents"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
1
),
Strings
(
params
,
params
+
1
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksWhenDescriptionContainsMultipleInterpolations
)
{
const
char
*
params
[]
=
{
"5"
,
"6"
};
const
char
*
const
desc
=
"in %(*)s or [%(x)s, %(y)s]"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
+
3
,
desc
+
8
,
kTupleInterpolation
),
Interpolation
(
desc
+
13
,
desc
+
18
,
0
),
Interpolation
(
desc
+
20
,
desc
+
25
,
1
)
};
EXPECT_EQ
(
"in (5, 6) or [5, 6]"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
3
),
Strings
(
params
,
params
+
2
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksWhenDescriptionContainsRepeatedParams
)
{
const
char
*
params
[]
=
{
"9"
};
const
char
*
const
desc
=
"in [-%(x)s, %(x)s]"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
+
5
,
desc
+
10
,
0
),
Interpolation
(
desc
+
12
,
desc
+
17
,
0
)
};
EXPECT_EQ
(
"in [-9, 9]"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
2
),
Strings
(
params
,
params
+
1
)));
}
TEST
(
FormatMatcherDescriptionTest
,
WorksForDescriptionWithInvalidInterpolation
)
{
const
char
*
params
[]
=
{
"9"
};
const
char
*
const
desc
=
"> %(x)s %(x)"
;
const
Interpolation
interp
[]
=
{
Interpolation
(
desc
+
2
,
desc
+
7
,
0
)
};
EXPECT_EQ
(
"> 9 %(x)"
,
FormatMatcherDescription
(
"Foo"
,
desc
,
Interpolations
(
interp
,
interp
+
1
),
Strings
(
params
,
params
+
1
)));
}
// Tests PolymorphicMatcher::mutable_impl().
TEST
(
PolymorphicMatcherTest
,
CanAccessMutableImpl
)
{
PolymorphicMatcher
<
DivisibleByImpl
>
m
(
DivisibleByImpl
(
42
));
...
...
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