Chromium Code Reviews| 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 exceptions |
| 9 import StringIO | 9 import StringIO |
| 10 import sys | |
| 11 import unittest | 10 import unittest |
| 12 | 11 |
| 13 # Local imports | 12 # Local imports |
| 14 import __init__ | 13 import __init__ |
| 15 import gcl | |
| 16 import gclient | |
| 17 import presubmit_support as presubmit | 14 import presubmit_support as presubmit |
| 18 import presubmit_canned_checks | 15 import presubmit_canned_checks |
| 19 mox = __init__.mox | 16 mox = __init__.mox |
| 20 | 17 |
| 21 | 18 |
| 22 class PresubmitTestsBase(mox.MoxTestBase): | 19 class PresubmitTestsBase(mox.MoxTestBase): |
| 23 """Setups and tear downs the mocks but doesn't test anything as-is.""" | 20 """Setups and tear downs the mocks but doesn't test anything as-is.""" |
| 24 def setUp(self): | 21 presubmit_text = """ |
| 25 super(PresubmitTestsBase, self).setUp() | |
| 26 self.mox.StubOutWithMock(presubmit, 'warnings') | |
| 27 self.original_IsFile = os.path.isfile | |
| 28 def MockIsFile(f): | |
| 29 dir = os.path.dirname(f) | |
| 30 return dir.endswith('haspresubmit') or dir == '' | |
| 31 os.path.isfile = MockIsFile | |
| 32 | |
| 33 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo | |
| 34 def MockCaptureSVNInfo(path): | |
| 35 if path.count('notfound'): | |
| 36 return {} | |
| 37 results = { | |
| 38 'Path': path[len('svn:/foo/'):], | |
| 39 'URL': 'svn:/foo/%s' % path.replace('\\', '/'), | |
| 40 } | |
| 41 if path.endswith('isdir'): | |
| 42 results['Node Kind'] = 'directory' | |
| 43 else: | |
| 44 results['Node Kind'] = 'file' | |
| 45 return results | |
| 46 gclient.CaptureSVNInfo = MockCaptureSVNInfo | |
| 47 | |
| 48 self.original_GetSVNFileProperty = gcl.GetSVNFileProperty | |
| 49 def MockGetSVNFileProperty(path, property_name): | |
| 50 if property_name == 'svn:secret-property': | |
| 51 return 'secret-property-value' | |
| 52 elif path.count('binary'): | |
| 53 return 'application/octet-stream' | |
| 54 else: | |
| 55 if len(path) % 2: | |
| 56 return 'text/plain' | |
| 57 else: | |
| 58 return '' | |
| 59 gcl.GetSVNFileProperty = MockGetSVNFileProperty | |
| 60 | |
| 61 self.original_ReadFile = gcl.ReadFile | |
| 62 def MockReadFile(path, dummy='r'): | |
| 63 if path.count('nosuchfile'): | |
| 64 return None | |
| 65 elif path.endswith('isdir'): | |
| 66 self.fail('Should not attempt to read file that is directory.') | |
| 67 elif path.endswith('PRESUBMIT.py'): | |
| 68 # used in testDoPresubmitChecks | |
| 69 return """ | |
| 70 def CheckChangeOnUpload(input_api, output_api): | 22 def CheckChangeOnUpload(input_api, output_api): |
| 71 if not input_api.change.NOSUCHKEY: | 23 if not input_api.change.NOSUCHKEY: |
| 72 return [output_api.PresubmitError("!!")] | 24 return [output_api.PresubmitError("!!")] |
| 73 elif not input_api.change.REALLYNOSUCHKEY: | 25 elif not input_api.change.REALLYNOSUCHKEY: |
| 74 return [output_api.PresubmitPromptWarning("??")] | 26 return [output_api.PresubmitPromptWarning("??")] |
| 75 elif not input_api.change.REALLYABSOLUTELYNOSUCHKEY: | 27 elif not input_api.change.REALLYABSOLUTELYNOSUCHKEY: |
| 76 return [output_api.PresubmitPromptWarning("??"), | 28 return [output_api.PresubmitPromptWarning("??"), |
| 77 output_api.PresubmitError("XX!!XX")] | 29 output_api.PresubmitError("XX!!XX")] |
| 78 else: | 30 else: |
| 79 return () | 31 return () |
| 80 """ | 32 """ |
| 81 else: | |
| 82 return 'one:%s\r\ntwo:%s' % (path, path) | |
| 83 gcl.ReadFile = MockReadFile | |
| 84 | 33 |
| 85 self.original_GetRepositoryRoot = gcl.GetRepositoryRoot | 34 def setUp(self): |
| 35 mox.MoxTestBase.setUp(self) | |
| 36 self.mox.StubOutWithMock(presubmit, 'warnings') | |
| 37 # Stub out 'os' but keep os.path.join(). | |
|
Jói Sigurðsson
2009/05/30 12:06:45
maybe update the comment since you're keeping more
| |
| 38 path_join = presubmit.os.path.join | |
| 39 path_dirname = presubmit.os.path.dirname | |
| 40 path_normpath = presubmit.os.path.normpath | |
| 41 self.mox.StubOutWithMock(presubmit, 'os') | |
| 42 self.mox.StubOutWithMock(presubmit.os, 'path') | |
| 43 presubmit.os.path.join = path_join | |
| 44 presubmit.os.path.dirname = path_dirname | |
| 45 presubmit.os.path.normpath = path_normpath | |
| 46 self.mox.StubOutWithMock(presubmit, 'sys') | |
| 47 # Special mock. | |
| 48 def MockAbsPath(f): | |
| 49 return f | |
| 50 presubmit.os.path.abspath = MockAbsPath | |
| 51 self.mox.StubOutWithMock(presubmit.gcl, 'GetRepositoryRoot') | |
| 86 def MockGetRepositoryRoot(): | 52 def MockGetRepositoryRoot(): |
| 87 return '' | 53 return '' |
| 88 gcl.GetRepositoryRoot = MockGetRepositoryRoot | 54 presubmit.gcl.GetRepositoryRoot = MockGetRepositoryRoot |
| 89 self._sys_stdout = sys.stdout | 55 self.mox.StubOutWithMock(presubmit.gclient, 'CaptureSVNInfo') |
| 90 sys.stdout = StringIO.StringIO() | 56 self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty') |
| 91 self._os_path_exists = os.path.exists | 57 self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile') |
| 92 os.path.exists = self.mox.CreateMockAnything() | |
| 93 self._os_path_isdir = os.path.isdir | |
| 94 os.path.isdir = self.mox.CreateMockAnything() | |
| 95 | |
| 96 def tearDown(self): | |
| 97 os.path.isfile = self.original_IsFile | |
| 98 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo | |
| 99 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty | |
| 100 gcl.ReadFile = self.original_ReadFile | |
| 101 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot | |
| 102 sys.stdout = self._sys_stdout | |
| 103 os.path.exists = self._os_path_exists | |
| 104 os.path.isdir = self._os_path_isdir | |
| 105 | 58 |
| 106 @staticmethod | 59 @staticmethod |
| 107 def MakeBasicChange(name, description): | 60 def MakeBasicChange(name, description): |
| 108 ci = gcl.ChangeInfo(name=name, | 61 ci = presubmit.gcl.ChangeInfo(name=name, description=description) |
| 109 description=description, | |
| 110 files=[]) | |
| 111 change = presubmit.GclChange(ci) | 62 change = presubmit.GclChange(ci) |
| 112 return change | 63 return change |
| 113 | 64 |
| 114 def compareMembers(self, object, members): | 65 def compareMembers(self, object, members): |
| 115 """If you add a member, be sure to add the relevant test!""" | 66 """If you add a member, be sure to add the relevant test!""" |
| 116 # Skip over members starting with '_' since they are usually not meant to | 67 # Skip over members starting with '_' since they are usually not meant to |
| 117 # be for public use. | 68 # be for public use. |
| 118 actual_members = [x for x in sorted(dir(object)) | 69 actual_members = [x for x in sorted(dir(object)) |
| 119 if not x.startswith('_')] | 70 if not x.startswith('_')] |
| 120 self.assertEqual(actual_members, sorted(members)) | 71 self.assertEqual(actual_members, sorted(members)) |
| 121 | 72 |
| 122 | 73 |
| 123 class PresubmitUnittest(PresubmitTestsBase): | 74 class PresubmitUnittest(PresubmitTestsBase): |
| 124 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" | 75 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" |
| 125 def testMembersChanged(self): | 76 def testMembersChanged(self): |
| 126 members = [ | 77 members = [ |
| 127 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', | 78 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', |
| 128 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', | 79 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', |
| 129 'OutputApi', 'ParseFiles', 'PresubmitExecuter', | 80 'OutputApi', 'ParseFiles', 'PresubmitExecuter', |
| 130 'ScanSubDirs', 'SvnAffectedFile', | 81 'ScanSubDirs', 'SvnAffectedFile', |
| 131 'cPickle', 'cStringIO', 'deprecated', 'exceptions', | 82 'cPickle', 'cStringIO', 'deprecated', 'exceptions', |
| 132 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', | 83 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', |
| 133 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', | 84 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', |
| 134 'tempfile', 'types', 'urllib2', 'warnings', | 85 'tempfile', 'types', 'urllib2', 'warnings', |
| 135 ] | 86 ] |
| 136 # If this test fails, you should add the relevant test. | 87 # If this test fails, you should add the relevant test. |
| 137 self.compareMembers(presubmit, members) | 88 self.compareMembers(presubmit, members) |
| 138 | 89 |
| 139 def testListRelevantPresubmitFiles(self): | 90 def testListRelevantPresubmitFiles(self): |
| 91 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) | |
| 92 presubmit.os.path.isfile( | |
| 93 presubmit.os.path.join('foo/haspresubmit/yodle', | |
| 94 'PRESUBMIT.py')).AndReturn(False) | |
| 95 presubmit.os.path.isfile( | |
| 96 presubmit.os.path.join('foo/haspresubmit', | |
| 97 'PRESUBMIT.py')).AndReturn(True) | |
| 98 presubmit.os.path.isfile( | |
| 99 presubmit.os.path.join('foo', 'PRESUBMIT.py')).AndReturn(False) | |
| 100 presubmit.os.path.isfile( | |
| 101 presubmit.os.path.join('moo/mat/gat', | |
| 102 'PRESUBMIT.py')).AndReturn(False) | |
| 103 presubmit.os.path.isfile( | |
| 104 presubmit.os.path.join('moo/mat', | |
| 105 'PRESUBMIT.py')).AndReturn(False) | |
| 106 presubmit.os.path.isfile( | |
| 107 presubmit.os.path.join('moo', 'PRESUBMIT.py')).AndReturn(False) | |
| 108 self.mox.ReplayAll() | |
| 140 presubmit_files = presubmit.ListRelevantPresubmitFiles([ | 109 presubmit_files = presubmit.ListRelevantPresubmitFiles([ |
| 141 'blat.cc', | 110 'blat.cc', |
| 142 'foo/haspresubmit/yodle/smart.h', | 111 'foo/haspresubmit/yodle/smart.h', |
| 143 'moo/mat/gat/yo.h', | 112 'moo/mat/gat/yo.h', |
| 144 'foo/luck.h']) | 113 'foo/luck.h']) |
| 145 self.failUnless(len(presubmit_files) == 2) | 114 self.assertEqual(len(presubmit_files), 2) |
| 146 self.failUnless(presubmit.normpath('PRESUBMIT.py') in presubmit_files) | 115 self.failUnless(presubmit.normpath('PRESUBMIT.py') in presubmit_files) |
| 147 self.failUnless(presubmit.normpath('foo/haspresubmit/PRESUBMIT.py') in | 116 self.failUnless(presubmit.normpath('foo/haspresubmit/PRESUBMIT.py') in |
| 148 presubmit_files) | 117 presubmit_files) |
| 149 | 118 |
| 150 def testTagLineRe(self): | 119 def testTagLineRe(self): |
| 151 m = presubmit.GclChange._tag_line_re.match(' BUG =1223, 1445 \t') | 120 m = presubmit.GclChange._tag_line_re.match(' BUG =1223, 1445 \t') |
| 152 self.failUnless(m) | 121 self.failUnless(m) |
| 153 self.failUnlessEqual(m.group('key'), 'BUG') | 122 self.failUnlessEqual(m.group('key'), 'BUG') |
| 154 self.failUnlessEqual(m.group('value'), '1223, 1445') | 123 self.failUnlessEqual(m.group('value'), '1223, 1445') |
| 155 | 124 |
| 156 def testGclChange(self): | 125 def testGclChange(self): |
| 157 description_lines = ('Hello there', | 126 description_lines = ('Hello there', |
| 158 'this is a change', | 127 'this is a change', |
| 159 'BUG=123', | 128 'BUG=123', |
| 160 ' STORY =http://foo/ \t', | 129 ' STORY =http://foo/ \t', |
| 161 'and some more regular text \t') | 130 'and some more regular text \t') |
| 162 files = [ | 131 files = [ |
| 163 ['A', 'foo/blat.cc'], | 132 ['A', 'foo/blat.cc'], |
| 164 ['M', 'binary.dll'], # a binary file | 133 ['M', 'binary.dll'], # a binary file |
| 165 ['A', 'isdir'], # a directory | 134 ['A', 'isdir'], # a directory |
| 166 ['M', 'flop/notfound.txt'], # not found in SVN, still exists locally | 135 ['?', 'flop/notfound.txt'], # not found in SVN, still exists locally |
| 167 ['D', 'boo/flap.h'], | 136 ['D', 'boo/flap.h'], |
| 168 ] | 137 ] |
| 169 os.path.exists(os.path.join('foo', 'blat.cc')).AndReturn(True) | 138 blat = presubmit.os.path.join('foo', 'blat.cc') |
| 170 os.path.isdir(os.path.join('foo', 'blat.cc')).AndReturn(False) | 139 notfound = presubmit.os.path.join('flop', 'notfound.txt') |
| 171 os.path.exists('binary.dll').AndReturn(True) | 140 flap = presubmit.os.path.join('boo', 'flap.h') |
| 172 os.path.isdir('binary.dll').AndReturn(False) | 141 presubmit.os.path.exists(blat).AndReturn(True) |
| 173 os.path.exists('isdir').AndReturn(True) | 142 presubmit.os.path.isdir(blat).AndReturn(False) |
| 174 os.path.isdir('isdir').AndReturn(True) | 143 presubmit.os.path.exists('binary.dll').AndReturn(True) |
| 175 os.path.exists(os.path.join('flop', 'notfound.txt')).AndReturn(False) | 144 presubmit.os.path.isdir('binary.dll').AndReturn(False) |
| 176 os.path.exists(os.path.join('boo', 'flap.h')).AndReturn(False) | 145 presubmit.os.path.exists('isdir').AndReturn(True) |
| 146 presubmit.os.path.isdir('isdir').AndReturn(True) | |
| 147 presubmit.os.path.exists(notfound).AndReturn(True) | |
| 148 presubmit.os.path.isdir(notfound).AndReturn(False) | |
| 149 presubmit.os.path.exists(flap).AndReturn(False) | |
| 150 presubmit.gclient.CaptureSVNInfo(flap | |
| 151 ).AndReturn({'Node Kind': 'file'}) | |
| 152 presubmit.gcl.GetSVNFileProperty(blat, 'svn:mime-type').AndReturn(None) | |
| 153 presubmit.gcl.GetSVNFileProperty( | |
| 154 'binary.dll', 'svn:mime-type').AndReturn('application/octet-stream') | |
| 155 presubmit.gcl.GetSVNFileProperty( | |
| 156 notfound, 'svn:mime-type').AndReturn('') | |
| 157 presubmit.gclient.CaptureSVNInfo(blat).AndReturn( | |
| 158 {'URL': 'svn:/foo/foo/blat.cc'}) | |
| 159 presubmit.gclient.CaptureSVNInfo('binary.dll').AndReturn( | |
| 160 {'URL': 'svn:/foo/binary.dll'}) | |
| 161 presubmit.gclient.CaptureSVNInfo(notfound).AndReturn({}) | |
| 162 presubmit.gclient.CaptureSVNInfo(flap).AndReturn( | |
| 163 {'URL': 'svn:/foo/boo/flap.h'}) | |
| 164 presubmit.gcl.ReadFile(blat).AndReturn('boo!\nahh?') | |
| 165 presubmit.gcl.ReadFile(notfound).AndReturn('look!\nthere?') | |
| 177 self.mox.ReplayAll() | 166 self.mox.ReplayAll() |
| 178 ci = gcl.ChangeInfo(name='mychange', | 167 |
| 179 description='\n'.join(description_lines), | 168 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 180 files=files) | 169 description='\n'.join(description_lines), |
| 170 files=files) | |
| 181 change = presubmit.GclChange(ci) | 171 change = presubmit.GclChange(ci) |
| 182 | 172 |
| 183 self.failUnless(change.Change() == 'mychange') | 173 self.failUnless(change.Change() == 'mychange') |
| 184 self.failUnless(change.DescriptionText() == | 174 self.failUnless(change.DescriptionText() == |
| 185 'Hello there\nthis is a change\nand some more regular text') | 175 'Hello there\nthis is a change\nand some more regular text') |
| 186 self.failUnless(change.FullDescriptionText() == | 176 self.failUnless(change.FullDescriptionText() == |
| 187 '\n'.join(description_lines)) | 177 '\n'.join(description_lines)) |
| 188 | 178 |
| 189 self.failUnless(change.BUG == '123') | 179 self.failUnless(change.BUG == '123') |
| 190 self.failUnless(change.STORY == 'http://foo/') | 180 self.failUnless(change.STORY == 'http://foo/') |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 202 | 192 |
| 203 local_paths = change.LocalPaths() | 193 local_paths = change.LocalPaths() |
| 204 expected_paths = [presubmit.normpath(f[1]) for f in files] | 194 expected_paths = [presubmit.normpath(f[1]) for f in files] |
| 205 self.failUnless( | 195 self.failUnless( |
| 206 len(filter(lambda x: x in expected_paths, local_paths)) == 4) | 196 len(filter(lambda x: x in expected_paths, local_paths)) == 4) |
| 207 | 197 |
| 208 server_paths = change.ServerPaths() | 198 server_paths = change.ServerPaths() |
| 209 expected_paths = ['svn:/foo/%s' % f[1] for f in files if | 199 expected_paths = ['svn:/foo/%s' % f[1] for f in files if |
| 210 f[1] != 'flop/notfound.txt'] | 200 f[1] != 'flop/notfound.txt'] |
| 211 expected_paths.append('') # one unknown file | 201 expected_paths.append('') # one unknown file |
| 212 self.failUnless( | 202 self.assertEqual( |
| 213 len(filter(lambda x: x in expected_paths, server_paths)) == 4) | 203 len(filter(lambda x: x in expected_paths, server_paths)), 4) |
| 214 | 204 |
| 215 files = [[x[0], presubmit.normpath(x[1])] for x in files] | 205 files = [[x[0], presubmit.normpath(x[1])] for x in files] |
| 216 | 206 |
| 217 rhs_lines = [] | 207 rhs_lines = [] |
| 218 for line in change.RightHandSideLines(): | 208 for line in change.RightHandSideLines(): |
| 219 rhs_lines.append(line) | 209 rhs_lines.append(line) |
| 220 self.failUnless(rhs_lines[0][0].LocalPath() == files[0][1]) | 210 self.assertEquals(rhs_lines[0][0].LocalPath(), files[0][1]) |
| 221 self.failUnless(rhs_lines[0][1] == 1) | 211 self.assertEquals(rhs_lines[0][1], 1) |
| 222 self.failUnless(rhs_lines[0][2] == 'one:%s' % files[0][1]) | 212 self.assertEquals(rhs_lines[0][2],'boo!') |
| 223 | 213 |
| 224 self.failUnless(rhs_lines[1][0].LocalPath() == files[0][1]) | 214 self.assertEquals(rhs_lines[1][0].LocalPath(), files[0][1]) |
| 225 self.failUnless(rhs_lines[1][1] == 2) | 215 self.assertEquals(rhs_lines[1][1], 2) |
| 226 self.failUnless(rhs_lines[1][2] == 'two:%s' % files[0][1]) | 216 self.assertEquals(rhs_lines[1][2], 'ahh?') |
| 227 | 217 |
| 228 self.failUnless(rhs_lines[2][0].LocalPath() == files[3][1]) | 218 self.assertEquals(rhs_lines[2][0].LocalPath(), files[3][1]) |
| 229 self.failUnless(rhs_lines[2][1] == 1) | 219 self.assertEquals(rhs_lines[2][1], 1) |
| 230 self.failUnless(rhs_lines[2][2] == 'one:%s' % files[3][1]) | 220 self.assertEquals(rhs_lines[2][2], 'look!') |
| 231 | 221 |
| 232 self.failUnless(rhs_lines[3][0].LocalPath() == files[3][1]) | 222 self.assertEquals(rhs_lines[3][0].LocalPath(), files[3][1]) |
| 233 self.failUnless(rhs_lines[3][1] == 2) | 223 self.assertEquals(rhs_lines[3][1], 2) |
| 234 self.failUnless(rhs_lines[3][2] == 'two:%s' % files[3][1]) | 224 self.assertEquals(rhs_lines[3][2], 'there?') |
| 235 self.mox.VerifyAll() | |
| 236 | 225 |
| 237 def testExecPresubmitScript(self): | 226 def testExecPresubmitScript(self): |
| 238 description_lines = ('Hello there', | 227 description_lines = ('Hello there', |
| 239 'this is a change', | 228 'this is a change', |
| 240 'STORY=http://tracker/123') | 229 'STORY=http://tracker/123') |
| 241 files = [ | 230 files = [ |
| 242 ['A', 'foo\\blat.cc'], | 231 ['A', 'foo\\blat.cc'], |
| 243 ] | 232 ] |
| 244 ci = gcl.ChangeInfo(name='mychange', | 233 self.mox.ReplayAll() |
| 245 description='\n'.join(description_lines), | 234 |
| 246 files=files) | 235 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 236 description='\n'.join(description_lines), | |
| 237 files=files) | |
| 247 | 238 |
| 248 executer = presubmit.PresubmitExecuter(ci, False) | 239 executer = presubmit.PresubmitExecuter(ci, False) |
| 249 self.failIf(executer.ExecPresubmitScript('', 'PRESUBMIT.py')) | 240 self.failIf(executer.ExecPresubmitScript('', 'PRESUBMIT.py')) |
| 250 # No error if no on-upload entry point | 241 # No error if no on-upload entry point |
| 251 self.failIf(executer.ExecPresubmitScript( | 242 self.failIf(executer.ExecPresubmitScript( |
| 252 ('def CheckChangeOnCommit(input_api, output_api):\n' | 243 ('def CheckChangeOnCommit(input_api, output_api):\n' |
| 253 ' return (output_api.PresubmitError("!!"))\n'), | 244 ' return (output_api.PresubmitError("!!"))\n'), |
| 254 'PRESUBMIT.py' | 245 'PRESUBMIT.py' |
| 255 )) | 246 )) |
| 256 | 247 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 273 | 264 |
| 274 self.failUnless(executer.ExecPresubmitScript( | 265 self.failUnless(executer.ExecPresubmitScript( |
| 275 ('def CheckChangeOnCommit(input_api, output_api):\n' | 266 ('def CheckChangeOnCommit(input_api, output_api):\n' |
| 276 ' if not input_api.change.NOSUCHKEY:\n' | 267 ' if not input_api.change.NOSUCHKEY:\n' |
| 277 ' return [output_api.PresubmitError("!!")]\n' | 268 ' return [output_api.PresubmitError("!!")]\n' |
| 278 ' else:\n' | 269 ' else:\n' |
| 279 ' return ()'), | 270 ' return ()'), |
| 280 'PRESUBMIT.py' | 271 'PRESUBMIT.py' |
| 281 )) | 272 )) |
| 282 | 273 |
| 283 try: | 274 self.assertRaises(exceptions.RuntimeError, |
| 284 executer.ExecPresubmitScript( | 275 executer.ExecPresubmitScript, |
| 285 ('def CheckChangeOnCommit(input_api, output_api):\n' | 276 'def CheckChangeOnCommit(input_api, output_api):\n' |
| 286 ' return "foo"'), | 277 ' return "foo"', |
| 287 'PRESUBMIT.py') | 278 'PRESUBMIT.py') |
| 288 self.fail() | |
| 289 except: | |
| 290 pass # expected case | |
| 291 | 279 |
| 292 try: | 280 self.assertRaises(exceptions.RuntimeError, |
| 293 executer.ExecPresubmitScript( | 281 executer.ExecPresubmitScript, |
| 294 ('def CheckChangeOnCommit(input_api, output_api):\n' | 282 'def CheckChangeOnCommit(input_api, output_api):\n' |
| 295 ' return ["foo"]'), | 283 ' return ["foo"]', |
| 296 'PRESUBMIT.py') | 284 'PRESUBMIT.py') |
| 297 self.fail() | |
| 298 except: | |
| 299 pass # expected case | |
| 300 | 285 |
| 301 def testDoPresubmitChecks(self): | 286 def testDoPresubmitChecks(self): |
| 302 description_lines = ('Hello there', | 287 description_lines = ('Hello there', |
| 303 'this is a change', | 288 'this is a change', |
| 304 'STORY=http://tracker/123') | 289 'STORY=http://tracker/123') |
| 305 files = [ | 290 files = [ |
| 306 ['A', 'haspresubmit\\blat.cc'], | 291 ['A', 'haspresubmit\\blat.cc'], |
| 307 ] | 292 ] |
| 308 ci = gcl.ChangeInfo(name='mychange', | 293 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 309 description='\n'.join(description_lines), | 294 presubmit.os.path.isfile(path).AndReturn(True) |
| 310 files=files) | 295 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 296 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) | |
| 297 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) | |
| 298 self.mox.ReplayAll() | |
| 299 | |
| 300 ci = presubmit.gcl.ChangeInfo(name='mychange', | |
| 301 description='\n'.join(description_lines), | |
| 302 files=files) | |
| 311 | 303 |
| 312 output = StringIO.StringIO() | 304 output = StringIO.StringIO() |
| 313 input = StringIO.StringIO('y\n') | 305 input = StringIO.StringIO('y\n') |
| 314 | 306 |
| 315 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 307 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 316 None)) | 308 None)) |
| 317 self.assertEqual(output.getvalue().count('!!'), 2) | 309 self.assertEqual(output.getvalue().count('!!'), 2) |
| 318 | 310 |
| 319 def testDoPresubmitChecksPromptsAfterWarnings(self): | 311 def testDoPresubmitChecksPromptsAfterWarnings(self): |
| 320 description_lines = ('Hello there', | 312 description_lines = ('Hello there', |
| 321 'this is a change', | 313 'this is a change', |
| 322 'NOSUCHKEY=http://tracker/123') | 314 'NOSUCHKEY=http://tracker/123') |
| 323 files = [ | 315 files = [ |
| 324 ['A', 'haspresubmit\\blat.cc'], | 316 ['A', 'haspresubmit\\blat.cc'], |
| 325 ] | 317 ] |
| 326 ci = gcl.ChangeInfo(name='mychange', | 318 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 327 description='\n'.join(description_lines), | 319 presubmit.os.path.isfile(path).AndReturn(True) |
| 328 files=files) | 320 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 321 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) | |
| 322 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) | |
| 323 presubmit.os.path.isfile(path).AndReturn(True) | |
| 324 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) | |
| 325 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) | |
| 326 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) | |
| 327 self.mox.ReplayAll() | |
| 328 | |
| 329 ci = presubmit.gcl.ChangeInfo(name='mychange', | |
| 330 description='\n'.join(description_lines), | |
| 331 files=files) | |
| 329 | 332 |
| 330 output = StringIO.StringIO() | 333 output = StringIO.StringIO() |
| 331 input = StringIO.StringIO('n\n') # say no to the warning | 334 input = StringIO.StringIO('n\n') # say no to the warning |
| 332 | |
| 333 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 335 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 334 None)) | 336 None)) |
| 335 self.assertEqual(output.getvalue().count('??'), 2) | 337 self.assertEqual(output.getvalue().count('??'), 2) |
| 336 | 338 |
| 337 output = StringIO.StringIO() | 339 output = StringIO.StringIO() |
| 338 input = StringIO.StringIO('y\n') # say yes to the warning | 340 input = StringIO.StringIO('y\n') # say yes to the warning |
| 339 | |
| 340 self.failUnless(presubmit.DoPresubmitChecks(ci, | 341 self.failUnless(presubmit.DoPresubmitChecks(ci, |
| 341 False, | 342 False, |
| 342 True, | 343 True, |
| 343 output, | 344 output, |
| 344 input, | 345 input, |
| 345 None)) | 346 None)) |
| 346 self.failUnless(output.getvalue().count('??')) | 347 self.assertEquals(output.getvalue().count('??'), 2) |
| 347 | 348 |
| 348 def testDoPresubmitChecksNoWarningPromptIfErrors(self): | 349 def testDoPresubmitChecksNoWarningPromptIfErrors(self): |
| 349 description_lines = ('Hello there', | 350 description_lines = ('Hello there', |
| 350 'this is a change', | 351 'this is a change', |
| 351 'NOSUCHKEY=http://tracker/123', | 352 'NOSUCHKEY=http://tracker/123', |
| 352 'REALLYNOSUCHKEY=http://tracker/123') | 353 'REALLYNOSUCHKEY=http://tracker/123') |
| 353 files = [ | 354 files = [ |
| 354 ['A', 'haspresubmit\\blat.cc'], | 355 ['A', 'haspresubmit\\blat.cc'], |
| 355 ] | 356 ] |
| 356 ci = gcl.ChangeInfo(name='mychange', | 357 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 357 description='\n'.join(description_lines), | 358 presubmit.os.path.isfile(path).AndReturn(True) |
| 358 files=files) | 359 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 360 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) | |
| 361 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) | |
| 362 self.mox.ReplayAll() | |
| 363 | |
| 364 ci = presubmit.gcl.ChangeInfo(name='mychange', | |
| 365 description='\n'.join(description_lines), | |
| 366 files=files) | |
| 359 | 367 |
| 360 output = StringIO.StringIO() | 368 output = StringIO.StringIO() |
| 361 input = StringIO.StringIO() # should be unused | 369 input = StringIO.StringIO() # should be unused |
| 362 | 370 |
| 363 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 371 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 364 None)) | 372 None)) |
| 365 self.assertEqual(output.getvalue().count('??'), 2) | 373 self.assertEqual(output.getvalue().count('??'), 2) |
| 366 self.assertEqual(output.getvalue().count('XX!!XX'), 2) | 374 self.assertEqual(output.getvalue().count('XX!!XX'), 2) |
| 367 self.assertEqual(output.getvalue().count('(y/N)'), 0) | 375 self.assertEqual(output.getvalue().count('(y/N)'), 0) |
| 368 | 376 |
| 369 def testDoDefaultPresubmitChecks(self): | 377 def testDoDefaultPresubmitChecks(self): |
| 370 description_lines = ('Hello there', | 378 description_lines = ('Hello there', |
| 371 'this is a change', | 379 'this is a change', |
| 372 'STORY=http://tracker/123') | 380 'STORY=http://tracker/123') |
| 373 files = [ | 381 files = [ |
| 374 ['A', 'haspresubmit\\blat.cc'], | 382 ['A', 'haspresubmit\\blat.cc'], |
| 375 ] | 383 ] |
| 376 ci = gcl.ChangeInfo(name='mychange', | |
| 377 description='\n'.join(description_lines), | |
| 378 files=files) | |
| 379 | |
| 380 output = StringIO.StringIO() | |
| 381 input = StringIO.StringIO('y\n') | |
| 382 # Always fail. | |
| 383 DEFAULT_SCRIPT = """ | 384 DEFAULT_SCRIPT = """ |
| 384 def CheckChangeOnUpload(input_api, output_api): | 385 def CheckChangeOnUpload(input_api, output_api): |
| 385 print 'This is a test' | |
| 386 return [output_api.PresubmitError("!!")] | 386 return [output_api.PresubmitError("!!")] |
| 387 def CheckChangeOnCommit(input_api, output_api): | 387 def CheckChangeOnCommit(input_api, output_api): |
| 388 raise Exception("Test error") | 388 raise Exception("Test error") |
| 389 """ | 389 """ |
| 390 def MockReadFile(dummy): | 390 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 391 return '' | 391 presubmit.os.path.isfile(path).AndReturn(False) |
| 392 gcl.ReadFile = MockReadFile | 392 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(False) |
| 393 def MockIsFile(dummy): | 393 self.mox.ReplayAll() |
| 394 return False | 394 |
| 395 os.path.isfile = MockIsFile | 395 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 396 description='\n'.join(description_lines), | |
| 397 files=files) | |
| 398 | |
| 399 | |
| 400 output = StringIO.StringIO() | |
| 401 input = StringIO.StringIO('y\n') | |
| 402 # Always fail. | |
| 396 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 403 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 397 DEFAULT_SCRIPT)) | 404 DEFAULT_SCRIPT)) |
| 398 self.assertEquals(output.getvalue().count('!!'), 1) | 405 self.assertEquals(output.getvalue().count('!!'), 1) |
| 399 | 406 |
| 400 def testDirectoryHandling(self): | 407 def testDirectoryHandling(self): |
| 401 files = [ | 408 files = [ |
| 402 ['A', 'isdir'], | 409 ['A', 'isdir'], |
| 403 ['A', 'isdir\\blat.cc'], | 410 ['A', 'isdir\\blat.cc'], |
| 404 ] | 411 ] |
| 405 os.path.exists('isdir').AndReturn(True) | 412 presubmit.os.path.exists('isdir').AndReturn(True) |
| 406 os.path.isdir('isdir').AndReturn(True) | 413 presubmit.os.path.isdir('isdir').AndReturn(True) |
| 407 os.path.exists(os.path.join('isdir', 'blat.cc')).AndReturn(True) | 414 presubmit.os.path.exists(presubmit.os.path.join('isdir', 'blat.cc') |
| 408 os.path.isdir(os.path.join('isdir', 'blat.cc')).AndReturn(False) | 415 ).AndReturn(True) |
| 416 presubmit.os.path.isdir(presubmit.os.path.join('isdir', 'blat.cc') | |
| 417 ).AndReturn(False) | |
| 409 self.mox.ReplayAll() | 418 self.mox.ReplayAll() |
| 410 ci = gcl.ChangeInfo(name='mychange', | 419 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 411 description='foo', | 420 description='foo', |
| 412 files=files) | 421 files=files) |
| 413 change = presubmit.GclChange(ci) | 422 change = presubmit.GclChange(ci) |
| 414 | 423 |
| 415 affected_files = change.AffectedFiles(include_dirs=False) | 424 affected_files = change.AffectedFiles(include_dirs=False) |
| 416 self.failUnless(len(affected_files) == 1) | 425 self.failUnless(len(affected_files) == 1) |
| 417 self.failUnless(affected_files[0].LocalPath().endswith('blat.cc')) | 426 self.failUnless(affected_files[0].LocalPath().endswith('blat.cc')) |
| 418 self.mox.VerifyAll() | |
| 419 affected_files_and_dirs = change.AffectedFiles(include_dirs=True) | 427 affected_files_and_dirs = change.AffectedFiles(include_dirs=True) |
| 420 self.failUnless(len(affected_files_and_dirs) == 2) | 428 self.failUnless(len(affected_files_and_dirs) == 2) |
| 421 | 429 |
| 422 def testTags(self): | 430 def testTags(self): |
| 423 DEFAULT_SCRIPT = """ | 431 DEFAULT_SCRIPT = """ |
| 424 def CheckChangeOnUpload(input_api, output_api): | 432 def CheckChangeOnUpload(input_api, output_api): |
| 425 if input_api.change.tags['BUG'] != 'boo': | 433 if input_api.change.tags['BUG'] != 'boo': |
| 426 return [output_api.PresubmitError('Tag parsing failed. 1')] | 434 return [output_api.PresubmitError('Tag parsing failed. 1')] |
| 427 if input_api.change.tags['STORY'] != 'http://tracker.com/42': | 435 if input_api.change.tags['STORY'] != 'http://tracker.com/42': |
| 428 return [output_api.PresubmitError('Tag parsing failed. 2')] | 436 return [output_api.PresubmitError('Tag parsing failed. 2')] |
| 429 if 'TEST' in input_api.change.tags: | 437 if 'TEST' in input_api.change.tags: |
| 430 return [output_api.PresubmitError('Tag parsing failed. 3')] | 438 return [output_api.PresubmitError('Tag parsing failed. 3')] |
| 431 if input_api.change.DescriptionText() != 'Blah Blah': | 439 if input_api.change.DescriptionText() != 'Blah Blah': |
| 432 return [output_api.PresubmitError('Tag parsing failed. 4 ' + | 440 return [output_api.PresubmitError('Tag parsing failed. 4 ' + |
| 433 input_api.change.DescriptionText())] | 441 input_api.change.DescriptionText())] |
| 434 if (input_api.change.FullDescriptionText() != | 442 if (input_api.change.FullDescriptionText() != |
| 435 'Blah Blah\\n\\nSTORY=http://tracker.com/42\\nBUG=boo\\n'): | 443 'Blah Blah\\n\\nSTORY=http://tracker.com/42\\nBUG=boo\\n'): |
| 436 return [output_api.PresubmitError('Tag parsing failed. 5 ' + | 444 return [output_api.PresubmitError('Tag parsing failed. 5 ' + |
| 437 input_api.change.FullDescriptionText())] | 445 input_api.change.FullDescriptionText())] |
| 438 return [output_api.PresubmitNotifyResult(input_api.change.tags['STORY'])] | 446 return [output_api.PresubmitNotifyResult(input_api.change.tags['STORY'])] |
| 439 def CheckChangeOnCommit(input_api, output_api): | 447 def CheckChangeOnCommit(input_api, output_api): |
| 440 raise Exception("Test error") | 448 raise Exception("Test error") |
| 441 """ | 449 """ |
| 442 def MockReadFile(dummy): | 450 self.mox.ReplayAll() |
| 443 return '' | 451 change = presubmit.gcl.ChangeInfo( |
| 444 gcl.ReadFile = MockReadFile | |
| 445 def MockIsFile(dummy): | |
| 446 return False | |
| 447 os.path.isfile = MockIsFile | |
| 448 change = gcl.ChangeInfo( | |
| 449 name='foo', | 452 name='foo', |
| 450 description="Blah Blah\n\nSTORY=http://tracker.com/42\nBUG=boo\n") | 453 description="Blah Blah\n\nSTORY=http://tracker.com/42\nBUG=boo\n") |
| 451 output = StringIO.StringIO() | 454 output = StringIO.StringIO() |
| 452 input = StringIO.StringIO('y\n') | 455 input = StringIO.StringIO('y\n') |
| 453 self.failUnless(presubmit.DoPresubmitChecks(change, False, True, output, | 456 self.failUnless(presubmit.DoPresubmitChecks(change, False, True, output, |
| 454 input, DEFAULT_SCRIPT)) | 457 input, DEFAULT_SCRIPT)) |
| 455 self.assertEquals(output.getvalue(), | 458 self.assertEquals(output.getvalue(), |
| 456 ('Warning, no presubmit.py found.\n' | 459 ('Warning, no presubmit.py found.\n' |
| 457 'Running default presubmit script.\n\n' | 460 'Running default presubmit script.\n\n' |
| 458 '** Presubmit Messages **\n\n' | 461 '** Presubmit Messages **\n\n' |
| 459 'http://tracker.com/42\n\n')) | 462 'http://tracker.com/42\n\n')) |
| 460 | 463 |
| 461 | 464 |
| 462 class InputApiUnittest(PresubmitTestsBase): | 465 class InputApiUnittest(PresubmitTestsBase): |
| 463 """Tests presubmit.InputApi.""" | 466 """Tests presubmit.InputApi.""" |
| 464 def testMembersChanged(self): | 467 def testMembersChanged(self): |
| 465 members = [ | 468 members = [ |
| 466 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', | 469 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', |
| 467 'DepotToLocalPath', 'LocalPaths', 'LocalToDepotPath', | 470 'DepotToLocalPath', 'LocalPaths', 'LocalToDepotPath', |
| 468 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', | 471 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', |
| 469 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', | 472 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', |
| 470 'marshal', 'os_path', 'pickle', 'platform', | 473 'marshal', 'os_path', 'pickle', 'platform', |
| 471 're', 'subprocess', 'tempfile', 'urllib2', 'version', | 474 're', 'subprocess', 'tempfile', 'urllib2', 'version', |
| 472 ] | 475 ] |
| 473 # If this test fails, you should add the relevant test. | 476 # If this test fails, you should add the relevant test. |
| 474 self.compareMembers(presubmit.InputApi(None, './.'), members) | 477 self.compareMembers(presubmit.InputApi(None, './.'), members) |
| 475 | 478 |
| 476 def testDepotToLocalPath(self): | 479 def testDepotToLocalPath(self): |
| 477 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn:/foo/smurf') | 480 presubmit.gclient.CaptureSVNInfo('svn://foo/smurf').AndReturn( |
| 478 self.failUnless(path == 'smurf') | 481 {'Path': 'prout'}) |
| 482 presubmit.gclient.CaptureSVNInfo('svn:/foo/notfound/burp').AndReturn({}) | |
| 483 self.mox.ReplayAll() | |
| 484 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn://foo/smurf') | |
| 485 self.failUnless(path == 'prout') | |
| 479 path = presubmit.InputApi(None, './p').DepotToLocalPath( | 486 path = presubmit.InputApi(None, './p').DepotToLocalPath( |
| 480 'svn:/foo/notfound/burp') | 487 'svn:/foo/notfound/burp') |
| 481 self.failUnless(path == None) | 488 self.failUnless(path == None) |
| 482 | 489 |
| 483 def testLocalToDepotPath(self): | 490 def testLocalToDepotPath(self): |
| 491 presubmit.gclient.CaptureSVNInfo('smurf').AndReturn({'URL': 'svn://foo'}) | |
| 492 presubmit.gclient.CaptureSVNInfo('notfound-food').AndReturn({}) | |
| 493 self.mox.ReplayAll() | |
| 484 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') | 494 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') |
| 485 self.failUnless(path == 'svn:/foo/smurf') | 495 self.assertEqual(path, 'svn://foo') |
| 486 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') | 496 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') |
| 487 self.failUnless(path == None) | 497 self.failUnless(path == None) |
| 488 | 498 |
| 489 def testInputApiConstruction(self): | 499 def testInputApiConstruction(self): |
| 490 # Fudge the change object, it's not used during construction anyway | 500 # Fudge the change object, it's not used during construction anyway |
| 491 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') | 501 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') |
| 492 self.failUnless(api.PresubmitLocalPath() == 'foo/path') | 502 self.failUnless(api.PresubmitLocalPath() == 'foo/path') |
| 493 self.failUnless(api.change == 42) | 503 self.failUnless(api.change == 42) |
| 494 | 504 |
| 495 def testInputApiPresubmitScriptFiltering(self): | 505 def testInputApiPresubmitScriptFiltering(self): |
| 496 description_lines = ('Hello there', | 506 description_lines = ('Hello there', |
| 497 'this is a change', | 507 'this is a change', |
| 498 'BUG=123', | 508 'BUG=123', |
| 499 ' STORY =http://foo/ \t', | 509 ' STORY =http://foo/ \t', |
| 500 'and some more regular text') | 510 'and some more regular text') |
| 501 files = [ | 511 files = [ |
| 502 ['A', os.path.join('foo', 'blat.cc')], | 512 ['A', presubmit.os.path.join('foo', 'blat.cc')], |
| 503 ['M', os.path.join('foo', 'blat', 'binary.dll')], | 513 ['M', presubmit.os.path.join('foo', 'blat', 'binary.dll')], |
| 504 ['D', 'foo/mat/beingdeleted.txt'], | 514 ['D', 'foo/mat/beingdeleted.txt'], |
| 505 ['M', 'flop/notfound.txt'], | 515 ['M', 'flop/notfound.txt'], |
| 506 ['A', 'boo/flap.h'], | 516 ['A', 'boo/flap.h'], |
| 507 ] | 517 ] |
| 508 | 518 |
| 509 os.path.exists(os.path.join('foo', 'blat.cc')).AndReturn(True) | 519 blat = presubmit.os.path.join('foo', 'blat.cc') |
| 510 os.path.isdir(os.path.join('foo', 'blat.cc')).AndReturn(False) | 520 binary = presubmit.os.path.join('foo', 'blat', 'binary.dll') |
| 511 os.path.exists(os.path.join('foo', 'blat', 'binary.dll')).AndReturn(True) | 521 beingdeleted = presubmit.os.path.join('foo', 'mat', 'beingdeleted.txt') |
| 512 os.path.isdir(os.path.join('foo', 'blat', 'binary.dll')).AndReturn(False) | 522 notfound = presubmit.os.path.join('flop', 'notfound.txt') |
| 513 os.path.exists(os.path.join('foo', 'mat', 'beingdeleted.txt')).AndReturn( | 523 flap = presubmit.os.path.join('boo', 'flap.h') |
| 514 False) | 524 presubmit.os.path.exists(blat).AndReturn(True) |
| 515 os.path.exists(os.path.join('flop', 'notfound.txt')).AndReturn(False) | 525 presubmit.os.path.isdir(blat).AndReturn(False) |
| 516 os.path.exists(os.path.join('boo', 'flap.h')).AndReturn(True) | 526 presubmit.os.path.exists(binary).AndReturn(True) |
| 517 os.path.isdir(os.path.join('boo', 'flap.h')).AndReturn(False) | 527 presubmit.os.path.isdir(binary).AndReturn(False) |
| 528 presubmit.os.path.exists(beingdeleted).AndReturn(False) | |
| 529 presubmit.os.path.exists(notfound).AndReturn(False) | |
| 530 presubmit.os.path.exists(flap).AndReturn(True) | |
| 531 presubmit.os.path.isdir(flap).AndReturn(False) | |
| 532 presubmit.gclient.CaptureSVNInfo(beingdeleted).AndReturn({}) | |
| 533 presubmit.gclient.CaptureSVNInfo(notfound).AndReturn({}) | |
| 534 presubmit.gcl.GetSVNFileProperty(blat, 'svn:mime-type').AndReturn(None) | |
| 535 presubmit.gcl.GetSVNFileProperty(binary, 'svn:mime-type').AndReturn( | |
| 536 'application/octet-stream') | |
| 537 presubmit.gcl.ReadFile(blat).AndReturn('whatever\ncookie') | |
| 518 self.mox.ReplayAll() | 538 self.mox.ReplayAll() |
| 519 ci = gcl.ChangeInfo(name='mychange', | 539 |
| 520 description='\n'.join(description_lines), | 540 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 521 files=files) | 541 description='\n'.join(description_lines), |
| 542 files=files) | |
| 522 change = presubmit.GclChange(ci) | 543 change = presubmit.GclChange(ci) |
| 523 | 544 |
| 524 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') | 545 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') |
| 525 | 546 |
| 526 affected_files = api.AffectedFiles() | 547 affected_files = api.AffectedFiles() |
| 527 self.assertEquals(len(affected_files), 3) | 548 self.assertEquals(len(affected_files), 3) |
| 528 self.assertEquals(affected_files[0].LocalPath(), | 549 self.assertEquals(affected_files[0].LocalPath(), |
| 529 presubmit.normpath('foo/blat.cc')) | 550 presubmit.normpath('foo/blat.cc')) |
| 530 self.assertEquals(affected_files[1].LocalPath(), | 551 self.assertEquals(affected_files[1].LocalPath(), |
| 531 presubmit.normpath('foo/blat/binary.dll')) | 552 presubmit.normpath('foo/blat/binary.dll')) |
| 532 self.assertEquals(affected_files[2].LocalPath(), | 553 self.assertEquals(affected_files[2].LocalPath(), |
| 533 presubmit.normpath('foo/mat/beingdeleted.txt')) | 554 presubmit.normpath('foo/mat/beingdeleted.txt')) |
| 534 | 555 |
| 535 rhs_lines = [] | 556 rhs_lines = [] |
| 536 for line in api.RightHandSideLines(): | 557 for line in api.RightHandSideLines(): |
| 537 rhs_lines.append(line) | 558 rhs_lines.append(line) |
| 538 self.failUnless(len(rhs_lines) == 2) | 559 self.assertEquals(len(rhs_lines), 2) |
| 539 self.assertEqual(rhs_lines[0][0].LocalPath(), | 560 self.assertEqual(rhs_lines[0][0].LocalPath(), |
| 540 presubmit.normpath('foo/blat.cc')) | 561 presubmit.normpath('foo/blat.cc')) |
| 541 self.mox.VerifyAll() | |
| 542 | 562 |
| 543 def testGetAbsoluteLocalPath(self): | 563 def testGetAbsoluteLocalPath(self): |
| 544 # Regression test for bug of presubmit stuff that relies on invoking | 564 # Regression test for bug of presubmit stuff that relies on invoking |
| 545 # SVN (e.g. to get mime type of file) not working unless gcl invoked | 565 # SVN (e.g. to get mime type of file) not working unless gcl invoked |
| 546 # from the client root (e.g. if you were at 'src' and did 'cd base' before | 566 # from the client root (e.g. if you were at 'src' and did 'cd base' before |
| 547 # invoking 'gcl upload' it would fail because svn wouldn't find the files | 567 # invoking 'gcl upload' it would fail because svn wouldn't find the files |
| 548 # the presubmit script was asking about). | 568 # the presubmit script was asking about). |
| 549 files = [ | 569 files = [ |
| 550 ['A', 'isdir'], | 570 ['A', 'isdir'], |
| 551 ['A', os.path.join('isdir', 'blat.cc')] | 571 ['A', presubmit.os.path.join('isdir', 'blat.cc')] |
| 552 ] | 572 ] |
| 553 ci = gcl.ChangeInfo(name='mychange', | 573 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 554 description='', | 574 description='', |
| 555 files=files) | 575 files=files) |
| 556 # It doesn't make sense on non-Windows platform. This is somewhat hacky, | 576 # It doesn't make sense on non-Windows platform. This is somewhat hacky, |
| 557 # but it is needed since we can't just use os.path.join('c:', 'temp'). | 577 # but it is needed since we can't just use os.path.join('c:', 'temp'). |
| 558 change = presubmit.GclChange(ci, 'c:' + os.sep + 'temp') | 578 change = presubmit.GclChange(ci, 'c:' + presubmit.os.sep + 'temp') |
| 559 affected_files = change.AffectedFiles(include_dirs=True) | 579 affected_files = change.AffectedFiles(include_dirs=True) |
| 560 # Local paths should remain the same | 580 # Local paths should remain the same |
| 561 self.failUnless(affected_files[0].LocalPath() == | 581 self.failUnless(affected_files[0].LocalPath() == |
| 562 presubmit.normpath('isdir')) | 582 presubmit.normpath('isdir')) |
| 563 self.failUnless(affected_files[1].LocalPath() == | 583 self.failUnless(affected_files[1].LocalPath() == |
| 564 presubmit.normpath('isdir/blat.cc')) | 584 presubmit.normpath('isdir/blat.cc')) |
| 565 # Absolute paths should be prefixed | 585 # Absolute paths should be prefixed |
| 566 self.failUnless(affected_files[0].AbsoluteLocalPath() == | 586 self.failUnless(affected_files[0].AbsoluteLocalPath() == |
| 567 presubmit.normpath('c:/temp/isdir')) | 587 presubmit.normpath('c:/temp/isdir')) |
| 568 self.failUnless(affected_files[1].AbsoluteLocalPath() == | 588 self.failUnless(affected_files[1].AbsoluteLocalPath() == |
| 569 presubmit.normpath('c:/temp/isdir/blat.cc')) | 589 presubmit.normpath('c:/temp/isdir/blat.cc')) |
| 570 | 590 |
| 571 # New helper functions need to work | 591 # New helper functions need to work |
| 572 absolute_paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) | 592 absolute_paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) |
| 573 api = presubmit.InputApi(change=change, presubmit_path='isdir/PRESUBMIT.py') | 593 api = presubmit.InputApi(change=change, |
| 594 presubmit_path='isdir/PRESUBMIT.py') | |
| 574 absolute_paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) | 595 absolute_paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) |
| 575 for absolute_paths in [absolute_paths_from_change, | 596 for absolute_paths in [absolute_paths_from_change, |
| 576 absolute_paths_from_api]: | 597 absolute_paths_from_api]: |
| 577 self.failUnless(absolute_paths[0] == presubmit.normpath('c:/temp/isdir')) | 598 self.failUnless(absolute_paths[0] == presubmit.normpath('c:/temp/isdir')) |
| 578 self.failUnless(absolute_paths[1] == | 599 self.failUnless(absolute_paths[1] == |
| 579 presubmit.normpath('c:/temp/isdir/blat.cc')) | 600 presubmit.normpath('c:/temp/isdir/blat.cc')) |
| 580 | 601 |
| 581 def testDeprecated(self): | 602 def testDeprecated(self): |
| 582 presubmit.warnings.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), | 603 presubmit.warnings.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), |
| 583 stacklevel=2) | 604 stacklevel=2) |
| 584 self.mox.ReplayAll() | 605 self.mox.ReplayAll() |
| 585 change = presubmit.GclChange(gcl.ChangeInfo(name='mychange', | 606 change = presubmit.GclChange( |
| 586 description='Bleh\n')) | 607 presubmit.gcl.ChangeInfo(name='mychange', description='Bleh\n')) |
| 587 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') | 608 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') |
| 588 api.AffectedTextFiles(include_deletes=False) | 609 api.AffectedTextFiles(include_deletes=False) |
| 589 self.mox.VerifyAll() | |
| 590 | 610 |
| 591 | 611 |
| 592 class OuputApiUnittest(PresubmitTestsBase): | 612 class OuputApiUnittest(PresubmitTestsBase): |
| 593 """Tests presubmit.OutputApi.""" | 613 """Tests presubmit.OutputApi.""" |
| 594 def testMembersChanged(self): | 614 def testMembersChanged(self): |
| 595 members = [ | 615 members = [ |
| 596 'MailTextResult', 'PresubmitError', 'PresubmitNotifyResult', | 616 'MailTextResult', 'PresubmitError', 'PresubmitNotifyResult', |
| 597 'PresubmitPromptWarning', 'PresubmitResult', | 617 'PresubmitPromptWarning', 'PresubmitResult', |
| 598 ] | 618 ] |
| 599 # If this test fails, you should add the relevant test. | 619 # If this test fails, you should add the relevant test. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 def testMembersChanged(self): | 667 def testMembersChanged(self): |
| 648 members = [ | 668 members = [ |
| 649 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', 'LocalPath', | 669 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', 'LocalPath', |
| 650 'NewContents', 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', | 670 'NewContents', 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', |
| 651 ] | 671 ] |
| 652 # If this test fails, you should add the relevant test. | 672 # If this test fails, you should add the relevant test. |
| 653 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) | 673 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) |
| 654 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) | 674 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) |
| 655 | 675 |
| 656 def testAffectedFile(self): | 676 def testAffectedFile(self): |
| 677 path = presubmit.os.path.join('foo', 'blat.cc') | |
| 678 presubmit.os.path.exists(path).AndReturn(True) | |
| 679 presubmit.os.path.isdir(path).AndReturn(False) | |
| 680 presubmit.gcl.ReadFile(path).AndReturn('whatever\ncookie') | |
| 681 presubmit.gclient.CaptureSVNInfo(path).AndReturn( | |
| 682 {'URL': 'svn:/foo/foo/blat.cc'}) | |
| 683 self.mox.ReplayAll() | |
| 657 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M') | 684 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M') |
| 658 os.path.exists(os.path.join('foo', 'blat.cc')).AndReturn(False) | |
| 659 self.mox.ReplayAll() | |
| 660 self.failUnless(af.ServerPath() == 'svn:/foo/foo/blat.cc') | 685 self.failUnless(af.ServerPath() == 'svn:/foo/foo/blat.cc') |
| 661 self.failUnless(af.LocalPath() == presubmit.normpath('foo/blat.cc')) | 686 self.failUnless(af.LocalPath() == presubmit.normpath('foo/blat.cc')) |
| 662 self.failUnless(af.Action() == 'M') | 687 self.failUnless(af.Action() == 'M') |
| 663 self.failUnless(af.NewContents() == ['one:%s' % af.LocalPath(), | 688 self.assertEquals(af.NewContents(), ['whatever', 'cookie']) |
| 664 'two:%s' % af.LocalPath()]) | |
| 665 self.mox.VerifyAll() | |
| 666 | |
| 667 af = presubmit.AffectedFile('notfound.cc', 'A') | 689 af = presubmit.AffectedFile('notfound.cc', 'A') |
| 668 self.failUnless(af.ServerPath() == '') | 690 self.failUnless(af.ServerPath() == '') |
| 669 | 691 |
| 670 def testProperty(self): | 692 def testProperty(self): |
| 693 presubmit.gcl.GetSVNFileProperty('foo.cc', 'svn:secret-property' | |
| 694 ).AndReturn('secret-property-value') | |
| 695 self.mox.ReplayAll() | |
| 671 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') | 696 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') |
| 697 # Verify cache coherency. | |
| 698 self.failUnless(affected_file.Property('svn:secret-property') == | |
| 699 'secret-property-value') | |
| 672 self.failUnless(affected_file.Property('svn:secret-property') == | 700 self.failUnless(affected_file.Property('svn:secret-property') == |
| 673 'secret-property-value') | 701 'secret-property-value') |
| 674 | 702 |
| 675 def testIsDirectoryNotExists(self): | 703 def testIsDirectoryNotExists(self): |
| 676 os.path.exists('foo.cc').AndReturn(False) | 704 presubmit.os.path.exists('foo.cc').AndReturn(False) |
| 705 presubmit.gclient.CaptureSVNInfo('foo.cc').AndReturn({}) | |
| 677 self.mox.ReplayAll() | 706 self.mox.ReplayAll() |
| 678 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') | 707 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') |
| 679 # Verify cache coherency. | 708 # Verify cache coherency. |
| 680 self.failIf(affected_file.IsDirectory()) | 709 self.failIf(affected_file.IsDirectory()) |
| 681 self.failIf(affected_file.IsDirectory()) | 710 self.failIf(affected_file.IsDirectory()) |
| 682 self.mox.VerifyAll() | |
| 683 | 711 |
| 684 def testIsDirectory(self): | 712 def testIsDirectory(self): |
| 685 os.path.exists('foo.cc').AndReturn(True) | 713 presubmit.os.path.exists('foo.cc').AndReturn(True) |
| 686 os.path.isdir('foo.cc').AndReturn(True) | 714 presubmit.os.path.isdir('foo.cc').AndReturn(True) |
| 687 self.mox.ReplayAll() | 715 self.mox.ReplayAll() |
| 688 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') | 716 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') |
| 689 # Verify cache coherency. | 717 # Verify cache coherency. |
| 690 self.failUnless(affected_file.IsDirectory()) | 718 self.failUnless(affected_file.IsDirectory()) |
| 691 self.failUnless(affected_file.IsDirectory()) | 719 self.failUnless(affected_file.IsDirectory()) |
| 692 self.mox.VerifyAll() | |
| 693 | 720 |
| 694 def testIsTextFile(self): | 721 def testIsTextFile(self): |
| 695 list = [presubmit.SvnAffectedFile('foo/blat.txt', 'M'), | 722 list = [presubmit.SvnAffectedFile('foo/blat.txt', 'M'), |
| 696 presubmit.SvnAffectedFile('foo/binary.blob', 'M'), | 723 presubmit.SvnAffectedFile('foo/binary.blob', 'M'), |
| 697 presubmit.SvnAffectedFile('blat/flop.txt', 'D')] | 724 presubmit.SvnAffectedFile('blat/flop.txt', 'D')] |
| 698 os.path.exists(os.path.join('foo', 'blat.txt')).AndReturn(True) | 725 blat = presubmit.os.path.join('foo', 'blat.txt') |
| 699 os.path.isdir(os.path.join('foo', 'blat.txt')).AndReturn(False) | 726 blob = presubmit.os.path.join('foo', 'binary.blob') |
| 700 os.path.exists(os.path.join('foo', 'binary.blob')).AndReturn(True) | 727 presubmit.os.path.exists(blat).AndReturn(True) |
| 701 os.path.isdir(os.path.join('foo', 'binary.blob')).AndReturn(False) | 728 presubmit.os.path.isdir(blat).AndReturn(False) |
| 729 presubmit.os.path.exists(blob).AndReturn(True) | |
| 730 presubmit.os.path.isdir(blob).AndReturn(False) | |
| 731 presubmit.gcl.GetSVNFileProperty(blat, 'svn:mime-type').AndReturn(None) | |
| 732 presubmit.gcl.GetSVNFileProperty(blob, 'svn:mime-type' | |
| 733 ).AndReturn('application/octet-stream') | |
| 702 self.mox.ReplayAll() | 734 self.mox.ReplayAll() |
| 703 | 735 |
| 704 output = filter(lambda x: x.IsTextFile(), list) | 736 output = filter(lambda x: x.IsTextFile(), list) |
| 705 self.failUnless(len(output) == 1) | 737 self.failUnless(len(output) == 1) |
| 706 self.failUnless(list[0] == output[0]) | 738 self.failUnless(list[0] == output[0]) |
| 707 self.mox.VerifyAll() | |
| 708 | 739 |
| 709 | 740 |
| 710 class CannedChecksUnittest(PresubmitTestsBase): | 741 class CannedChecksUnittest(PresubmitTestsBase): |
| 711 """Tests presubmit_canned_checks.py.""" | 742 """Tests presubmit_canned_checks.py.""" |
| 712 class MockInputApi(object): | 743 class MockInputApi(object): |
| 713 class MockUrllib2(object): | 744 class MockUrllib2(object): |
| 714 class urlopen(object): | 745 class urlopen(object): |
| 715 def __init__(self, url): | 746 def __init__(self, url): |
| 716 if url == 'url_to_open': | 747 if url == 'url_to_open': |
| 717 self.result = '1' | 748 self.result = '1' |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 842 # TODO(maruel): Add real tests. | 873 # TODO(maruel): Add real tests. |
| 843 self.failIf(presubmit_canned_checks.RunPythonUnitTests( | 874 self.failIf(presubmit_canned_checks.RunPythonUnitTests( |
| 844 self.MockInputApi(), | 875 self.MockInputApi(), |
| 845 presubmit.OutputApi, [])) | 876 presubmit.OutputApi, [])) |
| 846 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( | 877 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( |
| 847 self.MockInputApi(), | 878 self.MockInputApi(), |
| 848 presubmit.OutputApi, ['non_existent_module'])) | 879 presubmit.OutputApi, ['non_existent_module'])) |
| 849 | 880 |
| 850 if __name__ == '__main__': | 881 if __name__ == '__main__': |
| 851 unittest.main() | 882 unittest.main() |
| OLD | NEW |