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