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 testSimpleConstructorsAndDestructor(self): 69 source = """ 70 class Foo { 71 public: 72 Foo(); 73 Foo(int x); 74 Foo(const Foo& f); 75 Foo(Foo&& f); 76 ~Foo(); 77 virtual int Bar() = 0; 78 }; 79 """ 80 # The constructors and destructor should be ignored. 81 self.assertEqualIgnoreLeadingWhitespace( 82 'MOCK_METHOD0(Bar,\nint());', 83 self.GenerateMethodSource(source)) 84 85 def testVirtualDestructor(self): 86 source = """ 87 class Foo { 88 public: 89 virtual ~Foo(); 90 virtual int Bar() = 0; 91 }; 92 """ 93 # The destructor should be ignored. 94 self.assertEqualIgnoreLeadingWhitespace( 95 'MOCK_METHOD0(Bar,\nint());', 96 self.GenerateMethodSource(source)) 97 98 def testExplicitlyDefaultedConstructorsAndDestructor(self): 99 source = """ 100 class Foo { 101 public: 102 Foo() = default; 103 Foo(const Foo& f) = default; 104 Foo(Foo&& f) = default; 105 ~Foo() = default; 106 virtual int Bar() = 0; 107 }; 108 """ 109 # The constructors and destructor should be ignored. 110 self.assertEqualIgnoreLeadingWhitespace( 111 'MOCK_METHOD0(Bar,\nint());', 112 self.GenerateMethodSource(source)) 113 114 def testExplicitlyDeletedConstructorsAndDestructor(self): 115 source = """ 116 class Foo { 117 public: 118 Foo() = delete; 119 Foo(const Foo& f) = delete; 120 Foo(Foo&& f) = delete; 121 ~Foo() = delete; 122 virtual int Bar() = 0; 123 }; 124 """ 125 # The constructors and destructor should be ignored. 126 self.assertEqualIgnoreLeadingWhitespace( 127 'MOCK_METHOD0(Bar,\nint());', 128 self.GenerateMethodSource(source)) 129 130 def testSimpleOverrideMethod(self): 131 source = """ 132 class Foo { 133 public: 134 int Bar() override; 135 }; 136 """ 137 self.assertEqualIgnoreLeadingWhitespace( 138 'MOCK_METHOD0(Bar,\nint());', 139 self.GenerateMethodSource(source)) 140 141 def testSimpleConstMethod(self): 142 source = """ 143 class Foo { 144 public: 145 virtual void Bar(bool flag) const; 146 }; 147 """ 148 self.assertEqualIgnoreLeadingWhitespace( 149 'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));', 150 self.GenerateMethodSource(source)) 151 152 def testExplicitVoid(self): 153 source = """ 154 class Foo { 155 public: 156 virtual int Bar(void); 157 }; 158 """ 159 self.assertEqualIgnoreLeadingWhitespace( 160 'MOCK_METHOD0(Bar,\nint(void));', 161 self.GenerateMethodSource(source)) 162 163 def testStrangeNewlineInParameter(self): 164 source = """ 165 class Foo { 166 public: 167 virtual void Bar(int 168 a) = 0; 169 }; 170 """ 171 self.assertEqualIgnoreLeadingWhitespace( 172 'MOCK_METHOD1(Bar,\nvoid(int a));', 173 self.GenerateMethodSource(source)) 174 175 def testDefaultParameters(self): 176 source = """ 177 class Foo { 178 public: 179 virtual void Bar(int a, char c = 'x') = 0; 180 }; 181 """ 182 self.assertEqualIgnoreLeadingWhitespace( 183 'MOCK_METHOD2(Bar,\nvoid(int, char));', 184 self.GenerateMethodSource(source)) 185 186 def testMultipleDefaultParameters(self): 187 source = """ 188 class Foo { 189 public: 190 virtual void Bar(int a = 42, char c = 'x') = 0; 191 }; 192 """ 193 self.assertEqualIgnoreLeadingWhitespace( 194 'MOCK_METHOD2(Bar,\nvoid(int, char));', 195 self.GenerateMethodSource(source)) 196 197 def testRemovesCommentsWhenDefaultsArePresent(self): 198 source = """ 199 class Foo { 200 public: 201 virtual void Bar(int a = 42 /* a comment */, 202 char /* other comment */ c= 'x') = 0; 203 }; 204 """ 205 self.assertEqualIgnoreLeadingWhitespace( 206 'MOCK_METHOD2(Bar,\nvoid(int, char));', 207 self.GenerateMethodSource(source)) 208 209 def testDoubleSlashCommentsInParameterListAreRemoved(self): 210 source = """ 211 class Foo { 212 public: 213 virtual void Bar(int a, // inline comments should be elided. 214 int b // inline comments should be elided. 215 ) const = 0; 216 }; 217 """ 218 self.assertEqualIgnoreLeadingWhitespace( 219 'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));', 220 self.GenerateMethodSource(source)) 221 222 def testCStyleCommentsInParameterListAreNotRemoved(self): 223 # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these 224 # comments. Also note that C style comments after the last parameter 225 # are still elided. 226 source = """ 227 class Foo { 228 public: 229 virtual const string& Bar(int /* keeper */, int b); 230 }; 231 """ 232 self.assertEqualIgnoreLeadingWhitespace( 233 'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));', 234 self.GenerateMethodSource(source)) 235 236 def testArgsOfTemplateTypes(self): 237 source = """ 238 class Foo { 239 public: 240 virtual int Bar(const vector<int>& v, map<int, string>* output); 241 };""" 242 self.assertEqualIgnoreLeadingWhitespace( 243 'MOCK_METHOD2(Bar,\n' 244 'int(const vector<int>& v, map<int, string>* output));', 245 self.GenerateMethodSource(source)) 246 247 def testReturnTypeWithOneTemplateArg(self): 248 source = """ 249 class Foo { 250 public: 251 virtual vector<int>* Bar(int n); 252 };""" 253 self.assertEqualIgnoreLeadingWhitespace( 254 'MOCK_METHOD1(Bar,\nvector<int>*(int n));', 255 self.GenerateMethodSource(source)) 256 257 def testReturnTypeWithManyTemplateArgs(self): 258 source = """ 259 class Foo { 260 public: 261 virtual map<int, string> Bar(); 262 };""" 263 # Comparing the comment text is brittle - we'll think of something 264 # better in case this gets annoying, but for now let's keep it simple. 265 self.assertEqualIgnoreLeadingWhitespace( 266 '// The following line won\'t really compile, as the return\n' 267 '// type has multiple template arguments. To fix it, use a\n' 268 '// typedef for the return type.\n' 269 'MOCK_METHOD0(Bar,\nmap<int, string>());', 270 self.GenerateMethodSource(source)) 271 272 def testSimpleMethodInTemplatedClass(self): 273 source = """ 274 template<class T> 275 class Foo { 276 public: 277 virtual int Bar(); 278 }; 279 """ 280 self.assertEqualIgnoreLeadingWhitespace( 281 'MOCK_METHOD0_T(Bar,\nint());', 282 self.GenerateMethodSource(source)) 283 284 def testPointerArgWithoutNames(self): 285 source = """ 286 class Foo { 287 virtual int Bar(C*); 288 }; 289 """ 290 self.assertEqualIgnoreLeadingWhitespace( 291 'MOCK_METHOD1(Bar,\nint(C*));', 292 self.GenerateMethodSource(source)) 293 294 def testReferenceArgWithoutNames(self): 295 source = """ 296 class Foo { 297 virtual int Bar(C&); 298 }; 299 """ 300 self.assertEqualIgnoreLeadingWhitespace( 301 'MOCK_METHOD1(Bar,\nint(C&));', 302 self.GenerateMethodSource(source)) 303 304 def testArrayArgWithoutNames(self): 305 source = """ 306 class Foo { 307 virtual int Bar(C[]); 308 }; 309 """ 310 self.assertEqualIgnoreLeadingWhitespace( 311 'MOCK_METHOD1(Bar,\nint(C[]));', 312 self.GenerateMethodSource(source)) 313 314 315 class GenerateMocksTest(TestCase): 316 317 def GenerateMocks(self, cpp_source): 318 """Convert C++ source to complete Google Mock output source.""" 319 # <test> is a pseudo-filename, it is not read or written. 320 filename = '<test>' 321 builder = ast.BuilderFromSource(cpp_source, filename) 322 ast_list = list(builder.Generate()) 323 lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None) 324 return '\n'.join(lines) 325 326 def testNamespaces(self): 327 source = """ 328 namespace Foo { 329 namespace Bar { class Forward; } 330 namespace Baz { 331 332 class Test { 333 public: 334 virtual void Foo(); 335 }; 336 337 } // namespace Baz 338 } // namespace Foo 339 """ 340 expected = """\ 341 namespace Foo { 342 namespace Baz { 343 344 class MockTest : public Test { 345 public: 346 MOCK_METHOD0(Foo, 347 void()); 348 }; 349 350 } // namespace Baz 351 } // namespace Foo 352 """ 353 self.assertEqualIgnoreLeadingWhitespace( 354 expected, self.GenerateMocks(source)) 355 356 def testClassWithStorageSpecifierMacro(self): 357 source = """ 358 class STORAGE_SPECIFIER Test { 359 public: 360 virtual void Foo(); 361 }; 362 """ 363 expected = """\ 364 class MockTest : public Test { 365 public: 366 MOCK_METHOD0(Foo, 367 void()); 368 }; 369 """ 370 self.assertEqualIgnoreLeadingWhitespace( 371 expected, self.GenerateMocks(source)) 372 373 def testTemplatedForwardDeclaration(self): 374 source = """ 375 template <class T> class Forward; // Forward declaration should be ignored. 376 class Test { 377 public: 378 virtual void Foo(); 379 }; 380 """ 381 expected = """\ 382 class MockTest : public Test { 383 public: 384 MOCK_METHOD0(Foo, 385 void()); 386 }; 387 """ 388 self.assertEqualIgnoreLeadingWhitespace( 389 expected, self.GenerateMocks(source)) 390 391 def testTemplatedClass(self): 392 source = """ 393 template <typename S, typename T> 394 class Test { 395 public: 396 virtual void Foo(); 397 }; 398 """ 399 expected = """\ 400 template <typename T0, typename T1> 401 class MockTest : public Test<T0, T1> { 402 public: 403 MOCK_METHOD0_T(Foo, 404 void()); 405 }; 406 """ 407 self.assertEqualIgnoreLeadingWhitespace( 408 expected, self.GenerateMocks(source)) 409 410 def testTemplateInATemplateTypedef(self): 411 source = """ 412 class Test { 413 public: 414 typedef std::vector<std::list<int>> FooType; 415 virtual void Bar(const FooType& test_arg); 416 }; 417 """ 418 expected = """\ 419 class MockTest : public Test { 420 public: 421 MOCK_METHOD1(Bar, 422 void(const FooType& test_arg)); 423 }; 424 """ 425 self.assertEqualIgnoreLeadingWhitespace( 426 expected, self.GenerateMocks(source)) 427 428 def testTemplateInATemplateTypedefWithComma(self): 429 source = """ 430 class Test { 431 public: 432 typedef std::function<void( 433 const vector<std::list<int>>&, int> FooType; 434 virtual void Bar(const FooType& test_arg); 435 }; 436 """ 437 expected = """\ 438 class MockTest : public Test { 439 public: 440 MOCK_METHOD1(Bar, 441 void(const FooType& test_arg)); 442 }; 443 """ 444 self.assertEqualIgnoreLeadingWhitespace( 445 expected, self.GenerateMocks(source)) 446 447 def testEnumClass(self): 448 source = """ 449 class Test { 450 public: 451 enum class Baz { BAZINGA }; 452 virtual void Bar(const FooType& test_arg); 453 }; 454 """ 455 expected = """\ 456 class MockTest : public Test { 457 public: 458 MOCK_METHOD1(Bar, 459 void(const FooType& test_arg)); 460 }; 461 """ 462 self.assertEqualIgnoreLeadingWhitespace( 463 expected, self.GenerateMocks(source)) 464 465 if __name__ == '__main__': 466 unittest.main() 467