Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tests/presubmit_unittest.py

Issue 113964: Make AffectedFile member variables private. (Closed)
Patch Set: 80cols Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « presubmit_support.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Unit tests for presubmit_support.py and presubmit_canned_checks.py.""" 6 """Unit tests for presubmit_support.py and presubmit_canned_checks.py."""
7 7
8 import os 8 import os
9 import StringIO 9 import StringIO
10 import sys 10 import sys
11 import unittest 11 import unittest
12 import warnings 12 import warnings
13 13
14 # Local imports 14 # Local imports
15 import __init__
15 import gcl 16 import gcl
16 import gclient 17 import gclient
17 import presubmit_support as presubmit 18 import presubmit_support as presubmit
18 import presubmit_canned_checks 19 import presubmit_canned_checks
20 mox = __init__.mox
19 21
20 22
21 class PresubmitTestsBase(unittest.TestCase): 23 class PresubmitTestsBase(unittest.TestCase):
22 """Setups and tear downs the mocks but doesn't test anything as-is.""" 24 """Setups and tear downs the mocks but doesn't test anything as-is."""
23 def setUp(self): 25 def setUp(self):
24 self._warnings_stack = warnings.catch_warnings() 26 self._warnings_stack = warnings.catch_warnings()
27 self.mox = mox.Mox()
25 warnings.simplefilter("ignore", DeprecationWarning) 28 warnings.simplefilter("ignore", DeprecationWarning)
26 self.original_IsFile = os.path.isfile 29 self.original_IsFile = os.path.isfile
27 def MockIsFile(f): 30 def MockIsFile(f):
28 dir = os.path.dirname(f) 31 dir = os.path.dirname(f)
29 return dir.endswith('haspresubmit') or dir == '' 32 return dir.endswith('haspresubmit') or dir == ''
30 os.path.isfile = MockIsFile 33 os.path.isfile = MockIsFile
31 34
32 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo 35 self.original_CaptureSVNInfo = gclient.CaptureSVNInfo
33 def MockCaptureSVNInfo(path): 36 def MockCaptureSVNInfo(path):
34 if path.count('notfound'): 37 if path.count('notfound'):
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 else: 83 else:
81 return 'one:%s\r\ntwo:%s' % (path, path) 84 return 'one:%s\r\ntwo:%s' % (path, path)
82 gcl.ReadFile = MockReadFile 85 gcl.ReadFile = MockReadFile
83 86
84 self.original_GetRepositoryRoot = gcl.GetRepositoryRoot 87 self.original_GetRepositoryRoot = gcl.GetRepositoryRoot
85 def MockGetRepositoryRoot(): 88 def MockGetRepositoryRoot():
86 return '' 89 return ''
87 gcl.GetRepositoryRoot = MockGetRepositoryRoot 90 gcl.GetRepositoryRoot = MockGetRepositoryRoot
88 self._sys_stdout = sys.stdout 91 self._sys_stdout = sys.stdout
89 sys.stdout = StringIO.StringIO() 92 sys.stdout = StringIO.StringIO()
93 self._os_path_exists = os.path.exists
94 os.path.exists = self.mox.CreateMockAnything()
95 self._os_path_isdir = os.path.isdir
96 os.path.isdir = self.mox.CreateMockAnything()
90 97
91 def tearDown(self): 98 def tearDown(self):
92 os.path.isfile = self.original_IsFile 99 os.path.isfile = self.original_IsFile
93 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo 100 gclient.CaptureSVNInfo = self.original_CaptureSVNInfo
94 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty 101 gcl.GetSVNFileProperty = self.original_GetSVNFileProperty
95 gcl.ReadFile = self.original_ReadFile 102 gcl.ReadFile = self.original_ReadFile
96 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot 103 gcl.GetRepositoryRoot = self.original_GetRepositoryRoot
97 sys.stdout = self._sys_stdout 104 sys.stdout = self._sys_stdout
105 os.path.exists = self._os_path_exists
106 os.path.isdir = self._os_path_isdir
98 self._warnings_stack = None 107 self._warnings_stack = None
99 108
100 @staticmethod 109 @staticmethod
101 def MakeBasicChange(name, description): 110 def MakeBasicChange(name, description):
102 ci = gcl.ChangeInfo(name=name, 111 ci = gcl.ChangeInfo(name=name,
103 description=description, 112 description=description,
104 files=[]) 113 files=[])
105 change = presubmit.GclChange(ci) 114 change = presubmit.GclChange(ci)
106 return change 115 return change
107 116
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 'BUG=123', 162 'BUG=123',
154 ' STORY =http://foo/ \t', 163 ' STORY =http://foo/ \t',
155 'and some more regular text \t') 164 'and some more regular text \t')
156 files = [ 165 files = [
157 ['A', 'foo/blat.cc'], 166 ['A', 'foo/blat.cc'],
158 ['M', 'binary.dll'], # a binary file 167 ['M', 'binary.dll'], # a binary file
159 ['A', 'isdir'], # a directory 168 ['A', 'isdir'], # a directory
160 ['M', 'flop/notfound.txt'], # not found in SVN, still exists locally 169 ['M', 'flop/notfound.txt'], # not found in SVN, still exists locally
161 ['D', 'boo/flap.h'], 170 ['D', 'boo/flap.h'],
162 ] 171 ]
163 172 os.path.exists(os.path.join('foo', 'blat.cc')).AndReturn(True)
173 os.path.isdir(os.path.join('foo', 'blat.cc')).AndReturn(False)
174 os.path.exists('binary.dll').AndReturn(True)
175 os.path.isdir('binary.dll').AndReturn(False)
176 os.path.exists('isdir').AndReturn(True)
177 os.path.isdir('isdir').AndReturn(True)
178 os.path.exists(os.path.join('flop', 'notfound.txt')).AndReturn(False)
179 os.path.exists(os.path.join('boo', 'flap.h')).AndReturn(False)
180 self.mox.ReplayAll()
164 ci = gcl.ChangeInfo(name='mychange', 181 ci = gcl.ChangeInfo(name='mychange',
165 description='\n'.join(description_lines), 182 description='\n'.join(description_lines),
166 files=files) 183 files=files)
167 change = presubmit.GclChange(ci) 184 change = presubmit.GclChange(ci)
168 185
169 self.failUnless(change.Change() == 'mychange') 186 self.failUnless(change.Change() == 'mychange')
170 self.failUnless(change.DescriptionText() == 187 self.failUnless(change.DescriptionText() ==
171 'Hello there\nthis is a change\nand some more regular text') 188 'Hello there\nthis is a change\nand some more regular text')
172 self.failUnless(change.FullDescriptionText() == 189 self.failUnless(change.FullDescriptionText() ==
173 '\n'.join(description_lines)) 190 '\n'.join(description_lines))
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 self.failUnless(rhs_lines[1][1] == 2) 228 self.failUnless(rhs_lines[1][1] == 2)
212 self.failUnless(rhs_lines[1][2] == 'two:%s' % files[0][1]) 229 self.failUnless(rhs_lines[1][2] == 'two:%s' % files[0][1])
213 230
214 self.failUnless(rhs_lines[2][0].LocalPath() == files[3][1]) 231 self.failUnless(rhs_lines[2][0].LocalPath() == files[3][1])
215 self.failUnless(rhs_lines[2][1] == 1) 232 self.failUnless(rhs_lines[2][1] == 1)
216 self.failUnless(rhs_lines[2][2] == 'one:%s' % files[3][1]) 233 self.failUnless(rhs_lines[2][2] == 'one:%s' % files[3][1])
217 234
218 self.failUnless(rhs_lines[3][0].LocalPath() == files[3][1]) 235 self.failUnless(rhs_lines[3][0].LocalPath() == files[3][1])
219 self.failUnless(rhs_lines[3][1] == 2) 236 self.failUnless(rhs_lines[3][1] == 2)
220 self.failUnless(rhs_lines[3][2] == 'two:%s' % files[3][1]) 237 self.failUnless(rhs_lines[3][2] == 'two:%s' % files[3][1])
238 self.mox.VerifyAll()
221 239
222 def testExecPresubmitScript(self): 240 def testExecPresubmitScript(self):
223 description_lines = ('Hello there', 241 description_lines = ('Hello there',
224 'this is a change', 242 'this is a change',
225 'STORY=http://tracker/123') 243 'STORY=http://tracker/123')
226 files = [ 244 files = [
227 ['A', 'foo\\blat.cc'], 245 ['A', 'foo\\blat.cc'],
228 ] 246 ]
229 ci = gcl.ChangeInfo(name='mychange', 247 ci = gcl.ChangeInfo(name='mychange',
230 description='\n'.join(description_lines), 248 description='\n'.join(description_lines),
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 os.path.isfile = MockIsFile 398 os.path.isfile = MockIsFile
381 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, 399 self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input,
382 DEFAULT_SCRIPT)) 400 DEFAULT_SCRIPT))
383 self.assertEquals(output.getvalue().count('!!'), 1) 401 self.assertEquals(output.getvalue().count('!!'), 1)
384 402
385 def testDirectoryHandling(self): 403 def testDirectoryHandling(self):
386 files = [ 404 files = [
387 ['A', 'isdir'], 405 ['A', 'isdir'],
388 ['A', 'isdir\\blat.cc'], 406 ['A', 'isdir\\blat.cc'],
389 ] 407 ]
408 os.path.exists('isdir').AndReturn(True)
409 os.path.isdir('isdir').AndReturn(True)
410 os.path.exists(os.path.join('isdir', 'blat.cc')).AndReturn(True)
411 os.path.isdir(os.path.join('isdir', 'blat.cc')).AndReturn(False)
412 self.mox.ReplayAll()
390 ci = gcl.ChangeInfo(name='mychange', 413 ci = gcl.ChangeInfo(name='mychange',
391 description='foo', 414 description='foo',
392 files=files) 415 files=files)
393 change = presubmit.GclChange(ci) 416 change = presubmit.GclChange(ci)
394 417
395 affected_files = change.AffectedFiles(include_dirs=False) 418 affected_files = change.AffectedFiles(include_dirs=False)
396 self.failUnless(len(affected_files) == 1) 419 self.failUnless(len(affected_files) == 1)
397 self.failUnless(affected_files[0].LocalPath().endswith('blat.cc')) 420 self.failUnless(affected_files[0].LocalPath().endswith('blat.cc'))
398 421 self.mox.VerifyAll()
399 affected_files_and_dirs = change.AffectedFiles(include_dirs=True) 422 affected_files_and_dirs = change.AffectedFiles(include_dirs=True)
400 self.failUnless(len(affected_files_and_dirs) == 2) 423 self.failUnless(len(affected_files_and_dirs) == 2)
401 424
402 def testTags(self): 425 def testTags(self):
403 DEFAULT_SCRIPT = """ 426 DEFAULT_SCRIPT = """
404 def CheckChangeOnUpload(input_api, output_api): 427 def CheckChangeOnUpload(input_api, output_api):
405 if input_api.change.tags['BUG'] != 'boo': 428 if input_api.change.tags['BUG'] != 'boo':
406 return [output_api.PresubmitError('Tag parsing failed. 1')] 429 return [output_api.PresubmitError('Tag parsing failed. 1')]
407 if input_api.change.tags['STORY'] != 'http://tracker.com/42': 430 if input_api.change.tags['STORY'] != 'http://tracker.com/42':
408 return [output_api.PresubmitError('Tag parsing failed. 2')] 431 return [output_api.PresubmitError('Tag parsing failed. 2')]
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 ' STORY =http://foo/ \t', 526 ' STORY =http://foo/ \t',
504 'and some more regular text') 527 'and some more regular text')
505 files = [ 528 files = [
506 ['A', os.path.join('foo', 'blat.cc')], 529 ['A', os.path.join('foo', 'blat.cc')],
507 ['M', os.path.join('foo', 'blat', 'binary.dll')], 530 ['M', os.path.join('foo', 'blat', 'binary.dll')],
508 ['D', 'foo/mat/beingdeleted.txt'], 531 ['D', 'foo/mat/beingdeleted.txt'],
509 ['M', 'flop/notfound.txt'], 532 ['M', 'flop/notfound.txt'],
510 ['A', 'boo/flap.h'], 533 ['A', 'boo/flap.h'],
511 ] 534 ]
512 535
536 os.path.exists(os.path.join('foo', 'blat.cc')).AndReturn(True)
537 os.path.isdir(os.path.join('foo', 'blat.cc')).AndReturn(False)
538 os.path.exists(os.path.join('foo', 'blat', 'binary.dll')).AndReturn(True)
539 os.path.isdir(os.path.join('foo', 'blat', 'binary.dll')).AndReturn(False)
540 os.path.exists(os.path.join('foo', 'mat', 'beingdeleted.txt')).AndReturn(
541 False)
542 os.path.exists(os.path.join('flop', 'notfound.txt')).AndReturn(False)
543 os.path.exists(os.path.join('boo', 'flap.h')).AndReturn(True)
544 os.path.isdir(os.path.join('boo', 'flap.h')).AndReturn(False)
545 self.mox.ReplayAll()
513 ci = gcl.ChangeInfo(name='mychange', 546 ci = gcl.ChangeInfo(name='mychange',
514 description='\n'.join(description_lines), 547 description='\n'.join(description_lines),
515 files=files) 548 files=files)
516 change = presubmit.GclChange(ci) 549 change = presubmit.GclChange(ci)
517 550
518 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py') 551 api = presubmit.InputApi(change, 'foo/PRESUBMIT.py')
519 552
520 affected_files = api.AffectedFiles() 553 affected_files = api.AffectedFiles()
521 self.assertEquals(len(affected_files), 3) 554 self.assertEquals(len(affected_files), 3)
522 self.assertEquals(affected_files[0].LocalPath(), 555 self.assertEquals(affected_files[0].LocalPath(),
523 presubmit.normpath('foo/blat.cc')) 556 presubmit.normpath('foo/blat.cc'))
524 self.assertEquals(affected_files[1].LocalPath(), 557 self.assertEquals(affected_files[1].LocalPath(),
525 presubmit.normpath('foo/blat/binary.dll')) 558 presubmit.normpath('foo/blat/binary.dll'))
526 self.assertEquals(affected_files[2].LocalPath(), 559 self.assertEquals(affected_files[2].LocalPath(),
527 presubmit.normpath('foo/mat/beingdeleted.txt')) 560 presubmit.normpath('foo/mat/beingdeleted.txt'))
528 561
529 rhs_lines = [] 562 rhs_lines = []
530 for line in api.RightHandSideLines(): 563 for line in api.RightHandSideLines():
531 rhs_lines.append(line) 564 rhs_lines.append(line)
532 self.failUnless(len(rhs_lines) == 2) 565 self.failUnless(len(rhs_lines) == 2)
533 self.assertEqual(rhs_lines[0][0].LocalPath(), 566 self.assertEqual(rhs_lines[0][0].LocalPath(),
534 presubmit.normpath('foo/blat.cc')) 567 presubmit.normpath('foo/blat.cc'))
568 self.mox.VerifyAll()
535 569
536 def testGetAbsoluteLocalPath(self): 570 def testGetAbsoluteLocalPath(self):
537 # Regression test for bug of presubmit stuff that relies on invoking 571 # Regression test for bug of presubmit stuff that relies on invoking
538 # SVN (e.g. to get mime type of file) not working unless gcl invoked 572 # SVN (e.g. to get mime type of file) not working unless gcl invoked
539 # from the client root (e.g. if you were at 'src' and did 'cd base' before 573 # from the client root (e.g. if you were at 'src' and did 'cd base' before
540 # invoking 'gcl upload' it would fail because svn wouldn't find the files 574 # invoking 'gcl upload' it would fail because svn wouldn't find the files
541 # the presubmit script was asking about). 575 # the presubmit script was asking about).
542 files = [ 576 files = [
543 ['A', 'isdir'], 577 ['A', 'isdir'],
544 ['A', os.path.join('isdir', 'blat.cc')] 578 ['A', os.path.join('isdir', 'blat.cc')]
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 output = StringIO.StringIO() 656 output = StringIO.StringIO()
623 input = StringIO.StringIO('\n') 657 input = StringIO.StringIO('\n')
624 warning = presubmit.OutputApi.PresubmitPromptWarning('???') 658 warning = presubmit.OutputApi.PresubmitPromptWarning('???')
625 self.failIf(warning._Handle(output, input)) 659 self.failIf(warning._Handle(output, input))
626 self.failUnless(output.getvalue().count('???')) 660 self.failUnless(output.getvalue().count('???'))
627 661
628 662
629 class AffectedFileUnittest(PresubmitTestsBase): 663 class AffectedFileUnittest(PresubmitTestsBase):
630 def testMembersChanged(self): 664 def testMembersChanged(self):
631 members = [ 665 members = [
632 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', 666 'AbsoluteLocalPath', 'Action', 'IsDirectory', 'IsTextFile', 'LocalPath',
633 'LocalPath', 'NewContents', 667 'NewContents', 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath',
634 'OldContents', 'OldFileTempPath', 'Property', 'ServerPath', 'action',
635 'is_directory', 'path', 'properties', 'repository_root', 'server_path',
636 ] 668 ]
637 # If this test fails, you should add the relevant test. 669 # If this test fails, you should add the relevant test.
638 self.compareMembers(presubmit.AffectedFile('a', 'b'), members) 670 self.compareMembers(presubmit.AffectedFile('a', 'b'), members)
639 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members) 671 self.compareMembers(presubmit.SvnAffectedFile('a', 'b'), members)
640 672
641 def testAffectedFile(self): 673 def testAffectedFile(self):
642 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M') 674 af = presubmit.SvnAffectedFile('foo/blat.cc', 'M')
675 os.path.exists(os.path.join('foo', 'blat.cc')).AndReturn(False)
676 self.mox.ReplayAll()
643 self.failUnless(af.ServerPath() == 'svn:/foo/foo/blat.cc') 677 self.failUnless(af.ServerPath() == 'svn:/foo/foo/blat.cc')
644 self.failUnless(af.LocalPath() == presubmit.normpath('foo/blat.cc')) 678 self.failUnless(af.LocalPath() == presubmit.normpath('foo/blat.cc'))
645 self.failUnless(af.Action() == 'M') 679 self.failUnless(af.Action() == 'M')
646 self.failUnless(af.NewContents() == ['one:%s' % af.LocalPath(), 680 self.failUnless(af.NewContents() == ['one:%s' % af.LocalPath(),
647 'two:%s' % af.LocalPath()]) 681 'two:%s' % af.LocalPath()])
682 self.mox.VerifyAll()
648 683
649 af = presubmit.AffectedFile('notfound.cc', 'A') 684 af = presubmit.AffectedFile('notfound.cc', 'A')
650 self.failUnless(af.ServerPath() == '') 685 self.failUnless(af.ServerPath() == '')
651 686
652 def testProperty(self): 687 def testProperty(self):
653 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A') 688 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A')
654 self.failUnless(affected_file.Property('svn:secret-property') == 689 self.failUnless(affected_file.Property('svn:secret-property') ==
655 'secret-property-value') 690 'secret-property-value')
656 691
692 def testIsDirectoryNotExists(self):
693 # Verify cache coherency
694 os.path.exists('foo.cc').AndReturn(False)
695 self.mox.ReplayAll()
696 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A')
697 self.failIf(affected_file.IsDirectory())
698 self.failIf(affected_file.IsDirectory())
Jói Sigurðsson 2009/05/28 21:30:51 duplicate?
M-A Ruel 2009/05/29 00:59:55 Yes, that's to verify the cache coherency. I've mo
699 self.mox.VerifyAll()
700
701 def testIsDirectory(self):
702 # Verify cache coherency
703 os.path.exists('foo.cc').AndReturn(True)
704 os.path.isdir('foo.cc').AndReturn(True)
705 self.mox.ReplayAll()
706 affected_file = presubmit.SvnAffectedFile('foo.cc', 'A')
707 self.failUnless(affected_file.IsDirectory())
708 self.failUnless(affected_file.IsDirectory())
Jói Sigurðsson 2009/05/28 21:30:51 duplicate?
709 self.mox.VerifyAll()
710
657 711
658 class CannedChecksUnittest(PresubmitTestsBase): 712 class CannedChecksUnittest(PresubmitTestsBase):
659 """Tests presubmit_canned_checks.py.""" 713 """Tests presubmit_canned_checks.py."""
660 class MockInputApi(object): 714 class MockInputApi(object):
661 class MockUrllib2(object): 715 class MockUrllib2(object):
662 class urlopen(object): 716 class urlopen(object):
663 def __init__(self, url): 717 def __init__(self, url):
664 if url == 'url_to_open': 718 if url == 'url_to_open':
665 self.result = '1' 719 self.result = '1'
666 else: 720 else:
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 # TODO(maruel): Add real tests. 844 # TODO(maruel): Add real tests.
791 self.failIf(presubmit_canned_checks.RunPythonUnitTests( 845 self.failIf(presubmit_canned_checks.RunPythonUnitTests(
792 self.MockInputApi(), 846 self.MockInputApi(),
793 presubmit.OutputApi, [])) 847 presubmit.OutputApi, []))
794 self.failUnless(presubmit_canned_checks.RunPythonUnitTests( 848 self.failUnless(presubmit_canned_checks.RunPythonUnitTests(
795 self.MockInputApi(), 849 self.MockInputApi(),
796 presubmit.OutputApi, ['non_existent_module'])) 850 presubmit.OutputApi, ['non_existent_module']))
797 851
798 if __name__ == '__main__': 852 if __name__ == '__main__':
799 unittest.main() 853 unittest.main()
OLDNEW
« no previous file with comments | « presubmit_support.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698