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 20import os 21import sys 22import unittest 23 24# Allow the cpp imports below to work when run as a standalone script. 25sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 26 27from cpp import ast 28from cpp import gmock_class 29 30 31class TestCase(unittest.TestCase): 32 """Helper class that adds assert methods.""" 33 34 @staticmethod 35 def StripLeadingWhitespace(lines): 36 """Strip leading whitespace in each line in 'lines'.""" 37 return '\n'.join([s.lstrip() for s in lines.split('\n')]) 38 39 def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines): 40 """Specialized assert that ignores the indent level.""" 41 self.assertEqual(expected_lines, self.StripLeadingWhitespace(lines)) 42 43 44class GenerateMethodsTest(TestCase): 45 46 @staticmethod 47 def GenerateMethodSource(cpp_source): 48 """Convert C++ source to Google Mock output source lines.""" 49 method_source_lines = [] 50 # <test> is a pseudo-filename, it is not read or written. 51 builder = ast.BuilderFromSource(cpp_source, '<test>') 52 ast_list = list(builder.Generate()) 53 gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0]) 54 return '\n'.join(method_source_lines) 55 56 def testSimpleMethod(self): 57 source = """ 58class Foo { 59 public: 60 virtual int Bar(); 61}; 62""" 63 self.assertEqualIgnoreLeadingWhitespace( 64 'MOCK_METHOD0(Bar,\nint());', 65 self.GenerateMethodSource(source)) 66 67 def testSimpleConstructorsAndDestructor(self): 68 source = """ 69class Foo { 70 public: 71 Foo(); 72 Foo(int x); 73 Foo(const Foo& f); 74 Foo(Foo&& f); 75 ~Foo(); 76 virtual int Bar() = 0; 77}; 78""" 79 # The constructors and destructor should be ignored. 80 self.assertEqualIgnoreLeadingWhitespace( 81 'MOCK_METHOD0(Bar,\nint());', 82 self.GenerateMethodSource(source)) 83 84 def testVirtualDestructor(self): 85 source = """ 86class Foo { 87 public: 88 virtual ~Foo(); 89 virtual int Bar() = 0; 90}; 91""" 92 # The destructor should be ignored. 93 self.assertEqualIgnoreLeadingWhitespace( 94 'MOCK_METHOD0(Bar,\nint());', 95 self.GenerateMethodSource(source)) 96 97 def testExplicitlyDefaultedConstructorsAndDestructor(self): 98 source = """ 99class Foo { 100 public: 101 Foo() = default; 102 Foo(const Foo& f) = default; 103 Foo(Foo&& f) = default; 104 ~Foo() = default; 105 virtual int Bar() = 0; 106}; 107""" 108 # The constructors and destructor should be ignored. 109 self.assertEqualIgnoreLeadingWhitespace( 110 'MOCK_METHOD0(Bar,\nint());', 111 self.GenerateMethodSource(source)) 112 113 def testExplicitlyDeletedConstructorsAndDestructor(self): 114 source = """ 115class Foo { 116 public: 117 Foo() = delete; 118 Foo(const Foo& f) = delete; 119 Foo(Foo&& f) = delete; 120 ~Foo() = delete; 121 virtual int Bar() = 0; 122}; 123""" 124 # The constructors and destructor should be ignored. 125 self.assertEqualIgnoreLeadingWhitespace( 126 'MOCK_METHOD0(Bar,\nint());', 127 self.GenerateMethodSource(source)) 128 129 def testSimpleOverrideMethod(self): 130 source = """ 131class Foo { 132 public: 133 int Bar() override; 134}; 135""" 136 self.assertEqualIgnoreLeadingWhitespace( 137 'MOCK_METHOD0(Bar,\nint());', 138 self.GenerateMethodSource(source)) 139 140 def testSimpleConstMethod(self): 141 source = """ 142class Foo { 143 public: 144 virtual void Bar(bool flag) const; 145}; 146""" 147 self.assertEqualIgnoreLeadingWhitespace( 148 'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));', 149 self.GenerateMethodSource(source)) 150 151 def testExplicitVoid(self): 152 source = """ 153class Foo { 154 public: 155 virtual int Bar(void); 156}; 157""" 158 self.assertEqualIgnoreLeadingWhitespace( 159 'MOCK_METHOD0(Bar,\nint(void));', 160 self.GenerateMethodSource(source)) 161 162 def testStrangeNewlineInParameter(self): 163 source = """ 164class Foo { 165 public: 166 virtual void Bar(int 167a) = 0; 168}; 169""" 170 self.assertEqualIgnoreLeadingWhitespace( 171 'MOCK_METHOD1(Bar,\nvoid(int a));', 172 self.GenerateMethodSource(source)) 173 174 def testDefaultParameters(self): 175 source = """ 176class Foo { 177 public: 178 virtual void Bar(int a, char c = 'x') = 0; 179}; 180""" 181 self.assertEqualIgnoreLeadingWhitespace( 182 'MOCK_METHOD2(Bar,\nvoid(int a, char c ));', 183 self.GenerateMethodSource(source)) 184 185 def testMultipleDefaultParameters(self): 186 source = """ 187class Foo { 188 public: 189 virtual void Bar( 190 int a = 42, 191 char c = 'x', 192 const int* const p = nullptr, 193 const std::string& s = "42", 194 char tab[] = {'4','2'}, 195 int const *& rp = aDefaultPointer) = 0; 196}; 197""" 198 self.assertEqualIgnoreLeadingWhitespace( 199 "MOCK_METHOD7(Bar,\n" 200 "void(int a , char c , const int* const p , const std::string& s , char tab[] , int const *& rp ));", 201 self.GenerateMethodSource(source)) 202 203 def testConstDefaultParameter(self): 204 source = """ 205class Test { 206 public: 207 virtual bool Bar(const int test_arg = 42) = 0; 208}; 209""" 210 expected = 'MOCK_METHOD1(Bar,\nbool(const int test_arg ));' 211 self.assertEqualIgnoreLeadingWhitespace( 212 expected, self.GenerateMethodSource(source)) 213 214 def testConstRefDefaultParameter(self): 215 source = """ 216class Test { 217 public: 218 virtual bool Bar(const std::string& test_arg = "42" ) = 0; 219}; 220""" 221 expected = 'MOCK_METHOD1(Bar,\nbool(const std::string& test_arg ));' 222 self.assertEqualIgnoreLeadingWhitespace( 223 expected, self.GenerateMethodSource(source)) 224 225 def testRemovesCommentsWhenDefaultsArePresent(self): 226 source = """ 227class Foo { 228 public: 229 virtual void Bar(int a = 42 /* a comment */, 230 char /* other comment */ c= 'x') = 0; 231}; 232""" 233 self.assertEqualIgnoreLeadingWhitespace( 234 'MOCK_METHOD2(Bar,\nvoid(int a , char c));', 235 self.GenerateMethodSource(source)) 236 237 def testDoubleSlashCommentsInParameterListAreRemoved(self): 238 source = """ 239class Foo { 240 public: 241 virtual void Bar(int a, // inline comments should be elided. 242 int b // inline comments should be elided. 243 ) const = 0; 244}; 245""" 246 self.assertEqualIgnoreLeadingWhitespace( 247 'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));', 248 self.GenerateMethodSource(source)) 249 250 def testCStyleCommentsInParameterListAreNotRemoved(self): 251 # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these 252 # comments. Also note that C style comments after the last parameter 253 # are still elided. 254 source = """ 255class Foo { 256 public: 257 virtual const string& Bar(int /* keeper */, int b); 258}; 259""" 260 self.assertEqualIgnoreLeadingWhitespace( 261 'MOCK_METHOD2(Bar,\nconst string&(int , int b));', 262 self.GenerateMethodSource(source)) 263 264 def testArgsOfTemplateTypes(self): 265 source = """ 266class Foo { 267 public: 268 virtual int Bar(const vector<int>& v, map<int, string>* output); 269};""" 270 self.assertEqualIgnoreLeadingWhitespace( 271 'MOCK_METHOD2(Bar,\n' 272 'int(const vector<int>& v, map<int, string>* output));', 273 self.GenerateMethodSource(source)) 274 275 def testReturnTypeWithOneTemplateArg(self): 276 source = """ 277class Foo { 278 public: 279 virtual vector<int>* Bar(int n); 280};""" 281 self.assertEqualIgnoreLeadingWhitespace( 282 'MOCK_METHOD1(Bar,\nvector<int>*(int n));', 283 self.GenerateMethodSource(source)) 284 285 def testReturnTypeWithManyTemplateArgs(self): 286 source = """ 287class Foo { 288 public: 289 virtual map<int, string> Bar(); 290};""" 291 # Comparing the comment text is brittle - we'll think of something 292 # better in case this gets annoying, but for now let's keep it simple. 293 self.assertEqualIgnoreLeadingWhitespace( 294 '// The following line won\'t really compile, as the return\n' 295 '// type has multiple template arguments. To fix it, use a\n' 296 '// typedef for the return type.\n' 297 'MOCK_METHOD0(Bar,\nmap<int, string>());', 298 self.GenerateMethodSource(source)) 299 300 def testSimpleMethodInTemplatedClass(self): 301 source = """ 302template<class T> 303class Foo { 304 public: 305 virtual int Bar(); 306}; 307""" 308 self.assertEqualIgnoreLeadingWhitespace( 309 'MOCK_METHOD0_T(Bar,\nint());', 310 self.GenerateMethodSource(source)) 311 312 def testPointerArgWithoutNames(self): 313 source = """ 314class Foo { 315 virtual int Bar(C*); 316}; 317""" 318 self.assertEqualIgnoreLeadingWhitespace( 319 'MOCK_METHOD1(Bar,\nint(C*));', 320 self.GenerateMethodSource(source)) 321 322 def testReferenceArgWithoutNames(self): 323 source = """ 324class Foo { 325 virtual int Bar(C&); 326}; 327""" 328 self.assertEqualIgnoreLeadingWhitespace( 329 'MOCK_METHOD1(Bar,\nint(C&));', 330 self.GenerateMethodSource(source)) 331 332 def testArrayArgWithoutNames(self): 333 source = """ 334class Foo { 335 virtual int Bar(C[]); 336}; 337""" 338 self.assertEqualIgnoreLeadingWhitespace( 339 'MOCK_METHOD1(Bar,\nint(C[]));', 340 self.GenerateMethodSource(source)) 341 342 343class GenerateMocksTest(TestCase): 344 345 @staticmethod 346 def GenerateMocks(cpp_source): 347 """Convert C++ source to complete Google Mock output source.""" 348 # <test> is a pseudo-filename, it is not read or written. 349 filename = '<test>' 350 builder = ast.BuilderFromSource(cpp_source, filename) 351 ast_list = list(builder.Generate()) 352 lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None) 353 return '\n'.join(lines) 354 355 def testNamespaces(self): 356 source = """ 357namespace Foo { 358namespace Bar { class Forward; } 359namespace Baz { 360 361class Test { 362 public: 363 virtual void Foo(); 364}; 365 366} // namespace Baz 367} // namespace Foo 368""" 369 expected = """\ 370namespace Foo { 371namespace Baz { 372 373class MockTest : public Test { 374public: 375MOCK_METHOD0(Foo, 376void()); 377}; 378 379} // namespace Baz 380} // namespace Foo 381""" 382 self.assertEqualIgnoreLeadingWhitespace( 383 expected, self.GenerateMocks(source)) 384 385 def testClassWithStorageSpecifierMacro(self): 386 source = """ 387class STORAGE_SPECIFIER Test { 388 public: 389 virtual void Foo(); 390}; 391""" 392 expected = """\ 393class MockTest : public Test { 394public: 395MOCK_METHOD0(Foo, 396void()); 397}; 398""" 399 self.assertEqualIgnoreLeadingWhitespace( 400 expected, self.GenerateMocks(source)) 401 402 def testTemplatedForwardDeclaration(self): 403 source = """ 404template <class T> class Forward; // Forward declaration should be ignored. 405class Test { 406 public: 407 virtual void Foo(); 408}; 409""" 410 expected = """\ 411class MockTest : public Test { 412public: 413MOCK_METHOD0(Foo, 414void()); 415}; 416""" 417 self.assertEqualIgnoreLeadingWhitespace( 418 expected, self.GenerateMocks(source)) 419 420 def testTemplatedClass(self): 421 source = """ 422template <typename S, typename T> 423class Test { 424 public: 425 virtual void Foo(); 426}; 427""" 428 expected = """\ 429template <typename T0, typename T1> 430class MockTest : public Test<T0, T1> { 431public: 432MOCK_METHOD0_T(Foo, 433void()); 434}; 435""" 436 self.assertEqualIgnoreLeadingWhitespace( 437 expected, self.GenerateMocks(source)) 438 439 def testTemplateInATemplateTypedef(self): 440 source = """ 441class Test { 442 public: 443 typedef std::vector<std::list<int>> FooType; 444 virtual void Bar(const FooType& test_arg); 445}; 446""" 447 expected = """\ 448class MockTest : public Test { 449public: 450MOCK_METHOD1(Bar, 451void(const FooType& test_arg)); 452}; 453""" 454 self.assertEqualIgnoreLeadingWhitespace( 455 expected, self.GenerateMocks(source)) 456 457 def testTemplateInATemplateTypedefWithComma(self): 458 source = """ 459class Test { 460 public: 461 typedef std::function<void( 462 const vector<std::list<int>>&, int> FooType; 463 virtual void Bar(const FooType& test_arg); 464}; 465""" 466 expected = """\ 467class MockTest : public Test { 468public: 469MOCK_METHOD1(Bar, 470void(const FooType& test_arg)); 471}; 472""" 473 self.assertEqualIgnoreLeadingWhitespace( 474 expected, self.GenerateMocks(source)) 475 476 def testEnumType(self): 477 source = """ 478class Test { 479 public: 480 enum Bar { 481 BAZ, QUX, QUUX, QUUUX 482 }; 483 virtual void Foo(); 484}; 485""" 486 expected = """\ 487class MockTest : public Test { 488public: 489MOCK_METHOD0(Foo, 490void()); 491}; 492""" 493 self.assertEqualIgnoreLeadingWhitespace( 494 expected, self.GenerateMocks(source)) 495 496 def testEnumClassType(self): 497 source = """ 498class Test { 499 public: 500 enum class Bar { 501 BAZ, QUX, QUUX, QUUUX 502 }; 503 virtual void Foo(); 504}; 505""" 506 expected = """\ 507class MockTest : public Test { 508public: 509MOCK_METHOD0(Foo, 510void()); 511}; 512""" 513 self.assertEqualIgnoreLeadingWhitespace( 514 expected, self.GenerateMocks(source)) 515 516 def testStdFunction(self): 517 source = """ 518class Test { 519 public: 520 Test(std::function<int(std::string)> foo) : foo_(foo) {} 521 522 virtual std::function<int(std::string)> foo(); 523 524 private: 525 std::function<int(std::string)> foo_; 526}; 527""" 528 expected = """\ 529class MockTest : public Test { 530public: 531MOCK_METHOD0(foo, 532std::function<int (std::string)>()); 533}; 534""" 535 self.assertEqualIgnoreLeadingWhitespace( 536 expected, self.GenerateMocks(source)) 537 538 539if __name__ == '__main__': 540 unittest.main() 541