| 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 |
| 12 | 13 |
| 13 # Local imports | 14 # Local imports |
| 14 import gcl | 15 import gcl |
| 15 import gclient | 16 import gclient |
| 16 import presubmit_support as presubmit | 17 import presubmit_support as presubmit |
| 17 import presubmit_canned_checks | 18 import presubmit_canned_checks |
| 18 | 19 |
| 19 | 20 |
| 20 class PresubmitTestsBase(unittest.TestCase): | 21 class PresubmitTestsBase(unittest.TestCase): |
| 21 """Setups and tear downs the mocks but doesn't test anything as-is.""" | 22 """Setups and tear downs the mocks but doesn't test anything as-is.""" |
| 22 def setUp(self): | 23 def setUp(self): |
| 24 self._warnings_stack = warnings.catch_warnings() |
| 25 warnings.simplefilter("ignore", DeprecationWarning) |
| 23 self.original_IsFile = os.path.isfile | 26 self.original_IsFile = os.path.isfile |
| 24 def MockIsFile(f): | 27 def MockIsFile(f): |
| 25 dir = os.path.dirname(f) | 28 dir = os.path.dirname(f) |
| 26 return dir.endswith('haspresubmit') or dir == '' | 29 return dir.endswith('haspresubmit') or dir == '' |
| 27 os.path.isfile = MockIsFile | 30 os.path.isfile = MockIsFile |
| 28 | 31 |
| 29 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo | 32 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo |
| 30 def MockCaptureSVNInfo(path): | 33 def MockCaptureSVNInfo(path): |
| 31 if path.count('notfound'): | 34 if path.count('notfound'): |
| 32 return {} | 35 return {} |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 self._sys_stdout = sys.stdout | 88 self._sys_stdout = sys.stdout |
| 86 sys.stdout = StringIO.StringIO() | 89 sys.stdout = StringIO.StringIO() |
| 87 | 90 |
| 88 def tearDown(self): | 91 def tearDown(self): |
| 89 os.path.isfile = self.original_IsFile | 92 os.path.isfile = self.original_IsFile |
| 90 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo | 93 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo |
| 91 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty | 94 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty |
| 92 gcl.ReadFile = self.original_ReadFile | 95 gcl.ReadFile = self.original_ReadFile |
| 93 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot | 96 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot |
| 94 sys.stdout = self._sys_stdout | 97 sys.stdout = self._sys_stdout |
| 98 self._warnings_stack = None |
| 95 | 99 |
| 96 @staticmethod | 100 @staticmethod |
| 97 def MakeBasicChange(name, description): | 101 def MakeBasicChange(name, description): |
| 98 ci = gcl.ChangeInfo(name=name, | 102 ci = gcl.ChangeInfo(name=name, |
| 99 description=description, | 103 description=description, |
| 100 files=[]) | 104 files=[]) |
| 101 change = presubmit.GclChange(ci) | 105 change = presubmit.GclChange(ci) |
| 102 return change | 106 return change |
| 103 | 107 |
| 104 def compareMembers(self, object, members): | 108 def compareMembers(self, object, members): |
| 105 """If you add a member, be sure to add the relevant test!""" | 109 """If you add a member, be sure to add the relevant test!""" |
| 106 # Skip over members starting with '_' since they are usually not meant to | 110 # Skip over members starting with '_' since they are usually not meant to |
| 107 # be for public use. | 111 # be for public use. |
| 108 actual_members = [x for x in sorted(dir(object)) | 112 actual_members = [x for x in sorted(dir(object)) |
| 109 if not x.startswith('_')] | 113 if not x.startswith('_')] |
| 110 self.assertEqual(actual_members, sorted(members)) | 114 self.assertEqual(actual_members, sorted(members)) |
| 111 | 115 |
| 112 | 116 |
| 113 class PresubmitUnittest(PresubmitTestsBase): | 117 class PresubmitUnittest(PresubmitTestsBase): |
| 114 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" | 118 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" |
| 115 def testMembersChanged(self): | 119 def testMembersChanged(self): |
| 116 members = [ | 120 members = [ |
| 117 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', | 121 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', |
| 118 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', | 122 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', |
| 119 'OutputApi', 'ParseFiles', 'PresubmitExecuter', | 123 'OutputApi', 'ParseFiles', 'PresubmitExecuter', |
| 120 'ScanSubDirs', 'SvnAffectedFile', 'cPickle', 'cStringIO', 'exceptions', | 124 'ScanSubDirs', 'SvnAffectedFile', |
| 125 'cPickle', 'cStringIO', 'deprecated', 'exceptions', |
| 121 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', | 126 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', |
| 122 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', | 127 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', |
| 123 'tempfile', 'types', 'urllib2', | 128 'tempfile', 'types', 'urllib2', 'warnings', |
| 124 ] | 129 ] |
| 125 # If this test fails, you should add the relevant test. | 130 # If this test fails, you should add the relevant test. |
| 126 self.compareMembers(presubmit, members) | 131 self.compareMembers(presubmit, members) |
| 127 | 132 |
| 128 def testListRelevantPresubmitFiles(self): | 133 def testListRelevantPresubmitFiles(self): |
| 129 presubmit_files = presubmit.ListRelevantPresubmitFiles([ | 134 presubmit_files = presubmit.ListRelevantPresubmitFiles([ |
| 130 'blat.cc', | 135 'blat.cc', |
| 131 'foo/haspresubmit/yodle/smart.h', | 136 'foo/haspresubmit/yodle/smart.h', |
| 132 'moo/mat/gat/yo.h', | 137 'moo/mat/gat/yo.h', |
| 133 'foo/luck.h']) | 138 'foo/luck.h']) |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 'DepotToLocalPath', 'FilterTextFiles', 'LocalPaths', 'LocalToDepotPath', | 447 'DepotToLocalPath', 'FilterTextFiles', 'LocalPaths', 'LocalToDepotPath', |
| 443 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', | 448 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', |
| 444 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', | 449 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', |
| 445 'marshal', 'os_path', 'pickle', 'platform', | 450 'marshal', 'os_path', 'pickle', 'platform', |
| 446 're', 'subprocess', 'tempfile', 'urllib2', 'version', | 451 're', 'subprocess', 'tempfile', 'urllib2', 'version', |
| 447 ] | 452 ] |
| 448 # If this test fails, you should add the relevant test. | 453 # If this test fails, you should add the relevant test. |
| 449 self.compareMembers(presubmit.InputApi(None, './.'), members) | 454 self.compareMembers(presubmit.InputApi(None, './.'), members) |
| 450 | 455 |
| 451 def testDepotToLocalPath(self): | 456 def testDepotToLocalPath(self): |
| 452 path = presubmit.InputApi.DepotToLocalPath('svn:/foo/smurf') | 457 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn:/foo/smurf') |
| 453 self.failUnless(path == 'smurf') | 458 self.failUnless(path == 'smurf') |
| 454 path = presubmit.InputApi.DepotToLocalPath('svn:/foo/notfound/burp') | 459 path = presubmit.InputApi(None, './p').DepotToLocalPath( |
| 460 'svn:/foo/notfound/burp') |
| 455 self.failUnless(path == None) | 461 self.failUnless(path == None) |
| 456 | 462 |
| 457 def testLocalToDepotPath(self): | 463 def testLocalToDepotPath(self): |
| 458 path = presubmit.InputApi.LocalToDepotPath('smurf') | 464 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') |
| 459 self.failUnless(path == 'svn:/foo/smurf') | 465 self.failUnless(path == 'svn:/foo/smurf') |
| 460 path = presubmit.InputApi.LocalToDepotPath('notfound-food') | 466 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') |
| 461 self.failUnless(path == None) | 467 self.failUnless(path == None) |
| 462 | 468 |
| 463 def testInputApiConstruction(self): | 469 def testInputApiConstruction(self): |
| 464 # Fudge the change object, it's not used during construction anyway | 470 # Fudge the change object, it's not used during construction anyway |
| 465 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') | 471 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') |
| 466 self.failUnless(api.PresubmitLocalPath() == 'foo/path') | 472 self.failUnless(api.PresubmitLocalPath() == 'foo/path') |
| 467 self.failUnless(api.change == 42) | 473 self.failUnless(api.change == 42) |
| 468 | 474 |
| 469 def testFilterTextFiles(self): | 475 def testFilterTextFiles(self): |
| 470 class MockAffectedFile(object): | 476 class MockAffectedFile(object): |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 presubmit.normpath('foo/blat.cc')) | 523 presubmit.normpath('foo/blat.cc')) |
| 518 self.assertEquals(affected_files[1].LocalPath(), | 524 self.assertEquals(affected_files[1].LocalPath(), |
| 519 presubmit.normpath('foo/blat/binary.dll')) | 525 presubmit.normpath('foo/blat/binary.dll')) |
| 520 self.assertEquals(affected_files[2].LocalPath(), | 526 self.assertEquals(affected_files[2].LocalPath(), |
| 521 presubmit.normpath('foo/mat/beingdeleted.txt')) | 527 presubmit.normpath('foo/mat/beingdeleted.txt')) |
| 522 | 528 |
| 523 rhs_lines = [] | 529 rhs_lines = [] |
| 524 for line in api.RightHandSideLines(): | 530 for line in api.RightHandSideLines(): |
| 525 rhs_lines.append(line) | 531 rhs_lines.append(line) |
| 526 self.failUnless(len(rhs_lines) == 2) | 532 self.failUnless(len(rhs_lines) == 2) |
| 527 self.failUnless(rhs_lines[0][0].LocalPath() == | 533 self.assertEqual(rhs_lines[0][0].LocalPath(), |
| 528 presubmit.normpath('foo/blat.cc')) | 534 presubmit.normpath('foo/blat.cc')) |
| 529 | 535 |
| 530 def testGetAbsoluteLocalPath(self): | 536 def testGetAbsoluteLocalPath(self): |
| 531 # Regression test for bug of presubmit stuff that relies on invoking | 537 # Regression test for bug of presubmit stuff that relies on invoking |
| 532 # SVN (e.g. to get mime type of file) not working unless gcl invoked | 538 # SVN (e.g. to get mime type of file) not working unless gcl invoked |
| 533 # from the client root (e.g. if you were at 'src' and did 'cd base' before | 539 # from the client root (e.g. if you were at 'src' and did 'cd base' before |
| 534 # invoking 'gcl upload' it would fail because svn wouldn't find the files | 540 # invoking 'gcl upload' it would fail because svn wouldn't find the files |
| 535 # the presubmit script was asking about). | 541 # the presubmit script was asking about). |
| 536 files = [ | 542 files = [ |
| 537 ['A', 'isdir'], | 543 ['A', 'isdir'], |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 output = StringIO.StringIO() | 622 output = StringIO.StringIO() |
| 617 input = StringIO.StringIO('\n') | 623 input = StringIO.StringIO('\n') |
| 618 warning = presubmit.OutputApi.PresubmitPromptWarning('???') | 624 warning = presubmit.OutputApi.PresubmitPromptWarning('???') |
| 619 self.failIf(warning._Handle(output, input)) | 625 self.failIf(warning._Handle(output, input)) |
| 620 self.failUnless(output.getvalue().count('???')) | 626 self.failUnless(output.getvalue().count('???')) |
| 621 | 627 |
| 622 | 628 |
| 623 class AffectedFileUnittest(PresubmitTestsBase): | 629 class AffectedFileUnittest(PresubmitTestsBase): |
| 624 def testMembersChanged(self): | 630 def testMembersChanged(self): |
| 625 members = [ | 631 members = [ |
| 626 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'LocalPath', 'NewContents', | 632 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', |
| 633 'LocalPath', 'NewContents', |
| 627 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', 'action', | 634 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', 'action', |
| 628 'is_directory', 'path', 'properties', 'repository_root', 'server_path', | 635 'is_directory', 'path', 'properties', 'repository_root', 'server_path', |
| 629 ] | 636 ] |
| 630 # If this test fails, you should add the relevant test. | 637 # If this test fails, you should add the relevant test. |
| 631 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) | 638 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) |
| 632 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) | 639 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) |
| 633 | 640 |
| 634 def testAffectedFile(self): | 641 def testAffectedFile(self): |
| 635 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M') | 642 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M') |
| 636 self.failUnless(af.ServerPath() == 'svn:/foo/foo/blat.cc') | 643 self.failUnless(af.ServerPath() == 'svn:/foo/foo/blat.cc') |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 # TODO(maruel): Add real tests. | 790 # TODO(maruel): Add real tests. |
| 784 self.failIf(presubmit_canned_checks.RunPythonUnitTests( | 791 self.failIf(presubmit_canned_checks.RunPythonUnitTests( |
| 785 self.MockInputApi(), | 792 self.MockInputApi(), |
| 786 presubmit.OutputApi, [])) | 793 presubmit.OutputApi, [])) |
| 787 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( | 794 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( |
| 788 self.MockInputApi(), | 795 self.MockInputApi(), |
| 789 presubmit.OutputApi, ['non_existent_module'])) | 796 presubmit.OutputApi, ['non_existent_module'])) |
| 790 | 797 |
| 791 if __name__ == '__main__': | 798 if __name__ == '__main__': |
| 792 unittest.main() | 799 unittest.main() |
| OLD | NEW |