blob: f40586644257b594901edef26c5162720d4cfe9c [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
Craig Tiller2cc2b842015-02-27 11:38:31 -080058ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
59os.chdir(ROOT)
60
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
Craig Tillerc7449162015-01-16 14:42:10 -0800121class CLanguage(object):
122
Craig Tillere9c959d2015-01-18 10:23:26 -0800123 def __init__(self, make_target, test_lang):
Craig Tillerc7449162015-01-16 14:42:10 -0800124 self.make_target = make_target
Craig Tillerd50993d2015-08-05 08:04:36 -0700125 self.platform = platform_string()
Craig Tiller711bbe62015-08-19 12:35:16 -0700126 self.test_lang = test_lang
Craig Tillerc7449162015-01-16 14:42:10 -0800127
Craig Tiller883064c2015-11-04 10:06:10 -0800128 def test_specs(self, config, args):
Craig Tiller547db2b2015-01-30 14:08:39 -0800129 out = []
Craig Tiller883064c2015-11-04 10:06:10 -0800130 binaries = get_c_tests(args.travis, self.test_lang)
Craig Tiller711bbe62015-08-19 12:35:16 -0700131 for target in binaries:
murgatroid99a3e244f2015-09-22 11:25:53 -0700132 if config.build_config in target['exclude_configs']:
murgatroid99fafeeb32015-09-22 09:13:03 -0700133 continue
Nicolas Noblee1445362015-05-11 17:40:26 -0700134 if self.platform == 'windows':
Jan Tattermusch3de6b762016-01-28 11:38:11 -0800135 binary = 'vsprojects/%s%s/%s.exe' % (
136 'x64/' if args.arch == 'x64' else '',
137 _WINDOWS_CONFIG[config.build_config],
138 target['name'])
Nicolas Noblee1445362015-05-11 17:40:26 -0700139 else:
140 binary = 'bins/%s/%s' % (config.build_config, target['name'])
yang-g6c1fdc62015-08-18 11:57:42 -0700141 if os.path.isfile(binary):
Craig Tiller0fe5ee72015-12-22 12:50:36 -0800142 cmdline = [binary] + target['args']
143 out.append(config.job_spec(cmdline, [binary],
144 shortname=' '.join(cmdline),
Craig Tiller56c6b6a2016-01-20 08:27:37 -0800145 cpu_cost=target['cpu_cost'],
Craig Tillercc0535d2015-12-08 15:14:47 -0800146 environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
147 os.path.abspath(os.path.dirname(
Craig Tillered2164d2015-12-08 22:03:36 -0800148 sys.argv[0]) + '/../../src/core/tsi/test_creds/ca.pem')}))
Craig Tiller883064c2015-11-04 10:06:10 -0800149 elif args.regex == '.*' or platform_string() == 'windows':
Adele Zhoue4c35612015-10-16 15:34:23 -0700150 print '\nWARNING: binary not found, skipping', binary
Nicolas Noblee1445362015-05-11 17:40:26 -0700151 return sorted(out)
Craig Tillerc7449162015-01-16 14:42:10 -0800152
Craig Tiller883064c2015-11-04 10:06:10 -0800153 def make_targets(self, test_regex):
154 if platform_string() != 'windows' and test_regex != '.*':
155 # use the regex to minimize the number of things to build
Craig Tillerb0f275e2016-01-27 10:45:50 -0800156 return [os.path.basename(target['name'])
Craig Tiller883064c2015-11-04 10:06:10 -0800157 for target in get_c_tests(False, self.test_lang)
Craig Tillerb0f275e2016-01-27 10:45:50 -0800158 if re.search(test_regex, '/' + target['name'])]
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700159 if platform_string() == 'windows':
160 # don't build tools on windows just yet
161 return ['buildtests_%s' % self.make_target]
Craig Tiller7552f0f2015-06-19 17:46:20 -0700162 return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
Craig Tillerc7449162015-01-16 14:42:10 -0800163
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800164 def make_options(self):
165 return []
166
murgatroid99256d3df2015-09-21 16:58:02 -0700167 def pre_build_steps(self):
Jan Tattermusch874aec02015-10-07 19:26:19 -0700168 if self.platform == 'windows':
169 return [['tools\\run_tests\\pre_build_c.bat']]
170 else:
171 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700172
Craig Tillerc7449162015-01-16 14:42:10 -0800173 def build_steps(self):
174 return []
175
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200176 def post_tests_steps(self):
177 if self.platform == 'windows':
178 return []
179 else:
180 return [['tools/run_tests/post_tests_c.sh']]
181
murgatroid99a3e244f2015-09-22 11:25:53 -0700182 def makefile_name(self):
183 return 'Makefile'
184
murgatroid99132ce6a2015-03-04 17:29:14 -0800185 def supports_multi_config(self):
186 return True
187
Jan Tattermusch788ee232016-01-26 12:19:44 -0800188 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800189 return 'tools/dockerfile/test/cxx_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800190
murgatroid99132ce6a2015-03-04 17:29:14 -0800191 def __str__(self):
192 return self.make_target
193
Craig Tillercc0535d2015-12-08 15:14:47 -0800194
murgatroid992c8d5162015-01-26 10:41:21 -0800195class NodeLanguage(object):
196
Jan Tattermusche477b842016-02-06 22:19:01 -0800197 def __init__(self):
198 self.node_version = '0.12'
199
Craig Tiller883064c2015-11-04 10:06:10 -0800200 def test_specs(self, config, args):
Jan Tattermusche477b842016-02-06 22:19:01 -0800201 return [config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
202 None,
Craig Tiller06805272015-06-11 14:46:47 -0700203 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800204
murgatroid99256d3df2015-09-21 16:58:02 -0700205 def pre_build_steps(self):
murgatroid99ae369de2015-10-09 15:40:48 -0700206 # Default to 1 week cache expiration
Jan Tattermusche477b842016-02-06 22:19:01 -0800207 return [['tools/run_tests/pre_build_node.sh', self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700208
Craig Tiller883064c2015-11-04 10:06:10 -0800209 def make_targets(self, test_regex):
murgatroid99db5b1602015-10-01 13:20:11 -0700210 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800211
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800212 def make_options(self):
213 return []
214
murgatroid992c8d5162015-01-26 10:41:21 -0800215 def build_steps(self):
Jan Tattermusche477b842016-02-06 22:19:01 -0800216 return [['tools/run_tests/build_node.sh', self.node_version]]
Craig Tillerc7449162015-01-16 14:42:10 -0800217
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200218 def post_tests_steps(self):
219 return []
220
murgatroid99a3e244f2015-09-22 11:25:53 -0700221 def makefile_name(self):
222 return 'Makefile'
223
murgatroid99132ce6a2015-03-04 17:29:14 -0800224 def supports_multi_config(self):
225 return False
226
Jan Tattermusch788ee232016-01-26 12:19:44 -0800227 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800228 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800229
murgatroid99132ce6a2015-03-04 17:29:14 -0800230 def __str__(self):
231 return 'node'
232
Craig Tiller99775822015-01-30 13:07:16 -0800233
Craig Tillerc7449162015-01-16 14:42:10 -0800234class PhpLanguage(object):
235
Craig Tiller883064c2015-11-04 10:06:10 -0800236 def test_specs(self, config, args):
Craig Tiller4fc90032015-05-21 10:39:52 -0700237 return [config.job_spec(['src/php/bin/run_tests.sh'], None,
Craig Tiller06805272015-06-11 14:46:47 -0700238 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800239
murgatroid99256d3df2015-09-21 16:58:02 -0700240 def pre_build_steps(self):
241 return []
242
Craig Tiller883064c2015-11-04 10:06:10 -0800243 def make_targets(self, test_regex):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700244 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800245
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800246 def make_options(self):
247 return []
248
Craig Tillerc7449162015-01-16 14:42:10 -0800249 def build_steps(self):
250 return [['tools/run_tests/build_php.sh']]
251
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200252 def post_tests_steps(self):
Stanley Cheunga6b95482016-01-13 16:10:48 -0800253 return [['tools/run_tests/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200254
murgatroid99a3e244f2015-09-22 11:25:53 -0700255 def makefile_name(self):
256 return 'Makefile'
257
murgatroid99132ce6a2015-03-04 17:29:14 -0800258 def supports_multi_config(self):
259 return False
260
Jan Tattermusch788ee232016-01-26 12:19:44 -0800261 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800262 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800263
murgatroid99132ce6a2015-03-04 17:29:14 -0800264 def __str__(self):
265 return 'php'
266
Craig Tillerc7449162015-01-16 14:42:10 -0800267
Nathaniel Manista840615e2015-01-22 20:31:47 +0000268class PythonLanguage(object):
269
Craig Tiller49f61322015-03-03 13:02:11 -0800270 def __init__(self):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700271 self._build_python_versions = ['2.7']
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700272 self._has_python_versions = []
Craig Tiller49f61322015-03-03 13:02:11 -0800273
Craig Tiller883064c2015-11-04 10:06:10 -0800274 def test_specs(self, config, args):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700275 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
276 environment['PYVER'] = '2.7'
277 return [config.job_spec(
278 ['tools/run_tests/run_python.sh'],
279 None,
280 environ=environment,
281 shortname='py.test',
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -0700282 timeout_seconds=15*60
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700283 )]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000284
murgatroid99256d3df2015-09-21 16:58:02 -0700285 def pre_build_steps(self):
286 return []
287
Craig Tiller883064c2015-11-04 10:06:10 -0800288 def make_targets(self, test_regex):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700289 return ['static_c', 'grpc_python_plugin', 'shared_c']
Nathaniel Manista840615e2015-01-22 20:31:47 +0000290
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800291 def make_options(self):
292 return []
293
Nathaniel Manista840615e2015-01-22 20:31:47 +0000294 def build_steps(self):
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700295 commands = []
296 for python_version in self._build_python_versions:
297 try:
298 with open(os.devnull, 'w') as output:
299 subprocess.check_call(['which', 'python' + python_version],
300 stdout=output, stderr=output)
301 commands.append(['tools/run_tests/build_python.sh', python_version])
302 self._has_python_versions.append(python_version)
303 except:
304 jobset.message('WARNING', 'Missing Python ' + python_version,
305 do_newline=True)
306 return commands
Nathaniel Manista840615e2015-01-22 20:31:47 +0000307
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200308 def post_tests_steps(self):
309 return []
310
murgatroid99a3e244f2015-09-22 11:25:53 -0700311 def makefile_name(self):
312 return 'Makefile'
313
murgatroid99132ce6a2015-03-04 17:29:14 -0800314 def supports_multi_config(self):
315 return False
316
Jan Tattermusch788ee232016-01-26 12:19:44 -0800317 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800318 return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800319
murgatroid99132ce6a2015-03-04 17:29:14 -0800320 def __str__(self):
321 return 'python'
322
Craig Tillerd625d812015-04-08 15:52:35 -0700323
murgatroid996a4c4fa2015-02-27 12:08:57 -0800324class RubyLanguage(object):
325
Craig Tiller883064c2015-11-04 10:06:10 -0800326 def test_specs(self, config, args):
Craig Tiller4fc90032015-05-21 10:39:52 -0700327 return [config.job_spec(['tools/run_tests/run_ruby.sh'], None,
Craig Tiller06805272015-06-11 14:46:47 -0700328 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800329
murgatroid99256d3df2015-09-21 16:58:02 -0700330 def pre_build_steps(self):
Nicolas "Pixel" Noblebcf988f2015-10-08 03:00:42 +0200331 return [['tools/run_tests/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700332
Craig Tiller883064c2015-11-04 10:06:10 -0800333 def make_targets(self, test_regex):
murgatroid99a43c14f2015-07-30 13:31:23 -0700334 return ['static_c']
murgatroid996a4c4fa2015-02-27 12:08:57 -0800335
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800336 def make_options(self):
337 return []
338
murgatroid996a4c4fa2015-02-27 12:08:57 -0800339 def build_steps(self):
340 return [['tools/run_tests/build_ruby.sh']]
341
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200342 def post_tests_steps(self):
Nicolas "Pixel" Noble7ef1e532015-12-02 00:55:33 +0100343 return [['tools/run_tests/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200344
murgatroid99a3e244f2015-09-22 11:25:53 -0700345 def makefile_name(self):
346 return 'Makefile'
347
murgatroid99132ce6a2015-03-04 17:29:14 -0800348 def supports_multi_config(self):
349 return False
350
Jan Tattermusch788ee232016-01-26 12:19:44 -0800351 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800352 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800353
murgatroid99132ce6a2015-03-04 17:29:14 -0800354 def __str__(self):
355 return 'ruby'
356
Craig Tillerd625d812015-04-08 15:52:35 -0700357
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800358class CSharpLanguage(object):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700359 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700360 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700361
Craig Tiller883064c2015-11-04 10:06:10 -0800362 def test_specs(self, config, args):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800363 with open('src/csharp/tests.json') as f:
364 tests_json = json.load(f)
365 assemblies = tests_json['assemblies']
366 tests = tests_json['tests']
367
368 msbuild_config = _WINDOWS_CONFIG[config.build_config]
369 assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
370 for a in assemblies]
371
372 extra_args = ['-labels'] + assembly_files
373
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700374 if self.platform == 'windows':
Jan Tattermusch03c01062015-12-11 14:28:56 -0800375 script_name = 'tools\\run_tests\\run_csharp.bat'
376 extra_args += ['-domain=None']
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700377 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800378 script_name = 'tools/run_tests/run_csharp.sh'
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700379
Jan Tattermuschbdf4b2e2015-10-28 08:22:34 -0700380 if config.build_config == 'gcov':
381 # On Windows, we only collect C# code coverage.
382 # On Linux, we only collect coverage for native extension.
383 # For code coverage all tests need to run as one suite.
Jan Tattermusch03c01062015-12-11 14:28:56 -0800384 return [config.job_spec([script_name] + extra_args, None,
385 shortname='csharp.coverage',
386 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jan Tattermusch61c3a832015-10-27 17:54:50 -0700387 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800388 specs = []
389 for test in tests:
390 cmdline = [script_name, '-run=%s' % test] + extra_args
391 if self.platform == 'windows':
392 # use different output directory for each test to prevent
393 # TestResult.xml clash between parallel test runs.
394 cmdline += ['-work=test-result/%s' % uuid.uuid4()]
395 specs.append(config.job_spec(cmdline, None,
396 shortname='csharp.%s' % test,
397 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
398 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800399
murgatroid99256d3df2015-09-21 16:58:02 -0700400 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700401 if self.platform == 'windows':
Jan Tattermusch874aec02015-10-07 19:26:19 -0700402 return [['tools\\run_tests\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700403 else:
404 return [['tools/run_tests/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700405
Craig Tiller883064c2015-11-04 10:06:10 -0800406 def make_targets(self, test_regex):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700407 # For Windows, this target doesn't really build anything,
408 # everything is build by buildall script later.
Craig Tillerd5904822015-08-31 21:30:58 -0700409 if self.platform == 'windows':
410 return []
411 else:
412 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800413
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800414 def make_options(self):
415 if self.platform == 'mac':
416 # On Mac, official distribution of mono is 32bit.
417 return ['CFLAGS=-arch i386', 'LDFLAGS=-arch i386']
418 else:
419 return []
420
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800421 def build_steps(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700422 if self.platform == 'windows':
423 return [['src\\csharp\\buildall.bat']]
424 else:
425 return [['tools/run_tests/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000426
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200427 def post_tests_steps(self):
428 return []
429
murgatroid99a3e244f2015-09-22 11:25:53 -0700430 def makefile_name(self):
431 return 'Makefile'
432
murgatroid99132ce6a2015-03-04 17:29:14 -0800433 def supports_multi_config(self):
434 return False
435
Jan Tattermusch788ee232016-01-26 12:19:44 -0800436 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800437 return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800438
murgatroid99132ce6a2015-03-04 17:29:14 -0800439 def __str__(self):
440 return 'csharp'
441
Craig Tillerd625d812015-04-08 15:52:35 -0700442
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700443class ObjCLanguage(object):
444
Craig Tiller883064c2015-11-04 10:06:10 -0800445 def test_specs(self, config, args):
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700446 return [config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
447 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
448
murgatroid99256d3df2015-09-21 16:58:02 -0700449 def pre_build_steps(self):
450 return []
451
Craig Tiller883064c2015-11-04 10:06:10 -0800452 def make_targets(self, test_regex):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700453 return ['grpc_objective_c_plugin', 'interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700454
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800455 def make_options(self):
456 return []
457
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700458 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700459 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700460
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200461 def post_tests_steps(self):
462 return []
463
murgatroid99a3e244f2015-09-22 11:25:53 -0700464 def makefile_name(self):
465 return 'Makefile'
466
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700467 def supports_multi_config(self):
468 return False
469
Jan Tattermusch788ee232016-01-26 12:19:44 -0800470 def dockerfile_dir(self, config, arch):
471 return None
472
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700473 def __str__(self):
474 return 'objc'
475
476
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100477class Sanity(object):
478
Craig Tiller883064c2015-11-04 10:06:10 -0800479 def test_specs(self, config, args):
Craig Tiller94d04a52016-01-20 10:58:23 -0800480 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800481 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
482 return [config.job_spec(cmd['script'].split(), None,
483 timeout_seconds=None, environ={'TEST': 'true'},
484 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800485 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100486
murgatroid99256d3df2015-09-21 16:58:02 -0700487 def pre_build_steps(self):
488 return []
489
Craig Tiller883064c2015-11-04 10:06:10 -0800490 def make_targets(self, test_regex):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100491 return ['run_dep_checks']
492
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800493 def make_options(self):
494 return []
495
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100496 def build_steps(self):
497 return []
498
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200499 def post_tests_steps(self):
500 return []
501
murgatroid99a3e244f2015-09-22 11:25:53 -0700502 def makefile_name(self):
503 return 'Makefile'
504
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100505 def supports_multi_config(self):
506 return False
507
Jan Tattermusch788ee232016-01-26 12:19:44 -0800508 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800509 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800510
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100511 def __str__(self):
512 return 'sanity'
513
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200514
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100515class Build(object):
516
Craig Tiller883064c2015-11-04 10:06:10 -0800517 def test_specs(self, config, args):
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100518 return []
519
murgatroid99256d3df2015-09-21 16:58:02 -0700520 def pre_build_steps(self):
521 return []
522
Craig Tiller883064c2015-11-04 10:06:10 -0800523 def make_targets(self, test_regex):
Nicolas "Pixel" Noblec23827b2015-04-23 06:17:55 +0200524 return ['static']
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100525
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800526 def make_options(self):
527 return []
528
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100529 def build_steps(self):
530 return []
531
Nicolas "Pixel" Noblefe300452015-10-27 23:05:10 +0100532 def post_tests_steps(self):
533 return []
534
murgatroid99a3e244f2015-09-22 11:25:53 -0700535 def makefile_name(self):
536 return 'Makefile'
537
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100538 def supports_multi_config(self):
539 return True
540
Jan Tattermusch788ee232016-01-26 12:19:44 -0800541 def dockerfile_dir(self, config, arch):
542 return None
543
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100544 def __str__(self):
545 return self.make_target
546
547
Craig Tiller738c3342015-01-12 14:28:33 -0800548# different configurations we can run under
Craig Tillera0f85172016-01-20 15:56:06 -0800549with open('tools/run_tests/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800550 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800551
552
Nicolas "Pixel" Noble1fb5e822015-03-16 06:20:37 +0100553_DEFAULT = ['opt']
Craig Tillerc7449162015-01-16 14:42:10 -0800554_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800555 'c++': CLanguage('cxx', 'c++'),
556 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800557 'node': NodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000558 'php': PhpLanguage(),
559 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800560 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100561 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700562 'objc' : ObjCLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100563 'sanity': Sanity(),
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100564 'build': Build(),
Craig Tillereb272bc2015-01-30 13:13:14 -0800565 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800566
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700567_WINDOWS_CONFIG = {
568 'dbg': 'Debug',
569 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800570 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700571 }
572
David Garcia Quintase90cd372015-05-31 18:15:26 -0700573
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800574def _windows_arch_option(arch):
575 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800576 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800577 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800578 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800579 return '/p:Platform=x64'
580 else:
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800581 print 'Architecture %s not supported.' % arch
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800582 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800583
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800584
585def _check_arch_option(arch):
586 """Checks that architecture option is valid."""
587 if platform_string() == 'windows':
588 _windows_arch_option(arch)
589 elif platform_string() == 'linux':
590 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800591 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800592 if arch == 'default':
593 return
594 elif runtime_arch == '64bit' and arch == 'x64':
595 return
596 elif runtime_arch == '32bit' and arch == 'x86':
597 return
598 else:
599 print 'Architecture %s does not match current runtime architecture.' % arch
600 sys.exit(1)
601 else:
602 if args.arch != 'default':
603 print 'Architecture %s not supported on current platform.' % args.arch
604 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800605
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800606
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800607def _windows_build_bat(compiler):
608 """Returns name of build.bat for selected compiler."""
609 if compiler == 'default' or compiler == 'vs2013':
610 return 'vsprojects\\build_vs2013.bat'
611 elif compiler == 'vs2015':
612 return 'vsprojects\\build_vs2015.bat'
613 elif compiler == 'vs2010':
614 return 'vsprojects\\build_vs2010.bat'
615 else:
616 print 'Compiler %s not supported.' % compiler
617 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800618
619
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800620def _windows_toolset_option(compiler):
621 """Returns msbuild PlatformToolset for selected compiler."""
622 if compiler == 'default' or compiler == 'vs2013':
623 return '/p:PlatformToolset=v120'
624 elif compiler == 'vs2015':
625 return '/p:PlatformToolset=v140'
626 elif compiler == 'vs2010':
627 return '/p:PlatformToolset=v100'
628 else:
629 print 'Compiler %s not supported.' % compiler
630 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800631
632
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800633def _docker_arch_suffix(arch):
634 """Returns suffix to dockerfile dir to use."""
635 if arch == 'default' or arch == 'x64':
636 return 'x64'
637 elif arch == 'x86':
638 return 'x86'
639 else:
640 print 'Architecture %s not supported with current settings.' % arch
641 sys.exit(1)
642
643
Jan Tattermusch788ee232016-01-26 12:19:44 -0800644def _get_dockerfile_dir(language, cfg, arch):
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800645 """Returns dockerfile to use"""
Jan Tattermusch788ee232016-01-26 12:19:44 -0800646 custom = language.dockerfile_dir(cfg, arch)
647 if custom:
648 return custom
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800649 else:
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800650 return 'tools/dockerfile/grpc_tests_multilang_%s' % _docker_arch_suffix(arch)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800651
David Garcia Quintase90cd372015-05-31 18:15:26 -0700652def runs_per_test_type(arg_str):
653 """Auxilary function to parse the "runs_per_test" flag.
654
655 Returns:
656 A positive integer or 0, the latter indicating an infinite number of
657 runs.
658
659 Raises:
660 argparse.ArgumentTypeError: Upon invalid input.
661 """
662 if arg_str == 'inf':
663 return 0
664 try:
665 n = int(arg_str)
666 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -0700667 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -0700668 except:
Adele Zhoue4c35612015-10-16 15:34:23 -0700669 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700670 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700671
672# parse command line
673argp = argparse.ArgumentParser(description='Run grpc tests.')
674argp.add_argument('-c', '--config',
675 choices=['all'] + sorted(_CONFIGS.keys()),
676 nargs='+',
677 default=_DEFAULT)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700678argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
679 help='A positive integer or "inf". If "inf", all tests will run in an '
680 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -0800681argp.add_argument('-r', '--regex', default='.*', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -0800682argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -0800683argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -0800684argp.add_argument('-f', '--forever',
685 default=False,
686 action='store_const',
687 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +0100688argp.add_argument('-t', '--travis',
689 default=False,
690 action='store_const',
691 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -0800692argp.add_argument('--newline_on_success',
693 default=False,
694 action='store_const',
695 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -0800696argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -0700697 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -0800698 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -0700699 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -0700700argp.add_argument('-S', '--stop_on_failure',
701 default=False,
702 action='store_const',
703 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700704argp.add_argument('--use_docker',
705 default=False,
706 action='store_const',
707 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700708 help='Run all the tests under docker. That provides ' +
709 'additional isolation and prevents the need to install ' +
710 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -0700711argp.add_argument('--allow_flakes',
712 default=False,
713 action='store_const',
714 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700715 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800716argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800717 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800718 default='default',
719 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
720argp.add_argument('--compiler',
721 choices=['default', 'vs2010', 'vs2013', 'vs2015'],
722 default='default',
723 help='Selects compiler to use. For some platforms "default" is the only supported choice.')
724argp.add_argument('--build_only',
725 default=False,
726 action='store_const',
727 const=True,
728 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -0800729argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
730 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -0800731argp.add_argument('--update_submodules', default=[], nargs='*',
732 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
733 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -0700734argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +0200735argp.add_argument('-x', '--xml_report', default=None, type=str,
736 help='Generates a JUnit-compatible XML report')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800737args = argp.parse_args()
738
Craig Tiller5f735a62016-01-20 09:31:15 -0800739jobset.measure_cpu_costs = args.measure_cpu_costs
740
Craig Tiller1676f912016-01-05 10:49:44 -0800741# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -0800742need_to_regenerate_projects = False
743for spec in args.update_submodules:
744 spec = spec.split(':', 1)
745 if len(spec) == 1:
746 submodule = spec[0]
747 branch = 'master'
748 elif len(spec) == 2:
749 submodule = spec[0]
750 branch = spec[1]
751 cwd = 'third_party/%s' % submodule
752 def git(cmd, cwd=cwd):
753 print 'in %s: git %s' % (cwd, cmd)
754 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
755 git('fetch')
756 git('checkout %s' % branch)
757 git('pull origin %s' % branch)
758 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
759 need_to_regenerate_projects = True
760if need_to_regenerate_projects:
761 if jobset.platform_string() == 'linux':
762 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
763 else:
764 print 'WARNING: may need to regenerate projects, but since we are not on'
765 print ' Linux this step is being skipped. Compilation MAY fail.'
Craig Tiller1676f912016-01-05 10:49:44 -0800766
767
Nicolas Nobleddef2462015-01-06 18:08:25 -0800768# grab config
Craig Tiller738c3342015-01-12 14:28:33 -0800769run_configs = set(_CONFIGS[cfg]
770 for cfg in itertools.chain.from_iterable(
771 _CONFIGS.iterkeys() if x == 'all' else [x]
772 for x in args.config))
773build_configs = set(cfg.build_config for cfg in run_configs)
Craig Tillerf1973b02015-01-16 12:32:13 -0800774
Craig Tiller06805272015-06-11 14:46:47 -0700775if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -0700776 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -0700777
Adele Zhou6b9527c2015-11-20 15:56:35 -0800778if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -0800779 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -0800780else:
781 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -0800782# We don't support code coverage on some languages
783if 'gcov' in args.config:
784 for bad in ['objc', 'sanity', 'build']:
785 if bad in lang_list:
786 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -0800787
788languages = set(_LANGUAGES[l] for l in lang_list)
murgatroid99132ce6a2015-03-04 17:29:14 -0800789
790if len(build_configs) > 1:
791 for language in languages:
792 if not language.supports_multi_config():
793 print language, 'does not support multiple build configurations'
794 sys.exit(1)
795
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800796language_make_options=[]
797if any(language.make_options() for language in languages):
798 if len(languages) != 1:
799 print 'languages with custom make options cannot be built simultaneously with other languages'
800 sys.exit(1)
801 else:
802 language_make_options = next(iter(languages)).make_options()
803
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800804if len(languages) != 1 or len(build_configs) != 1:
805 print 'Multi-language and multi-config testing is not supported.'
806 sys.exit(1)
807
808if args.use_docker:
809 if not args.travis:
810 print 'Seen --use_docker flag, will run tests under docker.'
811 print
812 print 'IMPORTANT: The changes you are testing need to be locally committed'
813 print 'because only the committed changes in the current branch will be'
814 print 'copied to the docker environment.'
815 time.sleep(5)
816
817 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -0800818 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800819
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800820 env = os.environ.copy()
821 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch788ee232016-01-26 12:19:44 -0800822 env['DOCKERFILE_DIR'] = _get_dockerfile_dir(next(iter(languages)),
823 next(iter(build_configs)),
824 args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800825 env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh'
826 if args.xml_report:
827 env['XML_REPORT'] = args.xml_report
828 if not args.travis:
829 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
830
831 subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'],
832 shell=True,
833 env=env)
834 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800835
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800836if platform_string() != 'windows' and args.compiler != 'default':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800837 print 'Compiler %s not supported on current platform.' % args.compiler
838 sys.exit(1)
839
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800840_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800841
Jan Tattermuschfba65302016-01-25 18:21:14 -0800842def make_jobspec(cfg, targets, makefile='Makefile'):
843 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -0700844 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -0700845 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -0700846 # empirically /m:2 gives the best performance/price and should prevent
847 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -0700848 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -0700849 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -0700850 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -0700851 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800852 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -0700853 'vsprojects\\%s.sln' % target,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800854 '/p:Configuration=%s' % _WINDOWS_CONFIG[cfg],
855 _windows_toolset_option(args.compiler),
856 _windows_arch_option(args.arch)] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800857 extra_args +
858 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -0800859 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -0700860 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -0800861 else:
murgatroid998ae409f2015-10-26 16:39:00 -0700862 if targets:
863 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
864 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -0800865 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -0800866 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
867 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800868 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -0800869 ([] if not args.travis else ['JENKINS_BUILD=1']) +
870 targets,
Craig Tiller590105a2016-01-19 13:03:46 -0800871 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -0700872 else:
873 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -0800874
murgatroid99a3e244f2015-09-22 11:25:53 -0700875make_targets = {}
876for l in languages:
877 makefile = l.makefile_name()
878 make_targets[makefile] = make_targets.get(makefile, set()).union(
Craig Tiller883064c2015-11-04 10:06:10 -0800879 set(l.make_targets(args.regex)))
Craig Tiller5058c692015-04-08 09:42:04 -0700880
Jan Tattermusche4a69182015-12-15 09:53:01 -0800881def build_step_environ(cfg):
882 environ = {'CONFIG': cfg}
Jan Tattermusch68016a12015-12-16 15:31:33 -0800883 msbuild_cfg = _WINDOWS_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -0800884 if msbuild_cfg:
885 environ['MSBUILD_CONFIG'] = msbuild_cfg
886 return environ
887
murgatroid99fddac962015-09-22 09:20:11 -0700888build_steps = list(set(
Jan Tattermusche4a69182015-12-15 09:53:01 -0800889 jobset.JobSpec(cmdline, environ=build_step_environ(cfg), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -0700890 for cfg in build_configs
891 for l in languages
892 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -0700893if make_targets:
murgatroid99a3e244f2015-09-22 11:25:53 -0700894 make_commands = itertools.chain.from_iterable(make_jobspec(cfg, list(targets), makefile) for cfg in build_configs for (makefile, targets) in make_targets.iteritems())
Craig Tiller6fd23842015-09-01 07:36:31 -0700895 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -0700896build_steps.extend(set(
Craig Tiller590105a2016-01-19 13:03:46 -0800897 jobset.JobSpec(cmdline, environ=build_step_environ(cfg), timeout_seconds=None)
murgatroid99132ce6a2015-03-04 17:29:14 -0800898 for cfg in build_configs
Craig Tiller547db2b2015-01-30 14:08:39 -0800899 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -0700900 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -0800901
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200902post_tests_steps = list(set(
Jan Tattermusche4a69182015-12-15 09:53:01 -0800903 jobset.JobSpec(cmdline, environ=build_step_environ(cfg))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200904 for cfg in build_configs
905 for l in languages
906 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -0800907runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -0800908forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -0800909
Nicolas Nobleddef2462015-01-06 18:08:25 -0800910
Craig Tiller71735182015-01-15 17:07:13 -0800911class TestCache(object):
Craig Tillerb50d1662015-01-15 17:28:21 -0800912 """Cache for running tests."""
913
David Klempner25739582015-02-11 15:57:32 -0800914 def __init__(self, use_cache_results):
Craig Tiller71735182015-01-15 17:07:13 -0800915 self._last_successful_run = {}
David Klempner25739582015-02-11 15:57:32 -0800916 self._use_cache_results = use_cache_results
Craig Tiller69cd2372015-06-11 09:38:09 -0700917 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800918
919 def should_run(self, cmdline, bin_hash):
Craig Tiller71735182015-01-15 17:07:13 -0800920 if cmdline not in self._last_successful_run:
921 return True
922 if self._last_successful_run[cmdline] != bin_hash:
923 return True
David Klempner25739582015-02-11 15:57:32 -0800924 if not self._use_cache_results:
925 return True
Craig Tiller71735182015-01-15 17:07:13 -0800926 return False
927
928 def finished(self, cmdline, bin_hash):
Craig Tiller547db2b2015-01-30 14:08:39 -0800929 self._last_successful_run[cmdline] = bin_hash
Craig Tiller69cd2372015-06-11 09:38:09 -0700930 if time.time() - self._last_save > 1:
931 self.save()
Craig Tiller71735182015-01-15 17:07:13 -0800932
933 def dump(self):
Craig Tillerb50d1662015-01-15 17:28:21 -0800934 return [{'cmdline': k, 'hash': v}
935 for k, v in self._last_successful_run.iteritems()]
Craig Tiller71735182015-01-15 17:07:13 -0800936
937 def parse(self, exdump):
938 self._last_successful_run = dict((o['cmdline'], o['hash']) for o in exdump)
939
940 def save(self):
941 with open('.run_tests_cache', 'w') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800942 f.write(json.dumps(self.dump()))
Craig Tiller69cd2372015-06-11 09:38:09 -0700943 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800944
Craig Tiller1cc11db2015-01-15 22:50:50 -0800945 def maybe_load(self):
946 if os.path.exists('.run_tests_cache'):
947 with open('.run_tests_cache') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800948 self.parse(json.loads(f.read()))
Craig Tiller71735182015-01-15 17:07:13 -0800949
950
Craig Tillerf53d9c82015-08-04 14:19:43 -0700951def _start_port_server(port_server_port):
952 # check if a compatible port server is running
953 # if incompatible (version mismatch) ==> start a new one
954 # if not running ==> start a new one
955 # otherwise, leave it up
956 try:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700957 version = int(urllib2.urlopen(
958 'http://localhost:%d/version_number' % port_server_port,
959 timeout=1).read())
960 print 'detected port server running version %d' % version
Craig Tillerf53d9c82015-08-04 14:19:43 -0700961 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -0700962 except Exception as e:
Craig Tiller0d6499e2015-10-05 14:00:47 -0700963 print 'failed to detect port server: %s' % sys.exc_info()[0]
Craig Tillerfe4939f2015-10-06 12:55:36 -0700964 print e.strerror
Craig Tillerf53d9c82015-08-04 14:19:43 -0700965 running = False
966 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700967 current_version = int(subprocess.check_output(
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800968 [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
969 'dump_version']))
Craig Tillerfe4939f2015-10-06 12:55:36 -0700970 print 'my port server is version %d' % current_version
971 running = (version >= current_version)
972 if not running:
973 print 'port_server version mismatch: killing the old one'
974 urllib2.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
975 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -0700976 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -0700977 fd, logfile = tempfile.mkstemp()
978 os.close(fd)
979 print 'starting port_server, with log file %s' % logfile
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800980 args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
981 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -0700982 env = dict(os.environ)
983 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +0100984 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800985 # Working directory of port server needs to be outside of Jenkins
986 # workspace to prevent file lock issues.
987 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -0700988 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -0700989 args,
990 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800991 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -0700992 creationflags = 0x00000008, # detached process
993 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -0700994 else:
995 port_server = subprocess.Popen(
996 args,
Craig Tiller367d41d2015-10-12 13:00:22 -0700997 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -0700998 preexec_fn=os.setsid,
999 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001000 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001001 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001002 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001003 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001004 if waits > 10:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001005 print 'killing port server due to excessive start up waits'
Craig Tillerabd37fd2015-08-26 07:54:01 -07001006 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001007 if port_server.poll() is not None:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001008 print 'port_server failed to start'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001009 # try one final time: maybe another build managed to start one
1010 time.sleep(1)
1011 try:
1012 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1013 timeout=1).read()
1014 print 'last ditch attempt to contact port server succeeded'
1015 break
1016 except:
1017 traceback.print_exc();
1018 port_log = open(logfile, 'r').read()
1019 print port_log
1020 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001021 try:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001022 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1023 timeout=1).read()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001024 print 'port server is up and ready'
Craig Tillerf53d9c82015-08-04 14:19:43 -07001025 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001026 except socket.timeout:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001027 print 'waiting for port_server: timeout'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001028 traceback.print_exc();
1029 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001030 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001031 except urllib2.URLError:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001032 print 'waiting for port_server: urlerror'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001033 traceback.print_exc();
1034 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001035 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001036 except:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001037 traceback.print_exc();
Craig Tillerf53d9c82015-08-04 14:19:43 -07001038 port_server.kill()
1039 raise
1040
1041
Adele Zhoud5fffa52015-10-23 15:51:42 -07001042def _calculate_num_runs_failures(list_of_results):
1043 """Caculate number of runs and failures for a particular test.
1044
1045 Args:
1046 list_of_results: (List) of JobResult object.
1047 Returns:
1048 A tuple of total number of runs and failures.
1049 """
1050 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1051 num_failures = 0
1052 for jobresult in list_of_results:
1053 if jobresult.retries > 0:
1054 num_runs += jobresult.retries
1055 if jobresult.num_failures > 0:
1056 num_failures += jobresult.num_failures
1057 return num_runs, num_failures
1058
Adele Zhou6b9527c2015-11-20 15:56:35 -08001059
Craig Tillereb9de8b2016-01-08 08:57:41 -08001060# _build_and_run results
1061class BuildAndRunError(object):
1062
1063 BUILD = object()
1064 TEST = object()
1065 POST_TEST = object()
1066
1067
1068# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001069def _build_and_run(
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001070 check_cancelled, newline_on_success, cache, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001071 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001072 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001073 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001074 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001075 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001076 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001077 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001078
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001079 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001080 if xml_report:
1081 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001082 return []
ctiller3040cb72015-01-07 12:13:17 -08001083
Craig Tiller234b6e72015-05-23 10:12:40 -07001084 # start antagonists
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001085 antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001086 for _ in range(0, args.antagonists)]
Craig Tillerfe4939f2015-10-06 12:55:36 -07001087 port_server_port = 32767
Craig Tillerf53d9c82015-08-04 14:19:43 -07001088 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001089 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001090 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001091 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001092 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001093 one_run = set(
1094 spec
1095 for config in run_configs
1096 for language in languages
Craig Tiller883064c2015-11-04 10:06:10 -08001097 for spec in language.test_specs(config, args)
yang-g6c1fdc62015-08-18 11:57:42 -07001098 if re.search(args.regex, spec.shortname))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001099 # When running on travis, we want out test runs to be as similar as possible
1100 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001101 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001102 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1103 else:
1104 # whereas otherwise, we want to shuffle things up to give all tests a
1105 # chance to run.
1106 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1107 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001108 if infinite_runs:
1109 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 -07001110 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1111 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001112 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001113
Adele Zhou803af152015-11-30 15:16:16 -08001114 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001115 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001116 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001117 stop_on_failure=args.stop_on_failure,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001118 cache=cache if not xml_report else None,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001119 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
Adele Zhoud5fffa52015-10-23 15:51:42 -07001120 if resultset:
1121 for k, v in resultset.iteritems():
1122 num_runs, num_failures = _calculate_num_runs_failures(v)
1123 if num_failures == num_runs: # what about infinite_runs???
1124 jobset.message('FAILED', k, do_newline=True)
1125 elif num_failures > 0:
1126 jobset.message(
1127 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1128 do_newline=True)
1129 else:
1130 jobset.message('PASSED', k, do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001131 finally:
1132 for antagonist in antagonists:
1133 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001134 if xml_report and resultset:
Adele Zhou3bc7ba42015-11-05 10:21:58 -08001135 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillerd86a3942015-01-14 12:48:54 -08001136
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001137 number_failures, _ = jobset.run(
1138 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001139 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001140
1141 out = []
1142 if number_failures:
1143 out.append(BuildAndRunError.POST_TEST)
1144 if num_test_failures:
1145 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001146
Craig Tiller69cd2372015-06-11 09:38:09 -07001147 if cache: cache.save()
1148
Craig Tillereb9de8b2016-01-08 08:57:41 -08001149 return out
ctiller3040cb72015-01-07 12:13:17 -08001150
1151
David Klempner25739582015-02-11 15:57:32 -08001152test_cache = TestCache(runs_per_test == 1)
Craig Tiller547db2b2015-01-30 14:08:39 -08001153test_cache.maybe_load()
Craig Tiller71735182015-01-15 17:07:13 -08001154
ctiller3040cb72015-01-07 12:13:17 -08001155if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001156 success = True
ctiller3040cb72015-01-07 12:13:17 -08001157 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001158 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001159 initial_time = dw.most_recent_change()
1160 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001161 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001162 errors = _build_and_run(check_cancelled=have_files_changed,
1163 newline_on_success=False,
1164 cache=test_cache,
1165 build_only=args.build_only) == 0
1166 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001167 jobset.message('SUCCESS',
1168 'All tests are now passing properly',
1169 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001170 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001171 while not have_files_changed():
1172 time.sleep(1)
1173else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001174 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001175 newline_on_success=args.newline_on_success,
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001176 cache=test_cache,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001177 xml_report=args.xml_report,
1178 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001179 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001180 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1181 else:
1182 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001183 exit_code = 0
1184 if BuildAndRunError.BUILD in errors:
1185 exit_code |= 1
Craig Tiller4f2be362016-01-08 08:59:20 -08001186 if BuildAndRunError.TEST in errors and not args.travis:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001187 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001188 if BuildAndRunError.POST_TEST in errors:
1189 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001190 sys.exit(exit_code)
Craig Tillera0f85172016-01-20 15:56:06 -08001191