Skip to content

Commit

Permalink
Make Python tests run on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
soltanmm-google committed Jul 8, 2016
1 parent 639bb39 commit cab9d4f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 36 deletions.
19 changes: 12 additions & 7 deletions src/python/grpcio_tests/tests/_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,20 @@ def check_kill_self():
stderr_pipe.write_bypass(
'\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output().decode()))
os._exit(1)
signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGSEGV, fault_handler)
signal.signal(signal.SIGBUS, fault_handler)
signal.signal(signal.SIGABRT, fault_handler)
signal.signal(signal.SIGFPE, fault_handler)
signal.signal(signal.SIGILL, fault_handler)
def try_set_handler(name, handler):
try:
signal.signal(getattr(signal, name), handler)
except AttributeError:
pass
try_set_handler('SIGINT', sigint_handler)
try_set_handler('SIGSEGV', fault_handler)
try_set_handler('SIGBUS', fault_handler)
try_set_handler('SIGABRT', fault_handler)
try_set_handler('SIGFPE', fault_handler)
try_set_handler('SIGILL', fault_handler)
# Sometimes output will lag after a test has successfully finished; we
# ignore such writes to our pipes.
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
try_set_handler('SIGPIPE', signal.SIG_IGN)

# Run the tests
result.startTestRun()
Expand Down
36 changes: 36 additions & 0 deletions tools/run_tests/build_python_msys2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -ex

BUILD_PYTHON=`realpath "$(dirname $0)/build_python.sh"`
export MSYSTEM=$1
shift 1
bash --login $BUILD_PYTHON "$@"
74 changes: 45 additions & 29 deletions tools/run_tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,31 +375,27 @@ def __str__(self):


class PythonConfig(collections.namedtuple('PythonConfig', [
'python', 'venv', 'venv_relative_python', 'toolchain',])):

@property
def venv_python(self):
return os.path.abspath('{}/{}'.format(self.venv, self.venv_relative_python))

'name', 'build', 'run'])):
"""Tuple of commands (named s.t. 'what it says on the tin' applies)"""

class PythonLanguage(object):

def configure(self, config, args):
self.config = config
self.args = args
self.pythons = self._get_pythons(self.args.compiler)
self.pythons = self._get_pythons(self.args)

def test_specs(self):
# load list of known test suites
with open('src/python/grpcio_tests/tests/tests.json') as tests_json_file:
tests_json = json.load(tests_json_file)
environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
return [self.config.job_spec(
['tools/run_tests/run_python.sh', config.venv_python],
config.run,
timeout_seconds=5*60,
environ=dict(environment.items() +
[('GRPC_PYTHON_TESTRUNNER_FILTER', suite_name)]),
shortname='%s.test.%s' % (config.venv, suite_name),)
shortname='%s.test.%s' % (config.name, suite_name),)
for suite_name in tests_json
for config in self.pythons]

Expand All @@ -413,14 +409,7 @@ def make_options(self):
return []

def build_steps(self):
return [
[
'tools/run_tests/build_python.sh',
config.python, config.venv,
config.venv_relative_python, config.toolchain
]
for config in self.pythons
]
return [config.build for config in self.pythons]

def post_tests_steps(self):
return []
Expand All @@ -431,23 +420,50 @@ def makefile_name(self):
def dockerfile_dir(self):
return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(self.args.arch)

def _get_pythons(self, compiler):
def _get_pythons(self, args):
if args.arch == 'x86':
bits = '32'
else:
bits = '64'
if os.name == 'nt':
venv_relative_python = 'Scripts/python.exe'
toolchain = 'mingw32'
shell = ['bash']
builder = [os.path.abspath('tools/run_tests/build_python_msys2.sh')]
builder_prefix_arguments = ['MINGW{}'.format(bits)]
venv_relative_python = ['Scripts/python.exe']
toolchain = ['mingw32']
python_pattern_function = lambda major, minor, bits: (
'/c/Python{major}{minor}/python.exe'.format(major=major, minor=minor, bits=bits)
if bits == '64' else
'/c/Python{major}{minor}_{bits}bits/python.exe'.format(
major=major, minor=minor, bits=bits))
else:
venv_relative_python = 'bin/python'
toolchain = 'unix'
python27_config = PythonConfig('python2.7', 'py27', venv_relative_python, toolchain)
python34_config = PythonConfig('python3.4', 'py34', venv_relative_python, toolchain)
if compiler == 'default':
return (python27_config, python34_config,)
elif compiler == 'python2.7':
shell = []
builder = [os.path.abspath('tools/run_tests/build_python.sh')]
builder_prefix_arguments = []
venv_relative_python = ['bin/python']
toolchain = ['unix']
# Bit-ness is handled by the test machine's environment
python_pattern_function = lambda major, minor, bits: 'python{major}.{minor}'.format(major=major, minor=minor)
runner = [os.path.abspath('tools/run_tests/run_python.sh')]
python_config_generator = lambda name, major, minor, bits: PythonConfig(
name,
shell + builder + builder_prefix_arguments
+ [python_pattern_function(major=major, minor=minor, bits=bits)]
+ [name] + venv_relative_python + toolchain,
shell + runner + [os.path.join(name, venv_relative_python[0])])
python27_config = python_config_generator(name='py27', major='2', minor='7', bits=bits)
python34_config = python_config_generator(name='py34', major='3', minor='4', bits=bits)
if args.compiler == 'default':
if os.name == 'nt':
return (python27_config,)
else:
return (python27_config, python34_config,)
elif args.compiler == 'python2.7':
return (python27_config,)
elif compiler == 'python3.4':
elif args.compiler == 'python3.4':
return (python34_config,)
else:
raise Exception('Compiler %s not supported.' % compiler)
raise Exception('Compiler %s not supported.' % args.compiler)

def __str__(self):
return 'python'
Expand Down

0 comments on commit cab9d4f

Please sign in to comment.