Merge pull request #3605 from jtattermusch/interop_improvements

Build and run per-language containers for interop tests
pull/3614/head
Nicolas Noble 9 years ago
commit f8460df564
  1. 111
      tools/jenkins/build_docker_and_run_interop_tests.sh
  2. 93
      tools/jenkins/build_interop_image.sh
  3. 92
      tools/jenkins/grpc_interop_csharp/Dockerfile
  4. 44
      tools/jenkins/grpc_interop_csharp/build_interop.sh
  5. 75
      tools/jenkins/grpc_interop_cxx/Dockerfile
  6. 42
      tools/jenkins/grpc_interop_cxx/build_interop.sh
  7. 58
      tools/jenkins/grpc_interop_java/Dockerfile
  8. 12
      tools/jenkins/grpc_interop_java/build_interop.sh
  9. 79
      tools/jenkins/grpc_interop_node/Dockerfile
  10. 24
      tools/jenkins/grpc_interop_node/build_interop.sh
  11. 112
      tools/jenkins/grpc_interop_php/Dockerfile
  12. 40
      tools/jenkins/grpc_interop_php/build_interop.sh
  13. 87
      tools/jenkins/grpc_interop_ruby/Dockerfile
  14. 43
      tools/jenkins/grpc_interop_ruby/build_interop.sh
  15. 115
      tools/run_tests/dockerjob.py
  16. 5
      tools/run_tests/jobset.py
  17. 282
      tools/run_tests/run_interop_tests.py

@ -1,111 +0,0 @@
#!/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_interop_tests.py to accommodate
# "interop tests 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
# 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 -f jenkins-docker
# Make sure the CID files are gone.
rm -f prepare.cid server.cid client.cid
# Prepare image for interop tests
docker run \
-e CCACHE_DIR=/tmp/ccache \
-i $TTY_FLAG \
-v "$git_root:/var/local/jenkins/grpc" \
-v /tmp/ccache:/tmp/ccache \
--cidfile=prepare.cid \
$DOCKER_IMAGE_NAME \
bash -l /var/local/jenkins/grpc/tools/jenkins/docker_prepare_interop_tests.sh || DOCKER_FAILED="true"
PREPARE_CID=`cat prepare.cid`
# Create image from the container, we will spawn one docker for clients
# and one for servers.
INTEROP_IMAGE=interop_`uuidgen`
docker commit $PREPARE_CID $INTEROP_IMAGE
# remove container, possibly killing it first
docker rm -f $PREPARE_CID || true
echo "Successfully built image $INTEROP_IMAGE"
# run interop servers under docker in the background
docker run \
-d -i \
$SERVERS_DOCKER_EXTRA_ARGS \
--cidfile=server.cid \
$INTEROP_IMAGE bash -l /var/local/git/grpc/tools/jenkins/docker_run_interop_servers.sh
SERVER_CID=`cat server.cid`
SERVER_PORTS=""
for tuple in $SERVER_PORT_TUPLES
do
# lookup under which port docker exposes given internal port
exposed_port=`docker port $SERVER_CID ${tuple#*:} | awk -F ":" '{print $NF}'`
# override the port for corresponding cloud_to_cloud server
SERVER_PORTS+=" --override_server ${tuple%:*}=localhost:$exposed_port"
echo "${tuple%:*} server is exposed under port $exposed_port"
done
# run interop clients
docker run \
-e "RUN_TESTS_COMMAND=$RUN_TESTS_COMMAND $SERVER_PORTS" \
-w /var/local/git/grpc \
-i $TTY_FLAG \
--net=host \
--cidfile=client.cid \
$INTEROP_IMAGE bash -l /var/local/git/grpc/tools/jenkins/docker_run_interop_tests.sh || DOCKER_FAILED="true"
CLIENT_CID=`cat client.cid`
echo "killing and removing server container $SERVER_CID"
docker rm -f $SERVER_CID || true
docker cp $CLIENT_CID:/var/local/git/grpc/report.xml $git_root
docker rm -f $CLIENT_CID || true
docker rmi -f $DOCKER_IMAGE_NAME || true

@ -0,0 +1,93 @@
#!/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_interop_tests.py to build the docker image
# for interop testing. You should never need to call this script on your own.
set -x
cd `dirname $0`/../..
GRPC_ROOT=`pwd`
MOUNT_ARGS="-v $GRPC_ROOT:/var/local/jenkins/grpc"
GRPC_JAVA_ROOT=`cd ../grpc-java && pwd`
if [ "$GRPC_JAVA_ROOT" != "" ]
then
MOUNT_ARGS+=" -v $GRPC_JAVA_ROOT:/var/local/jenkins/grpc-java"
else
echo "WARNING: grpc-java not found, it won't be mounted to the docker container."
fi
GRPC_GO_ROOT=`cd ../grpc-go && pwd`
if [ "$GRPC_GO_ROOT" != "" ]
then
MOUNT_ARGS+=" -v $GRPC_GO_ROOT:/var/local/jenkins/grpc-go"
else
echo "WARNING: grpc-go not found, it won't be mounted to the docker container."
fi
mkdir -p /tmp/ccache
# Params:
# INTEROP_IMAGE - name of tag of the final interop image
# BASE_NAME - base name used to locate the base Dockerfile and build script
# TTY_FLAG - optional -t flag to make docker allocate tty.
# Use image name based on Dockerfile checksum
BASE_IMAGE=${BASE_NAME}_base:`sha1sum tools/jenkins/$BASE_NAME/Dockerfile | cut -f1 -d\ `
# Make sure base docker image has been built. Should be instantaneous if so.
docker build -t $BASE_IMAGE --force-rm=true tools/jenkins/$BASE_NAME || exit $?
# Create a local branch so the child Docker script won't complain
git branch -f jenkins-docker
CIDFILE=`mktemp -u --suffix=.cid`
# Prepare image for interop tests, commit it on success.
(docker run \
-e CCACHE_DIR=/tmp/ccache \
-i $TTY_FLAG \
$MOUNT_ARGS \
-v /tmp/ccache:/tmp/ccache \
--cidfile=$CIDFILE \
$BASE_IMAGE \
bash -l /var/local/jenkins/grpc/tools/jenkins/$BASE_NAME/build_interop.sh \
&& docker commit `cat $CIDFILE` $INTEROP_IMAGE \
&& echo "Successfully built image $INTEROP_IMAGE")
EXITCODE=$?
# remove intermediate container, possibly killing it first
docker rm -f `cat $CIDFILE`
# remove the cidfile
rm -rf `cat $CIDFILE`
exit $EXITCODE

@ -0,0 +1,92 @@
# 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.
# A work-in-progress Dockerfile that allows running gRPC test suites
# inside a docker container.
FROM debian:jessie
# Install Git.
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
gcc-multilib \
git \
gyp \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
strace \
python-dev \
python-setuptools \
python-yaml \
telnet \
unzip \
wget \
zip && apt-get clean
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
#################
# C# dependencies
# Update to a newer version of mono
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
# Install dependencies
RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \
mono-devel \
nunit \
nunit-console \
monodevelop
# Download NuGet
RUN cd /var/local && wget www.nuget.org/NuGet.exe
ENV NUGET mono /var/local/NuGet.exe
# Define the default command.
CMD ["bash"]

@ -0,0 +1,44 @@
#!/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.
#
# Builds C# interop server and client in a base image.
set -e
mkdir -p /var/local/git
git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
cd /var/local/git/grpc
make install-certs
# build C# interop client & server
make install_grpc_csharp_ext
(cd src/csharp && mono /var/local/NuGet.exe restore Grpc.sln)
(cd src/csharp && xbuild Grpc.sln)

@ -0,0 +1,75 @@
# 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.
# A work-in-progress Dockerfile that allows running gRPC test suites
# inside a docker container.
FROM debian:jessie
# Install Git.
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
gcc-multilib \
git \
gyp \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
strace \
python-dev \
python-setuptools \
python-yaml \
telnet \
unzip \
wget \
zip && apt-get clean
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
##################
# C++ dependencies
RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang
# Define the default command.
CMD ["bash"]

@ -0,0 +1,42 @@
#!/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.
#
# Builds C++ interop server and client in a base image.
set -e
mkdir -p /var/local/git
git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
cd /var/local/git/grpc
make install-certs
# build C++ interop client & server
make interop_client interop_server

@ -0,0 +1,58 @@
# 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.
FROM debian:jessie
# Install JDK 8 and Git
#
# TODO(temiola): simplify this if/when a simpler process is available.
#
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && \
apt-get update && \
apt-get -y install \
git \
libapr1 \
oracle-java8-installer \
&& \
apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
ENV PATH $PATH:$JAVA_HOME/bin
# Trigger download of as many Gradle artifacts as possible.
RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && \
cd grpc-java && \
./gradlew build -PskipCodegen=true && \
rm -r "$(pwd)"
# Define the default command.
CMD ["bash"]

@ -28,12 +28,12 @@
# (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 build_docker_and_run_interop_tests.sh inside
# a docker container. You should never need to call this script on your own.
# Builds Java interop server and client in a base image.
set -e
nvm use 0.12
rvm use ruby-2.1
mkdir -p /var/local/git
git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java
# run the cloud-to-prod interop tests
$RUN_TESTS_COMMAND
cd /var/local/git/grpc-java
./gradlew :grpc-interop-testing:installDist -PskipCodegen=true

@ -0,0 +1,79 @@
# 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.
# A work-in-progress Dockerfile that allows running gRPC test suites
# inside a docker container.
FROM debian:jessie
# Install Git.
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
gcc-multilib \
git \
gyp \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
strace \
python-dev \
python-setuptools \
python-yaml \
telnet \
unzip \
wget \
zip && apt-get clean
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
##################
# Node dependencies
# Install nvm
RUN touch .profile
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
RUN /bin/bash -l -c "nvm install 0.12"
# Define the default command.
CMD ["bash"]

@ -28,23 +28,19 @@
# (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. It contains the test logic
# that should run inside a docker container.
# Builds Node interop server and client in a base image.
set -e
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
# If port env variable is set, run corresponding interop server on given port in background.
# TODO(jtattermusch): ideally, run_interop_tests.py would generate the commands to run servers.
[ -z "${SERVER_PORT_cxx}" ] || bins/opt/interop_server --enable_ssl --port=${SERVER_PORT_cxx} &
[ -z "${SERVER_PORT_node}" ] || node src/node/interop/interop_server.js --use_tls=true --port=${SERVER_PORT_node} &
[ -z "${SERVER_PORT_ruby}" ] || ruby src/ruby/bin/interop/interop_server.rb --use_tls --port=${SERVER_PORT_ruby} &
nvm alias default 0.12 # prevent the need to run 'nvm use' in every shell
[ -z "${SERVER_PORT_csharp}" ] || (cd src/csharp/Grpc.IntegrationTesting.Server/bin/Debug && mono Grpc.IntegrationTesting.Server.exe --use_tls --port=${SERVER_PORT_csharp}) &
make install-certs
sleep infinity
# build Node interop client & server
npm install -g node-gyp
make install_c -C /var/local/git/grpc
(cd src/node && npm install && node-gyp rebuild)

@ -0,0 +1,112 @@
# 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.
# A work-in-progress Dockerfile that allows running gRPC test suites
# inside a docker container.
FROM debian:jessie
# Install Git.
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
gcc-multilib \
git \
gyp \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
strace \
python-dev \
python-setuptools \
python-yaml \
telnet \
unzip \
wget \
zip && apt-get clean
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
##################
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
RUN /bin/bash -l -c "rvm install ruby-2.1"
RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
##################
# PHP dependencies
# Install dependencies
RUN /bin/bash -l -c "echo 'deb http://packages.dotdeb.org wheezy-php55 all' \
>> /etc/apt/sources.list.d/dotdeb.list"
RUN /bin/bash -l -c "echo 'deb-src http://packages.dotdeb.org wheezy-php55 all' \
>> /etc/apt/sources.list.d/dotdeb.list"
RUN wget http://www.dotdeb.org/dotdeb.gpg -O- | apt-key add -
RUN apt-get update && apt-get install -y \
git php5 php5-dev phpunit unzip
# ronn: a ruby tool used to convert markdown to man pages, used during the
# install of Protobuf extensions
#
# rake: a ruby version of make used to build the PHP Protobuf extension
RUN /bin/bash -l -c "rvm all do gem install ronn rake"
ENV DEBIAN_FRONTEND noniteractive
# Install composer
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
# Define the default command.
CMD ["bash"]

@ -28,52 +28,32 @@
# (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. It contains the test logic
# that should run inside a docker container.
# Builds PHP interop server and client in a base image.
set -e
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
rvm --default use ruby-2.1
# TODO(jtattermusch): use cleaner way to install root certs
mkdir -p /usr/local/share/grpc
cp etc/roots.pem /usr/local/share/grpc/
make install-certs
# build C++ interop client & server
make interop_client interop_server
# gRPC core and protobuf need to be installed
make install
# build C# interop client & server
make install_grpc_csharp_ext
(cd src/csharp && mono /var/local/NuGet.exe restore Grpc.sln)
(cd src/csharp && xbuild Grpc.sln)
# build Node interop client & server
npm install -g node-gyp
make install_c -C /var/local/git/grpc
(cd src/node && npm install && node-gyp rebuild)
# build Ruby interop client and server
(cd src/ruby && gem update bundler && bundle && rake compile:grpc)
# TODO(jtattermusch): add python
# build PHP interop client
# TODO(jtattermusch): prerequisites for PHP should be installed sooner than here.
# Install composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
# Download the patched PHP protobuf so that PHP gRPC clients can be generated
# from proto3 schemas.
git clone https://github.com/stanley-cheung/Protobuf-PHP.git /var/local/git/protobuf-php
(cd src/php/ext/grpc && phpize && ./configure && make)
rvm all do gem install ronn rake
(cd third_party/protobuf && make install)
(cd /var/local/git/protobuf-php \
&& rvm all do rake pear:package version=1.0 \
&& pear install Protobuf-1.0.tgz)
(cd src/php && composer install)
(cd src/php && protoc-gen-php -i tests/interop/ -o tests/interop/ tests/interop/test.proto)

@ -0,0 +1,87 @@
# 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.
# A work-in-progress Dockerfile that allows running gRPC test suites
# inside a docker container.
FROM debian:jessie
# Install Git.
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
gcc-multilib \
git \
gyp \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
strace \
python-dev \
python-setuptools \
python-yaml \
telnet \
unzip \
wget \
zip && apt-get clean
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
##################
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
RUN /bin/bash -l -c "rvm install ruby-2.1"
RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
# Define the default command.
CMD ["bash"]

@ -0,0 +1,43 @@
#!/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.
#
# Builds Ruby interop server and client in a base image.
set -e
mkdir -p /var/local/git
git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
cd /var/local/git/grpc
rvm --default use ruby-2.1
make install-certs
# build Ruby interop client and server
(cd src/ruby && gem update bundler && bundle && rake compile:grpc)

@ -0,0 +1,115 @@
# 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.
"""Helpers to run docker instances as jobs."""
import jobset
import tempfile
import time
import uuid
import os
import subprocess
_DEVNULL = open(os.devnull, 'w')
def wait_for_file(filepath, timeout_seconds=15):
"""Wait until given file exists and returns its content."""
started = time.time()
while time.time() - started < timeout_seconds:
if os.path.isfile(filepath):
with open(filepath, 'r') as f:
content = f.read()
# make sure we don't return empty content
if content:
return content
time.sleep(1)
raise Exception('Failed to read file %s.' % filepath)
def docker_mapped_port(cid, port):
"""Get port mapped to internal given internal port for given container."""
output = subprocess.check_output('docker port %s %s' % (cid, port), shell=True)
return int(output.split(':', 2)[1])
def finish_jobs(jobs):
"""Kills given docker containers and waits for corresponding jobs to finish"""
for job in jobs:
job.kill(suppress_failure=True)
while any(job.is_running() for job in jobs):
time.sleep(1)
def image_exists(image):
"""Returns True if given docker image exists."""
return subprocess.call(['docker','inspect', image],
stdout=_DEVNULL,
stderr=_DEVNULL) == 0
def remove_image(image, skip_nonexistent=False, max_retries=10):
"""Attempts to remove docker image with retries."""
if skip_nonexistent and not image_exists(image):
return True
for attempt in range(0, max_retries):
if subprocess.call(['docker','rmi', '-f', image]) == 0:
return True
time.sleep(2)
print 'Failed to remove docker image %s' % image
return False
class DockerJob:
"""Encapsulates a job"""
def __init__(self, spec):
self._spec = spec
self._job = jobset.Job(spec, bin_hash=None, newline_on_success=True, travis=True, add_env={}, xml_report=None)
self._cidfile = spec.cidfile
self._cid = None
def cid(self):
"""Gets cid of this container"""
if not self._cid:
self._cid = wait_for_file(self._cidfile)
return self._cid
def mapped_port(self, port):
return docker_mapped_port(self.cid(), port)
def kill(self, suppress_failure=False):
"""Sends kill signal to the container."""
if suppress_failure:
self._job.suppress_failure_message()
return subprocess.call(['docker','kill', self.cid()]) == 0
def is_running(self):
"""Polls a job and returns True if given job is still running."""
return self._job.state(jobset.NoCache()) == jobset._RUNNING

@ -180,6 +180,7 @@ class Job(object):
name=self._spec.shortname) if xml_report is not None else None
self._retries = 0
self._timeout_retries = 0
self._suppress_failure_message = False
message('START', spec.shortname, do_newline=self._travis)
self.start()
@ -220,6 +221,7 @@ class Job(object):
self.start()
else:
self._state = _FAILURE
if not self._suppress_failure_message:
message('FAILED', '%s [ret=%d, pid=%d]' % (
self._spec.shortname, self._process.returncode, self._process.pid),
stdout, do_newline=True)
@ -254,6 +256,9 @@ class Job(object):
self._state = _KILLED
self._process.terminate()
def suppress_failure_message(self):
self._suppress_failure_message = True
class Jobset(object):
"""Manages one run of jobs."""

@ -31,14 +31,22 @@
"""Run interop (cross-language) tests in parallel."""
import argparse
import dockerjob
import itertools
import xml.etree.cElementTree as ET
import jobset
import multiprocessing
import os
import subprocess
import sys
import tempfile
import time
import uuid
ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
os.chdir(ROOT)
_DEFAULT_SERVER_PORT=8080
_CLOUD_TO_PROD_BASE_ARGS = [
'--server_host_override=grpc-test.sandbox.google.com',
@ -54,12 +62,15 @@ _CLOUD_TO_CLOUD_BASE_ARGS = [
_SSL_CERT_ENV = { 'SSL_CERT_FILE':'/usr/local/share/grpc/roots.pem' }
# TODO(jtatttermusch) unify usage of --use_tls and --use_tls=true
# TODO(jtatttermusch) unify usage of --use_prod_roots and --use_test_ca
class CXXLanguage:
def __init__(self):
self.client_cmdline_base = ['bins/opt/interop_client']
self.client_cwd = None
self.server_cwd = None
def cloud_to_prod_args(self):
return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@ -72,6 +83,9 @@ class CXXLanguage:
def cloud_to_prod_env(self):
return None
def server_args(self):
return ['bins/opt/interop_server', '--use_tls=true']
def __str__(self):
return 'c++'
@ -81,6 +95,7 @@ class CSharpLanguage:
def __init__(self):
self.client_cmdline_base = ['mono', 'Grpc.IntegrationTesting.Client.exe']
self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug'
self.server_cwd = 'src/csharp/Grpc.IntegrationTesting.Server/bin/Debug'
def cloud_to_prod_args(self):
return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@ -93,15 +108,44 @@ class CSharpLanguage:
def cloud_to_prod_env(self):
return _SSL_CERT_ENV
def server_args(self):
return ['mono', 'Grpc.IntegrationTesting.Server.exe', '--use_tls']
def __str__(self):
return 'csharp'
class JavaLanguage:
def __init__(self):
self.client_cmdline_base = ['./run-test-client.sh']
self.client_cwd = '../grpc-java'
self.server_cwd = '../grpc-java'
def cloud_to_prod_args(self):
return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
['--use_tls=true'])
def cloud_to_cloud_args(self):
return (self.client_cmdline_base + _CLOUD_TO_CLOUD_BASE_ARGS +
['--use_tls=true', '--use_test_ca=true'])
def cloud_to_prod_env(self):
return None
def server_args(self):
return ['./run-test-server.sh', '--use_tls=true']
def __str__(self):
return 'java'
class NodeLanguage:
def __init__(self):
self.client_cmdline_base = ['node', 'src/node/interop/interop_client.js']
self.client_cwd = None
self.server_cwd = None
def cloud_to_prod_args(self):
return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@ -114,6 +158,9 @@ class NodeLanguage:
def cloud_to_prod_env(self):
return _SSL_CERT_ENV
def server_args(self):
return ['node', 'src/node/interop/interop_server.js', '--use_tls=true']
def __str__(self):
return 'node'
@ -144,6 +191,7 @@ class RubyLanguage:
def __init__(self):
self.client_cmdline_base = ['ruby', 'src/ruby/bin/interop/interop_client.rb']
self.client_cwd = None
self.server_cwd = None
def cloud_to_prod_args(self):
return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
@ -156,14 +204,18 @@ class RubyLanguage:
def cloud_to_prod_env(self):
return _SSL_CERT_ENV
def server_args(self):
return ['ruby', 'src/ruby/bin/interop/interop_server.rb', '--use_tls']
def __str__(self):
return 'ruby'
# TODO(jtattermusch): add php and python once we get them working
# TODO(jtattermusch): python once we get it working
_LANGUAGES = {
'c++' : CXXLanguage(),
'csharp' : CSharpLanguage(),
'java' : JavaLanguage(),
'node' : NodeLanguage(),
'php' : PHPLanguage(),
'ruby' : RubyLanguage(),
@ -171,49 +223,132 @@ _LANGUAGES = {
# languages supported as cloud_to_cloud servers
# TODO(jtattermusch): enable other languages as servers as well
_SERVERS = { 'c++' : 8010, 'node' : 8040, 'csharp': 8070 }
_SERVERS = ['c++', 'node', 'csharp', 'java']
# TODO(jtattermusch): add empty_stream once C++ start supporting it.
# TODO(jtattermusch): add empty_stream once PHP starts supporting it.
# TODO(jtattermusch): add timeout_on_sleeping_server once java starts supporting it.
# TODO(jtattermusch): add support for auth tests.
_TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
'client_streaming', 'server_streaming',
'cancel_after_begin', 'cancel_after_first_response',
'timeout_on_sleeping_server']
'cancel_after_begin', 'cancel_after_first_response']
def cloud_to_prod_jobspec(language, test_case):
def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None):
"""Wraps given cmdline array to create 'docker run' cmdline from it."""
docker_cmdline = ['docker', 'run', '-i', '--rm=true']
# turn environ into -e docker args
if environ:
for k,v in environ.iteritems():
docker_cmdline += ['-e', '%s=%s' % (k,v)]
# set working directory
workdir = '/var/local/git/grpc'
if cwd:
workdir = os.path.join(workdir, cwd)
docker_cmdline += ['-w', workdir]
docker_cmdline += docker_args + [image] + cmdline
return docker_cmdline
def bash_login_cmdline(cmdline):
"""Creates bash -l -c cmdline from args list."""
# Use login shell:
# * rvm and nvm require it
# * makes error messages clearer if executables are missing
return ['bash', '-l', '-c', ' '.join(cmdline)]
def cloud_to_prod_jobspec(language, test_case, docker_image=None):
"""Creates jobspec for cloud-to-prod interop test"""
cmdline = language.cloud_to_prod_args() + ['--test_case=%s' % test_case]
cmdline = bash_login_cmdline(language.cloud_to_prod_args() +
['--test_case=%s' % test_case])
cwd = language.client_cwd
environ = language.cloud_to_prod_env()
if docker_image:
cmdline = docker_run_cmdline(cmdline, image=docker_image, cwd=cwd, environ=environ)
cwd = None
environ = None
test_job = jobset.JobSpec(
cmdline=cmdline,
cwd=language.client_cwd,
cwd=cwd,
environ=environ,
shortname="cloud_to_prod:%s:%s" % (language, test_case),
environ=language.cloud_to_prod_env(),
timeout_seconds=60)
timeout_seconds=2*60,
flake_retries=5 if args.allow_flakes else 0,
timeout_retries=2 if args.allow_flakes else 0)
return test_job
def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
server_port):
server_port, docker_image=None):
"""Creates jobspec for cloud-to-cloud interop test"""
cmdline = language.cloud_to_cloud_args() + ['--test_case=%s' % test_case,
cmdline = bash_login_cmdline(language.cloud_to_cloud_args() +
['--test_case=%s' % test_case,
'--server_host=%s' % server_host,
'--server_port=%s' % server_port ]
'--server_port=%s' % server_port ])
cwd = language.client_cwd
if docker_image:
cmdline = docker_run_cmdline(cmdline,
image=docker_image,
cwd=cwd,
docker_args=['--net=host'])
cwd = None
test_job = jobset.JobSpec(
cmdline=cmdline,
cwd=language.client_cwd,
cwd=cwd,
shortname="cloud_to_cloud:%s:%s_server:%s" % (language, server_name,
test_case),
timeout_seconds=60)
timeout_seconds=2*60,
flake_retries=5 if args.allow_flakes else 0,
timeout_retries=2 if args.allow_flakes else 0)
return test_job
def server_jobspec(language, docker_image):
"""Create jobspec for running a server"""
cidfile = tempfile.mktemp()
cmdline = bash_login_cmdline(language.server_args() +
['--port=%s' % _DEFAULT_SERVER_PORT])
docker_cmdline = docker_run_cmdline(cmdline,
image=docker_image,
cwd=language.server_cwd,
docker_args=['-p', str(_DEFAULT_SERVER_PORT),
'--cidfile', cidfile])
server_job = jobset.JobSpec(
cmdline=docker_cmdline,
shortname="interop_server:%s" % language,
timeout_seconds=30*60)
server_job.cidfile = cidfile
return server_job
def build_interop_image_jobspec(language, tag=None):
"""Creates jobspec for building interop docker image for a language"""
safelang = str(language).replace("+", "x")
if not tag:
tag = 'grpc_interop_%s:%s' % (safelang, uuid.uuid4())
env = {'INTEROP_IMAGE': tag, 'BASE_NAME': 'grpc_interop_%s' % safelang}
if not args.travis:
env['TTY_FLAG'] = '-t'
build_job = jobset.JobSpec(
cmdline=['tools/jenkins/build_interop_image.sh'],
environ=env,
shortname="build_docker_%s" % (language),
timeout_seconds=30*60)
build_job.tag = tag
return build_job
argp = argparse.ArgumentParser(description='Run interop tests.')
argp.add_argument('-l', '--language',
choices=['all'] + sorted(_LANGUAGES),
nargs='+',
default=['all'],
help='Clients to run.')
argp.add_argument('-j', '--jobs', default=24, type=int)
argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
argp.add_argument('--cloud_to_prod',
default=False,
action='store_const',
@ -242,9 +377,14 @@ argp.add_argument('--use_docker',
help='Run all the interop tests under docker. That provides ' +
'additional isolation and prevents the need to install ' +
'language specific prerequisites. Only available on Linux.')
argp.add_argument('--allow_flakes',
default=False,
action='store_const',
const=True,
help="Allow flaky tests to show as passing (re-runs failed tests up to five times)")
args = argp.parse_args()
servers = set(s for s in itertools.chain.from_iterable(_SERVERS.iterkeys()
servers = set(s for s in itertools.chain.from_iterable(_SERVERS
if x == 'all' else [x]
for x in args.server))
@ -257,52 +397,63 @@ if args.use_docker:
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_interop_tests.py %s' %
" ".join(child_argv[1:]))
# cmdline args to pass to the container running servers.
servers_extra_docker_args = ''
server_port_tuples = ''
for server in servers:
port = _SERVERS[server]
servers_extra_docker_args += ' -p %s' % port
servers_extra_docker_args += ' -e SERVER_PORT_%s=%s' % (server.replace("+", "x"), port)
server_port_tuples += ' %s:%s' % (server, port)
env = os.environ.copy()
env['RUN_TESTS_COMMAND'] = run_tests_cmd
env['SERVERS_DOCKER_EXTRA_ARGS'] = servers_extra_docker_args
env['SERVER_PORT_TUPLES'] = server_port_tuples
if not args.travis:
env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
subprocess.check_call(['tools/jenkins/build_docker_and_run_interop_tests.sh'],
shell=True,
env=env)
sys.exit(0)
if not args.use_docker and servers:
print "Running interop servers is only supported with --use_docker option enabled."
sys.exit(1)
languages = set(_LANGUAGES[l]
for l in itertools.chain.from_iterable(
_LANGUAGES.iterkeys() if x == 'all' else [x]
for x in args.language))
jobs = []
if args.cloud_to_prod:
docker_images={}
if args.use_docker:
# languages for which to build docker images
languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] +
[s for s in servers]))
build_jobs = []
for l in languages_to_build:
job = build_interop_image_jobspec(l)
docker_images[str(l)] = job.tag
build_jobs.append(job)
if build_jobs:
jobset.message('START', 'Building interop docker images.', do_newline=True)
if jobset.run(build_jobs, newline_on_success=True, maxjobs=args.jobs):
jobset.message('SUCCESS', 'All docker images built successfully.', do_newline=True)
else:
jobset.message('FAILED', 'Failed to build interop docker images.', do_newline=True)
for image in docker_images.itervalues():
dockerjob.remove_image(image, skip_nonexistent=True)
exit(1);
# Start interop servers.
server_jobs={}
server_addresses={}
try:
for s in servers:
lang = str(s)
spec = server_jobspec(_LANGUAGES[lang], docker_images.get(lang))
job = dockerjob.DockerJob(spec)
server_jobs[lang] = job
server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT))
jobs = []
if args.cloud_to_prod:
for language in languages:
for test_case in _TEST_CASES:
test_job = cloud_to_prod_jobspec(language, test_case)
test_job = cloud_to_prod_jobspec(language, test_case,
docker_image=docker_images.get(str(language)))
jobs.append(test_job)
# default servers to "localhost" and the default port
server_addresses = dict((s, ("localhost", _SERVERS[s])) for s in servers)
for server in args.override_server:
for server in args.override_server:
server_name = server[0]
(server_host, server_port) = server[1].split(":")
(server_host, server_port) = server[1].split(':')
server_addresses[server_name] = (server_host, server_port)
for server_name, server_address in server_addresses.iteritems():
for server_name, server_address in server_addresses.iteritems():
(server_host, server_port) = server_address
for language in languages:
for test_case in _TEST_CASES:
@ -310,20 +461,35 @@ for server_name, server_address in server_addresses.iteritems():
test_case,
server_name,
server_host,
server_port)
server_port,
docker_image=docker_images.get(str(language)))
jobs.append(test_job)
if not jobs:
if not jobs:
print "No jobs to run."
for image in docker_images.itervalues():
dockerjob.remove_image(image, skip_nonexistent=True)
sys.exit(1)
root = ET.Element('testsuites')
testsuite = ET.SubElement(root, 'testsuite', id='1', package='grpc', name='tests')
root = ET.Element('testsuites')
testsuite = ET.SubElement(root, 'testsuite', id='1', package='grpc', name='tests')
if jobset.run(jobs, newline_on_success=True, maxjobs=args.jobs, xml_report=testsuite):
if jobset.run(jobs, newline_on_success=True, maxjobs=args.jobs, xml_report=testsuite):
jobset.message('SUCCESS', 'All tests passed', do_newline=True)
else:
else:
jobset.message('FAILED', 'Some tests failed', do_newline=True)
tree = ET.ElementTree(root)
tree.write('report.xml', encoding='UTF-8')
tree = ET.ElementTree(root)
tree.write('report.xml', encoding='UTF-8')
finally:
# Check if servers are still running.
for server, job in server_jobs.iteritems():
if not job.is_running():
print 'Server "%s" has exited prematurely.' % server
dockerjob.finish_jobs([j for j in server_jobs.itervalues()])
for image in docker_images.itervalues():
print 'Removing docker image %s' % image
dockerjob.remove_image(image)

Loading…
Cancel
Save