blob: 09af0552ecc83339d8fc34ecb8e3f9a947d6c604 [file] [log] [blame]
Nathaniel Manistaae4fbcd2015-09-23 16:29:44 +00001#!/usr/bin/env python2.7
Craig Tiller40839772016-01-05 12:34:49 -08002# Copyright 2015-2016, 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
33import argparse
Craig Tiller9279ac22016-01-20 17:05:23 -080034import ast
Nicolas Nobleddef2462015-01-06 18:08:25 -080035import glob
Craig Tillerf53d9c82015-08-04 14:19:43 -070036import hashlib
Nicolas Nobleddef2462015-01-06 18:08:25 -080037import itertools
Craig Tiller261dd982015-01-16 16:41:45 -080038import json
Nicolas Nobleddef2462015-01-06 18:08:25 -080039import multiprocessing
Craig Tiller1cc11db2015-01-15 22:50:50 -080040import os
David Garcia Quintas79e389f2015-06-02 17:49:42 -070041import platform
42import random
Craig Tillerfe406ec2015-02-24 13:55:12 -080043import re
Craig Tiller82875232015-09-25 13:57:34 -070044import socket
David Garcia Quintas79e389f2015-06-02 17:49:42 -070045import subprocess
Nicolas Nobleddef2462015-01-06 18:08:25 -080046import sys
Craig Tillerf0a293e2015-10-12 10:05:50 -070047import tempfile
48import traceback
ctiller3040cb72015-01-07 12:13:17 -080049import time
Craig Tillerf53d9c82015-08-04 14:19:43 -070050import urllib2
Jan Tattermusch03c01062015-12-11 14:28:56 -080051import uuid
Nicolas Nobleddef2462015-01-06 18:08:25 -080052
53import jobset
Adele Zhoua30f8292015-11-02 13:15:46 -080054import report_utils
ctiller3040cb72015-01-07 12:13:17 -080055import watch_dirs
Nicolas Nobleddef2462015-01-06 18:08:25 -080056
Craig Tillerb361b4e2016-01-06 11:44:17 -080057
Jan Tattermusch3b5121b2016-02-22 17:41:05 -080058_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
59os.chdir(_ROOT)
Craig Tiller2cc2b842015-02-27 11:38:31 -080060
61
Craig Tiller06805272015-06-11 14:46:47 -070062_FORCE_ENVIRON_FOR_WRAPPERS = {}
63
64
Craig Tillerd50993d2015-08-05 08:04:36 -070065def platform_string():
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +010066 return jobset.platform_string()
Craig Tillerd50993d2015-08-05 08:04:36 -070067
68
Craig Tiller738c3342015-01-12 14:28:33 -080069# SimpleConfig: just compile with CONFIG=config, and run the binary to test
Craig Tillera0f85172016-01-20 15:56:06 -080070class Config(object):
Craig Tillerb50d1662015-01-15 17:28:21 -080071
Craig Tillera0f85172016-01-20 15:56:06 -080072 def __init__(self, config, environ=None, timeout_multiplier=1, tool_prefix=[]):
murgatroid99132ce6a2015-03-04 17:29:14 -080073 if environ is None:
74 environ = {}
Craig Tiller738c3342015-01-12 14:28:33 -080075 self.build_config = config
Craig Tillerc7449162015-01-16 14:42:10 -080076 self.allow_hashing = (config != 'gcov')
Craig Tiller547db2b2015-01-30 14:08:39 -080077 self.environ = environ
murgatroid99132ce6a2015-03-04 17:29:14 -080078 self.environ['CONFIG'] = config
Craig Tillera0f85172016-01-20 15:56:06 -080079 self.tool_prefix = tool_prefix
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -070080 self.timeout_multiplier = timeout_multiplier
Craig Tiller738c3342015-01-12 14:28:33 -080081
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -070082 def job_spec(self, cmdline, hash_targets, timeout_seconds=5*60,
Craig Tiller56c6b6a2016-01-20 08:27:37 -080083 shortname=None, environ={}, cpu_cost=1.0):
Craig Tiller49f61322015-03-03 13:02:11 -080084 """Construct a jobset.JobSpec for a test under this config
85
86 Args:
87 cmdline: a list of strings specifying the command line the test
88 would like to run
89 hash_targets: either None (don't do caching of test results), or
90 a list of strings specifying files to include in a
91 binary hash to check if a test has changed
92 -- if used, all artifacts needed to run the test must
93 be listed
94 """
Craig Tiller4fc90032015-05-21 10:39:52 -070095 actual_environ = self.environ.copy()
96 for k, v in environ.iteritems():
97 actual_environ[k] = v
Craig Tillera0f85172016-01-20 15:56:06 -080098 return jobset.JobSpec(cmdline=self.tool_prefix + cmdline,
Jan Tattermusch9a7d30c2015-04-23 16:12:55 -070099 shortname=shortname,
Craig Tiller4fc90032015-05-21 10:39:52 -0700100 environ=actual_environ,
Craig Tiller56c6b6a2016-01-20 08:27:37 -0800101 cpu_cost=cpu_cost,
Craig Tiller94d04a52016-01-20 10:58:23 -0800102 timeout_seconds=(self.timeout_multiplier * timeout_seconds if timeout_seconds else None),
Craig Tiller547db2b2015-01-30 14:08:39 -0800103 hash_targets=hash_targets
Craig Tillerd4509a12015-09-28 09:18:40 -0700104 if self.allow_hashing else None,
Craig Tiller35505de2015-10-08 13:31:33 -0700105 flake_retries=5 if args.allow_flakes else 0,
106 timeout_retries=3 if args.allow_flakes else 0)
Craig Tiller738c3342015-01-12 14:28:33 -0800107
108
murgatroid99cf08daf2015-09-21 15:33:16 -0700109def get_c_tests(travis, test_lang) :
110 out = []
111 platforms_str = 'ci_platforms' if travis else 'platforms'
112 with open('tools/run_tests/tests.json') as f:
murgatroid9989899b12015-09-22 09:14:48 -0700113 js = json.load(f)
murgatroid99a3e244f2015-09-22 11:25:53 -0700114 return [tgt
115 for tgt in js
116 if tgt['language'] == test_lang and
117 platform_string() in tgt[platforms_str] and
118 not (travis and tgt['flaky'])]
murgatroid99cf08daf2015-09-21 15:33:16 -0700119
murgatroid99fafeeb32015-09-22 09:13:03 -0700120
Jan Tattermusch77db4322016-02-20 20:19:35 -0800121def _check_compiler(compiler, supported_compilers):
122 if compiler not in supported_compilers:
123 raise Exception('Compiler %s not supported.' % compiler)
124
125
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800126def _is_use_docker_child():
127 """Returns True if running running as a --use_docker child."""
128 return True if os.getenv('RUN_TESTS_COMMAND') else False
129
130
Craig Tillerc7449162015-01-16 14:42:10 -0800131class CLanguage(object):
132
Craig Tillere9c959d2015-01-18 10:23:26 -0800133 def __init__(self, make_target, test_lang):
Craig Tillerc7449162015-01-16 14:42:10 -0800134 self.make_target = make_target
Craig Tillerd50993d2015-08-05 08:04:36 -0700135 self.platform = platform_string()
Craig Tiller711bbe62015-08-19 12:35:16 -0700136 self.test_lang = test_lang
Craig Tillerc7449162015-01-16 14:42:10 -0800137
Jan Tattermusch77db4322016-02-20 20:19:35 -0800138 def configure(self, config, args):
139 self.config = config
140 self.args = args
141 if self.platform == 'windows':
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800142 self._make_options = [_windows_toolset_option(self.args.compiler),
143 _windows_arch_option(self.args.arch)]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800144 else:
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800145 self._make_options = []
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800146 self._docker_distro = self._get_docker_distro(self.args.use_docker,
147 self.args.compiler)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800148
149 def test_specs(self):
Craig Tiller547db2b2015-01-30 14:08:39 -0800150 out = []
Jan Tattermusch77db4322016-02-20 20:19:35 -0800151 binaries = get_c_tests(self.args.travis, self.test_lang)
Craig Tiller711bbe62015-08-19 12:35:16 -0700152 for target in binaries:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800153 if self.config.build_config in target['exclude_configs']:
murgatroid99fafeeb32015-09-22 09:13:03 -0700154 continue
Nicolas Noblee1445362015-05-11 17:40:26 -0700155 if self.platform == 'windows':
Jan Tattermusch3de6b762016-01-28 11:38:11 -0800156 binary = 'vsprojects/%s%s/%s.exe' % (
Jan Tattermusch77db4322016-02-20 20:19:35 -0800157 'x64/' if self.args.arch == 'x64' else '',
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800158 _MSBUILD_CONFIG[self.config.build_config],
Jan Tattermusch3de6b762016-01-28 11:38:11 -0800159 target['name'])
Nicolas Noblee1445362015-05-11 17:40:26 -0700160 else:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800161 binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
yang-g6c1fdc62015-08-18 11:57:42 -0700162 if os.path.isfile(binary):
Craig Tiller0fe5ee72015-12-22 12:50:36 -0800163 cmdline = [binary] + target['args']
Jan Tattermusch77db4322016-02-20 20:19:35 -0800164 out.append(self.config.job_spec(cmdline, [binary],
165 shortname=' '.join(cmdline),
166 cpu_cost=target['cpu_cost'],
167 environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800168 _ROOT + '/src/core/tsi/test_creds/ca.pem'}))
Jan Tattermusch77db4322016-02-20 20:19:35 -0800169 elif self.args.regex == '.*' or self.platform == 'windows':
Adele Zhoue4c35612015-10-16 15:34:23 -0700170 print '\nWARNING: binary not found, skipping', binary
Nicolas Noblee1445362015-05-11 17:40:26 -0700171 return sorted(out)
Craig Tillerc7449162015-01-16 14:42:10 -0800172
Jan Tattermusch77db4322016-02-20 20:19:35 -0800173 def make_targets(self):
174 test_regex = self.args.regex
175 if self.platform != 'windows' and self.args.regex != '.*':
Craig Tiller883064c2015-11-04 10:06:10 -0800176 # use the regex to minimize the number of things to build
Craig Tillerb0f275e2016-01-27 10:45:50 -0800177 return [os.path.basename(target['name'])
Craig Tiller883064c2015-11-04 10:06:10 -0800178 for target in get_c_tests(False, self.test_lang)
Craig Tillerb0f275e2016-01-27 10:45:50 -0800179 if re.search(test_regex, '/' + target['name'])]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800180 if self.platform == 'windows':
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700181 # don't build tools on windows just yet
182 return ['buildtests_%s' % self.make_target]
Craig Tiller7552f0f2015-06-19 17:46:20 -0700183 return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
Craig Tillerc7449162015-01-16 14:42:10 -0800184
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800185 def make_options(self):
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800186 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800187
murgatroid99256d3df2015-09-21 16:58:02 -0700188 def pre_build_steps(self):
Jan Tattermusch874aec02015-10-07 19:26:19 -0700189 if self.platform == 'windows':
190 return [['tools\\run_tests\\pre_build_c.bat']]
191 else:
192 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700193
Craig Tillerc7449162015-01-16 14:42:10 -0800194 def build_steps(self):
195 return []
196
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200197 def post_tests_steps(self):
198 if self.platform == 'windows':
199 return []
200 else:
201 return [['tools/run_tests/post_tests_c.sh']]
202
murgatroid99a3e244f2015-09-22 11:25:53 -0700203 def makefile_name(self):
204 return 'Makefile'
205
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800206 def _get_docker_distro(self, use_docker, compiler):
207 if _is_use_docker_child():
208 return "already_under_docker"
209 if not use_docker:
210 _check_compiler(compiler, ['default'])
211
212 if compiler == 'gcc4.9' or compiler == 'default':
213 return 'jessie'
214 elif compiler == 'gcc4.4':
215 return 'squeeze'
216 elif compiler == 'gcc5.3':
217 return 'ubuntu1604'
218 else:
219 raise Exception('Compiler %s not supported.' % compiler)
220
Jan Tattermusch77db4322016-02-20 20:19:35 -0800221 def dockerfile_dir(self):
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800222 return 'tools/dockerfile/test/cxx_%s_%s' % (self._docker_distro,
223 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800224
murgatroid99132ce6a2015-03-04 17:29:14 -0800225 def __str__(self):
226 return self.make_target
227
Craig Tillercc0535d2015-12-08 15:14:47 -0800228
murgatroid992c8d5162015-01-26 10:41:21 -0800229class NodeLanguage(object):
230
Jan Tattermusche477b842016-02-06 22:19:01 -0800231 def __init__(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800232 self.platform = platform_string()
Jan Tattermusche477b842016-02-06 22:19:01 -0800233 self.node_version = '0.12'
234
Jan Tattermusch77db4322016-02-20 20:19:35 -0800235 def configure(self, config, args):
236 self.config = config
237 self.args = args
238 _check_compiler(self.args.compiler, ['default'])
239
240 def test_specs(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800241 if self.platform == 'windows':
Jan Tattermusch77db4322016-02-20 20:19:35 -0800242 return [self.config.job_spec(['tools\\run_tests\\run_node.bat'], None)]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800243 else:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800244 return [self.config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
245 None,
246 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800247
murgatroid99256d3df2015-09-21 16:58:02 -0700248 def pre_build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800249 if self.platform == 'windows':
250 return [['tools\\run_tests\\pre_build_node.bat']]
251 else:
252 return [['tools/run_tests/pre_build_node.sh', self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700253
Jan Tattermusch77db4322016-02-20 20:19:35 -0800254 def make_targets(self):
murgatroid99db5b1602015-10-01 13:20:11 -0700255 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800256
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800257 def make_options(self):
258 return []
259
murgatroid992c8d5162015-01-26 10:41:21 -0800260 def build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800261 if self.platform == 'windows':
262 return [['tools\\run_tests\\build_node.bat']]
263 else:
264 return [['tools/run_tests/build_node.sh', self.node_version]]
Craig Tillerc7449162015-01-16 14:42:10 -0800265
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200266 def post_tests_steps(self):
267 return []
268
murgatroid99a3e244f2015-09-22 11:25:53 -0700269 def makefile_name(self):
270 return 'Makefile'
271
Jan Tattermusch77db4322016-02-20 20:19:35 -0800272 def dockerfile_dir(self):
273 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800274
murgatroid99132ce6a2015-03-04 17:29:14 -0800275 def __str__(self):
276 return 'node'
277
Craig Tiller99775822015-01-30 13:07:16 -0800278
Craig Tillerc7449162015-01-16 14:42:10 -0800279class PhpLanguage(object):
280
Jan Tattermusch77db4322016-02-20 20:19:35 -0800281 def configure(self, config, args):
282 self.config = config
283 self.args = args
284 _check_compiler(self.args.compiler, ['default'])
285
286 def test_specs(self):
287 return [self.config.job_spec(['src/php/bin/run_tests.sh'], None,
288 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800289
murgatroid99256d3df2015-09-21 16:58:02 -0700290 def pre_build_steps(self):
291 return []
292
Jan Tattermusch77db4322016-02-20 20:19:35 -0800293 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700294 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800295
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800296 def make_options(self):
297 return []
298
Craig Tillerc7449162015-01-16 14:42:10 -0800299 def build_steps(self):
300 return [['tools/run_tests/build_php.sh']]
301
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200302 def post_tests_steps(self):
Stanley Cheunga6b95482016-01-13 16:10:48 -0800303 return [['tools/run_tests/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200304
murgatroid99a3e244f2015-09-22 11:25:53 -0700305 def makefile_name(self):
306 return 'Makefile'
307
Jan Tattermusch77db4322016-02-20 20:19:35 -0800308 def dockerfile_dir(self):
309 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800310
murgatroid99132ce6a2015-03-04 17:29:14 -0800311 def __str__(self):
312 return 'php'
313
Craig Tillerc7449162015-01-16 14:42:10 -0800314
Nathaniel Manista840615e2015-01-22 20:31:47 +0000315class PythonLanguage(object):
316
Craig Tiller49f61322015-03-03 13:02:11 -0800317 def __init__(self):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700318 self._build_python_versions = ['2.7']
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700319 self._has_python_versions = []
Craig Tiller49f61322015-03-03 13:02:11 -0800320
Jan Tattermusch77db4322016-02-20 20:19:35 -0800321 def configure(self, config, args):
322 self.config = config
323 self.args = args
324 _check_compiler(self.args.compiler, ['default'])
325
326 def test_specs(self):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700327 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
328 environment['PYVER'] = '2.7'
Jan Tattermusch77db4322016-02-20 20:19:35 -0800329 return [self.config.job_spec(
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700330 ['tools/run_tests/run_python.sh'],
331 None,
332 environ=environment,
333 shortname='py.test',
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -0700334 timeout_seconds=15*60
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700335 )]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000336
murgatroid99256d3df2015-09-21 16:58:02 -0700337 def pre_build_steps(self):
338 return []
339
Jan Tattermusch77db4322016-02-20 20:19:35 -0800340 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700341 return ['static_c', 'grpc_python_plugin', 'shared_c']
Nathaniel Manista840615e2015-01-22 20:31:47 +0000342
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800343 def make_options(self):
344 return []
345
Nathaniel Manista840615e2015-01-22 20:31:47 +0000346 def build_steps(self):
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700347 commands = []
348 for python_version in self._build_python_versions:
349 try:
350 with open(os.devnull, 'w') as output:
351 subprocess.check_call(['which', 'python' + python_version],
352 stdout=output, stderr=output)
353 commands.append(['tools/run_tests/build_python.sh', python_version])
354 self._has_python_versions.append(python_version)
355 except:
356 jobset.message('WARNING', 'Missing Python ' + python_version,
357 do_newline=True)
358 return commands
Nathaniel Manista840615e2015-01-22 20:31:47 +0000359
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200360 def post_tests_steps(self):
361 return []
362
murgatroid99a3e244f2015-09-22 11:25:53 -0700363 def makefile_name(self):
364 return 'Makefile'
365
Jan Tattermusch77db4322016-02-20 20:19:35 -0800366 def dockerfile_dir(self):
367 return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800368
murgatroid99132ce6a2015-03-04 17:29:14 -0800369 def __str__(self):
370 return 'python'
371
Craig Tillerd625d812015-04-08 15:52:35 -0700372
murgatroid996a4c4fa2015-02-27 12:08:57 -0800373class RubyLanguage(object):
374
Jan Tattermusch77db4322016-02-20 20:19:35 -0800375 def configure(self, config, args):
376 self.config = config
377 self.args = args
378 _check_compiler(self.args.compiler, ['default'])
379
380 def test_specs(self):
381 return [self.config.job_spec(['tools/run_tests/run_ruby.sh'], None,
382 timeout_seconds=10*60,
383 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800384
murgatroid99256d3df2015-09-21 16:58:02 -0700385 def pre_build_steps(self):
Nicolas "Pixel" Noblebcf988f2015-10-08 03:00:42 +0200386 return [['tools/run_tests/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700387
Craig Tiller883064c2015-11-04 10:06:10 -0800388 def make_targets(self, test_regex):
murgatroid997d243df2016-02-18 09:58:05 -0800389 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800390
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800391 def make_options(self):
392 return []
393
murgatroid996a4c4fa2015-02-27 12:08:57 -0800394 def build_steps(self):
395 return [['tools/run_tests/build_ruby.sh']]
396
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200397 def post_tests_steps(self):
Nicolas "Pixel" Noble7ef1e532015-12-02 00:55:33 +0100398 return [['tools/run_tests/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200399
murgatroid99a3e244f2015-09-22 11:25:53 -0700400 def makefile_name(self):
401 return 'Makefile'
402
Jan Tattermusch77db4322016-02-20 20:19:35 -0800403 def dockerfile_dir(self):
404 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800405
murgatroid99132ce6a2015-03-04 17:29:14 -0800406 def __str__(self):
407 return 'ruby'
408
Craig Tillerd625d812015-04-08 15:52:35 -0700409
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800410class CSharpLanguage(object):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800411
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700412 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700413 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700414
Jan Tattermusch77db4322016-02-20 20:19:35 -0800415 def configure(self, config, args):
416 self.config = config
417 self.args = args
418 _check_compiler(self.args.compiler, ['default'])
419
420 def test_specs(self):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800421 with open('src/csharp/tests.json') as f:
422 tests_json = json.load(f)
423 assemblies = tests_json['assemblies']
424 tests = tests_json['tests']
425
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800426 msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
Jan Tattermusch03c01062015-12-11 14:28:56 -0800427 assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
428 for a in assemblies]
429
430 extra_args = ['-labels'] + assembly_files
431
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700432 if self.platform == 'windows':
Jan Tattermusch03c01062015-12-11 14:28:56 -0800433 script_name = 'tools\\run_tests\\run_csharp.bat'
434 extra_args += ['-domain=None']
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700435 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800436 script_name = 'tools/run_tests/run_csharp.sh'
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700437
Jan Tattermusch77db4322016-02-20 20:19:35 -0800438 if self.config.build_config == 'gcov':
Jan Tattermuschbdf4b2e2015-10-28 08:22:34 -0700439 # On Windows, we only collect C# code coverage.
440 # On Linux, we only collect coverage for native extension.
441 # For code coverage all tests need to run as one suite.
Jan Tattermusch77db4322016-02-20 20:19:35 -0800442 return [self.config.job_spec([script_name] + extra_args, None,
443 shortname='csharp.coverage',
444 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jan Tattermusch61c3a832015-10-27 17:54:50 -0700445 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800446 specs = []
447 for test in tests:
448 cmdline = [script_name, '-run=%s' % test] + extra_args
449 if self.platform == 'windows':
450 # use different output directory for each test to prevent
451 # TestResult.xml clash between parallel test runs.
452 cmdline += ['-work=test-result/%s' % uuid.uuid4()]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800453 specs.append(self.config.job_spec(cmdline, None,
454 shortname='csharp.%s' % test,
455 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
Jan Tattermusch03c01062015-12-11 14:28:56 -0800456 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800457
murgatroid99256d3df2015-09-21 16:58:02 -0700458 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700459 if self.platform == 'windows':
Jan Tattermusch874aec02015-10-07 19:26:19 -0700460 return [['tools\\run_tests\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700461 else:
462 return [['tools/run_tests/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700463
Jan Tattermusch77db4322016-02-20 20:19:35 -0800464 def make_targets(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700465 # For Windows, this target doesn't really build anything,
466 # everything is build by buildall script later.
Craig Tillerd5904822015-08-31 21:30:58 -0700467 if self.platform == 'windows':
468 return []
469 else:
470 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800471
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800472 def make_options(self):
473 if self.platform == 'mac':
474 # On Mac, official distribution of mono is 32bit.
475 return ['CFLAGS=-arch i386', 'LDFLAGS=-arch i386']
476 else:
477 return []
478
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800479 def build_steps(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700480 if self.platform == 'windows':
481 return [['src\\csharp\\buildall.bat']]
482 else:
483 return [['tools/run_tests/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000484
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200485 def post_tests_steps(self):
486 return []
487
murgatroid99a3e244f2015-09-22 11:25:53 -0700488 def makefile_name(self):
489 return 'Makefile'
490
Jan Tattermusch77db4322016-02-20 20:19:35 -0800491 def dockerfile_dir(self):
492 return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800493
murgatroid99132ce6a2015-03-04 17:29:14 -0800494 def __str__(self):
495 return 'csharp'
496
Craig Tillerd625d812015-04-08 15:52:35 -0700497
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700498class ObjCLanguage(object):
499
Jan Tattermusch77db4322016-02-20 20:19:35 -0800500 def configure(self, config, args):
501 self.config = config
502 self.args = args
503 _check_compiler(self.args.compiler, ['default'])
504
505 def test_specs(self):
506 return [self.config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
507 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700508
murgatroid99256d3df2015-09-21 16:58:02 -0700509 def pre_build_steps(self):
510 return []
511
Jan Tattermusch77db4322016-02-20 20:19:35 -0800512 def make_targets(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700513 return ['grpc_objective_c_plugin', 'interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700514
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800515 def make_options(self):
516 return []
517
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700518 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700519 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700520
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200521 def post_tests_steps(self):
522 return []
523
murgatroid99a3e244f2015-09-22 11:25:53 -0700524 def makefile_name(self):
525 return 'Makefile'
526
Jan Tattermusch77db4322016-02-20 20:19:35 -0800527 def dockerfile_dir(self):
Jan Tattermusch788ee232016-01-26 12:19:44 -0800528 return None
529
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700530 def __str__(self):
531 return 'objc'
532
533
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100534class Sanity(object):
535
Jan Tattermusch77db4322016-02-20 20:19:35 -0800536 def configure(self, config, args):
537 self.config = config
538 self.args = args
539 _check_compiler(self.args.compiler, ['default'])
540
541 def test_specs(self):
Craig Tiller94d04a52016-01-20 10:58:23 -0800542 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800543 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800544 return [self.config.job_spec(cmd['script'].split(), None,
545 timeout_seconds=None, environ={'TEST': 'true'},
546 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800547 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100548
murgatroid99256d3df2015-09-21 16:58:02 -0700549 def pre_build_steps(self):
550 return []
551
Jan Tattermusch77db4322016-02-20 20:19:35 -0800552 def make_targets(self):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100553 return ['run_dep_checks']
554
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800555 def make_options(self):
556 return []
557
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100558 def build_steps(self):
559 return []
560
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200561 def post_tests_steps(self):
562 return []
563
murgatroid99a3e244f2015-09-22 11:25:53 -0700564 def makefile_name(self):
565 return 'Makefile'
566
Jan Tattermusch77db4322016-02-20 20:19:35 -0800567 def dockerfile_dir(self):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800568 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800569
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100570 def __str__(self):
571 return 'sanity'
572
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200573
Craig Tiller738c3342015-01-12 14:28:33 -0800574# different configurations we can run under
Craig Tillera0f85172016-01-20 15:56:06 -0800575with open('tools/run_tests/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800576 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800577
578
Craig Tillerc7449162015-01-16 14:42:10 -0800579_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800580 'c++': CLanguage('cxx', 'c++'),
581 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800582 'node': NodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000583 'php': PhpLanguage(),
584 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800585 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100586 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700587 'objc' : ObjCLanguage(),
Jan Tattermusch70a57e42016-02-20 18:50:27 -0800588 'sanity': Sanity()
Craig Tillereb272bc2015-01-30 13:13:14 -0800589 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800590
Jan Tattermusch77db4322016-02-20 20:19:35 -0800591
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800592_MSBUILD_CONFIG = {
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700593 'dbg': 'Debug',
594 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800595 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700596 }
597
David Garcia Quintase90cd372015-05-31 18:15:26 -0700598
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800599def _windows_arch_option(arch):
600 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800601 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800602 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800603 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800604 return '/p:Platform=x64'
605 else:
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800606 print 'Architecture %s not supported.' % arch
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800607 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800608
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800609
610def _check_arch_option(arch):
611 """Checks that architecture option is valid."""
612 if platform_string() == 'windows':
613 _windows_arch_option(arch)
614 elif platform_string() == 'linux':
615 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800616 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800617 if arch == 'default':
618 return
619 elif runtime_arch == '64bit' and arch == 'x64':
620 return
621 elif runtime_arch == '32bit' and arch == 'x86':
622 return
623 else:
624 print 'Architecture %s does not match current runtime architecture.' % arch
625 sys.exit(1)
626 else:
627 if args.arch != 'default':
628 print 'Architecture %s not supported on current platform.' % args.arch
629 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800630
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800631
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800632def _windows_build_bat(compiler):
633 """Returns name of build.bat for selected compiler."""
634 if compiler == 'default' or compiler == 'vs2013':
635 return 'vsprojects\\build_vs2013.bat'
636 elif compiler == 'vs2015':
637 return 'vsprojects\\build_vs2015.bat'
638 elif compiler == 'vs2010':
639 return 'vsprojects\\build_vs2010.bat'
640 else:
641 print 'Compiler %s not supported.' % compiler
642 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800643
644
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800645def _windows_toolset_option(compiler):
646 """Returns msbuild PlatformToolset for selected compiler."""
647 if compiler == 'default' or compiler == 'vs2013':
648 return '/p:PlatformToolset=v120'
649 elif compiler == 'vs2015':
650 return '/p:PlatformToolset=v140'
651 elif compiler == 'vs2010':
652 return '/p:PlatformToolset=v100'
653 else:
654 print 'Compiler %s not supported.' % compiler
655 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800656
657
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800658def _docker_arch_suffix(arch):
659 """Returns suffix to dockerfile dir to use."""
660 if arch == 'default' or arch == 'x64':
661 return 'x64'
662 elif arch == 'x86':
663 return 'x86'
664 else:
665 print 'Architecture %s not supported with current settings.' % arch
666 sys.exit(1)
667
668
David Garcia Quintase90cd372015-05-31 18:15:26 -0700669def runs_per_test_type(arg_str):
670 """Auxilary function to parse the "runs_per_test" flag.
671
672 Returns:
673 A positive integer or 0, the latter indicating an infinite number of
674 runs.
675
676 Raises:
677 argparse.ArgumentTypeError: Upon invalid input.
678 """
679 if arg_str == 'inf':
680 return 0
681 try:
682 n = int(arg_str)
683 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -0700684 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -0700685 except:
Adele Zhoue4c35612015-10-16 15:34:23 -0700686 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700687 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700688
689# parse command line
690argp = argparse.ArgumentParser(description='Run grpc tests.')
691argp.add_argument('-c', '--config',
Jan Tattermusch77db4322016-02-20 20:19:35 -0800692 choices=sorted(_CONFIGS.keys()),
693 default='opt')
David Garcia Quintase90cd372015-05-31 18:15:26 -0700694argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
695 help='A positive integer or "inf". If "inf", all tests will run in an '
696 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -0800697argp.add_argument('-r', '--regex', default='.*', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -0800698argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -0800699argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -0800700argp.add_argument('-f', '--forever',
701 default=False,
702 action='store_const',
703 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +0100704argp.add_argument('-t', '--travis',
705 default=False,
706 action='store_const',
707 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -0800708argp.add_argument('--newline_on_success',
709 default=False,
710 action='store_const',
711 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -0800712argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -0700713 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -0800714 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -0700715 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -0700716argp.add_argument('-S', '--stop_on_failure',
717 default=False,
718 action='store_const',
719 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700720argp.add_argument('--use_docker',
721 default=False,
722 action='store_const',
723 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700724 help='Run all the tests under docker. That provides ' +
725 'additional isolation and prevents the need to install ' +
726 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -0700727argp.add_argument('--allow_flakes',
728 default=False,
729 action='store_const',
730 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700731 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800732argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800733 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800734 default='default',
735 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
736argp.add_argument('--compiler',
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800737 choices=['default',
738 'gcc4.4', 'gcc4.9', 'gcc5.3',
739 'vs2010', 'vs2013', 'vs2015'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800740 default='default',
Jan Tattermusch77db4322016-02-20 20:19:35 -0800741 help='Selects compiler to use. Allowed values depend on the platform and language.')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800742argp.add_argument('--build_only',
743 default=False,
744 action='store_const',
745 const=True,
746 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -0800747argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
748 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -0800749argp.add_argument('--update_submodules', default=[], nargs='*',
750 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
751 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -0700752argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +0200753argp.add_argument('-x', '--xml_report', default=None, type=str,
754 help='Generates a JUnit-compatible XML report')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800755args = argp.parse_args()
756
Craig Tiller5f735a62016-01-20 09:31:15 -0800757jobset.measure_cpu_costs = args.measure_cpu_costs
758
Craig Tiller1676f912016-01-05 10:49:44 -0800759# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -0800760need_to_regenerate_projects = False
761for spec in args.update_submodules:
762 spec = spec.split(':', 1)
763 if len(spec) == 1:
764 submodule = spec[0]
765 branch = 'master'
766 elif len(spec) == 2:
767 submodule = spec[0]
768 branch = spec[1]
769 cwd = 'third_party/%s' % submodule
770 def git(cmd, cwd=cwd):
771 print 'in %s: git %s' % (cwd, cmd)
772 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
773 git('fetch')
774 git('checkout %s' % branch)
775 git('pull origin %s' % branch)
776 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
777 need_to_regenerate_projects = True
778if need_to_regenerate_projects:
779 if jobset.platform_string() == 'linux':
780 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
781 else:
782 print 'WARNING: may need to regenerate projects, but since we are not on'
783 print ' Linux this step is being skipped. Compilation MAY fail.'
Craig Tiller1676f912016-01-05 10:49:44 -0800784
785
Nicolas Nobleddef2462015-01-06 18:08:25 -0800786# grab config
Jan Tattermusch77db4322016-02-20 20:19:35 -0800787run_config = _CONFIGS[args.config]
788build_config = run_config.build_config
Craig Tillerf1973b02015-01-16 12:32:13 -0800789
Craig Tiller06805272015-06-11 14:46:47 -0700790if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -0700791 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -0700792
Adele Zhou6b9527c2015-11-20 15:56:35 -0800793if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -0800794 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -0800795else:
796 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -0800797# We don't support code coverage on some languages
798if 'gcov' in args.config:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800799 for bad in ['objc', 'sanity']:
Craig Tiller16900662016-01-07 19:30:54 -0800800 if bad in lang_list:
801 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -0800802
803languages = set(_LANGUAGES[l] for l in lang_list)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800804for l in languages:
805 l.configure(run_config, args)
murgatroid99132ce6a2015-03-04 17:29:14 -0800806
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800807language_make_options=[]
808if any(language.make_options() for language in languages):
809 if len(languages) != 1:
810 print 'languages with custom make options cannot be built simultaneously with other languages'
811 sys.exit(1)
812 else:
813 language_make_options = next(iter(languages)).make_options()
814
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800815if args.use_docker:
816 if not args.travis:
817 print 'Seen --use_docker flag, will run tests under docker.'
818 print
819 print 'IMPORTANT: The changes you are testing need to be locally committed'
820 print 'because only the committed changes in the current branch will be'
821 print 'copied to the docker environment.'
822 time.sleep(5)
823
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800824 dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
825 if len(dockerfile_dirs) > 1:
826 print 'Languages to be tested require running under different docker images.'
827 sys.exit(1)
828 dockerfile_dir = next(iter(dockerfile_dirs))
829
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800830 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -0800831 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800832
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800833 env = os.environ.copy()
834 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800835 env['DOCKERFILE_DIR'] = dockerfile_dir
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800836 env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh'
837 if args.xml_report:
838 env['XML_REPORT'] = args.xml_report
839 if not args.travis:
840 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
841
842 subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'],
843 shell=True,
844 env=env)
845 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800846
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800847_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800848
Jan Tattermuschfba65302016-01-25 18:21:14 -0800849def make_jobspec(cfg, targets, makefile='Makefile'):
850 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -0700851 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -0700852 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -0700853 # empirically /m:2 gives the best performance/price and should prevent
854 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -0700855 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -0700856 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -0700857 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -0700858 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800859 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -0700860 'vsprojects\\%s.sln' % target,
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800861 '/p:Configuration=%s' % _MSBUILD_CONFIG[cfg]] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800862 extra_args +
863 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -0800864 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -0700865 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -0800866 else:
murgatroid998ae409f2015-10-26 16:39:00 -0700867 if targets:
868 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
869 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -0800870 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -0800871 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
872 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800873 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -0800874 ([] if not args.travis else ['JENKINS_BUILD=1']) +
875 targets,
Craig Tiller590105a2016-01-19 13:03:46 -0800876 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -0700877 else:
878 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -0800879
murgatroid99a3e244f2015-09-22 11:25:53 -0700880make_targets = {}
881for l in languages:
882 makefile = l.makefile_name()
883 make_targets[makefile] = make_targets.get(makefile, set()).union(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800884 set(l.make_targets()))
Craig Tiller5058c692015-04-08 09:42:04 -0700885
Jan Tattermusche4a69182015-12-15 09:53:01 -0800886def build_step_environ(cfg):
887 environ = {'CONFIG': cfg}
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800888 msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -0800889 if msbuild_cfg:
890 environ['MSBUILD_CONFIG'] = msbuild_cfg
891 return environ
892
murgatroid99fddac962015-09-22 09:20:11 -0700893build_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800894 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -0700895 for l in languages
896 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -0700897if make_targets:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800898 make_commands = itertools.chain.from_iterable(make_jobspec(build_config, list(targets), makefile) for (makefile, targets) in make_targets.iteritems())
Craig Tiller6fd23842015-09-01 07:36:31 -0700899 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -0700900build_steps.extend(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800901 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), timeout_seconds=None)
Craig Tiller547db2b2015-01-30 14:08:39 -0800902 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -0700903 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -0800904
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200905post_tests_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800906 jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200907 for l in languages
908 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -0800909runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -0800910forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -0800911
Nicolas Nobleddef2462015-01-06 18:08:25 -0800912
Craig Tiller71735182015-01-15 17:07:13 -0800913class TestCache(object):
Craig Tillerb50d1662015-01-15 17:28:21 -0800914 """Cache for running tests."""
915
David Klempner25739582015-02-11 15:57:32 -0800916 def __init__(self, use_cache_results):
Craig Tiller71735182015-01-15 17:07:13 -0800917 self._last_successful_run = {}
David Klempner25739582015-02-11 15:57:32 -0800918 self._use_cache_results = use_cache_results
Craig Tiller69cd2372015-06-11 09:38:09 -0700919 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800920
921 def should_run(self, cmdline, bin_hash):
Craig Tiller71735182015-01-15 17:07:13 -0800922 if cmdline not in self._last_successful_run:
923 return True
924 if self._last_successful_run[cmdline] != bin_hash:
925 return True
David Klempner25739582015-02-11 15:57:32 -0800926 if not self._use_cache_results:
927 return True
Craig Tiller71735182015-01-15 17:07:13 -0800928 return False
929
930 def finished(self, cmdline, bin_hash):
Craig Tiller547db2b2015-01-30 14:08:39 -0800931 self._last_successful_run[cmdline] = bin_hash
Craig Tiller69cd2372015-06-11 09:38:09 -0700932 if time.time() - self._last_save > 1:
933 self.save()
Craig Tiller71735182015-01-15 17:07:13 -0800934
935 def dump(self):
Craig Tillerb50d1662015-01-15 17:28:21 -0800936 return [{'cmdline': k, 'hash': v}
937 for k, v in self._last_successful_run.iteritems()]
Craig Tiller71735182015-01-15 17:07:13 -0800938
939 def parse(self, exdump):
940 self._last_successful_run = dict((o['cmdline'], o['hash']) for o in exdump)
941
942 def save(self):
943 with open('.run_tests_cache', 'w') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800944 f.write(json.dumps(self.dump()))
Craig Tiller69cd2372015-06-11 09:38:09 -0700945 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800946
Craig Tiller1cc11db2015-01-15 22:50:50 -0800947 def maybe_load(self):
948 if os.path.exists('.run_tests_cache'):
949 with open('.run_tests_cache') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800950 self.parse(json.loads(f.read()))
Craig Tiller71735182015-01-15 17:07:13 -0800951
952
Craig Tillerf53d9c82015-08-04 14:19:43 -0700953def _start_port_server(port_server_port):
954 # check if a compatible port server is running
955 # if incompatible (version mismatch) ==> start a new one
956 # if not running ==> start a new one
957 # otherwise, leave it up
958 try:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700959 version = int(urllib2.urlopen(
960 'http://localhost:%d/version_number' % port_server_port,
961 timeout=1).read())
962 print 'detected port server running version %d' % version
Craig Tillerf53d9c82015-08-04 14:19:43 -0700963 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -0700964 except Exception as e:
Craig Tiller0d6499e2015-10-05 14:00:47 -0700965 print 'failed to detect port server: %s' % sys.exc_info()[0]
Craig Tillerfe4939f2015-10-06 12:55:36 -0700966 print e.strerror
Craig Tillerf53d9c82015-08-04 14:19:43 -0700967 running = False
968 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700969 current_version = int(subprocess.check_output(
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800970 [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
971 'dump_version']))
Craig Tillerfe4939f2015-10-06 12:55:36 -0700972 print 'my port server is version %d' % current_version
973 running = (version >= current_version)
974 if not running:
975 print 'port_server version mismatch: killing the old one'
976 urllib2.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
977 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -0700978 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -0700979 fd, logfile = tempfile.mkstemp()
980 os.close(fd)
981 print 'starting port_server, with log file %s' % logfile
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800982 args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
983 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -0700984 env = dict(os.environ)
985 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +0100986 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800987 # Working directory of port server needs to be outside of Jenkins
988 # workspace to prevent file lock issues.
989 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -0700990 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -0700991 args,
992 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800993 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -0700994 creationflags = 0x00000008, # detached process
995 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -0700996 else:
997 port_server = subprocess.Popen(
998 args,
Craig Tiller367d41d2015-10-12 13:00:22 -0700999 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -07001000 preexec_fn=os.setsid,
1001 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001002 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001003 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001004 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001005 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001006 if waits > 10:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001007 print 'killing port server due to excessive start up waits'
Craig Tillerabd37fd2015-08-26 07:54:01 -07001008 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001009 if port_server.poll() is not None:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001010 print 'port_server failed to start'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001011 # try one final time: maybe another build managed to start one
1012 time.sleep(1)
1013 try:
1014 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1015 timeout=1).read()
1016 print 'last ditch attempt to contact port server succeeded'
1017 break
1018 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001019 traceback.print_exc()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001020 port_log = open(logfile, 'r').read()
1021 print port_log
1022 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001023 try:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001024 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1025 timeout=1).read()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001026 print 'port server is up and ready'
Craig Tillerf53d9c82015-08-04 14:19:43 -07001027 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001028 except socket.timeout:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001029 print 'waiting for port_server: timeout'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001030 traceback.print_exc();
1031 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001032 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001033 except urllib2.URLError:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001034 print 'waiting for port_server: urlerror'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001035 traceback.print_exc();
1036 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001037 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001038 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001039 traceback.print_exc()
Craig Tillerf53d9c82015-08-04 14:19:43 -07001040 port_server.kill()
1041 raise
1042
1043
Adele Zhoud5fffa52015-10-23 15:51:42 -07001044def _calculate_num_runs_failures(list_of_results):
1045 """Caculate number of runs and failures for a particular test.
1046
1047 Args:
1048 list_of_results: (List) of JobResult object.
1049 Returns:
1050 A tuple of total number of runs and failures.
1051 """
1052 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1053 num_failures = 0
1054 for jobresult in list_of_results:
1055 if jobresult.retries > 0:
1056 num_runs += jobresult.retries
1057 if jobresult.num_failures > 0:
1058 num_failures += jobresult.num_failures
1059 return num_runs, num_failures
1060
Adele Zhou6b9527c2015-11-20 15:56:35 -08001061
Craig Tillereb9de8b2016-01-08 08:57:41 -08001062# _build_and_run results
1063class BuildAndRunError(object):
1064
1065 BUILD = object()
1066 TEST = object()
1067 POST_TEST = object()
1068
1069
1070# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001071def _build_and_run(
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001072 check_cancelled, newline_on_success, cache, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001073 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001074 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001075 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001076 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001077 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001078 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001079 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001080
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001081 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001082 if xml_report:
1083 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001084 return []
ctiller3040cb72015-01-07 12:13:17 -08001085
Craig Tiller234b6e72015-05-23 10:12:40 -07001086 # start antagonists
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001087 antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001088 for _ in range(0, args.antagonists)]
Craig Tillerfe4939f2015-10-06 12:55:36 -07001089 port_server_port = 32767
Craig Tillerf53d9c82015-08-04 14:19:43 -07001090 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001091 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001092 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001093 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001094 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001095 one_run = set(
1096 spec
yang-g6c1fdc62015-08-18 11:57:42 -07001097 for language in languages
Jan Tattermusch77db4322016-02-20 20:19:35 -08001098 for spec in language.test_specs()
yang-g6c1fdc62015-08-18 11:57:42 -07001099 if re.search(args.regex, spec.shortname))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001100 # When running on travis, we want out test runs to be as similar as possible
1101 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001102 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001103 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1104 else:
1105 # whereas otherwise, we want to shuffle things up to give all tests a
1106 # chance to run.
1107 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1108 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001109 if infinite_runs:
1110 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 -07001111 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1112 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001113 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001114
Adele Zhou803af152015-11-30 15:16:16 -08001115 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001116 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001117 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001118 stop_on_failure=args.stop_on_failure,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001119 cache=cache if not xml_report else None,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001120 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
Adele Zhoud5fffa52015-10-23 15:51:42 -07001121 if resultset:
1122 for k, v in resultset.iteritems():
1123 num_runs, num_failures = _calculate_num_runs_failures(v)
1124 if num_failures == num_runs: # what about infinite_runs???
1125 jobset.message('FAILED', k, do_newline=True)
1126 elif num_failures > 0:
1127 jobset.message(
1128 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1129 do_newline=True)
1130 else:
1131 jobset.message('PASSED', k, do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001132 finally:
1133 for antagonist in antagonists:
1134 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001135 if xml_report and resultset:
Adele Zhou3bc7ba42015-11-05 10:21:58 -08001136 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillerd86a3942015-01-14 12:48:54 -08001137
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001138 number_failures, _ = jobset.run(
1139 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001140 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001141
1142 out = []
1143 if number_failures:
1144 out.append(BuildAndRunError.POST_TEST)
1145 if num_test_failures:
1146 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001147
Craig Tiller69cd2372015-06-11 09:38:09 -07001148 if cache: cache.save()
1149
Craig Tillereb9de8b2016-01-08 08:57:41 -08001150 return out
ctiller3040cb72015-01-07 12:13:17 -08001151
1152
David Klempner25739582015-02-11 15:57:32 -08001153test_cache = TestCache(runs_per_test == 1)
Craig Tiller547db2b2015-01-30 14:08:39 -08001154test_cache.maybe_load()
Craig Tiller71735182015-01-15 17:07:13 -08001155
ctiller3040cb72015-01-07 12:13:17 -08001156if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001157 success = True
ctiller3040cb72015-01-07 12:13:17 -08001158 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001159 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001160 initial_time = dw.most_recent_change()
1161 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001162 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001163 errors = _build_and_run(check_cancelled=have_files_changed,
1164 newline_on_success=False,
1165 cache=test_cache,
1166 build_only=args.build_only) == 0
1167 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001168 jobset.message('SUCCESS',
1169 'All tests are now passing properly',
1170 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001171 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001172 while not have_files_changed():
1173 time.sleep(1)
1174else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001175 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001176 newline_on_success=args.newline_on_success,
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001177 cache=test_cache,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001178 xml_report=args.xml_report,
1179 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001180 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001181 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1182 else:
1183 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001184 exit_code = 0
1185 if BuildAndRunError.BUILD in errors:
1186 exit_code |= 1
Craig Tiller4f2be362016-01-08 08:59:20 -08001187 if BuildAndRunError.TEST in errors and not args.travis:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001188 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001189 if BuildAndRunError.POST_TEST in errors:
1190 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001191 sys.exit(exit_code)