blob: 4146eec42df6e10d58d134ecb5112e6bde7c79a9 [file] [log] [blame]
Tsuyoshi Ozawa4e0238d2016-09-20 05:56:10 +09001#!/usr/bin/env python
Jan Tattermusch7897ae92017-06-07 22:57:36 +02002# Copyright 2015 gRPC authors.
Craig Tillerc2c79212015-02-16 12:00:01 -08003#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02004# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
Craig Tillerc2c79212015-02-16 12:00:01 -08007#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02008# http://www.apache.org/licenses/LICENSE-2.0
Craig Tillerc2c79212015-02-16 12:00:01 -08009#
Jan Tattermusch7897ae92017-06-07 22:57:36 +020010# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
Nicolas Nobleddef2462015-01-06 18:08:25 -080015"""Run tests in parallel."""
16
siddharthshukla0589e532016-07-07 16:08:01 +020017from __future__ import print_function
18
Nicolas Nobleddef2462015-01-06 18:08:25 -080019import argparse
Craig Tiller9279ac22016-01-20 17:05:23 -080020import ast
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070021import collections
Nicolas Nobleddef2462015-01-06 18:08:25 -080022import glob
23import itertools
Craig Tiller261dd982015-01-16 16:41:45 -080024import json
David Garcia Quintas0727c102017-02-21 10:48:35 -080025import logging
Nicolas Nobleddef2462015-01-06 18:08:25 -080026import multiprocessing
Craig Tiller1cc11db2015-01-15 22:50:50 -080027import os
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070028import os.path
Craig Tiller38fb8de2016-07-13 08:23:32 -070029import pipes
David Garcia Quintas79e389f2015-06-02 17:49:42 -070030import platform
31import random
Craig Tillerfe406ec2015-02-24 13:55:12 -080032import re
Craig Tiller82875232015-09-25 13:57:34 -070033import socket
David Garcia Quintas79e389f2015-06-02 17:49:42 -070034import subprocess
Nicolas Nobleddef2462015-01-06 18:08:25 -080035import sys
Craig Tillerf0a293e2015-10-12 10:05:50 -070036import tempfile
37import traceback
ctiller3040cb72015-01-07 12:13:17 -080038import time
siddharthshukla0589e532016-07-07 16:08:01 +020039from six.moves import urllib
Jan Tattermusch03c01062015-12-11 14:28:56 -080040import uuid
Siddharth Shuklad194f592017-03-11 19:12:43 +010041import six
Nicolas Nobleddef2462015-01-06 18:08:25 -080042
Jan Tattermusch5c79a312016-12-20 11:02:50 +010043import python_utils.jobset as jobset
44import python_utils.report_utils as report_utils
45import python_utils.watch_dirs as watch_dirs
Craig Tiller7dc4ea62017-02-02 16:08:05 -080046import python_utils.start_port_server as start_port_server
Matt Kwong52ff9862017-04-17 13:56:51 -070047try:
ncteisen888093c2017-12-11 18:00:40 -080048 from python_utils.upload_test_results import upload_results_to_bq
Matt Kwong52ff9862017-04-17 13:56:51 -070049except (ImportError):
ncteisen888093c2017-12-11 18:00:40 -080050 pass # It's ok to not import because this is only necessary to upload results to BQ.
Craig Tillerb361b4e2016-01-06 11:44:17 -080051
ncteisen888093c2017-12-11 18:00:40 -080052gcp_utils_dir = os.path.abspath(
53 os.path.join(os.path.dirname(__file__), '../gcp/utils'))
David Garcia Quintasfaafa4d2017-06-06 14:52:17 -070054sys.path.append(gcp_utils_dir)
David Garcia Quintasfaafa4d2017-06-06 14:52:17 -070055
Jan Tattermusch3b5121b2016-02-22 17:41:05 -080056_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
57os.chdir(_ROOT)
Craig Tiller2cc2b842015-02-27 11:38:31 -080058
Craig Tiller8f18ee62016-07-18 08:00:33 -070059_FORCE_ENVIRON_FOR_WRAPPERS = {
ncteisen888093c2017-12-11 18:00:40 -080060 'GRPC_VERBOSITY': 'DEBUG',
Craig Tiller8f18ee62016-07-18 08:00:33 -070061}
Craig Tiller06805272015-06-11 14:46:47 -070062
Craig Tiller123f1372016-06-15 15:06:14 -070063_POLLING_STRATEGIES = {
ncteisen888093c2017-12-11 18:00:40 -080064 'linux': ['epollex', 'epollsig', 'epoll1', 'poll', 'poll-cv'],
65 'mac': ['poll'],
Craig Tiller123f1372016-06-15 15:06:14 -070066}
67
Craig Tiller9992bdb2017-09-06 15:00:31 -070068BigQueryTestData = collections.namedtuple('BigQueryTestData', 'name flaky cpu')
69
70
71def get_bqtest_data(limit=None):
ncteisen888093c2017-12-11 18:00:40 -080072 import big_query_utils
Craig Tillerd16abf82017-06-07 08:58:55 -070073
ncteisen888093c2017-12-11 18:00:40 -080074 bq = big_query_utils.create_big_query()
75 query = """
David Garcia Quintas48623592017-08-02 18:15:22 -070076SELECT
77 filtered_test_name,
Craig Tiller120d4fd2017-09-07 12:25:25 -070078 SUM(result != 'PASSED' AND result != 'SKIPPED') > 0 as flaky,
Craig Tillerf7617bb2017-09-13 09:47:28 -070079 MAX(cpu_measured) + 0.01 as cpu
David Garcia Quintas48623592017-08-02 18:15:22 -070080 FROM (
81 SELECT
82 REGEXP_REPLACE(test_name, r'/\d+', '') AS filtered_test_name,
Craig Tiller9992bdb2017-09-06 15:00:31 -070083 result, cpu_measured
David Garcia Quintas48623592017-08-02 18:15:22 -070084 FROM
85 [grpc-testing:jenkins_test_results.aggregate_results]
86 WHERE
87 timestamp >= DATE_ADD(CURRENT_DATE(), -1, "WEEK")
ncteisen888093c2017-12-11 18:00:40 -080088 AND platform = '""" + platform_string() + """'
David Garcia Quintas48623592017-08-02 18:15:22 -070089 AND NOT REGEXP_MATCH(job_name, '.*portability.*') )
90GROUP BY
Craig Tillerf7617bb2017-09-13 09:47:28 -070091 filtered_test_name"""
ncteisen888093c2017-12-11 18:00:40 -080092 if limit:
93 query += " limit {}".format(limit)
94 query_job = big_query_utils.sync_query_job(bq, 'grpc-testing', query)
95 page = bq.jobs().getQueryResults(
96 pageToken=None, **query_job['jobReference']).execute(num_retries=3)
97 test_data = [
98 BigQueryTestData(row['f'][0]['v'], row['f'][1]['v'] == 'true',
99 float(row['f'][2]['v'])) for row in page['rows']
100 ]
101 return test_data
David Garcia Quintasfaafa4d2017-06-06 14:52:17 -0700102
103
Craig Tillerd50993d2015-08-05 08:04:36 -0700104def platform_string():
ncteisen888093c2017-12-11 18:00:40 -0800105 return jobset.platform_string()
Craig Tillerd50993d2015-08-05 08:04:36 -0700106
107
Craig Tiller38fb8de2016-07-13 08:23:32 -0700108_DEFAULT_TIMEOUT_SECONDS = 5 * 60
109
ncteisen888093c2017-12-11 18:00:40 -0800110
David Garcia Quintas03920252017-02-15 12:51:21 -0800111def run_shell_command(cmd, env=None, cwd=None):
ncteisen888093c2017-12-11 18:00:40 -0800112 try:
113 subprocess.check_output(cmd, shell=True, env=env, cwd=cwd)
114 except subprocess.CalledProcessError as e:
115 logging.exception(
116 "Error while running command '%s'. Exit status %d. Output:\n%s",
117 e.cmd, e.returncode, e.output)
118 raise
119
Craig Tiller38fb8de2016-07-13 08:23:32 -0700120
Alexander Polcyndbfcd452017-10-01 15:34:29 -0700121def max_parallel_tests_for_current_platform():
ncteisen888093c2017-12-11 18:00:40 -0800122 # Too much test parallelization has only been seen to be a problem
123 # so far on windows.
124 if jobset.platform_string() == 'windows':
125 return 64
126 return 1024
127
Alexander Polcyndbfcd452017-10-01 15:34:29 -0700128
Craig Tiller738c3342015-01-12 14:28:33 -0800129# SimpleConfig: just compile with CONFIG=config, and run the binary to test
Craig Tillera0f85172016-01-20 15:56:06 -0800130class Config(object):
Craig Tillerb50d1662015-01-15 17:28:21 -0800131
ncteisen888093c2017-12-11 18:00:40 -0800132 def __init__(self,
133 config,
134 environ=None,
135 timeout_multiplier=1,
136 tool_prefix=[],
137 iomgr_platform='native'):
138 if environ is None:
139 environ = {}
140 self.build_config = config
141 self.environ = environ
142 self.environ['CONFIG'] = config
143 self.tool_prefix = tool_prefix
144 self.timeout_multiplier = timeout_multiplier
145 self.iomgr_platform = iomgr_platform
Craig Tiller738c3342015-01-12 14:28:33 -0800146
ncteisen888093c2017-12-11 18:00:40 -0800147 def job_spec(self,
148 cmdline,
149 timeout_seconds=_DEFAULT_TIMEOUT_SECONDS,
150 shortname=None,
151 environ={},
152 cpu_cost=1.0,
153 flaky=False):
154 """Construct a jobset.JobSpec for a test under this config
Craig Tiller49f61322015-03-03 13:02:11 -0800155
156 Args:
157 cmdline: a list of strings specifying the command line the test
158 would like to run
Craig Tiller49f61322015-03-03 13:02:11 -0800159 """
ncteisen888093c2017-12-11 18:00:40 -0800160 actual_environ = self.environ.copy()
161 for k, v in environ.items():
162 actual_environ[k] = v
163 if not flaky and shortname and shortname in flaky_tests:
164 flaky = True
165 if shortname in shortname_to_cpu:
166 cpu_cost = shortname_to_cpu[shortname]
167 return jobset.JobSpec(
168 cmdline=self.tool_prefix + cmdline,
169 shortname=shortname,
170 environ=actual_environ,
171 cpu_cost=cpu_cost,
172 timeout_seconds=(self.timeout_multiplier * timeout_seconds
173 if timeout_seconds else None),
174 flake_retries=4 if flaky or args.allow_flakes else 0,
175 timeout_retries=1 if flaky or args.allow_flakes else 0)
Craig Tiller738c3342015-01-12 14:28:33 -0800176
177
ncteisen888093c2017-12-11 18:00:40 -0800178def get_c_tests(travis, test_lang):
179 out = []
180 platforms_str = 'ci_platforms' if travis else 'platforms'
181 with open('tools/run_tests/generated/tests.json') as f:
182 js = json.load(f)
183 return [
184 tgt for tgt in js
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800185 if tgt['language'] == test_lang and platform_string() in
186 tgt[platforms_str] and not (travis and tgt['flaky'])
ncteisen888093c2017-12-11 18:00:40 -0800187 ]
murgatroid99cf08daf2015-09-21 15:33:16 -0700188
murgatroid99fafeeb32015-09-22 09:13:03 -0700189
Jan Tattermusch77db4322016-02-20 20:19:35 -0800190def _check_compiler(compiler, supported_compilers):
ncteisen888093c2017-12-11 18:00:40 -0800191 if compiler not in supported_compilers:
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800192 raise Exception(
193 'Compiler %s not supported (on this platform).' % compiler)
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700194
195
196def _check_arch(arch, supported_archs):
ncteisen888093c2017-12-11 18:00:40 -0800197 if arch not in supported_archs:
198 raise Exception('Architecture %s not supported.' % arch)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800199
200
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800201def _is_use_docker_child():
ncteisen888093c2017-12-11 18:00:40 -0800202 """Returns True if running running as a --use_docker child."""
203 return True if os.getenv('RUN_TESTS_COMMAND') else False
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800204
205
ncteisen888093c2017-12-11 18:00:40 -0800206_PythonConfigVars = collections.namedtuple('_ConfigVars', [
kpayson641bfff8e2018-03-13 22:05:48 -0700207 'shell',
208 'builder',
209 'builder_prefix_arguments',
210 'venv_relative_python',
211 'toolchain',
212 'runner',
213 'test_name',
214 'iomgr_platform',
ncteisen888093c2017-12-11 18:00:40 -0800215])
siddharthshukla2135a1b2016-08-04 02:11:53 +0200216
217
218def _python_config_generator(name, major, minor, bits, config_vars):
kpayson641bfff8e2018-03-13 22:05:48 -0700219 name += '_' + config_vars.iomgr_platform
ncteisen888093c2017-12-11 18:00:40 -0800220 return PythonConfig(
221 name, config_vars.shell + config_vars.builder +
222 config_vars.builder_prefix_arguments + [
223 _python_pattern_function(major=major, minor=minor, bits=bits)
224 ] + [name] + config_vars.venv_relative_python + config_vars.toolchain,
kpayson641bfff8e2018-03-13 22:05:48 -0700225 config_vars.shell + config_vars.runner + [
226 os.path.join(name, config_vars.venv_relative_python[0]),
227 config_vars.test_name
228 ])
siddharthshukla2135a1b2016-08-04 02:11:53 +0200229
230
231def _pypy_config_generator(name, major, config_vars):
ncteisen888093c2017-12-11 18:00:40 -0800232 return PythonConfig(
233 name,
234 config_vars.shell + config_vars.builder +
235 config_vars.builder_prefix_arguments + [
236 _pypy_pattern_function(major=major)
237 ] + [name] + config_vars.venv_relative_python + config_vars.toolchain,
238 config_vars.shell + config_vars.runner +
239 [os.path.join(name, config_vars.venv_relative_python[0])])
siddharthshukla2135a1b2016-08-04 02:11:53 +0200240
241
242def _python_pattern_function(major, minor, bits):
ncteisen888093c2017-12-11 18:00:40 -0800243 # Bit-ness is handled by the test machine's environment
244 if os.name == "nt":
245 if bits == "64":
246 return '/c/Python{major}{minor}/python.exe'.format(
247 major=major, minor=minor, bits=bits)
248 else:
249 return '/c/Python{major}{minor}_{bits}bits/python.exe'.format(
250 major=major, minor=minor, bits=bits)
siddharthshukla2135a1b2016-08-04 02:11:53 +0200251 else:
ncteisen888093c2017-12-11 18:00:40 -0800252 return 'python{major}.{minor}'.format(major=major, minor=minor)
siddharthshukla2135a1b2016-08-04 02:11:53 +0200253
254
255def _pypy_pattern_function(major):
ncteisen888093c2017-12-11 18:00:40 -0800256 if major == '2':
257 return 'pypy'
258 elif major == '3':
259 return 'pypy3'
260 else:
261 raise ValueError("Unknown PyPy major version")
siddharthshukla2135a1b2016-08-04 02:11:53 +0200262
263
Craig Tillerc7449162015-01-16 14:42:10 -0800264class CLanguage(object):
265
ncteisen888093c2017-12-11 18:00:40 -0800266 def __init__(self, make_target, test_lang):
267 self.make_target = make_target
268 self.platform = platform_string()
269 self.test_lang = test_lang
Craig Tillerc7449162015-01-16 14:42:10 -0800270
ncteisen888093c2017-12-11 18:00:40 -0800271 def configure(self, config, args):
272 self.config = config
273 self.args = args
Craig Tillerb38197e2016-02-26 10:14:54 -0800274 if self.platform == 'windows':
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800275 _check_compiler(
276 self.args.compiler,
277 ['default', 'cmake', 'cmake_vs2015', 'cmake_vs2017'])
ncteisen888093c2017-12-11 18:00:40 -0800278 _check_arch(self.args.arch, ['default', 'x64', 'x86'])
279 self._cmake_generator_option = 'Visual Studio 15 2017' if self.args.compiler == 'cmake_vs2017' else 'Visual Studio 14 2015'
280 self._cmake_arch_option = 'x64' if self.args.arch == 'x64' else 'Win32'
281 self._use_cmake = True
282 self._make_options = []
283 elif self.args.compiler == 'cmake':
284 _check_arch(self.args.arch, ['default'])
285 self._use_cmake = True
286 self._docker_distro = 'jessie'
287 self._make_options = []
Craig Tillerca62ff02016-02-24 22:22:57 -0800288 else:
ncteisen888093c2017-12-11 18:00:40 -0800289 self._use_cmake = False
290 self._docker_distro, self._make_options = self._compiler_options(
291 self.args.use_docker, self.args.compiler)
292 if args.iomgr_platform == "uv":
kpayson641bfff8e2018-03-13 22:05:48 -0700293 cflags = '-DGRPC_UV -DGRPC_CUSTOM_IOMGR_THREAD_CHECK -DGRPC_CUSTOM_SOCKET '
ncteisen888093c2017-12-11 18:00:40 -0800294 try:
295 cflags += subprocess.check_output(
296 ['pkg-config', '--cflags', 'libuv']).strip() + ' '
297 except (subprocess.CalledProcessError, OSError):
298 pass
299 try:
300 ldflags = subprocess.check_output(
301 ['pkg-config', '--libs', 'libuv']).strip() + ' '
302 except (subprocess.CalledProcessError, OSError):
303 ldflags = '-luv '
304 self._make_options += [
305 'EXTRA_CPPFLAGS={}'.format(cflags),
306 'EXTRA_LDLIBS={}'.format(ldflags)
307 ]
ncteisend439b4e2017-09-11 17:57:18 -0700308
ncteisen888093c2017-12-11 18:00:40 -0800309 def test_specs(self):
310 out = []
311 binaries = get_c_tests(self.args.travis, self.test_lang)
312 for target in binaries:
313 if self._use_cmake and target.get('boringssl', False):
314 # cmake doesn't build boringssl tests
315 continue
316 auto_timeout_scaling = target.get('auto_timeout_scaling', True)
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800317 polling_strategies = (_POLLING_STRATEGIES.get(
318 self.platform, ['all']) if target.get('uses_polling', True) else
319 ['none'])
ncteisen888093c2017-12-11 18:00:40 -0800320 if self.args.iomgr_platform == 'uv':
321 polling_strategies = ['all']
322 for polling_strategy in polling_strategies:
323 env = {
324 'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
325 _ROOT + '/src/core/tsi/test_creds/ca.pem',
326 'GRPC_POLL_STRATEGY':
327 polling_strategy,
328 'GRPC_VERBOSITY':
329 'DEBUG'
330 }
331 resolver = os.environ.get('GRPC_DNS_RESOLVER', None)
332 if resolver:
333 env['GRPC_DNS_RESOLVER'] = resolver
334 shortname_ext = '' if polling_strategy == 'all' else ' GRPC_POLL_STRATEGY=%s' % polling_strategy
335 if polling_strategy in target.get('excluded_poll_engines', []):
336 continue
Craig Tillerc7449162015-01-16 14:42:10 -0800337
ncteisen888093c2017-12-11 18:00:40 -0800338 timeout_scaling = 1
339 if auto_timeout_scaling:
340 config = self.args.config
341 if ('asan' in config or config == 'msan' or
342 config == 'tsan' or config == 'ubsan' or
343 config == 'helgrind' or config == 'memcheck'):
344 # Scale overall test timeout if running under various sanitizers.
345 # scaling value is based on historical data analysis
346 timeout_scaling *= 3
347 elif polling_strategy == 'poll-cv':
348 # scale test timeout if running with poll-cv
349 # sanitizer and poll-cv scaling is not cumulative to ensure
350 # reasonable timeout values.
351 # TODO(jtattermusch): based on historical data and 5min default
352 # test timeout poll-cv scaling is currently not useful.
353 # Leaving here so it can be reintroduced if the default test timeout
354 # is decreased in the future.
355 timeout_scaling *= 1
Craig Tillerc7449162015-01-16 14:42:10 -0800356
ncteisen888093c2017-12-11 18:00:40 -0800357 if self.config.build_config in target['exclude_configs']:
358 continue
359 if self.args.iomgr_platform in target.get('exclude_iomgrs', []):
360 continue
361 if self.platform == 'windows':
362 binary = 'cmake/build/%s/%s.exe' % (
363 _MSBUILD_CONFIG[self.config.build_config],
364 target['name'])
365 else:
366 if self._use_cmake:
367 binary = 'cmake/build/%s' % target['name']
368 else:
369 binary = 'bins/%s/%s' % (self.config.build_config,
370 target['name'])
371 cpu_cost = target['cpu_cost']
372 if cpu_cost == 'capacity':
373 cpu_cost = multiprocessing.cpu_count()
374 if os.path.isfile(binary):
375 list_test_command = None
376 filter_test_command = None
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800377
ncteisen888093c2017-12-11 18:00:40 -0800378 # these are the flag defined by gtest and benchmark framework to list
379 # and filter test runs. We use them to split each individual test
380 # into its own JobSpec, and thus into its own process.
381 if 'benchmark' in target and target['benchmark']:
382 with open(os.devnull, 'w') as fnull:
383 tests = subprocess.check_output(
384 [binary, '--benchmark_list_tests'],
385 stderr=fnull)
386 for line in tests.split('\n'):
387 test = line.strip()
388 if not test: continue
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800389 cmdline = [binary,
390 '--benchmark_filter=%s$' % test
ncteisen888093c2017-12-11 18:00:40 -0800391 ] + target['args']
392 out.append(
393 self.config.job_spec(
394 cmdline,
395 shortname='%s %s' % (' '.join(cmdline),
396 shortname_ext),
397 cpu_cost=cpu_cost,
ncteisene2612aa2017-12-19 15:00:35 -0800398 timeout_seconds=target.get(
399 'timeout_seconds',
400 _DEFAULT_TIMEOUT_SECONDS) *
ncteisen888093c2017-12-11 18:00:40 -0800401 timeout_scaling,
402 environ=env))
403 elif 'gtest' in target and target['gtest']:
404 # here we parse the output of --gtest_list_tests to build up a complete
405 # list of the tests contained in a binary for each test, we then
406 # add a job to run, filtering for just that test.
407 with open(os.devnull, 'w') as fnull:
408 tests = subprocess.check_output(
409 [binary, '--gtest_list_tests'], stderr=fnull)
410 base = None
411 for line in tests.split('\n'):
412 i = line.find('#')
413 if i >= 0: line = line[:i]
414 if not line: continue
415 if line[0] != ' ':
416 base = line.strip()
417 else:
418 assert base is not None
419 assert line[1] == ' '
420 test = base + line.strip()
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800421 cmdline = [binary,
422 '--gtest_filter=%s' % test
ncteisen888093c2017-12-11 18:00:40 -0800423 ] + target['args']
424 out.append(
425 self.config.job_spec(
426 cmdline,
427 shortname='%s %s' % (' '.join(cmdline),
428 shortname_ext),
429 cpu_cost=cpu_cost,
430 timeout_seconds=target.get(
431 'timeout_seconds',
432 _DEFAULT_TIMEOUT_SECONDS) *
433 timeout_scaling,
434 environ=env))
435 else:
436 cmdline = [binary] + target['args']
437 shortname = target.get('shortname', ' '.join(
438 pipes.quote(arg) for arg in cmdline))
439 shortname += shortname_ext
440 out.append(
441 self.config.job_spec(
442 cmdline,
443 shortname=shortname,
444 cpu_cost=cpu_cost,
445 flaky=target.get('flaky', False),
446 timeout_seconds=target.get(
447 'timeout_seconds', _DEFAULT_TIMEOUT_SECONDS)
448 * timeout_scaling,
449 environ=env))
450 elif self.args.regex == '.*' or self.platform == 'windows':
451 print('\nWARNING: binary not found, skipping', binary)
452 return sorted(out)
murgatroid99256d3df2015-09-21 16:58:02 -0700453
ncteisen888093c2017-12-11 18:00:40 -0800454 def make_targets(self):
455 if self.platform == 'windows':
456 # don't build tools on windows just yet
457 return ['buildtests_%s' % self.make_target]
458 return [
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800459 'buildtests_%s' % self.make_target,
460 'tools_%s' % self.make_target, 'check_epollexclusive'
ncteisen888093c2017-12-11 18:00:40 -0800461 ]
Craig Tillerc7449162015-01-16 14:42:10 -0800462
ncteisen888093c2017-12-11 18:00:40 -0800463 def make_options(self):
464 return self._make_options
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200465
ncteisen888093c2017-12-11 18:00:40 -0800466 def pre_build_steps(self):
467 if self.platform == 'windows':
468 return [[
469 'tools\\run_tests\\helper_scripts\\pre_build_cmake.bat',
470 self._cmake_generator_option, self._cmake_arch_option
471 ]]
472 elif self._use_cmake:
473 return [['tools/run_tests/helper_scripts/pre_build_cmake.sh']]
474 else:
475 return []
murgatroid99a3e244f2015-09-22 11:25:53 -0700476
ncteisen888093c2017-12-11 18:00:40 -0800477 def build_steps(self):
478 return []
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800479
ncteisen888093c2017-12-11 18:00:40 -0800480 def post_tests_steps(self):
481 if self.platform == 'windows':
482 return []
483 else:
484 return [['tools/run_tests/helper_scripts/post_tests_c.sh']]
Jan Tattermusch9bb70622016-03-18 10:28:54 -0700485
ncteisen888093c2017-12-11 18:00:40 -0800486 def makefile_name(self):
487 if self._use_cmake:
488 return 'cmake/build/Makefile'
489 else:
490 return 'Makefile'
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800491
ncteisen888093c2017-12-11 18:00:40 -0800492 def _clang_make_options(self, version_suffix=''):
493 return [
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800494 'CC=clang%s' % version_suffix,
495 'CXX=clang++%s' % version_suffix,
496 'LD=clang%s' % version_suffix,
497 'LDXX=clang++%s' % version_suffix
ncteisen888093c2017-12-11 18:00:40 -0800498 ]
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800499
ncteisen888093c2017-12-11 18:00:40 -0800500 def _gcc_make_options(self, version_suffix):
501 return [
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800502 'CC=gcc%s' % version_suffix,
503 'CXX=g++%s' % version_suffix,
504 'LD=gcc%s' % version_suffix,
505 'LDXX=g++%s' % version_suffix
ncteisen888093c2017-12-11 18:00:40 -0800506 ]
Jan Tattermusch788ee232016-01-26 12:19:44 -0800507
ncteisen888093c2017-12-11 18:00:40 -0800508 def _compiler_options(self, use_docker, compiler):
509 """Returns docker distro and make options to use for given compiler."""
510 if not use_docker and not _is_use_docker_child():
511 _check_compiler(compiler, ['default'])
512
513 if compiler == 'gcc4.9' or compiler == 'default':
514 return ('jessie', [])
515 elif compiler == 'gcc4.8':
516 return ('jessie', self._gcc_make_options(version_suffix='-4.8'))
517 elif compiler == 'gcc5.3':
518 return ('ubuntu1604', [])
Jan Tattermusch0614a682018-01-23 11:51:21 +0100519 elif compiler == 'gcc7.2':
520 return ('ubuntu1710', [])
ncteisen888093c2017-12-11 18:00:40 -0800521 elif compiler == 'gcc_musl':
522 return ('alpine', [])
523 elif compiler == 'clang3.4':
524 # on ubuntu1404, clang-3.4 alias doesn't exist, just use 'clang'
525 return ('ubuntu1404', self._clang_make_options())
526 elif compiler == 'clang3.5':
527 return ('jessie', self._clang_make_options(version_suffix='-3.5'))
528 elif compiler == 'clang3.6':
529 return ('ubuntu1604',
530 self._clang_make_options(version_suffix='-3.6'))
531 elif compiler == 'clang3.7':
532 return ('ubuntu1604',
533 self._clang_make_options(version_suffix='-3.7'))
534 else:
535 raise Exception('Compiler %s not supported.' % compiler)
536
537 def dockerfile_dir(self):
538 return 'tools/dockerfile/test/cxx_%s_%s' % (
539 self._docker_distro, _docker_arch_suffix(self.args.arch))
540
541 def __str__(self):
542 return self.make_target
murgatroid99132ce6a2015-03-04 17:29:14 -0800543
Craig Tillercc0535d2015-12-08 15:14:47 -0800544
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700545# This tests Node on grpc/grpc-node and will become the standard for Node testing
546class RemoteNodeLanguage(object):
547
ncteisen888093c2017-12-11 18:00:40 -0800548 def __init__(self):
549 self.platform = platform_string()
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700550
ncteisen888093c2017-12-11 18:00:40 -0800551 def configure(self, config, args):
552 self.config = config
553 self.args = args
554 # Note: electron ABI only depends on major and minor version, so that's all
555 # we should specify in the compiler argument
556 _check_compiler(self.args.compiler, [
557 'default', 'node0.12', 'node4', 'node5', 'node6', 'node7', 'node8',
558 'electron1.3', 'electron1.6'
559 ])
560 if self.args.compiler == 'default':
561 self.runtime = 'node'
562 self.node_version = '8'
563 else:
564 if self.args.compiler.startswith('electron'):
565 self.runtime = 'electron'
566 self.node_version = self.args.compiler[8:]
567 else:
568 self.runtime = 'node'
569 # Take off the word "node"
570 self.node_version = self.args.compiler[4:]
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700571
ncteisen888093c2017-12-11 18:00:40 -0800572 # TODO: update with Windows/electron scripts when available for grpc/grpc-node
573 def test_specs(self):
574 if self.platform == 'windows':
575 return [
576 self.config.job_spec(
577 ['tools\\run_tests\\helper_scripts\\run_node.bat'])
578 ]
579 else:
580 return [
581 self.config.job_spec(
582 ['tools/run_tests/helper_scripts/run_grpc-node.sh'],
583 None,
584 environ=_FORCE_ENVIRON_FOR_WRAPPERS)
585 ]
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700586
ncteisen888093c2017-12-11 18:00:40 -0800587 def pre_build_steps(self):
588 return []
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700589
ncteisen888093c2017-12-11 18:00:40 -0800590 def make_targets(self):
591 return []
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700592
ncteisen888093c2017-12-11 18:00:40 -0800593 def make_options(self):
594 return []
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700595
ncteisen888093c2017-12-11 18:00:40 -0800596 def build_steps(self):
597 return []
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700598
ncteisen888093c2017-12-11 18:00:40 -0800599 def post_tests_steps(self):
600 return []
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700601
ncteisen888093c2017-12-11 18:00:40 -0800602 def makefile_name(self):
603 return 'Makefile'
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700604
ncteisen888093c2017-12-11 18:00:40 -0800605 def dockerfile_dir(self):
606 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(
607 self.args.arch)
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700608
ncteisen888093c2017-12-11 18:00:40 -0800609 def __str__(self):
610 return 'grpc-node'
Matt Kwonge2e7cf42017-09-15 11:17:04 -0700611
612
Craig Tillerc7449162015-01-16 14:42:10 -0800613class PhpLanguage(object):
614
ncteisen888093c2017-12-11 18:00:40 -0800615 def configure(self, config, args):
616 self.config = config
617 self.args = args
618 _check_compiler(self.args.compiler, ['default'])
619 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
Jan Tattermusch77db4322016-02-20 20:19:35 -0800620
ncteisen888093c2017-12-11 18:00:40 -0800621 def test_specs(self):
622 return [
623 self.config.job_spec(
624 ['src/php/bin/run_tests.sh'],
625 environ=_FORCE_ENVIRON_FOR_WRAPPERS)
626 ]
Craig Tillerc7449162015-01-16 14:42:10 -0800627
ncteisen888093c2017-12-11 18:00:40 -0800628 def pre_build_steps(self):
629 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700630
ncteisen888093c2017-12-11 18:00:40 -0800631 def make_targets(self):
632 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800633
ncteisen888093c2017-12-11 18:00:40 -0800634 def make_options(self):
635 return self._make_options
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800636
ncteisen888093c2017-12-11 18:00:40 -0800637 def build_steps(self):
638 return [['tools/run_tests/helper_scripts/build_php.sh']]
Craig Tillerc7449162015-01-16 14:42:10 -0800639
ncteisen888093c2017-12-11 18:00:40 -0800640 def post_tests_steps(self):
641 return [['tools/run_tests/helper_scripts/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200642
ncteisen888093c2017-12-11 18:00:40 -0800643 def makefile_name(self):
644 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -0700645
ncteisen888093c2017-12-11 18:00:40 -0800646 def dockerfile_dir(self):
647 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(
648 self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800649
ncteisen888093c2017-12-11 18:00:40 -0800650 def __str__(self):
651 return 'php'
murgatroid99132ce6a2015-03-04 17:29:14 -0800652
Craig Tillerc7449162015-01-16 14:42:10 -0800653
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700654class Php7Language(object):
655
ncteisen888093c2017-12-11 18:00:40 -0800656 def configure(self, config, args):
657 self.config = config
658 self.args = args
659 _check_compiler(self.args.compiler, ['default'])
660 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700661
ncteisen888093c2017-12-11 18:00:40 -0800662 def test_specs(self):
663 return [
664 self.config.job_spec(
665 ['src/php/bin/run_tests.sh'],
666 environ=_FORCE_ENVIRON_FOR_WRAPPERS)
667 ]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700668
ncteisen888093c2017-12-11 18:00:40 -0800669 def pre_build_steps(self):
670 return []
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700671
ncteisen888093c2017-12-11 18:00:40 -0800672 def make_targets(self):
673 return ['static_c', 'shared_c']
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700674
ncteisen888093c2017-12-11 18:00:40 -0800675 def make_options(self):
676 return self._make_options
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700677
ncteisen888093c2017-12-11 18:00:40 -0800678 def build_steps(self):
679 return [['tools/run_tests/helper_scripts/build_php.sh']]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700680
ncteisen888093c2017-12-11 18:00:40 -0800681 def post_tests_steps(self):
682 return [['tools/run_tests/helper_scripts/post_tests_php.sh']]
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700683
ncteisen888093c2017-12-11 18:00:40 -0800684 def makefile_name(self):
685 return 'Makefile'
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700686
ncteisen888093c2017-12-11 18:00:40 -0800687 def dockerfile_dir(self):
688 return 'tools/dockerfile/test/php7_jessie_%s' % _docker_arch_suffix(
689 self.args.arch)
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700690
ncteisen888093c2017-12-11 18:00:40 -0800691 def __str__(self):
692 return 'php7'
Stanley Cheung2e2cdff2016-07-23 19:07:36 -0700693
694
ncteisen888093c2017-12-11 18:00:40 -0800695class PythonConfig(
696 collections.namedtuple('PythonConfig', ['name', 'build', 'run'])):
697 """Tuple of commands (named s.t. 'what it says on the tin' applies)"""
698
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700699
Nathaniel Manista840615e2015-01-22 20:31:47 +0000700class PythonLanguage(object):
701
ncteisen888093c2017-12-11 18:00:40 -0800702 def configure(self, config, args):
703 self.config = config
704 self.args = args
705 self.pythons = self._get_pythons(self.args)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800706
ncteisen888093c2017-12-11 18:00:40 -0800707 def test_specs(self):
708 # load list of known test suites
709 with open(
710 'src/python/grpcio_tests/tests/tests.json') as tests_json_file:
711 tests_json = json.load(tests_json_file)
712 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
713 return [
714 self.config.job_spec(
715 config.run,
716 timeout_seconds=5 * 60,
717 environ=dict(
718 list(environment.items()) + [(
719 'GRPC_PYTHON_TESTRUNNER_FILTER', str(suite_name))]),
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800720 shortname='%s.test.%s' % (config.name, suite_name),
721 ) for suite_name in tests_json for config in self.pythons
ncteisen888093c2017-12-11 18:00:40 -0800722 ]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000723
ncteisen888093c2017-12-11 18:00:40 -0800724 def pre_build_steps(self):
725 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700726
ncteisen888093c2017-12-11 18:00:40 -0800727 def make_targets(self):
728 return []
Nathaniel Manista840615e2015-01-22 20:31:47 +0000729
ncteisen888093c2017-12-11 18:00:40 -0800730 def make_options(self):
731 return []
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800732
ncteisen888093c2017-12-11 18:00:40 -0800733 def build_steps(self):
734 return [config.build for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000735
ncteisen888093c2017-12-11 18:00:40 -0800736 def post_tests_steps(self):
737 if self.config.build_config != 'gcov':
738 return []
739 else:
740 return [['tools/run_tests/helper_scripts/post_tests_python.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200741
ncteisen888093c2017-12-11 18:00:40 -0800742 def makefile_name(self):
743 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -0700744
ncteisen888093c2017-12-11 18:00:40 -0800745 def dockerfile_dir(self):
746 return 'tools/dockerfile/test/python_%s_%s' % (
747 self.python_manager_name(), _docker_arch_suffix(self.args.arch))
siddharthshuklac4782142016-06-28 18:48:47 +0200748
ncteisen888093c2017-12-11 18:00:40 -0800749 def python_manager_name(self):
750 if self.args.compiler in ['python3.5', 'python3.6']:
751 return 'pyenv'
752 elif self.args.compiler == 'python_alpine':
753 return 'alpine'
754 else:
755 return 'jessie'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800756
ncteisen888093c2017-12-11 18:00:40 -0800757 def _get_pythons(self, args):
758 if args.arch == 'x86':
759 bits = '32'
760 else:
761 bits = '64'
siddharthshukla2135a1b2016-08-04 02:11:53 +0200762
ncteisen888093c2017-12-11 18:00:40 -0800763 if os.name == 'nt':
764 shell = ['bash']
765 builder = [
766 os.path.abspath(
767 'tools/run_tests/helper_scripts/build_python_msys2.sh')
768 ]
769 builder_prefix_arguments = ['MINGW{}'.format(bits)]
770 venv_relative_python = ['Scripts/python.exe']
771 toolchain = ['mingw32']
772 else:
773 shell = []
774 builder = [
775 os.path.abspath(
776 'tools/run_tests/helper_scripts/build_python.sh')
777 ]
778 builder_prefix_arguments = []
779 venv_relative_python = ['bin/python']
780 toolchain = ['unix']
siddharthshukla2135a1b2016-08-04 02:11:53 +0200781
kpayson641bfff8e2018-03-13 22:05:48 -0700782 test_command = 'test_lite'
783 if args.iomgr_platform == 'gevent':
784 test_command = 'test_gevent'
ncteisen888093c2017-12-11 18:00:40 -0800785 runner = [
786 os.path.abspath('tools/run_tests/helper_scripts/run_python.sh')
787 ]
kpayson641bfff8e2018-03-13 22:05:48 -0700788
789 config_vars = _PythonConfigVars(
790 shell, builder, builder_prefix_arguments, venv_relative_python,
791 toolchain, runner, test_command, args.iomgr_platform)
ncteisen888093c2017-12-11 18:00:40 -0800792 python27_config = _python_config_generator(
793 name='py27',
794 major='2',
795 minor='7',
796 bits=bits,
797 config_vars=config_vars)
798 python34_config = _python_config_generator(
799 name='py34',
800 major='3',
801 minor='4',
802 bits=bits,
803 config_vars=config_vars)
804 python35_config = _python_config_generator(
805 name='py35',
806 major='3',
807 minor='5',
808 bits=bits,
809 config_vars=config_vars)
810 python36_config = _python_config_generator(
811 name='py36',
812 major='3',
813 minor='6',
814 bits=bits,
815 config_vars=config_vars)
816 pypy27_config = _pypy_config_generator(
817 name='pypy', major='2', config_vars=config_vars)
818 pypy32_config = _pypy_config_generator(
819 name='pypy3', major='3', config_vars=config_vars)
siddharthshukla2135a1b2016-08-04 02:11:53 +0200820
ncteisen888093c2017-12-11 18:00:40 -0800821 if args.compiler == 'default':
822 if os.name == 'nt':
823 return (python35_config,)
824 else:
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800825 return (
826 python27_config,
827 python34_config,
828 )
ncteisen888093c2017-12-11 18:00:40 -0800829 elif args.compiler == 'python2.7':
830 return (python27_config,)
831 elif args.compiler == 'python3.4':
832 return (python34_config,)
833 elif args.compiler == 'python3.5':
834 return (python35_config,)
835 elif args.compiler == 'python3.6':
836 return (python36_config,)
837 elif args.compiler == 'pypy':
838 return (pypy27_config,)
839 elif args.compiler == 'pypy3':
840 return (pypy32_config,)
841 elif args.compiler == 'python_alpine':
842 return (python27_config,)
843 elif args.compiler == 'all_the_cpythons':
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800844 return (
845 python27_config,
846 python34_config,
847 python35_config,
848 python36_config,
849 )
ncteisen888093c2017-12-11 18:00:40 -0800850 else:
851 raise Exception('Compiler %s not supported.' % args.compiler)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700852
ncteisen888093c2017-12-11 18:00:40 -0800853 def __str__(self):
854 return 'python'
murgatroid99132ce6a2015-03-04 17:29:14 -0800855
Craig Tillerd625d812015-04-08 15:52:35 -0700856
murgatroid996a4c4fa2015-02-27 12:08:57 -0800857class RubyLanguage(object):
858
ncteisen888093c2017-12-11 18:00:40 -0800859 def configure(self, config, args):
860 self.config = config
861 self.args = args
862 _check_compiler(self.args.compiler, ['default'])
Jan Tattermusch77db4322016-02-20 20:19:35 -0800863
ncteisen888093c2017-12-11 18:00:40 -0800864 def test_specs(self):
865 tests = [
866 self.config.job_spec(
867 ['tools/run_tests/helper_scripts/run_ruby.sh'],
868 timeout_seconds=10 * 60,
869 environ=_FORCE_ENVIRON_FOR_WRAPPERS)
870 ]
871 tests.append(
872 self.config.job_spec(
873 ['tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh'],
874 timeout_seconds=10 * 60,
875 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
876 return tests
murgatroid996a4c4fa2015-02-27 12:08:57 -0800877
ncteisen888093c2017-12-11 18:00:40 -0800878 def pre_build_steps(self):
879 return [['tools/run_tests/helper_scripts/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700880
ncteisen888093c2017-12-11 18:00:40 -0800881 def make_targets(self):
882 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800883
ncteisen888093c2017-12-11 18:00:40 -0800884 def make_options(self):
885 return []
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800886
ncteisen888093c2017-12-11 18:00:40 -0800887 def build_steps(self):
888 return [['tools/run_tests/helper_scripts/build_ruby.sh']]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800889
ncteisen888093c2017-12-11 18:00:40 -0800890 def post_tests_steps(self):
891 return [['tools/run_tests/helper_scripts/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200892
ncteisen888093c2017-12-11 18:00:40 -0800893 def makefile_name(self):
894 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -0700895
ncteisen888093c2017-12-11 18:00:40 -0800896 def dockerfile_dir(self):
897 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(
898 self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800899
ncteisen888093c2017-12-11 18:00:40 -0800900 def __str__(self):
901 return 'ruby'
murgatroid99132ce6a2015-03-04 17:29:14 -0800902
Craig Tillerd625d812015-04-08 15:52:35 -0700903
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800904class CSharpLanguage(object):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800905
ncteisen888093c2017-12-11 18:00:40 -0800906 def __init__(self):
907 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700908
ncteisen888093c2017-12-11 18:00:40 -0800909 def configure(self, config, args):
910 self.config = config
911 self.args = args
912 if self.platform == 'windows':
913 _check_compiler(self.args.compiler, ['coreclr', 'default'])
914 _check_arch(self.args.arch, ['default'])
915 self._cmake_arch_option = 'x64'
916 self._make_options = []
917 else:
918 _check_compiler(self.args.compiler, ['default', 'coreclr'])
919 self._docker_distro = 'jessie'
Jan Tattermusch76511a52016-06-17 14:00:57 -0700920
ncteisen888093c2017-12-11 18:00:40 -0800921 if self.platform == 'mac':
922 # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
923 self._make_options = ['EMBED_OPENSSL=true']
924 if self.args.compiler != 'coreclr':
925 # On Mac, official distribution of mono is 32bit.
926 self._make_options += ['ARCH_FLAGS=-m32', 'LDFLAGS=-m32']
927 else:
928 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
Jan Tattermusch77db4322016-02-20 20:19:35 -0800929
ncteisen888093c2017-12-11 18:00:40 -0800930 def test_specs(self):
931 with open('src/csharp/tests.json') as f:
932 tests_by_assembly = json.load(f)
Jan Tattermusch03c01062015-12-11 14:28:56 -0800933
ncteisen888093c2017-12-11 18:00:40 -0800934 msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
935 nunit_args = ['--labels=All', '--noresult', '--workers=1']
936 assembly_subdir = 'bin/%s' % msbuild_config
937 assembly_extension = '.exe'
Jan Tattermusch76511a52016-06-17 14:00:57 -0700938
ncteisen888093c2017-12-11 18:00:40 -0800939 if self.args.compiler == 'coreclr':
940 assembly_subdir += '/netcoreapp1.0'
941 runtime_cmd = ['dotnet', 'exec']
942 assembly_extension = '.dll'
943 else:
944 assembly_subdir += '/net45'
945 if self.platform == 'windows':
946 runtime_cmd = []
947 else:
948 runtime_cmd = ['mono']
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700949
ncteisen888093c2017-12-11 18:00:40 -0800950 specs = []
951 for assembly in six.iterkeys(tests_by_assembly):
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800952 assembly_file = 'src/csharp/%s/%s/%s%s' % (assembly,
953 assembly_subdir,
954 assembly,
955 assembly_extension)
ncteisen888093c2017-12-11 18:00:40 -0800956 if self.config.build_config != 'gcov' or self.platform != 'windows':
957 # normally, run each test as a separate process
958 for test in tests_by_assembly[assembly]:
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800959 cmdline = runtime_cmd + [assembly_file,
960 '--test=%s' % test] + nunit_args
ncteisen888093c2017-12-11 18:00:40 -0800961 specs.append(
962 self.config.job_spec(
963 cmdline,
964 shortname='csharp.%s' % test,
965 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
966 else:
967 # For C# test coverage, run all tests from the same assembly at once
968 # using OpenCover.Console (only works on Windows).
969 cmdline = [
970 'src\\csharp\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe',
971 '-target:%s' % assembly_file, '-targetdir:src\\csharp',
972 '-targetargs:%s' % ' '.join(nunit_args),
973 '-filter:+[Grpc.Core]*', '-register:user',
974 '-output:src\\csharp\\coverage_csharp_%s.xml' % assembly
975 ]
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700976
ncteisen888093c2017-12-11 18:00:40 -0800977 # set really high cpu_cost to make sure instances of OpenCover.Console run exclusively
978 # to prevent problems with registering the profiler.
979 run_exclusive = 1000000
980 specs.append(
981 self.config.job_spec(
982 cmdline,
983 shortname='csharp.coverage.%s' % assembly,
984 cpu_cost=run_exclusive,
985 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
986 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800987
ncteisen888093c2017-12-11 18:00:40 -0800988 def pre_build_steps(self):
989 if self.platform == 'windows':
990 return [[
991 'tools\\run_tests\\helper_scripts\\pre_build_csharp.bat',
992 self._cmake_arch_option
993 ]]
994 else:
995 return [['tools/run_tests/helper_scripts/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700996
ncteisen888093c2017-12-11 18:00:40 -0800997 def make_targets(self):
998 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800999
ncteisen888093c2017-12-11 18:00:40 -08001000 def make_options(self):
1001 return self._make_options
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001002
ncteisen888093c2017-12-11 18:00:40 -08001003 def build_steps(self):
1004 if self.platform == 'windows':
1005 return [['tools\\run_tests\\helper_scripts\\build_csharp.bat']]
1006 else:
1007 return [['tools/run_tests/helper_scripts/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +00001008
ncteisen888093c2017-12-11 18:00:40 -08001009 def post_tests_steps(self):
1010 if self.platform == 'windows':
1011 return [['tools\\run_tests\\helper_scripts\\post_tests_csharp.bat']]
1012 else:
1013 return [['tools/run_tests/helper_scripts/post_tests_csharp.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001014
ncteisen888093c2017-12-11 18:00:40 -08001015 def makefile_name(self):
1016 if self.platform == 'windows':
1017 return 'cmake/build/%s/Makefile' % self._cmake_arch_option
1018 else:
1019 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -07001020
ncteisen888093c2017-12-11 18:00:40 -08001021 def dockerfile_dir(self):
1022 return 'tools/dockerfile/test/csharp_%s_%s' % (
1023 self._docker_distro, _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -08001024
ncteisen888093c2017-12-11 18:00:40 -08001025 def __str__(self):
1026 return 'csharp'
murgatroid99132ce6a2015-03-04 17:29:14 -08001027
Craig Tillerd625d812015-04-08 15:52:35 -07001028
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -07001029class ObjCLanguage(object):
1030
ncteisen888093c2017-12-11 18:00:40 -08001031 def configure(self, config, args):
1032 self.config = config
1033 self.args = args
1034 _check_compiler(self.args.compiler, ['default'])
Jan Tattermusch77db4322016-02-20 20:19:35 -08001035
ncteisen888093c2017-12-11 18:00:40 -08001036 def test_specs(self):
1037 return [
1038 self.config.job_spec(
1039 ['src/objective-c/tests/run_tests.sh'],
1040 timeout_seconds=60 * 60,
1041 shortname='objc-tests',
1042 cpu_cost=1e6,
1043 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
1044 self.config.job_spec(
1045 ['src/objective-c/tests/run_plugin_tests.sh'],
1046 timeout_seconds=60 * 60,
1047 shortname='objc-plugin-tests',
1048 cpu_cost=1e6,
1049 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
1050 self.config.job_spec(
1051 ['src/objective-c/tests/build_one_example.sh'],
1052 timeout_seconds=10 * 60,
1053 shortname='objc-build-example-helloworld',
1054 cpu_cost=1e6,
1055 environ={
1056 'SCHEME': 'HelloWorld',
1057 'EXAMPLE_PATH': 'examples/objective-c/helloworld'
1058 }),
1059 self.config.job_spec(
1060 ['src/objective-c/tests/build_one_example.sh'],
1061 timeout_seconds=10 * 60,
1062 shortname='objc-build-example-routeguide',
1063 cpu_cost=1e6,
1064 environ={
1065 'SCHEME': 'RouteGuideClient',
1066 'EXAMPLE_PATH': 'examples/objective-c/route_guide'
1067 }),
1068 self.config.job_spec(
1069 ['src/objective-c/tests/build_one_example.sh'],
1070 timeout_seconds=10 * 60,
1071 shortname='objc-build-example-authsample',
1072 cpu_cost=1e6,
1073 environ={
1074 'SCHEME': 'AuthSample',
1075 'EXAMPLE_PATH': 'examples/objective-c/auth_sample'
1076 }),
1077 self.config.job_spec(
1078 ['src/objective-c/tests/build_one_example.sh'],
1079 timeout_seconds=10 * 60,
1080 shortname='objc-build-example-sample',
1081 cpu_cost=1e6,
1082 environ={
1083 'SCHEME': 'Sample',
1084 'EXAMPLE_PATH': 'src/objective-c/examples/Sample'
1085 }),
1086 self.config.job_spec(
1087 ['src/objective-c/tests/build_one_example.sh'],
1088 timeout_seconds=10 * 60,
1089 shortname='objc-build-example-sample-frameworks',
1090 cpu_cost=1e6,
1091 environ={
1092 'SCHEME': 'Sample',
1093 'EXAMPLE_PATH': 'src/objective-c/examples/Sample',
1094 'FRAMEWORKS': 'YES'
1095 }),
1096 self.config.job_spec(
1097 ['src/objective-c/tests/build_one_example.sh'],
1098 timeout_seconds=10 * 60,
1099 shortname='objc-build-example-switftsample',
1100 cpu_cost=1e6,
1101 environ={
1102 'SCHEME': 'SwiftSample',
1103 'EXAMPLE_PATH': 'src/objective-c/examples/SwiftSample'
1104 }),
1105 ]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -07001106
ncteisen888093c2017-12-11 18:00:40 -08001107 def pre_build_steps(self):
1108 return []
murgatroid99256d3df2015-09-21 16:58:02 -07001109
ncteisen888093c2017-12-11 18:00:40 -08001110 def make_targets(self):
1111 return ['interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -07001112
ncteisen888093c2017-12-11 18:00:40 -08001113 def make_options(self):
1114 return []
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001115
ncteisen888093c2017-12-11 18:00:40 -08001116 def build_steps(self):
1117 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -07001118
ncteisen888093c2017-12-11 18:00:40 -08001119 def post_tests_steps(self):
1120 return []
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001121
ncteisen888093c2017-12-11 18:00:40 -08001122 def makefile_name(self):
1123 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -07001124
ncteisen888093c2017-12-11 18:00:40 -08001125 def dockerfile_dir(self):
1126 return None
Jan Tattermusch788ee232016-01-26 12:19:44 -08001127
ncteisen888093c2017-12-11 18:00:40 -08001128 def __str__(self):
1129 return 'objc'
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -07001130
1131
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001132class Sanity(object):
1133
ncteisen888093c2017-12-11 18:00:40 -08001134 def configure(self, config, args):
1135 self.config = config
1136 self.args = args
1137 _check_compiler(self.args.compiler, ['default'])
Jan Tattermusch77db4322016-02-20 20:19:35 -08001138
ncteisen888093c2017-12-11 18:00:40 -08001139 def test_specs(self):
1140 import yaml
1141 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
1142 environ = {'TEST': 'true'}
1143 if _is_use_docker_child():
1144 environ['CLANG_FORMAT_SKIP_DOCKER'] = 'true'
Noah Eisene737ae92018-01-16 18:02:04 -08001145 environ['CLANG_TIDY_SKIP_DOCKER'] = 'true'
ncteisen888093c2017-12-11 18:00:40 -08001146 return [
1147 self.config.job_spec(
1148 cmd['script'].split(),
1149 timeout_seconds=30 * 60,
1150 environ=environ,
1151 cpu_cost=cmd.get('cpu_cost', 1)) for cmd in yaml.load(f)
1152 ]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001153
ncteisen888093c2017-12-11 18:00:40 -08001154 def pre_build_steps(self):
1155 return []
murgatroid99256d3df2015-09-21 16:58:02 -07001156
ncteisen888093c2017-12-11 18:00:40 -08001157 def make_targets(self):
1158 return ['run_dep_checks']
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001159
ncteisen888093c2017-12-11 18:00:40 -08001160 def make_options(self):
1161 return []
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001162
ncteisen888093c2017-12-11 18:00:40 -08001163 def build_steps(self):
1164 return []
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001165
ncteisen888093c2017-12-11 18:00:40 -08001166 def post_tests_steps(self):
1167 return []
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +02001168
ncteisen888093c2017-12-11 18:00:40 -08001169 def makefile_name(self):
1170 return 'Makefile'
murgatroid99a3e244f2015-09-22 11:25:53 -07001171
ncteisen888093c2017-12-11 18:00:40 -08001172 def dockerfile_dir(self):
1173 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -08001174
ncteisen888093c2017-12-11 18:00:40 -08001175 def __str__(self):
1176 return 'sanity'
1177
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001178
Craig Tiller738c3342015-01-12 14:28:33 -08001179# different configurations we can run under
Jan Tattermusch5c79a312016-12-20 11:02:50 +01001180with open('tools/run_tests/generated/configs.json') as f:
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001181 _CONFIGS = dict(
1182 (cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -08001183
Craig Tillerc7449162015-01-16 14:42:10 -08001184_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -08001185 'c++': CLanguage('cxx', 'c++'),
1186 'c': CLanguage('c', 'c'),
Matt Kwonge2e7cf42017-09-15 11:17:04 -07001187 'grpc-node': RemoteNodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +00001188 'php': PhpLanguage(),
Stanley Cheung2e2cdff2016-07-23 19:07:36 -07001189 'php7': Php7Language(),
Nathaniel Manista840615e2015-01-22 20:31:47 +00001190 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -08001191 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +01001192 'csharp': CSharpLanguage(),
ncteisen888093c2017-12-11 18:00:40 -08001193 'objc': ObjCLanguage(),
Jan Tattermusch70a57e42016-02-20 18:50:27 -08001194 'sanity': Sanity()
ncteisen888093c2017-12-11 18:00:40 -08001195}
Jan Tattermusch77db4322016-02-20 20:19:35 -08001196
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001197_MSBUILD_CONFIG = {
Craig Tiller7bb3efd2015-09-01 08:04:03 -07001198 'dbg': 'Debug',
1199 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -08001200 'gcov': 'Debug',
ncteisen888093c2017-12-11 18:00:40 -08001201}
Craig Tiller7bb3efd2015-09-01 08:04:03 -07001202
David Garcia Quintase90cd372015-05-31 18:15:26 -07001203
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001204def _windows_arch_option(arch):
ncteisen888093c2017-12-11 18:00:40 -08001205 """Returns msbuild cmdline option for selected architecture."""
1206 if arch == 'default' or arch == 'x86':
1207 return '/p:Platform=Win32'
1208 elif arch == 'x64':
1209 return '/p:Platform=x64'
1210 else:
1211 print('Architecture %s not supported.' % arch)
1212 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -08001213
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001214
1215def _check_arch_option(arch):
ncteisen888093c2017-12-11 18:00:40 -08001216 """Checks that architecture option is valid."""
1217 if platform_string() == 'windows':
1218 _windows_arch_option(arch)
1219 elif platform_string() == 'linux':
1220 # On linux, we need to be running under docker with the right architecture.
1221 runtime_arch = platform.architecture()[0]
1222 if arch == 'default':
1223 return
1224 elif runtime_arch == '64bit' and arch == 'x64':
1225 return
1226 elif runtime_arch == '32bit' and arch == 'x86':
1227 return
1228 else:
1229 print('Architecture %s does not match current runtime architecture.'
1230 % arch)
1231 sys.exit(1)
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001232 else:
ncteisen888093c2017-12-11 18:00:40 -08001233 if args.arch != 'default':
1234 print('Architecture %s not supported on current platform.' %
1235 args.arch)
1236 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001237
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001238
Jan Tattermusche70b3c52016-02-07 20:21:02 -08001239def _docker_arch_suffix(arch):
ncteisen888093c2017-12-11 18:00:40 -08001240 """Returns suffix to dockerfile dir to use."""
1241 if arch == 'default' or arch == 'x64':
1242 return 'x64'
1243 elif arch == 'x86':
1244 return 'x86'
1245 else:
1246 print('Architecture %s not supported with current settings.' % arch)
1247 sys.exit(1)
Jan Tattermusche70b3c52016-02-07 20:21:02 -08001248
1249
David Garcia Quintase90cd372015-05-31 18:15:26 -07001250def runs_per_test_type(arg_str):
1251 """Auxilary function to parse the "runs_per_test" flag.
1252
1253 Returns:
1254 A positive integer or 0, the latter indicating an infinite number of
1255 runs.
1256
1257 Raises:
1258 argparse.ArgumentTypeError: Upon invalid input.
1259 """
1260 if arg_str == 'inf':
1261 return 0
1262 try:
1263 n = int(arg_str)
1264 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -07001265 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -07001266 except:
Adele Zhoue4c35612015-10-16 15:34:23 -07001267 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -07001268 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001269
siddharthshukla2135a1b2016-08-04 02:11:53 +02001270
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001271def percent_type(arg_str):
ncteisen888093c2017-12-11 18:00:40 -08001272 pct = float(arg_str)
1273 if pct > 100 or pct < 0:
1274 raise argparse.ArgumentTypeError(
1275 "'%f' is not a valid percentage in the [0, 100] range" % pct)
1276 return pct
1277
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001278
1279# This is math.isclose in python >= 3.5
1280def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
ncteisen888093c2017-12-11 18:00:40 -08001281 return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
David Garcia Quintas95b37b72017-02-15 16:49:49 -08001282
1283
Jan Tattermuschc95eead2015-09-18 13:03:50 -07001284# parse command line
1285argp = argparse.ArgumentParser(description='Run grpc tests.')
ncteisen888093c2017-12-11 18:00:40 -08001286argp.add_argument(
1287 '-c', '--config', choices=sorted(_CONFIGS.keys()), default='opt')
1288argp.add_argument(
1289 '-n',
1290 '--runs_per_test',
1291 default=1,
1292 type=runs_per_test_type,
1293 help='A positive integer or "inf". If "inf", all tests will run in an '
1294 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -08001295argp.add_argument('-r', '--regex', default='.*', type=str)
Vijay Pai488fd0e2016-06-13 12:37:12 -07001296argp.add_argument('--regex_exclude', default='', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -08001297argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -08001298argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ncteisen888093c2017-12-11 18:00:40 -08001299argp.add_argument(
1300 '-p',
1301 '--sample_percent',
1302 default=100.0,
1303 type=percent_type,
1304 help='Run a random sample with that percentage of tests')
1305argp.add_argument(
1306 '-f', '--forever', default=False, action='store_const', const=True)
1307argp.add_argument(
1308 '-t', '--travis', default=False, action='store_const', const=True)
1309argp.add_argument(
1310 '--newline_on_success', default=False, action='store_const', const=True)
1311argp.add_argument(
1312 '-l',
1313 '--language',
1314 choices=['all'] + sorted(_LANGUAGES.keys()),
1315 nargs='+',
1316 default=['all'])
1317argp.add_argument(
1318 '-S', '--stop_on_failure', default=False, action='store_const', const=True)
1319argp.add_argument(
1320 '--use_docker',
1321 default=False,
1322 action='store_const',
1323 const=True,
1324 help='Run all the tests under docker. That provides ' +
1325 'additional isolation and prevents the need to install ' +
1326 'language specific prerequisites. Only available on Linux.')
1327argp.add_argument(
1328 '--allow_flakes',
1329 default=False,
1330 action='store_const',
1331 const=True,
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001332 help=
1333 'Allow flaky tests to show as passing (re-runs failed tests up to five times)'
ncteisen888093c2017-12-11 18:00:40 -08001334)
1335argp.add_argument(
1336 '--arch',
1337 choices=['default', 'x86', 'x64'],
1338 default='default',
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001339 help=
1340 'Selects architecture to target. For some platforms "default" is the only supported choice.'
ncteisen888093c2017-12-11 18:00:40 -08001341)
1342argp.add_argument(
1343 '--compiler',
1344 choices=[
Jan Tattermusch0614a682018-01-23 11:51:21 +01001345 'default', 'gcc4.4', 'gcc4.6', 'gcc4.8', 'gcc4.9', 'gcc5.3', 'gcc7.2',
1346 'gcc_musl', 'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7', 'python2.7',
ncteisen888093c2017-12-11 18:00:40 -08001347 'python3.4', 'python3.5', 'python3.6', 'pypy', 'pypy3', 'python_alpine',
1348 'all_the_cpythons', 'electron1.3', 'electron1.6', 'coreclr', 'cmake',
1349 'cmake_vs2015', 'cmake_vs2017'
1350 ],
1351 default='default',
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001352 help=
1353 'Selects compiler to use. Allowed values depend on the platform and language.'
ncteisen888093c2017-12-11 18:00:40 -08001354)
1355argp.add_argument(
1356 '--iomgr_platform',
kpayson641bfff8e2018-03-13 22:05:48 -07001357 choices=['native', 'uv', 'gevent'],
ncteisen888093c2017-12-11 18:00:40 -08001358 default='native',
1359 help='Selects iomgr platform to build on')
1360argp.add_argument(
1361 '--build_only',
1362 default=False,
1363 action='store_const',
1364 const=True,
1365 help='Perform all the build steps but don\'t run any tests.')
1366argp.add_argument(
1367 '--measure_cpu_costs',
1368 default=False,
1369 action='store_const',
1370 const=True,
1371 help='Measure the cpu costs of tests')
1372argp.add_argument(
1373 '--update_submodules',
1374 default=[],
1375 nargs='*',
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001376 help=
1377 'Update some submodules before building. If any are updated, also run generate_projects. '
ncteisen888093c2017-12-11 18:00:40 -08001378 +
1379 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.'
1380)
Craig Tiller234b6e72015-05-23 10:12:40 -07001381argp.add_argument('-a', '--antagonists', default=0, type=int)
ncteisen888093c2017-12-11 18:00:40 -08001382argp.add_argument(
1383 '-x',
1384 '--xml_report',
1385 default=None,
1386 type=str,
1387 help='Generates a JUnit-compatible XML report')
1388argp.add_argument(
1389 '--report_suite_name',
1390 default='tests',
1391 type=str,
1392 help='Test suite name to use in generated JUnit XML report')
1393argp.add_argument(
1394 '--quiet_success',
1395 default=False,
1396 action='store_const',
1397 const=True,
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001398 help=
1399 'Don\'t print anything when a test passes. Passing tests also will not be reported in XML report. '
ncteisen888093c2017-12-11 18:00:40 -08001400 + 'Useful when running many iterations of each test (argument -n).')
1401argp.add_argument(
1402 '--force_default_poller',
1403 default=False,
1404 action='store_const',
1405 const=True,
1406 help='Don\'t try to iterate over many polling strategies when they exist')
1407argp.add_argument(
1408 '--force_use_pollers',
1409 default=None,
1410 type=str,
1411 help='Only use the specified comma-delimited list of polling engines. '
1412 'Example: --force_use_pollers epollsig,poll '
1413 ' (This flag has no effect if --force_default_poller flag is also used)')
1414argp.add_argument(
1415 '--max_time', default=-1, type=int, help='Maximum test runtime in seconds')
1416argp.add_argument(
1417 '--bq_result_table',
1418 default='',
1419 type=str,
1420 nargs='?',
1421 help='Upload test results to a specified BQ table.')
1422argp.add_argument(
1423 '--disable_auto_set_flakes',
1424 default=False,
1425 const=True,
1426 action='store_const',
1427 help='Disable rerunning historically flaky tests')
Nicolas Nobleddef2462015-01-06 18:08:25 -08001428args = argp.parse_args()
1429
Craig Tillerd16abf82017-06-07 08:58:55 -07001430flaky_tests = set()
Craig Tiller0b86d032017-09-07 13:47:45 -07001431shortname_to_cpu = {}
Matt Kwongc5fd8902017-08-10 13:39:21 -07001432if not args.disable_auto_set_flakes:
ncteisen888093c2017-12-11 18:00:40 -08001433 try:
1434 for test in get_bqtest_data():
1435 if test.flaky: flaky_tests.add(test.name)
1436 if test.cpu > 0: shortname_to_cpu[test.name] = test.cpu
1437 except:
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001438 print(
1439 "Unexpected error getting flaky tests: %s" % traceback.format_exc())
David Garcia Quintasfaafa4d2017-06-06 14:52:17 -07001440
Craig Tiller123f1372016-06-15 15:06:14 -07001441if args.force_default_poller:
ncteisen888093c2017-12-11 18:00:40 -08001442 _POLLING_STRATEGIES = {}
Sree Kuchibhotla15d91642017-08-15 14:00:23 -07001443elif args.force_use_pollers:
ncteisen888093c2017-12-11 18:00:40 -08001444 _POLLING_STRATEGIES[platform_string()] = args.force_use_pollers.split(',')
Craig Tiller123f1372016-06-15 15:06:14 -07001445
Craig Tiller5f735a62016-01-20 09:31:15 -08001446jobset.measure_cpu_costs = args.measure_cpu_costs
1447
Craig Tiller1676f912016-01-05 10:49:44 -08001448# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -08001449need_to_regenerate_projects = False
1450for spec in args.update_submodules:
ncteisen888093c2017-12-11 18:00:40 -08001451 spec = spec.split(':', 1)
1452 if len(spec) == 1:
1453 submodule = spec[0]
1454 branch = 'master'
1455 elif len(spec) == 2:
1456 submodule = spec[0]
1457 branch = spec[1]
1458 cwd = 'third_party/%s' % submodule
Craig Tiller1676f912016-01-05 10:49:44 -08001459
ncteisen888093c2017-12-11 18:00:40 -08001460 def git(cmd, cwd=cwd):
1461 print('in %s: git %s' % (cwd, cmd))
1462 run_shell_command('git %s' % cmd, cwd=cwd)
1463
1464 git('fetch')
1465 git('checkout %s' % branch)
1466 git('pull origin %s' % branch)
1467 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
1468 need_to_regenerate_projects = True
1469if need_to_regenerate_projects:
1470 if jobset.platform_string() == 'linux':
1471 run_shell_command('tools/buildgen/generate_projects.sh')
1472 else:
1473 print(
1474 'WARNING: may need to regenerate projects, but since we are not on')
1475 print(
1476 ' Linux this step is being skipped. Compilation MAY fail.')
Craig Tiller1676f912016-01-05 10:49:44 -08001477
Nicolas Nobleddef2462015-01-06 18:08:25 -08001478# grab config
Jan Tattermusch77db4322016-02-20 20:19:35 -08001479run_config = _CONFIGS[args.config]
1480build_config = run_config.build_config
Craig Tillerf1973b02015-01-16 12:32:13 -08001481
Craig Tiller06805272015-06-11 14:46:47 -07001482if args.travis:
ncteisen888093c2017-12-11 18:00:40 -08001483 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -07001484
Adele Zhou6b9527c2015-11-20 15:56:35 -08001485if 'all' in args.language:
ncteisen888093c2017-12-11 18:00:40 -08001486 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -08001487else:
ncteisen888093c2017-12-11 18:00:40 -08001488 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -08001489# We don't support code coverage on some languages
1490if 'gcov' in args.config:
ncteisen888093c2017-12-11 18:00:40 -08001491 for bad in ['objc', 'sanity']:
1492 if bad in lang_list:
1493 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -08001494
1495languages = set(_LANGUAGES[l] for l in lang_list)
Jan Tattermusch77db4322016-02-20 20:19:35 -08001496for l in languages:
ncteisen888093c2017-12-11 18:00:40 -08001497 l.configure(run_config, args)
murgatroid99132ce6a2015-03-04 17:29:14 -08001498
ncteisen888093c2017-12-11 18:00:40 -08001499language_make_options = []
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001500if any(language.make_options() for language in languages):
ncteisen888093c2017-12-11 18:00:40 -08001501 if not 'gcov' in args.config and len(languages) != 1:
1502 print(
1503 'languages with custom make options cannot be built simultaneously with other languages'
1504 )
1505 sys.exit(1)
1506 else:
1507 # Combining make options is not clean and just happens to work. It allows C/C++ and C# to build
1508 # together, and is only used under gcov. All other configs should build languages individually.
1509 language_make_options = list(
1510 set([
1511 make_option
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001512 for lang in languages
1513 for make_option in lang.make_options()
ncteisen888093c2017-12-11 18:00:40 -08001514 ]))
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001515
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001516if args.use_docker:
ncteisen888093c2017-12-11 18:00:40 -08001517 if not args.travis:
1518 print('Seen --use_docker flag, will run tests under docker.')
1519 print('')
1520 print(
1521 'IMPORTANT: The changes you are testing need to be locally committed'
1522 )
1523 print(
1524 'because only the committed changes in the current branch will be')
1525 print('copied to the docker environment.')
1526 time.sleep(5)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001527
ncteisen888093c2017-12-11 18:00:40 -08001528 dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
1529 if len(dockerfile_dirs) > 1:
1530 if 'gcov' in args.config:
1531 dockerfile_dir = 'tools/dockerfile/test/multilang_jessie_x64'
1532 print(
1533 'Using multilang_jessie_x64 docker image for code coverage for '
1534 'all languages.')
1535 else:
1536 print(
1537 'Languages to be tested require running under different docker '
1538 'images.')
1539 sys.exit(1)
Adele Zhou9506ef22016-03-02 13:53:34 -08001540 else:
ncteisen888093c2017-12-11 18:00:40 -08001541 dockerfile_dir = next(iter(dockerfile_dirs))
Craig Tillerde7edf82016-03-20 09:12:16 -07001542
ncteisen888093c2017-12-11 18:00:40 -08001543 child_argv = [arg for arg in sys.argv if not arg == '--use_docker']
1544 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(
1545 child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001546
ncteisen888093c2017-12-11 18:00:40 -08001547 env = os.environ.copy()
1548 env['RUN_TESTS_COMMAND'] = run_tests_cmd
1549 env['DOCKERFILE_DIR'] = dockerfile_dir
1550 env['DOCKER_RUN_SCRIPT'] = 'tools/run_tests/dockerize/docker_run_tests.sh'
1551 if args.xml_report:
1552 env['XML_REPORT'] = args.xml_report
1553 if not args.travis:
1554 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001555
ncteisen888093c2017-12-11 18:00:40 -08001556 subprocess.check_call(
1557 'tools/run_tests/dockerize/build_docker_and_run_tests.sh',
1558 shell=True,
1559 env=env)
1560 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -08001561
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001562_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001563
ncteisen888093c2017-12-11 18:00:40 -08001564
Jan Tattermuschfba65302016-01-25 18:21:14 -08001565def make_jobspec(cfg, targets, makefile='Makefile'):
ncteisen888093c2017-12-11 18:00:40 -08001566 if platform_string() == 'windows':
1567 return [
1568 jobset.JobSpec(
1569 [
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001570 'cmake', '--build', '.', '--target',
1571 '%s' % target, '--config', _MSBUILD_CONFIG[cfg]
ncteisen888093c2017-12-11 18:00:40 -08001572 ],
1573 cwd=os.path.dirname(makefile),
1574 timeout_seconds=None) for target in targets
1575 ]
murgatroid998ae409f2015-10-26 16:39:00 -07001576 else:
ncteisen888093c2017-12-11 18:00:40 -08001577 if targets and makefile.startswith('cmake/build/'):
1578 # With cmake, we've passed all the build configuration in the pre-build step already
1579 return [
1580 jobset.JobSpec(
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001581 [os.getenv('MAKE', 'make'), '-j',
1582 '%d' % args.jobs] + targets,
ncteisen888093c2017-12-11 18:00:40 -08001583 cwd='cmake/build',
1584 timeout_seconds=None)
1585 ]
1586 if targets:
1587 return [
1588 jobset.JobSpec(
1589 [
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001590 os.getenv('MAKE', 'make'), '-f', makefile, '-j',
1591 '%d' % args.jobs,
ncteisen888093c2017-12-11 18:00:40 -08001592 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' %
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001593 args.slowdown,
1594 'CONFIG=%s' % cfg, 'Q='
ncteisen888093c2017-12-11 18:00:40 -08001595 ] + language_make_options +
1596 ([] if not args.travis else ['JENKINS_BUILD=1']) + targets,
1597 timeout_seconds=None)
1598 ]
1599 else:
1600 return []
1601
Jan Tattermuschfba65302016-01-25 18:21:14 -08001602
murgatroid99a3e244f2015-09-22 11:25:53 -07001603make_targets = {}
1604for l in languages:
ncteisen888093c2017-12-11 18:00:40 -08001605 makefile = l.makefile_name()
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001606 make_targets[makefile] = make_targets.get(makefile, set()).union(
1607 set(l.make_targets()))
ncteisen888093c2017-12-11 18:00:40 -08001608
Craig Tiller5058c692015-04-08 09:42:04 -07001609
Jan Tattermusche4a69182015-12-15 09:53:01 -08001610def build_step_environ(cfg):
ncteisen888093c2017-12-11 18:00:40 -08001611 environ = {'CONFIG': cfg}
1612 msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
1613 if msbuild_cfg:
1614 environ['MSBUILD_CONFIG'] = msbuild_cfg
1615 return environ
Jan Tattermusche4a69182015-12-15 09:53:01 -08001616
ncteisen888093c2017-12-11 18:00:40 -08001617
1618build_steps = list(
1619 set(
1620 jobset.JobSpec(
1621 cmdline, environ=build_step_environ(build_config), flake_retries=2)
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001622 for l in languages
1623 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -07001624if make_targets:
ncteisen888093c2017-12-11 18:00:40 -08001625 make_commands = itertools.chain.from_iterable(
1626 make_jobspec(build_config, list(targets), makefile)
1627 for (makefile, targets) in make_targets.items())
1628 build_steps.extend(set(make_commands))
1629build_steps.extend(
1630 set(
1631 jobset.JobSpec(
1632 cmdline,
1633 environ=build_step_environ(build_config),
1634 timeout_seconds=None)
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001635 for l in languages
1636 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -08001637
ncteisen888093c2017-12-11 18:00:40 -08001638post_tests_steps = list(
1639 set(
1640 jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001641 for l in languages
1642 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -08001643runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -08001644forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -08001645
Nicolas Nobleddef2462015-01-06 18:08:25 -08001646
Ken Paysonfa51de52016-06-30 23:50:48 -07001647def _shut_down_legacy_server(legacy_server_port):
ncteisen888093c2017-12-11 18:00:40 -08001648 try:
1649 version = int(
1650 urllib.request.urlopen(
1651 'http://localhost:%d/version_number' % legacy_server_port,
1652 timeout=10).read())
1653 except:
1654 pass
1655 else:
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001656 urllib.request.urlopen(
1657 'http://localhost:%d/quitquitquit' % legacy_server_port).read()
Ken Paysonfa51de52016-06-30 23:50:48 -07001658
1659
Adele Zhoud5fffa52015-10-23 15:51:42 -07001660def _calculate_num_runs_failures(list_of_results):
ncteisen888093c2017-12-11 18:00:40 -08001661 """Caculate number of runs and failures for a particular test.
Adele Zhoud5fffa52015-10-23 15:51:42 -07001662
1663 Args:
1664 list_of_results: (List) of JobResult object.
1665 Returns:
1666 A tuple of total number of runs and failures.
1667 """
ncteisen888093c2017-12-11 18:00:40 -08001668 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1669 num_failures = 0
1670 for jobresult in list_of_results:
1671 if jobresult.retries > 0:
1672 num_runs += jobresult.retries
1673 if jobresult.num_failures > 0:
1674 num_failures += jobresult.num_failures
1675 return num_runs, num_failures
Adele Zhoud5fffa52015-10-23 15:51:42 -07001676
Adele Zhou6b9527c2015-11-20 15:56:35 -08001677
Craig Tillereb9de8b2016-01-08 08:57:41 -08001678# _build_and_run results
1679class BuildAndRunError(object):
1680
ncteisen888093c2017-12-11 18:00:40 -08001681 BUILD = object()
1682 TEST = object()
1683 POST_TEST = object()
Craig Tillereb9de8b2016-01-08 08:57:41 -08001684
1685
Craig Tiller819cd882017-04-25 13:18:22 -07001686def _has_epollexclusive():
ncteisen888093c2017-12-11 18:00:40 -08001687 binary = 'bins/%s/check_epollexclusive' % args.config
1688 if not os.path.exists(binary):
1689 return False
1690 try:
1691 subprocess.check_call(binary)
1692 return True
1693 except subprocess.CalledProcessError, e:
1694 return False
1695 except OSError, e:
1696 # For languages other than C and Windows the binary won't exist
1697 return False
Craig Tiller819cd882017-04-25 13:18:22 -07001698
1699
Craig Tillereb9de8b2016-01-08 08:57:41 -08001700# returns a list of things that failed (or an empty list on success)
ncteisen888093c2017-12-11 18:00:40 -08001701def _build_and_run(check_cancelled,
1702 newline_on_success,
1703 xml_report=None,
1704 build_only=False):
1705 """Do one pass of building & running tests."""
1706 # build latest sequentially
1707 num_failures, resultset = jobset.run(
1708 build_steps,
1709 maxjobs=1,
1710 stop_on_failure=True,
1711 newline_on_success=newline_on_success,
1712 travis=args.travis)
1713 if num_failures:
1714 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001715
ncteisen888093c2017-12-11 18:00:40 -08001716 if build_only:
1717 if xml_report:
1718 report_utils.render_junit_xml_report(
1719 resultset, xml_report, suite_name=args.report_suite_name)
1720 return []
ctiller3040cb72015-01-07 12:13:17 -08001721
ncteisen888093c2017-12-11 18:00:40 -08001722 if not args.travis and not _has_epollexclusive() and platform_string(
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001723 ) in _POLLING_STRATEGIES and 'epollex' in _POLLING_STRATEGIES[platform_string(
1724 )]:
ncteisen888093c2017-12-11 18:00:40 -08001725 print('\n\nOmitting EPOLLEXCLUSIVE tests\n\n')
1726 _POLLING_STRATEGIES[platform_string()].remove('epollex')
Craig Tiller819cd882017-04-25 13:18:22 -07001727
ncteisen888093c2017-12-11 18:00:40 -08001728 # start antagonists
1729 antagonists = [
1730 subprocess.Popen(['tools/run_tests/python_utils/antagonist.py'])
1731 for _ in range(0, args.antagonists)
1732 ]
1733 start_port_server.start_port_server()
1734 resultset = None
1735 num_test_failures = 0
1736 try:
1737 infinite_runs = runs_per_test == 0
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001738 one_run = set(
1739 spec for language in languages for spec in language.test_specs()
1740 if (re.search(args.regex, spec.shortname) and
1741 (args.regex_exclude == '' or
1742 not re.search(args.regex_exclude, spec.shortname))))
ncteisen888093c2017-12-11 18:00:40 -08001743 # When running on travis, we want out test runs to be as similar as possible
1744 # for reproducibility purposes.
1745 if args.travis and args.max_time <= 0:
1746 massaged_one_run = sorted(one_run, key=lambda x: x.cpu_cost)
1747 else:
1748 # whereas otherwise, we want to shuffle things up to give all tests a
1749 # chance to run.
1750 massaged_one_run = list(
1751 one_run) # random.sample needs an indexable seq.
1752 num_jobs = len(massaged_one_run)
1753 # for a random sample, get as many as indicated by the 'sample_percent'
1754 # argument. By default this arg is 100, resulting in a shuffle of all
1755 # jobs.
1756 sample_size = int(num_jobs * args.sample_percent / 100.0)
1757 massaged_one_run = random.sample(massaged_one_run, sample_size)
1758 if not isclose(args.sample_percent, 100.0):
1759 assert args.runs_per_test == 1, "Can't do sampling (-p) over multiple runs (-n)."
1760 print("Running %d tests out of %d (~%d%%)" %
1761 (sample_size, num_jobs, args.sample_percent))
1762 if infinite_runs:
1763 assert len(massaged_one_run
1764 ) > 0, 'Must have at least one test for a -n inf run'
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001765 runs_sequence = (itertools.repeat(massaged_one_run)
1766 if infinite_runs else itertools.repeat(
1767 massaged_one_run, runs_per_test))
ncteisen888093c2017-12-11 18:00:40 -08001768 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001769
ncteisen888093c2017-12-11 18:00:40 -08001770 if args.quiet_success:
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001771 jobset.message(
ncteisen888093c2017-12-11 18:00:40 -08001772 'START',
1773 'Running tests quietly, only failing tests will be reported',
Jan Tattermusch68e27bf2016-12-16 14:09:03 +01001774 do_newline=True)
ncteisen888093c2017-12-11 18:00:40 -08001775 num_test_failures, resultset = jobset.run(
1776 all_runs,
1777 check_cancelled,
1778 newline_on_success=newline_on_success,
1779 travis=args.travis,
1780 maxjobs=args.jobs,
1781 maxjobs_cpu_agnostic=max_parallel_tests_for_current_platform(),
1782 stop_on_failure=args.stop_on_failure,
1783 quiet_success=args.quiet_success,
1784 max_time=args.max_time)
1785 if resultset:
1786 for k, v in sorted(resultset.items()):
1787 num_runs, num_failures = _calculate_num_runs_failures(v)
1788 if num_failures > 0:
1789 if num_failures == num_runs: # what about infinite_runs???
1790 jobset.message('FAILED', k, do_newline=True)
1791 else:
1792 jobset.message(
1793 'FLAKE',
Mehrdad Afshari87cd9942018-01-02 14:40:00 -08001794 '%s [%d/%d runs flaked]' % (k, num_failures,
1795 num_runs),
ncteisen888093c2017-12-11 18:00:40 -08001796 do_newline=True)
1797 finally:
1798 for antagonist in antagonists:
1799 antagonist.kill()
1800 if args.bq_result_table and resultset:
1801 upload_results_to_bq(resultset, args.bq_result_table, args,
1802 platform_string())
1803 if xml_report and resultset:
1804 report_utils.render_junit_xml_report(
1805 resultset, xml_report, suite_name=args.report_suite_name)
Craig Tillerd86a3942015-01-14 12:48:54 -08001806
ncteisen888093c2017-12-11 18:00:40 -08001807 number_failures, _ = jobset.run(
1808 post_tests_steps,
1809 maxjobs=1,
1810 stop_on_failure=False,
1811 newline_on_success=newline_on_success,
1812 travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001813
ncteisen888093c2017-12-11 18:00:40 -08001814 out = []
1815 if number_failures:
1816 out.append(BuildAndRunError.POST_TEST)
1817 if num_test_failures:
1818 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001819
ncteisen888093c2017-12-11 18:00:40 -08001820 return out
ctiller3040cb72015-01-07 12:13:17 -08001821
1822
1823if forever:
ncteisen888093c2017-12-11 18:00:40 -08001824 success = True
1825 while True:
1826 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
1827 initial_time = dw.most_recent_change()
1828 have_files_changed = lambda: dw.most_recent_change() != initial_time
1829 previous_success = success
1830 errors = _build_and_run(
1831 check_cancelled=have_files_changed,
1832 newline_on_success=False,
1833 build_only=args.build_only) == 0
1834 if not previous_success and not errors:
1835 jobset.message(
1836 'SUCCESS',
1837 'All tests are now passing properly',
1838 do_newline=True)
1839 jobset.message('IDLE', 'No change detected')
1840 while not have_files_changed():
1841 time.sleep(1)
ctiller3040cb72015-01-07 12:13:17 -08001842else:
ncteisen888093c2017-12-11 18:00:40 -08001843 errors = _build_and_run(
1844 check_cancelled=lambda: False,
1845 newline_on_success=args.newline_on_success,
1846 xml_report=args.xml_report,
1847 build_only=args.build_only)
1848 if not errors:
1849 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1850 else:
1851 jobset.message('FAILED', 'Some tests failed', do_newline=True)
1852 exit_code = 0
1853 if BuildAndRunError.BUILD in errors:
1854 exit_code |= 1
1855 if BuildAndRunError.TEST in errors:
1856 exit_code |= 2
1857 if BuildAndRunError.POST_TEST in errors:
1858 exit_code |= 4
1859 sys.exit(exit_code)