OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 # pylint: disable=E1101,E1103 | 8 # pylint: disable=E1101,E1103 |
9 | 9 |
10 import StringIO | 10 import StringIO |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 else: | 61 else: |
62 return %s | 62 return %s |
63 """ | 63 """ |
64 | 64 |
65 presubmit_trymaster = """ | 65 presubmit_trymaster = """ |
66 def GetPreferredTryMasters(project, change): | 66 def GetPreferredTryMasters(project, change): |
67 return %s | 67 return %s |
68 """ | 68 """ |
69 | 69 |
70 presubmit_diffs = """ | 70 presubmit_diffs = """ |
71 --- file1 2011-02-09 10:38:16.517224845 -0800 | 71 diff --git %(filename)s %(filename)s |
72 +++ file2 2011-02-09 10:38:53.177226516 -0800 | 72 index fe3de7b..54ae6e1 100755 |
| 73 --- %(filename)s 2011-02-09 10:38:16.517224845 -0800 |
| 74 +++ %(filename)s 2011-02-09 10:38:53.177226516 -0800 |
73 @@ -1,6 +1,5 @@ | 75 @@ -1,6 +1,5 @@ |
74 this is line number 0 | 76 this is line number 0 |
75 this is line number 1 | 77 this is line number 1 |
76 -this is line number 2 to be deleted | 78 -this is line number 2 to be deleted |
77 this is line number 3 | 79 this is line number 3 |
78 this is line number 4 | 80 this is line number 4 |
79 this is line number 5 | 81 this is line number 5 |
80 @@ -8,7 +7,7 @@ | 82 @@ -8,7 +7,7 @@ |
81 this is line number 7 | 83 this is line number 7 |
82 this is line number 8 | 84 this is line number 8 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 # Special mocks. | 145 # Special mocks. |
144 def MockAbsPath(f): | 146 def MockAbsPath(f): |
145 return f | 147 return f |
146 def MockChdir(f): | 148 def MockChdir(f): |
147 return None | 149 return None |
148 # SuperMoxTestBase already mock these but simplify our life. | 150 # SuperMoxTestBase already mock these but simplify our life. |
149 presubmit.os.path.abspath = MockAbsPath | 151 presubmit.os.path.abspath = MockAbsPath |
150 presubmit.os.getcwd = self.RootDir | 152 presubmit.os.getcwd = self.RootDir |
151 presubmit.os.chdir = MockChdir | 153 presubmit.os.chdir = MockChdir |
152 self.mox.StubOutWithMock(presubmit.scm, 'determine_scm') | 154 self.mox.StubOutWithMock(presubmit.scm, 'determine_scm') |
153 self.mox.StubOutWithMock(presubmit.scm.SVN, '_CaptureInfo') | |
154 self.mox.StubOutWithMock(presubmit.scm.SVN, 'GetFileProperty') | |
155 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileRead') | 155 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileRead') |
156 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileWrite') | 156 self.mox.StubOutWithMock(presubmit.gclient_utils, 'FileWrite') |
157 self.mox.StubOutWithMock(presubmit.scm.SVN, 'GenerateDiff') | |
158 self.mox.StubOutWithMock(presubmit.scm.GIT, 'GenerateDiff') | 157 self.mox.StubOutWithMock(presubmit.scm.GIT, 'GenerateDiff') |
159 | 158 |
160 # On some platforms this does all sorts of undesirable system calls, so | 159 # On some platforms this does all sorts of undesirable system calls, so |
161 # just permanently mock it with a lambda that returns 2 | 160 # just permanently mock it with a lambda that returns 2 |
162 multiprocessing.cpu_count = lambda: 2 | 161 multiprocessing.cpu_count = lambda: 2 |
163 | 162 |
164 | 163 |
165 class PresubmitUnittest(PresubmitTestsBase): | 164 class PresubmitUnittest(PresubmitTestsBase): |
166 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" | 165 """General presubmit_support.py tests (excluding InputApi and OutputApi).""" |
167 | 166 |
168 _INHERIT_SETTINGS = 'inherit-review-settings-ok' | 167 _INHERIT_SETTINGS = 'inherit-review-settings-ok' |
169 | 168 |
170 def testMembersChanged(self): | 169 def testMembersChanged(self): |
171 self.mox.ReplayAll() | 170 self.mox.ReplayAll() |
172 members = [ | 171 members = [ |
173 'AffectedFile', 'Change', 'DoGetTrySlaves', | 172 'AffectedFile', 'Change', 'DoGetTrySlaves', |
174 'DoPostUploadExecuter', 'DoPresubmitChecks', 'GetPostUploadExecuter', | 173 'DoPostUploadExecuter', 'DoPresubmitChecks', 'GetPostUploadExecuter', |
175 'GetTrySlavesExecuter', 'GitAffectedFile', 'CallCommand', 'CommandData', | 174 'GetTrySlavesExecuter', 'GitAffectedFile', 'CallCommand', 'CommandData', |
176 'GitChange', 'InputApi', 'ListRelevantPresubmitFiles', 'main', | 175 'GitChange', 'InputApi', 'ListRelevantPresubmitFiles', 'main', |
177 'NonexistantCannedCheckFilter', 'OutputApi', 'ParseFiles', | 176 'NonexistantCannedCheckFilter', 'OutputApi', 'ParseFiles', |
178 'PresubmitFailure', 'PresubmitExecuter', 'PresubmitOutput', 'ScanSubDirs', | 177 'PresubmitFailure', 'PresubmitExecuter', 'PresubmitOutput', 'ScanSubDirs', |
179 'SvnAffectedFile', 'SvnChange', 'auth', 'cPickle', 'cpplint', 'cStringIO', | 178 'auth', 'cPickle', 'cpplint', 'cStringIO', |
180 'contextlib', 'canned_check_filter', 'fix_encoding', 'fnmatch', | 179 'contextlib', 'canned_check_filter', 'fix_encoding', 'fnmatch', |
181 'gclient_utils', 'glob', 'inspect', 'json', 'load_files', 'logging', | 180 'gclient_utils', 'glob', 'inspect', 'json', 'load_files', 'logging', |
182 'marshal', 'normpath', 'optparse', 'os', 'owners', 'pickle', | 181 'marshal', 'normpath', 'optparse', 'os', 'owners', 'pickle', |
183 'presubmit_canned_checks', 'random', 're', 'rietveld', 'scm', | 182 'presubmit_canned_checks', 'random', 're', 'rietveld', 'scm', |
184 'subprocess', 'sys', 'tempfile', 'time', 'traceback', 'types', 'unittest', | 183 'subprocess', 'sys', 'tempfile', 'time', 'traceback', 'types', 'unittest', |
185 'urllib2', 'warn', 'multiprocessing', 'DoGetTryMasters', | 184 'urllib2', 'warn', 'multiprocessing', 'DoGetTryMasters', |
186 'GetTryMastersExecuter', 'itertools', 'urlparse', 'gerrit_util', | 185 'GetTryMastersExecuter', 'itertools', 'urlparse', 'gerrit_util', |
187 'GerritAccessor', | 186 'GerritAccessor', |
188 ] | 187 ] |
189 # If this test fails, you should add the relevant test. | 188 # If this test fails, you should add the relevant test. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 join(sys_root_dir, 'foo', 'bar', 'moo', 'PRESUBMIT.py') | 300 join(sys_root_dir, 'foo', 'bar', 'moo', 'PRESUBMIT.py') |
302 ]) | 301 ]) |
303 | 302 |
304 def testTagLineRe(self): | 303 def testTagLineRe(self): |
305 self.mox.ReplayAll() | 304 self.mox.ReplayAll() |
306 m = presubmit.Change.TAG_LINE_RE.match(' BUG =1223, 1445 \t') | 305 m = presubmit.Change.TAG_LINE_RE.match(' BUG =1223, 1445 \t') |
307 self.failUnless(m) | 306 self.failUnless(m) |
308 self.failUnlessEqual(m.group('key'), 'BUG') | 307 self.failUnlessEqual(m.group('key'), 'BUG') |
309 self.failUnlessEqual(m.group('value'), '1223, 1445') | 308 self.failUnlessEqual(m.group('value'), '1223, 1445') |
310 | 309 |
311 def testGclChange(self): | |
312 description_lines = ('Hello there', | |
313 'this is a change', | |
314 'BUG=123', | |
315 ' STORY =http://foo/ \t', | |
316 'and some more regular text \t') | |
317 files = [ | |
318 ['A', 'foo/blat.cc'], | |
319 ['M', 'binary.dll'], # a binary file | |
320 ['A', 'isdir'], # a directory | |
321 ['?', 'flop/notfound.txt'], # not found in SVN, still exists locally | |
322 ['D', 'boo/flap.h'], | |
323 ] | |
324 blat = presubmit.os.path.join('foo', 'blat.cc') | |
325 notfound = presubmit.os.path.join('flop', 'notfound.txt') | |
326 flap = presubmit.os.path.join('boo', 'flap.h') | |
327 binary = 'binary.dll' | |
328 isdir = 'isdir' | |
329 f_blat = presubmit.os.path.join(self.fake_root_dir, blat) | |
330 f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound) | |
331 f_flap = presubmit.os.path.join(self.fake_root_dir, flap) | |
332 f_binary = presubmit.os.path.join(self.fake_root_dir, binary) | |
333 f_isdir = presubmit.os.path.join(self.fake_root_dir, isdir) | |
334 presubmit.os.path.exists(f_blat).AndReturn(True) | |
335 presubmit.os.path.isdir(f_blat).AndReturn(False) | |
336 presubmit.os.path.exists(f_binary).AndReturn(True) | |
337 presubmit.os.path.isdir(f_binary).AndReturn(False) | |
338 presubmit.os.path.exists(f_isdir).AndReturn(True) | |
339 presubmit.os.path.isdir(f_isdir).AndReturn(True) | |
340 presubmit.os.path.exists(f_notfound).AndReturn(True) | |
341 presubmit.os.path.isdir(f_notfound).AndReturn(False) | |
342 presubmit.os.path.exists(f_flap).AndReturn(False) | |
343 presubmit.scm.SVN._CaptureInfo([flap], self.fake_root_dir | |
344 ).AndReturn({'Node Kind': 'file'}) | |
345 presubmit.scm.SVN.GetFileProperty( | |
346 blat, 'svn:mime-type', self.fake_root_dir).AndReturn(None) | |
347 presubmit.scm.SVN.GetFileProperty( | |
348 binary, 'svn:mime-type', self.fake_root_dir | |
349 ).AndReturn('application/octet-stream') | |
350 presubmit.scm.SVN.GetFileProperty( | |
351 notfound, 'svn:mime-type', self.fake_root_dir).AndReturn('') | |
352 presubmit.scm.SVN._CaptureInfo([blat], self.fake_root_dir).AndReturn( | |
353 {'URL': 'svn:/foo/foo/blat.cc'}) | |
354 presubmit.scm.SVN._CaptureInfo([binary], self.fake_root_dir).AndReturn( | |
355 {'URL': 'svn:/foo/binary.dll'}) | |
356 presubmit.scm.SVN._CaptureInfo([notfound], self.fake_root_dir).AndReturn({}) | |
357 presubmit.scm.SVN._CaptureInfo([flap], self.fake_root_dir).AndReturn( | |
358 {'URL': 'svn:/foo/boo/flap.h'}) | |
359 presubmit.scm.SVN.GenerateDiff([blat], self.fake_root_dir, False, None | |
360 ).AndReturn(self.presubmit_diffs) | |
361 presubmit.scm.SVN.GenerateDiff([notfound], self.fake_root_dir, False, None | |
362 ).AndReturn(self.presubmit_diffs) | |
363 | |
364 self.mox.ReplayAll() | |
365 | |
366 change = presubmit.SvnChange( | |
367 'mychange', | |
368 '\n'.join(description_lines), | |
369 self.fake_root_dir, | |
370 files, | |
371 0, | |
372 0, | |
373 None) | |
374 self.failUnless(change.Name() == 'mychange') | |
375 self.failUnless(change.DescriptionText() == | |
376 'Hello there\nthis is a change\nand some more regular text') | |
377 self.failUnless(change.FullDescriptionText() == | |
378 '\n'.join(description_lines)) | |
379 | |
380 self.failUnless(change.BUG == '123') | |
381 self.failUnless(change.STORY == 'http://foo/') | |
382 self.failUnless(change.BLEH == None) | |
383 | |
384 self.failUnless(len(change.AffectedFiles()) == 4) | |
385 self.failUnless(len(change.AffectedFiles(include_dirs=True)) == 5) | |
386 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 3) | |
387 self.failUnless(len(change.AffectedFiles(include_dirs=True, | |
388 include_deletes=False)) == 4) | |
389 | |
390 affected_text_files = change.AffectedTextFiles() | |
391 self.failUnless(len(affected_text_files) == 2) | |
392 self.failIf(filter(lambda x: x.LocalPath() == 'binary.dll', | |
393 affected_text_files)) | |
394 | |
395 local_paths = change.LocalPaths() | |
396 expected_paths = [presubmit.normpath(f[1]) for f in files] | |
397 self.failUnless( | |
398 len(filter(lambda x: x in expected_paths, local_paths)) == 4) | |
399 | |
400 server_paths = change.ServerPaths() | |
401 expected_paths = ['svn:/foo/%s' % f[1] for f in files if | |
402 f[1] != 'flop/notfound.txt'] | |
403 expected_paths.append('') # one unknown file | |
404 self.assertEqual( | |
405 len(filter(lambda x: x in expected_paths, server_paths)), 4) | |
406 | |
407 files = [[x[0], presubmit.normpath(x[1])] for x in files] | |
408 | |
409 rhs_lines = [] | |
410 for line in change.RightHandSideLines(): | |
411 rhs_lines.append(line) | |
412 self.assertEquals(rhs_lines[0][0].LocalPath(), files[0][1]) | |
413 self.assertEquals(rhs_lines[0][1], 10) | |
414 self.assertEquals(rhs_lines[0][2],'this is line number 10') | |
415 | |
416 self.assertEquals(rhs_lines[3][0].LocalPath(), files[0][1]) | |
417 self.assertEquals(rhs_lines[3][1], 32) | |
418 self.assertEquals(rhs_lines[3][2], 'this is line number 32.1') | |
419 | |
420 self.assertEquals(rhs_lines[8][0].LocalPath(), files[3][1]) | |
421 self.assertEquals(rhs_lines[8][1], 23) | |
422 self.assertEquals(rhs_lines[8][2], 'this is line number 23.1') | |
423 | |
424 self.assertEquals(rhs_lines[12][0].LocalPath(), files[3][1]) | |
425 self.assertEquals(rhs_lines[12][1], 46) | |
426 self.assertEquals(rhs_lines[12][2], '') | |
427 | |
428 self.assertEquals(rhs_lines[13][0].LocalPath(), files[3][1]) | |
429 self.assertEquals(rhs_lines[13][1], 49) | |
430 self.assertEquals(rhs_lines[13][2], 'this is line number 48.1') | |
431 | |
432 def testGitChange(self): | 310 def testGitChange(self): |
433 description_lines = ('Hello there', | 311 description_lines = ('Hello there', |
434 'this is a change', | 312 'this is a change', |
435 'BUG=123', | 313 'BUG=123', |
436 ' STORY =http://foo/ \t', | 314 ' STORY =http://foo/ \t', |
437 'and some more regular text \t') | 315 'and some more regular text \t') |
438 unified_diff = [ | 316 unified_diff = [ |
439 'diff --git binary_a.png binary_a.png', | 317 'diff --git binary_a.png binary_a.png', |
440 'new file mode 100644', | 318 'new file mode 100644', |
441 'index 0000000..6fbdd6d', | 319 'index 0000000..6fbdd6d', |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 files = [('A ', 'binary_a.png'), | 406 files = [('A ', 'binary_a.png'), |
529 ('D ', 'binary_d.png'), | 407 ('D ', 'binary_d.png'), |
530 ('M ', 'binary_m.png'), | 408 ('M ', 'binary_m.png'), |
531 ('M ', 'binary_md.png'), # Binary w/ diff | 409 ('M ', 'binary_md.png'), # Binary w/ diff |
532 ('A ', 'boo/blat.cc'), | 410 ('A ', 'boo/blat.cc'), |
533 ('D ', 'floo/delburt.cc'), | 411 ('D ', 'floo/delburt.cc'), |
534 ('M ', 'foo/TestExpectations')] | 412 ('M ', 'foo/TestExpectations')] |
535 | 413 |
536 for op, path in files: | 414 for op, path in files: |
537 full_path = presubmit.os.path.join(self.fake_root_dir, *path.split('/')) | 415 full_path = presubmit.os.path.join(self.fake_root_dir, *path.split('/')) |
538 if op.startswith('D'): | 416 if not op.startswith('D'): |
539 os.path.exists(full_path).AndReturn(False) | |
540 else: | |
541 os.path.exists(full_path).AndReturn(False) | |
542 os.path.isfile(full_path).AndReturn(True) | 417 os.path.isfile(full_path).AndReturn(True) |
543 | 418 |
544 presubmit.scm.GIT.GenerateDiff( | 419 presubmit.scm.GIT.GenerateDiff( |
545 self.fake_root_dir, files=[], full_move=True, branch=None | 420 self.fake_root_dir, files=[], full_move=True, branch=None |
546 ).AndReturn('\n'.join(unified_diff)) | 421 ).AndReturn('\n'.join(unified_diff)) |
547 | 422 |
548 self.mox.ReplayAll() | 423 self.mox.ReplayAll() |
549 | 424 |
550 change = presubmit.GitChange( | 425 change = presubmit.GitChange( |
551 'mychange', | 426 'mychange', |
552 '\n'.join(description_lines), | 427 '\n'.join(description_lines), |
553 self.fake_root_dir, | 428 self.fake_root_dir, |
554 files, | 429 files, |
555 0, | 430 0, |
556 0, | 431 0, |
557 None, | 432 None, |
558 upstream=None) | 433 upstream=None) |
559 self.failUnless(change.Name() == 'mychange') | 434 self.failUnless(change.Name() == 'mychange') |
560 self.failUnless(change.DescriptionText() == | 435 self.failUnless(change.DescriptionText() == |
561 'Hello there\nthis is a change\nand some more regular text') | 436 'Hello there\nthis is a change\nand some more regular text') |
562 self.failUnless(change.FullDescriptionText() == | 437 self.failUnless(change.FullDescriptionText() == |
563 '\n'.join(description_lines)) | 438 '\n'.join(description_lines)) |
564 | 439 |
565 self.failUnless(change.BUG == '123') | 440 self.failUnless(change.BUG == '123') |
566 self.failUnless(change.STORY == 'http://foo/') | 441 self.failUnless(change.STORY == 'http://foo/') |
567 self.failUnless(change.BLEH == None) | 442 self.failUnless(change.BLEH == None) |
568 | 443 |
569 self.failUnless(len(change.AffectedFiles()) == 7) | 444 self.failUnless(len(change.AffectedFiles()) == 7) |
570 self.failUnless(len(change.AffectedFiles(include_dirs=True)) == 7) | 445 self.failUnless(len(change.AffectedFiles()) == 7) |
571 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 5) | 446 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 5) |
572 self.failUnless(len(change.AffectedFiles(include_dirs=True, | 447 self.failUnless(len(change.AffectedFiles(include_deletes=False)) == 5) |
573 include_deletes=False)) == 5) | |
574 | 448 |
575 # Note that on git, there's no distinction between binary files and text | 449 # Note that on git, there's no distinction between binary files and text |
576 # files; everything that's not a delete is a text file. | 450 # files; everything that's not a delete is a text file. |
577 affected_text_files = change.AffectedTextFiles() | 451 affected_text_files = change.AffectedTestableFiles() |
578 self.failUnless(len(affected_text_files) == 5) | 452 self.failUnless(len(affected_text_files) == 5) |
579 | 453 |
580 local_paths = change.LocalPaths() | 454 local_paths = change.LocalPaths() |
581 expected_paths = [os.path.normpath(f) for op, f in files] | 455 expected_paths = [os.path.normpath(f) for op, f in files] |
582 self.assertEqual(local_paths, expected_paths) | 456 self.assertEqual(local_paths, expected_paths) |
583 | 457 |
584 try: | |
585 _ = change.ServerPaths() | |
586 self.fail("ServerPaths implemented.") | |
587 except NotImplementedError: | |
588 pass | |
589 | |
590 actual_rhs_lines = [] | 458 actual_rhs_lines = [] |
591 for f, linenum, line in change.RightHandSideLines(): | 459 for f, linenum, line in change.RightHandSideLines(): |
592 actual_rhs_lines.append((f.LocalPath(), linenum, line)) | 460 actual_rhs_lines.append((f.LocalPath(), linenum, line)) |
593 | 461 |
594 f_blat = os.path.normpath('boo/blat.cc') | 462 f_blat = os.path.normpath('boo/blat.cc') |
595 f_test_expectations = os.path.normpath('foo/TestExpectations') | 463 f_test_expectations = os.path.normpath('foo/TestExpectations') |
596 expected_rhs_lines = [ | 464 expected_rhs_lines = [ |
597 (f_blat, 1, 'This is some text'), | 465 (f_blat, 1, 'This is some text'), |
598 (f_blat, 2, 'which lacks a copyright warning'), | 466 (f_blat, 2, 'which lacks a copyright warning'), |
599 (f_blat, 3, 'but it is nonetheless interesting'), | 467 (f_blat, 3, 'but it is nonetheless interesting'), |
(...skipping 13 matching lines...) Expand all Loading... |
613 (f_test_expectations, 21, 'and have this not be interpreted'), | 481 (f_test_expectations, 21, 'and have this not be interpreted'), |
614 (f_test_expectations, 22, 'as the start of a new file'), | 482 (f_test_expectations, 22, 'as the start of a new file'), |
615 (f_test_expectations, 23, 'or anything messed up like that,'), | 483 (f_test_expectations, 23, 'or anything messed up like that,'), |
616 (f_test_expectations, 24, 'because you parsed the header'), | 484 (f_test_expectations, 24, 'because you parsed the header'), |
617 (f_test_expectations, 25, 'correctly.')] | 485 (f_test_expectations, 25, 'correctly.')] |
618 | 486 |
619 self.assertEquals(expected_rhs_lines, actual_rhs_lines) | 487 self.assertEquals(expected_rhs_lines, actual_rhs_lines) |
620 | 488 |
621 def testInvalidChange(self): | 489 def testInvalidChange(self): |
622 try: | 490 try: |
623 presubmit.SvnChange( | 491 presubmit.GitChange( |
624 'mychange', | 492 'mychange', |
625 'description', | 493 'description', |
626 self.fake_root_dir, | 494 self.fake_root_dir, |
627 ['foo/blat.cc', 'bar'], | 495 ['foo/blat.cc', 'bar'], |
628 0, | 496 0, |
629 0, | 497 0, |
630 None) | 498 None) |
631 self.fail() | 499 self.fail() |
632 except AssertionError: | 500 except AssertionError: |
633 pass | 501 pass |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 'Running presubmit upload checks ...\n' | 743 'Running presubmit upload checks ...\n' |
876 'Warning, no PRESUBMIT.py found.\n' | 744 'Warning, no PRESUBMIT.py found.\n' |
877 'Running default presubmit script.\n' | 745 'Running default presubmit script.\n' |
878 '\n' | 746 '\n' |
879 '** Presubmit ERRORS **\n!!\n\n' | 747 '** Presubmit ERRORS **\n!!\n\n' |
880 'Was the presubmit check useful? If not, run "git cl presubmit -v"\n' | 748 'Was the presubmit check useful? If not, run "git cl presubmit -v"\n' |
881 'to figure out which PRESUBMIT.py was run, then run git blame\n' | 749 'to figure out which PRESUBMIT.py was run, then run git blame\n' |
882 'on the file to figure out who to ask for help.\n') | 750 'on the file to figure out who to ask for help.\n') |
883 self.assertEquals(output.getvalue(), text) | 751 self.assertEquals(output.getvalue(), text) |
884 | 752 |
885 def testDirectoryHandling(self): | |
886 files = [ | |
887 ['A', 'isdir'], | |
888 ['A', presubmit.os.path.join('isdir', 'blat.cc')], | |
889 ] | |
890 isdir = presubmit.os.path.join(self.fake_root_dir, 'isdir') | |
891 blat = presubmit.os.path.join(isdir, 'blat.cc') | |
892 presubmit.os.path.exists(isdir).AndReturn(True) | |
893 presubmit.os.path.isdir(isdir).AndReturn(True) | |
894 presubmit.os.path.exists(blat).AndReturn(True) | |
895 presubmit.os.path.isdir(blat).AndReturn(False) | |
896 self.mox.ReplayAll() | |
897 | |
898 change = presubmit.Change( | |
899 'mychange', 'foo', self.fake_root_dir, files, 0, 0, None) | |
900 affected_files = change.AffectedFiles(include_dirs=False) | |
901 self.failUnless(len(affected_files) == 1) | |
902 self.failUnless(affected_files[0].LocalPath().endswith('blat.cc')) | |
903 affected_files_and_dirs = change.AffectedFiles(include_dirs=True) | |
904 self.failUnless(len(affected_files_and_dirs) == 2) | |
905 | |
906 def testTags(self): | 753 def testTags(self): |
907 DEFAULT_SCRIPT = """ | 754 DEFAULT_SCRIPT = """ |
908 def CheckChangeOnUpload(input_api, output_api): | 755 def CheckChangeOnUpload(input_api, output_api): |
909 if input_api.change.tags['BUG'] != 'boo': | 756 if input_api.change.tags['BUG'] != 'boo': |
910 return [output_api.PresubmitError('Tag parsing failed. 1')] | 757 return [output_api.PresubmitError('Tag parsing failed. 1')] |
911 if input_api.change.tags['STORY'] != 'http://tracker.com/42': | 758 if input_api.change.tags['STORY'] != 'http://tracker.com/42': |
912 return [output_api.PresubmitError('Tag parsing failed. 2')] | 759 return [output_api.PresubmitError('Tag parsing failed. 2')] |
913 if input_api.change.BUG != 'boo': | 760 if input_api.change.BUG != 'boo': |
914 return [output_api.PresubmitError('Tag parsing failed. 6')] | 761 return [output_api.PresubmitError('Tag parsing failed. 6')] |
915 if input_api.change.STORY != 'http://tracker.com/42': | 762 if input_api.change.STORY != 'http://tracker.com/42': |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 | 1080 |
1234 | 1081 |
1235 class InputApiUnittest(PresubmitTestsBase): | 1082 class InputApiUnittest(PresubmitTestsBase): |
1236 """Tests presubmit.InputApi.""" | 1083 """Tests presubmit.InputApi.""" |
1237 def testMembersChanged(self): | 1084 def testMembersChanged(self): |
1238 self.mox.ReplayAll() | 1085 self.mox.ReplayAll() |
1239 members = [ | 1086 members = [ |
1240 'AbsoluteLocalPaths', | 1087 'AbsoluteLocalPaths', |
1241 'AffectedFiles', | 1088 'AffectedFiles', |
1242 'AffectedSourceFiles', | 1089 'AffectedSourceFiles', |
| 1090 'AffectedTestableFiles', |
1243 'AffectedTextFiles', | 1091 'AffectedTextFiles', |
1244 'DEFAULT_BLACK_LIST', | 1092 'DEFAULT_BLACK_LIST', |
1245 'DEFAULT_WHITE_LIST', | 1093 'DEFAULT_WHITE_LIST', |
1246 'DepotToLocalPath', | |
1247 'FilterSourceFile', | 1094 'FilterSourceFile', |
1248 'LocalPaths', | 1095 'LocalPaths', |
1249 'LocalToDepotPath', | |
1250 'Command', | 1096 'Command', |
1251 'RunTests', | 1097 'RunTests', |
1252 'PresubmitLocalPath', | 1098 'PresubmitLocalPath', |
1253 'ReadFile', | 1099 'ReadFile', |
1254 'RightHandSideLines', | 1100 'RightHandSideLines', |
1255 'ServerPaths', | |
1256 'ShutdownPool', | 1101 'ShutdownPool', |
1257 'basename', | 1102 'basename', |
1258 'cPickle', | 1103 'cPickle', |
1259 'cpplint', | 1104 'cpplint', |
1260 'cStringIO', | 1105 'cStringIO', |
1261 'canned_checks', | 1106 'canned_checks', |
1262 'change', | 1107 'change', |
1263 'cpu_count', | 1108 'cpu_count', |
1264 'environ', | 1109 'environ', |
1265 'fnmatch', | 1110 'fnmatch', |
(...skipping 23 matching lines...) Expand all Loading... |
1289 'version', | 1134 'version', |
1290 'verbose', | 1135 'verbose', |
1291 'dry_run', | 1136 'dry_run', |
1292 'gerrit', | 1137 'gerrit', |
1293 ] | 1138 ] |
1294 # If this test fails, you should add the relevant test. | 1139 # If this test fails, you should add the relevant test. |
1295 self.compareMembers( | 1140 self.compareMembers( |
1296 presubmit.InputApi(self.fake_change, './.', False, None, False), | 1141 presubmit.InputApi(self.fake_change, './.', False, None, False), |
1297 members) | 1142 members) |
1298 | 1143 |
1299 def testDepotToLocalPath(self): | |
1300 presubmit.scm.SVN._CaptureInfo(['svn://foo/smurf'], self.fake_root_dir | |
1301 ).AndReturn({'Path': 'prout'}) | |
1302 presubmit.scm.SVN._CaptureInfo( | |
1303 ['svn:/foo/notfound/burp'], self.fake_root_dir | |
1304 ).AndReturn({}) | |
1305 self.mox.ReplayAll() | |
1306 | |
1307 path = presubmit.InputApi( | |
1308 self.fake_change, './p', False, None, False).DepotToLocalPath( | |
1309 'svn://foo/smurf') | |
1310 self.failUnless(path == 'prout') | |
1311 path = presubmit.InputApi( | |
1312 self.fake_change, './p', False, None, False).DepotToLocalPath( | |
1313 'svn:/foo/notfound/burp') | |
1314 self.failUnless(path == None) | |
1315 | |
1316 def testLocalToDepotPath(self): | |
1317 presubmit.scm.SVN._CaptureInfo(['smurf'], self.fake_root_dir | |
1318 ).AndReturn({'URL': 'svn://foo'}) | |
1319 presubmit.scm.SVN._CaptureInfo(['notfound-food'], self.fake_root_dir | |
1320 ).AndReturn({}) | |
1321 self.mox.ReplayAll() | |
1322 path = presubmit.InputApi( | |
1323 self.fake_change, './p', False, None, False).LocalToDepotPath( | |
1324 'smurf') | |
1325 self.assertEqual(path, 'svn://foo') | |
1326 path = presubmit.InputApi( | |
1327 self.fake_change, './p', False, None, False).LocalToDepotPath( | |
1328 'notfound-food') | |
1329 self.assertEquals(path, None) | |
1330 | |
1331 def testInputApiConstruction(self): | 1144 def testInputApiConstruction(self): |
1332 self.mox.ReplayAll() | 1145 self.mox.ReplayAll() |
1333 api = presubmit.InputApi( | 1146 api = presubmit.InputApi( |
1334 self.fake_change, | 1147 self.fake_change, |
1335 presubmit_path='foo/path/PRESUBMIT.py', | 1148 presubmit_path='foo/path/PRESUBMIT.py', |
1336 is_committing=False, rietveld_obj=None, verbose=False) | 1149 is_committing=False, rietveld_obj=None, verbose=False) |
1337 self.assertEquals(api.PresubmitLocalPath(), 'foo/path') | 1150 self.assertEquals(api.PresubmitLocalPath(), 'foo/path') |
1338 self.assertEquals(api.change, self.fake_change) | 1151 self.assertEquals(api.change, self.fake_change) |
1339 self.assertEquals(api.host_url, 'http://codereview.chromium.org') | 1152 self.assertEquals(api.host_url, 'http://codereview.chromium.org') |
1340 | 1153 |
1341 def testInputApiPresubmitScriptFiltering(self): | 1154 def testInputApiPresubmitScriptFiltering(self): |
1342 join = presubmit.os.path.join | 1155 join = presubmit.os.path.join |
1343 description_lines = ('Hello there', | 1156 description_lines = ('Hello there', |
1344 'this is a change', | 1157 'this is a change', |
1345 'BUG=123', | 1158 'BUG=123', |
1346 ' STORY =http://foo/ \t', | 1159 ' STORY =http://foo/ \t', |
1347 'and some more regular text') | 1160 'and some more regular text') |
1348 files = [ | 1161 files = [ |
1349 ['A', join('foo', 'blat.cc')], | 1162 ['A', join('foo', 'blat.cc'), True], |
1350 ['M', join('foo', 'blat', 'READ_ME2')], | 1163 ['M', join('foo', 'blat', 'READ_ME2'), True], |
1351 ['M', join('foo', 'blat', 'binary.dll')], | 1164 ['M', join('foo', 'blat', 'binary.dll'), True], |
1352 ['M', join('foo', 'blat', 'weird.xyz')], | 1165 ['M', join('foo', 'blat', 'weird.xyz'), True], |
1353 ['M', join('foo', 'blat', 'another.h')], | 1166 ['M', join('foo', 'blat', 'another.h'), True], |
1354 ['M', join('foo', 'third_party', 'third.cc')], | 1167 ['M', join('foo', 'third_party', 'third.cc'), True], |
1355 ['D', join('foo', 'mat', 'beingdeleted.txt')], | 1168 ['D', join('foo', 'mat', 'beingdeleted.txt'), False], |
1356 ['M', join('flop', 'notfound.txt')], | 1169 ['M', join('flop', 'notfound.txt'), False], |
1357 ['A', join('boo', 'flap.h')], | 1170 ['A', join('boo', 'flap.h'), True], |
1358 ] | 1171 ] |
1359 blat = presubmit.normpath(join(self.fake_root_dir, files[0][1])) | 1172 diffs = [] |
1360 readme = presubmit.normpath(join(self.fake_root_dir, files[1][1])) | 1173 for _, f, exists in files: |
1361 binary = presubmit.normpath(join(self.fake_root_dir, files[2][1])) | 1174 full_file = presubmit.os.path.join(self.fake_root_dir, f) |
1362 weird = presubmit.normpath(join(self.fake_root_dir, files[3][1])) | 1175 if exists and f.startswith('foo/'): |
1363 another = presubmit.normpath(join(self.fake_root_dir, files[4][1])) | 1176 presubmit.os.path.isfile(full_file).AndReturn(exists) |
1364 third_party = presubmit.normpath(join(self.fake_root_dir, files[5][1])) | 1177 diffs.append(self.presubmit_diffs % {'filename': f}) |
1365 beingdeleted = presubmit.normpath(join(self.fake_root_dir, files[6][1])) | 1178 presubmit.scm.GIT.GenerateDiff( |
1366 notfound = presubmit.normpath(join(self.fake_root_dir, files[7][1])) | 1179 self.fake_root_dir, branch=None, files=[], full_move=True |
1367 flap = presubmit.normpath(join(self.fake_root_dir, files[8][1])) | 1180 ).AndReturn('\n'.join(diffs)) |
1368 for i in (blat, readme, binary, weird, another, third_party): | |
1369 presubmit.os.path.exists(i).AndReturn(True) | |
1370 presubmit.os.path.isdir(i).AndReturn(False) | |
1371 presubmit.os.path.exists(beingdeleted).AndReturn(False) | |
1372 presubmit.os.path.exists(notfound).AndReturn(False) | |
1373 presubmit.os.path.exists(flap).AndReturn(True) | |
1374 presubmit.os.path.isdir(flap).AndReturn(False) | |
1375 presubmit.scm.SVN._CaptureInfo( | |
1376 [files[6][1]], self.fake_root_dir).AndReturn({}) | |
1377 presubmit.scm.SVN._CaptureInfo( | |
1378 [files[7][1]], self.fake_root_dir).AndReturn({}) | |
1379 presubmit.scm.SVN.GetFileProperty( | |
1380 files[0][1], 'svn:mime-type', self.fake_root_dir | |
1381 ).AndReturn(None) | |
1382 presubmit.scm.SVN.GetFileProperty( | |
1383 files[1][1], 'svn:mime-type', self.fake_root_dir | |
1384 ).AndReturn(None) | |
1385 presubmit.scm.SVN.GetFileProperty( | |
1386 files[2][1], 'svn:mime-type', self.fake_root_dir | |
1387 ).AndReturn('application/octet-stream') | |
1388 presubmit.scm.SVN.GetFileProperty( | |
1389 files[3][1], 'svn:mime-type', self.fake_root_dir | |
1390 ).AndReturn(None) | |
1391 presubmit.scm.SVN.GetFileProperty( | |
1392 files[4][1], 'svn:mime-type', self.fake_root_dir | |
1393 ).AndReturn(None) | |
1394 presubmit.scm.SVN.GetFileProperty( | |
1395 files[5][1], 'svn:mime-type', self.fake_root_dir | |
1396 ).AndReturn(None) | |
1397 presubmit.scm.SVN.GenerateDiff( | |
1398 [files[0][1]], self.fake_root_dir, False, None | |
1399 ).AndReturn(self.presubmit_diffs) | |
1400 presubmit.scm.SVN.GenerateDiff( | |
1401 [files[4][1]], self.fake_root_dir, False, None | |
1402 ).AndReturn(self.presubmit_diffs) | |
1403 | 1181 |
1404 self.mox.ReplayAll() | 1182 self.mox.ReplayAll() |
1405 | 1183 |
1406 change = presubmit.SvnChange( | 1184 change = presubmit.GitChange( |
1407 'mychange', | 1185 'mychange', |
1408 '\n'.join(description_lines), | 1186 '\n'.join(description_lines), |
1409 self.fake_root_dir, | 1187 self.fake_root_dir, |
1410 files, | 1188 [[f[0], f[1]] for f in files], |
1411 0, | 1189 0, |
1412 0, | 1190 0, |
1413 None) | 1191 None) |
1414 input_api = presubmit.InputApi( | 1192 input_api = presubmit.InputApi( |
1415 change, | 1193 change, |
1416 join(self.fake_root_dir, 'foo', 'PRESUBMIT.py'), | 1194 join(self.fake_root_dir, 'foo', 'PRESUBMIT.py'), |
1417 False, None, False) | 1195 False, None, False) |
1418 # Doesn't filter much | 1196 # Doesn't filter much |
1419 got_files = input_api.AffectedFiles() | 1197 got_files = input_api.AffectedFiles() |
1420 self.assertEquals(len(got_files), 7) | 1198 self.assertEquals(len(got_files), 7) |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 self.assertEquals(sorted([f.LocalPath().replace(presubmit.os.sep, '/') | 1305 self.assertEquals(sorted([f.LocalPath().replace(presubmit.os.sep, '/') |
1528 for f in results]), | 1306 for f in results]), |
1529 sorted(item[1])) | 1307 sorted(item[1])) |
1530 | 1308 |
1531 def testCustomFilter(self): | 1309 def testCustomFilter(self): |
1532 def FilterSourceFile(affected_file): | 1310 def FilterSourceFile(affected_file): |
1533 return 'a' in affected_file.LocalPath() | 1311 return 'a' in affected_file.LocalPath() |
1534 files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee')] | 1312 files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee')] |
1535 for _, item in files: | 1313 for _, item in files: |
1536 full_item = presubmit.os.path.join(self.fake_root_dir, item) | 1314 full_item = presubmit.os.path.join(self.fake_root_dir, item) |
1537 presubmit.os.path.exists(full_item).AndReturn(True) | 1315 presubmit.os.path.isfile(full_item).AndReturn(True) |
1538 presubmit.os.path.isdir(full_item).AndReturn(False) | |
1539 presubmit.scm.SVN.GetFileProperty( | |
1540 item, 'svn:mime-type', self.fake_root_dir).AndReturn(None) | |
1541 self.mox.ReplayAll() | 1316 self.mox.ReplayAll() |
1542 | 1317 |
1543 change = presubmit.SvnChange( | 1318 change = presubmit.GitChange( |
1544 'mychange', '', self.fake_root_dir, files, 0, 0, None) | 1319 'mychange', '', self.fake_root_dir, files, 0, 0, None) |
1545 input_api = presubmit.InputApi( | 1320 input_api = presubmit.InputApi( |
1546 change, | 1321 change, |
1547 presubmit.os.path.join(self.fake_root_dir, 'PRESUBMIT.py'), | 1322 presubmit.os.path.join(self.fake_root_dir, 'PRESUBMIT.py'), |
1548 False, None, False) | 1323 False, None, False) |
1549 got_files = input_api.AffectedSourceFiles(FilterSourceFile) | 1324 got_files = input_api.AffectedSourceFiles(FilterSourceFile) |
1550 self.assertEquals(len(got_files), 2) | 1325 self.assertEquals(len(got_files), 2) |
1551 self.assertEquals(got_files[0].LocalPath(), 'eeaee') | 1326 self.assertEquals(got_files[0].LocalPath(), 'eeaee') |
1552 self.assertEquals(got_files[1].LocalPath(), 'eeabee') | 1327 self.assertEquals(got_files[1].LocalPath(), 'eeabee') |
1553 | 1328 |
1554 def testLambdaFilter(self): | 1329 def testLambdaFilter(self): |
1555 white_list = presubmit.InputApi.DEFAULT_BLACK_LIST + (r".*?a.*?",) | 1330 white_list = presubmit.InputApi.DEFAULT_BLACK_LIST + (r".*?a.*?",) |
1556 black_list = [r".*?b.*?"] | 1331 black_list = [r".*?b.*?"] |
1557 files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee'), ('M', 'eecaee')] | 1332 files = [('A', 'eeaee'), ('M', 'eeabee'), ('M', 'eebcee'), ('M', 'eecaee')] |
1558 for _, item in files: | 1333 for _, item in files: |
1559 full_item = presubmit.os.path.join(self.fake_root_dir, item) | 1334 full_item = presubmit.os.path.join(self.fake_root_dir, item) |
1560 presubmit.os.path.exists(full_item).AndReturn(True) | 1335 presubmit.os.path.isfile(full_item).AndReturn(True) |
1561 presubmit.os.path.isdir(full_item).AndReturn(False) | |
1562 presubmit.scm.SVN.GetFileProperty( | |
1563 item, 'svn:mime-type', self.fake_root_dir).AndReturn(None) | |
1564 self.mox.ReplayAll() | 1336 self.mox.ReplayAll() |
1565 | 1337 |
1566 change = presubmit.SvnChange( | 1338 change = presubmit.GitChange( |
1567 'mychange', '', self.fake_root_dir, files, 0, 0, None) | 1339 'mychange', '', self.fake_root_dir, files, 0, 0, None) |
1568 input_api = presubmit.InputApi( | 1340 input_api = presubmit.InputApi( |
1569 change, './PRESUBMIT.py', False, None, False) | 1341 change, './PRESUBMIT.py', False, None, False) |
1570 # Sample usage of overiding the default white and black lists. | 1342 # Sample usage of overiding the default white and black lists. |
1571 got_files = input_api.AffectedSourceFiles( | 1343 got_files = input_api.AffectedSourceFiles( |
1572 lambda x: input_api.FilterSourceFile(x, white_list, black_list)) | 1344 lambda x: input_api.FilterSourceFile(x, white_list, black_list)) |
1573 self.assertEquals(len(got_files), 2) | 1345 self.assertEquals(len(got_files), 2) |
1574 self.assertEquals(got_files[0].LocalPath(), 'eeaee') | 1346 self.assertEquals(got_files[0].LocalPath(), 'eeaee') |
1575 self.assertEquals(got_files[1].LocalPath(), 'eecaee') | 1347 self.assertEquals(got_files[1].LocalPath(), 'eecaee') |
1576 | 1348 |
1577 def testGetAbsoluteLocalPath(self): | 1349 def testGetAbsoluteLocalPath(self): |
1578 join = presubmit.os.path.join | 1350 join = presubmit.os.path.join |
1579 normpath = presubmit.normpath | 1351 normpath = presubmit.normpath |
1580 # Regression test for bug of presubmit stuff that relies on invoking | 1352 # Regression test for bug of presubmit stuff that relies on invoking |
1581 # SVN (e.g. to get mime type of file) not working unless gcl invoked | 1353 # SVN (e.g. to get mime type of file) not working unless gcl invoked |
1582 # from the client root (e.g. if you were at 'src' and did 'cd base' before | 1354 # from the client root (e.g. if you were at 'src' and did 'cd base' before |
1583 # invoking 'gcl upload' it would fail because svn wouldn't find the files | 1355 # invoking 'gcl upload' it would fail because svn wouldn't find the files |
1584 # the presubmit script was asking about). | 1356 # the presubmit script was asking about). |
1585 files = [ | 1357 files = [ |
1586 ['A', 'isdir'], | 1358 ['A', 'isdir'], |
1587 ['A', join('isdir', 'blat.cc')], | 1359 ['A', join('isdir', 'blat.cc')], |
1588 ['M', join('elsewhere', 'ouf.cc')], | 1360 ['M', join('elsewhere', 'ouf.cc')], |
1589 ] | 1361 ] |
1590 self.mox.ReplayAll() | 1362 self.mox.ReplayAll() |
1591 | 1363 |
1592 change = presubmit.Change( | 1364 change = presubmit.Change( |
1593 'mychange', '', self.fake_root_dir, files, 0, 0, None) | 1365 'mychange', '', self.fake_root_dir, files, 0, 0, None) |
1594 affected_files = change.AffectedFiles(include_dirs=True) | 1366 affected_files = change.AffectedFiles() |
1595 # Local paths should remain the same | 1367 # Local paths should remain the same |
1596 self.assertEquals(affected_files[0].LocalPath(), normpath('isdir')) | 1368 self.assertEquals(affected_files[0].LocalPath(), normpath('isdir')) |
1597 self.assertEquals(affected_files[1].LocalPath(), normpath('isdir/blat.cc')) | 1369 self.assertEquals(affected_files[1].LocalPath(), normpath('isdir/blat.cc')) |
1598 # Absolute paths should be prefixed | 1370 # Absolute paths should be prefixed |
1599 self.assertEquals(affected_files[0].AbsoluteLocalPath(), | 1371 self.assertEquals(affected_files[0].AbsoluteLocalPath(), |
1600 normpath(join(self.fake_root_dir, 'isdir'))) | 1372 normpath(join(self.fake_root_dir, 'isdir'))) |
1601 self.assertEquals(affected_files[1].AbsoluteLocalPath(), | 1373 self.assertEquals(affected_files[1].AbsoluteLocalPath(), |
1602 normpath(join(self.fake_root_dir, 'isdir/blat.cc'))) | 1374 normpath(join(self.fake_root_dir, 'isdir/blat.cc'))) |
1603 | 1375 |
1604 # New helper functions need to work | 1376 # New helper functions need to work |
1605 paths_from_change = change.AbsoluteLocalPaths(include_dirs=True) | 1377 paths_from_change = change.AbsoluteLocalPaths() |
1606 self.assertEqual(len(paths_from_change), 3) | 1378 self.assertEqual(len(paths_from_change), 3) |
1607 presubmit_path = join(self.fake_root_dir, 'isdir', 'PRESUBMIT.py') | 1379 presubmit_path = join(self.fake_root_dir, 'isdir', 'PRESUBMIT.py') |
1608 api = presubmit.InputApi( | 1380 api = presubmit.InputApi( |
1609 change=change, presubmit_path=presubmit_path, | 1381 change=change, presubmit_path=presubmit_path, |
1610 is_committing=True, rietveld_obj=None, verbose=False) | 1382 is_committing=True, rietveld_obj=None, verbose=False) |
1611 paths_from_api = api.AbsoluteLocalPaths(include_dirs=True) | 1383 paths_from_api = api.AbsoluteLocalPaths() |
1612 self.assertEqual(len(paths_from_api), 2) | 1384 self.assertEqual(len(paths_from_api), 2) |
1613 for absolute_paths in [paths_from_change, paths_from_api]: | 1385 for absolute_paths in [paths_from_change, paths_from_api]: |
1614 self.assertEqual(absolute_paths[0], | 1386 self.assertEqual(absolute_paths[0], |
1615 normpath(join(self.fake_root_dir, 'isdir'))) | 1387 normpath(join(self.fake_root_dir, 'isdir'))) |
1616 self.assertEqual(absolute_paths[1], | 1388 self.assertEqual(absolute_paths[1], |
1617 normpath(join(self.fake_root_dir, 'isdir', 'blat.cc'))) | 1389 normpath(join(self.fake_root_dir, 'isdir', 'blat.cc'))) |
1618 | 1390 |
1619 def testDeprecated(self): | 1391 def testDeprecated(self): |
1620 presubmit.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), stacklevel=2) | 1392 presubmit.warn(mox.IgnoreArg(), category=mox.IgnoreArg(), stacklevel=2) |
1621 self.mox.ReplayAll() | 1393 self.mox.ReplayAll() |
1622 | 1394 |
1623 change = presubmit.Change( | 1395 change = presubmit.Change( |
1624 'mychange', '', self.fake_root_dir, [], 0, 0, None) | 1396 'mychange', '', self.fake_root_dir, [], 0, 0, None) |
1625 api = presubmit.InputApi( | 1397 api = presubmit.InputApi( |
1626 change, | 1398 change, |
1627 presubmit.os.path.join(self.fake_root_dir, 'foo', 'PRESUBMIT.py'), True, | 1399 presubmit.os.path.join(self.fake_root_dir, 'foo', 'PRESUBMIT.py'), True, |
1628 None, False) | 1400 None, False) |
1629 api.AffectedTextFiles(include_deletes=False) | 1401 api.AffectedTestableFiles(include_deletes=False) |
1630 | 1402 |
1631 def testReadFileStringDenied(self): | 1403 def testReadFileStringDenied(self): |
1632 self.mox.ReplayAll() | 1404 self.mox.ReplayAll() |
1633 | 1405 |
1634 change = presubmit.Change( | 1406 change = presubmit.Change( |
1635 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) | 1407 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, None) |
1636 input_api = presubmit.InputApi( | 1408 input_api = presubmit.InputApi( |
1637 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, | 1409 change, presubmit.os.path.join(self.fake_root_dir, '/p'), False, |
1638 None, False) | 1410 None, False) |
1639 self.assertRaises(IOError, input_api.ReadFile, 'boo', 'x') | 1411 self.assertRaises(IOError, input_api.ReadFile, 'boo', 'x') |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1748 output.prompt_yes_no('prompt: ') | 1520 output.prompt_yes_no('prompt: ') |
1749 self.failIf(output.should_continue()) | 1521 self.failIf(output.should_continue()) |
1750 self.failUnless(output.getvalue().count('???')) | 1522 self.failUnless(output.getvalue().count('???')) |
1751 | 1523 |
1752 | 1524 |
1753 class AffectedFileUnittest(PresubmitTestsBase): | 1525 class AffectedFileUnittest(PresubmitTestsBase): |
1754 def testMembersChanged(self): | 1526 def testMembersChanged(self): |
1755 self.mox.ReplayAll() | 1527 self.mox.ReplayAll() |
1756 members = [ | 1528 members = [ |
1757 'AbsoluteLocalPath', 'Action', 'ChangedContents', 'DIFF_CACHE', | 1529 'AbsoluteLocalPath', 'Action', 'ChangedContents', 'DIFF_CACHE', |
1758 'GenerateScmDiff', 'IsDirectory', 'IsTextFile', 'LocalPath', | 1530 'GenerateScmDiff', 'IsTestableFile', 'IsTextFile', 'LocalPath', |
1759 'NewContents', 'Property', 'ServerPath', | 1531 'NewContents', |
1760 ] | 1532 ] |
1761 # If this test fails, you should add the relevant test. | 1533 # If this test fails, you should add the relevant test. |
1762 self.compareMembers( | 1534 self.compareMembers( |
1763 presubmit.AffectedFile('a', 'b', self.fake_root_dir, None), members) | 1535 presubmit.AffectedFile('a', 'b', self.fake_root_dir, None), members) |
1764 self.compareMembers( | 1536 self.compareMembers( |
1765 presubmit.SvnAffectedFile('a', 'b', self.fake_root_dir, None), members) | |
1766 self.compareMembers( | |
1767 presubmit.GitAffectedFile('a', 'b', self.fake_root_dir, None), members) | 1537 presubmit.GitAffectedFile('a', 'b', self.fake_root_dir, None), members) |
1768 | 1538 |
1769 def testAffectedFile(self): | 1539 def testAffectedFile(self): |
1770 path = presubmit.os.path.join('foo', 'blat.cc') | 1540 path = presubmit.os.path.join('foo', 'blat.cc') |
1771 f_path = presubmit.os.path.join(self.fake_root_dir, path) | 1541 f_path = presubmit.os.path.join(self.fake_root_dir, path) |
1772 presubmit.os.path.exists(f_path).AndReturn(True) | |
1773 presubmit.os.path.isdir(f_path).AndReturn(False) | |
1774 presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie') | 1542 presubmit.gclient_utils.FileRead(f_path, 'rU').AndReturn('whatever\ncookie') |
1775 presubmit.scm.SVN._CaptureInfo([path], self.fake_root_dir).AndReturn( | |
1776 {'URL': 'svn:/foo/foo/blat.cc'}) | |
1777 self.mox.ReplayAll() | 1543 self.mox.ReplayAll() |
1778 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M', self.fake_root_dir, None) | 1544 af = presubmit.GitAffectedFile('foo/blat.cc', 'M', self.fake_root_dir, None) |
1779 self.assertEquals('svn:/foo/foo/blat.cc', af.ServerPath()) | |
1780 self.assertEquals(presubmit.normpath('foo/blat.cc'), af.LocalPath()) | 1545 self.assertEquals(presubmit.normpath('foo/blat.cc'), af.LocalPath()) |
1781 self.assertEquals('M', af.Action()) | 1546 self.assertEquals('M', af.Action()) |
1782 self.assertEquals(['whatever', 'cookie'], af.NewContents()) | 1547 self.assertEquals(['whatever', 'cookie'], af.NewContents()) |
1783 | 1548 |
1784 def testAffectedFileNotExists(self): | 1549 def testAffectedFileNotExists(self): |
1785 notfound = 'notfound.cc' | 1550 notfound = 'notfound.cc' |
1786 f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound) | 1551 f_notfound = presubmit.os.path.join(self.fake_root_dir, notfound) |
1787 presubmit.os.path.exists(f_notfound).AndReturn(False) | |
1788 presubmit.gclient_utils.FileRead(f_notfound, 'rU').AndRaise(IOError) | 1552 presubmit.gclient_utils.FileRead(f_notfound, 'rU').AndRaise(IOError) |
1789 self.mox.ReplayAll() | 1553 self.mox.ReplayAll() |
1790 af = presubmit.AffectedFile(notfound, 'A', self.fake_root_dir, None) | 1554 af = presubmit.AffectedFile(notfound, 'A', self.fake_root_dir, None) |
1791 self.assertEquals('', af.ServerPath()) | |
1792 self.assertEquals([], af.NewContents()) | 1555 self.assertEquals([], af.NewContents()) |
1793 | 1556 |
1794 def testProperty(self): | 1557 def testIsTestableFile(self): |
1795 presubmit.scm.SVN.GetFileProperty( | |
1796 'foo.cc', 'svn:secret-property', self.fake_root_dir | |
1797 ).AndReturn('secret-property-value') | |
1798 self.mox.ReplayAll() | |
1799 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A', self.fake_root_dir, | |
1800 None) | |
1801 # Verify cache coherency. | |
1802 self.assertEquals('secret-property-value', | |
1803 affected_file.Property('svn:secret-property')) | |
1804 self.assertEquals('secret-property-value', | |
1805 affected_file.Property('svn:secret-property')) | |
1806 | |
1807 def testIsDirectoryNotExists(self): | |
1808 filename = 'foo.cc' | |
1809 f_filename = presubmit.os.path.join(self.fake_root_dir, filename) | |
1810 presubmit.os.path.exists(f_filename).AndReturn(False) | |
1811 presubmit.scm.SVN._CaptureInfo([filename], self.fake_root_dir).AndReturn({}) | |
1812 self.mox.ReplayAll() | |
1813 affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir, | |
1814 None) | |
1815 # Verify cache coherency. | |
1816 self.failIf(affected_file.IsDirectory()) | |
1817 self.failIf(affected_file.IsDirectory()) | |
1818 | |
1819 def testIsDirectory(self): | |
1820 filename = 'foo.cc' | |
1821 f_filename = presubmit.os.path.join(self.fake_root_dir, filename) | |
1822 presubmit.os.path.exists(f_filename).AndReturn(True) | |
1823 presubmit.os.path.isdir(f_filename).AndReturn(True) | |
1824 self.mox.ReplayAll() | |
1825 affected_file = presubmit.SvnAffectedFile(filename, 'A', self.fake_root_dir, | |
1826 None) | |
1827 # Verify cache coherency. | |
1828 self.failUnless(affected_file.IsDirectory()) | |
1829 self.failUnless(affected_file.IsDirectory()) | |
1830 | |
1831 def testIsTextFile(self): | |
1832 files = [ | 1558 files = [ |
1833 presubmit.SvnAffectedFile('foo/blat.txt', 'M', self.fake_root_dir, | 1559 presubmit.GitAffectedFile('foo/blat.txt', 'M', self.fake_root_dir, |
1834 None), | 1560 None), |
1835 presubmit.SvnAffectedFile('foo/binary.blob', 'M', self.fake_root_dir, | 1561 presubmit.GitAffectedFile('foo/binary.blob', 'M', self.fake_root_dir, |
1836 None), | 1562 None), |
1837 presubmit.SvnAffectedFile('blat/flop.txt', 'D', self.fake_root_dir, | 1563 presubmit.GitAffectedFile('blat/flop.txt', 'D', self.fake_root_dir, |
1838 None) | 1564 None) |
1839 ] | 1565 ] |
1840 blat = presubmit.os.path.join('foo', 'blat.txt') | 1566 blat = presubmit.os.path.join('foo', 'blat.txt') |
1841 blob = presubmit.os.path.join('foo', 'binary.blob') | 1567 blob = presubmit.os.path.join('foo', 'binary.blob') |
1842 f_blat = presubmit.os.path.join(self.fake_root_dir, blat) | 1568 f_blat = presubmit.os.path.join(self.fake_root_dir, blat) |
1843 f_blob = presubmit.os.path.join(self.fake_root_dir, blob) | 1569 f_blob = presubmit.os.path.join(self.fake_root_dir, blob) |
1844 presubmit.os.path.exists(f_blat).AndReturn(True) | 1570 presubmit.os.path.isfile(f_blat).AndReturn(True) |
1845 presubmit.os.path.isdir(f_blat).AndReturn(False) | 1571 presubmit.os.path.isfile(f_blob).AndReturn(True) |
1846 presubmit.os.path.exists(f_blob).AndReturn(True) | |
1847 presubmit.os.path.isdir(f_blob).AndReturn(False) | |
1848 presubmit.scm.SVN.GetFileProperty(blat, 'svn:mime-type', self.fake_root_dir | |
1849 ).AndReturn(None) | |
1850 presubmit.scm.SVN.GetFileProperty(blob, 'svn:mime-type', self.fake_root_dir | |
1851 ).AndReturn('application/octet-stream') | |
1852 self.mox.ReplayAll() | 1572 self.mox.ReplayAll() |
1853 | 1573 |
1854 output = filter(lambda x: x.IsTextFile(), files) | 1574 output = filter(lambda x: x.IsTestableFile(), files) |
1855 self.assertEquals(1, len(output)) | 1575 self.assertEquals(2, len(output)) |
1856 self.assertEquals(files[0], output[0]) | 1576 self.assertEquals(files[0], output[0]) |
1857 | 1577 |
1858 | 1578 |
1859 class ChangeUnittest(PresubmitTestsBase): | 1579 class ChangeUnittest(PresubmitTestsBase): |
1860 def testMembersChanged(self): | 1580 def testMembersChanged(self): |
1861 members = [ | 1581 members = [ |
1862 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', 'AllFiles', | 1582 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTestableFiles', |
1863 'DescriptionText', 'FullDescriptionText', 'LocalPaths', 'Name', | 1583 'AffectedTextFiles', |
1864 'RepositoryRoot', 'RightHandSideLines', 'ServerPaths', | 1584 'AllFiles', 'DescriptionText', 'FullDescriptionText', 'LocalPaths', |
| 1585 'Name', 'RepositoryRoot', 'RightHandSideLines', |
1865 'SetDescriptionText', 'TAG_LINE_RE', | 1586 'SetDescriptionText', 'TAG_LINE_RE', |
1866 'author_email', 'issue', 'patchset', 'scm', 'tags', | 1587 'author_email', 'issue', 'patchset', 'scm', 'tags', |
1867 ] | 1588 ] |
1868 # If this test fails, you should add the relevant test. | 1589 # If this test fails, you should add the relevant test. |
1869 self.mox.ReplayAll() | 1590 self.mox.ReplayAll() |
1870 | 1591 |
1871 change = presubmit.Change( | 1592 change = presubmit.Change( |
1872 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, 'foo') | 1593 'foo', 'foo', self.fake_root_dir, [('M', 'AA')], 0, 0, 'foo') |
1873 self.compareMembers(change, members) | 1594 self.compareMembers(change, members) |
1874 | 1595 |
1875 def testMembers(self): | 1596 def testMembers(self): |
1876 change = presubmit.Change( | 1597 change = presubmit.Change( |
1877 'foo1', 'foo2\nDRU=ro', self.fake_root_dir, [('Y', 'AA')], 3, 5, 'foo3') | 1598 'foo1', 'foo2\nDRU=ro', self.fake_root_dir, [('Y', 'AA')], 3, 5, 'foo3') |
1878 self.assertEquals('foo1', change.Name()) | 1599 self.assertEquals('foo1', change.Name()) |
1879 self.assertEquals('foo2', change.DescriptionText()) | 1600 self.assertEquals('foo2', change.DescriptionText()) |
1880 self.assertEquals('foo3', change.author_email) | 1601 self.assertEquals('foo3', change.author_email) |
1881 self.assertEquals('ro', change.DRU) | 1602 self.assertEquals('ro', change.DRU) |
1882 self.assertEquals(3, change.issue) | 1603 self.assertEquals(3, change.issue) |
1883 self.assertEquals(5, change.patchset) | 1604 self.assertEquals(5, change.patchset) |
1884 self.assertEquals(self.fake_root_dir, change.RepositoryRoot()) | 1605 self.assertEquals(self.fake_root_dir, change.RepositoryRoot()) |
1885 self.assertEquals(1, len(change.AffectedFiles(include_dirs=True))) | 1606 self.assertEquals(1, len(change.AffectedFiles())) |
1886 self.assertEquals('Y', change.AffectedFiles(include_dirs=True)[0].Action()) | 1607 self.assertEquals('Y', change.AffectedFiles()[0].Action()) |
1887 | 1608 |
1888 def testSetDescriptionText(self): | 1609 def testSetDescriptionText(self): |
1889 change = presubmit.Change( | 1610 change = presubmit.Change( |
1890 '', 'foo\nDRU=ro', self.fake_root_dir, [], 3, 5, '') | 1611 '', 'foo\nDRU=ro', self.fake_root_dir, [], 3, 5, '') |
1891 self.assertEquals('foo', change.DescriptionText()) | 1612 self.assertEquals('foo', change.DescriptionText()) |
1892 self.assertEquals('foo\nDRU=ro', change.FullDescriptionText()) | 1613 self.assertEquals('foo\nDRU=ro', change.FullDescriptionText()) |
1893 self.assertEquals('ro', change.DRU) | 1614 self.assertEquals('ro', change.DRU) |
1894 | 1615 |
1895 change.SetDescriptionText('bar\nWHIZ=bang') | 1616 change.SetDescriptionText('bar\nWHIZ=bang') |
1896 self.assertEquals('bar', change.DescriptionText()) | 1617 self.assertEquals('bar', change.DescriptionText()) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1954 'BLACKLIST_LINT_FILTERS', | 1675 'BLACKLIST_LINT_FILTERS', |
1955 'CheckBuildbotPendingBuilds', | 1676 'CheckBuildbotPendingBuilds', |
1956 'CheckChangeHasBugField', 'CheckChangeHasDescription', | 1677 'CheckChangeHasBugField', 'CheckChangeHasDescription', |
1957 'CheckChangeHasNoStrayWhitespace', | 1678 'CheckChangeHasNoStrayWhitespace', |
1958 'CheckChangeHasOnlyOneEol', 'CheckChangeHasNoCR', | 1679 'CheckChangeHasOnlyOneEol', 'CheckChangeHasNoCR', |
1959 'CheckChangeHasNoCrAndHasOnlyOneEol', 'CheckChangeHasNoTabs', | 1680 'CheckChangeHasNoCrAndHasOnlyOneEol', 'CheckChangeHasNoTabs', |
1960 'CheckChangeTodoHasOwner', | 1681 'CheckChangeTodoHasOwner', |
1961 'CheckChangeHasQaField', 'CheckChangeHasTestedField', | 1682 'CheckChangeHasQaField', 'CheckChangeHasTestedField', |
1962 'CheckChangeHasTestField', | 1683 'CheckChangeHasTestField', |
1963 'CheckChangeLintsClean', | 1684 'CheckChangeLintsClean', |
1964 'CheckChangeSvnEolStyle', | |
1965 'CheckChangeWasUploaded', | 1685 'CheckChangeWasUploaded', |
1966 'CheckDoNotSubmit', | 1686 'CheckDoNotSubmit', |
1967 'CheckDoNotSubmitInDescription', 'CheckDoNotSubmitInFiles', | 1687 'CheckDoNotSubmitInDescription', 'CheckDoNotSubmitInFiles', |
1968 'CheckGenderNeutral', | 1688 'CheckGenderNeutral', |
1969 'CheckLongLines', 'CheckTreeIsOpen', 'PanProjectChecks', | 1689 'CheckLongLines', 'CheckTreeIsOpen', 'PanProjectChecks', |
1970 'CheckLicense', | 1690 'CheckLicense', |
1971 'CheckOwners', | 1691 'CheckOwners', |
1972 'CheckPatchFormatted', | 1692 'CheckPatchFormatted', |
1973 'CheckGNFormatted', | 1693 'CheckGNFormatted', |
1974 'CheckRietveldTryJobExecution', | 1694 'CheckRietveldTryJobExecution', |
1975 'CheckSingletonInHeaders', | 1695 'CheckSingletonInHeaders', |
1976 'CheckSvnForCommonMimeTypes', 'CheckSvnProperty', | |
1977 'RunPythonUnitTests', 'RunPylint', | 1696 'RunPythonUnitTests', 'RunPylint', |
1978 'RunUnitTests', 'RunUnitTestsInDirectory', | 1697 'RunUnitTests', 'RunUnitTestsInDirectory', |
1979 'GetCodereviewOwnerAndReviewers', | 1698 'GetCodereviewOwnerAndReviewers', |
1980 'GetPythonUnitTests', 'GetPylint', | 1699 'GetPythonUnitTests', 'GetPylint', |
1981 'GetUnitTests', 'GetUnitTestsInDirectory', 'GetUnitTestsRecursively', | 1700 'GetUnitTests', 'GetUnitTestsInDirectory', 'GetUnitTestsRecursively', |
1982 ] | 1701 ] |
1983 # If this test fails, you should add the relevant test. | 1702 # If this test fails, you should add the relevant test. |
1984 self.compareMembers(presubmit_canned_checks, members) | 1703 self.compareMembers(presubmit_canned_checks, members) |
1985 | 1704 |
1986 def DescriptionTest(self, check, description1, description2, error_type, | 1705 def DescriptionTest(self, check, description1, description2, error_type, |
(...skipping 20 matching lines...) Expand all Loading... |
2007 check: the check to run. | 1726 check: the check to run. |
2008 content1: content which is expected to pass the check. | 1727 content1: content which is expected to pass the check. |
2009 content1_path: file path for content1. | 1728 content1_path: file path for content1. |
2010 content2: content which is expected to fail the check. | 1729 content2: content which is expected to fail the check. |
2011 content2_path: file path for content2. | 1730 content2_path: file path for content2. |
2012 error_type: the type of the error expected for content2. | 1731 error_type: the type of the error expected for content2. |
2013 """ | 1732 """ |
2014 change1 = presubmit.Change( | 1733 change1 = presubmit.Change( |
2015 'foo1', 'foo1\n', self.fake_root_dir, None, 0, 0, None) | 1734 'foo1', 'foo1\n', self.fake_root_dir, None, 0, 0, None) |
2016 input_api1 = self.MockInputApi(change1, False) | 1735 input_api1 = self.MockInputApi(change1, False) |
2017 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1736 affected_file = self.mox.CreateMock(presubmit.GitAffectedFile) |
2018 input_api1.AffectedFiles( | 1737 input_api1.AffectedFiles( |
2019 include_deletes=False, | 1738 include_deletes=False, |
2020 file_filter=mox.IgnoreArg()).AndReturn([affected_file]) | 1739 file_filter=mox.IgnoreArg()).AndReturn([affected_file]) |
2021 affected_file.LocalPath().AndReturn(content1_path) | 1740 affected_file.LocalPath().AndReturn(content1_path) |
2022 affected_file.NewContents().AndReturn([ | 1741 affected_file.NewContents().AndReturn([ |
2023 'afoo', | 1742 'afoo', |
2024 content1, | 1743 content1, |
2025 'bfoo', | 1744 'bfoo', |
2026 'cfoo', | 1745 'cfoo', |
2027 'dfoo']) | 1746 'dfoo']) |
(...skipping 26 matching lines...) Expand all Loading... |
2054 results1 = check(input_api1, presubmit.OutputApi, None) | 1773 results1 = check(input_api1, presubmit.OutputApi, None) |
2055 self.assertEquals(results1, []) | 1774 self.assertEquals(results1, []) |
2056 results2 = check(input_api2, presubmit.OutputApi, None) | 1775 results2 = check(input_api2, presubmit.OutputApi, None) |
2057 self.assertEquals(len(results2), 1) | 1776 self.assertEquals(len(results2), 1) |
2058 self.assertEquals(results2[0].__class__, error_type) | 1777 self.assertEquals(results2[0].__class__, error_type) |
2059 | 1778 |
2060 def ReadFileTest(self, check, content1, content2, error_type): | 1779 def ReadFileTest(self, check, content1, content2, error_type): |
2061 change1 = presubmit.Change( | 1780 change1 = presubmit.Change( |
2062 'foo1', 'foo1\n', self.fake_root_dir, None, 0, 0, None) | 1781 'foo1', 'foo1\n', self.fake_root_dir, None, 0, 0, None) |
2063 input_api1 = self.MockInputApi(change1, False) | 1782 input_api1 = self.MockInputApi(change1, False) |
2064 affected_file1 = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1783 affected_file1 = self.mox.CreateMock(presubmit.GitAffectedFile) |
2065 input_api1.AffectedSourceFiles(None).AndReturn([affected_file1]) | 1784 input_api1.AffectedSourceFiles(None).AndReturn([affected_file1]) |
2066 input_api1.ReadFile(affected_file1, 'rb').AndReturn(content1) | 1785 input_api1.ReadFile(affected_file1, 'rb').AndReturn(content1) |
2067 change2 = presubmit.Change( | 1786 change2 = presubmit.Change( |
2068 'foo2', 'foo2\n', self.fake_root_dir, None, 0, 0, None) | 1787 'foo2', 'foo2\n', self.fake_root_dir, None, 0, 0, None) |
2069 input_api2 = self.MockInputApi(change2, False) | 1788 input_api2 = self.MockInputApi(change2, False) |
2070 affected_file2 = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1789 affected_file2 = self.mox.CreateMock(presubmit.GitAffectedFile) |
2071 input_api2.AffectedSourceFiles(None).AndReturn([affected_file2]) | 1790 input_api2.AffectedSourceFiles(None).AndReturn([affected_file2]) |
2072 input_api2.ReadFile(affected_file2, 'rb').AndReturn(content2) | 1791 input_api2.ReadFile(affected_file2, 'rb').AndReturn(content2) |
2073 affected_file2.LocalPath().AndReturn('bar.cc') | 1792 affected_file2.LocalPath().AndReturn('bar.cc') |
2074 self.mox.ReplayAll() | 1793 self.mox.ReplayAll() |
2075 | 1794 |
2076 results = check(input_api1, presubmit.OutputApi) | 1795 results = check(input_api1, presubmit.OutputApi) |
2077 self.assertEquals(results, []) | 1796 self.assertEquals(results, []) |
2078 results2 = check(input_api2, presubmit.OutputApi) | 1797 results2 = check(input_api2, presubmit.OutputApi) |
2079 self.assertEquals(len(results2), 1) | 1798 self.assertEquals(len(results2), 1) |
2080 self.assertEquals(results2[0].__class__, error_type) | 1799 self.assertEquals(results2[0].__class__, error_type) |
2081 | 1800 |
2082 def SvnPropertyTest(self, check, property_name, value1, value2, committing, | |
2083 error_type, use_source_file): | |
2084 change1 = presubmit.SvnChange( | |
2085 'mychange', '', self.fake_root_dir, [], 0, 0, None) | |
2086 input_api1 = self.MockInputApi(change1, committing) | |
2087 files1 = [ | |
2088 presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir, None), | |
2089 presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir, None), | |
2090 ] | |
2091 if use_source_file: | |
2092 input_api1.AffectedSourceFiles(None).AndReturn(files1) | |
2093 else: | |
2094 input_api1.AffectedFiles(include_deletes=False).AndReturn(files1) | |
2095 presubmit.scm.SVN.GetFileProperty( | |
2096 presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir | |
2097 ).AndReturn(value1) | |
2098 presubmit.scm.SVN.GetFileProperty( | |
2099 presubmit.normpath('foo.cc'), property_name, self.fake_root_dir | |
2100 ).AndReturn(value1) | |
2101 change2 = presubmit.SvnChange( | |
2102 'mychange', '', self.fake_root_dir, [], 0, 0, None) | |
2103 input_api2 = self.MockInputApi(change2, committing) | |
2104 files2 = [ | |
2105 presubmit.SvnAffectedFile('foo/bar.cc', 'A', self.fake_root_dir, None), | |
2106 presubmit.SvnAffectedFile('foo.cc', 'M', self.fake_root_dir, None), | |
2107 ] | |
2108 if use_source_file: | |
2109 input_api2.AffectedSourceFiles(None).AndReturn(files2) | |
2110 else: | |
2111 input_api2.AffectedFiles(include_deletes=False).AndReturn(files2) | |
2112 | |
2113 presubmit.scm.SVN.GetFileProperty( | |
2114 presubmit.normpath('foo/bar.cc'), property_name, self.fake_root_dir | |
2115 ).AndReturn(value2) | |
2116 presubmit.scm.SVN.GetFileProperty( | |
2117 presubmit.normpath('foo.cc'), property_name, self.fake_root_dir | |
2118 ).AndReturn(value2) | |
2119 self.mox.ReplayAll() | |
2120 | |
2121 results1 = check(input_api1, presubmit.OutputApi, None) | |
2122 self.assertEquals(results1, []) | |
2123 results2 = check(input_api2, presubmit.OutputApi, None) | |
2124 self.assertEquals(len(results2), 1) | |
2125 self.assertEquals(results2[0].__class__, error_type) | |
2126 | |
2127 def testCannedCheckChangeHasBugField(self): | 1801 def testCannedCheckChangeHasBugField(self): |
2128 self.DescriptionTest(presubmit_canned_checks.CheckChangeHasBugField, | 1802 self.DescriptionTest(presubmit_canned_checks.CheckChangeHasBugField, |
2129 'Foo\nBUG=1234', 'Foo\n', | 1803 'Foo\nBUG=1234', 'Foo\n', |
2130 presubmit.OutputApi.PresubmitNotifyResult, | 1804 presubmit.OutputApi.PresubmitNotifyResult, |
2131 False) | 1805 False) |
2132 | 1806 |
2133 def testCheckChangeHasDescription(self): | 1807 def testCheckChangeHasDescription(self): |
2134 self.DescriptionTest(presubmit_canned_checks.CheckChangeHasDescription, | 1808 self.DescriptionTest(presubmit_canned_checks.CheckChangeHasDescription, |
2135 'Bleh', '', | 1809 'Bleh', '', |
2136 presubmit.OutputApi.PresubmitNotifyResult, | 1810 presubmit.OutputApi.PresubmitNotifyResult, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2206 | 1880 |
2207 def testCannedCheckChangeHasNoTabs(self): | 1881 def testCannedCheckChangeHasNoTabs(self): |
2208 self.ContentTest(presubmit_canned_checks.CheckChangeHasNoTabs, | 1882 self.ContentTest(presubmit_canned_checks.CheckChangeHasNoTabs, |
2209 'blah blah', None, 'blah\tblah', None, | 1883 'blah blah', None, 'blah\tblah', None, |
2210 presubmit.OutputApi.PresubmitPromptWarning) | 1884 presubmit.OutputApi.PresubmitPromptWarning) |
2211 | 1885 |
2212 # Make sure makefiles are ignored. | 1886 # Make sure makefiles are ignored. |
2213 change1 = presubmit.Change( | 1887 change1 = presubmit.Change( |
2214 'foo1', 'foo1\n', self.fake_root_dir, None, 0, 0, None) | 1888 'foo1', 'foo1\n', self.fake_root_dir, None, 0, 0, None) |
2215 input_api1 = self.MockInputApi(change1, False) | 1889 input_api1 = self.MockInputApi(change1, False) |
2216 affected_file1 = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1890 affected_file1 = self.mox.CreateMock(presubmit.GitAffectedFile) |
2217 affected_file1.LocalPath().AndReturn('foo.cc') | 1891 affected_file1.LocalPath().AndReturn('foo.cc') |
2218 affected_file2 = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1892 affected_file2 = self.mox.CreateMock(presubmit.GitAffectedFile) |
2219 affected_file2.LocalPath().AndReturn('foo/Makefile') | 1893 affected_file2.LocalPath().AndReturn('foo/Makefile') |
2220 affected_file3 = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1894 affected_file3 = self.mox.CreateMock(presubmit.GitAffectedFile) |
2221 affected_file3.LocalPath().AndReturn('makefile') | 1895 affected_file3.LocalPath().AndReturn('makefile') |
2222 # Only this one will trigger. | 1896 # Only this one will trigger. |
2223 affected_file4 = self.mox.CreateMock(presubmit.SvnAffectedFile) | 1897 affected_file4 = self.mox.CreateMock(presubmit.GitAffectedFile) |
2224 affected_file1.LocalPath().AndReturn('foo.cc') | 1898 affected_file1.LocalPath().AndReturn('foo.cc') |
2225 affected_file1.NewContents().AndReturn(['yo, ']) | 1899 affected_file1.NewContents().AndReturn(['yo, ']) |
2226 affected_file4.LocalPath().AndReturn('makefile.foo') | 1900 affected_file4.LocalPath().AndReturn('makefile.foo') |
2227 affected_file4.LocalPath().AndReturn('makefile.foo') | 1901 affected_file4.LocalPath().AndReturn('makefile.foo') |
2228 affected_file4.NewContents().AndReturn(['ye\t']) | 1902 affected_file4.NewContents().AndReturn(['ye\t']) |
2229 affected_file4.ChangedContents().AndReturn([(46, 'ye\t')]) | 1903 affected_file4.ChangedContents().AndReturn([(46, 'ye\t')]) |
2230 affected_file4.LocalPath().AndReturn('makefile.foo') | 1904 affected_file4.LocalPath().AndReturn('makefile.foo') |
2231 affected_files = (affected_file1, affected_file2, | 1905 affected_files = (affected_file1, affected_file2, |
2232 affected_file3, affected_file4) | 1906 affected_file3, affected_file4) |
2233 | 1907 |
2234 def test(include_dirs=False, include_deletes=True, file_filter=None): | 1908 def test(include_deletes=True, file_filter=None): |
2235 self.assertFalse(include_deletes) | 1909 self.assertFalse(include_deletes) |
2236 for x in affected_files: | 1910 for x in affected_files: |
2237 if file_filter(x): | 1911 if file_filter(x): |
2238 yield x | 1912 yield x |
2239 # Override the mock of these functions. | 1913 # Override the mock of these functions. |
2240 input_api1.FilterSourceFile = lambda x: x | 1914 input_api1.FilterSourceFile = lambda x: x |
2241 input_api1.AffectedFiles = test | 1915 input_api1.AffectedFiles = test |
2242 self.mox.ReplayAll() | 1916 self.mox.ReplayAll() |
2243 | 1917 |
2244 results1 = presubmit_canned_checks.CheckChangeHasNoTabs(input_api1, | 1918 results1 = presubmit_canned_checks.CheckChangeHasNoTabs(input_api1, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2331 def testCannedCheckLongLinesLongSymbol(self): | 2005 def testCannedCheckLongLinesLongSymbol(self): |
2332 check = lambda x, y, z: presubmit_canned_checks.CheckLongLines(x, y, 10, z) | 2006 check = lambda x, y, z: presubmit_canned_checks.CheckLongLines(x, y, 10, z) |
2333 self.ContentTest( | 2007 self.ContentTest( |
2334 check, | 2008 check, |
2335 ' TUP5D_LoNG_SY ', | 2009 ' TUP5D_LoNG_SY ', |
2336 None, | 2010 None, |
2337 ' TUP5D_LoNG_SY5 ', | 2011 ' TUP5D_LoNG_SY5 ', |
2338 None, | 2012 None, |
2339 presubmit.OutputApi.PresubmitPromptWarning) | 2013 presubmit.OutputApi.PresubmitPromptWarning) |
2340 | 2014 |
2341 def testCheckChangeSvnEolStyleCommit(self): | |
2342 # Test CheckSvnProperty at the same time. | |
2343 self.SvnPropertyTest(presubmit_canned_checks.CheckChangeSvnEolStyle, | |
2344 'svn:eol-style', 'LF', '', True, | |
2345 presubmit.OutputApi.PresubmitError, True) | |
2346 | |
2347 def testCheckChangeSvnEolStyleUpload(self): | |
2348 self.SvnPropertyTest(presubmit_canned_checks.CheckChangeSvnEolStyle, | |
2349 'svn:eol-style', 'LF', '', False, | |
2350 presubmit.OutputApi.PresubmitNotifyResult, True) | |
2351 | |
2352 def _LicenseCheck(self, text, license_text, committing, expected_result, | 2015 def _LicenseCheck(self, text, license_text, committing, expected_result, |
2353 **kwargs): | 2016 **kwargs): |
2354 change = self.mox.CreateMock(presubmit.SvnChange) | 2017 change = self.mox.CreateMock(presubmit.GitChange) |
2355 change.scm = 'svn' | 2018 change.scm = 'svn' |
2356 input_api = self.MockInputApi(change, committing) | 2019 input_api = self.MockInputApi(change, committing) |
2357 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) | 2020 affected_file = self.mox.CreateMock(presubmit.GitAffectedFile) |
2358 input_api.AffectedSourceFiles(42).AndReturn([affected_file]) | 2021 input_api.AffectedSourceFiles(42).AndReturn([affected_file]) |
2359 input_api.ReadFile(affected_file, 'rb').AndReturn(text) | 2022 input_api.ReadFile(affected_file, 'rb').AndReturn(text) |
2360 if expected_result: | 2023 if expected_result: |
2361 affected_file.LocalPath().AndReturn('bleh') | 2024 affected_file.LocalPath().AndReturn('bleh') |
2362 | 2025 |
2363 self.mox.ReplayAll() | 2026 self.mox.ReplayAll() |
2364 result = presubmit_canned_checks.CheckLicense( | 2027 result = presubmit_canned_checks.CheckLicense( |
2365 input_api, presubmit.OutputApi, license_text, | 2028 input_api, presubmit.OutputApi, license_text, |
2366 source_file_filter=42, | 2029 source_file_filter=42, |
2367 **kwargs) | 2030 **kwargs) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2413 presubmit.OutputApi.PresubmitPromptWarning) | 2076 presubmit.OutputApi.PresubmitPromptWarning) |
2414 | 2077 |
2415 def testCheckLicenseEmptySuccess(self): | 2078 def testCheckLicenseEmptySuccess(self): |
2416 text = '' | 2079 text = '' |
2417 license_text = ( | 2080 license_text = ( |
2418 r".*? Copyright \(c\) 2037 Nobody." "\n" | 2081 r".*? Copyright \(c\) 2037 Nobody." "\n" |
2419 r".*? All Rights Reserved\." "\n" | 2082 r".*? All Rights Reserved\." "\n" |
2420 ) | 2083 ) |
2421 self._LicenseCheck(text, license_text, True, None, accept_empty_files=True) | 2084 self._LicenseCheck(text, license_text, True, None, accept_empty_files=True) |
2422 | 2085 |
2423 def testCheckSvnForCommonMimeTypes(self): | |
2424 self.mox.StubOutWithMock(presubmit_canned_checks, 'CheckSvnProperty') | |
2425 input_api = self.MockInputApi(None, False) | |
2426 output_api = presubmit.OutputApi(False) | |
2427 A = lambda x: presubmit.AffectedFile(x, 'M', self.fake_root_dir, None) | |
2428 files = [ | |
2429 A('a.pdf'), A('b.bmp'), A('c.gif'), A('d.png'), A('e.jpg'), A('f.jpe'), | |
2430 A('random'), A('g.jpeg'), A('h.ico'), | |
2431 ] | |
2432 input_api.AffectedFiles(include_deletes=False).AndReturn(files) | |
2433 presubmit_canned_checks.CheckSvnProperty( | |
2434 input_api, output_api, 'svn:mime-type', 'application/pdf', [files[0]] | |
2435 ).AndReturn([1]) | |
2436 presubmit_canned_checks.CheckSvnProperty( | |
2437 input_api, output_api, 'svn:mime-type', 'image/bmp', [files[1]] | |
2438 ).AndReturn([2]) | |
2439 presubmit_canned_checks.CheckSvnProperty( | |
2440 input_api, output_api, 'svn:mime-type', 'image/gif', [files[2]] | |
2441 ).AndReturn([3]) | |
2442 presubmit_canned_checks.CheckSvnProperty( | |
2443 input_api, output_api, 'svn:mime-type', 'image/png', [files[3]] | |
2444 ).AndReturn([4]) | |
2445 presubmit_canned_checks.CheckSvnProperty( | |
2446 input_api, output_api, 'svn:mime-type', 'image/jpeg', | |
2447 [files[4], files[5], files[7]] | |
2448 ).AndReturn([5]) | |
2449 presubmit_canned_checks.CheckSvnProperty( | |
2450 input_api, output_api, 'svn:mime-type', 'image/vnd.microsoft.icon', | |
2451 [files[8]]).AndReturn([6]) | |
2452 self.mox.ReplayAll() | |
2453 | |
2454 results = presubmit_canned_checks.CheckSvnForCommonMimeTypes( | |
2455 input_api, output_api) | |
2456 self.assertEquals(results, [1, 2, 3, 4, 5, 6]) | |
2457 | |
2458 def testCannedCheckTreeIsOpenOpen(self): | 2086 def testCannedCheckTreeIsOpenOpen(self): |
2459 input_api = self.MockInputApi(None, True) | 2087 input_api = self.MockInputApi(None, True) |
2460 connection = self.mox.CreateMockAnything() | 2088 connection = self.mox.CreateMockAnything() |
2461 input_api.urllib2.urlopen('url_to_open').AndReturn(connection) | 2089 input_api.urllib2.urlopen('url_to_open').AndReturn(connection) |
2462 connection.read().AndReturn('The tree is open') | 2090 connection.read().AndReturn('The tree is open') |
2463 connection.close() | 2091 connection.close() |
2464 self.mox.ReplayAll() | 2092 self.mox.ReplayAll() |
2465 results = presubmit_canned_checks.CheckTreeIsOpen( | 2093 results = presubmit_canned_checks.CheckTreeIsOpen( |
2466 input_api, presubmit.OutputApi, url='url_to_open', closed='.*closed.*') | 2094 input_api, presubmit.OutputApi, url='url_to_open', closed='.*closed.*') |
2467 self.assertEquals(results, []) | 2095 self.assertEquals(results, []) |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2660 if uncovered_files is None: | 2288 if uncovered_files is None: |
2661 uncovered_files = set() | 2289 uncovered_files = set() |
2662 if manually_specified_reviewers is None: | 2290 if manually_specified_reviewers is None: |
2663 manually_specified_reviewers = [] | 2291 manually_specified_reviewers = [] |
2664 | 2292 |
2665 change = self.mox.CreateMock(presubmit.Change) | 2293 change = self.mox.CreateMock(presubmit.Change) |
2666 change.issue = issue | 2294 change.issue = issue |
2667 change.author_email = 'john@example.com' | 2295 change.author_email = 'john@example.com' |
2668 change.R = ','.join(manually_specified_reviewers) | 2296 change.R = ','.join(manually_specified_reviewers) |
2669 change.TBR = '' | 2297 change.TBR = '' |
2670 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) | 2298 affected_file = self.mox.CreateMock(presubmit.GitAffectedFile) |
2671 input_api = self.MockInputApi(change, False) | 2299 input_api = self.MockInputApi(change, False) |
2672 if gerrit_response: | 2300 if gerrit_response: |
2673 assert not rietveld_response | 2301 assert not rietveld_response |
2674 input_api.rietveld = None | 2302 input_api.rietveld = None |
2675 input_api.gerrit = presubmit.GerritAccessor('host') | 2303 input_api.gerrit = presubmit.GerritAccessor('host') |
2676 | 2304 |
2677 fake_db = self.mox.CreateMock(owners.Database) | 2305 fake_db = self.mox.CreateMock(owners.Database) |
2678 fake_db.email_regexp = input_api.re.compile(owners.BASIC_EMAIL_REGEXP) | 2306 fake_db.email_regexp = input_api.re.compile(owners.BASIC_EMAIL_REGEXP) |
2679 input_api.owners_db = fake_db | 2307 input_api.owners_db = fake_db |
2680 input_api.is_committing = is_committing | 2308 input_api.is_committing = is_committing |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3056 self.assertEqual(1, len(results)) | 2684 self.assertEqual(1, len(results)) |
3057 self.assertEqual( | 2685 self.assertEqual( |
3058 presubmit.OutputApi.PresubmitNotifyResult, results[0].__class__) | 2686 presubmit.OutputApi.PresubmitNotifyResult, results[0].__class__) |
3059 self.checkstdout('') | 2687 self.checkstdout('') |
3060 | 2688 |
3061 def testPanProjectChecks(self): | 2689 def testPanProjectChecks(self): |
3062 # Make sure it accepts both list and tuples. | 2690 # Make sure it accepts both list and tuples. |
3063 change = presubmit.Change( | 2691 change = presubmit.Change( |
3064 'foo1', 'description1', self.fake_root_dir, None, 0, 0, None) | 2692 'foo1', 'description1', self.fake_root_dir, None, 0, 0, None) |
3065 input_api = self.MockInputApi(change, False) | 2693 input_api = self.MockInputApi(change, False) |
3066 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) | 2694 affected_file = self.mox.CreateMock(presubmit.GitAffectedFile) |
3067 for _ in range(3): | 2695 for _ in range(3): |
3068 input_api.AffectedFiles(file_filter=mox.IgnoreArg(), include_deletes=False | 2696 input_api.AffectedFiles(file_filter=mox.IgnoreArg(), include_deletes=False |
3069 ).AndReturn([affected_file]) | 2697 ).AndReturn([affected_file]) |
3070 affected_file.LocalPath() | 2698 affected_file.LocalPath() |
3071 affected_file.NewContents().AndReturn('Hey!\nHo!\nHey!\nHo!\n\n') | 2699 affected_file.NewContents().AndReturn('Hey!\nHo!\nHey!\nHo!\n\n') |
3072 affected_file.ChangedContents().AndReturn([ | 2700 affected_file.ChangedContents().AndReturn([ |
3073 (0, 'Hey!\n'), | 2701 (0, 'Hey!\n'), |
3074 (1, 'Ho!\n'), | 2702 (1, 'Ho!\n'), |
3075 (2, 'Hey!\n'), | 2703 (2, 'Hey!\n'), |
3076 (3, 'Ho!\n'), | 2704 (3, 'Ho!\n'), |
3077 (4, '\n')]) | 2705 (4, '\n')]) |
3078 for _ in range(5): | 2706 for _ in range(5): |
3079 affected_file.LocalPath().AndReturn('hello.py') | 2707 affected_file.LocalPath().AndReturn('hello.py') |
3080 input_api.AffectedSourceFiles(mox.IgnoreArg()).AndReturn([affected_file]) | 2708 input_api.AffectedSourceFiles(mox.IgnoreArg()).AndReturn([affected_file]) |
3081 input_api.ReadFile(affected_file).AndReturn('Hey!\nHo!\nHey!\nHo!\n\n') | 2709 input_api.ReadFile(affected_file).AndReturn('Hey!\nHo!\nHey!\nHo!\n\n') |
3082 | |
3083 input_api.AffectedSourceFiles(mox.IgnoreArg()).AndReturn([affected_file]) | |
3084 | |
3085 input_api.AffectedSourceFiles(mox.IgnoreArg()).AndReturn([affected_file]) | 2710 input_api.AffectedSourceFiles(mox.IgnoreArg()).AndReturn([affected_file]) |
3086 input_api.ReadFile(affected_file, 'rb').AndReturn( | 2711 input_api.ReadFile(affected_file, 'rb').AndReturn( |
3087 'Hey!\nHo!\nHey!\nHo!\n\n') | 2712 'Hey!\nHo!\nHey!\nHo!\n\n') |
3088 affected_file.LocalPath() | 2713 affected_file.LocalPath() |
3089 | 2714 |
3090 self.mox.ReplayAll() | 2715 self.mox.ReplayAll() |
3091 results = presubmit_canned_checks.PanProjectChecks( | 2716 results = presubmit_canned_checks.PanProjectChecks( |
3092 input_api, | 2717 input_api, |
3093 presubmit.OutputApi, | 2718 presubmit.OutputApi, |
3094 excluded_paths=None, | 2719 excluded_paths=None, |
3095 text_files=None, | 2720 text_files=None, |
3096 license_header=None, | 2721 license_header=None, |
3097 project_name=None, | 2722 project_name=None, |
3098 owners_check=False) | 2723 owners_check=False) |
3099 self.assertEqual(2, len(results)) | 2724 self.assertEqual(2, len(results)) |
3100 self.assertEqual( | 2725 self.assertEqual( |
3101 'Found line ending with white spaces in:', results[0]._message) | 2726 'Found line ending with white spaces in:', results[0]._message) |
3102 self.checkstdout('') | 2727 self.checkstdout('') |
3103 | 2728 |
3104 | 2729 |
3105 if __name__ == '__main__': | 2730 if __name__ == '__main__': |
3106 import unittest | 2731 import unittest |
3107 unittest.main() | 2732 unittest.main() |
OLD | NEW |