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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 'NonexistantCannedCheckFilter', 'OutputApi', 'ParseFiles', | 177 'NonexistantCannedCheckFilter', 'OutputApi', 'ParseFiles', |
178 'PresubmitFailure', 'PresubmitExecuter', 'PresubmitOutput', 'ScanSubDirs', | 178 'PresubmitFailure', 'PresubmitExecuter', 'PresubmitOutput', 'ScanSubDirs', |
179 'SvnAffectedFile', 'SvnChange', 'auth', 'cPickle', 'cpplint', 'cStringIO', | 179 'SvnAffectedFile', 'SvnChange', 'auth', 'cPickle', 'cpplint', 'cStringIO', |
180 'contextlib', 'canned_check_filter', 'fix_encoding', 'fnmatch', | 180 'contextlib', 'canned_check_filter', 'fix_encoding', 'fnmatch', |
181 'gclient_utils', 'glob', 'inspect', 'json', 'load_files', 'logging', | 181 'gclient_utils', 'glob', 'inspect', 'json', 'load_files', 'logging', |
182 'marshal', 'normpath', 'optparse', 'os', 'owners', 'pickle', | 182 'marshal', 'normpath', 'optparse', 'os', 'owners', 'pickle', |
183 'presubmit_canned_checks', 'random', 're', 'rietveld', 'scm', | 183 'presubmit_canned_checks', 'random', 're', 'rietveld', 'scm', |
184 'subprocess', 'sys', 'tempfile', 'time', 'traceback', 'types', 'unittest', | 184 'subprocess', 'sys', 'tempfile', 'time', 'traceback', 'types', 'unittest', |
185 'urllib2', 'warn', 'multiprocessing', 'DoGetTryMasters', | 185 'urllib2', 'warn', 'multiprocessing', 'DoGetTryMasters', |
186 'GetTryMastersExecuter', 'itertools', 'urlparse', 'gerrit_util', | 186 'GetTryMastersExecuter', 'itertools', 'urlparse', 'gerrit_util', |
187 '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. |
190 self.compareMembers(presubmit, members) | 189 self.compareMembers(presubmit, members) |
191 | 190 |
192 def testCannedCheckFilter(self): | 191 def testCannedCheckFilter(self): |
193 canned = presubmit.presubmit_canned_checks | 192 canned = presubmit.presubmit_canned_checks |
194 orig = canned.CheckOwners | 193 orig = canned.CheckOwners |
195 with presubmit.canned_check_filter(['CheckOwners']): | 194 with presubmit.canned_check_filter(['CheckOwners']): |
196 self.assertNotEqual(canned.CheckOwners, orig) | 195 self.assertNotEqual(canned.CheckOwners, orig) |
197 self.assertEqual(canned.CheckOwners(None, None), []) | 196 self.assertEqual(canned.CheckOwners(None, None), []) |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 # Always fail. | 821 # Always fail. |
823 change = presubmit.Change( | 822 change = presubmit.Change( |
824 'mychange', | 823 'mychange', |
825 '\n'.join(description_lines), | 824 '\n'.join(description_lines), |
826 self.fake_root_dir, | 825 self.fake_root_dir, |
827 files, | 826 files, |
828 0, | 827 0, |
829 0, | 828 0, |
830 None) | 829 None) |
831 output = presubmit.DoPresubmitChecks( | 830 output = presubmit.DoPresubmitChecks( |
832 change, False, True, None, input_buf, DEFAULT_SCRIPT, False, None, None, | 831 change, False, True, None, input_buf, DEFAULT_SCRIPT, False, None) |
833 None) | |
834 self.failIf(output.should_continue()) | 832 self.failIf(output.should_continue()) |
835 text = ( | 833 text = ( |
836 'Running presubmit upload checks ...\n' | 834 'Running presubmit upload checks ...\n' |
837 'Warning, no PRESUBMIT.py found.\n' | 835 'Warning, no PRESUBMIT.py found.\n' |
838 'Running default presubmit script.\n' | 836 'Running default presubmit script.\n' |
839 '\n' | 837 '\n' |
840 '** Presubmit ERRORS **\n!!\n\n' | 838 '** Presubmit ERRORS **\n!!\n\n' |
841 'Was the presubmit check useful? If not, run "git cl presubmit -v"\n' | 839 'Was the presubmit check useful? If not, run "git cl presubmit -v"\n' |
842 'to figure out which PRESUBMIT.py was run, then run git blame\n' | 840 'to figure out which PRESUBMIT.py was run, then run git blame\n' |
843 'on the file to figure out who to ask for help.\n') | 841 'on the file to figure out who to ask for help.\n') |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 input_buf = StringIO.StringIO('y\n') | 903 input_buf = StringIO.StringIO('y\n') |
906 change = presubmit.Change( | 904 change = presubmit.Change( |
907 'foo', | 905 'foo', |
908 'Blah Blah\n\nSTORY=http://tracker.com/42\nBUG=boo\n', | 906 'Blah Blah\n\nSTORY=http://tracker.com/42\nBUG=boo\n', |
909 self.fake_root_dir, | 907 self.fake_root_dir, |
910 None, | 908 None, |
911 0, | 909 0, |
912 0, | 910 0, |
913 None) | 911 None) |
914 self.failUnless(presubmit.DoPresubmitChecks( | 912 self.failUnless(presubmit.DoPresubmitChecks( |
915 change, False, True, output, input_buf, DEFAULT_SCRIPT, False, None, | 913 change, False, True, output, input_buf, DEFAULT_SCRIPT, False, None)) |
916 None)) | |
917 self.assertEquals(output.getvalue(), | 914 self.assertEquals(output.getvalue(), |
918 ('Running presubmit upload checks ...\n' | 915 ('Running presubmit upload checks ...\n' |
919 'Warning, no PRESUBMIT.py found.\n' | 916 'Warning, no PRESUBMIT.py found.\n' |
920 'Running default presubmit script.\n' | 917 'Running default presubmit script.\n' |
921 '\n' | 918 '\n' |
922 '** Presubmit Messages **\n' | 919 '** Presubmit Messages **\n' |
923 'http://tracker.com/42\n' | 920 'http://tracker.com/42\n' |
924 '\n' | 921 '\n' |
925 'Presubmit checks passed.\n')) | 922 'Presubmit checks passed.\n')) |
926 | 923 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 self.mox.StubOutWithMock(presubmit, 'ParseFiles') | 1146 self.mox.StubOutWithMock(presubmit, 'ParseFiles') |
1150 presubmit.scm.determine_scm(self.fake_root_dir).AndReturn(None) | 1147 presubmit.scm.determine_scm(self.fake_root_dir).AndReturn(None) |
1151 presubmit.ParseFiles(['random_file.txt'], None | 1148 presubmit.ParseFiles(['random_file.txt'], None |
1152 ).AndReturn([('M', 'random_file.txt')]) | 1149 ).AndReturn([('M', 'random_file.txt')]) |
1153 output = self.mox.CreateMock(presubmit.PresubmitOutput) | 1150 output = self.mox.CreateMock(presubmit.PresubmitOutput) |
1154 output.should_continue().AndReturn(False) | 1151 output.should_continue().AndReturn(False) |
1155 | 1152 |
1156 presubmit.DoPresubmitChecks(mox.IgnoreArg(), False, False, | 1153 presubmit.DoPresubmitChecks(mox.IgnoreArg(), False, False, |
1157 mox.IgnoreArg(), | 1154 mox.IgnoreArg(), |
1158 mox.IgnoreArg(), | 1155 mox.IgnoreArg(), |
1159 None, False, None, None, None).AndReturn(output) | 1156 None, False, None, None).AndReturn(output) |
1160 self.mox.ReplayAll() | 1157 self.mox.ReplayAll() |
1161 | 1158 |
1162 self.assertEquals( | 1159 self.assertEquals( |
1163 True, | 1160 True, |
1164 presubmit.main(['--root', self.fake_root_dir, 'random_file.txt'])) | 1161 presubmit.main(['--root', self.fake_root_dir, 'random_file.txt'])) |
1165 | 1162 |
1166 def testMainUnversionedFail(self): | 1163 def testMainUnversionedFail(self): |
1167 # OptParser calls presubmit.os.path.exists and is a pain when mocked. | 1164 # OptParser calls presubmit.os.path.exists and is a pain when mocked. |
1168 self.UnMock(presubmit.os.path, 'exists') | 1165 self.UnMock(presubmit.os.path, 'exists') |
1169 self.mox.StubOutWithMock(presubmit, 'DoPresubmitChecks') | 1166 self.mox.StubOutWithMock(presubmit, 'DoPresubmitChecks') |
(...skipping 23 matching lines...) Expand all Loading... |
1193 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedSourceFiles', | 1190 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedSourceFiles', |
1194 'AffectedTextFiles', 'DEFAULT_BLACK_LIST', 'DEFAULT_WHITE_LIST', | 1191 'AffectedTextFiles', 'DEFAULT_BLACK_LIST', 'DEFAULT_WHITE_LIST', |
1195 'DepotToLocalPath', 'FilterSourceFile', 'LocalPaths', 'LocalToDepotPath', | 1192 'DepotToLocalPath', 'FilterSourceFile', 'LocalPaths', 'LocalToDepotPath', |
1196 'Command', 'RunTests', 'PresubmitLocalPath', 'ReadFile', | 1193 'Command', 'RunTests', 'PresubmitLocalPath', 'ReadFile', |
1197 'RightHandSideLines', 'ServerPaths', 'basename', 'cPickle', 'cpplint', | 1194 'RightHandSideLines', 'ServerPaths', 'basename', 'cPickle', 'cpplint', |
1198 'cStringIO', 'canned_checks', 'change', 'cpu_count', 'environ', 'glob', | 1195 'cStringIO', 'canned_checks', 'change', 'cpu_count', 'environ', 'glob', |
1199 'host_url', 'is_committing', 'json', 'logging', 'marshal', 'os_listdir', | 1196 'host_url', 'is_committing', 'json', 'logging', 'marshal', 'os_listdir', |
1200 'os_walk', 'os_path', 'os_stat', 'owners_db', 'pickle', 'platform', | 1197 'os_walk', 'os_path', 'os_stat', 'owners_db', 'pickle', 'platform', |
1201 'python_executable', 're', 'rietveld', 'subprocess', 'tbr', 'tempfile', | 1198 'python_executable', 're', 'rietveld', 'subprocess', 'tbr', 'tempfile', |
1202 'time', 'traceback', 'unittest', 'urllib2', 'version', 'verbose', | 1199 'time', 'traceback', 'unittest', 'urllib2', 'version', 'verbose', |
1203 'dry_run', 'gerrit', | 1200 'dry_run', |
1204 ] | 1201 ] |
1205 # If this test fails, you should add the relevant test. | 1202 # If this test fails, you should add the relevant test. |
1206 self.compareMembers( | 1203 self.compareMembers( |
1207 presubmit.InputApi(self.fake_change, './.', False, None, False), | 1204 presubmit.InputApi(self.fake_change, './.', False, None, False), |
1208 members) | 1205 members) |
1209 | 1206 |
1210 def testDepotToLocalPath(self): | 1207 def testDepotToLocalPath(self): |
1211 presubmit.scm.SVN._CaptureInfo(['svn://foo/smurf'], self.fake_root_dir | 1208 presubmit.scm.SVN._CaptureInfo(['svn://foo/smurf'], self.fake_root_dir |
1212 ).AndReturn({'Path': 'prout'}) | 1209 ).AndReturn({'Path': 'prout'}) |
1213 presubmit.scm.SVN._CaptureInfo( | 1210 presubmit.scm.SVN._CaptureInfo( |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1835 # pylint: disable=R0201 | 1832 # pylint: disable=R0201 |
1836 input_api = self.mox.CreateMock(presubmit.InputApi) | 1833 input_api = self.mox.CreateMock(presubmit.InputApi) |
1837 input_api.cStringIO = presubmit.cStringIO | 1834 input_api.cStringIO = presubmit.cStringIO |
1838 input_api.json = presubmit.json | 1835 input_api.json = presubmit.json |
1839 input_api.logging = logging | 1836 input_api.logging = logging |
1840 input_api.os_listdir = self.mox.CreateMockAnything() | 1837 input_api.os_listdir = self.mox.CreateMockAnything() |
1841 input_api.os_walk = self.mox.CreateMockAnything() | 1838 input_api.os_walk = self.mox.CreateMockAnything() |
1842 input_api.os_path = presubmit.os.path | 1839 input_api.os_path = presubmit.os.path |
1843 input_api.re = presubmit.re | 1840 input_api.re = presubmit.re |
1844 input_api.rietveld = self.mox.CreateMock(rietveld.Rietveld) | 1841 input_api.rietveld = self.mox.CreateMock(rietveld.Rietveld) |
1845 input_api.gerrit = None | |
1846 input_api.traceback = presubmit.traceback | 1842 input_api.traceback = presubmit.traceback |
1847 input_api.urllib2 = self.mox.CreateMock(presubmit.urllib2) | 1843 input_api.urllib2 = self.mox.CreateMock(presubmit.urllib2) |
1848 input_api.unittest = unittest | 1844 input_api.unittest = unittest |
1849 input_api.subprocess = self.mox.CreateMock(subprocess) | 1845 input_api.subprocess = self.mox.CreateMock(subprocess) |
1850 presubmit.subprocess = input_api.subprocess | 1846 presubmit.subprocess = input_api.subprocess |
1851 class fake_CalledProcessError(Exception): | 1847 class fake_CalledProcessError(Exception): |
1852 def __str__(self): | 1848 def __str__(self): |
1853 return 'foo' | 1849 return 'foo' |
1854 input_api.subprocess.CalledProcessError = fake_CalledProcessError | 1850 input_api.subprocess.CalledProcessError = fake_CalledProcessError |
1855 input_api.verbose = False | 1851 input_api.verbose = False |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2558 connection.close() | 2554 connection.close() |
2559 self.mox.ReplayAll() | 2555 self.mox.ReplayAll() |
2560 | 2556 |
2561 results = presubmit_canned_checks.CheckBuildbotPendingBuilds( | 2557 results = presubmit_canned_checks.CheckBuildbotPendingBuilds( |
2562 input_api, presubmit.OutputApi, 'uurl', 2, ('foo')) | 2558 input_api, presubmit.OutputApi, 'uurl', 2, ('foo')) |
2563 self.assertEquals(len(results), 1) | 2559 self.assertEquals(len(results), 1) |
2564 self.assertEquals(results[0].__class__, | 2560 self.assertEquals(results[0].__class__, |
2565 presubmit.OutputApi.PresubmitNotifyResult) | 2561 presubmit.OutputApi.PresubmitNotifyResult) |
2566 | 2562 |
2567 def AssertOwnersWorks(self, tbr=False, issue='1', approvers=None, | 2563 def AssertOwnersWorks(self, tbr=False, issue='1', approvers=None, |
2568 reviewers=None, is_committing=True, | 2564 reviewers=None, is_committing=True, rietveld_response=None, |
2569 rietveld_response=None, gerrit_response=None, | |
2570 uncovered_files=None, expected_output='', | 2565 uncovered_files=None, expected_output='', |
2571 manually_specified_reviewers=None, dry_run=None): | 2566 manually_specified_reviewers=None, dry_run=None): |
2572 if approvers is None: | 2567 if approvers is None: |
2573 # The set of people who lgtm'ed a change. | 2568 # The set of people who lgtm'ed a change. |
2574 approvers = set() | 2569 approvers = set() |
2575 if reviewers is None: | 2570 if reviewers is None: |
2576 # The set of people needed to lgtm a change. We default to | 2571 # The set of people needed to lgtm a change. We default to |
2577 # the same list as the people who approved it. We use 'reviewers' | 2572 # the same list as the people who approved it. We use 'reviewers' |
2578 # to avoid a name collision w/ owners.py. | 2573 # to avoid a name collision w/ owners.py. |
2579 reviewers = approvers | 2574 reviewers = approvers |
2580 if uncovered_files is None: | 2575 if uncovered_files is None: |
2581 uncovered_files = set() | 2576 uncovered_files = set() |
2582 if manually_specified_reviewers is None: | 2577 if manually_specified_reviewers is None: |
2583 manually_specified_reviewers = [] | 2578 manually_specified_reviewers = [] |
2584 | 2579 |
2585 change = self.mox.CreateMock(presubmit.Change) | 2580 change = self.mox.CreateMock(presubmit.Change) |
2586 change.issue = issue | 2581 change.issue = issue |
2587 change.author_email = 'john@example.com' | 2582 change.author_email = 'john@example.com' |
2588 change.R = ','.join(manually_specified_reviewers) | 2583 change.R = ','.join(manually_specified_reviewers) |
2589 change.TBR = '' | 2584 change.TBR = '' |
2590 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) | 2585 affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile) |
2591 input_api = self.MockInputApi(change, False) | 2586 input_api = self.MockInputApi(change, False) |
2592 if gerrit_response: | |
2593 assert not rietveld_response | |
2594 input_api.rietveld = None | |
2595 input_api.gerrit = presubmit.GerritAccessor('host') | |
2596 | |
2597 fake_db = self.mox.CreateMock(owners.Database) | 2587 fake_db = self.mox.CreateMock(owners.Database) |
2598 fake_db.email_regexp = input_api.re.compile(owners.BASIC_EMAIL_REGEXP) | 2588 fake_db.email_regexp = input_api.re.compile(owners.BASIC_EMAIL_REGEXP) |
2599 input_api.owners_db = fake_db | 2589 input_api.owners_db = fake_db |
2600 input_api.is_committing = is_committing | 2590 input_api.is_committing = is_committing |
2601 input_api.tbr = tbr | 2591 input_api.tbr = tbr |
2602 input_api.dry_run = dry_run | 2592 input_api.dry_run = dry_run |
2603 | 2593 |
2604 if not is_committing or (not tbr and issue): | 2594 if not is_committing or (not tbr and issue): |
2605 if not dry_run: | 2595 if not dry_run: |
2606 affected_file.LocalPath().AndReturn('foo/xyz.cc') | 2596 affected_file.LocalPath().AndReturn('foo/xyz.cc') |
2607 change.AffectedFiles(file_filter=None).AndReturn([affected_file]) | 2597 change.AffectedFiles(file_filter=None).AndReturn([affected_file]) |
2608 if issue and not rietveld_response and not gerrit_response: | 2598 if issue and not rietveld_response: |
2609 rietveld_response = { | 2599 rietveld_response = { |
2610 "owner_email": change.author_email, | 2600 "owner_email": change.author_email, |
2611 "messages": [ | 2601 "messages": [ |
2612 {"sender": a, "text": "I approve", "approval": True} | 2602 {"sender": a, "text": "I approve", "approval": True} |
2613 for a in approvers | 2603 for a in approvers |
2614 ], | 2604 ], |
2615 "reviewers": reviewers | 2605 "reviewers": reviewers |
2616 } | 2606 } |
2617 | 2607 |
2618 if is_committing: | 2608 if is_committing: |
2619 people = approvers | 2609 people = approvers |
2620 else: | 2610 else: |
2621 people = reviewers | 2611 people = reviewers |
2622 | 2612 |
2623 if not dry_run: | 2613 if not dry_run: |
2624 if issue: | 2614 if issue: |
2625 if rietveld_response: | 2615 input_api.rietveld.get_issue_properties( |
2626 input_api.rietveld.get_issue_properties( | 2616 issue=int(input_api.change.issue), messages=True).AndReturn( |
2627 issue=int(input_api.change.issue), messages=True).AndReturn( | 2617 rietveld_response) |
2628 rietveld_response) | |
2629 elif gerrit_response: | |
2630 input_api.gerrit._FetchChangeDetail = lambda _: gerrit_response | |
2631 | 2618 |
2632 people.add(change.author_email) | 2619 people.add(change.author_email) |
2633 fake_db.files_not_covered_by(set(['foo/xyz.cc']), | 2620 fake_db.files_not_covered_by(set(['foo/xyz.cc']), |
2634 people).AndReturn(uncovered_files) | 2621 people).AndReturn(uncovered_files) |
2635 if not is_committing and uncovered_files: | 2622 if not is_committing and uncovered_files: |
2636 fake_db.reviewers_for(set(['foo']), | 2623 fake_db.reviewers_for(set(['foo']), |
2637 change.author_email).AndReturn(change.author_email) | 2624 change.author_email).AndReturn(change.author_email) |
2638 | 2625 |
2639 self.mox.ReplayAll() | 2626 self.mox.ReplayAll() |
2640 output = presubmit.PresubmitOutput() | 2627 output = presubmit.PresubmitOutput() |
(...skipping 12 matching lines...) Expand all Loading... |
2653 dry_run=True, | 2640 dry_run=True, |
2654 rietveld_response=response, | 2641 rietveld_response=response, |
2655 reviewers=set(["ben@example.com"]), | 2642 reviewers=set(["ben@example.com"]), |
2656 expected_output='This is a dry run, skipping OWNERS check\n') | 2643 expected_output='This is a dry run, skipping OWNERS check\n') |
2657 | 2644 |
2658 self.AssertOwnersWorks(approvers=set(['ben@example.com']), | 2645 self.AssertOwnersWorks(approvers=set(['ben@example.com']), |
2659 is_committing=False, | 2646 is_committing=False, |
2660 rietveld_response=response, | 2647 rietveld_response=response, |
2661 expected_output='') | 2648 expected_output='') |
2662 | 2649 |
2663 def testCannedCheckOwners_Approved_Gerrit(self): | |
2664 response = { | |
2665 "owner": {"email": "john@example.com"}, | |
2666 "labels": {"Code-Review": { | |
2667 u'all': [ | |
2668 { | |
2669 u'email': u'john@example.com', # self +1 :) | |
2670 u'value': 1 | |
2671 }, | |
2672 { | |
2673 u'email': u'ben@example.com', | |
2674 u'value': 2 | |
2675 }, | |
2676 ], | |
2677 u'approved': {u'email': u'ben@example.org'}, | |
2678 u'default_value': 0, | |
2679 u'values': {u' 0': u'No score', | |
2680 u'+1': u'Looks good to me, but someone else must approve', | |
2681 u'+2': u'Looks good to me, approved', | |
2682 u'-1': u"I would prefer that you didn't submit this", | |
2683 u'-2': u'Do not submit'} | |
2684 }}, | |
2685 } | |
2686 self.AssertOwnersWorks(approvers=set(['ben@example.com']), | |
2687 gerrit_response=response, | |
2688 is_committing=True, | |
2689 expected_output='') | |
2690 | |
2691 self.AssertOwnersWorks(approvers=set(['ben@example.com']), | |
2692 is_committing=False, | |
2693 gerrit_response=response, | |
2694 expected_output='') | |
2695 | |
2696 def testCannedCheckOwners_Approved(self): | 2650 def testCannedCheckOwners_Approved(self): |
2697 response = { | 2651 response = { |
2698 "owner_email": "john@example.com", | 2652 "owner_email": "john@example.com", |
2699 "messages": [ | 2653 "messages": [ |
2700 { | 2654 { |
2701 "sender": "ben@example.com", "text": "foo", "approval": True, | 2655 "sender": "ben@example.com", "text": "foo", "approval": True, |
2702 }, | 2656 }, |
2703 ], | 2657 ], |
2704 "reviewers": ["ben@example.com"], | 2658 "reviewers": ["ben@example.com"], |
2705 } | 2659 } |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2932 owners_check=False) | 2886 owners_check=False) |
2933 self.assertEqual(2, len(results)) | 2887 self.assertEqual(2, len(results)) |
2934 self.assertEqual( | 2888 self.assertEqual( |
2935 'Found line ending with white spaces in:', results[0]._message) | 2889 'Found line ending with white spaces in:', results[0]._message) |
2936 self.checkstdout('') | 2890 self.checkstdout('') |
2937 | 2891 |
2938 | 2892 |
2939 if __name__ == '__main__': | 2893 if __name__ == '__main__': |
2940 import unittest | 2894 import unittest |
2941 unittest.main() | 2895 unittest.main() |
OLD | NEW |