blob: 3698d1b8618fcd28e368e05ceeecec393b4b4528 [file] [log] [blame]
Tsuyoshi Ozawa4e0238d2016-09-20 05:56:10 +09001#!/usr/bin/env python
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
David Garcia Quintas0727c102017-02-21 10:48:35 -080041import logging
Nicolas Nobleddef2462015-01-06 18:08:25 -080042import multiprocessing
Craig Tiller1cc11db2015-01-15 22:50:50 -080043import os
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070044import os.path
Craig Tiller38fb8de2016-07-13 08:23:32 -070045import pipes
David Garcia Quintas79e389f2015-06-02 17:49:42 -070046import platform
47import random
Craig Tillerfe406ec2015-02-24 13:55:12 -080048import re
Craig Tiller82875232015-09-25 13:57:34 -070049import socket
David Garcia Quintas79e389f2015-06-02 17:49:42 -070050import subprocess
Nicolas Nobleddef2462015-01-06 18:08:25 -080051import sys
Craig Tillerf0a293e2015-10-12 10:05:50 -070052import tempfile
53import traceback
ctiller3040cb72015-01-07 12:13:17 -080054import time
siddharthshukla0589e532016-07-07 16:08:01 +020055from six.moves import urllib
Jan Tattermusch03c01062015-12-11 14:28:56 -080056import uuid
Siddharth Shuklad194f592017-03-11 19:12:43 +010057import six
Nicolas Nobleddef2462015-01-06 18:08:25 -080058
Jan Tattermusch5c79a312016-12-20 11:02:50 +010059import python_utils.jobset as jobset
60import python_utils.report_utils as report_utils
61import python_utils.watch_dirs as watch_dirs
Craig Tiller7dc4ea62017-02-02 16:08:05 -080062import python_utils.start_port_server as start_port_server
Nicolas Nobleddef2462015-01-06 18:08:25 -080063
Craig Tillerb361b4e2016-01-06 11:44:17 -080064
Jan Tattermusch3b5121b2016-02-22 17:41:05 -080065_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
66os.chdir(_ROOT)
Craig Tiller2cc2b842015-02-27 11:38:31 -080067
68
Craig Tiller8f18ee62016-07-18 08:00:33 -070069_FORCE_ENVIRON_FOR_WRAPPERS = {
70 'GRPC_VERBOSITY': 'DEBUG',
71}
Craig Tiller06805272015-06-11 14:46:47 -070072
73
Craig Tiller123f1372016-06-15 15:06:14 -070074_POLLING_STRATEGIES = {
Craig Tillereb73f802017-04-07 21:55:34 +000075 'linux': ['epollex', 'epoll', 'poll', 'poll-cv']
Craig Tiller123f1372016-06-15 15:06:14 -070076}
77
78
Craig Tillerd50993d2015-08-05 08:04:36 -070079def platform_string():
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +010080 return jobset.platform_string()
Craig Tillerd50993d2015-08-05 08:04:36 -070081
82
Craig Tiller38fb8de2016-07-13 08:23:32 -070083_DEFAULT_TIMEOUT_SECONDS = 5 * 60
84
David Garcia Quintas03920252017-02-15 12:51:21 -080085def run_shell_command(cmd, env=None, cwd=None):
86 try:
87 subprocess.check_output(cmd, shell=True, env=env, cwd=cwd)
88 except subprocess.CalledProcessError as e:
David Garcia Quintas0727c102017-02-21 10:48:35 -080089 logging.exception("Error while running command '%s'. Exit status %d. Output:\n%s",
90 e.cmd, e.returncode, e.output)
David Garcia Quintas03920252017-02-15 12:51:21 -080091 raise
Craig Tiller38fb8de2016-07-13 08:23:32 -070092
Craig Tiller738c3342015-01-12 14:28:33 -080093# SimpleConfig: just compile with CONFIG=config, and run the binary to test
Craig Tillera0f85172016-01-20 15:56:06 -080094class Config(object):
Craig Tillerb50d1662015-01-15 17:28:21 -080095
murgatroid99c36f6ea2016-10-03 09:24:09 -070096 def __init__(self, config, environ=None, timeout_multiplier=1, tool_prefix=[], iomgr_platform='native'):
murgatroid99132ce6a2015-03-04 17:29:14 -080097 if environ is None:
98 environ = {}
Craig Tiller738c3342015-01-12 14:28:33 -080099 self.build_config = config
Craig Tiller547db2b2015-01-30 14:08:39 -0800100 self.environ = environ
murgatroid99132ce6a2015-03-04 17:29:14 -0800101 self.environ['CONFIG'] = config
Craig Tillera0f85172016-01-20 15:56:06 -0800102 self.tool_prefix = tool_prefix
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -0700103 self.timeout_multiplier = timeout_multiplier
murgatroid99c36f6ea2016-10-03 09:24:09 -0700104 self.iomgr_platform = iomgr_platform
Craig Tiller738c3342015-01-12 14:28:33 -0800105
Craig Tiller38fb8de2016-07-13 08:23:32 -0700106 def job_spec(self, cmdline, timeout_seconds=_DEFAULT_TIMEOUT_SECONDS,
Craig Tillerde7edf82016-03-20 09:12:16 -0700107 shortname=None, environ={}, cpu_cost=1.0, flaky=False):
Craig Tiller49f61322015-03-03 13:02:11 -0800108 """Construct a jobset.JobSpec for a test under this config
109
110 Args:
111 cmdline: a list of strings specifying the command line the test
112 would like to run
Craig Tiller49f61322015-03-03 13:02:11 -0800113 """
Craig Tiller4fc90032015-05-21 10:39:52 -0700114 actual_environ = self.environ.copy()
siddharthshukla0589e532016-07-07 16:08:01 +0200115 for k, v in environ.items():
Craig Tiller4fc90032015-05-21 10:39:52 -0700116 actual_environ[k] = v
Craig Tillera0f85172016-01-20 15:56:06 -0800117 return jobset.JobSpec(cmdline=self.tool_prefix + cmdline,
Jan Tattermusch9a7d30c2015-04-23 16:12:55 -0700118 shortname=shortname,
Craig Tiller4fc90032015-05-21 10:39:52 -0700119 environ=actual_environ,
Craig Tiller56c6b6a2016-01-20 08:27:37 -0800120 cpu_cost=cpu_cost,
Craig Tiller94d04a52016-01-20 10:58:23 -0800121 timeout_seconds=(self.timeout_multiplier * timeout_seconds if timeout_seconds else None),
Craig Tillerde7edf82016-03-20 09:12:16 -0700122 flake_retries=5 if flaky or args.allow_flakes else 0,
Craig Tiller35505de2015-10-08 13:31:33 -0700123 timeout_retries=3 if args.allow_flakes else 0)
Craig Tiller738c3342015-01-12 14:28:33 -0800124
125
murgatroid99cf08daf2015-09-21 15:33:16 -0700126def get_c_tests(travis, test_lang) :
127 out = []
128 platforms_str = 'ci_platforms' if travis else 'platforms'
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100129 with open('tools/run_tests/generated/tests.json') as f:
murgatroid9989899b12015-09-22 09:14:48 -0700130 js = json.load(f)
murgatroid99a3e244f2015-09-22 11:25:53 -0700131 return [tgt
132 for tgt in js
133 if tgt['language'] == test_lang and
134 platform_string() in tgt[platforms_str] and
135 not (travis and tgt['flaky'])]
murgatroid99cf08daf2015-09-21 15:33:16 -0700136
murgatroid99fafeeb32015-09-22 09:13:03 -0700137
Jan Tattermusch77db4322016-02-20 20:19:35 -0800138def _check_compiler(compiler, supported_compilers):
139 if compiler not in supported_compilers:
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700140 raise Exception('Compiler %s not supported (on this platform).' % compiler)
141
142
143def _check_arch(arch, supported_archs):
144 if arch not in supported_archs:
145 raise Exception('Architecture %s not supported.' % arch)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800146
147
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800148def _is_use_docker_child():
149 """Returns True if running running as a --use_docker child."""
150 return True if os.getenv('RUN_TESTS_COMMAND') else False
151
152
siddharthshukla2135a1b2016-08-04 02:11:53 +0200153_PythonConfigVars = collections.namedtuple(
154 '_ConfigVars', ['shell', 'builder', 'builder_prefix_arguments',
155 'venv_relative_python', 'toolchain', 'runner'])
156
157
158def _python_config_generator(name, major, minor, bits, config_vars):
159 return PythonConfig(
160 name,
161 config_vars.shell + config_vars.builder + config_vars.builder_prefix_arguments + [
162 _python_pattern_function(major=major, minor=minor, bits=bits)] + [
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 _pypy_config_generator(name, major, config_vars):
169 return PythonConfig(
170 name,
171 config_vars.shell + config_vars.builder + config_vars.builder_prefix_arguments + [
172 _pypy_pattern_function(major=major)] + [
173 name] + config_vars.venv_relative_python + config_vars.toolchain,
174 config_vars.shell + config_vars.runner + [
175 os.path.join(name, config_vars.venv_relative_python[0])])
176
177
178def _python_pattern_function(major, minor, bits):
179 # Bit-ness is handled by the test machine's environment
180 if os.name == "nt":
181 if bits == "64":
182 return '/c/Python{major}{minor}/python.exe'.format(
183 major=major, minor=minor, bits=bits)
184 else:
185 return '/c/Python{major}{minor}_{bits}bits/python.exe'.format(
186 major=major, minor=minor, bits=bits)
187 else:
188 return 'python{major}.{minor}'.format(major=major, minor=minor)
189
190
191def _pypy_pattern_function(major):
192 if major == '2':
193 return 'pypy'
194 elif major == '3':
195 return 'pypy3'
196 else:
197 raise ValueError("Unknown PyPy major version")
198
199
Craig Tillerc7449162015-01-16 14:42:10 -0800200class CLanguage(object):
201
Craig Tillere9c959d2015-01-18 10:23:26 -0800202 def __init__(self, make_target, test_lang):
Craig Tillerc7449162015-01-16 14:42:10 -0800203 self.make_target = make_target
Craig Tillerd50993d2015-08-05 08:04:36 -0700204 self.platform = platform_string()
Craig Tiller711bbe62015-08-19 12:35:16 -0700205 self.test_lang = test_lang
Craig Tillerc7449162015-01-16 14:42:10 -0800206
Jan Tattermusch77db4322016-02-20 20:19:35 -0800207 def configure(self, config, args):
208 self.config = config
209 self.args = args
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100210 if self.args.compiler == 'cmake':
211 _check_arch(self.args.arch, ['default'])
212 self._use_cmake = True
213 self._docker_distro = 'jessie'
214 self._make_options = []
215 elif self.platform == 'windows':
216 self._use_cmake = False
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800217 self._make_options = [_windows_toolset_option(self.args.compiler),
218 _windows_arch_option(self.args.arch)]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800219 else:
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100220 self._use_cmake = False
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800221 self._docker_distro, self._make_options = self._compiler_options(self.args.use_docker,
222 self.args.compiler)
murgatroid99c36f6ea2016-10-03 09:24:09 -0700223 if args.iomgr_platform == "uv":
224 cflags = '-DGRPC_UV '
225 try:
226 cflags += subprocess.check_output(['pkg-config', '--cflags', 'libuv']).strip() + ' '
murgatroid991687cab2016-10-11 11:42:01 -0700227 except (subprocess.CalledProcessError, OSError):
murgatroid99c36f6ea2016-10-03 09:24:09 -0700228 pass
229 try:
230 ldflags = subprocess.check_output(['pkg-config', '--libs', 'libuv']).strip() + ' '
murgatroid991687cab2016-10-11 11:42:01 -0700231 except (subprocess.CalledProcessError, OSError):
murgatroid99c36f6ea2016-10-03 09:24:09 -0700232 ldflags = '-luv '
233 self._make_options += ['EXTRA_CPPFLAGS={}'.format(cflags),
234 'EXTRA_LDLIBS={}'.format(ldflags)]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800235
236 def test_specs(self):
Craig Tiller547db2b2015-01-30 14:08:39 -0800237 out = []
Jan Tattermusch77db4322016-02-20 20:19:35 -0800238 binaries = get_c_tests(self.args.travis, self.test_lang)
Craig Tiller946ce7a2016-04-06 10:35:58 -0700239 for target in binaries:
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100240 if self._use_cmake and target.get('boringssl', False):
241 # cmake doesn't build boringssl tests
242 continue
Craig Tiller123f1372016-06-15 15:06:14 -0700243 polling_strategies = (_POLLING_STRATEGIES.get(self.platform, ['all'])
Craig Tiller946ce7a2016-04-06 10:35:58 -0700244 if target.get('uses_polling', True)
245 else ['all'])
murgatroid992c287ca2016-10-07 09:55:35 -0700246 if self.args.iomgr_platform == 'uv':
247 polling_strategies = ['all']
Craig Tiller946ce7a2016-04-06 10:35:58 -0700248 for polling_strategy in polling_strategies:
249 env={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
Craig Tillerb29f1fe2017-03-28 15:49:23 -0700250 _ROOT + '/src/core/tsi/test_creds/ca.pem',
Craig Tiller8f18ee62016-07-18 08:00:33 -0700251 'GRPC_POLL_STRATEGY': polling_strategy,
252 'GRPC_VERBOSITY': 'DEBUG'}
Yuchen Zengfdae4bd2016-11-07 17:46:16 -0800253 resolver = os.environ.get('GRPC_DNS_RESOLVER', None);
254 if resolver:
255 env['GRPC_DNS_RESOLVER'] = resolver
Craig Tiller38fb8de2016-07-13 08:23:32 -0700256 shortname_ext = '' if polling_strategy=='all' else ' GRPC_POLL_STRATEGY=%s' % polling_strategy
Craig Tillerbc28cd62016-12-02 13:52:21 -0800257 timeout_scaling = 1
258 if polling_strategy == 'poll-cv':
259 timeout_scaling *= 5
Robbie Shadeca7effc2017-01-17 09:14:29 -0500260
Sree Kuchibhotla70d9ca42017-01-27 10:54:05 -0800261 if polling_strategy in target.get('excluded_poll_engines', []):
Sree Kuchibhotlab5517dd2017-01-27 14:18:18 -0800262 continue
Sree Kuchibhotla03370d32017-02-01 08:33:33 -0800263
Robbie Shadeca7effc2017-01-17 09:14:29 -0500264 # Scale overall test timeout if running under various sanitizers.
265 config = self.args.config
266 if ('asan' in config
267 or config == 'msan'
268 or config == 'tsan'
269 or config == 'ubsan'
270 or config == 'helgrind'
271 or config == 'memcheck'):
272 timeout_scaling *= 20
273
Craig Tillerb38197e2016-02-26 10:14:54 -0800274 if self.config.build_config in target['exclude_configs']:
275 continue
murgatroid99c36f6ea2016-10-03 09:24:09 -0700276 if self.args.iomgr_platform in target.get('exclude_iomgrs', []):
277 continue
Craig Tillerb38197e2016-02-26 10:14:54 -0800278 if self.platform == 'windows':
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100279 if self._use_cmake:
280 binary = 'cmake/build/%s/%s.exe' % (_MSBUILD_CONFIG[self.config.build_config], target['name'])
281 else:
282 binary = 'vsprojects/%s%s/%s.exe' % (
283 'x64/' if self.args.arch == 'x64' else '',
284 _MSBUILD_CONFIG[self.config.build_config],
285 target['name'])
Craig Tillerca62ff02016-02-24 22:22:57 -0800286 else:
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100287 if self._use_cmake:
288 binary = 'cmake/build/%s' % target['name']
289 else:
290 binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
Craig Tillerab34b122016-11-28 13:19:12 -0800291 cpu_cost = target['cpu_cost']
292 if cpu_cost == 'capacity':
293 cpu_cost = multiprocessing.cpu_count()
Craig Tillerb38197e2016-02-26 10:14:54 -0800294 if os.path.isfile(binary):
295 if 'gtest' in target and target['gtest']:
296 # here we parse the output of --gtest_list_tests to build up a
297 # complete list of the tests contained in a binary
298 # for each test, we then add a job to run, filtering for just that
299 # test
300 with open(os.devnull, 'w') as fnull:
301 tests = subprocess.check_output([binary, '--gtest_list_tests'],
302 stderr=fnull)
303 base = None
304 for line in tests.split('\n'):
305 i = line.find('#')
306 if i >= 0: line = line[:i]
307 if not line: continue
308 if line[0] != ' ':
309 base = line.strip()
310 else:
311 assert base is not None
312 assert line[1] == ' '
313 test = base + line.strip()
David Garcia Quintas947e5302017-02-17 16:44:45 -0800314 cmdline = [binary, '--gtest_filter=%s' % test] + target['args']
Craig Tiller38fb8de2016-07-13 08:23:32 -0700315 out.append(self.config.job_spec(cmdline,
David Garcia Quintas947e5302017-02-17 16:44:45 -0800316 shortname='%s %s' % (' '.join(cmdline), shortname_ext),
Craig Tillerab34b122016-11-28 13:19:12 -0800317 cpu_cost=cpu_cost,
Craig Tillerbc28cd62016-12-02 13:52:21 -0800318 timeout_seconds=_DEFAULT_TIMEOUT_SECONDS * timeout_scaling,
Craig Tillerb38197e2016-02-26 10:14:54 -0800319 environ=env))
320 else:
321 cmdline = [binary] + target['args']
Craig Tiller38fb8de2016-07-13 08:23:32 -0700322 out.append(self.config.job_spec(cmdline,
323 shortname=' '.join(
324 pipes.quote(arg)
325 for arg in cmdline) +
326 shortname_ext,
Craig Tillerab34b122016-11-28 13:19:12 -0800327 cpu_cost=cpu_cost,
Craig Tillerc2278152016-03-21 08:59:54 -0700328 flaky=target.get('flaky', False),
Craig Tillerbc28cd62016-12-02 13:52:21 -0800329 timeout_seconds=target.get('timeout_seconds', _DEFAULT_TIMEOUT_SECONDS) * timeout_scaling,
Craig Tillerb38197e2016-02-26 10:14:54 -0800330 environ=env))
331 elif self.args.regex == '.*' or self.platform == 'windows':
siddharthshukla0589e532016-07-07 16:08:01 +0200332 print('\nWARNING: binary not found, skipping', binary)
Nicolas Noblee1445362015-05-11 17:40:26 -0700333 return sorted(out)
Craig Tillerc7449162015-01-16 14:42:10 -0800334
Jan Tattermusch77db4322016-02-20 20:19:35 -0800335 def make_targets(self):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800336 if self.platform == 'windows':
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700337 # don't build tools on windows just yet
338 return ['buildtests_%s' % self.make_target]
Craig Tiller7552f0f2015-06-19 17:46:20 -0700339 return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
Craig Tillerc7449162015-01-16 14:42:10 -0800340
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800341 def make_options(self):
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800342 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800343
murgatroid99256d3df2015-09-21 16:58:02 -0700344 def pre_build_steps(self):
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100345 if self._use_cmake:
346 if self.platform == 'windows':
347 return [['tools\\run_tests\\helper_scripts\\pre_build_cmake.bat']]
348 else:
349 return [['tools/run_tests/helper_scripts/pre_build_cmake.sh']]
Jan Tattermusch874aec02015-10-07 19:26:19 -0700350 else:
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100351 if self.platform == 'windows':
352 return [['tools\\run_tests\\helper_scripts\\pre_build_c.bat']]
353 else:
354 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700355
Craig Tillerc7449162015-01-16 14:42:10 -0800356 def build_steps(self):
357 return []
358
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200359 def post_tests_steps(self):
360 if self.platform == 'windows':
361 return []
362 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100363 return [['tools/run_tests/helper_scripts/post_tests_c.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200364
murgatroid99a3e244f2015-09-22 11:25:53 -0700365 def makefile_name(self):
Jan Tattermuschc98bde62017-01-25 19:12:11 +0100366 if self._use_cmake:
367 return 'cmake/build/Makefile'
368 else:
369 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -0700370
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700371 def _clang_make_options(self, version_suffix=''):
372 return ['CC=clang%s' % version_suffix,
373 'CXX=clang++%s' % version_suffix,
374 'LD=clang%s' % version_suffix,
375 'LDXX=clang++%s' % version_suffix]
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800376
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700377 def _gcc_make_options(self, version_suffix):
378 return ['CC=gcc%s' % version_suffix,
379 'CXX=g++%s' % version_suffix,
380 'LD=gcc%s' % version_suffix,
381 'LDXX=g++%s' % version_suffix]
Jan Tattermusch9bb70622016-03-18 10:28:54 -0700382
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800383 def _compiler_options(self, use_docker, compiler):
384 """Returns docker distro and make options to use for given compiler."""
Jan Tattermuschfd3857b2016-06-03 12:24:03 -0700385 if not use_docker and not _is_use_docker_child():
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800386 _check_compiler(compiler, ['default'])
387
388 if compiler == 'gcc4.9' or compiler == 'default':
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800389 return ('jessie', [])
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800390 elif compiler == 'gcc4.4':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700391 return ('wheezy', self._gcc_make_options(version_suffix='-4.4'))
392 elif compiler == 'gcc4.6':
393 return ('wheezy', self._gcc_make_options(version_suffix='-4.6'))
Matt Kwong029ed102016-11-01 18:04:47 -0700394 elif compiler == 'gcc4.8':
Matt Kwong1347e402016-11-02 18:07:40 -0700395 return ('jessie', self._gcc_make_options(version_suffix='-4.8'))
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800396 elif compiler == 'gcc5.3':
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800397 return ('ubuntu1604', [])
Ken Payson975b5102017-03-30 17:38:40 -0700398 elif compiler == 'gcc_musl':
399 return ('alpine', [])
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800400 elif compiler == 'clang3.4':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700401 # on ubuntu1404, clang-3.4 alias doesn't exist, just use 'clang'
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800402 return ('ubuntu1404', self._clang_make_options())
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700403 elif compiler == 'clang3.5':
404 return ('jessie', self._clang_make_options(version_suffix='-3.5'))
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800405 elif compiler == 'clang3.6':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700406 return ('ubuntu1604', self._clang_make_options(version_suffix='-3.6'))
407 elif compiler == 'clang3.7':
408 return ('ubuntu1604', self._clang_make_options(version_suffix='-3.7'))
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800409 else:
410 raise Exception('Compiler %s not supported.' % compiler)
411
Jan Tattermusch77db4322016-02-20 20:19:35 -0800412 def dockerfile_dir(self):
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800413 return 'tools/dockerfile/test/cxx_%s_%s' % (self._docker_distro,
414 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800415
murgatroid99132ce6a2015-03-04 17:29:14 -0800416 def __str__(self):
417 return self.make_target
418
Craig Tillercc0535d2015-12-08 15:14:47 -0800419
murgatroid992c8d5162015-01-26 10:41:21 -0800420class NodeLanguage(object):
421
Jan Tattermusche477b842016-02-06 22:19:01 -0800422 def __init__(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800423 self.platform = platform_string()
Jan Tattermusche477b842016-02-06 22:19:01 -0800424
Jan Tattermusch77db4322016-02-20 20:19:35 -0800425 def configure(self, config, args):
426 self.config = config
427 self.args = args
murgatroid99eaf79642016-11-01 11:05:02 -0700428 # Note: electron ABI only depends on major and minor version, so that's all
429 # we should specify in the compiler argument
murgatroid999fab4382016-04-29 15:05:00 -0700430 _check_compiler(self.args.compiler, ['default', 'node0.12',
murgatroid99eaf79642016-11-01 11:05:02 -0700431 'node4', 'node5', 'node6',
murgatroid99f25f5052017-04-13 17:22:32 -0700432 'node7', 'electron1.3', 'electron1.6'])
murgatroid991191b722017-02-08 11:56:52 -0800433 if args.iomgr_platform == "uv":
434 self.use_uv = True
435 else:
436 self.use_uv = False
murgatroid999fab4382016-04-29 15:05:00 -0700437 if self.args.compiler == 'default':
murgatroid99c5181982017-01-12 12:40:11 -0800438 self.runtime = 'node'
murgatroid991191b722017-02-08 11:56:52 -0800439 self.node_version = '7'
murgatroid999fab4382016-04-29 15:05:00 -0700440 else:
murgatroid99eaf79642016-11-01 11:05:02 -0700441 if self.args.compiler.startswith('electron'):
442 self.runtime = 'electron'
443 self.node_version = self.args.compiler[8:]
444 else:
445 self.runtime = 'node'
446 # Take off the word "node"
447 self.node_version = self.args.compiler[4:]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800448
449 def test_specs(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800450 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100451 return [self.config.job_spec(['tools\\run_tests\\helper_scripts\\run_node.bat'])]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800452 else:
murgatroid99eaf79642016-11-01 11:05:02 -0700453 run_script = 'run_node'
454 if self.runtime == 'electron':
455 run_script += '_electron'
murgatroid99c34cac22017-01-04 15:43:02 -0800456 return [self.config.job_spec(['tools/run_tests/helper_scripts/{}.sh'.format(run_script),
murgatroid99eaf79642016-11-01 11:05:02 -0700457 self.node_version],
Jan Tattermusch77db4322016-02-20 20:19:35 -0800458 None,
459 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800460
murgatroid99256d3df2015-09-21 16:58:02 -0700461 def pre_build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800462 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100463 return [['tools\\run_tests\\helper_scripts\\pre_build_node.bat']]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800464 else:
murgatroid99eaf79642016-11-01 11:05:02 -0700465 build_script = 'pre_build_node'
466 if self.runtime == 'electron':
467 build_script += '_electron'
murgatroid991191b722017-02-08 11:56:52 -0800468 return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script),
469 self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700470
Jan Tattermusch77db4322016-02-20 20:19:35 -0800471 def make_targets(self):
murgatroid99db5b1602015-10-01 13:20:11 -0700472 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800473
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800474 def make_options(self):
475 return []
476
murgatroid992c8d5162015-01-26 10:41:21 -0800477 def build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800478 if self.platform == 'windows':
murgatroid9988113f72017-02-21 10:04:29 -0800479 if self.config == 'dbg':
murgatroid991191b722017-02-08 11:56:52 -0800480 config_flag = '--debug'
481 else:
482 config_flag = '--release'
483 return [['tools\\run_tests\\helper_scripts\\build_node.bat',
484 '--grpc_uv={}'.format('true' if self.use_uv else 'false'),
485 config_flag]]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800486 else:
murgatroid99eaf79642016-11-01 11:05:02 -0700487 build_script = 'build_node'
488 if self.runtime == 'electron':
489 build_script += '_electron'
490 # building for electron requires a patch version
491 self.node_version += '.0'
murgatroid991191b722017-02-08 11:56:52 -0800492 return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script),
493 self.node_version,
494 '--grpc_uv={}'.format('true' if self.use_uv else 'false')]]
Craig Tillerc7449162015-01-16 14:42:10 -0800495
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200496 def post_tests_steps(self):
497 return []
498
murgatroid99a3e244f2015-09-22 11:25:53 -0700499 def makefile_name(self):
500 return 'Makefile'
501
Jan Tattermusch77db4322016-02-20 20:19:35 -0800502 def dockerfile_dir(self):
503 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800504
murgatroid99132ce6a2015-03-04 17:29:14 -0800505 def __str__(self):
506 return 'node'
507
Craig Tiller99775822015-01-30 13:07:16 -0800508
Craig Tillerc7449162015-01-16 14:42:10 -0800509class PhpLanguage(object):
510
Jan Tattermusch77db4322016-02-20 20:19:35 -0800511 def configure(self, config, args):
512 self.config = config
513 self.args = args
514 _check_compiler(self.args.compiler, ['default'])
515
516 def test_specs(self):
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100517 return [self.config.job_spec(['src/php/bin/run_tests.sh'],
Jan Tattermusch77db4322016-02-20 20:19:35 -0800518 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800519
murgatroid99256d3df2015-09-21 16:58:02 -0700520 def pre_build_steps(self):
521 return []
522
Jan Tattermusch77db4322016-02-20 20:19:35 -0800523 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700524 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800525
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800526 def make_options(self):
527 return []
528
Craig Tillerc7449162015-01-16 14:42:10 -0800529 def build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100530 return [['tools/run_tests/helper_scripts/build_php.sh']]
Craig Tillerc7449162015-01-16 14:42:10 -0800531
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200532 def post_tests_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100533 return [['tools/run_tests/helper_scripts/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200534
murgatroid99a3e244f2015-09-22 11:25:53 -0700535 def makefile_name(self):
536 return 'Makefile'
537
Jan Tattermusch77db4322016-02-20 20:19:35 -0800538 def dockerfile_dir(self):
539 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800540
murgatroid99132ce6a2015-03-04 17:29:14 -0800541 def __str__(self):
542 return 'php'
543
Craig Tillerc7449162015-01-16 14:42:10 -0800544
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700545class Php7Language(object):
546
547 def configure(self, config, args):
548 self.config = config
549 self.args = args
550 _check_compiler(self.args.compiler, ['default'])
551
552 def test_specs(self):
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100553 return [self.config.job_spec(['src/php/bin/run_tests.sh'],
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700554 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
555
556 def pre_build_steps(self):
557 return []
558
559 def make_targets(self):
560 return ['static_c', 'shared_c']
561
562 def make_options(self):
563 return []
564
565 def build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100566 return [['tools/run_tests/helper_scripts/build_php.sh']]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700567
568 def post_tests_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100569 return [['tools/run_tests/helper_scripts/post_tests_php.sh']]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700570
571 def makefile_name(self):
572 return 'Makefile'
573
574 def dockerfile_dir(self):
575 return 'tools/dockerfile/test/php7_jessie_%s' % _docker_arch_suffix(self.args.arch)
576
577 def __str__(self):
578 return 'php7'
579
580
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700581class PythonConfig(collections.namedtuple('PythonConfig', [
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700582 'name', 'build', 'run'])):
583 """Tuple of commands (named s.t. 'what it says on the tin' applies)"""
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700584
Nathaniel Manista840615e2015-01-22 20:31:47 +0000585class PythonLanguage(object):
586
Jan Tattermusch77db4322016-02-20 20:19:35 -0800587 def configure(self, config, args):
588 self.config = config
589 self.args = args
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700590 self.pythons = self._get_pythons(self.args)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800591
592 def test_specs(self):
Jan Tattermusch072ebaa2016-03-01 18:33:12 -0800593 # load list of known test suites
Masood Malekghassemi1ff429d2016-06-02 16:39:20 -0700594 with open('src/python/grpcio_tests/tests/tests.json') as tests_json_file:
Jan Tattermusch072ebaa2016-03-01 18:33:12 -0800595 tests_json = json.load(tests_json_file)
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700596 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700597 return [self.config.job_spec(
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700598 config.run,
Masood Malekghassemie6a23e22016-06-28 13:58:42 -0700599 timeout_seconds=5*60,
siddharthshukla0589e532016-07-07 16:08:01 +0200600 environ=dict(list(environment.items()) +
Masood Malekghassemic4f5a2e2016-12-05 15:54:56 -0800601 [('GRPC_PYTHON_TESTRUNNER_FILTER', str(suite_name))]),
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700602 shortname='%s.test.%s' % (config.name, suite_name),)
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700603 for suite_name in tests_json
604 for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000605
murgatroid99256d3df2015-09-21 16:58:02 -0700606 def pre_build_steps(self):
607 return []
608
Jan Tattermusch77db4322016-02-20 20:19:35 -0800609 def make_targets(self):
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700610 return []
Nathaniel Manista840615e2015-01-22 20:31:47 +0000611
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800612 def make_options(self):
613 return []
614
Nathaniel Manista840615e2015-01-22 20:31:47 +0000615 def build_steps(self):
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700616 return [config.build for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000617
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200618 def post_tests_steps(self):
Matt Kwong0ff19572017-03-30 18:22:21 -0700619 if self.config != 'gcov':
620 return []
621 else:
622 return [['tools/run_tests/helper_scripts/post_tests_python.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200623
murgatroid99a3e244f2015-09-22 11:25:53 -0700624 def makefile_name(self):
625 return 'Makefile'
626
Jan Tattermusch77db4322016-02-20 20:19:35 -0800627 def dockerfile_dir(self):
siddharthshuklac4782142016-06-28 18:48:47 +0200628 return 'tools/dockerfile/test/python_%s_%s' % (self.python_manager_name(), _docker_arch_suffix(self.args.arch))
629
630 def python_manager_name(self):
Ken Payson975b5102017-03-30 17:38:40 -0700631 if self.args.compiler in ['python3.5', 'python3.6']:
632 return 'pyenv'
633 elif self.args.compiler == 'python_alpine':
634 return 'alpine'
635 else:
636 return 'jessie'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800637
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700638 def _get_pythons(self, args):
639 if args.arch == 'x86':
640 bits = '32'
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700641 else:
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700642 bits = '64'
siddharthshukla2135a1b2016-08-04 02:11:53 +0200643
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700644 if os.name == 'nt':
645 shell = ['bash']
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100646 builder = [os.path.abspath('tools/run_tests/helper_scripts/build_python_msys2.sh')]
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700647 builder_prefix_arguments = ['MINGW{}'.format(bits)]
648 venv_relative_python = ['Scripts/python.exe']
649 toolchain = ['mingw32']
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700650 else:
651 shell = []
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100652 builder = [os.path.abspath('tools/run_tests/helper_scripts/build_python.sh')]
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700653 builder_prefix_arguments = []
654 venv_relative_python = ['bin/python']
655 toolchain = ['unix']
siddharthshukla2135a1b2016-08-04 02:11:53 +0200656
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100657 runner = [os.path.abspath('tools/run_tests/helper_scripts/run_python.sh')]
siddharthshukla2135a1b2016-08-04 02:11:53 +0200658 config_vars = _PythonConfigVars(shell, builder, builder_prefix_arguments,
659 venv_relative_python, toolchain, runner)
660 python27_config = _python_config_generator(name='py27', major='2',
661 minor='7', bits=bits,
662 config_vars=config_vars)
663 python34_config = _python_config_generator(name='py34', major='3',
664 minor='4', bits=bits,
665 config_vars=config_vars)
666 python35_config = _python_config_generator(name='py35', major='3',
667 minor='5', bits=bits,
668 config_vars=config_vars)
669 python36_config = _python_config_generator(name='py36', major='3',
670 minor='6', bits=bits,
671 config_vars=config_vars)
672 pypy27_config = _pypy_config_generator(name='pypy', major='2',
673 config_vars=config_vars)
674 pypy32_config = _pypy_config_generator(name='pypy3', major='3',
675 config_vars=config_vars)
676
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700677 if args.compiler == 'default':
678 if os.name == 'nt':
679 return (python27_config,)
680 else:
681 return (python27_config, python34_config,)
682 elif args.compiler == 'python2.7':
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700683 return (python27_config,)
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700684 elif args.compiler == 'python3.4':
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700685 return (python34_config,)
siddharthshuklac4782142016-06-28 18:48:47 +0200686 elif args.compiler == 'python3.5':
687 return (python35_config,)
688 elif args.compiler == 'python3.6':
689 return (python36_config,)
siddharthshukla2135a1b2016-08-04 02:11:53 +0200690 elif args.compiler == 'pypy':
691 return (pypy27_config,)
692 elif args.compiler == 'pypy3':
693 return (pypy32_config,)
Ken Payson975b5102017-03-30 17:38:40 -0700694 elif args.compiler == 'python_alpine':
695 return (python27_config,)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700696 else:
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700697 raise Exception('Compiler %s not supported.' % args.compiler)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700698
murgatroid99132ce6a2015-03-04 17:29:14 -0800699 def __str__(self):
700 return 'python'
701
Craig Tillerd625d812015-04-08 15:52:35 -0700702
murgatroid996a4c4fa2015-02-27 12:08:57 -0800703class RubyLanguage(object):
704
Jan Tattermusch77db4322016-02-20 20:19:35 -0800705 def configure(self, config, args):
706 self.config = config
707 self.args = args
708 _check_compiler(self.args.compiler, ['default'])
709
710 def test_specs(self):
Alexander Polcync44c16e2017-03-14 17:44:21 -0700711 tests = [self.config.job_spec(['tools/run_tests/helper_scripts/run_ruby.sh'],
712 timeout_seconds=10*60,
713 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Alexander Polcync44c16e2017-03-14 17:44:21 -0700714 tests.append(self.config.job_spec(['tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh'],
715 timeout_seconds=10*60,
716 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
717 return tests
murgatroid996a4c4fa2015-02-27 12:08:57 -0800718
murgatroid99256d3df2015-09-21 16:58:02 -0700719 def pre_build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100720 return [['tools/run_tests/helper_scripts/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700721
Jan Tattermusch4651bef2016-02-23 08:31:25 -0800722 def make_targets(self):
murgatroid997d243df2016-02-18 09:58:05 -0800723 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800724
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800725 def make_options(self):
726 return []
727
murgatroid996a4c4fa2015-02-27 12:08:57 -0800728 def build_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100729 return [['tools/run_tests/helper_scripts/build_ruby.sh']]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800730
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200731 def post_tests_steps(self):
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100732 return [['tools/run_tests/helper_scripts/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200733
murgatroid99a3e244f2015-09-22 11:25:53 -0700734 def makefile_name(self):
735 return 'Makefile'
736
Jan Tattermusch77db4322016-02-20 20:19:35 -0800737 def dockerfile_dir(self):
738 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800739
murgatroid99132ce6a2015-03-04 17:29:14 -0800740 def __str__(self):
741 return 'ruby'
742
Craig Tillerd625d812015-04-08 15:52:35 -0700743
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800744class CSharpLanguage(object):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800745
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700746 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700747 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700748
Jan Tattermusch77db4322016-02-20 20:19:35 -0800749 def configure(self, config, args):
750 self.config = config
751 self.args = args
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700752 if self.platform == 'windows':
Jan Tattermusche7f0b852017-02-08 19:06:10 -0800753 _check_compiler(self.args.compiler, ['coreclr', 'default'])
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700754 _check_arch(self.args.arch, ['default'])
Jan Tattermusch3c344d22017-04-04 16:49:06 +0200755 self._cmake_arch_option = 'x64'
Jan Tattermusche7f0b852017-02-08 19:06:10 -0800756 self._make_options = []
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700757 else:
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700758 _check_compiler(self.args.compiler, ['default', 'coreclr'])
Jan Tattermusch3c344d22017-04-04 16:49:06 +0200759 self._docker_distro = 'jessie'
Jan Tattermusch76511a52016-06-17 14:00:57 -0700760
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700761 if self.platform == 'mac':
Jan Tattermusch2a322c22016-03-30 13:55:07 -0700762 # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
Jan Tattermusch6d082202016-06-21 10:03:38 -0700763 self._make_options = ['EMBED_OPENSSL=true']
764 if self.args.compiler != 'coreclr':
765 # On Mac, official distribution of mono is 32bit.
766 self._make_options += ['CFLAGS=-m32', 'LDFLAGS=-m32']
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700767 else:
768 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
Jan Tattermusch77db4322016-02-20 20:19:35 -0800769
770 def test_specs(self):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800771 with open('src/csharp/tests.json') as f:
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700772 tests_by_assembly = json.load(f)
Jan Tattermusch03c01062015-12-11 14:28:56 -0800773
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800774 msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
Jan Tattermusch78cb9312017-04-11 11:04:42 +0200775 nunit_args = ['--labels=All', '--noresult', '--workers=1']
Jan Tattermusch76511a52016-06-17 14:00:57 -0700776 assembly_subdir = 'bin/%s' % msbuild_config
777 assembly_extension = '.exe'
778
779 if self.args.compiler == 'coreclr':
Jan Tattermusch1f7ce192016-09-08 16:21:16 +0200780 assembly_subdir += '/netcoreapp1.0'
781 runtime_cmd = ['dotnet', 'exec']
782 assembly_extension = '.dll'
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700783 else:
Jan Tattermusch3c344d22017-04-04 16:49:06 +0200784 assembly_subdir += '/net45'
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700785 if self.platform == 'windows':
786 runtime_cmd = []
787 else:
788 runtime_cmd = ['mono']
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700789
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700790 specs = []
Siddharth Shuklad194f592017-03-11 19:12:43 +0100791 for assembly in six.iterkeys(tests_by_assembly):
Jan Tattermusch76511a52016-06-17 14:00:57 -0700792 assembly_file = 'src/csharp/%s/%s/%s%s' % (assembly,
793 assembly_subdir,
794 assembly,
795 assembly_extension)
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700796 if self.config.build_config != 'gcov' or self.platform != 'windows':
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700797 # normally, run each test as a separate process
798 for test in tests_by_assembly[assembly]:
799 cmdline = runtime_cmd + [assembly_file, '--test=%s' % test] + nunit_args
800 specs.append(self.config.job_spec(cmdline,
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700801 shortname='csharp.%s' % test,
802 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
803 else:
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700804 # For C# test coverage, run all tests from the same assembly at once
805 # using OpenCover.Console (only works on Windows).
806 cmdline = ['src\\csharp\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe',
807 '-target:%s' % assembly_file,
808 '-targetdir:src\\csharp',
809 '-targetargs:%s' % ' '.join(nunit_args),
810 '-filter:+[Grpc.Core]*',
811 '-register:user',
812 '-output:src\\csharp\\coverage_csharp_%s.xml' % assembly]
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700813
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700814 # set really high cpu_cost to make sure instances of OpenCover.Console run exclusively
815 # to prevent problems with registering the profiler.
816 run_exclusive = 1000000
Jan Tattermusch35e608f2016-04-09 16:35:06 -0700817 specs.append(self.config.job_spec(cmdline,
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700818 shortname='csharp.coverage.%s' % assembly,
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700819 cpu_cost=run_exclusive,
Jan Tattermusch77db4322016-02-20 20:19:35 -0800820 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700821 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800822
murgatroid99256d3df2015-09-21 16:58:02 -0700823 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700824 if self.platform == 'windows':
Jan Tattermusche7f0b852017-02-08 19:06:10 -0800825 return [['tools\\run_tests\\helper_scripts\\pre_build_csharp.bat', self._cmake_arch_option]]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700826 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100827 return [['tools/run_tests/helper_scripts/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700828
Jan Tattermusch77db4322016-02-20 20:19:35 -0800829 def make_targets(self):
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700830 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800831
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800832 def make_options(self):
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700833 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800834
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800835 def build_steps(self):
Jan Tattermusch3c344d22017-04-04 16:49:06 +0200836 if self.platform == 'windows':
837 return [['tools\\run_tests\\helper_scripts\\build_csharp.bat']]
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700838 else:
Jan Tattermusch3c344d22017-04-04 16:49:06 +0200839 return [['tools/run_tests/helper_scripts/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000840
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200841 def post_tests_steps(self):
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700842 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100843 return [['tools\\run_tests\\helper_scripts\\post_tests_csharp.bat']]
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700844 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100845 return [['tools/run_tests/helper_scripts/post_tests_csharp.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200846
murgatroid99a3e244f2015-09-22 11:25:53 -0700847 def makefile_name(self):
Jan Tattermusche7f0b852017-02-08 19:06:10 -0800848 if self.platform == 'windows':
849 return 'cmake/build/%s/Makefile' % self._cmake_arch_option
850 else:
851 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -0700852
Jan Tattermusch77db4322016-02-20 20:19:35 -0800853 def dockerfile_dir(self):
Jan Tattermusch76511a52016-06-17 14:00:57 -0700854 return 'tools/dockerfile/test/csharp_%s_%s' % (self._docker_distro,
855 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800856
murgatroid99132ce6a2015-03-04 17:29:14 -0800857 def __str__(self):
858 return 'csharp'
859
Craig Tillerd625d812015-04-08 15:52:35 -0700860
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700861class ObjCLanguage(object):
862
Jan Tattermusch77db4322016-02-20 20:19:35 -0800863 def configure(self, config, args):
864 self.config = config
865 self.args = args
866 _check_compiler(self.args.compiler, ['default'])
867
868 def test_specs(self):
Jorge Canizales8a9fe2a2016-07-29 15:44:47 -0700869 return [
870 self.config.job_spec(['src/objective-c/tests/run_tests.sh'],
Jan Tattermuschfffb2672016-12-19 15:24:45 +0100871 timeout_seconds=60*60,
Jorge Canizales8a9fe2a2016-07-29 15:44:47 -0700872 shortname='objc-tests',
873 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
874 self.config.job_spec(['src/objective-c/tests/build_example_test.sh'],
Nicolas "Pixel" Noble7f074e02016-08-11 21:00:08 +0200875 timeout_seconds=30*60,
Jorge Canizales8a9fe2a2016-07-29 15:44:47 -0700876 shortname='objc-examples-build',
877 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
878 ]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700879
murgatroid99256d3df2015-09-21 16:58:02 -0700880 def pre_build_steps(self):
881 return []
882
Jan Tattermusch77db4322016-02-20 20:19:35 -0800883 def make_targets(self):
Jorge Canizales6eade6d2016-07-11 00:34:14 -0700884 return ['interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700885
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800886 def make_options(self):
887 return []
888
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700889 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700890 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700891
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200892 def post_tests_steps(self):
893 return []
894
murgatroid99a3e244f2015-09-22 11:25:53 -0700895 def makefile_name(self):
896 return 'Makefile'
897
Jan Tattermusch77db4322016-02-20 20:19:35 -0800898 def dockerfile_dir(self):
Jan Tattermusch788ee232016-01-26 12:19:44 -0800899 return None
900
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700901 def __str__(self):
902 return 'objc'
903
904
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100905class Sanity(object):
906
Jan Tattermusch77db4322016-02-20 20:19:35 -0800907 def configure(self, config, args):
908 self.config = config
909 self.args = args
910 _check_compiler(self.args.compiler, ['default'])
911
912 def test_specs(self):
Craig Tiller94d04a52016-01-20 10:58:23 -0800913 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800914 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
Jan Tattermusch7dd2cc62016-12-20 17:15:39 +0100915 environ={'TEST': 'true'}
916 if _is_use_docker_child():
917 environ['CLANG_FORMAT_SKIP_DOCKER'] = 'true'
Craig Tiller34226af2016-06-24 16:46:25 -0700918 return [self.config.job_spec(cmd['script'].split(),
Jan Tattermusch7dd2cc62016-12-20 17:15:39 +0100919 timeout_seconds=30*60,
920 environ=environ,
Jan Tattermusch77db4322016-02-20 20:19:35 -0800921 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800922 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100923
murgatroid99256d3df2015-09-21 16:58:02 -0700924 def pre_build_steps(self):
925 return []
926
Jan Tattermusch77db4322016-02-20 20:19:35 -0800927 def make_targets(self):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100928 return ['run_dep_checks']
929
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800930 def make_options(self):
931 return []
932
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100933 def build_steps(self):
934 return []
935
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200936 def post_tests_steps(self):
937 return []
938
murgatroid99a3e244f2015-09-22 11:25:53 -0700939 def makefile_name(self):
940 return 'Makefile'
941
Jan Tattermusch77db4322016-02-20 20:19:35 -0800942 def dockerfile_dir(self):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800943 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800944
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100945 def __str__(self):
946 return 'sanity'
947
murgatroid99b53e5d12016-10-18 09:55:28 -0700948class NodeExpressLanguage(object):
949 """Dummy Node express test target to enable running express performance
950 benchmarks"""
951
952 def __init__(self):
953 self.platform = platform_string()
954
955 def configure(self, config, args):
956 self.config = config
957 self.args = args
958 _check_compiler(self.args.compiler, ['default', 'node0.12',
959 'node4', 'node5', 'node6'])
960 if self.args.compiler == 'default':
961 self.node_version = '4'
962 else:
963 # Take off the word "node"
964 self.node_version = self.args.compiler[4:]
965
966 def test_specs(self):
967 return []
968
969 def pre_build_steps(self):
970 if self.platform == 'windows':
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100971 return [['tools\\run_tests\\helper_scripts\\pre_build_node.bat']]
murgatroid99b53e5d12016-10-18 09:55:28 -0700972 else:
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100973 return [['tools/run_tests/helper_scripts/pre_build_node.sh', self.node_version]]
murgatroid99b53e5d12016-10-18 09:55:28 -0700974
975 def make_targets(self):
976 return []
977
978 def make_options(self):
979 return []
980
981 def build_steps(self):
982 return []
983
984 def post_tests_steps(self):
985 return []
986
987 def makefile_name(self):
988 return 'Makefile'
989
990 def dockerfile_dir(self):
991 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
992
993 def __str__(self):
994 return 'node_express'
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200995
Craig Tiller738c3342015-01-12 14:28:33 -0800996# different configurations we can run under
Jan Tattermusch5c79a312016-12-20 11:02:50 +0100997with open('tools/run_tests/generated/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800998 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800999
1000
Craig Tillerc7449162015-01-16 14:42:10 -08001001_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -08001002 'c++': CLanguage('cxx', 'c++'),
1003 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -08001004 'node': NodeLanguage(),
murgatroid99b53e5d12016-10-18 09:55:28 -07001005 'node_express': NodeExpressLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +00001006 'php': PhpLanguage(),
Stanley Cheung2e2cdff2016-07-23 19:07:36 -07001007 'php7': Php7Language(),
Nathaniel Manista840615e2015-01-22 20:31:47 +00001008 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -08001009 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001010 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -07001011 'objc' : ObjCLanguage(),
Jan Tattermusch70a57e42016-02-20 18:50:27 -08001012 'sanity': Sanity()
Craig Tillereb272bc2015-01-30 13:13:14 -08001013 }
Nicolas Nobleddef2462015-01-06 18:08:25 -08001014
Jan Tattermusch77db4322016-02-20 20:19:35 -08001015
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001016_MSBUILD_CONFIG = {
Craig Tiller7bb3efd2015-09-01 08:04:03 -07001017 'dbg': 'Debug',
1018 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -08001019 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -07001020 }
1021
David Garcia Quintase90cd372015-05-31 18:15:26 -07001022
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001023def _windows_arch_option(arch):
1024 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -08001025 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001026 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -08001027 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001028 return '/p:Platform=x64'
1029 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001030 print('Architecture %s not supported.' % arch)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001031 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -08001032
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001033
1034def _check_arch_option(arch):
1035 """Checks that architecture option is valid."""
1036 if platform_string() == 'windows':
1037 _windows_arch_option(arch)
1038 elif platform_string() == 'linux':
1039 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -08001040 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001041 if arch == 'default':
1042 return
1043 elif runtime_arch == '64bit' and arch == 'x64':
1044 return
1045 elif runtime_arch == '32bit' and arch == 'x86':
1046 return
1047 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001048 print('Architecture %s does not match current runtime architecture.' % arch)
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001049 sys.exit(1)
1050 else:
1051 if args.arch != 'default':
siddharthshukla0589e532016-07-07 16:08:01 +02001052 print('Architecture %s not supported on current platform.' % args.arch)
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001053 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001054
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001055
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001056def _windows_build_bat(compiler):
1057 """Returns name of build.bat for selected compiler."""
Jan Tattermuschbc98af12016-06-17 18:38:27 -07001058 # For CoreCLR, fall back to the default compiler for C core
Jan Tattermuschdd900d52017-02-09 16:26:41 -08001059 if compiler == 'default' or compiler == 'vs2013':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001060 return 'vsprojects\\build_vs2013.bat'
1061 elif compiler == 'vs2015':
1062 return 'vsprojects\\build_vs2015.bat'
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001063 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001064 print('Compiler %s not supported.' % compiler)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001065 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001066
1067
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001068def _windows_toolset_option(compiler):
1069 """Returns msbuild PlatformToolset for selected compiler."""
Jan Tattermuschbc98af12016-06-17 18:38:27 -07001070 # For CoreCLR, fall back to the default compiler for C core
1071 if compiler == 'default' or compiler == 'vs2013' or compiler == 'coreclr':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001072 return '/p:PlatformToolset=v120'
1073 elif compiler == 'vs2015':
1074 return '/p:PlatformToolset=v140'
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001075 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001076 print('Compiler %s not supported.' % compiler)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001077 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001078
1079
Jan Tattermusche70b3c52016-02-07 20:21:02 -08001080def _docker_arch_suffix(arch):
1081 """Returns suffix to dockerfile dir to use."""
1082 if arch == 'default' or arch == 'x64':
1083 return 'x64'
1084 elif arch == 'x86':
1085 return 'x86'
1086 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001087 print('Architecture %s not supported with current settings.' % arch)
Jan Tattermusche70b3c52016-02-07 20:21:02 -08001088 sys.exit(1)
1089
1090
David Garcia Quintase90cd372015-05-31 18:15:26 -07001091def runs_per_test_type(arg_str):
1092 """Auxilary function to parse the "runs_per_test" flag.
1093
1094 Returns:
1095 A positive integer or 0, the latter indicating an infinite number of
1096 runs.
1097
1098 Raises:
1099 argparse.ArgumentTypeError: Upon invalid input.
1100 """
1101 if arg_str == 'inf':
1102 return 0
1103 try:
1104 n = int(arg_str)
1105 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -07001106 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -07001107 except:
Adele Zhoue4c35612015-10-16 15:34:23 -07001108 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -07001109 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001110
siddharthshukla2135a1b2016-08-04 02:11:53 +02001111
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001112def percent_type(arg_str):
1113 pct = float(arg_str)
1114 if pct > 100 or pct < 0:
1115 raise argparse.ArgumentTypeError(
1116 "'%f' is not a valid percentage in the [0, 100] range" % pct)
1117 return pct
1118
1119# This is math.isclose in python >= 3.5
1120def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
1121 return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
1122
1123
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001124# parse command line
1125argp = argparse.ArgumentParser(description='Run grpc tests.')
1126argp.add_argument('-c', '--config',
Jan Tattermusch77db4322016-02-20 20:19:35 -08001127 choices=sorted(_CONFIGS.keys()),
1128 default='opt')
David Garcia Quintase90cd372015-05-31 18:15:26 -07001129argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
1130 help='A positive integer or "inf". If "inf", all tests will run in an '
1131 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -08001132argp.add_argument('-r', '--regex', default='.*', type=str)
Vijay Pai488fd0e2016-06-13 12:37:12 -07001133argp.add_argument('--regex_exclude', default='', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -08001134argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -08001135argp.add_argument('-s', '--slowdown', default=1.0, type=float)
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001136argp.add_argument('-p', '--sample_percent', default=100.0, type=percent_type,
1137 help='Run a random sample with that percentage of tests')
ctiller3040cb72015-01-07 12:13:17 -08001138argp.add_argument('-f', '--forever',
1139 default=False,
1140 action='store_const',
1141 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +01001142argp.add_argument('-t', '--travis',
1143 default=False,
1144 action='store_const',
1145 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001146argp.add_argument('--newline_on_success',
1147 default=False,
1148 action='store_const',
1149 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -08001150argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -07001151 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -08001152 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -07001153 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -07001154argp.add_argument('-S', '--stop_on_failure',
1155 default=False,
1156 action='store_const',
1157 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001158argp.add_argument('--use_docker',
1159 default=False,
1160 action='store_const',
1161 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -07001162 help='Run all the tests under docker. That provides ' +
1163 'additional isolation and prevents the need to install ' +
1164 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -07001165argp.add_argument('--allow_flakes',
1166 default=False,
1167 action='store_const',
1168 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -07001169 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001170argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -08001171 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001172 default='default',
1173 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
1174argp.add_argument('--compiler',
Jan Tattermuschc4cbe392016-02-22 19:29:38 -08001175 choices=['default',
Ken Payson975b5102017-03-30 17:38:40 -07001176 'gcc4.4', 'gcc4.6', 'gcc4.8', 'gcc4.9', 'gcc5.3', 'gcc_musl',
Jan Tattermusch6d258c52016-06-10 09:36:51 -07001177 'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7',
Jan Tattermuschdc5e5092017-02-09 16:15:12 -08001178 'vs2013', 'vs2015',
Ken Payson975b5102017-03-30 17:38:40 -07001179 'python2.7', 'python3.4', 'python3.5', 'python3.6', 'pypy', 'pypy3', 'python_alpine',
murgatroid995a3f8622016-10-26 13:45:04 -07001180 'node0.12', 'node4', 'node5', 'node6', 'node7',
murgatroid99f25f5052017-04-13 17:22:32 -07001181 'electron1.3', 'electron1.6',
Jan Tattermuschc98bde62017-01-25 19:12:11 +01001182 'coreclr',
1183 'cmake'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001184 default='default',
Jan Tattermusch77db4322016-02-20 20:19:35 -08001185 help='Selects compiler to use. Allowed values depend on the platform and language.')
murgatroid99c36f6ea2016-10-03 09:24:09 -07001186argp.add_argument('--iomgr_platform',
1187 choices=['native', 'uv'],
1188 default='native',
1189 help='Selects iomgr platform to build on')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001190argp.add_argument('--build_only',
1191 default=False,
1192 action='store_const',
1193 const=True,
1194 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -08001195argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
1196 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -08001197argp.add_argument('--update_submodules', default=[], nargs='*',
1198 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
1199 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -07001200argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001201argp.add_argument('-x', '--xml_report', default=None, type=str,
1202 help='Generates a JUnit-compatible XML report')
Jan Tattermuschcfcc0752016-10-09 17:02:34 +02001203argp.add_argument('--report_suite_name', default='tests', type=str,
1204 help='Test suite name to use in generated JUnit XML report')
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001205argp.add_argument('--quiet_success',
1206 default=False,
1207 action='store_const',
1208 const=True,
1209 help='Dont print anything when a test passes. Passing tests also will not be reported in XML report. ' +
1210 'Useful when running many iterations of each test (argument -n).')
Craig Tiller123f1372016-06-15 15:06:14 -07001211argp.add_argument('--force_default_poller', default=False, action='store_const', const=True,
1212 help='Dont try to iterate over many polling strategies when they exist')
Craig Tillera1ac2a12017-04-21 07:20:38 -07001213argp.add_argument('--max_time', default=-1, type=int, help='Maximum test runtime in seconds')
Nicolas Nobleddef2462015-01-06 18:08:25 -08001214args = argp.parse_args()
1215
Craig Tiller123f1372016-06-15 15:06:14 -07001216if args.force_default_poller:
1217 _POLLING_STRATEGIES = {}
1218
Craig Tiller5f735a62016-01-20 09:31:15 -08001219jobset.measure_cpu_costs = args.measure_cpu_costs
1220
Craig Tiller1676f912016-01-05 10:49:44 -08001221# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -08001222need_to_regenerate_projects = False
1223for spec in args.update_submodules:
1224 spec = spec.split(':', 1)
1225 if len(spec) == 1:
1226 submodule = spec[0]
1227 branch = 'master'
1228 elif len(spec) == 2:
1229 submodule = spec[0]
1230 branch = spec[1]
1231 cwd = 'third_party/%s' % submodule
1232 def git(cmd, cwd=cwd):
siddharthshukla0589e532016-07-07 16:08:01 +02001233 print('in %s: git %s' % (cwd, cmd))
David Garcia Quintas03920252017-02-15 12:51:21 -08001234 run_shell_command('git %s' % cmd, cwd=cwd)
Craig Tillerb361b4e2016-01-06 11:44:17 -08001235 git('fetch')
1236 git('checkout %s' % branch)
1237 git('pull origin %s' % branch)
1238 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
1239 need_to_regenerate_projects = True
1240if need_to_regenerate_projects:
1241 if jobset.platform_string() == 'linux':
David Garcia Quintas03920252017-02-15 12:51:21 -08001242 run_shell_command('tools/buildgen/generate_projects.sh')
Craig Tillerb361b4e2016-01-06 11:44:17 -08001243 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001244 print('WARNING: may need to regenerate projects, but since we are not on')
1245 print(' Linux this step is being skipped. Compilation MAY fail.')
Craig Tiller1676f912016-01-05 10:49:44 -08001246
1247
Nicolas Nobleddef2462015-01-06 18:08:25 -08001248# grab config
Jan Tattermusch77db4322016-02-20 20:19:35 -08001249run_config = _CONFIGS[args.config]
1250build_config = run_config.build_config
Craig Tillerf1973b02015-01-16 12:32:13 -08001251
Craig Tiller06805272015-06-11 14:46:47 -07001252if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -07001253 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -07001254
Adele Zhou6b9527c2015-11-20 15:56:35 -08001255if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -08001256 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -08001257else:
1258 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -08001259# We don't support code coverage on some languages
1260if 'gcov' in args.config:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001261 for bad in ['objc', 'sanity']:
Craig Tiller16900662016-01-07 19:30:54 -08001262 if bad in lang_list:
1263 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -08001264
1265languages = set(_LANGUAGES[l] for l in lang_list)
Jan Tattermusch77db4322016-02-20 20:19:35 -08001266for l in languages:
1267 l.configure(run_config, args)
murgatroid99132ce6a2015-03-04 17:29:14 -08001268
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001269language_make_options=[]
1270if any(language.make_options() for language in languages):
Adele Zhou3b6ab812016-05-18 17:04:20 -07001271 if not 'gcov' in args.config and len(languages) != 1:
siddharthshukla0589e532016-07-07 16:08:01 +02001272 print('languages with custom make options cannot be built simultaneously with other languages')
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001273 sys.exit(1)
1274 else:
Matt Kwong0ff19572017-03-30 18:22:21 -07001275 # Combining make options is not clean and just happens to work. It allows C/C++ and C# to build
1276 # together, and is only used under gcov. All other configs should build languages individually.
1277 language_make_options = list(set([make_option for lang in languages for make_option in lang.make_options()]))
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001278
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001279if args.use_docker:
1280 if not args.travis:
siddharthshukla0589e532016-07-07 16:08:01 +02001281 print('Seen --use_docker flag, will run tests under docker.')
1282 print('')
1283 print('IMPORTANT: The changes you are testing need to be locally committed')
1284 print('because only the committed changes in the current branch will be')
1285 print('copied to the docker environment.')
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001286 time.sleep(5)
1287
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001288 dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
1289 if len(dockerfile_dirs) > 1:
Adele Zhou9506ef22016-03-02 13:53:34 -08001290 if 'gcov' in args.config:
1291 dockerfile_dir = 'tools/dockerfile/test/multilang_jessie_x64'
1292 print ('Using multilang_jessie_x64 docker image for code coverage for '
1293 'all languages.')
1294 else:
1295 print ('Languages to be tested require running under different docker '
1296 'images.')
1297 sys.exit(1)
1298 else:
1299 dockerfile_dir = next(iter(dockerfile_dirs))
Craig Tillerde7edf82016-03-20 09:12:16 -07001300
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001301 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -08001302 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001303
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001304 env = os.environ.copy()
1305 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001306 env['DOCKERFILE_DIR'] = dockerfile_dir
Jan Tattermusch9835d4b2016-04-29 15:05:05 -07001307 env['DOCKER_RUN_SCRIPT'] = 'tools/run_tests/dockerize/docker_run_tests.sh'
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001308 if args.xml_report:
1309 env['XML_REPORT'] = args.xml_report
1310 if not args.travis:
1311 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
1312
Jan Tattermusch3464f702017-03-08 20:50:57 +01001313 subprocess.check_call('tools/run_tests/dockerize/build_docker_and_run_tests.sh',
1314 shell=True,
1315 env=env)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001316 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -08001317
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001318_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001319
Jan Tattermuschfba65302016-01-25 18:21:14 -08001320def make_jobspec(cfg, targets, makefile='Makefile'):
1321 if platform_string() == 'windows':
Jan Tattermuschc98bde62017-01-25 19:12:11 +01001322 if makefile.startswith('cmake/build/'):
1323 return [jobset.JobSpec(['cmake', '--build', '.',
1324 '--target', '%s' % target,
1325 '--config', _MSBUILD_CONFIG[cfg]],
Jan Tattermusche7f0b852017-02-08 19:06:10 -08001326 cwd=os.path.dirname(makefile),
Jan Tattermuschc98bde62017-01-25 19:12:11 +01001327 timeout_seconds=None) for target in targets]
Craig Tillerfc3c0c42015-09-01 16:47:54 -07001328 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -07001329 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -07001330 # empirically /m:2 gives the best performance/price and should prevent
1331 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -07001332 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -07001333 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -07001334 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -07001335 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001336 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -07001337 'vsprojects\\%s.sln' % target,
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001338 '/p:Configuration=%s' % _MSBUILD_CONFIG[cfg]] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001339 extra_args +
1340 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -08001341 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -07001342 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -08001343 else:
Jan Tattermuschc98bde62017-01-25 19:12:11 +01001344 if targets and makefile.startswith('cmake/build/'):
1345 # With cmake, we've passed all the build configuration in the pre-build step already
1346 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
1347 '-j', '%d' % args.jobs] +
1348 targets,
1349 cwd='cmake/build',
1350 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -07001351 if targets:
1352 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
1353 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -08001354 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -08001355 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
1356 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001357 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -08001358 ([] if not args.travis else ['JENKINS_BUILD=1']) +
1359 targets,
Craig Tiller590105a2016-01-19 13:03:46 -08001360 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -07001361 else:
1362 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -08001363
murgatroid99a3e244f2015-09-22 11:25:53 -07001364make_targets = {}
1365for l in languages:
1366 makefile = l.makefile_name()
1367 make_targets[makefile] = make_targets.get(makefile, set()).union(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001368 set(l.make_targets()))
Craig Tiller5058c692015-04-08 09:42:04 -07001369
Jan Tattermusche4a69182015-12-15 09:53:01 -08001370def build_step_environ(cfg):
1371 environ = {'CONFIG': cfg}
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001372 msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -08001373 if msbuild_cfg:
1374 environ['MSBUILD_CONFIG'] = msbuild_cfg
1375 return environ
1376
murgatroid99fddac962015-09-22 09:20:11 -07001377build_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001378 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -07001379 for l in languages
1380 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -07001381if make_targets:
siddharthshukla0589e532016-07-07 16:08:01 +02001382 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 -07001383 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -07001384build_steps.extend(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001385 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), timeout_seconds=None)
Craig Tiller547db2b2015-01-30 14:08:39 -08001386 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -07001387 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -08001388
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001389post_tests_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001390 jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001391 for l in languages
1392 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -08001393runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -08001394forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -08001395
Nicolas Nobleddef2462015-01-06 18:08:25 -08001396
Ken Paysonfa51de52016-06-30 23:50:48 -07001397def _shut_down_legacy_server(legacy_server_port):
1398 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001399 version = int(urllib.request.urlopen(
Ken Paysonfa51de52016-06-30 23:50:48 -07001400 'http://localhost:%d/version_number' % legacy_server_port,
1401 timeout=10).read())
1402 except:
1403 pass
1404 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001405 urllib.request.urlopen(
Ken Paysonfa51de52016-06-30 23:50:48 -07001406 'http://localhost:%d/quitquitquit' % legacy_server_port).read()
1407
1408
Adele Zhoud5fffa52015-10-23 15:51:42 -07001409def _calculate_num_runs_failures(list_of_results):
1410 """Caculate number of runs and failures for a particular test.
1411
1412 Args:
1413 list_of_results: (List) of JobResult object.
1414 Returns:
1415 A tuple of total number of runs and failures.
1416 """
1417 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1418 num_failures = 0
1419 for jobresult in list_of_results:
1420 if jobresult.retries > 0:
1421 num_runs += jobresult.retries
1422 if jobresult.num_failures > 0:
1423 num_failures += jobresult.num_failures
1424 return num_runs, num_failures
1425
Adele Zhou6b9527c2015-11-20 15:56:35 -08001426
Craig Tillereb9de8b2016-01-08 08:57:41 -08001427# _build_and_run results
1428class BuildAndRunError(object):
1429
1430 BUILD = object()
1431 TEST = object()
1432 POST_TEST = object()
1433
1434
Craig Tiller819cd882017-04-25 13:18:22 -07001435def _has_epollexclusive():
1436 try:
1437 subprocess.check_call('bins/%s/check_epollexclusive' % args.config)
1438 return True
1439 except subprocess.CalledProcessError, e:
1440 return False
1441
1442
Craig Tillereb9de8b2016-01-08 08:57:41 -08001443# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001444def _build_and_run(
Craig Tiller74189cd2016-06-23 15:39:06 -07001445 check_cancelled, newline_on_success, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001446 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001447 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001448 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001449 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001450 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001451 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001452 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001453
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001454 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001455 if xml_report:
Jan Tattermuschcfcc0752016-10-09 17:02:34 +02001456 report_utils.render_junit_xml_report(resultset, xml_report,
1457 suite_name=args.report_suite_name)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001458 return []
ctiller3040cb72015-01-07 12:13:17 -08001459
Craig Tiller819cd882017-04-25 13:18:22 -07001460 if not args.travis and not _has_epollexclusive() and 'epollex' in _POLLING_STRATEGIES[platform_string()]:
1461 print('\n\nOmitting EPOLLEXCLUSIVE tests\n\n')
1462 _POLLING_STRATEGIES[platform_string()].remove('epollex')
1463
Craig Tiller234b6e72015-05-23 10:12:40 -07001464 # start antagonists
Jan Tattermusch5c79a312016-12-20 11:02:50 +01001465 antagonists = [subprocess.Popen(['tools/run_tests/python_utils/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001466 for _ in range(0, args.antagonists)]
Craig Tillercba864b2017-02-17 10:27:56 -08001467 start_port_server.start_port_server()
Adele Zhou7cf72112015-11-04 11:18:43 -08001468 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001469 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001470 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001471 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001472 one_run = set(
1473 spec
yang-g6c1fdc62015-08-18 11:57:42 -07001474 for language in languages
Jan Tattermusch77db4322016-02-20 20:19:35 -08001475 for spec in language.test_specs()
Vijay Pai488fd0e2016-06-13 12:37:12 -07001476 if (re.search(args.regex, spec.shortname) and
1477 (args.regex_exclude == '' or
1478 not re.search(args.regex_exclude, spec.shortname))))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001479 # When running on travis, we want out test runs to be as similar as possible
1480 # for reproducibility purposes.
Craig Tillera1ac2a12017-04-21 07:20:38 -07001481 if args.travis and args.max_time <= 0:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001482 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1483 else:
1484 # whereas otherwise, we want to shuffle things up to give all tests a
1485 # chance to run.
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001486 massaged_one_run = list(one_run) # random.sample needs an indexable seq.
1487 num_jobs = len(massaged_one_run)
1488 # for a random sample, get as many as indicated by the 'sample_percent'
1489 # argument. By default this arg is 100, resulting in a shuffle of all
1490 # jobs.
1491 sample_size = int(num_jobs * args.sample_percent/100.0)
1492 massaged_one_run = random.sample(massaged_one_run, sample_size)
1493 if not isclose(args.sample_percent, 100.0):
David Garcia Quintase2bdbfe2017-03-08 11:55:07 -08001494 assert args.runs_per_test == 1, "Can't do sampling (-p) over multiple runs (-n)."
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001495 print("Running %d tests out of %d (~%d%%)" %
1496 (sample_size, num_jobs, args.sample_percent))
Craig Tillerf7b7c892015-06-22 14:33:25 -07001497 if infinite_runs:
1498 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 -07001499 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1500 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001501 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001502
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001503 if args.quiet_success:
1504 jobset.message('START', 'Running tests quietly, only failing tests will be reported', do_newline=True)
Adele Zhou803af152015-11-30 15:16:16 -08001505 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001506 all_runs, check_cancelled, newline_on_success=newline_on_success,
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001507 travis=args.travis, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001508 stop_on_failure=args.stop_on_failure,
Craig Tillera1ac2a12017-04-21 07:20:38 -07001509 quiet_success=args.quiet_success, max_time=args.max_time)
Adele Zhoud5fffa52015-10-23 15:51:42 -07001510 if resultset:
Craig Tiller2b59dbc2016-05-13 15:59:09 -07001511 for k, v in sorted(resultset.items()):
Adele Zhoud5fffa52015-10-23 15:51:42 -07001512 num_runs, num_failures = _calculate_num_runs_failures(v)
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001513 if num_failures > 0:
1514 if num_failures == num_runs: # what about infinite_runs???
1515 jobset.message('FAILED', k, do_newline=True)
1516 else:
1517 jobset.message(
1518 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1519 do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001520 finally:
1521 for antagonist in antagonists:
1522 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001523 if xml_report and resultset:
Jan Tattermuschcfcc0752016-10-09 17:02:34 +02001524 report_utils.render_junit_xml_report(resultset, xml_report,
1525 suite_name=args.report_suite_name)
Craig Tillerd86a3942015-01-14 12:48:54 -08001526
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001527 number_failures, _ = jobset.run(
1528 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001529 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001530
1531 out = []
1532 if number_failures:
1533 out.append(BuildAndRunError.POST_TEST)
1534 if num_test_failures:
1535 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001536
Craig Tillereb9de8b2016-01-08 08:57:41 -08001537 return out
ctiller3040cb72015-01-07 12:13:17 -08001538
1539
1540if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001541 success = True
ctiller3040cb72015-01-07 12:13:17 -08001542 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001543 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001544 initial_time = dw.most_recent_change()
1545 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001546 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001547 errors = _build_and_run(check_cancelled=have_files_changed,
1548 newline_on_success=False,
Craig Tillereb9de8b2016-01-08 08:57:41 -08001549 build_only=args.build_only) == 0
1550 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001551 jobset.message('SUCCESS',
1552 'All tests are now passing properly',
1553 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001554 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001555 while not have_files_changed():
1556 time.sleep(1)
1557else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001558 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001559 newline_on_success=args.newline_on_success,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001560 xml_report=args.xml_report,
1561 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001562 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001563 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1564 else:
1565 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001566 exit_code = 0
1567 if BuildAndRunError.BUILD in errors:
1568 exit_code |= 1
Jan Tattermusche480a6a2016-10-07 12:59:08 +02001569 if BuildAndRunError.TEST in errors:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001570 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001571 if BuildAndRunError.POST_TEST in errors:
1572 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001573 sys.exit(exit_code)