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
360f5f70
Commit
360f5f70
authored
Feb 10, 2020
by
Abseil Team
Committed by
Mark Barolak
Feb 11, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Googletest export
Fix gmock_gen to use MOCK_METHOD instead of old style macros. PiperOrigin-RevId: 294332975
parent
139fa202
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
371 additions
and
406 deletions
+371
-406
gmock_class.py
googlemock/scripts/generator/cpp/gmock_class.py
+164
-184
gmock_class_test.py
googlemock/scripts/generator/cpp/gmock_class_test.py
+207
-222
No files found.
googlemock/scripts/generator/cpp/gmock_class.py
View file @
360f5f70
...
@@ -35,11 +35,11 @@ from cpp import utils
...
@@ -35,11 +35,11 @@ from cpp import utils
# Preserve compatibility with Python 2.3.
# Preserve compatibility with Python 2.3.
try
:
try
:
_dummy
=
set
_dummy
=
set
except
NameError
:
except
NameError
:
import
sets
import
sets
set
=
sets
.
Set
set
=
sets
.
Set
_VERSION
=
(
1
,
0
,
1
)
# The version of this script.
_VERSION
=
(
1
,
0
,
1
)
# The version of this script.
# How many spaces to indent. Can set me with the INDENT environment variable.
# How many spaces to indent. Can set me with the INDENT environment variable.
...
@@ -47,202 +47,182 @@ _INDENT = 2
...
@@ -47,202 +47,182 @@ _INDENT = 2
def
_RenderType
(
ast_type
):
def
_RenderType
(
ast_type
):
"""Renders the potentially recursively templated type into a string.
"""Renders the potentially recursively templated type into a string.
Args:
Args:
ast_type: The AST of the type.
ast_type: The AST of the type.
Returns:
Returns:
Rendered string and a boolean to indicate whether we have multiple args
Rendered string of the type
(which is not handled correctly).
"""
"""
has_multiarg_error
=
False
# Add modifiers like 'const'.
# Add modifiers like 'const'.
modifiers
=
''
modifiers
=
''
if
ast_type
.
modifiers
:
if
ast_type
.
modifiers
:
modifiers
=
' '
.
join
(
ast_type
.
modifiers
)
+
' '
modifiers
=
' '
.
join
(
ast_type
.
modifiers
)
+
' '
return_type
=
modifiers
+
ast_type
.
name
return_type
=
modifiers
+
ast_type
.
name
if
ast_type
.
templated_types
:
if
ast_type
.
templated_types
:
# Collect template args.
# Collect template args.
template_args
=
[]
template_args
=
[]
for
arg
in
ast_type
.
templated_types
:
for
arg
in
ast_type
.
templated_types
:
rendered_arg
=
_RenderType
(
arg
)
rendered_arg
,
e
=
_RenderType
(
arg
)
template_args
.
append
(
rendered_arg
)
if
e
:
has_multiarg_error
=
True
return_type
+=
'<'
+
', '
.
join
(
template_args
)
+
'>'
template_args
.
append
(
rendered_arg
)
if
ast_type
.
pointer
:
return_type
+=
'<'
+
', '
.
join
(
template_args
)
+
'>'
return_type
+=
'*'
# We are actually not handling multi-template-args correctly. So mark it.
if
ast_type
.
reference
:
if
len
(
template_args
)
>
1
:
return_type
+=
'&'
has_multiarg_error
=
True
return
return_type
if
ast_type
.
pointer
:
return_type
+=
'*'
if
ast_type
.
reference
:
return_type
+=
'&'
return
return_type
,
has_multiarg_error
def
_GetNumParameters
(
parameters
,
source
):
num_parameters
=
len
(
parameters
)
if
num_parameters
==
1
:
first_param
=
parameters
[
0
]
if
source
[
first_param
.
start
:
first_param
.
end
]
.
strip
()
==
'void'
:
# We must treat T(void) as a function with no parameters.
return
0
return
num_parameters
def
_GenerateMethods
(
output_lines
,
source
,
class_node
):
def
_GenerateMethods
(
output_lines
,
source
,
class_node
):
function_type
=
(
ast
.
FUNCTION_VIRTUAL
|
ast
.
FUNCTION_PURE_VIRTUAL
|
function_type
=
(
ast
.
FUNCTION_OVERRIDE
)
ast
.
FUNCTION_VIRTUAL
|
ast
.
FUNCTION_PURE_VIRTUAL
|
ast
.
FUNCTION_OVERRIDE
)
ctor_or_dtor
=
ast
.
FUNCTION_CTOR
|
ast
.
FUNCTION_DTOR
ctor_or_dtor
=
ast
.
FUNCTION_CTOR
|
ast
.
FUNCTION_DTOR
indent
=
' '
*
_INDENT
indent
=
' '
*
_INDENT
for
node
in
class_node
.
body
:
for
node
in
class_node
.
body
:
# We only care about virtual functions.
# We only care about virtual functions.
if
(
isinstance
(
node
,
ast
.
Function
)
and
if
(
isinstance
(
node
,
ast
.
Function
)
and
node
.
modifiers
&
function_type
and
node
.
modifiers
&
function_type
and
not
node
.
modifiers
&
ctor_or_dtor
):
not
node
.
modifiers
&
ctor_or_dtor
):
# Pick out all the elements we need from the original function.
# Pick out all the elements we need from the original function.
modifiers
=
'override'
const
=
''
if
node
.
modifiers
&
ast
.
FUNCTION_CONST
:
if
node
.
modifiers
&
ast
.
FUNCTION_CONST
:
modifiers
=
'const, '
+
modifiers
const
=
'CONST_'
num_parameters
=
_GetNumParameters
(
node
.
parameters
,
source
)
return_type
=
'void'
return_type
=
'void'
if
node
.
return_type
:
if
node
.
return_type
:
return_type
=
_RenderType
(
node
.
return_type
)
return_type
,
has_multiarg_error
=
_RenderType
(
node
.
return_type
)
# commas mess with macros, so nest it in parens if it has one
if
has_multiarg_error
:
if
','
in
return_type
:
for
line
in
[
return_type
=
'('
+
return_type
+
')'
'// The following line won
\'
t really compile, as the return'
,
'// type has multiple template arguments. To fix it, use a'
,
args
=
''
'// typedef for the return type.'
]:
if
node
.
parameters
:
output_lines
.
append
(
indent
+
line
)
# Get the full text of the parameters from the start
tmpl
=
''
# of the first parameter to the end of the last parameter.
if
class_node
.
templated_types
:
start
=
node
.
parameters
[
0
]
.
start
tmpl
=
'_T'
end
=
node
.
parameters
[
-
1
]
.
end
mock_method_macro
=
'MOCK_
%
sMETHOD
%
d
%
s'
%
(
const
,
num_parameters
,
tmpl
)
# Remove // comments.
args_strings
=
re
.
sub
(
r'//.*'
,
''
,
source
[
start
:
end
])
args
=
''
# Remove /* comments */.
if
node
.
parameters
:
args_strings
=
re
.
sub
(
r'/\*.*\*/'
,
''
,
args_strings
)
# Get the full text of the parameters from the start
# Remove default arguments.
# of the first parameter to the end of the last parameter.
args_strings
=
re
.
sub
(
r'=.*,'
,
','
,
args_strings
)
start
=
node
.
parameters
[
0
]
.
start
args_strings
=
re
.
sub
(
r'=.*'
,
''
,
args_strings
)
end
=
node
.
parameters
[
-
1
]
.
end
# Condense multiple spaces and eliminate newlines putting the
# Remove // comments.
# parameters together on a single line. Ensure there is a
args_strings
=
re
.
sub
(
r'//.*'
,
''
,
source
[
start
:
end
])
# space in an argument which is split by a newline without
# Remove /* comments */.
# intervening whitespace, e.g.: int\nBar
args_strings
=
re
.
sub
(
r'/\*.*\*/'
,
''
,
args_strings
)
args_strings
=
re
.
sub
(
' +'
,
' '
,
args_strings
.
replace
(
'
\n
'
,
' '
))
# Remove default arguments.
# Remove spaces from the begining, end, and before commas
args_strings
=
re
.
sub
(
r'=.*,'
,
','
,
args_strings
)
args
=
re
.
sub
(
' ,'
,
','
,
args_strings
)
.
strip
()
args_strings
=
re
.
sub
(
r'=.*'
,
''
,
args_strings
)
# Condense multiple spaces and eliminate newlines putting the
# Create the mock method definition.
# parameters together on a single line. Ensure there is a
output_lines
.
extend
([
# space in an argument which is split by a newline without
'
%
sMOCK_METHOD(
%
s,
%
s, (
%
s), (
%
s));'
%
# intervening whitespace, e.g.: int\nBar
(
indent
,
return_type
,
node
.
name
,
args
,
modifiers
)
args
=
re
.
sub
(
' +'
,
' '
,
args_strings
.
replace
(
'
\n
'
,
' '
))
])
# Create the mock method definition.
output_lines
.
extend
([
'
%
s
%
s(
%
s,'
%
(
indent
,
mock_method_macro
,
node
.
name
),
'
%
s
%
s(
%
s));'
%
(
indent
*
3
,
return_type
,
args
)])
def
_GenerateMocks
(
filename
,
source
,
ast_list
,
desired_class_names
):
def
_GenerateMocks
(
filename
,
source
,
ast_list
,
desired_class_names
):
processed_class_names
=
set
()
processed_class_names
=
set
()
lines
=
[]
lines
=
[]
for
node
in
ast_list
:
for
node
in
ast_list
:
if
(
isinstance
(
node
,
ast
.
Class
)
and
node
.
body
and
if
(
isinstance
(
node
,
ast
.
Class
)
and
node
.
body
and
# desired_class_names being None means that all classes are selected.
# desired_class_names being None means that all classes are selected.
(
not
desired_class_names
or
node
.
name
in
desired_class_names
)):
(
not
desired_class_names
or
node
.
name
in
desired_class_names
)):
class_name
=
node
.
name
class_name
=
node
.
name
parent_name
=
class_name
parent_name
=
class_name
processed_class_names
.
add
(
class_name
)
processed_class_names
.
add
(
class_name
)
class_node
=
node
class_node
=
node
# Add namespace before the class.
# Add namespace before the class.
if
class_node
.
namespace
:
if
class_node
.
namespace
:
lines
.
extend
([
'namespace
%
s {'
%
n
for
n
in
class_node
.
namespace
])
# }
lines
.
extend
([
'namespace
%
s {'
%
n
for
n
in
class_node
.
namespace
])
# }
lines
.
append
(
''
)
lines
.
append
(
''
)
# Add template args for templated classes.
# Add template args for templated classes.
if
class_node
.
templated_types
:
if
class_node
.
templated_types
:
# TODO(paulchang): The AST doesn't preserve template argument order,
# TODO(paulchang): The AST doesn't preserve template argument order,
# so we have to make up names here.
# so we have to make up names here.
# TODO(paulchang): Handle non-type template arguments (e.g.
# TODO(paulchang): Handle non-type template arguments (e.g.
# template<typename T, int N>).
# template<typename T, int N>).
template_arg_count
=
len
(
class_node
.
templated_types
.
keys
())
template_arg_count
=
len
(
class_node
.
templated_types
.
keys
())
template_args
=
[
'T
%
d'
%
n
for
n
in
range
(
template_arg_count
)]
template_args
=
[
'T
%
d'
%
n
for
n
in
range
(
template_arg_count
)]
template_decls
=
[
'typename '
+
arg
for
arg
in
template_args
]
template_decls
=
[
'typename '
+
arg
for
arg
in
template_args
]
lines
.
append
(
'template <'
+
', '
.
join
(
template_decls
)
+
'>'
)
lines
.
append
(
'template <'
+
', '
.
join
(
template_decls
)
+
'>'
)
parent_name
+=
'<'
+
', '
.
join
(
template_args
)
+
'>'
parent_name
+=
'<'
+
', '
.
join
(
template_args
)
+
'>'
# Add the class prolog.
# Add the class prolog.
lines
.
append
(
'class Mock
%
s : public
%
s {'
# }
lines
.
append
(
'class Mock
%
s : public
%
s {'
# }
%
(
class_name
,
parent_name
))
%
(
class_name
,
parent_name
))
lines
.
append
(
'
%
spublic:'
%
(
' '
*
(
_INDENT
//
2
)))
lines
.
append
(
'
%
spublic:'
%
(
' '
*
(
_INDENT
//
2
)))
# Add all the methods.
# Add all the methods.
_GenerateMethods
(
lines
,
source
,
class_node
)
_GenerateMethods
(
lines
,
source
,
class_node
)
# Close the class.
# Close the class.
if
lines
:
if
lines
:
# If there are no virtual methods, no need for a public label.
# If there are no virtual methods, no need for a public label.
if
len
(
lines
)
==
2
:
if
len
(
lines
)
==
2
:
del
lines
[
-
1
]
del
lines
[
-
1
]
# Only close the class if there really is a class.
# Only close the class if there really is a class.
lines
.
append
(
'};'
)
lines
.
append
(
'};'
)
lines
.
append
(
''
)
# Add an extra newline.
lines
.
append
(
''
)
# Add an extra newline.
# Close the namespace.
# Close the namespace.
if
class_node
.
namespace
:
if
class_node
.
namespace
:
for
i
in
range
(
len
(
class_node
.
namespace
)
-
1
,
-
1
,
-
1
):
for
i
in
range
(
len
(
class_node
.
namespace
)
-
1
,
-
1
,
-
1
):
lines
.
append
(
'} // namespace
%
s'
%
class_node
.
namespace
[
i
])
lines
.
append
(
'} // namespace
%
s'
%
class_node
.
namespace
[
i
])
lines
.
append
(
''
)
# Add an extra newline.
lines
.
append
(
''
)
# Add an extra newline.
if
desired_class_names
:
if
desired_class_names
:
missing_class_name_list
=
list
(
desired_class_names
-
processed_class_names
)
missing_class_name_list
=
list
(
desired_class_names
-
processed_class_names
)
if
missing_class_name_list
:
if
missing_class_name_list
:
missing_class_name_list
.
sort
()
missing_class_name_list
.
sort
()
sys
.
stderr
.
write
(
'Class(es) not found in
%
s:
%
s
\n
'
%
sys
.
stderr
.
write
(
'Class(es) not found in
%
s:
%
s
\n
'
%
(
filename
,
', '
.
join
(
missing_class_name_list
)))
(
filename
,
', '
.
join
(
missing_class_name_list
)))
elif
not
processed_class_names
:
elif
not
processed_class_names
:
sys
.
stderr
.
write
(
'No class found in
%
s
\n
'
%
filename
)
sys
.
stderr
.
write
(
'No class found in
%
s
\n
'
%
filename
)
return
lines
return
lines
def
main
(
argv
=
sys
.
argv
):
def
main
(
argv
=
sys
.
argv
):
if
len
(
argv
)
<
2
:
if
len
(
argv
)
<
2
:
sys
.
stderr
.
write
(
'Google Mock Class Generator v
%
s
\n\n
'
%
sys
.
stderr
.
write
(
'Google Mock Class Generator v
%
s
\n\n
'
%
'.'
.
join
(
map
(
str
,
_VERSION
)))
'.'
.
join
(
map
(
str
,
_VERSION
)))
sys
.
stderr
.
write
(
__doc__
)
sys
.
stderr
.
write
(
__doc__
)
return
1
return
1
global
_INDENT
global
_INDENT
try
:
try
:
_INDENT
=
int
(
os
.
environ
[
'INDENT'
])
_INDENT
=
int
(
os
.
environ
[
'INDENT'
])
except
KeyError
:
except
KeyError
:
pass
pass
except
:
except
:
sys
.
stderr
.
write
(
'Unable to use indent of
%
s
\n
'
%
os
.
environ
.
get
(
'INDENT'
))
sys
.
stderr
.
write
(
'Unable to use indent of
%
s
\n
'
%
os
.
environ
.
get
(
'INDENT'
))
filename
=
argv
[
1
]
filename
=
argv
[
1
]
desired_class_names
=
None
# None means all classes in the source file.
desired_class_names
=
None
# None means all classes in the source file.
if
len
(
argv
)
>=
3
:
if
len
(
argv
)
>=
3
:
desired_class_names
=
set
(
argv
[
2
:])
desired_class_names
=
set
(
argv
[
2
:])
source
=
utils
.
ReadFile
(
filename
)
source
=
utils
.
ReadFile
(
filename
)
if
source
is
None
:
if
source
is
None
:
return
1
return
1
builder
=
ast
.
BuilderFromSource
(
source
,
filename
)
builder
=
ast
.
BuilderFromSource
(
source
,
filename
)
try
:
try
:
entire_ast
=
filter
(
None
,
builder
.
Generate
())
entire_ast
=
filter
(
None
,
builder
.
Generate
())
except
KeyboardInterrupt
:
except
KeyboardInterrupt
:
return
return
except
:
except
:
# An error message was already printed since we couldn't parse.
# An error message was already printed since we couldn't parse.
sys
.
exit
(
1
)
sys
.
exit
(
1
)
else
:
else
:
lines
=
_GenerateMocks
(
filename
,
source
,
entire_ast
,
desired_class_names
)
lines
=
_GenerateMocks
(
filename
,
source
,
entire_ast
,
desired_class_names
)
sys
.
stdout
.
write
(
'
\n
'
.
join
(
lines
))
sys
.
stdout
.
write
(
'
\n
'
.
join
(
lines
))
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
(
sys
.
argv
)
main
(
sys
.
argv
)
googlemock/scripts/generator/cpp/gmock_class_test.py
View file @
360f5f70
...
@@ -29,43 +29,43 @@ from cpp import gmock_class
...
@@ -29,43 +29,43 @@ from cpp import gmock_class
class
TestCase
(
unittest
.
TestCase
):
class
TestCase
(
unittest
.
TestCase
):
"""Helper class that adds assert methods."""
"""Helper class that adds assert methods."""
@staticmethod
@staticmethod
def
StripLeadingWhitespace
(
lines
):
def
StripLeadingWhitespace
(
lines
):
"""Strip leading whitespace in each line in 'lines'."""
"""Strip leading whitespace in each line in 'lines'."""
return
'
\n
'
.
join
([
s
.
lstrip
()
for
s
in
lines
.
split
(
'
\n
'
)])
return
'
\n
'
.
join
([
s
.
lstrip
()
for
s
in
lines
.
split
(
'
\n
'
)])
def
assertEqualIgnoreLeadingWhitespace
(
self
,
expected_lines
,
lines
):
def
assertEqualIgnoreLeadingWhitespace
(
self
,
expected_lines
,
lines
):
"""Specialized assert that ignores the indent level."""
"""Specialized assert that ignores the indent level."""
self
.
assertEqual
(
expected_lines
,
self
.
StripLeadingWhitespace
(
lines
))
self
.
assertEqual
(
expected_lines
,
self
.
StripLeadingWhitespace
(
lines
))
class
GenerateMethodsTest
(
TestCase
):
class
GenerateMethodsTest
(
TestCase
):
@staticmethod
@staticmethod
def
GenerateMethodSource
(
cpp_source
):
def
GenerateMethodSource
(
cpp_source
):
"""Convert C++ source to Google Mock output source lines."""
"""Convert C++ source to Google Mock output source lines."""
method_source_lines
=
[]
method_source_lines
=
[]
# <test> is a pseudo-filename, it is not read or written.
# <test> is a pseudo-filename, it is not read or written.
builder
=
ast
.
BuilderFromSource
(
cpp_source
,
'<test>'
)
builder
=
ast
.
BuilderFromSource
(
cpp_source
,
'<test>'
)
ast_list
=
list
(
builder
.
Generate
())
ast_list
=
list
(
builder
.
Generate
())
gmock_class
.
_GenerateMethods
(
method_source_lines
,
cpp_source
,
ast_list
[
0
])
gmock_class
.
_GenerateMethods
(
method_source_lines
,
cpp_source
,
ast_list
[
0
])
return
'
\n
'
.
join
(
method_source_lines
)
return
'
\n
'
.
join
(
method_source_lines
)
def
testSimpleMethod
(
self
):
def
testSimpleMethod
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual int Bar();
virtual int Bar();
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testSimpleConstructorsAndDestructor
(
self
):
def
testSimpleConstructorsAndDestructor
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
Foo();
Foo();
...
@@ -76,26 +76,26 @@ class Foo {
...
@@ -76,26 +76,26 @@ class Foo {
virtual int Bar() = 0;
virtual int Bar() = 0;
};
};
"""
"""
# The constructors and destructor should be ignored.
# The constructors and destructor should be ignored.
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testVirtualDestructor
(
self
):
def
testVirtualDestructor
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual ~Foo();
virtual ~Foo();
virtual int Bar() = 0;
virtual int Bar() = 0;
};
};
"""
"""
# The destructor should be ignored.
# The destructor should be ignored.
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testExplicitlyDefaultedConstructorsAndDestructor
(
self
):
def
testExplicitlyDefaultedConstructorsAndDestructor
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
Foo() = default;
Foo() = default;
...
@@ -105,13 +105,13 @@ class Foo {
...
@@ -105,13 +105,13 @@ class Foo {
virtual int Bar() = 0;
virtual int Bar() = 0;
};
};
"""
"""
# The constructors and destructor should be ignored.
# The constructors and destructor should be ignored.
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testExplicitlyDeletedConstructorsAndDestructor
(
self
):
def
testExplicitlyDeletedConstructorsAndDestructor
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
Foo() = delete;
Foo() = delete;
...
@@ -121,69 +121,69 @@ class Foo {
...
@@ -121,69 +121,69 @@ class Foo {
virtual int Bar() = 0;
virtual int Bar() = 0;
};
};
"""
"""
# The constructors and destructor should be ignored.
# The constructors and destructor should be ignored.
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testSimpleOverrideMethod
(
self
):
def
testSimpleOverrideMethod
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
int Bar() override;
int Bar() override;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testSimpleConstMethod
(
self
):
def
testSimpleConstMethod
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual void Bar(bool flag) const;
virtual void Bar(bool flag) const;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_CONST_METHOD1(Bar,
\n
void(bool flag
));'
,
'MOCK_METHOD(void, Bar, (bool flag), (const, override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testExplicitVoid
(
self
):
def
testExplicitVoid
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual int Bar(void);
virtual int Bar(void);
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0(Bar,
\n
int(void
));'
,
'MOCK_METHOD(int, Bar, (void), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testStrangeNewlineInParameter
(
self
):
def
testStrangeNewlineInParameter
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual void Bar(int
virtual void Bar(int
a) = 0;
a) = 0;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD1(Bar,
\n
void(int a
));'
,
'MOCK_METHOD(void, Bar, (int a), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testDefaultParameters
(
self
):
def
testDefaultParameters
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual void Bar(int a, char c = 'x') = 0;
virtual void Bar(int a, char c = 'x') = 0;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD2(Bar,
\n
void(int a, char c
));'
,
'MOCK_METHOD(void, Bar, (int a, char c), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testMultipleDefaultParameters
(
self
):
def
testMultipleDefaultParameters
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual void Bar(
virtual void Bar(
...
@@ -195,47 +195,47 @@ class Foo {
...
@@ -195,47 +195,47 @@ class Foo {
int const *& rp = aDefaultPointer) = 0;
int const *& rp = aDefaultPointer) = 0;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
"MOCK_METHOD7(Bar,
\n
"
'MOCK_METHOD(void, Bar, '
"void(int a , char c , const int* const p , const std::string& s , char tab[] , int const *& rp ));"
,
'(int a, char c, const int* const p, const std::string& s, char tab[], int const *& rp), '
self
.
GenerateMethodSource
(
source
))
'(override));'
,
self
.
GenerateMethodSource
(
source
))
def
testConstDefaultParameter
(
self
):
def
testConstDefaultParameter
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
virtual bool Bar(const int test_arg = 42) = 0;
virtual bool Bar(const int test_arg = 42) = 0;
};
};
"""
"""
expected
=
'MOCK_METHOD1(Bar,
\n
bool(const int test_arg ));'
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD(bool, Bar, (const int test_arg), (override));'
,
expected
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testConstRefDefaultParameter
(
self
):
def
testConstRefDefaultParameter
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
virtual bool Bar(const std::string& test_arg = "42" ) = 0;
virtual bool Bar(const std::string& test_arg = "42" ) = 0;
};
};
"""
"""
expected
=
'MOCK_METHOD1(Bar,
\n
bool(const std::string& test_arg ));'
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD(bool, Bar, (const std::string& test_arg), (override));'
,
expected
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testRemovesCommentsWhenDefaultsArePresent
(
self
):
def
testRemovesCommentsWhenDefaultsArePresent
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual void Bar(int a = 42 /* a comment */,
virtual void Bar(int a = 42 /* a comment */,
char /* other comment */ c= 'x') = 0;
char /* other comment */ c= 'x') = 0;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD2(Bar,
\n
void(int a , char c
));'
,
'MOCK_METHOD(void, Bar, (int a, char c), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testDoubleSlashCommentsInParameterListAreRemoved
(
self
):
def
testDoubleSlashCommentsInParameterListAreRemoved
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual void Bar(int a, // inline comments should be elided.
virtual void Bar(int a, // inline comments should be elided.
...
@@ -243,117 +243,111 @@ class Foo {
...
@@ -243,117 +243,111 @@ class Foo {
) const = 0;
) const = 0;
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_CONST_METHOD2(Bar,
\n
void(int a, int b
));'
,
'MOCK_METHOD(void, Bar, (int a, int b), (const, override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testCStyleCommentsInParameterListAreNotRemoved
(
self
):
def
testCStyleCommentsInParameterListAreNotRemoved
(
self
):
# NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
# NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
# comments. Also note that C style comments after the last parameter
# comments. Also note that C style comments after the last parameter
# are still elided.
# are still elided.
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual const string& Bar(int /* keeper */, int b);
virtual const string& Bar(int /* keeper */, int b);
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD2(Bar,
\n
const string&(int , int b
));'
,
'MOCK_METHOD(const string&, Bar, (int, int b), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testArgsOfTemplateTypes
(
self
):
def
testArgsOfTemplateTypes
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual int Bar(const vector<int>& v, map<int, string>* output);
virtual int Bar(const vector<int>& v, map<int, string>* output);
};"""
};"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD2(Bar,
\n
'
'MOCK_METHOD(int, Bar, (const vector<int>& v, map<int, string>* output), (override));'
,
'int(const vector<int>& v, map<int, string>* output));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testReturnTypeWithOneTemplateArg
(
self
):
def
testReturnTypeWithOneTemplateArg
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual vector<int>* Bar(int n);
virtual vector<int>* Bar(int n);
};"""
};"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD1(Bar,
\n
vector<int>*(int n
));'
,
'MOCK_METHOD(vector<int>*, Bar, (int n), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testReturnTypeWithManyTemplateArgs
(
self
):
def
testReturnTypeWithManyTemplateArgs
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
public:
public:
virtual map<int, string> Bar();
virtual map<int, string> Bar();
};"""
};"""
# Comparing the comment text is brittle - we'll think of something
self
.
assertEqualIgnoreLeadingWhitespace
(
# better in case this gets annoying, but for now let's keep it simple.
'MOCK_METHOD((map<int, string>), Bar, (), (override));'
,
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
GenerateMethodSource
(
source
))
'// The following line won
\'
t really compile, as the return
\n
'
'// type has multiple template arguments. To fix it, use a
\n
'
def
testSimpleMethodInTemplatedClass
(
self
):
'// typedef for the return type.
\n
'
source
=
"""
'MOCK_METHOD0(Bar,
\n
map<int, string>());'
,
self
.
GenerateMethodSource
(
source
))
def
testSimpleMethodInTemplatedClass
(
self
):
source
=
"""
template<class T>
template<class T>
class Foo {
class Foo {
public:
public:
virtual int Bar();
virtual int Bar();
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD0_T(Bar,
\n
int(
));'
,
'MOCK_METHOD(int, Bar, (), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testPointerArgWithoutNames
(
self
):
def
testPointerArgWithoutNames
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
virtual int Bar(C*);
virtual int Bar(C*);
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD1(Bar,
\n
int(C*
));'
,
'MOCK_METHOD(int, Bar, (C*), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testReferenceArgWithoutNames
(
self
):
def
testReferenceArgWithoutNames
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
virtual int Bar(C&);
virtual int Bar(C&);
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD1(Bar,
\n
int(C&
));'
,
'MOCK_METHOD(int, Bar, (C&), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
def
testArrayArgWithoutNames
(
self
):
def
testArrayArgWithoutNames
(
self
):
source
=
"""
source
=
"""
class Foo {
class Foo {
virtual int Bar(C[]);
virtual int Bar(C[]);
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
'MOCK_METHOD1(Bar,
\n
int(C[]
));'
,
'MOCK_METHOD(int, Bar, (C[]), (override
));'
,
self
.
GenerateMethodSource
(
source
))
self
.
GenerateMethodSource
(
source
))
class
GenerateMocksTest
(
TestCase
):
class
GenerateMocksTest
(
TestCase
):
@staticmethod
@staticmethod
def
GenerateMocks
(
cpp_source
):
def
GenerateMocks
(
cpp_source
):
"""Convert C++ source to complete Google Mock output source."""
"""Convert C++ source to complete Google Mock output source."""
# <test> is a pseudo-filename, it is not read or written.
# <test> is a pseudo-filename, it is not read or written.
filename
=
'<test>'
filename
=
'<test>'
builder
=
ast
.
BuilderFromSource
(
cpp_source
,
filename
)
builder
=
ast
.
BuilderFromSource
(
cpp_source
,
filename
)
ast_list
=
list
(
builder
.
Generate
())
ast_list
=
list
(
builder
.
Generate
())
lines
=
gmock_class
.
_GenerateMocks
(
filename
,
cpp_source
,
ast_list
,
None
)
lines
=
gmock_class
.
_GenerateMocks
(
filename
,
cpp_source
,
ast_list
,
None
)
return
'
\n
'
.
join
(
lines
)
return
'
\n
'
.
join
(
lines
)
def
testNamespaces
(
self
):
def
testNamespaces
(
self
):
source
=
"""
source
=
"""
namespace Foo {
namespace Foo {
namespace Bar { class Forward; }
namespace Bar { class Forward; }
namespace Baz {
namespace Baz {
...
@@ -366,96 +360,91 @@ class Test {
...
@@ -366,96 +360,91 @@ class Test {
} // namespace Baz
} // namespace Baz
} // namespace Foo
} // namespace Foo
"""
"""
expected
=
"""
\
expected
=
"""
\
namespace Foo {
namespace Foo {
namespace Baz {
namespace Baz {
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD0(Foo,
MOCK_METHOD(void, Foo, (), (override));
void());
};
};
} // namespace Baz
} // namespace Baz
} // namespace Foo
} // namespace Foo
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testClassWithStorageSpecifierMacro
(
self
):
def
testClassWithStorageSpecifierMacro
(
self
):
source
=
"""
source
=
"""
class STORAGE_SPECIFIER Test {
class STORAGE_SPECIFIER Test {
public:
public:
virtual void Foo();
virtual void Foo();
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD0(Foo,
MOCK_METHOD(void, Foo, (), (override));
void());
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testTemplatedForwardDeclaration
(
self
):
def
testTemplatedForwardDeclaration
(
self
):
source
=
"""
source
=
"""
template <class T> class Forward; // Forward declaration should be ignored.
template <class T> class Forward; // Forward declaration should be ignored.
class Test {
class Test {
public:
public:
virtual void Foo();
virtual void Foo();
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD0(Foo,
MOCK_METHOD(void, Foo, (), (override));
void());
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testTemplatedClass
(
self
):
def
testTemplatedClass
(
self
):
source
=
"""
source
=
"""
template <typename S, typename T>
template <typename S, typename T>
class Test {
class Test {
public:
public:
virtual void Foo();
virtual void Foo();
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
template <typename T0, typename T1>
template <typename T0, typename T1>
class MockTest : public Test<T0, T1> {
class MockTest : public Test<T0, T1> {
public:
public:
MOCK_METHOD0_T(Foo,
MOCK_METHOD(void, Foo, (), (override));
void());
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testTemplateInATemplateTypedef
(
self
):
def
testTemplateInATemplateTypedef
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
typedef std::vector<std::list<int>> FooType;
typedef std::vector<std::list<int>> FooType;
virtual void Bar(const FooType& test_arg);
virtual void Bar(const FooType& test_arg);
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD1(Bar,
MOCK_METHOD(void, Bar, (const FooType& test_arg), (override));
void(const FooType& test_arg));
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testTemplateInATemplateTypedefWithComma
(
self
):
def
testTemplateInATemplateTypedefWithComma
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
typedef std::function<void(
typedef std::function<void(
...
@@ -463,18 +452,17 @@ class Test {
...
@@ -463,18 +452,17 @@ class Test {
virtual void Bar(const FooType& test_arg);
virtual void Bar(const FooType& test_arg);
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD1(Bar,
MOCK_METHOD(void, Bar, (const FooType& test_arg), (override));
void(const FooType& test_arg));
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testEnumType
(
self
):
def
testEnumType
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
enum Bar {
enum Bar {
...
@@ -483,18 +471,17 @@ class Test {
...
@@ -483,18 +471,17 @@ class Test {
virtual void Foo();
virtual void Foo();
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD0(Foo,
MOCK_METHOD(void, Foo, (), (override));
void());
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testEnumClassType
(
self
):
def
testEnumClassType
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
enum class Bar {
enum class Bar {
...
@@ -503,18 +490,17 @@ class Test {
...
@@ -503,18 +490,17 @@ class Test {
virtual void Foo();
virtual void Foo();
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD0(Foo,
MOCK_METHOD(void, Foo, (), (override));
void());
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
def
testStdFunction
(
self
):
def
testStdFunction
(
self
):
source
=
"""
source
=
"""
class Test {
class Test {
public:
public:
Test(std::function<int(std::string)> foo) : foo_(foo) {}
Test(std::function<int(std::string)> foo) : foo_(foo) {}
...
@@ -525,16 +511,15 @@ class Test {
...
@@ -525,16 +511,15 @@ class Test {
std::function<int(std::string)> foo_;
std::function<int(std::string)> foo_;
};
};
"""
"""
expected
=
"""
\
expected
=
"""
\
class MockTest : public Test {
class MockTest : public Test {
public:
public:
MOCK_METHOD0(foo,
MOCK_METHOD(std::function<int (std::string)>, foo, (), (override));
std::function<int (std::string)>());
};
};
"""
"""
self
.
assertEqualIgnoreLeadingWhitespace
(
self
.
assertEqualIgnoreLeadingWhitespace
(
expected
,
expected
,
self
.
GenerateMocks
(
source
))
self
.
GenerateMocks
(
source
))
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
unittest
.
main
()
unittest
.
main
()
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