blob: 106f6bea390a30b5100602ac4587b85e4354c994 [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 Tillerb38197e2016-02-26 10:14:54 -0800152 POLLING_STRATEGIES = {
153 'windows': ['all'],
154 'mac': ['all'],
155 'posix': ['all'],
156 'linux': ['poll', 'legacy']
157 }
158 for polling_strategy in POLLING_STRATEGIES[self.platform]:
159 env={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
160 _ROOT + '/src/core/tsi/test_creds/ca.pem',
161 'GRPC_POLLING_STRATEGY': polling_strategy}
162 shortname_ext = '' if polling_strategy=='all' else ' polling=%s' % polling_strategy
163 for target in binaries:
164 if self.config.build_config in target['exclude_configs']:
165 continue
166 if self.platform == 'windows':
167 binary = 'vsprojects/%s%s/%s.exe' % (
168 'x64/' if self.args.arch == 'x64' else '',
169 _MSBUILD_CONFIG[self.config.build_config],
170 target['name'])
Craig Tillerca62ff02016-02-24 22:22:57 -0800171 else:
Craig Tillerb38197e2016-02-26 10:14:54 -0800172 binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
173 if os.path.isfile(binary):
174 if 'gtest' in target and target['gtest']:
175 # here we parse the output of --gtest_list_tests to build up a
176 # complete list of the tests contained in a binary
177 # for each test, we then add a job to run, filtering for just that
178 # test
179 with open(os.devnull, 'w') as fnull:
180 tests = subprocess.check_output([binary, '--gtest_list_tests'],
181 stderr=fnull)
182 base = None
183 for line in tests.split('\n'):
184 i = line.find('#')
185 if i >= 0: line = line[:i]
186 if not line: continue
187 if line[0] != ' ':
188 base = line.strip()
189 else:
190 assert base is not None
191 assert line[1] == ' '
192 test = base + line.strip()
193 cmdline = [binary] + ['--gtest_filter=%s' % test]
194 out.append(self.config.job_spec(cmdline, [binary],
195 shortname='%s:%s' % (binary, test, shortname_ext),
196 cpu_cost=target['cpu_cost'],
197 environ=env))
198 else:
199 cmdline = [binary] + target['args']
200 out.append(self.config.job_spec(cmdline, [binary],
201 shortname=' '.join(cmdline) + shortname_ext,
202 cpu_cost=target['cpu_cost'],
203 environ=env))
204 elif self.args.regex == '.*' or self.platform == 'windows':
205 print '\nWARNING: binary not found, skipping', binary
Nicolas Noblee1445362015-05-11 17:40:26 -0700206 return sorted(out)
Craig Tillerc7449162015-01-16 14:42:10 -0800207
Jan Tattermusch77db4322016-02-20 20:19:35 -0800208 def make_targets(self):
209 test_regex = self.args.regex
210 if self.platform != 'windows' and self.args.regex != '.*':
Craig Tiller883064c2015-11-04 10:06:10 -0800211 # use the regex to minimize the number of things to build
Craig Tillerb0f275e2016-01-27 10:45:50 -0800212 return [os.path.basename(target['name'])
Craig Tiller883064c2015-11-04 10:06:10 -0800213 for target in get_c_tests(False, self.test_lang)
Craig Tillerb0f275e2016-01-27 10:45:50 -0800214 if re.search(test_regex, '/' + target['name'])]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800215 if self.platform == 'windows':
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700216 # don't build tools on windows just yet
217 return ['buildtests_%s' % self.make_target]
Craig Tiller7552f0f2015-06-19 17:46:20 -0700218 return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
Craig Tillerc7449162015-01-16 14:42:10 -0800219
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800220 def make_options(self):
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800221 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800222
murgatroid99256d3df2015-09-21 16:58:02 -0700223 def pre_build_steps(self):
Jan Tattermusch874aec02015-10-07 19:26:19 -0700224 if self.platform == 'windows':
225 return [['tools\\run_tests\\pre_build_c.bat']]
226 else:
227 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700228
Craig Tillerc7449162015-01-16 14:42:10 -0800229 def build_steps(self):
230 return []
231
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200232 def post_tests_steps(self):
233 if self.platform == 'windows':
234 return []
235 else:
236 return [['tools/run_tests/post_tests_c.sh']]
237
murgatroid99a3e244f2015-09-22 11:25:53 -0700238 def makefile_name(self):
239 return 'Makefile'
240
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800241 def _get_docker_distro(self, use_docker, compiler):
242 if _is_use_docker_child():
243 return "already_under_docker"
244 if not use_docker:
245 _check_compiler(compiler, ['default'])
246
247 if compiler == 'gcc4.9' or compiler == 'default':
248 return 'jessie'
249 elif compiler == 'gcc4.4':
250 return 'squeeze'
251 elif compiler == 'gcc5.3':
252 return 'ubuntu1604'
253 else:
254 raise Exception('Compiler %s not supported.' % compiler)
255
Jan Tattermusch77db4322016-02-20 20:19:35 -0800256 def dockerfile_dir(self):
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800257 return 'tools/dockerfile/test/cxx_%s_%s' % (self._docker_distro,
258 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800259
murgatroid99132ce6a2015-03-04 17:29:14 -0800260 def __str__(self):
261 return self.make_target
262
Craig Tillercc0535d2015-12-08 15:14:47 -0800263
murgatroid992c8d5162015-01-26 10:41:21 -0800264class NodeLanguage(object):
265
Jan Tattermusche477b842016-02-06 22:19:01 -0800266 def __init__(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800267 self.platform = platform_string()
Jan Tattermusche477b842016-02-06 22:19:01 -0800268 self.node_version = '0.12'
269
Jan Tattermusch77db4322016-02-20 20:19:35 -0800270 def configure(self, config, args):
271 self.config = config
272 self.args = args
273 _check_compiler(self.args.compiler, ['default'])
274
275 def test_specs(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800276 if self.platform == 'windows':
Jan Tattermusch77db4322016-02-20 20:19:35 -0800277 return [self.config.job_spec(['tools\\run_tests\\run_node.bat'], None)]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800278 else:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800279 return [self.config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
280 None,
281 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800282
murgatroid99256d3df2015-09-21 16:58:02 -0700283 def pre_build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800284 if self.platform == 'windows':
285 return [['tools\\run_tests\\pre_build_node.bat']]
286 else:
287 return [['tools/run_tests/pre_build_node.sh', self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700288
Jan Tattermusch77db4322016-02-20 20:19:35 -0800289 def make_targets(self):
murgatroid99db5b1602015-10-01 13:20:11 -0700290 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800291
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800292 def make_options(self):
293 return []
294
murgatroid992c8d5162015-01-26 10:41:21 -0800295 def build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800296 if self.platform == 'windows':
297 return [['tools\\run_tests\\build_node.bat']]
298 else:
299 return [['tools/run_tests/build_node.sh', self.node_version]]
Craig Tillerc7449162015-01-16 14:42:10 -0800300
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200301 def post_tests_steps(self):
302 return []
303
murgatroid99a3e244f2015-09-22 11:25:53 -0700304 def makefile_name(self):
305 return 'Makefile'
306
Jan Tattermusch77db4322016-02-20 20:19:35 -0800307 def dockerfile_dir(self):
308 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800309
murgatroid99132ce6a2015-03-04 17:29:14 -0800310 def __str__(self):
311 return 'node'
312
Craig Tiller99775822015-01-30 13:07:16 -0800313
Craig Tillerc7449162015-01-16 14:42:10 -0800314class PhpLanguage(object):
315
Jan Tattermusch77db4322016-02-20 20:19:35 -0800316 def configure(self, config, args):
317 self.config = config
318 self.args = args
319 _check_compiler(self.args.compiler, ['default'])
320
321 def test_specs(self):
322 return [self.config.job_spec(['src/php/bin/run_tests.sh'], None,
323 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800324
murgatroid99256d3df2015-09-21 16:58:02 -0700325 def pre_build_steps(self):
326 return []
327
Jan Tattermusch77db4322016-02-20 20:19:35 -0800328 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700329 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800330
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800331 def make_options(self):
332 return []
333
Craig Tillerc7449162015-01-16 14:42:10 -0800334 def build_steps(self):
335 return [['tools/run_tests/build_php.sh']]
336
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200337 def post_tests_steps(self):
Stanley Cheunga6b95482016-01-13 16:10:48 -0800338 return [['tools/run_tests/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200339
murgatroid99a3e244f2015-09-22 11:25:53 -0700340 def makefile_name(self):
341 return 'Makefile'
342
Jan Tattermusch77db4322016-02-20 20:19:35 -0800343 def dockerfile_dir(self):
344 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800345
murgatroid99132ce6a2015-03-04 17:29:14 -0800346 def __str__(self):
347 return 'php'
348
Craig Tillerc7449162015-01-16 14:42:10 -0800349
Nathaniel Manista840615e2015-01-22 20:31:47 +0000350class PythonLanguage(object):
351
Craig Tiller49f61322015-03-03 13:02:11 -0800352 def __init__(self):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700353 self._build_python_versions = ['2.7']
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700354 self._has_python_versions = []
Craig Tiller49f61322015-03-03 13:02:11 -0800355
Jan Tattermusch77db4322016-02-20 20:19:35 -0800356 def configure(self, config, args):
357 self.config = config
358 self.args = args
359 _check_compiler(self.args.compiler, ['default'])
360
361 def test_specs(self):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700362 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
363 environment['PYVER'] = '2.7'
Jan Tattermusch77db4322016-02-20 20:19:35 -0800364 return [self.config.job_spec(
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700365 ['tools/run_tests/run_python.sh'],
366 None,
367 environ=environment,
368 shortname='py.test',
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -0700369 timeout_seconds=15*60
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700370 )]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000371
murgatroid99256d3df2015-09-21 16:58:02 -0700372 def pre_build_steps(self):
373 return []
374
Jan Tattermusch77db4322016-02-20 20:19:35 -0800375 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700376 return ['static_c', 'grpc_python_plugin', 'shared_c']
Nathaniel Manista840615e2015-01-22 20:31:47 +0000377
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800378 def make_options(self):
379 return []
380
Nathaniel Manista840615e2015-01-22 20:31:47 +0000381 def build_steps(self):
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700382 commands = []
383 for python_version in self._build_python_versions:
384 try:
385 with open(os.devnull, 'w') as output:
386 subprocess.check_call(['which', 'python' + python_version],
387 stdout=output, stderr=output)
388 commands.append(['tools/run_tests/build_python.sh', python_version])
389 self._has_python_versions.append(python_version)
390 except:
391 jobset.message('WARNING', 'Missing Python ' + python_version,
392 do_newline=True)
393 return commands
Nathaniel Manista840615e2015-01-22 20:31:47 +0000394
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200395 def post_tests_steps(self):
396 return []
397
murgatroid99a3e244f2015-09-22 11:25:53 -0700398 def makefile_name(self):
399 return 'Makefile'
400
Jan Tattermusch77db4322016-02-20 20:19:35 -0800401 def dockerfile_dir(self):
402 return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800403
murgatroid99132ce6a2015-03-04 17:29:14 -0800404 def __str__(self):
405 return 'python'
406
Craig Tillerd625d812015-04-08 15:52:35 -0700407
murgatroid996a4c4fa2015-02-27 12:08:57 -0800408class RubyLanguage(object):
409
Jan Tattermusch77db4322016-02-20 20:19:35 -0800410 def configure(self, config, args):
411 self.config = config
412 self.args = args
413 _check_compiler(self.args.compiler, ['default'])
414
415 def test_specs(self):
416 return [self.config.job_spec(['tools/run_tests/run_ruby.sh'], None,
417 timeout_seconds=10*60,
418 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800419
murgatroid99256d3df2015-09-21 16:58:02 -0700420 def pre_build_steps(self):
Nicolas "Pixel" Noblebcf988f2015-10-08 03:00:42 +0200421 return [['tools/run_tests/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700422
Jan Tattermusch4651bef2016-02-23 08:31:25 -0800423 def make_targets(self):
murgatroid997d243df2016-02-18 09:58:05 -0800424 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800425
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800426 def make_options(self):
427 return []
428
murgatroid996a4c4fa2015-02-27 12:08:57 -0800429 def build_steps(self):
430 return [['tools/run_tests/build_ruby.sh']]
431
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200432 def post_tests_steps(self):
Nicolas "Pixel" Noble7ef1e532015-12-02 00:55:33 +0100433 return [['tools/run_tests/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200434
murgatroid99a3e244f2015-09-22 11:25:53 -0700435 def makefile_name(self):
436 return 'Makefile'
437
Jan Tattermusch77db4322016-02-20 20:19:35 -0800438 def dockerfile_dir(self):
439 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800440
murgatroid99132ce6a2015-03-04 17:29:14 -0800441 def __str__(self):
442 return 'ruby'
443
Craig Tillerd625d812015-04-08 15:52:35 -0700444
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800445class CSharpLanguage(object):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800446
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700447 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700448 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700449
Jan Tattermusch77db4322016-02-20 20:19:35 -0800450 def configure(self, config, args):
451 self.config = config
452 self.args = args
453 _check_compiler(self.args.compiler, ['default'])
454
455 def test_specs(self):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800456 with open('src/csharp/tests.json') as f:
457 tests_json = json.load(f)
458 assemblies = tests_json['assemblies']
459 tests = tests_json['tests']
460
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800461 msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
Jan Tattermusch03c01062015-12-11 14:28:56 -0800462 assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
463 for a in assemblies]
464
465 extra_args = ['-labels'] + assembly_files
466
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700467 if self.platform == 'windows':
Jan Tattermusch03c01062015-12-11 14:28:56 -0800468 script_name = 'tools\\run_tests\\run_csharp.bat'
469 extra_args += ['-domain=None']
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700470 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800471 script_name = 'tools/run_tests/run_csharp.sh'
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700472
Jan Tattermusch77db4322016-02-20 20:19:35 -0800473 if self.config.build_config == 'gcov':
Jan Tattermuschbdf4b2e2015-10-28 08:22:34 -0700474 # On Windows, we only collect C# code coverage.
475 # On Linux, we only collect coverage for native extension.
476 # For code coverage all tests need to run as one suite.
Jan Tattermusch77db4322016-02-20 20:19:35 -0800477 return [self.config.job_spec([script_name] + extra_args, None,
478 shortname='csharp.coverage',
479 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jan Tattermusch61c3a832015-10-27 17:54:50 -0700480 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800481 specs = []
482 for test in tests:
483 cmdline = [script_name, '-run=%s' % test] + extra_args
484 if self.platform == 'windows':
485 # use different output directory for each test to prevent
486 # TestResult.xml clash between parallel test runs.
487 cmdline += ['-work=test-result/%s' % uuid.uuid4()]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800488 specs.append(self.config.job_spec(cmdline, None,
489 shortname='csharp.%s' % test,
490 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
Jan Tattermusch03c01062015-12-11 14:28:56 -0800491 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800492
murgatroid99256d3df2015-09-21 16:58:02 -0700493 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700494 if self.platform == 'windows':
Jan Tattermusch874aec02015-10-07 19:26:19 -0700495 return [['tools\\run_tests\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700496 else:
497 return [['tools/run_tests/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700498
Jan Tattermusch77db4322016-02-20 20:19:35 -0800499 def make_targets(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700500 # For Windows, this target doesn't really build anything,
501 # everything is build by buildall script later.
Craig Tillerd5904822015-08-31 21:30:58 -0700502 if self.platform == 'windows':
503 return []
504 else:
505 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800506
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800507 def make_options(self):
508 if self.platform == 'mac':
509 # On Mac, official distribution of mono is 32bit.
510 return ['CFLAGS=-arch i386', 'LDFLAGS=-arch i386']
511 else:
512 return []
513
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800514 def build_steps(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700515 if self.platform == 'windows':
516 return [['src\\csharp\\buildall.bat']]
517 else:
518 return [['tools/run_tests/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000519
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200520 def post_tests_steps(self):
521 return []
522
murgatroid99a3e244f2015-09-22 11:25:53 -0700523 def makefile_name(self):
524 return 'Makefile'
525
Jan Tattermusch77db4322016-02-20 20:19:35 -0800526 def dockerfile_dir(self):
527 return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800528
murgatroid99132ce6a2015-03-04 17:29:14 -0800529 def __str__(self):
530 return 'csharp'
531
Craig Tillerd625d812015-04-08 15:52:35 -0700532
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700533class ObjCLanguage(object):
534
Jan Tattermusch77db4322016-02-20 20:19:35 -0800535 def configure(self, config, args):
536 self.config = config
537 self.args = args
538 _check_compiler(self.args.compiler, ['default'])
539
540 def test_specs(self):
541 return [self.config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
542 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700543
murgatroid99256d3df2015-09-21 16:58:02 -0700544 def pre_build_steps(self):
545 return []
546
Jan Tattermusch77db4322016-02-20 20:19:35 -0800547 def make_targets(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700548 return ['grpc_objective_c_plugin', 'interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700549
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800550 def make_options(self):
551 return []
552
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700553 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700554 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700555
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200556 def post_tests_steps(self):
557 return []
558
murgatroid99a3e244f2015-09-22 11:25:53 -0700559 def makefile_name(self):
560 return 'Makefile'
561
Jan Tattermusch77db4322016-02-20 20:19:35 -0800562 def dockerfile_dir(self):
Jan Tattermusch788ee232016-01-26 12:19:44 -0800563 return None
564
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700565 def __str__(self):
566 return 'objc'
567
568
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100569class Sanity(object):
570
Jan Tattermusch77db4322016-02-20 20:19:35 -0800571 def configure(self, config, args):
572 self.config = config
573 self.args = args
574 _check_compiler(self.args.compiler, ['default'])
575
576 def test_specs(self):
Craig Tiller94d04a52016-01-20 10:58:23 -0800577 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800578 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800579 return [self.config.job_spec(cmd['script'].split(), None,
580 timeout_seconds=None, environ={'TEST': 'true'},
581 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800582 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100583
murgatroid99256d3df2015-09-21 16:58:02 -0700584 def pre_build_steps(self):
585 return []
586
Jan Tattermusch77db4322016-02-20 20:19:35 -0800587 def make_targets(self):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100588 return ['run_dep_checks']
589
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800590 def make_options(self):
591 return []
592
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100593 def build_steps(self):
594 return []
595
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200596 def post_tests_steps(self):
597 return []
598
murgatroid99a3e244f2015-09-22 11:25:53 -0700599 def makefile_name(self):
600 return 'Makefile'
601
Jan Tattermusch77db4322016-02-20 20:19:35 -0800602 def dockerfile_dir(self):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800603 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800604
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100605 def __str__(self):
606 return 'sanity'
607
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200608
Craig Tiller738c3342015-01-12 14:28:33 -0800609# different configurations we can run under
Craig Tillera0f85172016-01-20 15:56:06 -0800610with open('tools/run_tests/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800611 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800612
613
Craig Tillerc7449162015-01-16 14:42:10 -0800614_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800615 'c++': CLanguage('cxx', 'c++'),
616 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800617 'node': NodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000618 'php': PhpLanguage(),
619 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800620 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100621 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700622 'objc' : ObjCLanguage(),
Jan Tattermusch70a57e42016-02-20 18:50:27 -0800623 'sanity': Sanity()
Craig Tillereb272bc2015-01-30 13:13:14 -0800624 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800625
Jan Tattermusch77db4322016-02-20 20:19:35 -0800626
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800627_MSBUILD_CONFIG = {
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700628 'dbg': 'Debug',
629 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800630 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700631 }
632
David Garcia Quintase90cd372015-05-31 18:15:26 -0700633
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800634def _windows_arch_option(arch):
635 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800636 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800637 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800638 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800639 return '/p:Platform=x64'
640 else:
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800641 print 'Architecture %s not supported.' % arch
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800642 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800643
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800644
645def _check_arch_option(arch):
646 """Checks that architecture option is valid."""
647 if platform_string() == 'windows':
648 _windows_arch_option(arch)
649 elif platform_string() == 'linux':
650 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800651 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800652 if arch == 'default':
653 return
654 elif runtime_arch == '64bit' and arch == 'x64':
655 return
656 elif runtime_arch == '32bit' and arch == 'x86':
657 return
658 else:
659 print 'Architecture %s does not match current runtime architecture.' % arch
660 sys.exit(1)
661 else:
662 if args.arch != 'default':
663 print 'Architecture %s not supported on current platform.' % args.arch
664 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800665
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800666
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800667def _windows_build_bat(compiler):
668 """Returns name of build.bat for selected compiler."""
669 if compiler == 'default' or compiler == 'vs2013':
670 return 'vsprojects\\build_vs2013.bat'
671 elif compiler == 'vs2015':
672 return 'vsprojects\\build_vs2015.bat'
673 elif compiler == 'vs2010':
674 return 'vsprojects\\build_vs2010.bat'
675 else:
676 print 'Compiler %s not supported.' % compiler
677 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800678
679
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800680def _windows_toolset_option(compiler):
681 """Returns msbuild PlatformToolset for selected compiler."""
682 if compiler == 'default' or compiler == 'vs2013':
683 return '/p:PlatformToolset=v120'
684 elif compiler == 'vs2015':
685 return '/p:PlatformToolset=v140'
686 elif compiler == 'vs2010':
687 return '/p:PlatformToolset=v100'
688 else:
689 print 'Compiler %s not supported.' % compiler
690 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800691
692
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800693def _docker_arch_suffix(arch):
694 """Returns suffix to dockerfile dir to use."""
695 if arch == 'default' or arch == 'x64':
696 return 'x64'
697 elif arch == 'x86':
698 return 'x86'
699 else:
700 print 'Architecture %s not supported with current settings.' % arch
701 sys.exit(1)
702
703
David Garcia Quintase90cd372015-05-31 18:15:26 -0700704def runs_per_test_type(arg_str):
705 """Auxilary function to parse the "runs_per_test" flag.
706
707 Returns:
708 A positive integer or 0, the latter indicating an infinite number of
709 runs.
710
711 Raises:
712 argparse.ArgumentTypeError: Upon invalid input.
713 """
714 if arg_str == 'inf':
715 return 0
716 try:
717 n = int(arg_str)
718 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -0700719 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -0700720 except:
Adele Zhoue4c35612015-10-16 15:34:23 -0700721 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700722 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700723
724# parse command line
725argp = argparse.ArgumentParser(description='Run grpc tests.')
726argp.add_argument('-c', '--config',
Jan Tattermusch77db4322016-02-20 20:19:35 -0800727 choices=sorted(_CONFIGS.keys()),
728 default='opt')
David Garcia Quintase90cd372015-05-31 18:15:26 -0700729argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
730 help='A positive integer or "inf". If "inf", all tests will run in an '
731 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -0800732argp.add_argument('-r', '--regex', default='.*', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -0800733argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -0800734argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -0800735argp.add_argument('-f', '--forever',
736 default=False,
737 action='store_const',
738 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +0100739argp.add_argument('-t', '--travis',
740 default=False,
741 action='store_const',
742 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -0800743argp.add_argument('--newline_on_success',
744 default=False,
745 action='store_const',
746 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -0800747argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -0700748 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -0800749 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -0700750 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -0700751argp.add_argument('-S', '--stop_on_failure',
752 default=False,
753 action='store_const',
754 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700755argp.add_argument('--use_docker',
756 default=False,
757 action='store_const',
758 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700759 help='Run all the tests under docker. That provides ' +
760 'additional isolation and prevents the need to install ' +
761 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -0700762argp.add_argument('--allow_flakes',
763 default=False,
764 action='store_const',
765 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700766 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800767argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800768 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800769 default='default',
770 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
771argp.add_argument('--compiler',
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800772 choices=['default',
773 'gcc4.4', 'gcc4.9', 'gcc5.3',
774 'vs2010', 'vs2013', 'vs2015'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800775 default='default',
Jan Tattermusch77db4322016-02-20 20:19:35 -0800776 help='Selects compiler to use. Allowed values depend on the platform and language.')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800777argp.add_argument('--build_only',
778 default=False,
779 action='store_const',
780 const=True,
781 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -0800782argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
783 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -0800784argp.add_argument('--update_submodules', default=[], nargs='*',
785 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
786 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -0700787argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +0200788argp.add_argument('-x', '--xml_report', default=None, type=str,
789 help='Generates a JUnit-compatible XML report')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800790args = argp.parse_args()
791
Craig Tiller5f735a62016-01-20 09:31:15 -0800792jobset.measure_cpu_costs = args.measure_cpu_costs
793
Craig Tiller1676f912016-01-05 10:49:44 -0800794# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -0800795need_to_regenerate_projects = False
796for spec in args.update_submodules:
797 spec = spec.split(':', 1)
798 if len(spec) == 1:
799 submodule = spec[0]
800 branch = 'master'
801 elif len(spec) == 2:
802 submodule = spec[0]
803 branch = spec[1]
804 cwd = 'third_party/%s' % submodule
805 def git(cmd, cwd=cwd):
806 print 'in %s: git %s' % (cwd, cmd)
807 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
808 git('fetch')
809 git('checkout %s' % branch)
810 git('pull origin %s' % branch)
811 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
812 need_to_regenerate_projects = True
813if need_to_regenerate_projects:
814 if jobset.platform_string() == 'linux':
815 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
816 else:
817 print 'WARNING: may need to regenerate projects, but since we are not on'
818 print ' Linux this step is being skipped. Compilation MAY fail.'
Craig Tiller1676f912016-01-05 10:49:44 -0800819
820
Nicolas Nobleddef2462015-01-06 18:08:25 -0800821# grab config
Jan Tattermusch77db4322016-02-20 20:19:35 -0800822run_config = _CONFIGS[args.config]
823build_config = run_config.build_config
Craig Tillerf1973b02015-01-16 12:32:13 -0800824
Craig Tiller06805272015-06-11 14:46:47 -0700825if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -0700826 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -0700827
Adele Zhou6b9527c2015-11-20 15:56:35 -0800828if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -0800829 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -0800830else:
831 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -0800832# We don't support code coverage on some languages
833if 'gcov' in args.config:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800834 for bad in ['objc', 'sanity']:
Craig Tiller16900662016-01-07 19:30:54 -0800835 if bad in lang_list:
836 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -0800837
838languages = set(_LANGUAGES[l] for l in lang_list)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800839for l in languages:
840 l.configure(run_config, args)
murgatroid99132ce6a2015-03-04 17:29:14 -0800841
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800842language_make_options=[]
843if any(language.make_options() for language in languages):
844 if len(languages) != 1:
845 print 'languages with custom make options cannot be built simultaneously with other languages'
846 sys.exit(1)
847 else:
848 language_make_options = next(iter(languages)).make_options()
849
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800850if args.use_docker:
851 if not args.travis:
852 print 'Seen --use_docker flag, will run tests under docker.'
853 print
854 print 'IMPORTANT: The changes you are testing need to be locally committed'
855 print 'because only the committed changes in the current branch will be'
856 print 'copied to the docker environment.'
857 time.sleep(5)
858
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800859 dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
860 if len(dockerfile_dirs) > 1:
861 print 'Languages to be tested require running under different docker images.'
862 sys.exit(1)
863 dockerfile_dir = next(iter(dockerfile_dirs))
864
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800865 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -0800866 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800867
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800868 env = os.environ.copy()
869 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800870 env['DOCKERFILE_DIR'] = dockerfile_dir
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800871 env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh'
872 if args.xml_report:
873 env['XML_REPORT'] = args.xml_report
874 if not args.travis:
875 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
876
877 subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'],
878 shell=True,
879 env=env)
880 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800881
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800882_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800883
Jan Tattermuschfba65302016-01-25 18:21:14 -0800884def make_jobspec(cfg, targets, makefile='Makefile'):
885 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -0700886 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -0700887 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -0700888 # empirically /m:2 gives the best performance/price and should prevent
889 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -0700890 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -0700891 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -0700892 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -0700893 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800894 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -0700895 'vsprojects\\%s.sln' % target,
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800896 '/p:Configuration=%s' % _MSBUILD_CONFIG[cfg]] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800897 extra_args +
898 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -0800899 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -0700900 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -0800901 else:
murgatroid998ae409f2015-10-26 16:39:00 -0700902 if targets:
903 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
904 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -0800905 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -0800906 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
907 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800908 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -0800909 ([] if not args.travis else ['JENKINS_BUILD=1']) +
910 targets,
Craig Tiller590105a2016-01-19 13:03:46 -0800911 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -0700912 else:
913 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -0800914
murgatroid99a3e244f2015-09-22 11:25:53 -0700915make_targets = {}
916for l in languages:
917 makefile = l.makefile_name()
918 make_targets[makefile] = make_targets.get(makefile, set()).union(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800919 set(l.make_targets()))
Craig Tiller5058c692015-04-08 09:42:04 -0700920
Jan Tattermusche4a69182015-12-15 09:53:01 -0800921def build_step_environ(cfg):
922 environ = {'CONFIG': cfg}
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800923 msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -0800924 if msbuild_cfg:
925 environ['MSBUILD_CONFIG'] = msbuild_cfg
926 return environ
927
murgatroid99fddac962015-09-22 09:20:11 -0700928build_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800929 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -0700930 for l in languages
931 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -0700932if make_targets:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800933 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 -0700934 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -0700935build_steps.extend(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800936 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), timeout_seconds=None)
Craig Tiller547db2b2015-01-30 14:08:39 -0800937 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -0700938 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -0800939
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200940post_tests_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -0800941 jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200942 for l in languages
943 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -0800944runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -0800945forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -0800946
Nicolas Nobleddef2462015-01-06 18:08:25 -0800947
Craig Tiller71735182015-01-15 17:07:13 -0800948class TestCache(object):
Craig Tillerb50d1662015-01-15 17:28:21 -0800949 """Cache for running tests."""
950
David Klempner25739582015-02-11 15:57:32 -0800951 def __init__(self, use_cache_results):
Craig Tiller71735182015-01-15 17:07:13 -0800952 self._last_successful_run = {}
David Klempner25739582015-02-11 15:57:32 -0800953 self._use_cache_results = use_cache_results
Craig Tiller69cd2372015-06-11 09:38:09 -0700954 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800955
956 def should_run(self, cmdline, bin_hash):
Craig Tiller71735182015-01-15 17:07:13 -0800957 if cmdline not in self._last_successful_run:
958 return True
959 if self._last_successful_run[cmdline] != bin_hash:
960 return True
David Klempner25739582015-02-11 15:57:32 -0800961 if not self._use_cache_results:
962 return True
Craig Tiller71735182015-01-15 17:07:13 -0800963 return False
964
965 def finished(self, cmdline, bin_hash):
Craig Tiller547db2b2015-01-30 14:08:39 -0800966 self._last_successful_run[cmdline] = bin_hash
Craig Tiller69cd2372015-06-11 09:38:09 -0700967 if time.time() - self._last_save > 1:
968 self.save()
Craig Tiller71735182015-01-15 17:07:13 -0800969
970 def dump(self):
Craig Tillerb50d1662015-01-15 17:28:21 -0800971 return [{'cmdline': k, 'hash': v}
972 for k, v in self._last_successful_run.iteritems()]
Craig Tiller71735182015-01-15 17:07:13 -0800973
974 def parse(self, exdump):
975 self._last_successful_run = dict((o['cmdline'], o['hash']) for o in exdump)
976
977 def save(self):
978 with open('.run_tests_cache', 'w') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800979 f.write(json.dumps(self.dump()))
Craig Tiller69cd2372015-06-11 09:38:09 -0700980 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800981
Craig Tiller1cc11db2015-01-15 22:50:50 -0800982 def maybe_load(self):
983 if os.path.exists('.run_tests_cache'):
984 with open('.run_tests_cache') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800985 self.parse(json.loads(f.read()))
Craig Tiller71735182015-01-15 17:07:13 -0800986
987
Craig Tillerf53d9c82015-08-04 14:19:43 -0700988def _start_port_server(port_server_port):
989 # check if a compatible port server is running
990 # if incompatible (version mismatch) ==> start a new one
991 # if not running ==> start a new one
992 # otherwise, leave it up
993 try:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700994 version = int(urllib2.urlopen(
995 'http://localhost:%d/version_number' % port_server_port,
996 timeout=1).read())
997 print 'detected port server running version %d' % version
Craig Tillerf53d9c82015-08-04 14:19:43 -0700998 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -0700999 except Exception as e:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001000 print 'failed to detect port server: %s' % sys.exc_info()[0]
Craig Tillerfe4939f2015-10-06 12:55:36 -07001001 print e.strerror
Craig Tillerf53d9c82015-08-04 14:19:43 -07001002 running = False
1003 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -07001004 current_version = int(subprocess.check_output(
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001005 [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
1006 'dump_version']))
Craig Tillerfe4939f2015-10-06 12:55:36 -07001007 print 'my port server is version %d' % current_version
1008 running = (version >= current_version)
1009 if not running:
1010 print 'port_server version mismatch: killing the old one'
1011 urllib2.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
1012 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001013 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001014 fd, logfile = tempfile.mkstemp()
1015 os.close(fd)
1016 print 'starting port_server, with log file %s' % logfile
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001017 args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
1018 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -07001019 env = dict(os.environ)
1020 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +01001021 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001022 # Working directory of port server needs to be outside of Jenkins
1023 # workspace to prevent file lock issues.
1024 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -07001025 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -07001026 args,
1027 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001028 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -07001029 creationflags = 0x00000008, # detached process
1030 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -07001031 else:
1032 port_server = subprocess.Popen(
1033 args,
Craig Tiller367d41d2015-10-12 13:00:22 -07001034 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -07001035 preexec_fn=os.setsid,
1036 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001037 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001038 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001039 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001040 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001041 if waits > 10:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001042 print 'killing port server due to excessive start up waits'
Craig Tillerabd37fd2015-08-26 07:54:01 -07001043 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001044 if port_server.poll() is not None:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001045 print 'port_server failed to start'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001046 # try one final time: maybe another build managed to start one
1047 time.sleep(1)
1048 try:
1049 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1050 timeout=1).read()
1051 print 'last ditch attempt to contact port server succeeded'
1052 break
1053 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001054 traceback.print_exc()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001055 port_log = open(logfile, 'r').read()
1056 print port_log
1057 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001058 try:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001059 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1060 timeout=1).read()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001061 print 'port server is up and ready'
Craig Tillerf53d9c82015-08-04 14:19:43 -07001062 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001063 except socket.timeout:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001064 print 'waiting for port_server: timeout'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001065 traceback.print_exc();
1066 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001067 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001068 except urllib2.URLError:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001069 print 'waiting for port_server: urlerror'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001070 traceback.print_exc();
1071 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001072 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001073 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001074 traceback.print_exc()
Craig Tillerf53d9c82015-08-04 14:19:43 -07001075 port_server.kill()
1076 raise
1077
1078
Adele Zhoud5fffa52015-10-23 15:51:42 -07001079def _calculate_num_runs_failures(list_of_results):
1080 """Caculate number of runs and failures for a particular test.
1081
1082 Args:
1083 list_of_results: (List) of JobResult object.
1084 Returns:
1085 A tuple of total number of runs and failures.
1086 """
1087 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1088 num_failures = 0
1089 for jobresult in list_of_results:
1090 if jobresult.retries > 0:
1091 num_runs += jobresult.retries
1092 if jobresult.num_failures > 0:
1093 num_failures += jobresult.num_failures
1094 return num_runs, num_failures
1095
Adele Zhou6b9527c2015-11-20 15:56:35 -08001096
Craig Tillereb9de8b2016-01-08 08:57:41 -08001097# _build_and_run results
1098class BuildAndRunError(object):
1099
1100 BUILD = object()
1101 TEST = object()
1102 POST_TEST = object()
1103
1104
1105# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001106def _build_and_run(
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001107 check_cancelled, newline_on_success, cache, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001108 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001109 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001110 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001111 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001112 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001113 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001114 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001115
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001116 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001117 if xml_report:
1118 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001119 return []
ctiller3040cb72015-01-07 12:13:17 -08001120
Craig Tiller234b6e72015-05-23 10:12:40 -07001121 # start antagonists
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001122 antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001123 for _ in range(0, args.antagonists)]
Craig Tillerfe4939f2015-10-06 12:55:36 -07001124 port_server_port = 32767
Craig Tillerf53d9c82015-08-04 14:19:43 -07001125 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001126 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001127 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001128 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001129 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001130 one_run = set(
1131 spec
yang-g6c1fdc62015-08-18 11:57:42 -07001132 for language in languages
Jan Tattermusch77db4322016-02-20 20:19:35 -08001133 for spec in language.test_specs()
yang-g6c1fdc62015-08-18 11:57:42 -07001134 if re.search(args.regex, spec.shortname))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001135 # When running on travis, we want out test runs to be as similar as possible
1136 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001137 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001138 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1139 else:
1140 # whereas otherwise, we want to shuffle things up to give all tests a
1141 # chance to run.
1142 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1143 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001144 if infinite_runs:
1145 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 -07001146 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1147 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001148 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001149
Adele Zhou803af152015-11-30 15:16:16 -08001150 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001151 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001152 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001153 stop_on_failure=args.stop_on_failure,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001154 cache=cache if not xml_report else None,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001155 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
Adele Zhoud5fffa52015-10-23 15:51:42 -07001156 if resultset:
1157 for k, v in resultset.iteritems():
1158 num_runs, num_failures = _calculate_num_runs_failures(v)
1159 if num_failures == num_runs: # what about infinite_runs???
1160 jobset.message('FAILED', k, do_newline=True)
1161 elif num_failures > 0:
1162 jobset.message(
1163 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1164 do_newline=True)
1165 else:
1166 jobset.message('PASSED', k, do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001167 finally:
1168 for antagonist in antagonists:
1169 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001170 if xml_report and resultset:
Adele Zhou3bc7ba42015-11-05 10:21:58 -08001171 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillerd86a3942015-01-14 12:48:54 -08001172
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001173 number_failures, _ = jobset.run(
1174 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001175 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001176
1177 out = []
1178 if number_failures:
1179 out.append(BuildAndRunError.POST_TEST)
1180 if num_test_failures:
1181 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001182
Craig Tiller69cd2372015-06-11 09:38:09 -07001183 if cache: cache.save()
1184
Craig Tillereb9de8b2016-01-08 08:57:41 -08001185 return out
ctiller3040cb72015-01-07 12:13:17 -08001186
1187
David Klempner25739582015-02-11 15:57:32 -08001188test_cache = TestCache(runs_per_test == 1)
Craig Tiller547db2b2015-01-30 14:08:39 -08001189test_cache.maybe_load()
Craig Tiller71735182015-01-15 17:07:13 -08001190
ctiller3040cb72015-01-07 12:13:17 -08001191if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001192 success = True
ctiller3040cb72015-01-07 12:13:17 -08001193 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001194 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001195 initial_time = dw.most_recent_change()
1196 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001197 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001198 errors = _build_and_run(check_cancelled=have_files_changed,
1199 newline_on_success=False,
1200 cache=test_cache,
1201 build_only=args.build_only) == 0
1202 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001203 jobset.message('SUCCESS',
1204 'All tests are now passing properly',
1205 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001206 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001207 while not have_files_changed():
1208 time.sleep(1)
1209else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001210 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001211 newline_on_success=args.newline_on_success,
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001212 cache=test_cache,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001213 xml_report=args.xml_report,
1214 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001215 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001216 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1217 else:
1218 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001219 exit_code = 0
1220 if BuildAndRunError.BUILD in errors:
1221 exit_code |= 1
Craig Tiller4f2be362016-01-08 08:59:20 -08001222 if BuildAndRunError.TEST in errors and not args.travis:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001223 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001224 if BuildAndRunError.POST_TEST in errors:
1225 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001226 sys.exit(exit_code)