summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2013-09-06 22:52:14 +0000
committerzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2013-09-06 22:52:14 +0000
commit0364be7dfbb68cf9fb5344aa602022eab9f29228 (patch)
tree9993cd7a492e5012bb4523db13038bd6dbf29a05
parent8834a3bf14fd7b2895c7bb614e3a06cbd406fd01 (diff)
downloadgooglemock-0364be7dfbb68cf9fb5344aa602022eab9f29228.tar.gz
makes googlemock generator handle some class templates; pulls in gtest r662
git-svn-id: http://googlemock.googlecode.com/svn/trunk@449 8415998a-534a-0410-bf83-d39667b30386
-rw-r--r--CHANGES2
-rwxr-xr-xscripts/generator/cpp/ast.py2
-rwxr-xr-xscripts/generator/cpp/gmock_class.py22
-rwxr-xr-xscripts/generator/cpp/gmock_class_test.py50
-rwxr-xr-xtest/gmock_leak_test.py34
-rwxr-xr-xtest/gmock_test_utils.py7
6 files changed, 103 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index e42e68f..d6f2f76 100644
--- a/CHANGES
+++ b/CHANGES
@@ -23,6 +23,8 @@ Changes for 1.7.0:
* Improvement: the ElementsAreArray() matcher can now take a vector or
iterator range as input, and makes a copy of its input elements
before the conversion to a Matcher.
+* Improvement: the Google Mock Generator can now generate mocks for
+ some class templates.
* Bug fix: mock object destruction triggerred by another mock object's
destruction no longer hangs.
* Improvement: Google Mock Doctor works better with newer Clang and
diff --git a/scripts/generator/cpp/ast.py b/scripts/generator/cpp/ast.py
index 6f61f87..bb8226d 100755
--- a/scripts/generator/cpp/ast.py
+++ b/scripts/generator/cpp/ast.py
@@ -1546,7 +1546,7 @@ class AstBuilder(object):
self._AddBackToken(token)
return class_type(class_token.start, class_token.end, class_name,
- bases, None, body, self.namespace_stack)
+ bases, templated_types, body, self.namespace_stack)
def handle_namespace(self):
token = self._GetNextToken()
diff --git a/scripts/generator/cpp/gmock_class.py b/scripts/generator/cpp/gmock_class.py
index 427d206..3c8a877 100755
--- a/scripts/generator/cpp/gmock_class.py
+++ b/scripts/generator/cpp/gmock_class.py
@@ -88,7 +88,11 @@ def _GenerateMethods(output_lines, source, class_node):
if source[first_param.start:first_param.end].strip() == 'void':
# We must treat T(void) as a function with no parameters.
num_parameters = 0
- mock_method_macro = 'MOCK_%sMETHOD%d' % (const, num_parameters)
+ tmpl = ''
+ if class_node.templated_types:
+ tmpl = '_T'
+ mock_method_macro = 'MOCK_%sMETHOD%d%s' % (const, num_parameters, tmpl)
+
args = ''
if node.parameters:
# Due to the parser limitations, it is impossible to keep comments
@@ -126,6 +130,7 @@ def _GenerateMocks(filename, source, ast_list, desired_class_names):
# desired_class_names being None means that all classes are selected.
(not desired_class_names or node.name in desired_class_names)):
class_name = node.name
+ parent_name = class_name
processed_class_names.add(class_name)
class_node = node
# Add namespace before the class.
@@ -133,8 +138,21 @@ def _GenerateMocks(filename, source, ast_list, desired_class_names):
lines.extend(['namespace %s {' % n for n in class_node.namespace]) # }
lines.append('')
+ # Add template args for templated classes.
+ if class_node.templated_types:
+ # TODO(paulchang): The AST doesn't preserve template argument order,
+ # so we have to make up names here.
+ # TODO(paulchang): Handle non-type template arguments (e.g.
+ # template<typename T, int N>).
+ template_arg_count = len(class_node.templated_types.keys())
+ template_args = ['T%d' % n for n in range(template_arg_count)]
+ template_decls = ['typename ' + arg for arg in template_args]
+ lines.append('template <' + ', '.join(template_decls) + '>')
+ parent_name += '<' + ', '.join(template_args) + '>'
+
# Add the class prolog.
- lines.append('class Mock%s : public %s {' % (class_name, class_name)) # }
+ lines.append('class Mock%s : public %s {' # }
+ % (class_name, parent_name))
lines.append('%spublic:' % (' ' * (_INDENT // 2)))
# Add all the methods.
diff --git a/scripts/generator/cpp/gmock_class_test.py b/scripts/generator/cpp/gmock_class_test.py
index 7aa7027..07d5957 100755
--- a/scripts/generator/cpp/gmock_class_test.py
+++ b/scripts/generator/cpp/gmock_class_test.py
@@ -196,6 +196,18 @@ class Foo {
'MOCK_METHOD0(Bar,\nmap<int, string>());',
self.GenerateMethodSource(source))
+ def testSimpleMethodInTemplatedClass(self):
+ source = """
+template<class T>
+class Foo {
+ public:
+ virtual int Bar();
+};
+"""
+ self.assertEqualIgnoreLeadingWhitespace(
+ 'MOCK_METHOD0_T(Bar,\nint());',
+ self.GenerateMethodSource(source))
+
class GenerateMocksTest(TestCase):
@@ -255,5 +267,43 @@ void());
self.assertEqualIgnoreLeadingWhitespace(
expected, self.GenerateMocks(source))
+ def testTemplatedForwardDeclaration(self):
+ source = """
+template <class T> class Forward; // Forward declaration should be ignored.
+class Test {
+ public:
+ virtual void Foo();
+};
+"""
+ expected = """\
+class MockTest : public Test {
+public:
+MOCK_METHOD0(Foo,
+void());
+};
+"""
+ self.assertEqualIgnoreLeadingWhitespace(
+ expected, self.GenerateMocks(source))
+
+ def testTemplatedClass(self):
+ source = """
+template <typename S, typename T>
+class Test {
+ public:
+ virtual void Foo();
+};
+"""
+ expected = """\
+template <typename T0, typename T1>
+class MockTest : public Test<T0, T1> {
+public:
+MOCK_METHOD0_T(Foo,
+void());
+};
+"""
+ self.assertEqualIgnoreLeadingWhitespace(
+ expected, self.GenerateMocks(source))
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/test/gmock_leak_test.py b/test/gmock_leak_test.py
index 38ff9d0..997680c 100755
--- a/test/gmock_leak_test.py
+++ b/test/gmock_leak_test.py
@@ -42,48 +42,66 @@ TEST_WITH_EXPECT_CALL = [PROGRAM_PATH, '--gtest_filter=*ExpectCall*']
TEST_WITH_ON_CALL = [PROGRAM_PATH, '--gtest_filter=*OnCall*']
TEST_MULTIPLE_LEAKS = [PROGRAM_PATH, '--gtest_filter=*MultipleLeaked*']
+environ = gmock_test_utils.environ
+SetEnvVar = gmock_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely. Therefore they are incompatible with
+# the premature-exit-file protocol by design. Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gmock_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
class GMockLeakTest(gmock_test_utils.TestCase):
def testCatchesLeakedMockByDefault(self):
self.assertNotEqual(
0,
- gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL).exit_code)
+ gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL,
+ env=environ).exit_code)
self.assertNotEqual(
0,
- gmock_test_utils.Subprocess(TEST_WITH_ON_CALL).exit_code)
+ gmock_test_utils.Subprocess(TEST_WITH_ON_CALL,
+ env=environ).exit_code)
def testDoesNotCatchLeakedMockWhenDisabled(self):
self.assertEquals(
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
- ['--gmock_catch_leaked_mocks=0']).exit_code)
+ ['--gmock_catch_leaked_mocks=0'],
+ env=environ).exit_code)
self.assertEquals(
0,
gmock_test_utils.Subprocess(TEST_WITH_ON_CALL +
- ['--gmock_catch_leaked_mocks=0']).exit_code)
+ ['--gmock_catch_leaked_mocks=0'],
+ env=environ).exit_code)
def testCatchesLeakedMockWhenEnabled(self):
self.assertNotEqual(
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
- ['--gmock_catch_leaked_mocks']).exit_code)
+ ['--gmock_catch_leaked_mocks'],
+ env=environ).exit_code)
self.assertNotEqual(
0,
gmock_test_utils.Subprocess(TEST_WITH_ON_CALL +
- ['--gmock_catch_leaked_mocks']).exit_code)
+ ['--gmock_catch_leaked_mocks'],
+ env=environ).exit_code)
def testCatchesLeakedMockWhenEnabledWithExplictFlagValue(self):
self.assertNotEqual(
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
- ['--gmock_catch_leaked_mocks=1']).exit_code)
+ ['--gmock_catch_leaked_mocks=1'],
+ env=environ).exit_code)
def testCatchesMultipleLeakedMocks(self):
self.assertNotEqual(
0,
gmock_test_utils.Subprocess(TEST_MULTIPLE_LEAKS +
- ['--gmock_catch_leaked_mocks']).exit_code)
+ ['--gmock_catch_leaked_mocks'],
+ env=environ).exit_code)
if __name__ == '__main__':
diff --git a/test/gmock_test_utils.py b/test/gmock_test_utils.py
index ac3d67a..20e3d3d 100755
--- a/test/gmock_test_utils.py
+++ b/test/gmock_test_utils.py
@@ -96,11 +96,12 @@ def GetExitStatus(exit_code):
# Suppresses the "Invalid const name" lint complaint
# pylint: disable-msg=C6409
-# Exposes Subprocess from gtest_test_utils.
+# Exposes utilities from gtest_test_utils.
Subprocess = gtest_test_utils.Subprocess
-
-# Exposes TestCase from gtest_test_utils.
TestCase = gtest_test_utils.TestCase
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+PREMATURE_EXIT_FILE_ENV_VAR = gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR
# pylint: enable-msg=C6409