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 (at] google.com (Neal Norwitz)' 21 22 23 import os 24 import sys 25 import unittest 26 27 # Allow the cpp imports below to work when run as a standalone script. 28 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 29 30 from cpp import ast 31 from cpp import gmock_class 32 33 34 class 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 46 class 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 = """ 59 class 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 = """ 70 class 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 testExplicitVoid(self): 80 source = """ 81 class Foo { 82 public: 83 virtual int Bar(void); 84 }; 85 """ 86 self.assertEqualIgnoreLeadingWhitespace( 87 'MOCK_METHOD0(Bar,\nint(void));', 88 self.GenerateMethodSource(source)) 89 90 def testStrangeNewlineInParameter(self): 91 source = """ 92 class Foo { 93 public: 94 virtual void Bar(int 95 a) = 0; 96 }; 97 """ 98 self.assertEqualIgnoreLeadingWhitespace( 99 'MOCK_METHOD1(Bar,\nvoid(int a));', 100 self.GenerateMethodSource(source)) 101 102 def testDefaultParameters(self): 103 source = """ 104 class Foo { 105 public: 106 virtual void Bar(int a, char c = 'x') = 0; 107 }; 108 """ 109 self.assertEqualIgnoreLeadingWhitespace( 110 'MOCK_METHOD2(Bar,\nvoid(int, char));', 111 self.GenerateMethodSource(source)) 112 113 def testMultipleDefaultParameters(self): 114 source = """ 115 class Foo { 116 public: 117 virtual void Bar(int a = 42, char c = 'x') = 0; 118 }; 119 """ 120 self.assertEqualIgnoreLeadingWhitespace( 121 'MOCK_METHOD2(Bar,\nvoid(int, char));', 122 self.GenerateMethodSource(source)) 123 124 def testRemovesCommentsWhenDefaultsArePresent(self): 125 source = """ 126 class Foo { 127 public: 128 virtual void Bar(int a = 42 /* a comment */, 129 char /* other comment */ c= 'x') = 0; 130 }; 131 """ 132 self.assertEqualIgnoreLeadingWhitespace( 133 'MOCK_METHOD2(Bar,\nvoid(int, char));', 134 self.GenerateMethodSource(source)) 135 136 def testDoubleSlashCommentsInParameterListAreRemoved(self): 137 source = """ 138 class Foo { 139 public: 140 virtual void Bar(int a, // inline comments should be elided. 141 int b // inline comments should be elided. 142 ) const = 0; 143 }; 144 """ 145 self.assertEqualIgnoreLeadingWhitespace( 146 'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));', 147 self.GenerateMethodSource(source)) 148 149 def testCStyleCommentsInParameterListAreNotRemoved(self): 150 # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these 151 # comments. Also note that C style comments after the last parameter 152 # are still elided. 153 source = """ 154 class Foo { 155 public: 156 virtual const string& Bar(int /* keeper */, int b); 157 }; 158 """ 159 self.assertEqualIgnoreLeadingWhitespace( 160 'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));', 161 self.GenerateMethodSource(source)) 162 163 def testArgsOfTemplateTypes(self): 164 source = """ 165 class Foo { 166 public: 167 virtual int Bar(const vector<int>& v, map<int, string>* output); 168 };""" 169 self.assertEqualIgnoreLeadingWhitespace( 170 'MOCK_METHOD2(Bar,\n' 171 'int(const vector<int>& v, map<int, string>* output));', 172 self.GenerateMethodSource(source)) 173 174 def testReturnTypeWithOneTemplateArg(self): 175 source = """ 176 class Foo { 177 public: 178 virtual vector<int>* Bar(int n); 179 };""" 180 self.assertEqualIgnoreLeadingWhitespace( 181 'MOCK_METHOD1(Bar,\nvector<int>*(int n));', 182 self.GenerateMethodSource(source)) 183 184 def testReturnTypeWithManyTemplateArgs(self): 185 source = """ 186 class Foo { 187 public: 188 virtual map<int, string> Bar(); 189 };""" 190 # Comparing the comment text is brittle - we'll think of something 191 # better in case this gets annoying, but for now let's keep it simple. 192 self.assertEqualIgnoreLeadingWhitespace( 193 '// The following line won\'t really compile, as the return\n' 194 '// type has multiple template arguments. To fix it, use a\n' 195 '// typedef for the return type.\n' 196 'MOCK_METHOD0(Bar,\nmap<int, string>());', 197 self.GenerateMethodSource(source)) 198 199 200 class GenerateMocksTest(TestCase): 201 202 def GenerateMocks(self, cpp_source): 203 """Convert C++ source to complete Google Mock output source.""" 204 # <test> is a pseudo-filename, it is not read or written. 205 filename = '<test>' 206 builder = ast.BuilderFromSource(cpp_source, filename) 207 ast_list = list(builder.Generate()) 208 lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None) 209 return '\n'.join(lines) 210 211 def testNamespaces(self): 212 source = """ 213 namespace Foo { 214 namespace Bar { class Forward; } 215 namespace Baz { 216 217 class Test { 218 public: 219 virtual void Foo(); 220 }; 221 222 } // namespace Baz 223 } // namespace Foo 224 """ 225 expected = """\ 226 namespace Foo { 227 namespace Baz { 228 229 class MockTest : public Test { 230 public: 231 MOCK_METHOD0(Foo, 232 void()); 233 }; 234 235 } // namespace Baz 236 } // namespace Foo 237 """ 238 self.assertEqualIgnoreLeadingWhitespace( 239 expected, self.GenerateMocks(source)) 240 241 def testClassWithStorageSpecifierMacro(self): 242 source = """ 243 class STORAGE_SPECIFIER Test { 244 public: 245 virtual void Foo(); 246 }; 247 """ 248 expected = """\ 249 class MockTest : public Test { 250 public: 251 MOCK_METHOD0(Foo, 252 void()); 253 }; 254 """ 255 self.assertEqualIgnoreLeadingWhitespace( 256 expected, self.GenerateMocks(source)) 257 258 if __name__ == '__main__': 259 unittest.main() 260