1#!/usr/bin/env python 2# 3# Copyright 2009 Neal Norwitz All Rights Reserved. 4# Portions Copyright 2009 Google Inc. All Rights Reserved. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18"""Tests for gmock.scripts.generator.cpp.gmock_class.""" 19 20__author__ = 'nnorwitz@google.com (Neal Norwitz)' 21 22 23import os 24import sys 25import unittest 26 27# Allow the cpp imports below to work when run as a standalone script. 28sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 29 30from cpp import ast 31from cpp import gmock_class 32 33 34class TestCase(unittest.TestCase): 35 """Helper class that adds assert methods.""" 36 37 def StripLeadingWhitespace(self, lines): 38 """Strip leading whitespace in each line in 'lines'.""" 39 return '\n'.join([s.lstrip() for s in lines.split('\n')]) 40 41 def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines): 42 """Specialized assert that ignores the indent level.""" 43 self.assertEqual(expected_lines, self.StripLeadingWhitespace(lines)) 44 45 46class GenerateMethodsTest(TestCase): 47 48 def GenerateMethodSource(self, cpp_source): 49 """Convert C++ source to Google Mock output source lines.""" 50 method_source_lines = [] 51 # <test> is a pseudo-filename, it is not read or written. 52 builder = ast.BuilderFromSource(cpp_source, '<test>') 53 ast_list = list(builder.Generate()) 54 gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0]) 55 return '\n'.join(method_source_lines) 56 57 def testSimpleMethod(self): 58 source = """ 59class Foo { 60 public: 61 virtual int Bar(); 62}; 63""" 64 self.assertEqualIgnoreLeadingWhitespace( 65 'MOCK_METHOD0(Bar,\nint());', 66 self.GenerateMethodSource(source)) 67 68 def testSimpleConstMethod(self): 69 source = """ 70class Foo { 71 public: 72 virtual void Bar(bool flag) const; 73}; 74""" 75 self.assertEqualIgnoreLeadingWhitespace( 76 'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));', 77 self.GenerateMethodSource(source)) 78 79 def testStrangeNewlineInParameter(self): 80 source = """ 81class Foo { 82 public: 83 virtual void Bar(int 84a) = 0; 85}; 86""" 87 self.assertEqualIgnoreLeadingWhitespace( 88 'MOCK_METHOD1(Bar,\nvoid(int a));', 89 self.GenerateMethodSource(source)) 90 91 def testDoubleSlashCommentsInParameterListAreRemoved(self): 92 source = """ 93class Foo { 94 public: 95 virtual void Bar(int a, // inline comments should be elided. 96 int b // inline comments should be elided. 97 ) const = 0; 98}; 99""" 100 self.assertEqualIgnoreLeadingWhitespace( 101 'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));', 102 self.GenerateMethodSource(source)) 103 104 def testCStyleCommentsInParameterListAreNotRemoved(self): 105 # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these 106 # comments. Also note that C style comments after the last parameter 107 # are still elided. 108 source = """ 109class Foo { 110 public: 111 virtual const string& Bar(int /* keeper */, int b); 112}; 113""" 114 self.assertEqualIgnoreLeadingWhitespace( 115 'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));', 116 self.GenerateMethodSource(source)) 117 118 def testArgsOfTemplateTypes(self): 119 source = """ 120class Foo { 121 public: 122 virtual int Bar(const vector<int>& v, map<int, string>* output); 123};""" 124 self.assertEqualIgnoreLeadingWhitespace( 125 'MOCK_METHOD2(Bar,\n' 126 'int(const vector<int>& v, map<int, string>* output));', 127 self.GenerateMethodSource(source)) 128 129 def testReturnTypeWithOneTemplateArg(self): 130 source = """ 131class Foo { 132 public: 133 virtual vector<int>* Bar(int n); 134};""" 135 self.assertEqualIgnoreLeadingWhitespace( 136 'MOCK_METHOD1(Bar,\nvector<int>*(int n));', 137 self.GenerateMethodSource(source)) 138 139 def testReturnTypeWithManyTemplateArgs(self): 140 source = """ 141class Foo { 142 public: 143 virtual map<int, string> Bar(); 144};""" 145 # Comparing the comment text is brittle - we'll think of something 146 # better in case this gets annoying, but for now let's keep it simple. 147 self.assertEqualIgnoreLeadingWhitespace( 148 '// The following line won\'t really compile, as the return\n' 149 '// type has multiple template arguments. To fix it, use a\n' 150 '// typedef for the return type.\n' 151 'MOCK_METHOD0(Bar,\nmap<int, string>());', 152 self.GenerateMethodSource(source)) 153 154 155class GenerateMocksTest(TestCase): 156 157 def GenerateMocks(self, cpp_source): 158 """Convert C++ source to complete Google Mock output source.""" 159 # <test> is a pseudo-filename, it is not read or written. 160 filename = '<test>' 161 builder = ast.BuilderFromSource(cpp_source, filename) 162 ast_list = list(builder.Generate()) 163 lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None) 164 return '\n'.join(lines) 165 166 def testNamespaces(self): 167 source = """ 168namespace Foo { 169namespace Bar { class Forward; } 170namespace Baz { 171 172class Test { 173 public: 174 virtual void Foo(); 175}; 176 177} // namespace Baz 178} // namespace Foo 179""" 180 expected = """\ 181namespace Foo { 182namespace Baz { 183 184class MockTest : public Test { 185public: 186MOCK_METHOD0(Foo, 187void()); 188}; 189 190} // namespace Baz 191} // namespace Foo 192""" 193 self.assertEqualIgnoreLeadingWhitespace( 194 expected, self.GenerateMocks(source)) 195 196 def testClassWithStorageSpecifierMacro(self): 197 source = """ 198class STORAGE_SPECIFIER Test { 199 public: 200 virtual void Foo(); 201}; 202""" 203 expected = """\ 204class MockTest : public Test { 205public: 206MOCK_METHOD0(Foo, 207void()); 208}; 209""" 210 self.assertEqualIgnoreLeadingWhitespace( 211 expected, self.GenerateMocks(source)) 212 213if __name__ == '__main__': 214 unittest.main() 215