OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Unit tests for presubmit_support.py and presubmit_canned_checks.py.""" | 6 """Unit tests for presubmit_support.py and presubmit_canned_checks.py.""" |
7 | 7 |
8 # pylint: disable=E1101,E1103 | 8 # pylint: disable=E1101,E1103 |
9 | 9 |
10 import logging | 10 import logging |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 # SuperMoxTestBase already mock these but simplify our life. | 140 # SuperMoxTestBase already mock these but simplify our life. |
141 presubmit.os.path.abspath = MockAbsPath | 141 presubmit.os.path.abspath = MockAbsPath |
142 presubmit.os.getcwd = self.RootDir | 142 presubmit.os.getcwd = self.RootDir |
143 presubmit.os.chdir = MockChdir | 143 presubmit.os.chdir = MockChdir |
144 self.mox.StubOutWithMock(presubmit.scm, 'determine_scm') | 144 self.mox.StubOutWithMock(presubmit.scm, 'determine_scm') |
145 self.mox.StubOutWithMock(presubmit.scm.SVN, '_CaptureInfo') | 145 self.mox.StubOutWithMock(presubmit.scm.SVN, '_CaptureInfo') |
146 self.mox.StubOutWithMock(presubmit.scm.SVN, 'GetFileProperty') | 146 self.mox.StubOutWithMock(presubmit.scm.SVN, 'GetFileProperty') |
147 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileRead') | 147 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileRead') |
148 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileWrite') | 148 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileWrite') |
149 self.mox.StubOutWithMock(presubmit.scm.SVN, 'GenerateDiff') | 149 self.mox.StubOutWithMock(presubmit.scm.SVN, 'GenerateDiff') |
| 150 self.mox.StubOutWithMock(presubmit.scm.GIT, 'GenerateDiff') |
150 | 151 |
151 | 152 |
152 class PresubmitUnittest(PresubmitTestsBase): | 153 class PresubmitUnittest(PresubmitTestsBase): |
153 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" | 154 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" |
154 | 155 |
155 _INHERIT_SETTINGS = 'inherit-review-settings-ok' | 156 _INHERIT_SETTINGS = 'inherit-review-settings-ok' |
156 | 157 |
157 def testMembersChanged(self): | 158 def testMembersChanged(self): |
158 self.mox.ReplayAll() | 159 self.mox.ReplayAll() |
159 members = [ | 160 members = [ |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 self.assertEquals(rhs_lines[8][2], 'this is line number 23.1') | 379 self.assertEquals(rhs_lines[8][2], 'this is line number 23.1') |
379 | 380 |
380 self.assertEquals(rhs_lines[12][0].LocalPath(), files[3][1]) | 381 self.assertEquals(rhs_lines[12][0].LocalPath(), files[3][1]) |
381 self.assertEquals(rhs_lines[12][1], 46) | 382 self.assertEquals(rhs_lines[12][1], 46) |
382 self.assertEquals(rhs_lines[12][2], '') | 383 self.assertEquals(rhs_lines[12][2], '') |
383 | 384 |
384 self.assertEquals(rhs_lines[13][0].LocalPath(), files[3][1]) | 385 self.assertEquals(rhs_lines[13][0].LocalPath(), files[3][1]) |
385 self.assertEquals(rhs_lines[13][1], 49) | 386 self.assertEquals(rhs_lines[13][1], 49) |
386 self.assertEquals(rhs_lines[13][2], 'this is line number 48.1') | 387 self.assertEquals(rhs_lines[13][2], 'this is line number 48.1') |
387 | 388 |
| 389 def testGitChange(self): |
| 390 description_lines = ('Hello there', |
| 391 'this is a change', |
| 392 'BUG=123', |
| 393 ' STORY =http://foo/ \t', |
| 394 'and some more regular text \t') |
| 395 unified_diff = [ |
| 396 'diff --git binary_a.png binary_a.png', |
| 397 'new file mode 100644', |
| 398 'index 0000000..6fbdd6d', |
| 399 'Binary files /dev/null and binary_a.png differ', |
| 400 'diff --git binary_d.png binary_d.png', |
| 401 'deleted file mode 100644', |
| 402 'index 6fbdd6d..0000000', |
| 403 'Binary files binary_d.png and /dev/null differ', |
| 404 'diff --git binary_md.png binary_md.png', |
| 405 'index 6fbdd6..be3d5d8 100644', |
| 406 'GIT binary patch', |
| 407 'delta 109', |
| 408 'zcmeyihjs5>)(Opwi4&WXB~yyi6N|G`(i5|?i<2_a@)OH5N{Um`D-<SM@g!_^W9;SR', |
| 409 'zO9b*W5{pxTM0slZ=F42indK9U^MTyVQlJ2s%1BMmEKMv1Q^gtS&9nHn&*Ede;|~CU', |
| 410 'CMJxLN', |
| 411 '', |
| 412 'delta 34', |
| 413 'scmV+-0Nww+y#@BX1(1W0gkzIp3}CZh0gVZ>`wGVcgW(Rh;SK@ZPa9GXlK=n!', |
| 414 '', |
| 415 'diff --git binary_m.png binary_m.png', |
| 416 'index 6fbdd6d..be3d5d8 100644', |
| 417 'Binary files binary_m.png and binary_m.png differ', |
| 418 'diff --git boo/blat.cc boo/blat.cc', |
| 419 'new file mode 100644', |
| 420 'index 0000000..37d18ad', |
| 421 '--- boo/blat.cc', |
| 422 '+++ boo/blat.cc', |
| 423 '@@ -0,0 +1,5 @@', |
| 424 '+This is some text', |
| 425 '+which lacks a copyright warning', |
| 426 '+but it is nonetheless interesting', |
| 427 '+and worthy of your attention.', |
| 428 '+Its freshness factor is through the roof.', |
| 429 'diff --git floo/delburt.cc floo/delburt.cc', |
| 430 'deleted file mode 100644', |
| 431 'index e06377a..0000000', |
| 432 '--- floo/delburt.cc', |
| 433 '+++ /dev/null', |
| 434 '@@ -1,14 +0,0 @@', |
| 435 '-This text used to be here', |
| 436 '-but someone, probably you,', |
| 437 '-having consumed the text', |
| 438 '- (absorbed its meaning)', |
| 439 '-decided that it should be made to not exist', |
| 440 '-that others would not read it.', |
| 441 '- (What happened here?', |
| 442 '-was the author incompetent?', |
| 443 '-or is the world today so different from the world', |
| 444 '- the author foresaw', |
| 445 '-and past imaginination', |
| 446 '- amounts to rubble, insignificant,', |
| 447 '-something to be tripped over', |
| 448 '-and frustrated by)', |
| 449 'diff --git foo/TestExpectations foo/TestExpectations', |
| 450 'index c6e12ab..d1c5f23 100644', |
| 451 '--- foo/TestExpectations', |
| 452 '+++ foo/TestExpectations', |
| 453 '@@ -1,12 +1,24 @@', |
| 454 '-Stranger, behold:', |
| 455 '+Strange to behold:', |
| 456 ' This is a text', |
| 457 ' Its contents existed before.', |
| 458 '', |
| 459 '-It is written:', |
| 460 '+Weasel words suggest:', |
| 461 ' its contents shall exist after', |
| 462 ' and its contents', |
| 463 ' with the progress of time', |
| 464 ' will evolve,', |
| 465 '- snaillike,', |
| 466 '+ erratically,', |
| 467 ' into still different texts', |
| 468 '-from this.', |
| 469 '\ No newline at end of file', |
| 470 '+from this.', |
| 471 '+', |
| 472 '+For the most part,', |
| 473 '+I really think unified diffs', |
| 474 '+are elegant: the way you can type', |
| 475 '+diff --git inside/a/text inside/a/text', |
| 476 '+or something silly like', |
| 477 '+@@ -278,6 +278,10 @@', |
| 478 '+and have this not be interpreted', |
| 479 '+as the start of a new file', |
| 480 '+or anything messed up like that,', |
| 481 '+because you parsed the header', |
| 482 '+correctly.', |
| 483 '\ No newline at end of file', |
| 484 ''] |
| 485 files = [('A ', 'binary_a.png'), |
| 486 ('D ', 'binary_d.png'), |
| 487 ('M ', 'binary_m.png'), |
| 488 ('M ', 'binary_md.png'), # Binary w/ diff |
| 489 ('A ', 'boo/blat.cc'), |
| 490 ('D ', 'floo/delburt.cc'), |
| 491 ('M ', 'foo/TestExpectations')] |
| 492 |
| 493 for op, path in files: |
| 494 full_path = presubmit.os.path.join(self.fake_root_dir, *path.split('/')) |
| 495 if op.startswith('D'): |
| 496 os.path.exists(full_path).AndReturn(False) |
| 497 else: |
| 498 os.path.exists(full_path).AndReturn(False) |
| 499 os.path.isfile(full_path).AndReturn(True) |
| 500 |
| 501 presubmit.scm.GIT.GenerateDiff(self.fake_root_dir, files=[], full_move=True |
| 502 ).AndReturn('\n'.join(unified_diff)) |
| 503 |
| 504 self.mox.ReplayAll() |
| 505 |
| 506 change = presubmit.GitChange( |
| 507 'mychange', |
| 508 '\n'.join(description_lines), |
| 509 self.fake_root_dir, |
| 510 files, |
| 511 0, |
| 512 0, |
| 513 None) |
| 514 self.failUnless(change.Name() == 'mychange') |
| 515 self.failUnless(change.DescriptionText() == |
| 516 'Hello there\nthis is a change\nand some more regular text') |
| 517 self.failUnless(change.FullDescriptionText() == |
| 518 '\n'.join(description_lines)) |
| 519 |
| 520 self.failUnless(change.BUG == '123') |
| 521 self.failUnless(change.STORY == 'http://foo/') |
| 522 self.failUnless(change.BLEH == None) |
| 523 |
| 524 self.failUnless(len(change.AffectedFiles()) == 7) |
| 525 self.failUnless(len(change.AffectedFiles(include_dirs=True)) == 7) |
| 526 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 5) |
| 527 self.failUnless(len(change.AffectedFiles(include_dirs=True, |
| 528 include_deletes=False)) == 5) |
| 529 |
| 530 # Note that on git, there's no distinction between binary files and text |
| 531 # files; everything that's not a delete is a text file. |
| 532 affected_text_files = change.AffectedTextFiles() |
| 533 self.failUnless(len(affected_text_files) == 5) |
| 534 |
| 535 local_paths = change.LocalPaths() |
| 536 expected_paths = [os.path.normpath(f) for op, f in files] |
| 537 self.assertEqual(local_paths, expected_paths) |
| 538 |
| 539 try: |
| 540 _ = change.ServerPaths() |
| 541 self.fail("ServerPaths implemented.") |
| 542 except NotImplementedError: |
| 543 pass |
| 544 |
| 545 actual_rhs_lines = [] |
| 546 for f, linenum, line in change.RightHandSideLines(): |
| 547 actual_rhs_lines.append((f.LocalPath(), linenum, line)) |
| 548 |
| 549 f_blat = os.path.normpath('boo/blat.cc') |
| 550 f_test_expectations = os.path.normpath('foo/TestExpectations') |
| 551 expected_rhs_lines = [ |
| 552 (f_blat, 1, 'This is some text'), |
| 553 (f_blat, 2, 'which lacks a copyright warning'), |
| 554 (f_blat, 3, 'but it is nonetheless interesting'), |
| 555 (f_blat, 4, 'and worthy of your attention.'), |
| 556 (f_blat, 5, 'Its freshness factor is through the roof.'), |
| 557 (f_test_expectations, 1, 'Strange to behold:'), |
| 558 (f_test_expectations, 5, 'Weasel words suggest:'), |
| 559 (f_test_expectations, 10, ' erratically,'), |
| 560 (f_test_expectations, 13, 'from this.'), |
| 561 (f_test_expectations, 14, ''), |
| 562 (f_test_expectations, 15, 'For the most part,'), |
| 563 (f_test_expectations, 16, 'I really think unified diffs'), |
| 564 (f_test_expectations, 17, 'are elegant: the way you can type'), |
| 565 (f_test_expectations, 18, 'diff --git inside/a/text inside/a/text'), |
| 566 (f_test_expectations, 19, 'or something silly like'), |
| 567 (f_test_expectations, 20, '@@ -278,6 +278,10 @@'), |
| 568 (f_test_expectations, 21, 'and have this not be interpreted'), |
| 569 (f_test_expectations, 22, 'as the start of a new file'), |
| 570 (f_test_expectations, 23, 'or anything messed up like that,'), |
| 571 (f_test_expectations, 24, 'because you parsed the header'), |
| 572 (f_test_expectations, 25, 'correctly.')] |
| 573 |
| 574 self.assertEquals(expected_rhs_lines, actual_rhs_lines) |
| 575 |
388 def testInvalidChange(self): | 576 def testInvalidChange(self): |
389 try: | 577 try: |
390 presubmit.SvnChange( | 578 presubmit.SvnChange( |
391 'mychange', | 579 'mychange', |
392 'description', | 580 'description', |
393 self.fake_root_dir, | 581 self.fake_root_dir, |
394 ['foo/blat.cc', 'bar'], | 582 ['foo/blat.cc', 'bar'], |
395 0, | 583 0, |
396 0, | 584 0, |
397 None) | 585 None) |
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1244 self.mox.ReplayAll() | 1432 self.mox.ReplayAll() |
1245 | 1433 |
1246 change = presubmit.Change( | 1434 change = presubmit.Change( |
1247 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) | 1435 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) |
1248 input_api = presubmit.InputApi( | 1436 input_api = presubmit.InputApi( |
1249 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, | 1437 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, |
1250 None, False) | 1438 None, False) |
1251 input_api.ReadFile(path, 'x') | 1439 input_api.ReadFile(path, 'x') |
1252 | 1440 |
1253 def testReadFileAffectedFileDenied(self): | 1441 def testReadFileAffectedFileDenied(self): |
1254 fileobj = presubmit.AffectedFile('boo', 'M', 'Unrelated') | 1442 fileobj = presubmit.AffectedFile('boo', 'M', 'Unrelated', |
| 1443 diff_cache=mox.IsA(presubmit._DiffCache)) |
1255 self.mox.ReplayAll() | 1444 self.mox.ReplayAll() |
1256 | 1445 |
1257 change = presubmit.Change( | 1446 change = presubmit.Change( |
1258 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) | 1447 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) |
1259 input_api = presubmit.InputApi( | 1448 input_api = presubmit.InputApi( |
1260 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, | 1449 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, |
1261 None, False) | 1450 None, False) |
1262 self.assertRaises(IOError, input_api.ReadFile, fileobj, 'x') | 1451 self.assertRaises(IOError, input_api.ReadFile, fileobj, 'x') |
1263 | 1452 |
1264 def testReadFileAffectedFileAccepted(self): | 1453 def testReadFileAffectedFileAccepted(self): |
1265 fileobj = presubmit.AffectedFile('AA/boo', 'M', self.fake_root_dir) | 1454 fileobj = presubmit.AffectedFile('AA/boo', 'M', self.fake_root_dir, |
| 1455 diff_cache=mox.IsA(presubmit._DiffCache)) |
1266 presubmit.gclient_utils.FileRead(fileobj.AbsoluteLocalPath(), 'x' | 1456 presubmit.gclient_utils.FileRead(fileobj.AbsoluteLocalPath(), 'x' |
1267 ).AndReturn(None) | 1457 ).AndReturn(None) |
1268 self.mox.ReplayAll() | 1458 self.mox.ReplayAll() |
1269 | 1459 |
1270 change = presubmit.Change( | 1460 change = presubmit.Change( |
1271 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) | 1461 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) |
1272 input_api = presubmit.InputApi( | 1462 input_api = presubmit.InputApi( |
1273 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, | 1463 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, |
1274 None, False) | 1464 None, False) |
1275 input_api.ReadFile(fileobj, 'x') | 1465 input_api.ReadFile(fileobj, 'x') |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 self.failUnless(output.should_continue()) | 1541 self.failUnless(output.should_continue()) |
1352 self.failUnless(output.getvalue().count('???')) | 1542 self.failUnless(output.getvalue().count('???')) |
1353 | 1543 |
1354 output_api = presubmit.OutputApi(True) | 1544 output_api = presubmit.OutputApi(True) |
1355 output = presubmit.PresubmitOutput(input_stream=StringIO.StringIO('\n')) | 1545 output = presubmit.PresubmitOutput(input_stream=StringIO.StringIO('\n')) |
1356 output_api.PresubmitPromptOrNotify('???').handle(output) | 1546 output_api.PresubmitPromptOrNotify('???').handle(output) |
1357 output.prompt_yes_no('prompt: ') | 1547 output.prompt_yes_no('prompt: ') |
1358 self.failIf(output.should_continue()) | 1548 self.failIf(output.should_continue()) |
1359 self.failUnless(output.getvalue().count('???')) | 1549 self.failUnless(output.getvalue().count('???')) |
1360 | 1550 |
| 1551 |
1361 class AffectedFileUnittest(PresubmitTestsBase): | 1552 class AffectedFileUnittest(PresubmitTestsBase): |
1362 def testMembersChanged(self): | 1553 def testMembersChanged(self): |
1363 self.mox.ReplayAll() | 1554 self.mox.ReplayAll() |
1364 members = [ | 1555 members = [ |
1365 'AbsoluteLocalPath', 'Action', 'ChangedContents', 'GenerateScmDiff', | 1556 'AbsoluteLocalPath', 'Action', 'ChangedContents', 'DIFF_CACHE', |
1366 'IsDirectory', 'IsTextFile', 'LocalPath', 'NewContents', 'OldContents', | 1557 'GenerateScmDiff', 'IsDirectory', 'IsTextFile', 'LocalPath', |
1367 'OldFileTempPath', 'Property', 'ServerPath', | 1558 'NewContents', 'Property', 'ServerPath', |
1368 ] | 1559 ] |
1369 # If this test fails, you should add the relevant test. | 1560 # If this test fails, you should add the relevant test. |
1370 self.compareMembers( | 1561 self.compareMembers( |
1371 presubmit.AffectedFile('a', 'b', self.fake_root_dir), members) | 1562 presubmit.AffectedFile('a', 'b', self.fake_root_dir), members) |
1372 self.compareMembers( | 1563 self.compareMembers( |
1373 presubmit.SvnAffectedFile('a', 'b', self.fake_root_dir), members) | 1564 presubmit.SvnAffectedFile('a', 'b', self.fake_root_dir), members) |
| 1565 self.compareMembers( |
| 1566 presubmit.GitAffectedFile('a', 'b', self.fake_root_dir), members) |
1374 | 1567 |
1375 def testAffectedFile(self): | 1568 def testAffectedFile(self): |
1376 path = presubmit.os.path.join('foo', 'blat.cc') | 1569 path = presubmit.os.path.join('foo', 'blat.cc') |
1377 f_path = presubmit.os.path.join(self.fake_root_dir, path) | 1570 f_path = presubmit.os.path.join(self.fake_root_dir, path) |
1378 presubmit.os.path.exists(f_path).AndReturn(True) | 1571 presubmit.os.path.exists(f_path).AndReturn(True) |
1379 presubmit.os.path.isdir(f_path).AndReturn(False) | 1572 presubmit.os.path.isdir(f_path).AndReturn(False) |
1380 presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie') | 1573 presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie') |
1381 presubmit.scm.SVN._CaptureInfo([path], self.fake_root_dir).AndReturn( | 1574 presubmit.scm.SVN._CaptureInfo([path], self.fake_root_dir).AndReturn( |
1382 {'URL': 'svn:/foo/foo/blat.cc'}) | 1575 {'URL': 'svn:/foo/foo/blat.cc'}) |
1383 self.mox.ReplayAll() | 1576 self.mox.ReplayAll() |
(...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2531 owners_check=False) | 2724 owners_check=False) |
2532 self.assertEqual(1, len(results)) | 2725 self.assertEqual(1, len(results)) |
2533 self.assertEqual( | 2726 self.assertEqual( |
2534 'Found line ending with white spaces in:', results[0]._message) | 2727 'Found line ending with white spaces in:', results[0]._message) |
2535 self.checkstdout('') | 2728 self.checkstdout('') |
2536 | 2729 |
2537 | 2730 |
2538 if __name__ == '__main__': | 2731 if __name__ == '__main__': |
2539 import unittest | 2732 import unittest |
2540 unittest.main() | 2733 unittest.main() |
OLD | NEW |