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