depot_tools: Make it possible to run python3 tests on PRESUBMIT.

Add run_on_python2 and run_on_python3 to allow to be tests on
either only python2, only python3 or both.

Bug: 984182
Change-Id: I87d3b67412129cf3a8e627cd6bc97daa81147657
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1758849
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: smut <smut@google.com>
Reviewed-by: Robbie Iannucci <iannucci@chromium.org>
changes/49/1758849/6
Edward Lemur 6 years ago committed by Commit Bot
parent 3a96d62052
commit 940c282116

@ -576,7 +576,8 @@ def CheckTreeIsOpen(input_api, output_api,
return [] return []
def GetUnitTestsInDirectory( def GetUnitTestsInDirectory(
input_api, output_api, directory, whitelist=None, blacklist=None, env=None): input_api, output_api, directory, whitelist=None, blacklist=None, env=None,
run_on_python2=True, run_on_python3=True):
"""Lists all files in a directory and runs them. Doesn't recurse. """Lists all files in a directory and runs them. Doesn't recurse.
It's mainly a wrapper for RunUnitTests. Use whitelist and blacklist to filter It's mainly a wrapper for RunUnitTests. Use whitelist and blacklist to filter
@ -609,14 +610,24 @@ def GetUnitTestsInDirectory(
'Out of %d files, found none that matched w=%r, b=%r in directory %s' 'Out of %d files, found none that matched w=%r, b=%r in directory %s'
% (found, whitelist, blacklist, directory)) % (found, whitelist, blacklist, directory))
] ]
return GetUnitTests(input_api, output_api, unit_tests, env) return GetUnitTests(
input_api, output_api, unit_tests, env, run_on_python2, run_on_python3)
def GetUnitTests(input_api, output_api, unit_tests, env=None): def GetUnitTests(
input_api, output_api, unit_tests, env=None, run_on_python2=True,
run_on_python3=True):
"""Runs all unit tests in a directory. """Runs all unit tests in a directory.
On Windows, sys.executable is used for unit tests ending with ".py". On Windows, sys.executable is used for unit tests ending with ".py".
""" """
assert run_on_python3 or run_on_python2, (
'At least one of "run_on_python2" or "run_on_python3" must be set.')
def has_py3_shebang(test):
with open(test) as f:
maybe_shebang = f.readline()
return maybe_shebang.startswith('#!') and 'python3' in maybe_shebang
# We don't want to hinder users from uploading incomplete patches. # We don't want to hinder users from uploading incomplete patches.
if input_api.is_committing: if input_api.is_committing:
message_type = output_api.PresubmitError message_type = output_api.PresubmitError
@ -631,11 +642,26 @@ def GetUnitTests(input_api, output_api, unit_tests, env=None):
kwargs = {'cwd': input_api.PresubmitLocalPath()} kwargs = {'cwd': input_api.PresubmitLocalPath()}
if env: if env:
kwargs['env'] = env kwargs['env'] = env
results.append(input_api.Command( if not unit_test.endswith('.py'):
name=unit_test, results.append(input_api.Command(
cmd=cmd, name=unit_test,
kwargs=kwargs, cmd=cmd,
message=message_type)) kwargs=kwargs,
message=message_type))
else:
if has_py3_shebang(unit_test) and run_on_python3:
results.append(input_api.Command(
name=unit_test,
cmd=cmd,
kwargs=kwargs,
message=message_type,
python3=True))
if run_on_python2:
results.append(input_api.Command(
name=unit_test,
cmd=cmd,
kwargs=kwargs,
message=message_type))
return results return results

@ -66,7 +66,7 @@ class PresubmitFailure(Exception):
class CommandData(object): class CommandData(object):
def __init__(self, name, cmd, kwargs, message): def __init__(self, name, cmd, kwargs, message, python3=False):
self.name = name self.name = name
self.cmd = cmd self.cmd = cmd
self.stdin = kwargs.get('stdin', None) self.stdin = kwargs.get('stdin', None)
@ -76,6 +76,7 @@ class CommandData(object):
self.kwargs['stdin'] = subprocess.PIPE self.kwargs['stdin'] = subprocess.PIPE
self.message = message self.message = message
self.info = None self.info = None
self.python3 = python3
# Adapted from # Adapted from
@ -152,7 +153,11 @@ class ThreadPool(object):
This function converts invocation of .py files and invocations of "python" This function converts invocation of .py files and invocations of "python"
to vpython invocations. to vpython invocations.
""" """
vpython = 'vpython.bat' if sys.platform == 'win32' else 'vpython' vpython = 'vpython'
if test.python3:
vpython += '3'
if sys.platform == 'win32':
vpython += '.bat'
cmd = test.cmd cmd = test.cmd
if cmd[0] == 'python': if cmd[0] == 'python':

@ -58,6 +58,11 @@ class MockTemporaryFile(object):
pass pass
class MockProcess(object):
def __init__(self, returncode):
self.returncode = returncode
class PresubmitTestsBase(TestCaseUtils, unittest.TestCase): class PresubmitTestsBase(TestCaseUtils, unittest.TestCase):
"""Sets up and tears down the mocks but doesn't test anything as-is.""" """Sets up and tears down the mocks but doesn't test anything as-is."""
presubmit_text = """ presubmit_text = """
@ -2521,6 +2526,7 @@ the current line as well!
is_committing=False, is_committing=False,
uncovered_files=set()) uncovered_files=set())
@mock.patch('__builtin__.open', mock.mock_open(read_data=''))
def testCannedRunUnitTests(self): def testCannedRunUnitTests(self):
change = presubmit.Change( change = presubmit.Change(
'foo1', 'description1', self.fake_root_dir, None, 0, 0, None) 'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)
@ -2563,6 +2569,143 @@ the current line as well!
self.checkstdout('') self.checkstdout('')
@mock.patch('__builtin__.open', mock.mock_open())
def testCannedRunUnitTestsPython3(self):
open().readline.return_value = '#!/usr/bin/env python3'
change = presubmit.Change(
'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)
input_api = self.MockInputApi(change, False)
input_api.verbose = True
input_api.PresubmitLocalPath.return_value = self.fake_root_dir
presubmit.sigint_handler.wait.return_value = ('', None)
subprocess.Popen.side_effect = [
MockProcess(1),
MockProcess(0),
MockProcess(0),
]
unit_tests = ['allo', 'bar.py']
results = presubmit_canned_checks.RunUnitTests(
input_api,
presubmit.OutputApi,
unit_tests)
self.assertEqual([result.__class__ for result in results], [
presubmit.OutputApi.PresubmitPromptWarning,
presubmit.OutputApi.PresubmitNotifyResult,
presubmit.OutputApi.PresubmitNotifyResult,
])
cmd = ['bar.py', '--verbose']
vpython = 'vpython'
vpython3 = 'vpython3'
if input_api.platform == 'win32':
vpython += '.bat'
vpython3 += '.bat'
self.assertEqual(subprocess.Popen.mock_calls, [
mock.call(
[vpython] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
mock.call(
[vpython3] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
mock.call(
['allo', '--verbose'], cwd=self.fake_root_dir,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
stdin=subprocess.PIPE),
])
self.checkstdout('')
@mock.patch('__builtin__.open', mock.mock_open())
def testCannedRunUnitTestsDontRunOnPython2(self):
open().readline.return_value = '#!/usr/bin/env python3'
change = presubmit.Change(
'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)
input_api = self.MockInputApi(change, False)
input_api.verbose = True
input_api.PresubmitLocalPath.return_value = self.fake_root_dir
presubmit.sigint_handler.wait.return_value = ('', None)
subprocess.Popen.side_effect = [
MockProcess(1),
MockProcess(0),
MockProcess(0),
]
unit_tests = ['allo', 'bar.py']
results = presubmit_canned_checks.RunUnitTests(
input_api,
presubmit.OutputApi,
unit_tests,
run_on_python2=False)
self.assertEqual([result.__class__ for result in results], [
presubmit.OutputApi.PresubmitPromptWarning,
presubmit.OutputApi.PresubmitNotifyResult,
])
cmd = ['bar.py', '--verbose']
vpython3 = 'vpython3'
if input_api.platform == 'win32':
vpython3 += '.bat'
self.assertEqual(subprocess.Popen.mock_calls, [
mock.call(
[vpython3] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
mock.call(
['allo', '--verbose'], cwd=self.fake_root_dir,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
stdin=subprocess.PIPE),
])
self.checkstdout('')
@mock.patch('__builtin__.open', mock.mock_open())
def testCannedRunUnitTestsDontRunOnPython3(self):
open().readline.return_value = '#!/usr/bin/env python3'
change = presubmit.Change(
'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)
input_api = self.MockInputApi(change, False)
input_api.verbose = True
input_api.PresubmitLocalPath.return_value = self.fake_root_dir
presubmit.sigint_handler.wait.return_value = ('', None)
subprocess.Popen.side_effect = [
MockProcess(1),
MockProcess(0),
MockProcess(0),
]
unit_tests = ['allo', 'bar.py']
results = presubmit_canned_checks.RunUnitTests(
input_api,
presubmit.OutputApi,
unit_tests,
run_on_python3=False)
self.assertEqual([result.__class__ for result in results], [
presubmit.OutputApi.PresubmitPromptWarning,
presubmit.OutputApi.PresubmitNotifyResult,
])
cmd = ['bar.py', '--verbose']
vpython = 'vpython'
if input_api.platform == 'win32':
vpython += '.bat'
self.assertEqual(subprocess.Popen.mock_calls, [
mock.call(
[vpython] + cmd, cwd=self.fake_root_dir, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stdin=subprocess.PIPE),
mock.call(
['allo', '--verbose'], cwd=self.fake_root_dir,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
stdin=subprocess.PIPE),
])
self.checkstdout('')
def testCannedRunUnitTestsInDirectory(self): def testCannedRunUnitTestsInDirectory(self):
change = presubmit.Change( change = presubmit.Change(
'foo1', 'description1', self.fake_root_dir, None, 0, 0, None) 'foo1', 'description1', self.fake_root_dir, None, 0, 0, None)

Loading…
Cancel
Save