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

Side by Side Diff: tests/presubmit_unittest.py

Issue 1935563002: Revert of Implement owners check in presubmit for Gerrit. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@P300
Patch Set: Created 4 years, 7 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/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
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
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
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
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
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
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
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
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
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()
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