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 |