blob: 1008c6b6cf578a4eb6eb01fc547ee6a072327e8f [file] [log] [blame]
Nathaniel Manistaae4fbcd2015-09-23 16:29:44 +00001#!/usr/bin/env python2.7
Craig Tiller6169d5f2016-03-31 07:46:18 -07002# Copyright 2015, Google Inc.
Craig Tillerc2c79212015-02-16 12:00:01 -08003# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
Nicolas Nobleddef2462015-01-06 18:08:25 -080031"""Run tests in parallel."""
32
siddharthshukla0589e532016-07-07 16:08:01 +020033from __future__ import print_function
34
Nicolas Nobleddef2462015-01-06 18:08:25 -080035import argparse
Craig Tiller9279ac22016-01-20 17:05:23 -080036import ast
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070037import collections
Nicolas Nobleddef2462015-01-06 18:08:25 -080038import glob
39import itertools
Craig Tiller261dd982015-01-16 16:41:45 -080040import json
Nicolas Nobleddef2462015-01-06 18:08:25 -080041import multiprocessing
Craig Tiller1cc11db2015-01-15 22:50:50 -080042import os
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070043import os.path
Craig Tiller38fb8de2016-07-13 08:23:32 -070044import pipes
David Garcia Quintas79e389f2015-06-02 17:49:42 -070045import platform
46import random
Craig Tillerfe406ec2015-02-24 13:55:12 -080047import re
Craig Tiller82875232015-09-25 13:57:34 -070048import socket
David Garcia Quintas79e389f2015-06-02 17:49:42 -070049import subprocess
Nicolas Nobleddef2462015-01-06 18:08:25 -080050import sys
Craig Tillerf0a293e2015-10-12 10:05:50 -070051import tempfile
52import traceback
ctiller3040cb72015-01-07 12:13:17 -080053import time
siddharthshukla0589e532016-07-07 16:08:01 +020054from six.moves import urllib
Jan Tattermusch03c01062015-12-11 14:28:56 -080055import uuid
Nicolas Nobleddef2462015-01-06 18:08:25 -080056
Jan Tattermusch5c79a312016-12-20 11:02:50 +010057import python_utils.jobset as jobset
58import python_utils.report_utils as report_utils
59import python_utils.watch_dirs as watch_dirs
Nicolas Nobleddef2462015-01-06 18:08:25 -080060
Craig Tillerb361b4e2016-01-06 11:44:17 -080061
Jan Tattermusch3b5121b2016-02-22 17:41:05 -080062_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
63os.chdir(_ROOT)
Craig Tiller2cc2b842015-02-27 11:38:31 -080064
65
Craig Tiller8f18ee62016-07-18 08:00:33 -070066_FORCE_ENVIRON_FOR_WRAPPERS = {
67 'GRPC_VERBOSITY': 'DEBUG',
68}
Craig Tiller06805272015-06-11 14:46:47 -070069
70
Craig Tiller123f1372016-06-15 15:06:14 -070071_POLLING_STRATEGIES = {
Craig Tillere6684f42016-11-08 08:17:43 -080072 'linux': ['epoll', 'poll', 'poll-cv']
Craig Tiller123f1372016-06-15 15:06:14 -070073}
74
75
Craig Tillerd50993d2015-08-05 08:04:36 -070076def platform_string():
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +010077 return jobset.platform_string()
Craig Tillerd50993d2015-08-05 08:04:36 -070078
79
Craig Tiller38fb8de2016-07-13 08:23:32 -070080_DEFAULT_TIMEOUT_SECONDS = 5 * 60
81
82
Craig Tiller738c3342015-01-12 14:28:33 -080083# SimpleConfig: just compile with CONFIG=config, and run the binary to test
Craig Tillera0f85172016-01-20 15:56:06 -080084class Config(object):
Craig Tillerb50d1662015-01-15 17:28:21 -080085
murgatroid99c36f6ea2016-10-03 09:24:09 -070086 def __init__(self, config, environ=None, timeout_multiplier=1, tool_prefix=[], iomgr_platform='native'):
murgatroid99132ce6a2015-03-04 17:29:14 -080087 if environ is None:
88 environ = {}
Craig Tiller738c3342015-01-12 14:28:33 -080089 self.build_config = config
Craig Tiller547db2b2015-01-30 14:08:39 -080090 self.environ = environ
murgatroid99132ce6a2015-03-04 17:29:14 -080091 self.environ['CONFIG'] = config
Craig Tillera0f85172016-01-20 15:56:06 -080092 self.tool_prefix = tool_prefix
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -070093 self.timeout_multiplier = timeout_multiplier
murgatroid99c36f6ea2016-10-03 09:24:09 -070094 self.iomgr_platform = iomgr_platform
Craig Tiller738c3342015-01-12 14:28:33 -080095
Craig Tiller38fb8de2016-07-13 08:23:32 -070096 def job_spec(self, cmdline, timeout_seconds=_DEFAULT_TIMEOUT_SECONDS,
Craig Tillerde7edf82016-03-20 09:12:16 -070097 shortname=None, environ={}, cpu_cost=1.0, flaky=False):
Craig Tiller49f61322015-03-03 13:02:11 -080098 """Construct a jobset.JobSpec for a test under this config
99
100 Args:
101 cmdline: a list of strings specifying the command line the test
102 would like to run
Craig Tiller49f61322015-03-03 13:02:11 -0800103 """
Craig Tiller4fc90032015-05-21 10:39:52 -0700104 actual_environ = self.environ.copy()
siddharthshukla0589e532016-07-07 16:08:01 +0200105 for k, v in environ.items():
Craig Tiller4fc90032015-05-21 10:39:52 -0700106 actual_environ[k] = v
Craig Tillera0f85172016-01-20 15:56:06 -0800107 return jobset.JobSpec(cmdline=self.tool_prefix + cmdline,
Jan Tattermusch9a7d30c2015-04-23 16:12:55 -0700108 shortname=shortname,
Craig Tiller4fc90032015-05-21 10:39:52 -0700109 environ=actual_environ,
Craig Tiller56c6b6a2016-01-20 08:27:37 -0800110 cpu_cost=cpu_cost,
Craig Tiller94d04a52016-01-20 10:58:23 -0800111 timeout_seconds=(self.timeout_multiplier * timeout_seconds if timeout_seconds else None),
Craig Tillerde7edf82016-03-20 09:12:16 -0700112 flake_retries=5 if flaky or args.allow_flakes else 0,
Craig Tiller35505de2015-10-08 13:31:33 -0700113 timeout_retries=3 if args.allow_flakes else 0)
Craig Tiller738c3342015-01-12 14:28:33 -0800114
115
murgatroid99cf08daf2015-09-21 15:33:16 -0700116def get_c_tests(travis, test_lang) :
117 out = []
118 platforms_str = 'ci_platforms' if travis else 'platforms'
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100119 with open('tools/run_tests/generated/tests.json') as f:
murgatroid9989899b12015-09-22 09:14:48 -0700120 js = json.load(f)
murgatroid99a3e244f2015-09-22 11:25:53 -0700121 return [tgt
122 for tgt in js
123 if tgt['language'] == test_lang and
124 platform_string() in tgt[platforms_str] and
125 not (travis and tgt['flaky'])]
murgatroid99cf08daf2015-09-21 15:33:16 -0700126
murgatroid99fafeeb32015-09-22 09:13:03 -0700127
Jan Tattermusch77db4322016-02-20 20:19:35 -0800128def _check_compiler(compiler, supported_compilers):
129 if compiler not in supported_compilers:
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700130 raise Exception('Compiler %s not supported (on this platform).' % compiler)
131
132
133def _check_arch(arch, supported_archs):
134 if arch not in supported_archs:
135 raise Exception('Architecture %s not supported.' % arch)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800136
137
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800138def _is_use_docker_child():
139 """Returns True if running running as a --use_docker child."""
140 return True if os.getenv('RUN_TESTS_COMMAND') else False
141
142
siddharthshukla2135a1b2016-08-04 02:11:53 +0200143_PythonConfigVars = collections.namedtuple(
144 '_ConfigVars', ['shell', 'builder', 'builder_prefix_arguments',
145 'venv_relative_python', 'toolchain', 'runner'])
146
147
148def _python_config_generator(name, major, minor, bits, config_vars):
149 return PythonConfig(
150 name,
151 config_vars.shell + config_vars.builder + config_vars.builder_prefix_arguments + [
152 _python_pattern_function(major=major, minor=minor, bits=bits)] + [
153 name] + config_vars.venv_relative_python + config_vars.toolchain,
154 config_vars.shell + config_vars.runner + [
155 os.path.join(name, config_vars.venv_relative_python[0])])
156
157
158def _pypy_config_generator(name, major, config_vars):
159 return PythonConfig(
160 name,
161 config_vars.shell + config_vars.builder + config_vars.builder_prefix_arguments + [
162 _pypy_pattern_function(major=major)] + [
163 name] + config_vars.venv_relative_python + config_vars.toolchain,
164 config_vars.shell + config_vars.runner + [
165 os.path.join(name, config_vars.venv_relative_python[0])])
166
167
168def _python_pattern_function(major, minor, bits):
169 # Bit-ness is handled by the test machine's environment
170 if os.name == "nt":
171 if bits == "64":
172 return '/c/Python{major}{minor}/python.exe'.format(
173 major=major, minor=minor, bits=bits)
174 else:
175 return '/c/Python{major}{minor}_{bits}bits/python.exe'.format(
176 major=major, minor=minor, bits=bits)
177 else:
178 return 'python{major}.{minor}'.format(major=major, minor=minor)
179
180
181def _pypy_pattern_function(major):
182 if major == '2':
183 return 'pypy'
184 elif major == '3':
185 return 'pypy3'
186 else:
187 raise ValueError("Unknown PyPy major version")
188
189
Craig Tillerc7449162015-01-16 14:42:10 -0800190class CLanguage(object):
191
Craig Tillere9c959d2015-01-18 10:23:26 -0800192 def __init__(self, make_target, test_lang):
Craig Tillerc7449162015-01-16 14:42:10 -0800193 self.make_target = make_target
Craig Tillerd50993d2015-08-05 08:04:36 -0700194 self.platform = platform_string()
Craig Tiller711bbe62015-08-19 12:35:16 -0700195 self.test_lang = test_lang
Craig Tillerc7449162015-01-16 14:42:10 -0800196
Jan Tattermusch77db4322016-02-20 20:19:35 -0800197 def configure(self, config, args):
198 self.config = config
199 self.args = args
200 if self.platform == 'windows':
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800201 self._make_options = [_windows_toolset_option(self.args.compiler),
202 _windows_arch_option(self.args.arch)]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800203 else:
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800204 self._docker_distro, self._make_options = self._compiler_options(self.args.use_docker,
205 self.args.compiler)
murgatroid99c36f6ea2016-10-03 09:24:09 -0700206 if args.iomgr_platform == "uv":
207 cflags = '-DGRPC_UV '
208 try:
209 cflags += subprocess.check_output(['pkg-config', '--cflags', 'libuv']).strip() + ' '
murgatroid991687cab2016-10-11 11:42:01 -0700210 except (subprocess.CalledProcessError, OSError):
murgatroid99c36f6ea2016-10-03 09:24:09 -0700211 pass
212 try:
213 ldflags = subprocess.check_output(['pkg-config', '--libs', 'libuv']).strip() + ' '
murgatroid991687cab2016-10-11 11:42:01 -0700214 except (subprocess.CalledProcessError, OSError):
murgatroid99c36f6ea2016-10-03 09:24:09 -0700215 ldflags = '-luv '
216 self._make_options += ['EXTRA_CPPFLAGS={}'.format(cflags),
217 'EXTRA_LDLIBS={}'.format(ldflags)]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800218
219 def test_specs(self):
Craig Tiller547db2b2015-01-30 14:08:39 -0800220 out = []
Jan Tattermusch77db4322016-02-20 20:19:35 -0800221 binaries = get_c_tests(self.args.travis, self.test_lang)
Craig Tiller946ce7a2016-04-06 10:35:58 -0700222 for target in binaries:
Craig Tiller123f1372016-06-15 15:06:14 -0700223 polling_strategies = (_POLLING_STRATEGIES.get(self.platform, ['all'])
Craig Tiller946ce7a2016-04-06 10:35:58 -0700224 if target.get('uses_polling', True)
225 else ['all'])
murgatroid992c287ca2016-10-07 09:55:35 -0700226 if self.args.iomgr_platform == 'uv':
227 polling_strategies = ['all']
Craig Tiller946ce7a2016-04-06 10:35:58 -0700228 for polling_strategy in polling_strategies:
229 env={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
230 _ROOT + '/src/core/lib/tsi/test_creds/ca.pem',
Craig Tiller8f18ee62016-07-18 08:00:33 -0700231 'GRPC_POLL_STRATEGY': polling_strategy,
232 'GRPC_VERBOSITY': 'DEBUG'}
Craig Tiller38fb8de2016-07-13 08:23:32 -0700233 shortname_ext = '' if polling_strategy=='all' else ' GRPC_POLL_STRATEGY=%s' % polling_strategy
Craig Tillerbc28cd62016-12-02 13:52:21 -0800234 timeout_scaling = 1
235 if polling_strategy == 'poll-cv':
236 timeout_scaling *= 5
Craig Tillerb38197e2016-02-26 10:14:54 -0800237 if self.config.build_config in target['exclude_configs']:
238 continue
murgatroid99c36f6ea2016-10-03 09:24:09 -0700239 if self.args.iomgr_platform in target.get('exclude_iomgrs', []):
240 continue
Craig Tillerb38197e2016-02-26 10:14:54 -0800241 if self.platform == 'windows':
242 binary = 'vsprojects/%s%s/%s.exe' % (
243 'x64/' if self.args.arch == 'x64' else '',
244 _MSBUILD_CONFIG[self.config.build_config],
245 target['name'])
Craig Tillerca62ff02016-02-24 22:22:57 -0800246 else:
Craig Tillerb38197e2016-02-26 10:14:54 -0800247 binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
Craig Tillerab34b122016-11-28 13:19:12 -0800248 cpu_cost = target['cpu_cost']
249 if cpu_cost == 'capacity':
250 cpu_cost = multiprocessing.cpu_count()
Craig Tillerb38197e2016-02-26 10:14:54 -0800251 if os.path.isfile(binary):
252 if 'gtest' in target and target['gtest']:
253 # here we parse the output of --gtest_list_tests to build up a
254 # complete list of the tests contained in a binary
255 # for each test, we then add a job to run, filtering for just that
256 # test
257 with open(os.devnull, 'w') as fnull:
258 tests = subprocess.check_output([binary, '--gtest_list_tests'],
259 stderr=fnull)
260 base = None
261 for line in tests.split('\n'):
262 i = line.find('#')
263 if i >= 0: line = line[:i]
264 if not line: continue
265 if line[0] != ' ':
266 base = line.strip()
267 else:
268 assert base is not None
269 assert line[1] == ' '
270 test = base + line.strip()
271 cmdline = [binary] + ['--gtest_filter=%s' % test]
Craig Tiller38fb8de2016-07-13 08:23:32 -0700272 out.append(self.config.job_spec(cmdline,
273 shortname='%s --gtest_filter=%s %s' % (binary, test, shortname_ext),
Craig Tillerab34b122016-11-28 13:19:12 -0800274 cpu_cost=cpu_cost,
Craig Tillerbc28cd62016-12-02 13:52:21 -0800275 timeout_seconds=_DEFAULT_TIMEOUT_SECONDS * timeout_scaling,
Craig Tillerb38197e2016-02-26 10:14:54 -0800276 environ=env))
277 else:
278 cmdline = [binary] + target['args']
Craig Tiller38fb8de2016-07-13 08:23:32 -0700279 out.append(self.config.job_spec(cmdline,
280 shortname=' '.join(
281 pipes.quote(arg)
282 for arg in cmdline) +
283 shortname_ext,
Craig Tillerab34b122016-11-28 13:19:12 -0800284 cpu_cost=cpu_cost,
Craig Tillerc2278152016-03-21 08:59:54 -0700285 flaky=target.get('flaky', False),
Craig Tillerbc28cd62016-12-02 13:52:21 -0800286 timeout_seconds=target.get('timeout_seconds', _DEFAULT_TIMEOUT_SECONDS) * timeout_scaling,
Craig Tillerb38197e2016-02-26 10:14:54 -0800287 environ=env))
288 elif self.args.regex == '.*' or self.platform == 'windows':
siddharthshukla0589e532016-07-07 16:08:01 +0200289 print('\nWARNING: binary not found, skipping', binary)
Nicolas Noblee1445362015-05-11 17:40:26 -0700290 return sorted(out)
Craig Tillerc7449162015-01-16 14:42:10 -0800291
Jan Tattermusch77db4322016-02-20 20:19:35 -0800292 def make_targets(self):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800293 if self.platform == 'windows':
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700294 # don't build tools on windows just yet
295 return ['buildtests_%s' % self.make_target]
Craig Tiller7552f0f2015-06-19 17:46:20 -0700296 return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
Craig Tillerc7449162015-01-16 14:42:10 -0800297
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800298 def make_options(self):
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800299 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800300
murgatroid99256d3df2015-09-21 16:58:02 -0700301 def pre_build_steps(self):
Jan Tattermusch874aec02015-10-07 19:26:19 -0700302 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100303 return [['tools\\run_tests\\helper_scripts\\pre_build_c.bat']]
Jan Tattermusch874aec02015-10-07 19:26:19 -0700304 else:
305 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700306
Craig Tillerc7449162015-01-16 14:42:10 -0800307 def build_steps(self):
308 return []
309
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200310 def post_tests_steps(self):
311 if self.platform == 'windows':
312 return []
313 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100314 return [['tools/run_tests/helper_scripts/post_tests_c.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200315
murgatroid99a3e244f2015-09-22 11:25:53 -0700316 def makefile_name(self):
317 return 'Makefile'
318
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700319 def _clang_make_options(self, version_suffix=''):
320 return ['CC=clang%s' % version_suffix,
321 'CXX=clang++%s' % version_suffix,
322 'LD=clang%s' % version_suffix,
323 'LDXX=clang++%s' % version_suffix]
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800324
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700325 def _gcc_make_options(self, version_suffix):
326 return ['CC=gcc%s' % version_suffix,
327 'CXX=g++%s' % version_suffix,
328 'LD=gcc%s' % version_suffix,
329 'LDXX=g++%s' % version_suffix]
Jan Tattermusch9bb70622016-03-18 10:28:54 -0700330
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800331 def _compiler_options(self, use_docker, compiler):
332 """Returns docker distro and make options to use for given compiler."""
Jan Tattermuschfd3857b2016-06-03 12:24:03 -0700333 if not use_docker and not _is_use_docker_child():
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800334 _check_compiler(compiler, ['default'])
335
336 if compiler == 'gcc4.9' or compiler == 'default':
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800337 return ('jessie', [])
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800338 elif compiler == 'gcc4.4':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700339 return ('wheezy', self._gcc_make_options(version_suffix='-4.4'))
340 elif compiler == 'gcc4.6':
341 return ('wheezy', self._gcc_make_options(version_suffix='-4.6'))
Matt Kwong029ed102016-11-01 18:04:47 -0700342 elif compiler == 'gcc4.8':
Matt Kwong1347e402016-11-02 18:07:40 -0700343 return ('jessie', self._gcc_make_options(version_suffix='-4.8'))
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800344 elif compiler == 'gcc5.3':
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800345 return ('ubuntu1604', [])
346 elif compiler == 'clang3.4':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700347 # on ubuntu1404, clang-3.4 alias doesn't exist, just use 'clang'
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800348 return ('ubuntu1404', self._clang_make_options())
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700349 elif compiler == 'clang3.5':
350 return ('jessie', self._clang_make_options(version_suffix='-3.5'))
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800351 elif compiler == 'clang3.6':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700352 return ('ubuntu1604', self._clang_make_options(version_suffix='-3.6'))
353 elif compiler == 'clang3.7':
354 return ('ubuntu1604', self._clang_make_options(version_suffix='-3.7'))
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800355 else:
356 raise Exception('Compiler %s not supported.' % compiler)
357
Jan Tattermusch77db4322016-02-20 20:19:35 -0800358 def dockerfile_dir(self):
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800359 return 'tools/dockerfile/test/cxx_%s_%s' % (self._docker_distro,
360 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800361
murgatroid99132ce6a2015-03-04 17:29:14 -0800362 def __str__(self):
363 return self.make_target
364
Craig Tillercc0535d2015-12-08 15:14:47 -0800365
murgatroid992c8d5162015-01-26 10:41:21 -0800366class NodeLanguage(object):
367
Jan Tattermusche477b842016-02-06 22:19:01 -0800368 def __init__(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800369 self.platform = platform_string()
Jan Tattermusche477b842016-02-06 22:19:01 -0800370
Jan Tattermusch77db4322016-02-20 20:19:35 -0800371 def configure(self, config, args):
372 self.config = config
373 self.args = args
murgatroid999fab4382016-04-29 15:05:00 -0700374 _check_compiler(self.args.compiler, ['default', 'node0.12',
murgatroid9959792a32016-10-25 14:15:38 -0700375 'node4', 'node5', 'node6',
376 'node7'])
murgatroid999fab4382016-04-29 15:05:00 -0700377 if self.args.compiler == 'default':
378 self.node_version = '4'
379 else:
380 # Take off the word "node"
381 self.node_version = self.args.compiler[4:]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800382
383 def test_specs(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800384 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100385 return [self.config.job_spec(['tools\\run_tests\\helper_scripts\\run_node.bat'])]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800386 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100387 return [self.config.job_spec(['tools/run_tests/helper_scripts/run_node.sh', self.node_version],
Jan Tattermusch77db4322016-02-20 20:19:35 -0800388 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800389
murgatroid99256d3df2015-09-21 16:58:02 -0700390 def pre_build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800391 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100392 return [['tools\\run_tests\\helper_scripts\\pre_build_node.bat']]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800393 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100394 return [['tools/run_tests/helper_scripts/pre_build_node.sh', self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700395
Jan Tattermusch77db4322016-02-20 20:19:35 -0800396 def make_targets(self):
murgatroid99db5b1602015-10-01 13:20:11 -0700397 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800398
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800399 def make_options(self):
400 return []
401
murgatroid992c8d5162015-01-26 10:41:21 -0800402 def build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800403 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100404 return [['tools\\run_tests\\helper_scripts\\build_node.bat']]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800405 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100406 return [['tools/run_tests/helper_scripts/build_node.sh', self.node_version]]
Craig Tillerc7449162015-01-16 14:42:10 -0800407
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200408 def post_tests_steps(self):
409 return []
410
murgatroid99a3e244f2015-09-22 11:25:53 -0700411 def makefile_name(self):
412 return 'Makefile'
413
Jan Tattermusch77db4322016-02-20 20:19:35 -0800414 def dockerfile_dir(self):
415 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800416
murgatroid99132ce6a2015-03-04 17:29:14 -0800417 def __str__(self):
418 return 'node'
419
Craig Tiller99775822015-01-30 13:07:16 -0800420
Craig Tillerc7449162015-01-16 14:42:10 -0800421class PhpLanguage(object):
422
Jan Tattermusch77db4322016-02-20 20:19:35 -0800423 def configure(self, config, args):
424 self.config = config
425 self.args = args
426 _check_compiler(self.args.compiler, ['default'])
427
428 def test_specs(self):
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100429 return [self.config.job_spec(['src/php/bin/run_tests.sh'],
Jan Tattermusch77db4322016-02-20 20:19:35 -0800430 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800431
murgatroid99256d3df2015-09-21 16:58:02 -0700432 def pre_build_steps(self):
433 return []
434
Jan Tattermusch77db4322016-02-20 20:19:35 -0800435 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700436 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800437
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800438 def make_options(self):
439 return []
440
Craig Tillerc7449162015-01-16 14:42:10 -0800441 def build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100442 return [['tools/run_tests/helper_scripts/build_php.sh']]
Craig Tillerc7449162015-01-16 14:42:10 -0800443
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200444 def post_tests_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100445 return [['tools/run_tests/helper_scripts/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200446
murgatroid99a3e244f2015-09-22 11:25:53 -0700447 def makefile_name(self):
448 return 'Makefile'
449
Jan Tattermusch77db4322016-02-20 20:19:35 -0800450 def dockerfile_dir(self):
451 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800452
murgatroid99132ce6a2015-03-04 17:29:14 -0800453 def __str__(self):
454 return 'php'
455
Craig Tillerc7449162015-01-16 14:42:10 -0800456
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700457class Php7Language(object):
458
459 def configure(self, config, args):
460 self.config = config
461 self.args = args
462 _check_compiler(self.args.compiler, ['default'])
463
464 def test_specs(self):
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100465 return [self.config.job_spec(['src/php/bin/run_tests.sh'],
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700466 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
467
468 def pre_build_steps(self):
469 return []
470
471 def make_targets(self):
472 return ['static_c', 'shared_c']
473
474 def make_options(self):
475 return []
476
477 def build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100478 return [['tools/run_tests/helper_scripts/build_php.sh']]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700479
480 def post_tests_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100481 return [['tools/run_tests/helper_scripts/post_tests_php.sh']]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700482
483 def makefile_name(self):
484 return 'Makefile'
485
486 def dockerfile_dir(self):
487 return 'tools/dockerfile/test/php7_jessie_%s' % _docker_arch_suffix(self.args.arch)
488
489 def __str__(self):
490 return 'php7'
491
492
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700493class PythonConfig(collections.namedtuple('PythonConfig', [
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700494 'name', 'build', 'run'])):
495 """Tuple of commands (named s.t. 'what it says on the tin' applies)"""
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700496
Nathaniel Manista840615e2015-01-22 20:31:47 +0000497class PythonLanguage(object):
498
Jan Tattermusch77db4322016-02-20 20:19:35 -0800499 def configure(self, config, args):
500 self.config = config
501 self.args = args
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700502 self.pythons = self._get_pythons(self.args)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800503
504 def test_specs(self):
Jan Tattermusch072ebaa2016-03-01 18:33:12 -0800505 # load list of known test suites
Masood Malekghassemi1ff429d2016-06-02 16:39:20 -0700506 with open('src/python/grpcio_tests/tests/tests.json') as tests_json_file:
Jan Tattermusch072ebaa2016-03-01 18:33:12 -0800507 tests_json = json.load(tests_json_file)
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700508 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700509 return [self.config.job_spec(
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700510 config.run,
Masood Malekghassemie6a23e22016-06-28 13:58:42 -0700511 timeout_seconds=5*60,
siddharthshukla0589e532016-07-07 16:08:01 +0200512 environ=dict(list(environment.items()) +
Masood Malekghassemic4f5a2e2016-12-05 15:54:56 -0800513 [('GRPC_PYTHON_TESTRUNNER_FILTER', str(suite_name))]),
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700514 shortname='%s.test.%s' % (config.name, suite_name),)
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700515 for suite_name in tests_json
516 for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000517
murgatroid99256d3df2015-09-21 16:58:02 -0700518 def pre_build_steps(self):
519 return []
520
Jan Tattermusch77db4322016-02-20 20:19:35 -0800521 def make_targets(self):
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700522 return []
Nathaniel Manista840615e2015-01-22 20:31:47 +0000523
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800524 def make_options(self):
525 return []
526
Nathaniel Manista840615e2015-01-22 20:31:47 +0000527 def build_steps(self):
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700528 return [config.build for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000529
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200530 def post_tests_steps(self):
531 return []
532
murgatroid99a3e244f2015-09-22 11:25:53 -0700533 def makefile_name(self):
534 return 'Makefile'
535
Jan Tattermusch77db4322016-02-20 20:19:35 -0800536 def dockerfile_dir(self):
siddharthshuklac4782142016-06-28 18:48:47 +0200537 return 'tools/dockerfile/test/python_%s_%s' % (self.python_manager_name(), _docker_arch_suffix(self.args.arch))
538
539 def python_manager_name(self):
540 return 'pyenv' if self.args.compiler in ['python3.5', 'python3.6'] else 'jessie'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800541
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700542 def _get_pythons(self, args):
543 if args.arch == 'x86':
544 bits = '32'
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700545 else:
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700546 bits = '64'
siddharthshukla2135a1b2016-08-04 02:11:53 +0200547
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700548 if os.name == 'nt':
549 shell = ['bash']
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100550 builder = [os.path.abspath('tools/run_tests/helper_scripts/build_python_msys2.sh')]
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700551 builder_prefix_arguments = ['MINGW{}'.format(bits)]
552 venv_relative_python = ['Scripts/python.exe']
553 toolchain = ['mingw32']
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700554 else:
555 shell = []
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100556 builder = [os.path.abspath('tools/run_tests/helper_scripts/build_python.sh')]
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700557 builder_prefix_arguments = []
558 venv_relative_python = ['bin/python']
559 toolchain = ['unix']
siddharthshukla2135a1b2016-08-04 02:11:53 +0200560
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100561 runner = [os.path.abspath('tools/run_tests/helper_scripts/run_python.sh')]
siddharthshukla2135a1b2016-08-04 02:11:53 +0200562 config_vars = _PythonConfigVars(shell, builder, builder_prefix_arguments,
563 venv_relative_python, toolchain, runner)
564 python27_config = _python_config_generator(name='py27', major='2',
565 minor='7', bits=bits,
566 config_vars=config_vars)
567 python34_config = _python_config_generator(name='py34', major='3',
568 minor='4', bits=bits,
569 config_vars=config_vars)
570 python35_config = _python_config_generator(name='py35', major='3',
571 minor='5', bits=bits,
572 config_vars=config_vars)
573 python36_config = _python_config_generator(name='py36', major='3',
574 minor='6', bits=bits,
575 config_vars=config_vars)
576 pypy27_config = _pypy_config_generator(name='pypy', major='2',
577 config_vars=config_vars)
578 pypy32_config = _pypy_config_generator(name='pypy3', major='3',
579 config_vars=config_vars)
580
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700581 if args.compiler == 'default':
582 if os.name == 'nt':
583 return (python27_config,)
584 else:
585 return (python27_config, python34_config,)
586 elif args.compiler == 'python2.7':
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700587 return (python27_config,)
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700588 elif args.compiler == 'python3.4':
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700589 return (python34_config,)
siddharthshuklac4782142016-06-28 18:48:47 +0200590 elif args.compiler == 'python3.5':
591 return (python35_config,)
592 elif args.compiler == 'python3.6':
593 return (python36_config,)
siddharthshukla2135a1b2016-08-04 02:11:53 +0200594 elif args.compiler == 'pypy':
595 return (pypy27_config,)
596 elif args.compiler == 'pypy3':
597 return (pypy32_config,)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700598 else:
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700599 raise Exception('Compiler %s not supported.' % args.compiler)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700600
murgatroid99132ce6a2015-03-04 17:29:14 -0800601 def __str__(self):
602 return 'python'
603
Craig Tillerd625d812015-04-08 15:52:35 -0700604
murgatroid996a4c4fa2015-02-27 12:08:57 -0800605class RubyLanguage(object):
606
Jan Tattermusch77db4322016-02-20 20:19:35 -0800607 def configure(self, config, args):
608 self.config = config
609 self.args = args
610 _check_compiler(self.args.compiler, ['default'])
611
612 def test_specs(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100613 return [self.config.job_spec(['tools/run_tests/helper_scripts/run_ruby.sh'],
Jan Tattermusch77db4322016-02-20 20:19:35 -0800614 timeout_seconds=10*60,
615 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800616
murgatroid99256d3df2015-09-21 16:58:02 -0700617 def pre_build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100618 return [['tools/run_tests/helper_scripts/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700619
Jan Tattermusch4651bef2016-02-23 08:31:25 -0800620 def make_targets(self):
murgatroid997d243df2016-02-18 09:58:05 -0800621 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800622
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800623 def make_options(self):
624 return []
625
murgatroid996a4c4fa2015-02-27 12:08:57 -0800626 def build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100627 return [['tools/run_tests/helper_scripts/build_ruby.sh']]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800628
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200629 def post_tests_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100630 return [['tools/run_tests/helper_scripts/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200631
murgatroid99a3e244f2015-09-22 11:25:53 -0700632 def makefile_name(self):
633 return 'Makefile'
634
Jan Tattermusch77db4322016-02-20 20:19:35 -0800635 def dockerfile_dir(self):
636 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800637
murgatroid99132ce6a2015-03-04 17:29:14 -0800638 def __str__(self):
639 return 'ruby'
640
Craig Tillerd625d812015-04-08 15:52:35 -0700641
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800642class CSharpLanguage(object):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800643
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700644 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700645 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700646
Jan Tattermusch77db4322016-02-20 20:19:35 -0800647 def configure(self, config, args):
648 self.config = config
649 self.args = args
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700650 if self.platform == 'windows':
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700651 # Explicitly choosing between x86 and x64 arch doesn't work yet
652 _check_arch(self.args.arch, ['default'])
Jan Tattermusch6e2f88c2016-06-21 10:52:40 -0700653 # CoreCLR use 64bit runtime by default.
654 arch_option = 'x64' if self.args.compiler == 'coreclr' else self.args.arch
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700655 self._make_options = [_windows_toolset_option(self.args.compiler),
Jan Tattermusch6e2f88c2016-06-21 10:52:40 -0700656 _windows_arch_option(arch_option)]
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700657 else:
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700658 _check_compiler(self.args.compiler, ['default', 'coreclr'])
659 if self.platform == 'linux' and self.args.compiler == 'coreclr':
660 self._docker_distro = 'coreclr'
Jan Tattermusch743decd2016-06-21 11:40:47 -0700661 else:
662 self._docker_distro = 'jessie'
Jan Tattermusch76511a52016-06-17 14:00:57 -0700663
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700664 if self.platform == 'mac':
Jan Tattermusch2a322c22016-03-30 13:55:07 -0700665 # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
Jan Tattermusch6d082202016-06-21 10:03:38 -0700666 self._make_options = ['EMBED_OPENSSL=true']
667 if self.args.compiler != 'coreclr':
668 # On Mac, official distribution of mono is 32bit.
669 self._make_options += ['CFLAGS=-m32', 'LDFLAGS=-m32']
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700670 else:
671 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
Jan Tattermusch77db4322016-02-20 20:19:35 -0800672
673 def test_specs(self):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800674 with open('src/csharp/tests.json') as f:
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700675 tests_by_assembly = json.load(f)
Jan Tattermusch03c01062015-12-11 14:28:56 -0800676
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800677 msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700678 nunit_args = ['--labels=All']
Jan Tattermusch76511a52016-06-17 14:00:57 -0700679 assembly_subdir = 'bin/%s' % msbuild_config
680 assembly_extension = '.exe'
681
682 if self.args.compiler == 'coreclr':
Jan Tattermusch1f7ce192016-09-08 16:21:16 +0200683 assembly_subdir += '/netcoreapp1.0'
684 runtime_cmd = ['dotnet', 'exec']
685 assembly_extension = '.dll'
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700686 else:
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700687 nunit_args += ['--noresult', '--workers=1']
688 if self.platform == 'windows':
689 runtime_cmd = []
690 else:
691 runtime_cmd = ['mono']
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700692
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700693 specs = []
694 for assembly in tests_by_assembly.iterkeys():
Jan Tattermusch76511a52016-06-17 14:00:57 -0700695 assembly_file = 'src/csharp/%s/%s/%s%s' % (assembly,
696 assembly_subdir,
697 assembly,
698 assembly_extension)
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700699 if self.config.build_config != 'gcov' or self.platform != 'windows':
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700700 # normally, run each test as a separate process
701 for test in tests_by_assembly[assembly]:
702 cmdline = runtime_cmd + [assembly_file, '--test=%s' % test] + nunit_args
703 specs.append(self.config.job_spec(cmdline,
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700704 shortname='csharp.%s' % test,
705 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
706 else:
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700707 # For C# test coverage, run all tests from the same assembly at once
708 # using OpenCover.Console (only works on Windows).
709 cmdline = ['src\\csharp\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe',
710 '-target:%s' % assembly_file,
711 '-targetdir:src\\csharp',
712 '-targetargs:%s' % ' '.join(nunit_args),
713 '-filter:+[Grpc.Core]*',
714 '-register:user',
715 '-output:src\\csharp\\coverage_csharp_%s.xml' % assembly]
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700716
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700717 # set really high cpu_cost to make sure instances of OpenCover.Console run exclusively
718 # to prevent problems with registering the profiler.
719 run_exclusive = 1000000
Jan Tattermusch35e608f2016-04-09 16:35:06 -0700720 specs.append(self.config.job_spec(cmdline,
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700721 shortname='csharp.coverage.%s' % assembly,
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700722 cpu_cost=run_exclusive,
Jan Tattermusch77db4322016-02-20 20:19:35 -0800723 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700724 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800725
murgatroid99256d3df2015-09-21 16:58:02 -0700726 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700727 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100728 return [['tools\\run_tests\\helper_scripts\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700729 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100730 return [['tools/run_tests/helper_scripts/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700731
Jan Tattermusch77db4322016-02-20 20:19:35 -0800732 def make_targets(self):
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700733 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800734
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800735 def make_options(self):
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700736 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800737
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800738 def build_steps(self):
Jan Tattermusch76511a52016-06-17 14:00:57 -0700739 if self.args.compiler == 'coreclr':
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700740 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100741 return [['tools\\run_tests\\helper_scripts\\build_csharp_coreclr.bat']]
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700742 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100743 return [['tools/run_tests/helper_scripts/build_csharp_coreclr.sh']]
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700744 else:
Jan Tattermusch76511a52016-06-17 14:00:57 -0700745 if self.platform == 'windows':
746 return [[_windows_build_bat(self.args.compiler),
747 'src/csharp/Grpc.sln',
748 '/p:Configuration=%s' % _MSBUILD_CONFIG[self.config.build_config]]]
749 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100750 return [['tools/run_tests/helper_scripts/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000751
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200752 def post_tests_steps(self):
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700753 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100754 return [['tools\\run_tests\\helper_scripts\\post_tests_csharp.bat']]
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700755 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100756 return [['tools/run_tests/helper_scripts/post_tests_csharp.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200757
murgatroid99a3e244f2015-09-22 11:25:53 -0700758 def makefile_name(self):
759 return 'Makefile'
760
Jan Tattermusch77db4322016-02-20 20:19:35 -0800761 def dockerfile_dir(self):
Jan Tattermusch76511a52016-06-17 14:00:57 -0700762 return 'tools/dockerfile/test/csharp_%s_%s' % (self._docker_distro,
763 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800764
murgatroid99132ce6a2015-03-04 17:29:14 -0800765 def __str__(self):
766 return 'csharp'
767
Craig Tillerd625d812015-04-08 15:52:35 -0700768
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700769class ObjCLanguage(object):
770
Jan Tattermusch77db4322016-02-20 20:19:35 -0800771 def configure(self, config, args):
772 self.config = config
773 self.args = args
774 _check_compiler(self.args.compiler, ['default'])
775
776 def test_specs(self):
Jorge Canizales8a9fe2a2016-07-29 15:44:47 -0700777 return [
778 self.config.job_spec(['src/objective-c/tests/run_tests.sh'],
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100779 timeout_seconds=60*60,
Jorge Canizales8a9fe2a2016-07-29 15:44:47 -0700780 shortname='objc-tests',
781 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
782 self.config.job_spec(['src/objective-c/tests/build_example_test.sh'],
Nicolas "Pixel" Noble7f074e02016-08-11 21:00:08 +0200783 timeout_seconds=30*60,
Jorge Canizales8a9fe2a2016-07-29 15:44:47 -0700784 shortname='objc-examples-build',
785 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
786 ]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700787
murgatroid99256d3df2015-09-21 16:58:02 -0700788 def pre_build_steps(self):
789 return []
790
Jan Tattermusch77db4322016-02-20 20:19:35 -0800791 def make_targets(self):
Jorge Canizales6eade6d2016-07-11 00:34:14 -0700792 return ['interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700793
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800794 def make_options(self):
795 return []
796
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700797 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700798 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700799
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200800 def post_tests_steps(self):
801 return []
802
murgatroid99a3e244f2015-09-22 11:25:53 -0700803 def makefile_name(self):
804 return 'Makefile'
805
Jan Tattermusch77db4322016-02-20 20:19:35 -0800806 def dockerfile_dir(self):
Jan Tattermusch788ee232016-01-26 12:19:44 -0800807 return None
808
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700809 def __str__(self):
810 return 'objc'
811
812
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100813class Sanity(object):
814
Jan Tattermusch77db4322016-02-20 20:19:35 -0800815 def configure(self, config, args):
816 self.config = config
817 self.args = args
818 _check_compiler(self.args.compiler, ['default'])
819
820 def test_specs(self):
Craig Tiller94d04a52016-01-20 10:58:23 -0800821 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800822 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
Craig Tiller34226af2016-06-24 16:46:25 -0700823 return [self.config.job_spec(cmd['script'].split(),
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100824 timeout_seconds=30*60, environ={'TEST': 'true'},
Jan Tattermusch77db4322016-02-20 20:19:35 -0800825 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800826 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100827
murgatroid99256d3df2015-09-21 16:58:02 -0700828 def pre_build_steps(self):
829 return []
830
Jan Tattermusch77db4322016-02-20 20:19:35 -0800831 def make_targets(self):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100832 return ['run_dep_checks']
833
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800834 def make_options(self):
835 return []
836
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100837 def build_steps(self):
838 return []
839
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200840 def post_tests_steps(self):
841 return []
842
murgatroid99a3e244f2015-09-22 11:25:53 -0700843 def makefile_name(self):
844 return 'Makefile'
845
Jan Tattermusch77db4322016-02-20 20:19:35 -0800846 def dockerfile_dir(self):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800847 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800848
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100849 def __str__(self):
850 return 'sanity'
851
murgatroid99b53e5d12016-10-18 09:55:28 -0700852class NodeExpressLanguage(object):
853 """Dummy Node express test target to enable running express performance
854 benchmarks"""
855
856 def __init__(self):
857 self.platform = platform_string()
858
859 def configure(self, config, args):
860 self.config = config
861 self.args = args
862 _check_compiler(self.args.compiler, ['default', 'node0.12',
863 'node4', 'node5', 'node6'])
864 if self.args.compiler == 'default':
865 self.node_version = '4'
866 else:
867 # Take off the word "node"
868 self.node_version = self.args.compiler[4:]
869
870 def test_specs(self):
871 return []
872
873 def pre_build_steps(self):
874 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100875 return [['tools\\run_tests\\helper_scripts\\pre_build_node.bat']]
murgatroid99b53e5d12016-10-18 09:55:28 -0700876 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100877 return [['tools/run_tests/helper_scripts/pre_build_node.sh', self.node_version]]
murgatroid99b53e5d12016-10-18 09:55:28 -0700878
879 def make_targets(self):
880 return []
881
882 def make_options(self):
883 return []
884
885 def build_steps(self):
886 return []
887
888 def post_tests_steps(self):
889 return []
890
891 def makefile_name(self):
892 return 'Makefile'
893
894 def dockerfile_dir(self):
895 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
896
897 def __str__(self):
898 return 'node_express'
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200899
Craig Tiller738c3342015-01-12 14:28:33 -0800900# different configurations we can run under
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100901with open('tools/run_tests/generated/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800902 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800903
904
Craig Tillerc7449162015-01-16 14:42:10 -0800905_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800906 'c++': CLanguage('cxx', 'c++'),
907 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800908 'node': NodeLanguage(),
murgatroid99b53e5d12016-10-18 09:55:28 -0700909 'node_express': NodeExpressLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000910 'php': PhpLanguage(),
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700911 'php7': Php7Language(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000912 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800913 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100914 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700915 'objc' : ObjCLanguage(),
Jan Tattermusch70a57e42016-02-20 18:50:27 -0800916 'sanity': Sanity()
Craig Tillereb272bc2015-01-30 13:13:14 -0800917 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800918
Jan Tattermusch77db4322016-02-20 20:19:35 -0800919
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800920_MSBUILD_CONFIG = {
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700921 'dbg': 'Debug',
922 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800923 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700924 }
925
David Garcia Quintase90cd372015-05-31 18:15:26 -0700926
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800927def _windows_arch_option(arch):
928 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800929 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800930 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800931 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800932 return '/p:Platform=x64'
933 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200934 print('Architecture %s not supported.' % arch)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800935 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800936
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800937
938def _check_arch_option(arch):
939 """Checks that architecture option is valid."""
940 if platform_string() == 'windows':
941 _windows_arch_option(arch)
942 elif platform_string() == 'linux':
943 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800944 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800945 if arch == 'default':
946 return
947 elif runtime_arch == '64bit' and arch == 'x64':
948 return
949 elif runtime_arch == '32bit' and arch == 'x86':
950 return
951 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200952 print('Architecture %s does not match current runtime architecture.' % arch)
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800953 sys.exit(1)
954 else:
955 if args.arch != 'default':
siddharthshukla0589e532016-07-07 16:08:01 +0200956 print('Architecture %s not supported on current platform.' % args.arch)
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800957 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800958
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800959
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800960def _windows_build_bat(compiler):
961 """Returns name of build.bat for selected compiler."""
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700962 # For CoreCLR, fall back to the default compiler for C core
963 if compiler == 'default' or compiler == 'vs2013' or compiler == 'coreclr':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800964 return 'vsprojects\\build_vs2013.bat'
965 elif compiler == 'vs2015':
966 return 'vsprojects\\build_vs2015.bat'
967 elif compiler == 'vs2010':
968 return 'vsprojects\\build_vs2010.bat'
969 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200970 print('Compiler %s not supported.' % compiler)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800971 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800972
973
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800974def _windows_toolset_option(compiler):
975 """Returns msbuild PlatformToolset for selected compiler."""
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700976 # For CoreCLR, fall back to the default compiler for C core
977 if compiler == 'default' or compiler == 'vs2013' or compiler == 'coreclr':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800978 return '/p:PlatformToolset=v120'
979 elif compiler == 'vs2015':
980 return '/p:PlatformToolset=v140'
981 elif compiler == 'vs2010':
982 return '/p:PlatformToolset=v100'
983 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200984 print('Compiler %s not supported.' % compiler)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800985 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800986
987
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800988def _docker_arch_suffix(arch):
989 """Returns suffix to dockerfile dir to use."""
990 if arch == 'default' or arch == 'x64':
991 return 'x64'
992 elif arch == 'x86':
993 return 'x86'
994 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200995 print('Architecture %s not supported with current settings.' % arch)
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800996 sys.exit(1)
997
998
David Garcia Quintase90cd372015-05-31 18:15:26 -0700999def runs_per_test_type(arg_str):
1000 """Auxilary function to parse the "runs_per_test" flag.
1001
1002 Returns:
1003 A positive integer or 0, the latter indicating an infinite number of
1004 runs.
1005
1006 Raises:
1007 argparse.ArgumentTypeError: Upon invalid input.
1008 """
1009 if arg_str == 'inf':
1010 return 0
1011 try:
1012 n = int(arg_str)
1013 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -07001014 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -07001015 except:
Adele Zhoue4c35612015-10-16 15:34:23 -07001016 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -07001017 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001018
siddharthshukla2135a1b2016-08-04 02:11:53 +02001019
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001020# parse command line
1021argp = argparse.ArgumentParser(description='Run grpc tests.')
1022argp.add_argument('-c', '--config',
Jan Tattermusch77db4322016-02-20 20:19:35 -08001023 choices=sorted(_CONFIGS.keys()),
1024 default='opt')
David Garcia Quintase90cd372015-05-31 18:15:26 -07001025argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
1026 help='A positive integer or "inf". If "inf", all tests will run in an '
1027 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -08001028argp.add_argument('-r', '--regex', default='.*', type=str)
Vijay Pai488fd0e2016-06-13 12:37:12 -07001029argp.add_argument('--regex_exclude', default='', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -08001030argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -08001031argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -08001032argp.add_argument('-f', '--forever',
1033 default=False,
1034 action='store_const',
1035 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +01001036argp.add_argument('-t', '--travis',
1037 default=False,
1038 action='store_const',
1039 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001040argp.add_argument('--newline_on_success',
1041 default=False,
1042 action='store_const',
1043 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -08001044argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -07001045 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -08001046 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -07001047 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -07001048argp.add_argument('-S', '--stop_on_failure',
1049 default=False,
1050 action='store_const',
1051 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001052argp.add_argument('--use_docker',
1053 default=False,
1054 action='store_const',
1055 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -07001056 help='Run all the tests under docker. That provides ' +
1057 'additional isolation and prevents the need to install ' +
1058 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -07001059argp.add_argument('--allow_flakes',
1060 default=False,
1061 action='store_const',
1062 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -07001063 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001064argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -08001065 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001066 default='default',
1067 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
1068argp.add_argument('--compiler',
Jan Tattermuschc4cbe392016-02-22 19:29:38 -08001069 choices=['default',
Matt Kwong029ed102016-11-01 18:04:47 -07001070 'gcc4.4', 'gcc4.6', 'gcc4.8', 'gcc4.9', 'gcc5.3',
Jan Tattermusch6d258c52016-06-10 09:36:51 -07001071 'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7',
Jan Tattermusch825471c2016-04-25 16:52:25 -07001072 'vs2010', 'vs2013', 'vs2015',
siddharthshukla2135a1b2016-08-04 02:11:53 +02001073 'python2.7', 'python3.4', 'python3.5', 'python3.6', 'pypy', 'pypy3',
murgatroid995a3f8622016-10-26 13:45:04 -07001074 'node0.12', 'node4', 'node5', 'node6', 'node7',
Jan Tattermusch76511a52016-06-17 14:00:57 -07001075 'coreclr'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001076 default='default',
Jan Tattermusch77db4322016-02-20 20:19:35 -08001077 help='Selects compiler to use. Allowed values depend on the platform and language.')
murgatroid99c36f6ea2016-10-03 09:24:09 -07001078argp.add_argument('--iomgr_platform',
1079 choices=['native', 'uv'],
1080 default='native',
1081 help='Selects iomgr platform to build on')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001082argp.add_argument('--build_only',
1083 default=False,
1084 action='store_const',
1085 const=True,
1086 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -08001087argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
1088 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -08001089argp.add_argument('--update_submodules', default=[], nargs='*',
1090 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
1091 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -07001092argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001093argp.add_argument('-x', '--xml_report', default=None, type=str,
1094 help='Generates a JUnit-compatible XML report')
Jan Tattermuschcfcc0752016-10-09 17:02:34 +02001095argp.add_argument('--report_suite_name', default='tests', type=str,
1096 help='Test suite name to use in generated JUnit XML report')
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001097argp.add_argument('--quiet_success',
1098 default=False,
1099 action='store_const',
1100 const=True,
1101 help='Dont print anything when a test passes. Passing tests also will not be reported in XML report. ' +
1102 'Useful when running many iterations of each test (argument -n).')
Craig Tiller123f1372016-06-15 15:06:14 -07001103argp.add_argument('--force_default_poller', default=False, action='store_const', const=True,
1104 help='Dont try to iterate over many polling strategies when they exist')
Nicolas Nobleddef2462015-01-06 18:08:25 -08001105args = argp.parse_args()
1106
Craig Tiller123f1372016-06-15 15:06:14 -07001107if args.force_default_poller:
1108 _POLLING_STRATEGIES = {}
1109
Craig Tiller5f735a62016-01-20 09:31:15 -08001110jobset.measure_cpu_costs = args.measure_cpu_costs
1111
Craig Tiller1676f912016-01-05 10:49:44 -08001112# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -08001113need_to_regenerate_projects = False
1114for spec in args.update_submodules:
1115 spec = spec.split(':', 1)
1116 if len(spec) == 1:
1117 submodule = spec[0]
1118 branch = 'master'
1119 elif len(spec) == 2:
1120 submodule = spec[0]
1121 branch = spec[1]
1122 cwd = 'third_party/%s' % submodule
1123 def git(cmd, cwd=cwd):
siddharthshukla0589e532016-07-07 16:08:01 +02001124 print('in %s: git %s' % (cwd, cmd))
Craig Tillerb361b4e2016-01-06 11:44:17 -08001125 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
1126 git('fetch')
1127 git('checkout %s' % branch)
1128 git('pull origin %s' % branch)
1129 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
1130 need_to_regenerate_projects = True
1131if need_to_regenerate_projects:
1132 if jobset.platform_string() == 'linux':
1133 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
1134 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001135 print('WARNING: may need to regenerate projects, but since we are not on')
1136 print(' Linux this step is being skipped. Compilation MAY fail.')
Craig Tiller1676f912016-01-05 10:49:44 -08001137
1138
Nicolas Nobleddef2462015-01-06 18:08:25 -08001139# grab config
Jan Tattermusch77db4322016-02-20 20:19:35 -08001140run_config = _CONFIGS[args.config]
1141build_config = run_config.build_config
Craig Tillerf1973b02015-01-16 12:32:13 -08001142
Craig Tiller06805272015-06-11 14:46:47 -07001143if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -07001144 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -07001145
Adele Zhou6b9527c2015-11-20 15:56:35 -08001146if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -08001147 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -08001148else:
1149 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -08001150# We don't support code coverage on some languages
1151if 'gcov' in args.config:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001152 for bad in ['objc', 'sanity']:
Craig Tiller16900662016-01-07 19:30:54 -08001153 if bad in lang_list:
1154 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -08001155
1156languages = set(_LANGUAGES[l] for l in lang_list)
Jan Tattermusch77db4322016-02-20 20:19:35 -08001157for l in languages:
1158 l.configure(run_config, args)
murgatroid99132ce6a2015-03-04 17:29:14 -08001159
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001160language_make_options=[]
1161if any(language.make_options() for language in languages):
Adele Zhou3b6ab812016-05-18 17:04:20 -07001162 if not 'gcov' in args.config and len(languages) != 1:
siddharthshukla0589e532016-07-07 16:08:01 +02001163 print('languages with custom make options cannot be built simultaneously with other languages')
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001164 sys.exit(1)
1165 else:
1166 language_make_options = next(iter(languages)).make_options()
1167
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001168if args.use_docker:
1169 if not args.travis:
siddharthshukla0589e532016-07-07 16:08:01 +02001170 print('Seen --use_docker flag, will run tests under docker.')
1171 print('')
1172 print('IMPORTANT: The changes you are testing need to be locally committed')
1173 print('because only the committed changes in the current branch will be')
1174 print('copied to the docker environment.')
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001175 time.sleep(5)
1176
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001177 dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
1178 if len(dockerfile_dirs) > 1:
Adele Zhou9506ef22016-03-02 13:53:34 -08001179 if 'gcov' in args.config:
1180 dockerfile_dir = 'tools/dockerfile/test/multilang_jessie_x64'
1181 print ('Using multilang_jessie_x64 docker image for code coverage for '
1182 'all languages.')
1183 else:
1184 print ('Languages to be tested require running under different docker '
1185 'images.')
1186 sys.exit(1)
1187 else:
1188 dockerfile_dir = next(iter(dockerfile_dirs))
Craig Tillerde7edf82016-03-20 09:12:16 -07001189
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001190 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -08001191 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001192
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001193 env = os.environ.copy()
1194 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001195 env['DOCKERFILE_DIR'] = dockerfile_dir
Jan Tattermusch9835d4b2016-04-29 15:05:05 -07001196 env['DOCKER_RUN_SCRIPT'] = 'tools/run_tests/dockerize/docker_run_tests.sh'
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001197 if args.xml_report:
1198 env['XML_REPORT'] = args.xml_report
1199 if not args.travis:
1200 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
1201
Jan Tattermusch9835d4b2016-04-29 15:05:05 -07001202 subprocess.check_call(['tools/run_tests/dockerize/build_docker_and_run_tests.sh'],
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001203 shell=True,
1204 env=env)
1205 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -08001206
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001207_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001208
Jan Tattermuschfba65302016-01-25 18:21:14 -08001209def make_jobspec(cfg, targets, makefile='Makefile'):
1210 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -07001211 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -07001212 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -07001213 # empirically /m:2 gives the best performance/price and should prevent
1214 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -07001215 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -07001216 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -07001217 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -07001218 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001219 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -07001220 'vsprojects\\%s.sln' % target,
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001221 '/p:Configuration=%s' % _MSBUILD_CONFIG[cfg]] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001222 extra_args +
1223 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -08001224 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -07001225 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -08001226 else:
murgatroid998ae409f2015-10-26 16:39:00 -07001227 if targets:
1228 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
1229 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -08001230 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -08001231 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
1232 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001233 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -08001234 ([] if not args.travis else ['JENKINS_BUILD=1']) +
1235 targets,
Craig Tiller590105a2016-01-19 13:03:46 -08001236 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -07001237 else:
1238 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -08001239
murgatroid99a3e244f2015-09-22 11:25:53 -07001240make_targets = {}
1241for l in languages:
1242 makefile = l.makefile_name()
1243 make_targets[makefile] = make_targets.get(makefile, set()).union(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001244 set(l.make_targets()))
Craig Tiller5058c692015-04-08 09:42:04 -07001245
Jan Tattermusche4a69182015-12-15 09:53:01 -08001246def build_step_environ(cfg):
1247 environ = {'CONFIG': cfg}
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001248 msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -08001249 if msbuild_cfg:
1250 environ['MSBUILD_CONFIG'] = msbuild_cfg
1251 return environ
1252
murgatroid99fddac962015-09-22 09:20:11 -07001253build_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001254 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -07001255 for l in languages
1256 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -07001257if make_targets:
siddharthshukla0589e532016-07-07 16:08:01 +02001258 make_commands = itertools.chain.from_iterable(make_jobspec(build_config, list(targets), makefile) for (makefile, targets) in make_targets.items())
Craig Tiller6fd23842015-09-01 07:36:31 -07001259 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -07001260build_steps.extend(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001261 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), timeout_seconds=None)
Craig Tiller547db2b2015-01-30 14:08:39 -08001262 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -07001263 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -08001264
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001265post_tests_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001266 jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001267 for l in languages
1268 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -08001269runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -08001270forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -08001271
Nicolas Nobleddef2462015-01-06 18:08:25 -08001272
Ken Paysonfa51de52016-06-30 23:50:48 -07001273def _shut_down_legacy_server(legacy_server_port):
1274 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001275 version = int(urllib.request.urlopen(
Ken Paysonfa51de52016-06-30 23:50:48 -07001276 'http://localhost:%d/version_number' % legacy_server_port,
1277 timeout=10).read())
1278 except:
1279 pass
1280 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001281 urllib.request.urlopen(
Ken Paysonfa51de52016-06-30 23:50:48 -07001282 'http://localhost:%d/quitquitquit' % legacy_server_port).read()
1283
1284
Craig Tillerf53d9c82015-08-04 14:19:43 -07001285def _start_port_server(port_server_port):
1286 # check if a compatible port server is running
1287 # if incompatible (version mismatch) ==> start a new one
1288 # if not running ==> start a new one
1289 # otherwise, leave it up
1290 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001291 version = int(urllib.request.urlopen(
Craig Tillerfe4939f2015-10-06 12:55:36 -07001292 'http://localhost:%d/version_number' % port_server_port,
Jan Tattermusch292d0102016-06-28 10:29:41 -07001293 timeout=10).read())
siddharthshukla0589e532016-07-07 16:08:01 +02001294 print('detected port server running version %d' % version)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001295 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -07001296 except Exception as e:
siddharthshukla0589e532016-07-07 16:08:01 +02001297 print('failed to detect port server: %s' % sys.exc_info()[0])
1298 print(e.strerror)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001299 running = False
1300 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -07001301 current_version = int(subprocess.check_output(
Jan Tattermusch5c79a312016-12-20 11:02:50 +01001302 [sys.executable, os.path.abspath('tools/run_tests/python_utils/port_server.py'),
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001303 'dump_version']))
siddharthshukla0589e532016-07-07 16:08:01 +02001304 print('my port server is version %d' % current_version)
Craig Tillerfe4939f2015-10-06 12:55:36 -07001305 running = (version >= current_version)
1306 if not running:
siddharthshukla0589e532016-07-07 16:08:01 +02001307 print('port_server version mismatch: killing the old one')
1308 urllib.request.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
Craig Tillerfe4939f2015-10-06 12:55:36 -07001309 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001310 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001311 fd, logfile = tempfile.mkstemp()
1312 os.close(fd)
siddharthshukla0589e532016-07-07 16:08:01 +02001313 print('starting port_server, with log file %s' % logfile)
Jan Tattermusch5c79a312016-12-20 11:02:50 +01001314 args = [sys.executable, os.path.abspath('tools/run_tests/python_utils/port_server.py'),
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001315 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -07001316 env = dict(os.environ)
1317 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +01001318 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001319 # Working directory of port server needs to be outside of Jenkins
1320 # workspace to prevent file lock issues.
1321 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -07001322 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -07001323 args,
1324 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001325 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -07001326 creationflags = 0x00000008, # detached process
1327 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -07001328 else:
1329 port_server = subprocess.Popen(
1330 args,
Craig Tiller367d41d2015-10-12 13:00:22 -07001331 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -07001332 preexec_fn=os.setsid,
1333 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001334 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001335 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001336 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001337 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001338 if waits > 10:
siddharthshukla0589e532016-07-07 16:08:01 +02001339 print('killing port server due to excessive start up waits')
Craig Tillerabd37fd2015-08-26 07:54:01 -07001340 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001341 if port_server.poll() is not None:
siddharthshukla0589e532016-07-07 16:08:01 +02001342 print('port_server failed to start')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001343 # try one final time: maybe another build managed to start one
1344 time.sleep(1)
1345 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001346 urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
Craig Tillerf0a293e2015-10-12 10:05:50 -07001347 timeout=1).read()
siddharthshukla0589e532016-07-07 16:08:01 +02001348 print('last ditch attempt to contact port server succeeded')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001349 break
1350 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001351 traceback.print_exc()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001352 port_log = open(logfile, 'r').read()
siddharthshukla0589e532016-07-07 16:08:01 +02001353 print(port_log)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001354 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001355 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001356 urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
Craig Tillerabd37fd2015-08-26 07:54:01 -07001357 timeout=1).read()
siddharthshukla0589e532016-07-07 16:08:01 +02001358 print('port server is up and ready')
Craig Tillerf53d9c82015-08-04 14:19:43 -07001359 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001360 except socket.timeout:
siddharthshukla0589e532016-07-07 16:08:01 +02001361 print('waiting for port_server: timeout')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001362 traceback.print_exc();
1363 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001364 waits += 1
siddharthshukla0589e532016-07-07 16:08:01 +02001365 except urllib.error.URLError:
1366 print('waiting for port_server: urlerror')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001367 traceback.print_exc();
1368 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001369 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001370 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001371 traceback.print_exc()
Craig Tillerf53d9c82015-08-04 14:19:43 -07001372 port_server.kill()
1373 raise
1374
1375
Adele Zhoud5fffa52015-10-23 15:51:42 -07001376def _calculate_num_runs_failures(list_of_results):
1377 """Caculate number of runs and failures for a particular test.
1378
1379 Args:
1380 list_of_results: (List) of JobResult object.
1381 Returns:
1382 A tuple of total number of runs and failures.
1383 """
1384 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1385 num_failures = 0
1386 for jobresult in list_of_results:
1387 if jobresult.retries > 0:
1388 num_runs += jobresult.retries
1389 if jobresult.num_failures > 0:
1390 num_failures += jobresult.num_failures
1391 return num_runs, num_failures
1392
Adele Zhou6b9527c2015-11-20 15:56:35 -08001393
Craig Tillereb9de8b2016-01-08 08:57:41 -08001394# _build_and_run results
1395class BuildAndRunError(object):
1396
1397 BUILD = object()
1398 TEST = object()
1399 POST_TEST = object()
1400
1401
1402# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001403def _build_and_run(
Craig Tiller74189cd2016-06-23 15:39:06 -07001404 check_cancelled, newline_on_success, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001405 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001406 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001407 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001408 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001409 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001410 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001411 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001412
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001413 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001414 if xml_report:
Jan Tattermuschcfcc0752016-10-09 17:02:34 +02001415 report_utils.render_junit_xml_report(resultset, xml_report,
1416 suite_name=args.report_suite_name)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001417 return []
ctiller3040cb72015-01-07 12:13:17 -08001418
Craig Tiller234b6e72015-05-23 10:12:40 -07001419 # start antagonists
Jan Tattermusch5c79a312016-12-20 11:02:50 +01001420 antagonists = [subprocess.Popen(['tools/run_tests/python_utils/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001421 for _ in range(0, args.antagonists)]
Ken Paysonfa51de52016-06-30 23:50:48 -07001422 port_server_port = 32766
Craig Tillerf53d9c82015-08-04 14:19:43 -07001423 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001424 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001425 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001426 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001427 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001428 one_run = set(
1429 spec
yang-g6c1fdc62015-08-18 11:57:42 -07001430 for language in languages
Jan Tattermusch77db4322016-02-20 20:19:35 -08001431 for spec in language.test_specs()
Vijay Pai488fd0e2016-06-13 12:37:12 -07001432 if (re.search(args.regex, spec.shortname) and
1433 (args.regex_exclude == '' or
1434 not re.search(args.regex_exclude, spec.shortname))))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001435 # When running on travis, we want out test runs to be as similar as possible
1436 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001437 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001438 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1439 else:
1440 # whereas otherwise, we want to shuffle things up to give all tests a
1441 # chance to run.
1442 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1443 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001444 if infinite_runs:
1445 assert len(massaged_one_run) > 0, 'Must have at least one test for a -n inf run'
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001446 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1447 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001448 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001449
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001450 if args.quiet_success:
1451 jobset.message('START', 'Running tests quietly, only failing tests will be reported', do_newline=True)
Adele Zhou803af152015-11-30 15:16:16 -08001452 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001453 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001454 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001455 stop_on_failure=args.stop_on_failure,
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001456 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port},
1457 quiet_success=args.quiet_success)
Adele Zhoud5fffa52015-10-23 15:51:42 -07001458 if resultset:
Craig Tiller2b59dbc2016-05-13 15:59:09 -07001459 for k, v in sorted(resultset.items()):
Adele Zhoud5fffa52015-10-23 15:51:42 -07001460 num_runs, num_failures = _calculate_num_runs_failures(v)
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001461 if num_failures > 0:
1462 if num_failures == num_runs: # what about infinite_runs???
1463 jobset.message('FAILED', k, do_newline=True)
1464 else:
1465 jobset.message(
1466 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1467 do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001468 finally:
1469 for antagonist in antagonists:
1470 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001471 if xml_report and resultset:
Jan Tattermuschcfcc0752016-10-09 17:02:34 +02001472 report_utils.render_junit_xml_report(resultset, xml_report,
1473 suite_name=args.report_suite_name)
Craig Tillerd86a3942015-01-14 12:48:54 -08001474
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001475 number_failures, _ = jobset.run(
1476 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001477 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001478
1479 out = []
1480 if number_failures:
1481 out.append(BuildAndRunError.POST_TEST)
1482 if num_test_failures:
1483 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001484
Craig Tillereb9de8b2016-01-08 08:57:41 -08001485 return out
ctiller3040cb72015-01-07 12:13:17 -08001486
1487
1488if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001489 success = True
ctiller3040cb72015-01-07 12:13:17 -08001490 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001491 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001492 initial_time = dw.most_recent_change()
1493 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001494 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001495 errors = _build_and_run(check_cancelled=have_files_changed,
1496 newline_on_success=False,
Craig Tillereb9de8b2016-01-08 08:57:41 -08001497 build_only=args.build_only) == 0
1498 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001499 jobset.message('SUCCESS',
1500 'All tests are now passing properly',
1501 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001502 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001503 while not have_files_changed():
1504 time.sleep(1)
1505else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001506 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001507 newline_on_success=args.newline_on_success,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001508 xml_report=args.xml_report,
1509 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001510 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001511 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1512 else:
1513 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001514 exit_code = 0
1515 if BuildAndRunError.BUILD in errors:
1516 exit_code |= 1
Jan Tattermusche480a6a2016-10-07 12:59:08 +02001517 if BuildAndRunError.TEST in errors:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001518 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001519 if BuildAndRunError.POST_TEST in errors:
1520 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001521 sys.exit(exit_code)