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
ce198ff8
Commit
ce198ff8
authored
Feb 12, 2009
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implements the MATCHER* macros.
parent
2f0849fe
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
312 additions
and
1 deletion
+312
-1
gmock-generated-matchers.h
include/gmock/gmock-generated-matchers.h
+0
-0
gmock-generated-matchers.h.pump
include/gmock/gmock-generated-matchers.h.pump
+210
-0
gmock-printers.h
include/gmock/gmock-printers.h
+14
-1
gmock-internal-utils.h
include/gmock/internal/gmock-internal-utils.h
+6
-0
gmock-internal-utils.cc
src/gmock-internal-utils.cc
+24
-0
gmock-generated-matchers_test.cc
test/gmock-generated-matchers_test.cc
+0
-0
gmock-internal-utils_test.cc
test/gmock-internal-utils_test.cc
+34
-0
gmock-printers_test.cc
test/gmock-printers_test.cc
+24
-0
No files found.
include/gmock/gmock-generated-matchers.h
View file @
ce198ff8
This diff is collapsed.
Click to expand it.
include/gmock/gmock-generated-matchers.h.pump
View file @
ce198ff8
...
@@ -47,6 +47,14 @@ $var n = 10 $$ The maximum arity we support.
...
@@ -47,6 +47,14 @@ $var n = 10 $$ The maximum arity we support.
namespace
testing
{
namespace
testing
{
namespace
internal
{
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().
// Implements ElementsAre() and ElementsAreArray().
template
<
typename
Container
>
template
<
typename
Container
>
class
ElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
{
class
ElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
{
...
@@ -300,4 +308,206 @@ ElementsAreArray(const T (&array)[N]) {
...
@@ -300,4 +308,206 @@ ElementsAreArray(const T (&array)[N]) {
}
// namespace testing
}
// namespace testing
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax:
//
// MATCHER(name, description_string) { statements; }
//
// 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:
//
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
//
// allows you to write
//
// // Expects mock_foo.Bar(n) to be called where n is even.
// EXPECT_CALL(mock_foo, Bar(IsEven()));
//
// or,
//
// // Verifies that the value of some_expression is even.
// EXPECT_THAT(some_expression, IsEven());
//
// If the above assertion fails, it will print something like:
//
// Value of: some_expression
// Expected: is even
// Actual: 7
//
// where the description "is even" is automatically calculated from the
// matcher name IsEven.
//
// Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about
// declaring it (nor can you). This allows the matcher to be
// polymorphic. For example, IsEven() can be used to match any type
// where the value of "(arg % 2) == 0" can be implicitly converted to
// a bool. In the "Bar(IsEven())" example above, if method Bar()
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on.
//
// Sometimes you'll want to parameterize the matcher. For that you
// can use another macro:
//
// MATCHER_P(name, param_name, description_string) { statements; }
//
// For example:
//
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
//
// will allow you to write:
//
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
//
// which may lead to this message (assuming n is 10):
//
// Value of: Blah("a")
// Expected: has absolute value 10
// Actual: -9
//
// Note that both the matcher description and its parameter are
// printed, making the message human-friendly.
//
// In the matcher definition body, you can write 'foo_type' to
// reference the type of a parameter named 'foo'. For example, in the
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
// 'value_type' to refer to the type of 'value'.
//
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
// support multi-parameter matchers.
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
//
// as shorthand for
//
// template <typename p1_type, ..., typename pk_type>
// FooMatcherPk<p1_type, ..., pk_type>
// Foo(p1_type p1, ..., pk_type pk) { ... }
//
// When you write Foo(v1, ..., vk), the compiler infers the types of
// the parameters v1, ..., and vk for you. If you are not happy with
// the result of the type inference, you can specify the types by
// explicitly instantiating the template, as in Foo<long, bool>(5,
// false). As said earlier, you don't get to (or need to) specify
// 'arg_type' as that's determined by the context in which the matcher
// is used. You can assign the result of expression Foo(p1, ..., pk)
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
// can be useful when composing matchers.
//
// While you can instantiate a matcher template with reference types,
// passing the parameters by pointer usually makes your code more
// readable. If, however, you still want to pass a parameter by
// reference, be aware that in the failure message generated by the
// matcher you will see the value of the referenced object but not its
// address.
//
// You can overload matchers with different numbers of parameters:
//
// MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... }
//
// While it's tempting to always use the MATCHER* macros when defining
// a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher() instead,
// especially if you need to use the matcher a lot. While these
// approaches require more work, they give you more control on the
// types of the value being matched and the matcher parameters, which
// in general leads to better compiler error messages that pay off in
// the long run. They also allow overloading matchers based on
// parameter types (as opposed to just based on the number of
// parameters).
//
// CAVEAT:
//
// MATCHER*() can only be used in a namespace scope. The reason is
// that C++ doesn't yet allow function-local types to be used to
// instantiate templates. The up-coming C++0x standard will fix this.
// Once that's done, we'll consider supporting using MATCHER*() inside
// a function.
//
// MORE INFORMATION:
//
// To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook.
$
range
i
0.
.
n
$
for
i
[[
$
var
macro_name
=
[[
$
if
i
==
0
[[
MATCHER
]]
$
elif
i
==
1
[[
MATCHER_P
]]
$
else
[[
MATCHER_P
$
i
]]]]
$
var
class_name
=
[[
name
##
Matcher
[[
$
if
i
==
0
[[]]
$
elif
i
==
1
[[
P
]]
$
else
[[
P
$
i
]]]]]]
$
range
j
0.
.
i
-
1
$
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
inits
=
[[
$
if
i
==
0
[[]]
$
else
[[
:
$
for
j
,
[[
p
$
j
(
gmock_p
$
j
)]]]]]]
$
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
]]]]
$
var
param_field_decls
=
[[
$
for
j
[[
p
$
j
##
_type
p
$
j
;
\
]]]]
$
var
param_field_decls2
=
[[
$
for
j
[[
p
$
j
##
_type
p
$
j
;
\
]]]]
#define $macro_name(name$for j [[, p$j]], description)\$template
class
$
class_name
{
\
public
:
\
template
<
typename
arg_type
>
\
class
gmock_Impl
:
public
::
testing
::
MatcherInterface
<
arg_type
>
{
\
public
:
\
[[
$
if
i
==
1
[[
explicit
]]]]
gmock_Impl
(
$
ctor_param_list
)
$
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
<<
")"
;
\
]]]]
}
\$
param_field_decls
};
\
template
<
typename
arg_type
>
\
operator
::
testing
::
Matcher
<
arg_type
>
()
const
{
\
return
::
testing
::
Matcher
<
arg_type
>
(
new
gmock_Impl
<
arg_type
>
(
$
params
));
\
}
\
$
class_name
(
$
ctor_param_list
)
$
inits
{
\
::
testing
::
internal
::
ValidateMatcherDescription
(
description
);
\
}
\$
param_field_decls2
};
\$
template
inline
$
class_name
$
param_types
name
(
$
param_types_and_names
)
{
\
return
$
class_name
$
param_types
(
$
params
);
\
}
\$
template
template
<
typename
arg_type
>
\
bool
$
class_name
$
param_types
::
\
gmock_Impl
<
arg_type
>::
Matches
(
arg_type
arg
)
const
]]
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
include/gmock/gmock-printers.h
View file @
ce198ff8
...
@@ -44,9 +44,12 @@
...
@@ -44,9 +44,12 @@
// When T is a reference type, the address of the value is also
// When T is a reference type, the address of the value is also
// printed.
// printed.
//
//
// We also provide
a convenient wrapper
// We also provide
some convenient wrappers:
//
//
// // Prints to a string.
// string ::testing::internal::UniversalPrinter<T>::PrintAsString(value);
// string ::testing::internal::UniversalPrinter<T>::PrintAsString(value);
// // Prints a value using its inferred type.
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
...
@@ -585,6 +588,16 @@ class UniversalPrinter<T&> {
...
@@ -585,6 +588,16 @@ class UniversalPrinter<T&> {
#endif // _MSC_VER
#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.
template
<
typename
T
>
void
UniversalPrint
(
const
T
&
value
,
::
std
::
ostream
*
os
)
{
UniversalPrinter
<
T
>::
Print
(
value
,
os
);
}
}
// namespace internal
}
// namespace internal
}
// namespace testing
}
// namespace testing
...
...
include/gmock/internal/gmock-internal-utils.h
View file @
ce198ff8
...
@@ -63,6 +63,12 @@ namespace proto2 { class Message; }
...
@@ -63,6 +63,12 @@ namespace proto2 { class Message; }
namespace
testing
{
namespace
testing
{
namespace
internal
{
namespace
internal
{
// Converts an identifier name to a space-separated list of lower-case
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word. For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123".
string
ConvertIdentifierNameToWords
(
const
char
*
id_name
);
// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
// compiler error iff T1 and T2 are different types.
// compiler error iff T1 and T2 are different types.
template
<
typename
T1
,
typename
T2
>
template
<
typename
T1
,
typename
T2
>
...
...
src/gmock-internal-utils.cc
View file @
ce198ff8
...
@@ -37,6 +37,7 @@
...
@@ -37,6 +37,7 @@
#include <gmock/internal/gmock-internal-utils.h>
#include <gmock/internal/gmock-internal-utils.h>
#include <ctype.h>
#include <ostream> // NOLINT
#include <ostream> // NOLINT
#include <string>
#include <string>
#include <gmock/gmock.h>
#include <gmock/gmock.h>
...
@@ -46,6 +47,29 @@
...
@@ -46,6 +47,29 @@
namespace
testing
{
namespace
testing
{
namespace
internal
{
namespace
internal
{
// Converts an identifier name to a space-separated list of lower-case
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word. For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123".
string
ConvertIdentifierNameToWords
(
const
char
*
id_name
)
{
string
result
;
char
prev_char
=
'\0'
;
for
(
const
char
*
p
=
id_name
;
*
p
!=
'\0'
;
prev_char
=
*
(
p
++
))
{
// We don't care about the current locale as the input is
// guaranteed to be a valid C++ identifier name.
const
bool
starts_new_word
=
isupper
(
*
p
)
||
(
!
isalpha
(
prev_char
)
&&
islower
(
*
p
))
||
(
!
isdigit
(
prev_char
)
&&
isdigit
(
*
p
));
if
(
isalnum
(
*
p
))
{
if
(
starts_new_word
&&
result
!=
""
)
result
+=
' '
;
result
+=
tolower
(
*
p
);
}
}
return
result
;
}
// This class reports Google Mock failures as Google Test failures. A
// This class reports Google Mock failures as Google Test failures. A
// user can define another class in a similar fashion if he intends to
// user can define another class in a similar fashion if he intends to
// use Google Mock with a testing framework other than Google Test.
// use Google Mock with a testing framework other than Google Test.
...
...
test/gmock-generated-matchers_test.cc
View file @
ce198ff8
This diff is collapsed.
Click to expand it.
test/gmock-internal-utils_test.cc
View file @
ce198ff8
...
@@ -50,6 +50,40 @@ namespace {
...
@@ -50,6 +50,40 @@ namespace {
using
::
std
::
tr1
::
tuple
;
using
::
std
::
tr1
::
tuple
;
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameContainsNoWord
)
{
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
""
));
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
"_"
));
EXPECT_EQ
(
""
,
ConvertIdentifierNameToWords
(
"__"
));
}
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameContainsDigits
)
{
EXPECT_EQ
(
"1"
,
ConvertIdentifierNameToWords
(
"_1"
));
EXPECT_EQ
(
"2"
,
ConvertIdentifierNameToWords
(
"2_"
));
EXPECT_EQ
(
"34"
,
ConvertIdentifierNameToWords
(
"_34_"
));
EXPECT_EQ
(
"34 56"
,
ConvertIdentifierNameToWords
(
"_34_56"
));
}
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameContainsCamelCaseWords
)
{
EXPECT_EQ
(
"a big word"
,
ConvertIdentifierNameToWords
(
"ABigWord"
));
EXPECT_EQ
(
"foo bar"
,
ConvertIdentifierNameToWords
(
"FooBar"
));
EXPECT_EQ
(
"foo"
,
ConvertIdentifierNameToWords
(
"Foo_"
));
EXPECT_EQ
(
"foo bar"
,
ConvertIdentifierNameToWords
(
"_Foo_Bar_"
));
EXPECT_EQ
(
"foo and bar"
,
ConvertIdentifierNameToWords
(
"_Foo__And_Bar"
));
}
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameContains_SeparatedWords
)
{
EXPECT_EQ
(
"foo bar"
,
ConvertIdentifierNameToWords
(
"foo_bar"
));
EXPECT_EQ
(
"foo"
,
ConvertIdentifierNameToWords
(
"_foo_"
));
EXPECT_EQ
(
"foo bar"
,
ConvertIdentifierNameToWords
(
"_foo_bar_"
));
EXPECT_EQ
(
"foo and bar"
,
ConvertIdentifierNameToWords
(
"_foo__and_bar"
));
}
TEST
(
ConvertIdentifierNameToWordsTest
,
WorksWhenNameIsMixture
)
{
EXPECT_EQ
(
"foo bar 123"
,
ConvertIdentifierNameToWords
(
"Foo_bar123"
));
EXPECT_EQ
(
"chapter 11 section 1"
,
ConvertIdentifierNameToWords
(
"_Chapter11Section_1_"
));
}
// Tests that CompileAssertTypesEqual compiles when the type arguments are
// Tests that CompileAssertTypesEqual compiles when the type arguments are
// equal.
// equal.
TEST
(
CompileAssertTypesEqual
,
CompilesWhenTypesAreEqual
)
{
TEST
(
CompileAssertTypesEqual
,
CompilesWhenTypesAreEqual
)
{
...
...
test/gmock-printers_test.cc
View file @
ce198ff8
...
@@ -152,6 +152,7 @@ using ::std::tr1::make_tuple;
...
@@ -152,6 +152,7 @@ using ::std::tr1::make_tuple;
using
::
std
::
tr1
::
tuple
;
using
::
std
::
tr1
::
tuple
;
using
::
std
::
vector
;
using
::
std
::
vector
;
using
::
testing
::
StartsWith
;
using
::
testing
::
StartsWith
;
using
::
testing
::
internal
::
UniversalPrint
;
using
::
testing
::
internal
::
UniversalPrinter
;
using
::
testing
::
internal
::
UniversalPrinter
;
using
::
testing
::
internal
::
string
;
using
::
testing
::
internal
::
string
;
...
@@ -980,5 +981,28 @@ TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
...
@@ -980,5 +981,28 @@ TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
+
" "
+
Print
(
sizeof
(
p
))
+
"-byte object "
));
+
" "
+
Print
(
sizeof
(
p
))
+
"-byte object "
));
}
}
TEST
(
PrintAsStringTest
,
WorksForNonReference
)
{
EXPECT_EQ
(
"123"
,
UniversalPrinter
<
int
>::
PrintAsString
(
123
));
}
TEST
(
PrintAsStringTest
,
WorksForReference
)
{
int
n
=
123
;
EXPECT_EQ
(
"@"
+
PrintPointer
(
&
n
)
+
" 123"
,
UniversalPrinter
<
const
int
&>::
PrintAsString
(
n
));
}
TEST
(
UniversalPrintTest
,
WorksForNonReference
)
{
::
std
::
stringstream
ss
;
UniversalPrint
(
123
,
&
ss
);
EXPECT_EQ
(
"123"
,
ss
.
str
());
}
TEST
(
UniversalPrintTest
,
WorksForReference
)
{
const
int
&
n
=
123
;
::
std
::
stringstream
ss
;
UniversalPrint
(
n
,
&
ss
);
EXPECT_EQ
(
"123"
,
ss
.
str
());
}
}
// namespace gmock_printers_test
}
// namespace gmock_printers_test
}
// namespace testing
}
// 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