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_METHOD(int, Bar, (), (override));', 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_METHOD(int, Bar, (), (override));', 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_METHOD(int, Bar, (), (override));', 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_METHOD(int, Bar, (), (override));', 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_METHOD(int, Bar, (), (override));', 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_METHOD(int, Bar, (), (override));', 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_METHOD(void, Bar, (bool flag), (const, override));', 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_METHOD(int, Bar, (), (override));', 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_METHOD(void, Bar, (int a), (override));', 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_METHOD(void, Bar, (int a, char c), (override));', 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_METHOD(void, Bar, ' 200 '(int a, char c, const int* const p, const std::string& s, char tab[], int const *& rp), ' 201 '(override));', self.GenerateMethodSource(source)) 202 203 def testMultipleSingleLineDefaultParameters(self): 204 source = """ 205class Foo { 206 public: 207 virtual void Bar(int a = 42, int b = 43, int c = 44) = 0; 208}; 209""" 210 self.assertEqualIgnoreLeadingWhitespace( 211 'MOCK_METHOD(void, Bar, (int a, int b, int c), (override));', 212 self.GenerateMethodSource(source)) 213 214 def testConstDefaultParameter(self): 215 source = """ 216class Test { 217 public: 218 virtual bool Bar(const int test_arg = 42) = 0; 219}; 220""" 221 self.assertEqualIgnoreLeadingWhitespace( 222 'MOCK_METHOD(bool, Bar, (const int test_arg), (override));', 223 self.GenerateMethodSource(source)) 224 225 def testConstRefDefaultParameter(self): 226 source = """ 227class Test { 228 public: 229 virtual bool Bar(const std::string& test_arg = "42" ) = 0; 230}; 231""" 232 self.assertEqualIgnoreLeadingWhitespace( 233 'MOCK_METHOD(bool, Bar, (const std::string& test_arg), (override));', 234 self.GenerateMethodSource(source)) 235 236 def testRemovesCommentsWhenDefaultsArePresent(self): 237 source = """ 238class Foo { 239 public: 240 virtual void Bar(int a = 42 /* a comment */, 241 char /* other comment */ c= 'x') = 0; 242}; 243""" 244 self.assertEqualIgnoreLeadingWhitespace( 245 'MOCK_METHOD(void, Bar, (int a, char c), (override));', 246 self.GenerateMethodSource(source)) 247 248 def testDoubleSlashCommentsInParameterListAreRemoved(self): 249 source = """ 250class Foo { 251 public: 252 virtual void Bar(int a, // inline comments should be elided. 253 int b // inline comments should be elided. 254 ) const = 0; 255}; 256""" 257 self.assertEqualIgnoreLeadingWhitespace( 258 'MOCK_METHOD(void, Bar, (int a, int b), (const, override));', 259 self.GenerateMethodSource(source)) 260 261 def testCStyleCommentsInParameterListAreNotRemoved(self): 262 # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these 263 # comments. Also note that C style comments after the last parameter 264 # are still elided. 265 source = """ 266class Foo { 267 public: 268 virtual const string& Bar(int /* keeper */, int b); 269}; 270""" 271 self.assertEqualIgnoreLeadingWhitespace( 272 'MOCK_METHOD(const string&, Bar, (int, int b), (override));', 273 self.GenerateMethodSource(source)) 274 275 def testArgsOfTemplateTypes(self): 276 source = """ 277class Foo { 278 public: 279 virtual int Bar(const vector<int>& v, map<int, string>* output); 280};""" 281 self.assertEqualIgnoreLeadingWhitespace( 282 'MOCK_METHOD(int, Bar, (const vector<int>& v, (map<int, string>* output)), (override));', 283 self.GenerateMethodSource(source)) 284 285 def testReturnTypeWithOneTemplateArg(self): 286 source = """ 287class Foo { 288 public: 289 virtual vector<int>* Bar(int n); 290};""" 291 self.assertEqualIgnoreLeadingWhitespace( 292 'MOCK_METHOD(vector<int>*, Bar, (int n), (override));', 293 self.GenerateMethodSource(source)) 294 295 def testReturnTypeWithManyTemplateArgs(self): 296 source = """ 297class Foo { 298 public: 299 virtual map<int, string> Bar(); 300};""" 301 self.assertEqualIgnoreLeadingWhitespace( 302 'MOCK_METHOD((map<int, string>), Bar, (), (override));', 303 self.GenerateMethodSource(source)) 304 305 def testSimpleMethodInTemplatedClass(self): 306 source = """ 307template<class T> 308class Foo { 309 public: 310 virtual int Bar(); 311}; 312""" 313 self.assertEqualIgnoreLeadingWhitespace( 314 'MOCK_METHOD(int, Bar, (), (override));', 315 self.GenerateMethodSource(source)) 316 317 def testPointerArgWithoutNames(self): 318 source = """ 319class Foo { 320 virtual int Bar(C*); 321}; 322""" 323 self.assertEqualIgnoreLeadingWhitespace( 324 'MOCK_METHOD(int, Bar, (C*), (override));', 325 self.GenerateMethodSource(source)) 326 327 def testReferenceArgWithoutNames(self): 328 source = """ 329class Foo { 330 virtual int Bar(C&); 331}; 332""" 333 self.assertEqualIgnoreLeadingWhitespace( 334 'MOCK_METHOD(int, Bar, (C&), (override));', 335 self.GenerateMethodSource(source)) 336 337 def testArrayArgWithoutNames(self): 338 source = """ 339class Foo { 340 virtual int Bar(C[]); 341}; 342""" 343 self.assertEqualIgnoreLeadingWhitespace( 344 'MOCK_METHOD(int, Bar, (C[]), (override));', 345 self.GenerateMethodSource(source)) 346 347 348class GenerateMocksTest(TestCase): 349 350 @staticmethod 351 def GenerateMocks(cpp_source): 352 """Convert C++ source to complete Google Mock output source.""" 353 # <test> is a pseudo-filename, it is not read or written. 354 filename = '<test>' 355 builder = ast.BuilderFromSource(cpp_source, filename) 356 ast_list = list(builder.Generate()) 357 lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None) 358 return '\n'.join(lines) 359 360 def testNamespaces(self): 361 source = """ 362namespace Foo { 363namespace Bar { class Forward; } 364namespace Baz::Qux { 365 366class Test { 367 public: 368 virtual void Foo(); 369}; 370 371} // namespace Baz::Qux 372} // namespace Foo 373""" 374 expected = """\ 375namespace Foo { 376namespace Baz::Qux { 377 378class MockTest : public Test { 379public: 380MOCK_METHOD(void, Foo, (), (override)); 381}; 382 383} // namespace Baz::Qux 384} // namespace Foo 385""" 386 self.assertEqualIgnoreLeadingWhitespace(expected, 387 self.GenerateMocks(source)) 388 389 def testClassWithStorageSpecifierMacro(self): 390 source = """ 391class STORAGE_SPECIFIER Test { 392 public: 393 virtual void Foo(); 394}; 395""" 396 expected = """\ 397class MockTest : public Test { 398public: 399MOCK_METHOD(void, Foo, (), (override)); 400}; 401""" 402 self.assertEqualIgnoreLeadingWhitespace(expected, 403 self.GenerateMocks(source)) 404 405 def testTemplatedForwardDeclaration(self): 406 source = """ 407template <class T> class Forward; // Forward declaration should be ignored. 408class Test { 409 public: 410 virtual void Foo(); 411}; 412""" 413 expected = """\ 414class MockTest : public Test { 415public: 416MOCK_METHOD(void, Foo, (), (override)); 417}; 418""" 419 self.assertEqualIgnoreLeadingWhitespace(expected, 420 self.GenerateMocks(source)) 421 422 def testTemplatedClass(self): 423 source = """ 424template <typename S, typename T> 425class Test { 426 public: 427 virtual void Foo(); 428}; 429""" 430 expected = """\ 431template <typename S, typename T> 432class MockTest : public Test<S, T> { 433public: 434MOCK_METHOD(void, Foo, (), (override)); 435}; 436""" 437 self.assertEqualIgnoreLeadingWhitespace(expected, 438 self.GenerateMocks(source)) 439 440 def testTemplateInATemplateTypedef(self): 441 source = """ 442class Test { 443 public: 444 typedef std::vector<std::list<int>> FooType; 445 virtual void Bar(const FooType& test_arg); 446}; 447""" 448 expected = """\ 449class MockTest : public Test { 450public: 451MOCK_METHOD(void, Bar, (const FooType& test_arg), (override)); 452}; 453""" 454 self.assertEqualIgnoreLeadingWhitespace(expected, 455 self.GenerateMocks(source)) 456 457 def testTemplatedClassWithTemplatedArguments(self): 458 source = """ 459template <typename S, typename T, typename U, typename V, typename W> 460class Test { 461 public: 462 virtual U Foo(T some_arg); 463}; 464""" 465 expected = """\ 466template <typename S, typename T, typename U, typename V, typename W> 467class MockTest : public Test<S, T, U, V, W> { 468public: 469MOCK_METHOD(U, Foo, (T some_arg), (override)); 470}; 471""" 472 self.assertEqualIgnoreLeadingWhitespace(expected, 473 self.GenerateMocks(source)) 474 475 def testTemplateInATemplateTypedefWithComma(self): 476 source = """ 477class Test { 478 public: 479 typedef std::function<void( 480 const vector<std::list<int>>&, int> FooType; 481 virtual void Bar(const FooType& test_arg); 482}; 483""" 484 expected = """\ 485class MockTest : public Test { 486public: 487MOCK_METHOD(void, Bar, (const FooType& test_arg), (override)); 488}; 489""" 490 self.assertEqualIgnoreLeadingWhitespace(expected, 491 self.GenerateMocks(source)) 492 493 def testParenthesizedCommaInArg(self): 494 source = """ 495class Test { 496 public: 497 virtual void Bar(std::function<void(int, int)> f); 498}; 499""" 500 expected = """\ 501class MockTest : public Test { 502public: 503MOCK_METHOD(void, Bar, (std::function<void(int, int)> f), (override)); 504}; 505""" 506 self.assertEqualIgnoreLeadingWhitespace(expected, 507 self.GenerateMocks(source)) 508 509 def testEnumType(self): 510 source = """ 511class Test { 512 public: 513 enum Bar { 514 BAZ, QUX, QUUX, QUUUX 515 }; 516 virtual void Foo(); 517}; 518""" 519 expected = """\ 520class MockTest : public Test { 521public: 522MOCK_METHOD(void, Foo, (), (override)); 523}; 524""" 525 self.assertEqualIgnoreLeadingWhitespace(expected, 526 self.GenerateMocks(source)) 527 528 def testEnumClassType(self): 529 source = """ 530class Test { 531 public: 532 enum class Bar { 533 BAZ, QUX, QUUX, QUUUX 534 }; 535 virtual void Foo(); 536}; 537""" 538 expected = """\ 539class MockTest : public Test { 540public: 541MOCK_METHOD(void, Foo, (), (override)); 542}; 543""" 544 self.assertEqualIgnoreLeadingWhitespace(expected, 545 self.GenerateMocks(source)) 546 547 def testStdFunction(self): 548 source = """ 549class Test { 550 public: 551 Test(std::function<int(std::string)> foo) : foo_(foo) {} 552 553 virtual std::function<int(std::string)> foo(); 554 555 private: 556 std::function<int(std::string)> foo_; 557}; 558""" 559 expected = """\ 560class MockTest : public Test { 561public: 562MOCK_METHOD(std::function<int (std::string)>, foo, (), (override)); 563}; 564""" 565 self.assertEqualIgnoreLeadingWhitespace(expected, 566 self.GenerateMocks(source)) 567 568 569if __name__ == '__main__': 570 unittest.main() 571