| 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 exceptions | 8 import exceptions |
| 9 import random | |
| 10 import string | |
| 11 import StringIO | 9 import StringIO |
| 12 import unittest | 10 import unittest |
| 13 | 11 |
| 14 # Local imports | 12 # Local imports |
| 15 import __init__ | 13 import __init__ |
| 16 import presubmit_support as presubmit | 14 import presubmit_support as presubmit |
| 17 import presubmit_canned_checks | 15 import presubmit_canned_checks |
| 18 mox = __init__.mox | 16 mox = __init__.mox |
| 19 | 17 |
| 20 def String(max_length): | |
| 21 return ''.join([random.choice(string.letters) | |
| 22 for x in xrange(random.randint(1, max_length))]) | |
| 23 | |
| 24 def Strings(max_arg_count, max_arg_length): | |
| 25 return [String(max_arg_length) for x in xrange(max_arg_count)] | |
| 26 | |
| 27 def Args(max_arg_count=8, max_arg_length=16): | |
| 28 return Strings(max_arg_count, random.randint(1, max_arg_length)) | |
| 29 | |
| 30 def _DirElts(max_elt_count=4, max_elt_length=8): | |
| 31 return presubmit.os.sep.join(Strings(max_elt_count, max_elt_length)) | |
| 32 | |
| 33 def Dir(max_elt_count=4, max_elt_length=8): | |
| 34 return (random.choice((presubmit_support.os.sep, '')) + | |
| 35 _DirElts(max_elt_count, max_elt_length)) | |
| 36 | |
| 37 def Url(max_elt_count=4, max_elt_length=8): | |
| 38 return ('svn://random_host:port/a' + | |
| 39 _DirElts(max_elt_count, max_elt_length).replace(os.sep, '/')) | |
| 40 | |
| 41 def RootDir(max_elt_count=4, max_elt_length=8): | |
| 42 return presubmit.os.sep + _DirElts(max_elt_count, max_elt_length) | |
| 43 | |
| 44 | 18 |
| 45 class PresubmitTestsBase(mox.MoxTestBase): | 19 class PresubmitTestsBase(mox.MoxTestBase): |
| 46 """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.""" |
| 47 presubmit_text = """ | 21 presubmit_text = """ |
| 48 def CheckChangeOnUpload(input_api, output_api): | 22 def CheckChangeOnUpload(input_api, output_api): |
| 49 if not input_api.change.NOSUCHKEY: | 23 if not input_api.change.NOSUCHKEY: |
| 50 return [output_api.PresubmitError("!!")] | 24 return [output_api.PresubmitError("!!")] |
| 51 elif not input_api.change.REALLYNOSUCHKEY: | 25 elif not input_api.change.REALLYNOSUCHKEY: |
| 52 return [output_api.PresubmitPromptWarning("??")] | 26 return [output_api.PresubmitPromptWarning("??")] |
| 53 elif not input_api.change.REALLYABSOLUTELYNOSUCHKEY: | 27 elif not input_api.change.REALLYABSOLUTELYNOSUCHKEY: |
| 54 return [output_api.PresubmitPromptWarning("??"), | 28 return [output_api.PresubmitPromptWarning("??"), |
| 55 output_api.PresubmitError("XX!!XX")] | 29 output_api.PresubmitError("XX!!XX")] |
| 56 else: | 30 else: |
| 57 return () | 31 return () |
| 58 """ | 32 """ |
| 59 | 33 |
| 60 def setUp(self): | 34 def setUp(self): |
| 61 mox.MoxTestBase.setUp(self) | 35 mox.MoxTestBase.setUp(self) |
| 62 self.mox.StubOutWithMock(presubmit, 'warnings') | 36 self.mox.StubOutWithMock(presubmit, 'warnings') |
| 63 # Stub out 'os' but keep os.path.dirname/join/normpath and os.sep. | 37 # Stub out 'os' but keep os.path.dirname/join/normpath. |
| 64 os_sep = presubmit.os.sep | 38 path_join = presubmit.os.path.join |
| 65 os_path_join = presubmit.os.path.join | 39 path_dirname = presubmit.os.path.dirname |
| 66 os_path_dirname = presubmit.os.path.dirname | 40 path_normpath = presubmit.os.path.normpath |
| 67 os_path_normpath = presubmit.os.path.normpath | |
| 68 self.mox.StubOutWithMock(presubmit, 'os') | 41 self.mox.StubOutWithMock(presubmit, 'os') |
| 69 self.mox.StubOutWithMock(presubmit.os, 'path') | 42 self.mox.StubOutWithMock(presubmit.os, 'path') |
| 70 presubmit.os.sep = os_sep | 43 presubmit.os.path.join = path_join |
| 71 presubmit.os.path.join = os_path_join | 44 presubmit.os.path.dirname = path_dirname |
| 72 presubmit.os.path.dirname = os_path_dirname | 45 presubmit.os.path.normpath = path_normpath |
| 73 presubmit.os.path.normpath = os_path_normpath | |
| 74 self.mox.StubOutWithMock(presubmit, 'sys') | 46 self.mox.StubOutWithMock(presubmit, 'sys') |
| 75 # Special mocks. | 47 # Special mocks. |
| 76 def MockAbsPath(f): | 48 def MockAbsPath(f): |
| 77 return f | 49 return f |
| 78 presubmit.os.path.abspath = MockAbsPath | 50 presubmit.os.path.abspath = MockAbsPath |
| 79 self.mox.StubOutWithMock(presubmit.gcl, 'GetRepositoryRoot') | 51 self.mox.StubOutWithMock(presubmit.gcl, 'GetRepositoryRoot') |
| 80 fake_root_dir = RootDir() | |
| 81 self.fake_root_dir = fake_root_dir | |
| 82 def MockGetRepositoryRoot(): | 52 def MockGetRepositoryRoot(): |
| 83 return fake_root_dir | 53 return '' |
| 84 presubmit.gcl.GetRepositoryRoot = MockGetRepositoryRoot | 54 presubmit.gcl.GetRepositoryRoot = MockGetRepositoryRoot |
| 85 self.mox.StubOutWithMock(presubmit.gclient, 'CaptureSVNInfo') | 55 self.mox.StubOutWithMock(presubmit.gclient, 'CaptureSVNInfo') |
| 86 self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty') | 56 self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty') |
| 87 self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile') | 57 self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile') |
| 88 | 58 |
| 89 @staticmethod | 59 @staticmethod |
| 90 def MakeBasicChange(name, description): | 60 def MakeBasicChange(name, description): |
| 91 ci = presubmit.gcl.ChangeInfo(name=name, description=description) | 61 ci = presubmit.gcl.ChangeInfo(name=name, description=description) |
| 92 change = presubmit.GclChange(ci) | 62 change = presubmit.GclChange(ci) |
| 93 return change | 63 return change |
| 94 | 64 |
| 95 def compareMembers(self, object, members): | 65 def compareMembers(self, object, members): |
| 96 """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!""" |
| 97 # 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 |
| 98 # be for public use. | 68 # be for public use. |
| 99 actual_members = [x for x in sorted(dir(object)) | 69 actual_members = [x for x in sorted(dir(object)) |
| 100 if not x.startswith('_')] | 70 if not x.startswith('_')] |
| 101 self.assertEqual(actual_members, sorted(members)) | 71 self.assertEqual(actual_members, sorted(members)) |
| 102 | 72 |
| 103 | 73 |
| 104 class PresubmitUnittest(PresubmitTestsBase): | 74 class PresubmitUnittest(PresubmitTestsBase): |
| 105 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" | 75 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" |
| 106 def testMembersChanged(self): | 76 def testMembersChanged(self): |
| 107 self.mox.ReplayAll() | |
| 108 members = [ | 77 members = [ |
| 109 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', | 78 'AffectedFile', 'DoPresubmitChecks', 'GclChange', 'InputApi', |
| 110 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', | 79 'ListRelevantPresubmitFiles', 'Main', 'NotImplementedException', |
| 111 'OutputApi', 'ParseFiles', 'PresubmitExecuter', | 80 'OutputApi', 'ParseFiles', 'PresubmitExecuter', |
| 112 'ScanSubDirs', 'SvnAffectedFile', | 81 'ScanSubDirs', 'SvnAffectedFile', |
| 113 'cPickle', 'cStringIO', 'deprecated', 'exceptions', | 82 'cPickle', 'cStringIO', 'deprecated', 'exceptions', |
| 114 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', | 83 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', |
| 115 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', | 84 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', |
| 116 'tempfile', 'types', 'urllib2', 'warnings', | 85 'tempfile', 'types', 'urllib2', 'warnings', |
| 117 ] | 86 ] |
| 118 # If this test fails, you should add the relevant test. | 87 # If this test fails, you should add the relevant test. |
| 119 self.compareMembers(presubmit, members) | 88 self.compareMembers(presubmit, members) |
| 120 | 89 |
| 121 def testListRelevantPresubmitFiles(self): | 90 def testListRelevantPresubmitFiles(self): |
| 122 join = presubmit.os.path.join | 91 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 123 files = [ | 92 presubmit.os.path.isfile( |
| 124 'blat.cc', | 93 presubmit.os.path.join('foo/haspresubmit/yodle', |
| 125 join('foo', 'haspresubmit', 'yodle', 'smart.h'), | 94 'PRESUBMIT.py')).AndReturn(False) |
| 126 join('moo', 'mat', 'gat', 'yo.h'), | 95 presubmit.os.path.isfile( |
| 127 join('foo', 'luck.h'), | 96 presubmit.os.path.join('foo/haspresubmit', |
| 128 ] | 97 'PRESUBMIT.py')).AndReturn(True) |
| 129 presubmit.os.path.isfile(join(self.fake_root_dir, | 98 presubmit.os.path.isfile( |
| 130 'PRESUBMIT.py')).AndReturn(True) | 99 presubmit.os.path.join('foo', 'PRESUBMIT.py')).AndReturn(False) |
| 131 presubmit.os.path.isfile(join(self.fake_root_dir, 'foo', | 100 presubmit.os.path.isfile( |
| 132 'PRESUBMIT.py')).AndReturn(False) | 101 presubmit.os.path.join('moo/mat/gat', |
| 133 presubmit.os.path.isfile(join(self.fake_root_dir, 'foo', 'haspresubmit', | 102 'PRESUBMIT.py')).AndReturn(False) |
| 134 'PRESUBMIT.py')).AndReturn(True) | 103 presubmit.os.path.isfile( |
| 135 presubmit.os.path.isfile(join(self.fake_root_dir, 'foo', 'haspresubmit', | 104 presubmit.os.path.join('moo/mat', |
| 136 'yodle', 'PRESUBMIT.py')).AndReturn(True) | 105 'PRESUBMIT.py')).AndReturn(False) |
| 137 presubmit.os.path.isfile(join(self.fake_root_dir, 'moo', | 106 presubmit.os.path.isfile( |
| 138 'PRESUBMIT.py')).AndReturn(False) | 107 presubmit.os.path.join('moo', 'PRESUBMIT.py')).AndReturn(False) |
| 139 presubmit.os.path.isfile(join(self.fake_root_dir, 'moo', 'mat', | |
| 140 'PRESUBMIT.py')).AndReturn(False) | |
| 141 presubmit.os.path.isfile(join(self.fake_root_dir, 'moo', 'mat', 'gat', | |
| 142 'PRESUBMIT.py')).AndReturn(False) | |
| 143 #isfile(join('moo', 'PRESUBMIT.py')).AndReturn(False) | |
| 144 self.mox.ReplayAll() | 108 self.mox.ReplayAll() |
| 145 | 109 presubmit_files = presubmit.ListRelevantPresubmitFiles([ |
| 146 presubmit_files = presubmit.ListRelevantPresubmitFiles(files, | 110 'blat.cc', |
| 147 self.fake_root_dir) | 111 'foo/haspresubmit/yodle/smart.h', |
| 148 self.assertEqual(presubmit_files, | 112 'moo/mat/gat/yo.h', |
| 149 [ | 113 'foo/luck.h']) |
| 150 join(self.fake_root_dir, 'PRESUBMIT.py'), | 114 self.assertEqual(len(presubmit_files), 2) |
| 151 join(self.fake_root_dir, 'foo', 'haspresubmit', 'PRESUBMIT.py'), | 115 self.failUnless(presubmit.normpath('PRESUBMIT.py') in presubmit_files) |
| 152 join(self.fake_root_dir, 'foo', 'haspresubmit', 'yodle', | 116 self.failUnless(presubmit.normpath('foo/haspresubmit/PRESUBMIT.py') in |
| 153 'PRESUBMIT.py') | 117 presubmit_files) |
| 154 ]) | |
| 155 | 118 |
| 156 def testTagLineRe(self): | 119 def testTagLineRe(self): |
| 157 self.mox.ReplayAll() | |
| 158 m = presubmit.GclChange._tag_line_re.match(' BUG =1223, 1445 \t') | 120 m = presubmit.GclChange._tag_line_re.match(' BUG =1223, 1445 \t') |
| 159 self.failUnless(m) | 121 self.failUnless(m) |
| 160 self.failUnlessEqual(m.group('key'), 'BUG') | 122 self.failUnlessEqual(m.group('key'), 'BUG') |
| 161 self.failUnlessEqual(m.group('value'), '1223, 1445') | 123 self.failUnlessEqual(m.group('value'), '1223, 1445') |
| 162 | 124 |
| 163 def testGclChange(self): | 125 def testGclChange(self): |
| 164 description_lines = ('Hello there', | 126 description_lines = ('Hello there', |
| 165 'this is a change', | 127 'this is a change', |
| 166 'BUG=123', | 128 'BUG=123', |
| 167 ' STORY =http://foo/ \t', | 129 ' STORY =http://foo/ \t', |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 self.assertEquals(rhs_lines[3][1], 2) | 223 self.assertEquals(rhs_lines[3][1], 2) |
| 262 self.assertEquals(rhs_lines[3][2], 'there?') | 224 self.assertEquals(rhs_lines[3][2], 'there?') |
| 263 | 225 |
| 264 def testExecPresubmitScript(self): | 226 def testExecPresubmitScript(self): |
| 265 description_lines = ('Hello there', | 227 description_lines = ('Hello there', |
| 266 'this is a change', | 228 'this is a change', |
| 267 'STORY=http://tracker/123') | 229 'STORY=http://tracker/123') |
| 268 files = [ | 230 files = [ |
| 269 ['A', 'foo\\blat.cc'], | 231 ['A', 'foo\\blat.cc'], |
| 270 ] | 232 ] |
| 271 fake_presubmit = presubmit.os.path.join(self.fake_root_dir, 'PRESUBMIT.py') | |
| 272 self.mox.ReplayAll() | 233 self.mox.ReplayAll() |
| 273 | 234 |
| 274 ci = presubmit.gcl.ChangeInfo(name='mychange', | 235 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 275 description='\n'.join(description_lines), | 236 description='\n'.join(description_lines), |
| 276 files=files) | 237 files=files) |
| 277 | 238 |
| 278 executer = presubmit.PresubmitExecuter(ci, False) | 239 executer = presubmit.PresubmitExecuter(ci, False) |
| 279 self.failIf(executer.ExecPresubmitScript('', fake_presubmit)) | 240 self.failIf(executer.ExecPresubmitScript('', 'PRESUBMIT.py')) |
| 280 # No error if no on-upload entry point | 241 # No error if no on-upload entry point |
| 281 self.failIf(executer.ExecPresubmitScript( | 242 self.failIf(executer.ExecPresubmitScript( |
| 282 ('def CheckChangeOnCommit(input_api, output_api):\n' | 243 ('def CheckChangeOnCommit(input_api, output_api):\n' |
| 283 ' return (output_api.PresubmitError("!!"))\n'), | 244 ' return (output_api.PresubmitError("!!"))\n'), |
| 284 fake_presubmit | 245 'PRESUBMIT.py' |
| 285 )) | 246 )) |
| 286 | 247 |
| 287 executer = presubmit.PresubmitExecuter(ci, True) | 248 executer = presubmit.PresubmitExecuter(ci, True) |
| 288 # No error if no on-commit entry point | 249 # No error if no on-commit entry point |
| 289 self.failIf(executer.ExecPresubmitScript( | 250 self.failIf(executer.ExecPresubmitScript( |
| 290 ('def CheckChangeOnUpload(input_api, output_api):\n' | 251 ('def CheckChangeOnUpload(input_api, output_api):\n' |
| 291 ' return (output_api.PresubmitError("!!"))\n'), | 252 ' return (output_api.PresubmitError("!!"))\n'), |
| 292 fake_presubmit | 253 'PRESUBMIT.py' |
| 293 )) | 254 )) |
| 294 | 255 |
| 295 self.failIf(executer.ExecPresubmitScript( | 256 self.failIf(executer.ExecPresubmitScript( |
| 296 ('def CheckChangeOnUpload(input_api, output_api):\n' | 257 ('def CheckChangeOnUpload(input_api, output_api):\n' |
| 297 ' if not input_api.change.STORY:\n' | 258 ' if not input_api.change.STORY:\n' |
| 298 ' return (output_api.PresubmitError("!!"))\n' | 259 ' return (output_api.PresubmitError("!!"))\n' |
| 299 ' else:\n' | 260 ' else:\n' |
| 300 ' return ()'), | 261 ' return ()'), |
| 301 fake_presubmit | 262 'PRESUBMIT.py' |
| 302 )) | 263 )) |
| 303 | 264 |
| 304 self.failUnless(executer.ExecPresubmitScript( | 265 self.failUnless(executer.ExecPresubmitScript( |
| 305 ('def CheckChangeOnCommit(input_api, output_api):\n' | 266 ('def CheckChangeOnCommit(input_api, output_api):\n' |
| 306 ' if not input_api.change.NOSUCHKEY:\n' | 267 ' if not input_api.change.NOSUCHKEY:\n' |
| 307 ' return [output_api.PresubmitError("!!")]\n' | 268 ' return [output_api.PresubmitError("!!")]\n' |
| 308 ' else:\n' | 269 ' else:\n' |
| 309 ' return ()'), | 270 ' return ()'), |
| 310 fake_presubmit | 271 'PRESUBMIT.py' |
| 311 )) | 272 )) |
| 312 | 273 |
| 313 self.assertRaises(exceptions.RuntimeError, | 274 self.assertRaises(exceptions.RuntimeError, |
| 314 executer.ExecPresubmitScript, | 275 executer.ExecPresubmitScript, |
| 315 'def CheckChangeOnCommit(input_api, output_api):\n' | 276 'def CheckChangeOnCommit(input_api, output_api):\n' |
| 316 ' return "foo"', | 277 ' return "foo"', |
| 317 fake_presubmit) | 278 'PRESUBMIT.py') |
| 318 | 279 |
| 319 self.assertRaises(exceptions.RuntimeError, | 280 self.assertRaises(exceptions.RuntimeError, |
| 320 executer.ExecPresubmitScript, | 281 executer.ExecPresubmitScript, |
| 321 'def CheckChangeOnCommit(input_api, output_api):\n' | 282 'def CheckChangeOnCommit(input_api, output_api):\n' |
| 322 ' return ["foo"]', | 283 ' return ["foo"]', |
| 323 fake_presubmit) | 284 'PRESUBMIT.py') |
| 324 | 285 |
| 325 def testDoPresubmitChecks(self): | 286 def testDoPresubmitChecks(self): |
| 326 join = presubmit.os.path.join | |
| 327 description_lines = ('Hello there', | 287 description_lines = ('Hello there', |
| 328 'this is a change', | 288 'this is a change', |
| 329 'STORY=http://tracker/123') | 289 'STORY=http://tracker/123') |
| 330 files = [ | 290 files = [ |
| 331 ['A', join('haspresubmit', 'blat.cc')], | 291 ['A', 'haspresubmit\\blat.cc'], |
| 332 ] | 292 ] |
| 333 haspresubmit_path = join(self.fake_root_dir, 'haspresubmit', 'PRESUBMIT.py') | 293 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 334 root_path = join(self.fake_root_dir, 'PRESUBMIT.py') | 294 presubmit.os.path.isfile(path).AndReturn(True) |
| 335 presubmit.os.path.isfile(root_path).AndReturn(True) | 295 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 336 presubmit.os.path.isfile(haspresubmit_path).AndReturn(True) | 296 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) |
| 337 presubmit.gcl.ReadFile(root_path, | 297 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) |
| 338 'rU').AndReturn(self.presubmit_text) | |
| 339 presubmit.gcl.ReadFile(haspresubmit_path, | |
| 340 'rU').AndReturn(self.presubmit_text) | |
| 341 self.mox.ReplayAll() | 298 self.mox.ReplayAll() |
| 342 | 299 |
| 343 ci = presubmit.gcl.ChangeInfo(name='mychange', | 300 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 344 description='\n'.join(description_lines), | 301 description='\n'.join(description_lines), |
| 345 files=files) | 302 files=files) |
| 346 | 303 |
| 347 output = StringIO.StringIO() | 304 output = StringIO.StringIO() |
| 348 input = StringIO.StringIO('y\n') | 305 input = StringIO.StringIO('y\n') |
| 349 | 306 |
| 350 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 307 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 351 None)) | 308 None)) |
| 352 self.assertEqual(output.getvalue().count('!!'), 2) | 309 self.assertEqual(output.getvalue().count('!!'), 2) |
| 353 | 310 |
| 354 def testDoPresubmitChecksPromptsAfterWarnings(self): | 311 def testDoPresubmitChecksPromptsAfterWarnings(self): |
| 355 join = presubmit.os.path.join | |
| 356 description_lines = ('Hello there', | 312 description_lines = ('Hello there', |
| 357 'this is a change', | 313 'this is a change', |
| 358 'NOSUCHKEY=http://tracker/123') | 314 'NOSUCHKEY=http://tracker/123') |
| 359 files = [ | 315 files = [ |
| 360 ['A', join('haspresubmit', 'blat.cc')], | 316 ['A', 'haspresubmit\\blat.cc'], |
| 361 ] | 317 ] |
| 362 presubmit_path = join(self.fake_root_dir, 'PRESUBMIT.py') | 318 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 363 haspresubmit_path = join(self.fake_root_dir, 'haspresubmit', 'PRESUBMIT.py') | 319 presubmit.os.path.isfile(path).AndReturn(True) |
| 364 for i in range(2): | 320 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 365 presubmit.os.path.isfile(presubmit_path).AndReturn(True) | 321 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) |
| 366 presubmit.os.path.isfile(haspresubmit_path).AndReturn(True) | 322 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) |
| 367 presubmit.gcl.ReadFile(presubmit_path, 'rU' | 323 presubmit.os.path.isfile(path).AndReturn(True) |
| 368 ).AndReturn(self.presubmit_text) | 324 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 369 presubmit.gcl.ReadFile(haspresubmit_path, 'rU' | 325 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) |
| 370 ).AndReturn(self.presubmit_text) | 326 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) |
| 371 self.mox.ReplayAll() | 327 self.mox.ReplayAll() |
| 372 | 328 |
| 373 ci = presubmit.gcl.ChangeInfo(name='mychange', | 329 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 374 description='\n'.join(description_lines), | 330 description='\n'.join(description_lines), |
| 375 files=files) | 331 files=files) |
| 376 | 332 |
| 377 output = StringIO.StringIO() | 333 output = StringIO.StringIO() |
| 378 input = StringIO.StringIO('n\n') # say no to the warning | 334 input = StringIO.StringIO('n\n') # say no to the warning |
| 379 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 335 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 380 None)) | 336 None)) |
| 381 self.assertEqual(output.getvalue().count('??'), 2) | 337 self.assertEqual(output.getvalue().count('??'), 2) |
| 382 | 338 |
| 383 output = StringIO.StringIO() | 339 output = StringIO.StringIO() |
| 384 input = StringIO.StringIO('y\n') # say yes to the warning | 340 input = StringIO.StringIO('y\n') # say yes to the warning |
| 385 self.failUnless(presubmit.DoPresubmitChecks(ci, | 341 self.failUnless(presubmit.DoPresubmitChecks(ci, |
| 386 False, | 342 False, |
| 387 True, | 343 True, |
| 388 output, | 344 output, |
| 389 input, | 345 input, |
| 390 None)) | 346 None)) |
| 391 self.assertEquals(output.getvalue().count('??'), 2) | 347 self.assertEquals(output.getvalue().count('??'), 2) |
| 392 | 348 |
| 393 def testDoPresubmitChecksNoWarningPromptIfErrors(self): | 349 def testDoPresubmitChecksNoWarningPromptIfErrors(self): |
| 394 join = presubmit.os.path.join | |
| 395 description_lines = ('Hello there', | 350 description_lines = ('Hello there', |
| 396 'this is a change', | 351 'this is a change', |
| 397 'NOSUCHKEY=http://tracker/123', | 352 'NOSUCHKEY=http://tracker/123', |
| 398 'REALLYNOSUCHKEY=http://tracker/123') | 353 'REALLYNOSUCHKEY=http://tracker/123') |
| 399 files = [ | 354 files = [ |
| 400 ['A', join('haspresubmit', 'blat.cc')], | 355 ['A', 'haspresubmit\\blat.cc'], |
| 401 ] | 356 ] |
| 402 presubmit_path = join(self.fake_root_dir, 'PRESUBMIT.py') | 357 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 403 haspresubmit_path = join(self.fake_root_dir, 'haspresubmit', | 358 presubmit.os.path.isfile(path).AndReturn(True) |
| 404 'PRESUBMIT.py') | 359 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(True) |
| 405 presubmit.os.path.isfile(presubmit_path).AndReturn(True) | 360 presubmit.gcl.ReadFile(path, 'rU').AndReturn(self.presubmit_text) |
| 406 presubmit.os.path.isfile(haspresubmit_path).AndReturn(True) | 361 presubmit.gcl.ReadFile('PRESUBMIT.py', 'rU').AndReturn(self.presubmit_text) |
| 407 presubmit.gcl.ReadFile(presubmit_path, 'rU').AndReturn(self.presubmit_text) | |
| 408 presubmit.gcl.ReadFile(haspresubmit_path, 'rU' | |
| 409 ).AndReturn(self.presubmit_text) | |
| 410 self.mox.ReplayAll() | 362 self.mox.ReplayAll() |
| 411 | 363 |
| 412 ci = presubmit.gcl.ChangeInfo(name='mychange', | 364 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 413 description='\n'.join(description_lines), | 365 description='\n'.join(description_lines), |
| 414 files=files) | 366 files=files) |
| 367 |
| 415 output = StringIO.StringIO() | 368 output = StringIO.StringIO() |
| 416 input = StringIO.StringIO() # should be unused | 369 input = StringIO.StringIO() # should be unused |
| 370 |
| 417 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, | 371 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, |
| 418 None)) | 372 None)) |
| 419 self.assertEqual(output.getvalue().count('??'), 2) | 373 self.assertEqual(output.getvalue().count('??'), 2) |
| 420 self.assertEqual(output.getvalue().count('XX!!XX'), 2) | 374 self.assertEqual(output.getvalue().count('XX!!XX'), 2) |
| 421 self.assertEqual(output.getvalue().count('(y/N)'), 0) | 375 self.assertEqual(output.getvalue().count('(y/N)'), 0) |
| 422 | 376 |
| 423 def testDoDefaultPresubmitChecks(self): | 377 def testDoDefaultPresubmitChecks(self): |
| 424 join = presubmit.os.path.join | |
| 425 description_lines = ('Hello there', | 378 description_lines = ('Hello there', |
| 426 'this is a change', | 379 'this is a change', |
| 427 'STORY=http://tracker/123') | 380 'STORY=http://tracker/123') |
| 428 files = [ | 381 files = [ |
| 429 ['A', join('haspresubmit', 'blat.cc')], | 382 ['A', 'haspresubmit\\blat.cc'], |
| 430 ] | 383 ] |
| 431 DEFAULT_SCRIPT = """ | 384 DEFAULT_SCRIPT = """ |
| 432 def CheckChangeOnUpload(input_api, output_api): | 385 def CheckChangeOnUpload(input_api, output_api): |
| 433 return [output_api.PresubmitError("!!")] | 386 return [output_api.PresubmitError("!!")] |
| 434 def CheckChangeOnCommit(input_api, output_api): | 387 def CheckChangeOnCommit(input_api, output_api): |
| 435 raise Exception("Test error") | 388 raise Exception("Test error") |
| 436 """ | 389 """ |
| 437 presubmit.os.path.isfile(join(self.fake_root_dir, 'PRESUBMIT.py') | 390 path = presubmit.os.path.join('haspresubmit', 'PRESUBMIT.py') |
| 438 ).AndReturn(False) | 391 presubmit.os.path.isfile(path).AndReturn(False) |
| 439 presubmit.os.path.isfile(join(self.fake_root_dir, | 392 presubmit.os.path.isfile('PRESUBMIT.py').AndReturn(False) |
| 440 'haspresubmit', | |
| 441 'PRESUBMIT.py')).AndReturn(False) | |
| 442 self.mox.ReplayAll() | 393 self.mox.ReplayAll() |
| 443 | 394 |
| 444 ci = presubmit.gcl.ChangeInfo(name='mychange', | 395 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 445 description='\n'.join(description_lines), | 396 description='\n'.join(description_lines), |
| 446 files=files) | 397 files=files) |
| 447 | 398 |
| 448 | 399 |
| 449 output = StringIO.StringIO() | 400 output = StringIO.StringIO() |
| 450 input = StringIO.StringIO('y\n') | 401 input = StringIO.StringIO('y\n') |
| 451 # Always fail. | 402 # Always fail. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 input_api.change.DescriptionText())] | 441 input_api.change.DescriptionText())] |
| 491 if (input_api.change.FullDescriptionText() != | 442 if (input_api.change.FullDescriptionText() != |
| 492 'Blah Blah\\n\\nSTORY=http://tracker.com/42\\nBUG=boo\\n'): | 443 'Blah Blah\\n\\nSTORY=http://tracker.com/42\\nBUG=boo\\n'): |
| 493 return [output_api.PresubmitError('Tag parsing failed. 5 ' + | 444 return [output_api.PresubmitError('Tag parsing failed. 5 ' + |
| 494 input_api.change.FullDescriptionText())] | 445 input_api.change.FullDescriptionText())] |
| 495 return [output_api.PresubmitNotifyResult(input_api.change.tags['STORY'])] | 446 return [output_api.PresubmitNotifyResult(input_api.change.tags['STORY'])] |
| 496 def CheckChangeOnCommit(input_api, output_api): | 447 def CheckChangeOnCommit(input_api, output_api): |
| 497 raise Exception("Test error") | 448 raise Exception("Test error") |
| 498 """ | 449 """ |
| 499 self.mox.ReplayAll() | 450 self.mox.ReplayAll() |
| 500 | |
| 501 change = presubmit.gcl.ChangeInfo( | 451 change = presubmit.gcl.ChangeInfo( |
| 502 name='foo', | 452 name='foo', |
| 503 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") |
| 504 output = StringIO.StringIO() | 454 output = StringIO.StringIO() |
| 505 input = StringIO.StringIO('y\n') | 455 input = StringIO.StringIO('y\n') |
| 506 self.failUnless(presubmit.DoPresubmitChecks(change, False, True, output, | 456 self.failUnless(presubmit.DoPresubmitChecks(change, False, True, output, |
| 507 input, DEFAULT_SCRIPT)) | 457 input, DEFAULT_SCRIPT)) |
| 508 self.assertEquals(output.getvalue(), | 458 self.assertEquals(output.getvalue(), |
| 509 ('Warning, no presubmit.py found.\n' | 459 ('Warning, no presubmit.py found.\n' |
| 510 'Running default presubmit script.\n\n' | 460 'Running default presubmit script.\n\n' |
| 511 '** Presubmit Messages **\n\n' | 461 '** Presubmit Messages **\n\n' |
| 512 'http://tracker.com/42\n\n')) | 462 'http://tracker.com/42\n\n')) |
| 513 | 463 |
| 514 | 464 |
| 515 class InputApiUnittest(PresubmitTestsBase): | 465 class InputApiUnittest(PresubmitTestsBase): |
| 516 """Tests presubmit.InputApi.""" | 466 """Tests presubmit.InputApi.""" |
| 517 def testMembersChanged(self): | 467 def testMembersChanged(self): |
| 518 self.mox.ReplayAll() | |
| 519 members = [ | 468 members = [ |
| 520 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', | 469 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', |
| 521 'DepotToLocalPath', 'LocalPaths', 'LocalToDepotPath', | 470 'DepotToLocalPath', 'LocalPaths', 'LocalToDepotPath', |
| 522 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', | 471 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', |
| 523 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', | 472 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', |
| 524 'marshal', 'os_path', 'pickle', 'platform', | 473 'marshal', 'os_path', 'pickle', 'platform', |
| 525 're', 'subprocess', 'tempfile', 'urllib2', 'version', | 474 're', 'subprocess', 'tempfile', 'urllib2', 'version', |
| 526 ] | 475 ] |
| 527 # If this test fails, you should add the relevant test. | 476 # If this test fails, you should add the relevant test. |
| 528 self.compareMembers(presubmit.InputApi(None, './.'), members) | 477 self.compareMembers(presubmit.InputApi(None, './.'), members) |
| 529 | 478 |
| 530 def testDepotToLocalPath(self): | 479 def testDepotToLocalPath(self): |
| 531 presubmit.gclient.CaptureSVNInfo('svn://foo/smurf').AndReturn( | 480 presubmit.gclient.CaptureSVNInfo('svn://foo/smurf').AndReturn( |
| 532 {'Path': 'prout'}) | 481 {'Path': 'prout'}) |
| 533 presubmit.gclient.CaptureSVNInfo('svn:/foo/notfound/burp').AndReturn({}) | 482 presubmit.gclient.CaptureSVNInfo('svn:/foo/notfound/burp').AndReturn({}) |
| 534 self.mox.ReplayAll() | 483 self.mox.ReplayAll() |
| 535 | |
| 536 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn://foo/smurf') | 484 path = presubmit.InputApi(None, './p').DepotToLocalPath('svn://foo/smurf') |
| 537 self.failUnless(path == 'prout') | 485 self.failUnless(path == 'prout') |
| 538 path = presubmit.InputApi(None, './p').DepotToLocalPath( | 486 path = presubmit.InputApi(None, './p').DepotToLocalPath( |
| 539 'svn:/foo/notfound/burp') | 487 'svn:/foo/notfound/burp') |
| 540 self.failUnless(path == None) | 488 self.failUnless(path == None) |
| 541 | 489 |
| 542 def testLocalToDepotPath(self): | 490 def testLocalToDepotPath(self): |
| 543 presubmit.gclient.CaptureSVNInfo('smurf').AndReturn({'URL': 'svn://foo'}) | 491 presubmit.gclient.CaptureSVNInfo('smurf').AndReturn({'URL': 'svn://foo'}) |
| 544 presubmit.gclient.CaptureSVNInfo('notfound-food').AndReturn({}) | 492 presubmit.gclient.CaptureSVNInfo('notfound-food').AndReturn({}) |
| 545 self.mox.ReplayAll() | 493 self.mox.ReplayAll() |
| 546 | |
| 547 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') | 494 path = presubmit.InputApi(None, './p').LocalToDepotPath('smurf') |
| 548 self.assertEqual(path, 'svn://foo') | 495 self.assertEqual(path, 'svn://foo') |
| 549 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') | 496 path = presubmit.InputApi(None, './p').LocalToDepotPath('notfound-food') |
| 550 self.failUnless(path == None) | 497 self.failUnless(path == None) |
| 551 | 498 |
| 552 def testInputApiConstruction(self): | 499 def testInputApiConstruction(self): |
| 553 self.mox.ReplayAll() | |
| 554 # Fudge the change object, it's not used during construction anyway | 500 # Fudge the change object, it's not used during construction anyway |
| 555 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') | 501 api = presubmit.InputApi(change=42, presubmit_path='foo/path/PRESUBMIT.py') |
| 556 self.assertEquals(api.PresubmitLocalPath(), 'foo/path') | 502 self.failUnless(api.PresubmitLocalPath() == 'foo/path') |
| 557 self.assertEquals(api.change, 42) | 503 self.failUnless(api.change == 42) |
| 558 | 504 |
| 559 def testInputApiPresubmitScriptFiltering(self): | 505 def testInputApiPresubmitScriptFiltering(self): |
| 560 join = presubmit.os.path.join | |
| 561 description_lines = ('Hello there', | 506 description_lines = ('Hello there', |
| 562 'this is a change', | 507 'this is a change', |
| 563 'BUG=123', | 508 'BUG=123', |
| 564 ' STORY =http://foo/ \t', | 509 ' STORY =http://foo/ \t', |
| 565 'and some more regular text') | 510 'and some more regular text') |
| 566 files = [ | 511 files = [ |
| 567 ['A', join('foo', 'blat.cc')], | 512 ['A', presubmit.os.path.join('foo', 'blat.cc')], |
| 568 ['M', join('foo', 'blat', 'binary.dll')], | 513 ['M', presubmit.os.path.join('foo', 'blat', 'binary.dll')], |
| 569 ['D', 'foo/mat/beingdeleted.txt'], | 514 ['D', 'foo/mat/beingdeleted.txt'], |
| 570 ['M', 'flop/notfound.txt'], | 515 ['M', 'flop/notfound.txt'], |
| 571 ['A', 'boo/flap.h'], | 516 ['A', 'boo/flap.h'], |
| 572 ] | 517 ] |
| 573 | 518 |
| 574 | 519 blat = presubmit.os.path.join('foo', 'blat.cc') |
| 575 blat = join('foo', 'blat.cc') | 520 binary = presubmit.os.path.join('foo', 'blat', 'binary.dll') |
| 576 binary = join('foo', 'blat', 'binary.dll') | 521 beingdeleted = presubmit.os.path.join('foo', 'mat', 'beingdeleted.txt') |
| 577 beingdeleted = join('foo', 'mat', 'beingdeleted.txt') | 522 notfound = presubmit.os.path.join('flop', 'notfound.txt') |
| 578 notfound = join('flop', 'notfound.txt') | 523 flap = presubmit.os.path.join('boo', 'flap.h') |
| 579 flap = join('boo', 'flap.h') | |
| 580 presubmit.os.path.exists(blat).AndReturn(True) | 524 presubmit.os.path.exists(blat).AndReturn(True) |
| 581 presubmit.os.path.isdir(blat).AndReturn(False) | 525 presubmit.os.path.isdir(blat).AndReturn(False) |
| 582 presubmit.os.path.exists(binary).AndReturn(True) | 526 presubmit.os.path.exists(binary).AndReturn(True) |
| 583 presubmit.os.path.isdir(binary).AndReturn(False) | 527 presubmit.os.path.isdir(binary).AndReturn(False) |
| 584 presubmit.os.path.exists(beingdeleted).AndReturn(False) | 528 presubmit.os.path.exists(beingdeleted).AndReturn(False) |
| 585 presubmit.os.path.exists(notfound).AndReturn(False) | 529 presubmit.os.path.exists(notfound).AndReturn(False) |
| 586 presubmit.os.path.exists(flap).AndReturn(True) | 530 presubmit.os.path.exists(flap).AndReturn(True) |
| 587 presubmit.os.path.isdir(flap).AndReturn(False) | 531 presubmit.os.path.isdir(flap).AndReturn(False) |
| 588 presubmit.gclient.CaptureSVNInfo(beingdeleted).AndReturn({}) | 532 presubmit.gclient.CaptureSVNInfo(beingdeleted).AndReturn({}) |
| 589 presubmit.gclient.CaptureSVNInfo(notfound).AndReturn({}) | 533 presubmit.gclient.CaptureSVNInfo(notfound).AndReturn({}) |
| 590 presubmit.gcl.GetSVNFileProperty(blat, 'svn:mime-type').AndReturn(None) | 534 presubmit.gcl.GetSVNFileProperty(blat, 'svn:mime-type').AndReturn(None) |
| 591 presubmit.gcl.GetSVNFileProperty(binary, 'svn:mime-type').AndReturn( | 535 presubmit.gcl.GetSVNFileProperty(binary, 'svn:mime-type').AndReturn( |
| 592 'application/octet-stream') | 536 'application/octet-stream') |
| 593 presubmit.gcl.ReadFile(blat).AndReturn('whatever\ncookie') | 537 presubmit.gcl.ReadFile(blat).AndReturn('whatever\ncookie') |
| 594 self.mox.ReplayAll() | 538 self.mox.ReplayAll() |
| 595 | 539 |
| 596 ci = presubmit.gcl.ChangeInfo(name='mychange', | 540 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 597 description='\n'.join(description_lines), | 541 description='\n'.join(description_lines), |
| 598 files=files) | 542 files=files) |
| 599 change = presubmit.GclChange(ci) | 543 change = presubmit.GclChange(ci) |
| 544 |
| 600 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') | 545 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') |
| 546 |
| 601 affected_files = api.AffectedFiles() | 547 affected_files = api.AffectedFiles() |
| 602 self.assertEquals(len(affected_files), 3) | 548 self.assertEquals(len(affected_files), 3) |
| 603 self.assertEquals(affected_files[0].LocalPath(), | 549 self.assertEquals(affected_files[0].LocalPath(), |
| 604 presubmit.normpath('foo/blat.cc')) | 550 presubmit.normpath('foo/blat.cc')) |
| 605 self.assertEquals(affected_files[1].LocalPath(), | 551 self.assertEquals(affected_files[1].LocalPath(), |
| 606 presubmit.normpath('foo/blat/binary.dll')) | 552 presubmit.normpath('foo/blat/binary.dll')) |
| 607 self.assertEquals(affected_files[2].LocalPath(), | 553 self.assertEquals(affected_files[2].LocalPath(), |
| 608 presubmit.normpath('foo/mat/beingdeleted.txt')) | 554 presubmit.normpath('foo/mat/beingdeleted.txt')) |
| 555 |
| 609 rhs_lines = [] | 556 rhs_lines = [] |
| 610 for line in api.RightHandSideLines(): | 557 for line in api.RightHandSideLines(): |
| 611 rhs_lines.append(line) | 558 rhs_lines.append(line) |
| 612 self.assertEquals(len(rhs_lines), 2) | 559 self.assertEquals(len(rhs_lines), 2) |
| 613 self.assertEqual(rhs_lines[0][0].LocalPath(), | 560 self.assertEqual(rhs_lines[0][0].LocalPath(), |
| 614 presubmit.normpath('foo/blat.cc')) | 561 presubmit.normpath('foo/blat.cc')) |
| 615 | 562 |
| 616 def testGetAbsoluteLocalPath(self): | 563 def testGetAbsoluteLocalPath(self): |
| 617 join = presubmit.os.path.join | |
| 618 normpath = presubmit.normpath | |
| 619 # Regression test for bug of presubmit stuff that relies on invoking | 564 # Regression test for bug of presubmit stuff that relies on invoking |
| 620 # 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 |
| 621 # 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 |
| 622 # 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 |
| 623 # the presubmit script was asking about). | 568 # the presubmit script was asking about). |
| 624 files = [ | 569 files = [ |
| 625 ['A', 'isdir'], | 570 ['A', 'isdir'], |
| 626 ['A', join('isdir', 'blat.cc')], | 571 ['A', presubmit.os.path.join('isdir', 'blat.cc')] |
| 627 ['M', join('elsewhere', 'ouf.cc')], | |
| 628 ] | 572 ] |
| 629 self.mox.ReplayAll() | 573 ci = presubmit.gcl.ChangeInfo(name='mychange', |
| 630 | 574 description='', |
| 631 ci = presubmit.gcl.ChangeInfo(name='mychange', description='', files=files) | 575 files=files) |
| 632 # 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, |
| 633 # 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'). |
| 634 change = presubmit.GclChange(ci, self.fake_root_dir) | 578 change = presubmit.GclChange(ci, 'c:' + presubmit.os.sep + 'temp') |
| 635 affected_files = change.AffectedFiles(include_dirs=True) | 579 affected_files = change.AffectedFiles(include_dirs=True) |
| 636 # Local paths should remain the same | 580 # Local paths should remain the same |
| 637 self.assertEquals(affected_files[0].LocalPath(), normpath('isdir')) | 581 self.failUnless(affected_files[0].LocalPath() == |
| 638 self.assertEquals(affected_files[1].LocalPath(), normpath('isdir/blat.cc')) | 582 presubmit.normpath('isdir')) |
| 583 self.failUnless(affected_files[1].LocalPath() == |
| 584 presubmit.normpath('isdir/blat.cc')) |
| 639 # Absolute paths should be prefixed | 585 # Absolute paths should be prefixed |
| 640 self.assertEquals(affected_files[0].AbsoluteLocalPath(), | 586 self.failUnless(affected_files[0].AbsoluteLocalPath() == |
| 641 normpath(join(self.fake_root_dir, 'isdir'))) | 587 presubmit.normpath('c:/temp/isdir')) |
| 642 self.assertEquals(affected_files[1].AbsoluteLocalPath(), | 588 self.failUnless(affected_files[1].AbsoluteLocalPath() == |
| 643 normpath(join(self.fake_root_dir, 'isdir/blat.cc'))) | 589 presubmit.normpath('c:/temp/isdir/blat.cc')) |
| 644 | 590 |
| 645 # New helper functions need to work | 591 # New helper functions need to work |
| 646 paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) | 592 absolute_paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) |
| 647 self.assertEqual(len(paths_from_change), 3) | 593 api = presubmit.InputApi(change=change, |
| 648 presubmit_path = join(self.fake_root_dir, 'isdir', 'PRESUBMIT.py') | 594 presubmit_path='isdir/PRESUBMIT.py') |
| 649 api = presubmit.InputApi(change=change, presubmit_path=presubmit_path) | 595 absolute_paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) |
| 650 paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) | 596 for absolute_paths in [absolute_paths_from_change, |
| 651 self.assertEqual(len(paths_from_api), 2) | 597 absolute_paths_from_api]: |
| 652 for absolute_paths in [paths_from_change, paths_from_api]: | 598 self.failUnless(absolute_paths[0] == presubmit.normpath('c:/temp/isdir')) |
| 653 self.assertEqual(absolute_paths[0], | 599 self.failUnless(absolute_paths[1] == |
| 654 normpath(join(self.fake_root_dir, 'isdir'))) | 600 presubmit.normpath('c:/temp/isdir/blat.cc')) |
| 655 self.assertEqual(absolute_paths[1], | |
| 656 normpath(join(self.fake_root_dir, 'isdir', 'blat.cc'))) | |
| 657 | 601 |
| 658 def testDeprecated(self): | 602 def testDeprecated(self): |
| 659 presubmit.warnings.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), | 603 presubmit.warnings.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), |
| 660 stacklevel=2) | 604 stacklevel=2) |
| 661 self.mox.ReplayAll() | 605 self.mox.ReplayAll() |
| 662 change = presubmit.GclChange( | 606 change = presubmit.GclChange( |
| 663 presubmit.gcl.ChangeInfo(name='mychange', description='Bleh\n')) | 607 presubmit.gcl.ChangeInfo(name='mychange', description='Bleh\n')) |
| 664 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') | 608 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') |
| 665 api.AffectedTextFiles(include_deletes=False) | 609 api.AffectedTextFiles(include_deletes=False) |
| 666 | 610 |
| 667 | 611 |
| 668 class OuputApiUnittest(PresubmitTestsBase): | 612 class OuputApiUnittest(PresubmitTestsBase): |
| 669 """Tests presubmit.OutputApi.""" | 613 """Tests presubmit.OutputApi.""" |
| 670 def testMembersChanged(self): | 614 def testMembersChanged(self): |
| 671 self.mox.ReplayAll() | |
| 672 members = [ | 615 members = [ |
| 673 'MailTextResult', 'PresubmitError', 'PresubmitNotifyResult', | 616 'MailTextResult', 'PresubmitError', 'PresubmitNotifyResult', |
| 674 'PresubmitPromptWarning', 'PresubmitResult', | 617 'PresubmitPromptWarning', 'PresubmitResult', |
| 675 ] | 618 ] |
| 676 # If this test fails, you should add the relevant test. | 619 # If this test fails, you should add the relevant test. |
| 677 self.compareMembers(presubmit.OutputApi(), members) | 620 self.compareMembers(presubmit.OutputApi(), members) |
| 678 | 621 |
| 679 def testOutputApiBasics(self): | 622 def testOutputApiBasics(self): |
| 680 self.mox.ReplayAll() | |
| 681 self.failUnless(presubmit.OutputApi.PresubmitError('').IsFatal()) | 623 self.failUnless(presubmit.OutputApi.PresubmitError('').IsFatal()) |
| 682 self.failIf(presubmit.OutputApi.PresubmitError('').ShouldPrompt()) | 624 self.failIf(presubmit.OutputApi.PresubmitError('').ShouldPrompt()) |
| 683 | 625 |
| 684 self.failIf(presubmit.OutputApi.PresubmitPromptWarning('').IsFatal()) | 626 self.failIf(presubmit.OutputApi.PresubmitPromptWarning('').IsFatal()) |
| 685 self.failUnless( | 627 self.failUnless( |
| 686 presubmit.OutputApi.PresubmitPromptWarning('').ShouldPrompt()) | 628 presubmit.OutputApi.PresubmitPromptWarning('').ShouldPrompt()) |
| 687 | 629 |
| 688 self.failIf(presubmit.OutputApi.PresubmitNotifyResult('').IsFatal()) | 630 self.failIf(presubmit.OutputApi.PresubmitNotifyResult('').IsFatal()) |
| 689 self.failIf(presubmit.OutputApi.PresubmitNotifyResult('').ShouldPrompt()) | 631 self.failIf(presubmit.OutputApi.PresubmitNotifyResult('').ShouldPrompt()) |
| 690 | 632 |
| 691 # TODO(joi) Test MailTextResult once implemented. | 633 # TODO(joi) Test MailTextResult once implemented. |
| 692 | 634 |
| 693 def testOutputApiHandling(self): | 635 def testOutputApiHandling(self): |
| 694 self.mox.ReplayAll() | |
| 695 output = StringIO.StringIO() | 636 output = StringIO.StringIO() |
| 696 unused_input = StringIO.StringIO() | 637 unused_input = StringIO.StringIO() |
| 697 error = presubmit.OutputApi.PresubmitError('!!!') | 638 error = presubmit.OutputApi.PresubmitError('!!!') |
| 698 self.failIf(error._Handle(output, unused_input)) | 639 self.failIf(error._Handle(output, unused_input)) |
| 699 self.failUnless(output.getvalue().count('!!!')) | 640 self.failUnless(output.getvalue().count('!!!')) |
| 700 | 641 |
| 701 output = StringIO.StringIO() | 642 output = StringIO.StringIO() |
| 702 notify = presubmit.OutputApi.PresubmitNotifyResult('?see?') | 643 notify = presubmit.OutputApi.PresubmitNotifyResult('?see?') |
| 703 self.failUnless(notify._Handle(output, unused_input)) | 644 self.failUnless(notify._Handle(output, unused_input)) |
| 704 self.failUnless(output.getvalue().count('?see?')) | 645 self.failUnless(output.getvalue().count('?see?')) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 717 | 658 |
| 718 output = StringIO.StringIO() | 659 output = StringIO.StringIO() |
| 719 input = StringIO.StringIO('\n') | 660 input = StringIO.StringIO('\n') |
| 720 warning = presubmit.OutputApi.PresubmitPromptWarning('???') | 661 warning = presubmit.OutputApi.PresubmitPromptWarning('???') |
| 721 self.failIf(warning._Handle(output, input)) | 662 self.failIf(warning._Handle(output, input)) |
| 722 self.failUnless(output.getvalue().count('???')) | 663 self.failUnless(output.getvalue().count('???')) |
| 723 | 664 |
| 724 | 665 |
| 725 class AffectedFileUnittest(PresubmitTestsBase): | 666 class AffectedFileUnittest(PresubmitTestsBase): |
| 726 def testMembersChanged(self): | 667 def testMembersChanged(self): |
| 727 self.mox.ReplayAll() | |
| 728 members = [ | 668 members = [ |
| 729 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', 'LocalPath', | 669 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', 'LocalPath', |
| 730 'NewContents', 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', | 670 'NewContents', 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', |
| 731 ] | 671 ] |
| 732 # If this test fails, you should add the relevant test. | 672 # If this test fails, you should add the relevant test. |
| 733 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) | 673 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) |
| 734 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) | 674 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) |
| 735 | 675 |
| 736 def testAffectedFile(self): | 676 def testAffectedFile(self): |
| 737 path = presubmit.os.path.join('foo', 'blat.cc') | 677 path = presubmit.os.path.join('foo', 'blat.cc') |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 self.lines = lines | 756 self.lines = lines |
| 817 self.basename = lambda x: x | 757 self.basename = lambda x: x |
| 818 self.urllib2 = self.MockUrllib2() | 758 self.urllib2 = self.MockUrllib2() |
| 819 self.re = presubmit.re | 759 self.re = presubmit.re |
| 820 | 760 |
| 821 def RightHandSideLines(self): | 761 def RightHandSideLines(self): |
| 822 for line in self.lines: | 762 for line in self.lines: |
| 823 yield (presubmit.AffectedFile('bingo', 'M'), 1, line) | 763 yield (presubmit.AffectedFile('bingo', 'M'), 1, line) |
| 824 | 764 |
| 825 def testMembersChanged(self): | 765 def testMembersChanged(self): |
| 826 self.mox.ReplayAll() | |
| 827 members = [ | 766 members = [ |
| 828 'CheckChangeHasBugField', 'CheckChangeHasNoTabs', | 767 'CheckChangeHasBugField', 'CheckChangeHasNoTabs', |
| 829 'CheckChangeHasQaField', 'CheckChangeHasTestedField', | 768 'CheckChangeHasQaField', 'CheckChangeHasTestedField', |
| 830 'CheckChangeHasTestField', 'CheckDoNotSubmit', | 769 'CheckChangeHasTestField', 'CheckDoNotSubmit', |
| 831 'CheckDoNotSubmitInDescription', 'CheckDoNotSubmitInFiles', | 770 'CheckDoNotSubmitInDescription', 'CheckDoNotSubmitInFiles', |
| 832 'CheckLongLines', 'CheckTreeIsOpen', 'RunPythonUnitTests', | 771 'CheckLongLines', 'CheckTreeIsOpen', 'RunPythonUnitTests', |
| 833 ] | 772 ] |
| 834 # If this test fails, you should add the relevant test. | 773 # If this test fails, you should add the relevant test. |
| 835 self.compareMembers(presubmit_canned_checks, members) | 774 self.compareMembers(presubmit_canned_checks, members) |
| 836 | 775 |
| 837 def testCannedCheckChangeHasBugField(self): | 776 def testCannedCheckChangeHasBugField(self): |
| 838 self.mox.ReplayAll() | |
| 839 change = self.MakeBasicChange('foo', | 777 change = self.MakeBasicChange('foo', |
| 840 'Foo\nBUG=1234') | 778 'Foo\nBUG=1234') |
| 841 api = presubmit.InputApi(change, './PRESUBMIT.py') | 779 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 842 self.failIf(presubmit_canned_checks.CheckChangeHasBugField( | 780 self.failIf(presubmit_canned_checks.CheckChangeHasBugField( |
| 843 api, presubmit.OutputApi)) | 781 api, presubmit.OutputApi)) |
| 844 | 782 |
| 845 change = self.MakeBasicChange('foo', | 783 change = self.MakeBasicChange('foo', |
| 846 'Foo\nNEVERTESTED=did some stuff') | 784 'Foo\nNEVERTESTED=did some stuff') |
| 847 api = presubmit.InputApi(change, './PRESUBMIT.py') | 785 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 848 self.failUnless(presubmit_canned_checks.CheckChangeHasBugField( | 786 self.failUnless(presubmit_canned_checks.CheckChangeHasBugField( |
| 849 api, presubmit.OutputApi)) | 787 api, presubmit.OutputApi)) |
| 850 | 788 |
| 851 def testCannedCheckChangeHasTestField(self): | 789 def testCannedCheckChangeHasTestField(self): |
| 852 self.mox.ReplayAll() | |
| 853 change = self.MakeBasicChange('foo', | 790 change = self.MakeBasicChange('foo', |
| 854 'Foo\nTEST=did some stuff') | 791 'Foo\nTEST=did some stuff') |
| 855 api = presubmit.InputApi(change, './PRESUBMIT.py') | 792 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 856 self.failIf(presubmit_canned_checks.CheckChangeHasTestField( | 793 self.failIf(presubmit_canned_checks.CheckChangeHasTestField( |
| 857 api, presubmit.OutputApi)) | 794 api, presubmit.OutputApi)) |
| 858 | 795 |
| 859 change = self.MakeBasicChange('foo', | 796 change = self.MakeBasicChange('foo', |
| 860 'Foo\nNOTEST=did some stuff') | 797 'Foo\nNOTEST=did some stuff') |
| 861 api = presubmit.InputApi(change, './PRESUBMIT.py') | 798 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 862 self.failUnless(presubmit_canned_checks.CheckChangeHasTestField( | 799 self.failUnless(presubmit_canned_checks.CheckChangeHasTestField( |
| 863 api, presubmit.OutputApi)) | 800 api, presubmit.OutputApi)) |
| 864 | 801 |
| 865 def testCannedCheckChangeHasTestedField(self): | 802 def testCannedCheckChangeHasTestedField(self): |
| 866 self.mox.ReplayAll() | |
| 867 change = self.MakeBasicChange('foo', | 803 change = self.MakeBasicChange('foo', |
| 868 'Foo\nTESTED=did some stuff') | 804 'Foo\nTESTED=did some stuff') |
| 869 api = presubmit.InputApi(change, './PRESUBMIT.py') | 805 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 870 self.failIf(presubmit_canned_checks.CheckChangeHasTestedField( | 806 self.failIf(presubmit_canned_checks.CheckChangeHasTestedField( |
| 871 api, presubmit.OutputApi)) | 807 api, presubmit.OutputApi)) |
| 872 | 808 |
| 873 change = self.MakeBasicChange('foo', | 809 change = self.MakeBasicChange('foo', |
| 874 'Foo\nNEVERTESTED=did some stuff') | 810 'Foo\nNEVERTESTED=did some stuff') |
| 875 api = presubmit.InputApi(change, './PRESUBMIT.py') | 811 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 876 self.failUnless(presubmit_canned_checks.CheckChangeHasTestedField( | 812 self.failUnless(presubmit_canned_checks.CheckChangeHasTestedField( |
| 877 api, presubmit.OutputApi)) | 813 api, presubmit.OutputApi)) |
| 878 | 814 |
| 879 def testCannedCheckChangeHasQAField(self): | 815 def testCannedCheckChangeHasQAField(self): |
| 880 self.mox.ReplayAll() | |
| 881 change = self.MakeBasicChange('foo', | 816 change = self.MakeBasicChange('foo', |
| 882 'Foo\nQA=test floop feature very well') | 817 'Foo\nQA=test floop feature very well') |
| 883 api = presubmit.InputApi(change, './PRESUBMIT.py') | 818 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 884 self.failIf(presubmit_canned_checks.CheckChangeHasQaField( | 819 self.failIf(presubmit_canned_checks.CheckChangeHasQaField( |
| 885 api, presubmit.OutputApi)) | 820 api, presubmit.OutputApi)) |
| 886 | 821 |
| 887 change = self.MakeBasicChange('foo', | 822 change = self.MakeBasicChange('foo', |
| 888 'Foo\nNOTFORQA=test floop feature very well') | 823 'Foo\nNOTFORQA=test floop feature very well') |
| 889 api = presubmit.InputApi(change, './PRESUBMIT.py') | 824 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 890 self.failUnless(presubmit_canned_checks.CheckChangeHasQaField( | 825 self.failUnless(presubmit_canned_checks.CheckChangeHasQaField( |
| 891 api, presubmit.OutputApi)) | 826 api, presubmit.OutputApi)) |
| 892 | 827 |
| 893 def testCannedCheckDoNotSubmitInDescription(self): | 828 def testCannedCheckDoNotSubmitInDescription(self): |
| 894 self.mox.ReplayAll() | |
| 895 change = self.MakeBasicChange('foo', 'hello') | 829 change = self.MakeBasicChange('foo', 'hello') |
| 896 api = presubmit.InputApi(change, './PRESUBMIT.py') | 830 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 897 self.failIf(presubmit_canned_checks.CheckDoNotSubmitInDescription( | 831 self.failIf(presubmit_canned_checks.CheckDoNotSubmitInDescription( |
| 898 api, presubmit.OutputApi)) | 832 api, presubmit.OutputApi)) |
| 899 | 833 |
| 900 change = self.MakeBasicChange('foo', | 834 change = self.MakeBasicChange('foo', |
| 901 'DO NOT ' + 'SUBMIT') | 835 'DO NOT ' + 'SUBMIT') |
| 902 api = presubmit.InputApi(change, './PRESUBMIT.py') | 836 api = presubmit.InputApi(change, './PRESUBMIT.py') |
| 903 self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInDescription( | 837 self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInDescription( |
| 904 api, presubmit.OutputApi)) | 838 api, presubmit.OutputApi)) |
| 905 | 839 |
| 906 def testCannedCheckDoNotSubmitInFiles(self): | 840 def testCannedCheckDoNotSubmitInFiles(self): |
| 907 self.mox.ReplayAll() | |
| 908 self.failIf(presubmit_canned_checks.CheckDoNotSubmitInFiles( | 841 self.failIf(presubmit_canned_checks.CheckDoNotSubmitInFiles( |
| 909 self.MockInputApi(['hello', 'there']), presubmit.OutputApi | 842 self.MockInputApi(['hello', 'there']), presubmit.OutputApi |
| 910 )) | 843 )) |
| 911 self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInFiles( | 844 self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInFiles( |
| 912 self.MockInputApi(['hello', 'yo, DO NOT ' + 'SUBMIT']), | 845 self.MockInputApi(['hello', 'yo, DO NOT ' + 'SUBMIT']), |
| 913 presubmit.OutputApi)) | 846 presubmit.OutputApi)) |
| 914 | 847 |
| 915 def testCannedCheckChangeHasNoTabs(self): | 848 def testCannedCheckChangeHasNoTabs(self): |
| 916 self.mox.ReplayAll() | |
| 917 self.failIf(presubmit_canned_checks.CheckChangeHasNoTabs( | 849 self.failIf(presubmit_canned_checks.CheckChangeHasNoTabs( |
| 918 self.MockInputApi(['hello', 'there']), presubmit.OutputApi | 850 self.MockInputApi(['hello', 'there']), presubmit.OutputApi |
| 919 )) | 851 )) |
| 920 self.failUnless(presubmit_canned_checks.CheckChangeHasNoTabs( | 852 self.failUnless(presubmit_canned_checks.CheckChangeHasNoTabs( |
| 921 self.MockInputApi(['hello', 'there\tit is']), presubmit.OutputApi | 853 self.MockInputApi(['hello', 'there\tit is']), presubmit.OutputApi |
| 922 )) | 854 )) |
| 923 | 855 |
| 924 def testCannedCheckLongLines(self): | 856 def testCannedCheckLongLines(self): |
| 925 self.mox.ReplayAll() | |
| 926 self.failIf(presubmit_canned_checks.CheckLongLines( | 857 self.failIf(presubmit_canned_checks.CheckLongLines( |
| 927 self.MockInputApi(['hello', 'there']), presubmit.OutputApi, 5 | 858 self.MockInputApi(['hello', 'there']), presubmit.OutputApi, 5 |
| 928 )) | 859 )) |
| 929 self.failUnless(presubmit_canned_checks.CheckLongLines( | 860 self.failUnless(presubmit_canned_checks.CheckLongLines( |
| 930 self.MockInputApi(['hello', 'there!']), presubmit.OutputApi, 5 | 861 self.MockInputApi(['hello', 'there!']), presubmit.OutputApi, 5 |
| 931 )) | 862 )) |
| 932 | 863 |
| 933 def testCannedCheckTreeIsOpen(self): | 864 def testCannedCheckTreeIsOpen(self): |
| 934 self.mox.ReplayAll() | |
| 935 self.failIf(presubmit_canned_checks.CheckTreeIsOpen( | 865 self.failIf(presubmit_canned_checks.CheckTreeIsOpen( |
| 936 self.MockInputApi(), presubmit.OutputApi, url='url_to_open', closed='0' | 866 self.MockInputApi(), presubmit.OutputApi, url='url_to_open', closed='0' |
| 937 )) | 867 )) |
| 938 self.failUnless(presubmit_canned_checks.CheckTreeIsOpen( | 868 self.failUnless(presubmit_canned_checks.CheckTreeIsOpen( |
| 939 self.MockInputApi(), presubmit.OutputApi, url='url_to_closed', closed='0' | 869 self.MockInputApi(), presubmit.OutputApi, url='url_to_closed', closed='0' |
| 940 )) | 870 )) |
| 941 | 871 |
| 942 def RunPythonUnitTests(self): | 872 def RunPythonUnitTests(self): |
| 943 self.mox.ReplayAll() | |
| 944 # TODO(maruel): Add real tests. | 873 # TODO(maruel): Add real tests. |
| 945 self.failIf(presubmit_canned_checks.RunPythonUnitTests( | 874 self.failIf(presubmit_canned_checks.RunPythonUnitTests( |
| 946 self.MockInputApi(), | 875 self.MockInputApi(), |
| 947 presubmit.OutputApi, [])) | 876 presubmit.OutputApi, [])) |
| 948 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( | 877 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( |
| 949 self.MockInputApi(), | 878 self.MockInputApi(), |
| 950 presubmit.OutputApi, ['non_existent_module'])) | 879 presubmit.OutputApi, ['non_existent_module'])) |
| 951 | 880 |
| 952 if __name__ == '__main__': | 881 if __name__ == '__main__': |
| 953 unittest.main() | 882 unittest.main() |
| OLD | NEW |