OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 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 import os | 8 import os |
9 import StringIO | 9 import StringIO |
10 import sys | 10 import sys |
11 import unittest | 11 import unittest |
12 import warnings | |
13 | 12 |
14 # Local imports | 13 # Local imports |
15 import __init__ | 14 import __init__ |
16 import gcl | 15 import gcl |
17 import gclient | 16 import gclient |
18 import presubmit_support as presubmit | 17 import presubmit_support as presubmit |
19 import presubmit_canned_checks | 18 import presubmit_canned_checks |
20 mox = __init__.mox | 19 mox = __init__.mox |
21 | 20 |
22 | 21 |
23 class PresubmitTestsBase(unittest.TestCase): | 22 class PresubmitTestsBase(mox.MoxTestBase): |
24 """Setups and tear downs the mocks but doesn't test anything as-is.""" | 23 """Setups and tear downs the mocks but doesn't test anything as-is.""" |
25 def setUp(self): | 24 def setUp(self): |
26 if hasattr(warnings, 'catch_warnings'): | 25 super(PresubmitTestsBase, self).setUp() |
27 self._warnings_stack = warnings.catch_warnings() | 26 self.mox.StubOutWithMock(presubmit, 'warnings') |
28 else: | |
29 self._warnings_stack = None | |
30 warnings.simplefilter("ignore", DeprecationWarning) | |
31 self.mox = mox.Mox() | |
32 self.original_IsFile = os.path.isfile | 27 self.original_IsFile = os.path.isfile |
33 def MockIsFile(f): | 28 def MockIsFile(f): |
34 dir = os.path.dirname(f) | 29 dir = os.path.dirname(f) |
35 return dir.endswith('haspresubmit') or dir == '' | 30 return dir.endswith('haspresubmit') or dir == '' |
36 os.path.isfile = MockIsFile | 31 os.path.isfile = MockIsFile |
37 | 32 |
38 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo | 33 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo |
39 def MockCaptureSVNInfo(path): | 34 def MockCaptureSVNInfo(path): |
40 if path.count('notfound'): | 35 if path.count('notfound'): |
41 return {} | 36 return {} |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 | 95 |
101 def tearDown(self): | 96 def tearDown(self): |
102 os.path.isfile = self.original_IsFile | 97 os.path.isfile = self.original_IsFile |
103 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo | 98 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo |
104 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty | 99 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty |
105 gcl.ReadFile = self.original_ReadFile | 100 gcl.ReadFile = self.original_ReadFile |
106 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot | 101 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot |
107 sys.stdout = self._sys_stdout | 102 sys.stdout = self._sys_stdout |
108 os.path.exists = self._os_path_exists | 103 os.path.exists = self._os_path_exists |
109 os.path.isdir = self._os_path_isdir | 104 os.path.isdir = self._os_path_isdir |
110 self._warnings_stack = None | |
111 | 105 |
112 @staticmethod | 106 @staticmethod |
113 def MakeBasicChange(name, description): | 107 def MakeBasicChange(name, description): |
114 ci = gcl.ChangeInfo(name=name, | 108 ci = gcl.ChangeInfo(name=name, |
115 description=description, | 109 description=description, |
116 files=[]) | 110 files=[]) |
117 change = presubmit.GclChange(ci) | 111 change = presubmit.GclChange(ci) |
118 return change | 112 return change |
119 | 113 |
120 def compareMembers(self, object, members): | 114 def compareMembers(self, object, members): |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 | 188 |
195 self.failUnless(change.BUG == '123') | 189 self.failUnless(change.BUG == '123') |
196 self.failUnless(change.STORY == 'http://foo/') | 190 self.failUnless(change.STORY == 'http://foo/') |
197 | 191 |
198 self.failUnless(len(change.AffectedFiles()) == 4) | 192 self.failUnless(len(change.AffectedFiles()) == 4) |
199 self.failUnless(len(change.AffectedFiles(include_dirs=True)) == 5) | 193 self.failUnless(len(change.AffectedFiles(include_dirs=True)) == 5) |
200 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 3) | 194 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 3) |
201 self.failUnless(len(change.AffectedFiles(include_dirs=True, | 195 self.failUnless(len(change.AffectedFiles(include_dirs=True, |
202 include_deletes=False)) == 4) | 196 include_deletes=False)) == 4) |
203 | 197 |
204 affected_text_files = change.AffectedTextFiles(include_deletes=True) | 198 affected_text_files = change.AffectedTextFiles() |
205 self.failUnless(len(affected_text_files) == 3) | 199 self.failUnless(len(affected_text_files) == 2) |
206 self.failIf(filter(lambda x: x.LocalPath() == 'binary.dll', | 200 self.failIf(filter(lambda x: x.LocalPath() == 'binary.dll', |
207 affected_text_files)) | 201 affected_text_files)) |
208 | 202 |
209 local_paths = change.LocalPaths() | 203 local_paths = change.LocalPaths() |
210 expected_paths = [presubmit.normpath(f[1]) for f in files] | 204 expected_paths = [presubmit.normpath(f[1]) for f in files] |
211 self.failUnless( | 205 self.failUnless( |
212 len(filter(lambda x: x in expected_paths, local_paths)) == 4) | 206 len(filter(lambda x: x in expected_paths, local_paths)) == 4) |
213 | 207 |
214 server_paths = change.ServerPaths() | 208 server_paths = change.ServerPaths() |
215 expected_paths = ['svn:/foo/%s' % f[1] for f in files if | 209 expected_paths = ['svn:/foo/%s' % f[1] for f in files if |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 'Running default presubmit script.\n\n' | 457 'Running default presubmit script.\n\n' |
464 '** Presubmit Messages **\n\n' | 458 '** Presubmit Messages **\n\n' |
465 'http://tracker.com/42\n\n')) | 459 'http://tracker.com/42\n\n')) |
466 | 460 |
467 | 461 |
468 class InputApiUnittest(PresubmitTestsBase): | 462 class InputApiUnittest(PresubmitTestsBase): |
469 """Tests presubmit.InputApi.""" | 463 """Tests presubmit.InputApi.""" |
470 def testMembersChanged(self): | 464 def testMembersChanged(self): |
471 members = [ | 465 members = [ |
472 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', | 466 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', |
473 'DepotToLocalPath', 'FilterTextFiles', 'LocalPaths', 'LocalToDepotPath', | 467 'DepotToLocalPath', 'LocalPaths', 'LocalToDepotPath', |
474 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', | 468 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', |
475 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', | 469 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', |
476 'marshal', 'os_path', 'pickle', 'platform', | 470 'marshal', 'os_path', 'pickle', 'platform', |
477 're', 'subprocess', 'tempfile', 'urllib2', 'version', | 471 're', 'subprocess', 'tempfile', 'urllib2', 'version', |
478 ] | 472 ] |
479 # If this test fails, you should add the relevant test. | 473 # If this test fails, you should add the relevant test. |
480 self.compareMembers(presubmit.InputApi(None, './.'), members) | 474 self.compareMembers(presubmit.InputApi(None, './.'), members) |
481 | 475 |
482 def testDepotToLocalPath(self): | 476 def testDepotToLocalPath(self): |
483 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn:/foo/smurf') | 477 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn:/foo/smurf') |
484 self.failUnless(path == 'smurf') | 478 self.failUnless(path == 'smurf') |
485 path = presubmit.InputApi(None, './p').DepotToLocalPath( | 479 path = presubmit.InputApi(None, './p').DepotToLocalPath( |
486 'svn:/foo/notfound/burp') | 480 'svn:/foo/notfound/burp') |
487 self.failUnless(path == None) | 481 self.failUnless(path == None) |
488 | 482 |
489 def testLocalToDepotPath(self): | 483 def testLocalToDepotPath(self): |
490 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') | 484 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') |
491 self.failUnless(path == 'svn:/foo/smurf') | 485 self.failUnless(path == 'svn:/foo/smurf') |
492 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') | 486 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') |
493 self.failUnless(path == None) | 487 self.failUnless(path == None) |
494 | 488 |
495 def testInputApiConstruction(self): | 489 def testInputApiConstruction(self): |
496 # Fudge the change object, it's not used during construction anyway | 490 # Fudge the change object, it's not used during construction anyway |
497 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') | 491 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') |
498 self.failUnless(api.PresubmitLocalPath() == 'foo/path') | 492 self.failUnless(api.PresubmitLocalPath() == 'foo/path') |
499 self.failUnless(api.change == 42) | 493 self.failUnless(api.change == 42) |
500 | 494 |
501 def testFilterTextFiles(self): | |
502 class MockAffectedFile(object): | |
503 def __init__(self, path, action): | |
504 self.path = path | |
505 self.action = action | |
506 def Action(self): | |
507 return self.action | |
508 def LocalPath(self): | |
509 return self.path | |
510 def AbsoluteLocalPath(self): | |
511 return self.path | |
512 | |
513 list = [MockAffectedFile('foo/blat.txt', 'M'), | |
514 MockAffectedFile('foo/binary.blob', 'M'), | |
515 MockAffectedFile('blat/flop.txt', 'D')] | |
516 | |
517 output = presubmit.InputApi.FilterTextFiles(list, include_deletes=True) | |
518 self.failUnless(len(output) == 2) | |
519 self.failUnless(list[0] in output and list[2] in output) | |
520 | |
521 output = presubmit.InputApi.FilterTextFiles(list, include_deletes=False) | |
522 self.failUnless(len(output) == 1) | |
523 self.failUnless(list[0] in output) | |
524 | |
525 def testInputApiPresubmitScriptFiltering(self): | 495 def testInputApiPresubmitScriptFiltering(self): |
526 description_lines = ('Hello there', | 496 description_lines = ('Hello there', |
527 'this is a change', | 497 'this is a change', |
528 'BUG=123', | 498 'BUG=123', |
529 ' STORY =http://foo/ \t', | 499 ' STORY =http://foo/ \t', |
530 'and some more regular text') | 500 'and some more regular text') |
531 files = [ | 501 files = [ |
532 ['A', os.path.join('foo', 'blat.cc')], | 502 ['A', os.path.join('foo', 'blat.cc')], |
533 ['M', os.path.join('foo', 'blat', 'binary.dll')], | 503 ['M', os.path.join('foo', 'blat', 'binary.dll')], |
534 ['D', 'foo/mat/beingdeleted.txt'], | 504 ['D', 'foo/mat/beingdeleted.txt'], |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 # New helper functions need to work | 571 # New helper functions need to work |
602 absolute_paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) | 572 absolute_paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) |
603 api = presubmit.InputApi(change=change, presubmit_path='isdir/PRESUBMIT.py') | 573 api = presubmit.InputApi(change=change, presubmit_path='isdir/PRESUBMIT.py') |
604 absolute_paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) | 574 absolute_paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) |
605 for absolute_paths in [absolute_paths_from_change, | 575 for absolute_paths in [absolute_paths_from_change, |
606 absolute_paths_from_api]: | 576 absolute_paths_from_api]: |
607 self.failUnless(absolute_paths[0] == presubmit.normpath('c:/temp/isdir')) | 577 self.failUnless(absolute_paths[0] == presubmit.normpath('c:/temp/isdir')) |
608 self.failUnless(absolute_paths[1] == | 578 self.failUnless(absolute_paths[1] == |
609 presubmit.normpath('c:/temp/isdir/blat.cc')) | 579 presubmit.normpath('c:/temp/isdir/blat.cc')) |
610 | 580 |
| 581 def testDeprecated(self): |
| 582 presubmit.warnings.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), |
| 583 stacklevel=2) |
| 584 self.mox.ReplayAll() |
| 585 change = presubmit.GclChange(gcl.ChangeInfo(name='mychange', |
| 586 description='Bleh\n')) |
| 587 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') |
| 588 api.AffectedTextFiles(include_deletes=False) |
| 589 self.mox.VerifyAll() |
| 590 |
611 | 591 |
612 class OuputApiUnittest(PresubmitTestsBase): | 592 class OuputApiUnittest(PresubmitTestsBase): |
613 """Tests presubmit.OutputApi.""" | 593 """Tests presubmit.OutputApi.""" |
614 def testMembersChanged(self): | 594 def testMembersChanged(self): |
615 members = [ | 595 members = [ |
616 'MailTextResult', 'PresubmitError', 'PresubmitNotifyResult', | 596 'MailTextResult', 'PresubmitError', 'PresubmitNotifyResult', |
617 'PresubmitPromptWarning', 'PresubmitResult', | 597 'PresubmitPromptWarning', 'PresubmitResult', |
618 ] | 598 ] |
619 # If this test fails, you should add the relevant test. | 599 # If this test fails, you should add the relevant test. |
620 self.compareMembers(presubmit.OutputApi(), members) | 600 self.compareMembers(presubmit.OutputApi(), members) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 def testIsDirectory(self): | 684 def testIsDirectory(self): |
705 os.path.exists('foo.cc').AndReturn(True) | 685 os.path.exists('foo.cc').AndReturn(True) |
706 os.path.isdir('foo.cc').AndReturn(True) | 686 os.path.isdir('foo.cc').AndReturn(True) |
707 self.mox.ReplayAll() | 687 self.mox.ReplayAll() |
708 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') | 688 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') |
709 # Verify cache coherency. | 689 # Verify cache coherency. |
710 self.failUnless(affected_file.IsDirectory()) | 690 self.failUnless(affected_file.IsDirectory()) |
711 self.failUnless(affected_file.IsDirectory()) | 691 self.failUnless(affected_file.IsDirectory()) |
712 self.mox.VerifyAll() | 692 self.mox.VerifyAll() |
713 | 693 |
| 694 def testIsTextFile(self): |
| 695 list = [presubmit.SvnAffectedFile('foo/blat.txt', 'M'), |
| 696 presubmit.SvnAffectedFile('foo/binary.blob', 'M'), |
| 697 presubmit.SvnAffectedFile('blat/flop.txt', 'D')] |
| 698 os.path.exists(os.path.join('foo', 'blat.txt')).AndReturn(True) |
| 699 os.path.isdir(os.path.join('foo', 'blat.txt')).AndReturn(False) |
| 700 os.path.exists(os.path.join('foo', 'binary.blob')).AndReturn(True) |
| 701 os.path.isdir(os.path.join('foo', 'binary.blob')).AndReturn(False) |
| 702 self.mox.ReplayAll() |
| 703 |
| 704 output = filter(lambda x: x.IsTextFile(), list) |
| 705 self.failUnless(len(output) == 1) |
| 706 self.failUnless(list[0] == output[0]) |
| 707 self.mox.VerifyAll() |
| 708 |
714 | 709 |
715 class CannedChecksUnittest(PresubmitTestsBase): | 710 class CannedChecksUnittest(PresubmitTestsBase): |
716 """Tests presubmit_canned_checks.py.""" | 711 """Tests presubmit_canned_checks.py.""" |
717 class MockInputApi(object): | 712 class MockInputApi(object): |
718 class MockUrllib2(object): | 713 class MockUrllib2(object): |
719 class urlopen(object): | 714 class urlopen(object): |
720 def __init__(self, url): | 715 def __init__(self, url): |
721 if url == 'url_to_open': | 716 if url == 'url_to_open': |
722 self.result = '1' | 717 self.result = '1' |
723 else: | 718 else: |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 # TODO(maruel): Add real tests. | 842 # TODO(maruel): Add real tests. |
848 self.failIf(presubmit_canned_checks.RunPythonUnitTests( | 843 self.failIf(presubmit_canned_checks.RunPythonUnitTests( |
849 self.MockInputApi(), | 844 self.MockInputApi(), |
850 presubmit.OutputApi, [])) | 845 presubmit.OutputApi, [])) |
851 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( | 846 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( |
852 self.MockInputApi(), | 847 self.MockInputApi(), |
853 presubmit.OutputApi, ['non_existent_module'])) | 848 presubmit.OutputApi, ['non_existent_module'])) |
854 | 849 |
855 if __name__ == '__main__': | 850 if __name__ == '__main__': |
856 unittest.main() | 851 unittest.main() |
OLD | NEW |