From 95a137b692f38db6821fea8df499d258b657b6b7 Mon Sep 17 00:00:00 2001
From: Sree Kuchibhotla <sreek@google.com>
Date: Mon, 21 Mar 2016 11:10:42 -0700
Subject: [PATCH] Add build type option (asan/tsan/dbg or opt)

---
 .../dockerfile/gcp_api_libraries.include      |  4 ++
 .../Dockerfile.template                       | 40 ++++++++++++++
 .../grpc_interop_stress_cxx/Dockerfile        | 53 ++++++++++++++++---
 .../build_interop_stress.sh                   |  4 +-
 tools/jenkins/build_interop_stress_image.sh   |  7 ++-
 .../stress_test/run_stress_tests_on_gke.py    | 45 +++++++++++-----
 6 files changed, 128 insertions(+), 25 deletions(-)
 create mode 100644 templates/tools/dockerfile/gcp_api_libraries.include
 create mode 100644 templates/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile.template

diff --git a/templates/tools/dockerfile/gcp_api_libraries.include b/templates/tools/dockerfile/gcp_api_libraries.include
new file mode 100644
index 0000000000..669b0f887c
--- /dev/null
+++ b/templates/tools/dockerfile/gcp_api_libraries.include
@@ -0,0 +1,4 @@
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
+RUN pip install --upgrade google-api-python-client
+
diff --git a/templates/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile.template b/templates/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile.template
new file mode 100644
index 0000000000..b1049d0d7f
--- /dev/null
+++ b/templates/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile.template
@@ -0,0 +1,40 @@
+%YAML 1.2
+--- |
+  # Copyright 2015-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.
+  
+  FROM debian:jessie
+  
+  <%include file="../apt_get_basic.include"/>
+  <%include file="../ccache_setup.include"/>
+  <%include file="../cxx_deps.include"/>
+  <%include file="../gcp_api_libraries.include"/>
+  <%include file="../clang_update.include"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile b/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
index 4123cc1a26..214747fd4a 100644
--- a/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
+++ b/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
@@ -27,12 +27,9 @@
 # (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.
+# Install Git and basic packages.
 RUN apt-get update && apt-get install -y \
   autoconf \
   autotools-dev \
@@ -43,13 +40,16 @@ RUN apt-get update && apt-get install -y \
   gcc \
   gcc-multilib \
   git \
+  golang \
   gyp \
+  lcov \
   libc6 \
   libc6-dbg \
   libc6-dev \
   libgtest-dev \
   libtool \
   make \
+  perl \
   strace \
   python-dev \
   python-setuptools \
@@ -59,7 +59,9 @@ RUN apt-get update && apt-get install -y \
   wget \
   zip && apt-get clean
 
-RUN easy_install -U pip
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
@@ -69,12 +71,47 @@ 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
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
 
-# Google Cloud platform API libraries (for BigQuery)
+# Google Cloud platform API libraries
+RUN apt-get update && apt-get install -y python-pip && apt-get clean
 RUN pip install --upgrade google-api-python-client
 
+
+#=================
+# Update clang to a version with improved tsan
+
+RUN apt-get update && apt-get -y install python cmake && apt-get clean
+
+RUN git clone -n -b release_38 http://llvm.org/git/llvm.git && \
+  cd llvm && git checkout ad57503 && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/clang.git && \
+  cd clang && git checkout ad2c56e && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/compiler-rt.git && \
+  cd compiler-rt && git checkout 3176922 && cd ..
+RUN git clone -n -b release_38 \
+  http://llvm.org/git/clang-tools-extra.git && cd clang-tools-extra && \
+  git checkout c288525 && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/libcxx.git && \
+  cd libcxx && git checkout fda3549  && cd ..
+RUN git clone -n -b release_38 http://llvm.org/git/libcxxabi.git && \
+  cd libcxxabi && git checkout 8d4e51d && cd ..
+
+RUN mv clang llvm/tools
+RUN mv compiler-rt llvm/projects
+RUN mv clang-tools-extra llvm/tools/clang/tools
+RUN mv libcxx llvm/projects
+RUN mv libcxxabi llvm/projects
+
+RUN mkdir llvm-build
+RUN cd llvm-build && cmake \
+  -DCMAKE_BUILD_TYPE:STRING=Release \
+  -DCMAKE_INSTALL_PREFIX:STRING=/usr \
+  -DLLVM_TARGETS_TO_BUILD:STRING=X86 \
+  ../llvm
+RUN make -C llvm-build && make -C llvm-build install && rm -rf llvm-build
+
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh b/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
index 392bdfccda..470db4c13f 100755
--- a/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
+++ b/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
@@ -41,5 +41,7 @@ cd /var/local/git/grpc
 
 make install-certs
 
+BUILD_TYPE=${BUILD_TYPE:=opt}
+
 # build C++ interop stress client, interop client and server
-make stress_test metrics_client interop_client interop_server
+make CONFIG=$BUILD_TYPE stress_test metrics_client interop_client interop_server
diff --git a/tools/jenkins/build_interop_stress_image.sh b/tools/jenkins/build_interop_stress_image.sh
index 501dc5b7ca..b5dbcc5ce4 100755
--- a/tools/jenkins/build_interop_stress_image.sh
+++ b/tools/jenkins/build_interop_stress_image.sh
@@ -34,10 +34,12 @@
 set -x
 
 # Params:
-#  INTEROP_IMAGE - name of tag of the final interop image
+#  INTEROP_IMAGE - Name of tag of the final interop image
 #  INTEROP_IMAGE_TAG - Optional. If set, the created image will be tagged using
 #    the command: 'docker tag $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG'
-#  BASE_NAME - base name used to locate the base Dockerfile and build script
+#  BASE_NAME - Base name used to locate the base Dockerfile and build script
+#  BUILD_TYPE - The 'CONFIG' variable passed to the 'make' command (example:
+#  asan, tsan. Default value: opt).
 #  TTY_FLAG - optional -t flag to make docker allocate tty
 #  BUILD_INTEROP_DOCKER_EXTRA_ARGS - optional args to be passed to the
 #    docker run command
@@ -71,6 +73,7 @@ CONTAINER_NAME="build_${BASE_NAME}_$(uuidgen)"
 (docker run \
   -e CCACHE_DIR=/tmp/ccache \
   -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \
+  -e BUILD_TYPE=${BUILD_TYPE:=opt} \
   -i $TTY_FLAG \
   $MOUNT_ARGS \
   $BUILD_INTEROP_DOCKER_EXTRA_ARGS \
diff --git a/tools/run_tests/stress_test/run_stress_tests_on_gke.py b/tools/run_tests/stress_test/run_stress_tests_on_gke.py
index 634eb1aca5..79075f816c 100755
--- a/tools/run_tests/stress_test/run_stress_tests_on_gke.py
+++ b/tools/run_tests/stress_test/run_stress_tests_on_gke.py
@@ -122,9 +122,10 @@ class KubernetesProxy:
 
 class TestSettings:
 
-  def __init__(self, build_docker_image, test_poll_interval_secs,
+  def __init__(self, build_docker_image, build_type, test_poll_interval_secs,
                test_duration_secs, kubernetes_proxy_port):
     self.build_docker_image = build_docker_image
+    self.build_type = build_type
     self.test_poll_interval_secs = test_poll_interval_secs
     self.test_duration_secs = test_duration_secs
     self.kubernetes_proxy_port = kubernetes_proxy_port
@@ -149,17 +150,20 @@ class BigQuerySettings:
 
 class StressServerSettings:
 
-  def __init__(self, server_pod_name, server_port):
+  def __init__(self, build_type, server_pod_name, server_port):
+    self.build_type = build_type
     self.server_pod_name = server_pod_name
     self.server_port = server_port
 
 
 class StressClientSettings:
 
-  def __init__(self, num_clients, client_pod_name_prefix, server_pod_name,
-               server_port, metrics_port, metrics_collection_interval_secs,
+  def __init__(self, build_type, num_clients, client_pod_name_prefix,
+               server_pod_name, server_port, metrics_port,
+               metrics_collection_interval_secs,
                stress_client_poll_interval_secs, num_channels_per_server,
                num_stubs_per_channel, test_cases_str):
+    self.build_type = build_type
     self.num_clients = num_clients
     self.client_pod_name_prefix = client_pod_name_prefix
     self.server_pod_name = server_pod_name
@@ -181,7 +185,7 @@ class StressClientSettings:
                                   for i in range(1, num_clients + 1)]
 
 
-def _build_docker_image(image_name, tag_name):
+def _build_docker_image(image_name, tag_name, build_type):
   """ Build the docker image and add tag it to the GKE repository """
   print 'Building docker image: %s' % image_name
   os.environ['INTEROP_IMAGE'] = image_name
@@ -190,6 +194,7 @@ def _build_docker_image(image_name, tag_name):
   # build_interop_stress_image.sh invokes the following script:
   #   tools/dockerfile/$BASE_NAME/build_interop_stress.sh
   os.environ['BASE_NAME'] = 'grpc_interop_stress_cxx'
+  os.environ['BUILD_TYPE'] = build_type
   cmd = ['tools/jenkins/build_interop_stress_image.sh']
   retcode = subprocess.call(args=cmd)
   if retcode != 0:
@@ -226,9 +231,10 @@ def _launch_server(gke_settings, stress_server_settings, bq_settings,
 
   # The parameters to the script run_server.py are injected into the container
   # via environment variables
+  stress_test_image_path = '/var/local/git/grpc/bins/%s/interop_server' % stress_server_settings.build_type
   server_env = {
       'STRESS_TEST_IMAGE_TYPE': 'SERVER',
-      'STRESS_TEST_IMAGE': '/var/local/git/grpc/bins/opt/interop_server',
+      'STRESS_TEST_IMAGE': stress_test_image_path,
       'STRESS_TEST_ARGS_STR': '--port=%s' % stress_server_settings.server_port,
       'RUN_ID': bq_settings.run_id,
       'POD_NAME': stress_server_settings.server_pod_name,
@@ -285,11 +291,13 @@ def _launch_client(gke_settings, stress_server_settings, stress_client_settings,
 
   # The parameters to the script run_client.py are injected into the container
   # via environment variables
+  stress_test_image_path = '/var/local/git/grpc/bins/%s/stress_test' % stress_client_settings.build_type
+  metrics_client_image_path = '/var/local/git/grpc/bins/%s/metrics_client' % stress_client_settings.build_type
   client_env = {
       'STRESS_TEST_IMAGE_TYPE': 'CLIENT',
-      'STRESS_TEST_IMAGE': '/var/local/git/grpc/bins/opt/stress_test',
+      'STRESS_TEST_IMAGE': stress_test_image_path,
       'STRESS_TEST_ARGS_STR': ' '.join(stress_client_arg_list),
-      'METRICS_CLIENT_IMAGE': '/var/local/git/grpc/bins/opt/metrics_client',
+      'METRICS_CLIENT_IMAGE': metrics_client_image_path,
       'METRICS_CLIENT_ARGS_STR': ' '.join(metrics_client_arg_list),
       'RUN_ID': bq_settings.run_id,
       'POLL_INTERVAL_SECS':
@@ -384,7 +392,8 @@ def run_test_main(test_settings, gke_settings, stress_server_settings,
 
   if test_settings.build_docker_image:
     is_success = _build_docker_image(gke_settings.docker_image_name,
-                                     gke_settings.tag_name)
+                                     gke_settings.tag_name,
+                                     test_settings.build_type)
     if not is_success:
       return False
 
@@ -476,6 +485,11 @@ argp.add_argument('--do_not_build_docker_image',
                   'Registry')
 argp.set_defaults(build_docker_image=True)
 
+argp.add_argument('--build_type',
+                  choices=['opt', 'dbg', 'asan', 'tsan'],
+                  default='opt',
+                  help='The type of build i.e opt, dbg, asan or tsan.')
+
 argp.add_argument('--test_poll_interval_secs',
                   default=_DEFAULT_TEST_POLL_INTERVAL_SECS,
                   type=int,
@@ -537,16 +551,19 @@ if __name__ == '__main__':
   args = argp.parse_args()
 
   test_settings = TestSettings(
-      args.build_docker_image, args.test_poll_interval_secs,
+      args.build_docker_image, args.build_type, args.test_poll_interval_secs,
       args.test_duration_secs, args.kubernetes_proxy_port)
 
   gke_settings = GkeSettings(args.project_id, args.docker_image_name)
 
-  stress_server_settings = StressServerSettings(_SERVER_POD_NAME,
-                                                args.stress_server_port)
+  server_pod_name = "%s-%s" % (_SERVER_POD_NAME, args.build_type)
+  client_pod_name_prefix = "%s-%s" % (_CLIENT_POD_NAME_PREFIX, args.build_type)
+  stress_server_settings = StressServerSettings(
+      args.build_type, server_pod_name, args.stress_server_port)
   stress_client_settings = StressClientSettings(
-      args.num_clients, _CLIENT_POD_NAME_PREFIX, _SERVER_POD_NAME,
-      args.stress_server_port, args.stress_client_metrics_port,
+      args.build_type, args.num_clients, client_pod_name_prefix,
+      server_pod_name, args.stress_server_port,
+      args.stress_client_metrics_port,
       args.stress_client_metrics_collection_interval_secs,
       args.stress_client_poll_interval_secs,
       args.stress_client_num_channels_per_server,
-- 
GitLab