diff --git a/tools/jenkins/build_docker_and_run_tests.sh b/tools/jenkins/build_docker_and_run_tests.sh new file mode 100755 index 00000000000..fa6bd44e180 --- /dev/null +++ b/tools/jenkins/build_docker_and_run_tests.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# Copyright 2015, 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. +# +# This script is invoked by run_tests.py to accommodate "test under docker" +# scenario. You should never need to call this script on your own. + +set -ex + +cd `dirname $0`/../.. +git_root=`pwd` +cd - + +mkdir -p /tmp/ccache + +# Create a local branch so the child Docker script won't complain +git branch -f jenkins-docker + +# Use image name based on Dockerfile checksum +DOCKER_IMAGE_NAME=grpc_jenkins_slave${docker_suffix}_`sha1sum tools/jenkins/grpc_jenkins_slave/Dockerfile | cut -f1 -d\ ` + +# Make sure docker image has been built. Should be instantaneous if so. +docker build -t $DOCKER_IMAGE_NAME tools/jenkins/grpc_jenkins_slave$docker_suffix + +# Make sure the CID file is gone. +rm -f docker.cid + +# Run tests inside docker +docker run \ + -e "RUN_TESTS_COMMAND=$RUN_TESTS_COMMAND" \ + -e "config=$config" \ + -e "arch=$arch" \ + -e CCACHE_DIR=/tmp/ccache \ + -i $TTY_FLAG \ + -v "$git_root:/var/local/jenkins/grpc" \ + -v /tmp/ccache:/tmp/ccache \ + -w /var/local/git/grpc \ + --cidfile=docker.cid \ + $DOCKER_IMAGE_NAME \ + bash -l /var/local/jenkins/grpc/tools/jenkins/docker_run_tests.sh || DOCKER_FAILED="true" + +DOCKER_CID=`cat docker.cid` + +if [ "$XML_REPORT" != "" ] +then + docker cp "$DOCKER_CID:/var/local/git/grpc/$XML_REPORT" $git_root +fi + +# remove the container, possibly killing it first +docker rm -f $DOCKER_CID || true + +if [ "$DOCKER_FAILED" != "" ] && [ "$XML_REPORT" == "" ] +then + exit 1 +fi diff --git a/tools/jenkins/docker_run_jenkins.sh b/tools/jenkins/docker_run_tests.sh similarity index 88% rename from tools/jenkins/docker_run_jenkins.sh rename to tools/jenkins/docker_run_tests.sh index 0a5516c30df..781bff26b93 100755 --- a/tools/jenkins/docker_run_jenkins.sh +++ b/tools/jenkins/docker_run_tests.sh @@ -28,18 +28,17 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# This script is invoked by run_jekins.sh when piggy-backing into docker. +# This script is invoked by build_docker_and_run_tests.py inside a docker +# container. You should never need to call this script on your own. set -e export CONFIG=$config export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.5 -export CPPFLAGS=-I/tmp/prebuilt/include mkdir -p /var/local/git git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc -cd /var/local/git/grpc nvm use 0.12 rvm use ruby-2.1 -setarch $arch tools/run_tests/run_tests.py -t -c $config -l $language -x report.xml +$RUN_TESTS_COMMAND diff --git a/tools/jenkins/run_jenkins.sh b/tools/jenkins/run_jenkins.sh index 9ff588e8fa4..a55f1de9960 100755 --- a/tools/jenkins/run_jenkins.sh +++ b/tools/jenkins/run_jenkins.sh @@ -56,46 +56,8 @@ if [ "$platform" == "linux" ] then echo "building $language on Linux" - cd `dirname $0`/../.. - git_root=`pwd` - cd - + ./tools/run_tests/run_tests.py --use_docker -t -l $language -c $config -x report.xml || true - mkdir -p /tmp/ccache - - # Use image name based on Dockerfile checksum - DOCKER_IMAGE_NAME=grpc_jenkins_slave$docker_suffix_`sha1sum tools/jenkins/grpc_jenkins_slave/Dockerfile | cut -f1 -d\ ` - - # Make sure docker image has been built. Should be instantaneous if so. - docker build -t $DOCKER_IMAGE_NAME tools/jenkins/grpc_jenkins_slave$docker_suffix - - # Create a local branch so the child Docker script won't complain - git branch jenkins-docker - - # Make sure the CID file is gone. - rm -f docker.cid - - # Run tests inside docker - docker run \ - -e "config=$config" \ - -e "language=$language" \ - -e "arch=$arch" \ - -e CCACHE_DIR=/tmp/ccache \ - -i \ - -v "$git_root:/var/local/jenkins/grpc" \ - -v /tmp/ccache:/tmp/ccache \ - --cidfile=docker.cid \ - $DOCKER_IMAGE_NAME \ - bash -l /var/local/jenkins/grpc/tools/jenkins/docker_run_jenkins.sh || DOCKER_FAILED="true" - - DOCKER_CID=`cat docker.cid` - # forcefully kill the instance if it's still running, otherwise - # continue - # (failure to kill something that's already dead => things are dead) - docker kill $DOCKER_CID || true - docker cp $DOCKER_CID:/var/local/git/grpc/report.xml $git_root - # TODO(ctiller): why? - sleep 4 - docker rm $DOCKER_CID || true elif [ "$platform" == "interop" ] then python tools/run_tests/run_interops.py --language=$language diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 8f6511b1f88..f7e9805393d 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -397,12 +397,6 @@ _WINDOWS_CONFIG = { 'opt': 'Release', } -# parse command line -argp = argparse.ArgumentParser(description='Run grpc tests.') -argp.add_argument('-c', '--config', - choices=['all'] + sorted(_CONFIGS.keys()), - nargs='+', - default=_DEFAULT) def runs_per_test_type(arg_str): """Auxilary function to parse the "runs_per_test" flag. @@ -423,6 +417,13 @@ def runs_per_test_type(arg_str): except: msg = "'{}' isn't a positive integer or 'inf'".format(arg_str) raise argparse.ArgumentTypeError(msg) + +# parse command line +argp = argparse.ArgumentParser(description='Run grpc tests.') +argp.add_argument('-c', '--config', + choices=['all'] + sorted(_CONFIGS.keys()), + nargs='+', + default=_DEFAULT) argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type, help='A positive integer or "inf". If "inf", all tests will run in an ' 'infinite loop. Especially useful in combination with "-f"') @@ -449,11 +450,48 @@ argp.add_argument('-S', '--stop_on_failure', default=False, action='store_const', const=True) +argp.add_argument('--use_docker', + default=False, + action='store_const', + const=True, + help="Run all the tests under docker. That provides " + + "additional isolation and prevents the need to installs " + + "language specific prerequisites. Only available on Linux.") argp.add_argument('-a', '--antagonists', default=0, type=int) argp.add_argument('-x', '--xml_report', default=None, type=str, help='Generates a JUnit-compatible XML report') args = argp.parse_args() +if args.use_docker: + if not args.travis: + print 'Seen --use_docker flag, will run tests under docker.' + print + print 'IMPORTANT: The changes you are testing need to be locally committed' + print 'because only the committed changes in the current branch will be' + print 'copied to the docker environment.' + time.sleep(5) + + child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ] + run_tests_cmd = 'tools/run_tests/run_tests.py %s' % " ".join(child_argv[1:]) + + # TODO(jtattermusch): revisit if we need special handling for arch here + # set arch command prefix in case we are working with different arch. + arch_env = os.getenv('arch') + if arch_env: + run_test_cmd = 'arch %s %s' % (arch_env, run_test_cmd) + + env = os.environ.copy() + env['RUN_TESTS_COMMAND'] = run_tests_cmd + if args.xml_report: + env['XML_REPORT'] = args.xml_report + if not args.travis: + env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins. + + subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'], + shell=True, + env=env) + sys.exit(0) + # grab config run_configs = set(_CONFIGS[cfg] for cfg in itertools.chain.from_iterable(