blob: de3716bc887e743c2fa42cbb751ee3c18a21e3f2 [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):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800198 self.platform = platform_string()
Jan Tattermusche477b842016-02-06 22:19:01 -0800199 self.node_version = '0.12'
200
Craig Tiller883064c2015-11-04 10:06:10 -0800201 def test_specs(self, config, args):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800202 if self.platform == 'windows':
203 return [config.job_spec(['tools\\run_tests\\run_node.bat'], None)]
204 else:
205 return [config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
206 None,
207 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800208
murgatroid99256d3df2015-09-21 16:58:02 -0700209 def pre_build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800210 if self.platform == 'windows':
211 return [['tools\\run_tests\\pre_build_node.bat']]
212 else:
213 return [['tools/run_tests/pre_build_node.sh', self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700214
Craig Tiller883064c2015-11-04 10:06:10 -0800215 def make_targets(self, test_regex):
murgatroid99db5b1602015-10-01 13:20:11 -0700216 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800217
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800218 def make_options(self):
219 return []
220
murgatroid992c8d5162015-01-26 10:41:21 -0800221 def build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800222 if self.platform == 'windows':
223 return [['tools\\run_tests\\build_node.bat']]
224 else:
225 return [['tools/run_tests/build_node.sh', self.node_version]]
Craig Tillerc7449162015-01-16 14:42:10 -0800226
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200227 def post_tests_steps(self):
228 return []
229
murgatroid99a3e244f2015-09-22 11:25:53 -0700230 def makefile_name(self):
231 return 'Makefile'
232
murgatroid99132ce6a2015-03-04 17:29:14 -0800233 def supports_multi_config(self):
234 return False
235
Jan Tattermusch788ee232016-01-26 12:19:44 -0800236 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800237 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800238
murgatroid99132ce6a2015-03-04 17:29:14 -0800239 def __str__(self):
240 return 'node'
241
Craig Tiller99775822015-01-30 13:07:16 -0800242
Craig Tillerc7449162015-01-16 14:42:10 -0800243class PhpLanguage(object):
244
Craig Tiller883064c2015-11-04 10:06:10 -0800245 def test_specs(self, config, args):
Craig Tiller4fc90032015-05-21 10:39:52 -0700246 return [config.job_spec(['src/php/bin/run_tests.sh'], None,
Craig Tiller06805272015-06-11 14:46:47 -0700247 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800248
murgatroid99256d3df2015-09-21 16:58:02 -0700249 def pre_build_steps(self):
250 return []
251
Craig Tiller883064c2015-11-04 10:06:10 -0800252 def make_targets(self, test_regex):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700253 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800254
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800255 def make_options(self):
256 return []
257
Craig Tillerc7449162015-01-16 14:42:10 -0800258 def build_steps(self):
259 return [['tools/run_tests/build_php.sh']]
260
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200261 def post_tests_steps(self):
Stanley Cheunga6b95482016-01-13 16:10:48 -0800262 return [['tools/run_tests/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200263
murgatroid99a3e244f2015-09-22 11:25:53 -0700264 def makefile_name(self):
265 return 'Makefile'
266
murgatroid99132ce6a2015-03-04 17:29:14 -0800267 def supports_multi_config(self):
268 return False
269
Jan Tattermusch788ee232016-01-26 12:19:44 -0800270 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800271 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800272
murgatroid99132ce6a2015-03-04 17:29:14 -0800273 def __str__(self):
274 return 'php'
275
Craig Tillerc7449162015-01-16 14:42:10 -0800276
Nathaniel Manista840615e2015-01-22 20:31:47 +0000277class PythonLanguage(object):
278
Craig Tiller49f61322015-03-03 13:02:11 -0800279 def __init__(self):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700280 self._build_python_versions = ['2.7']
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700281 self._has_python_versions = []
Craig Tiller49f61322015-03-03 13:02:11 -0800282
Craig Tiller883064c2015-11-04 10:06:10 -0800283 def test_specs(self, config, args):
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700284 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
285 environment['PYVER'] = '2.7'
286 return [config.job_spec(
287 ['tools/run_tests/run_python.sh'],
288 None,
289 environ=environment,
290 shortname='py.test',
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -0700291 timeout_seconds=15*60
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700292 )]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000293
murgatroid99256d3df2015-09-21 16:58:02 -0700294 def pre_build_steps(self):
295 return []
296
Craig Tiller883064c2015-11-04 10:06:10 -0800297 def make_targets(self, test_regex):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700298 return ['static_c', 'grpc_python_plugin', 'shared_c']
Nathaniel Manista840615e2015-01-22 20:31:47 +0000299
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800300 def make_options(self):
301 return []
302
Nathaniel Manista840615e2015-01-22 20:31:47 +0000303 def build_steps(self):
Masood Malekghassemie5f70022015-06-29 09:20:26 -0700304 commands = []
305 for python_version in self._build_python_versions:
306 try:
307 with open(os.devnull, 'w') as output:
308 subprocess.check_call(['which', 'python' + python_version],
309 stdout=output, stderr=output)
310 commands.append(['tools/run_tests/build_python.sh', python_version])
311 self._has_python_versions.append(python_version)
312 except:
313 jobset.message('WARNING', 'Missing Python ' + python_version,
314 do_newline=True)
315 return commands
Nathaniel Manista840615e2015-01-22 20:31:47 +0000316
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200317 def post_tests_steps(self):
318 return []
319
murgatroid99a3e244f2015-09-22 11:25:53 -0700320 def makefile_name(self):
321 return 'Makefile'
322
murgatroid99132ce6a2015-03-04 17:29:14 -0800323 def supports_multi_config(self):
324 return False
325
Jan Tattermusch788ee232016-01-26 12:19:44 -0800326 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800327 return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800328
murgatroid99132ce6a2015-03-04 17:29:14 -0800329 def __str__(self):
330 return 'python'
331
Craig Tillerd625d812015-04-08 15:52:35 -0700332
murgatroid996a4c4fa2015-02-27 12:08:57 -0800333class RubyLanguage(object):
334
Craig Tiller883064c2015-11-04 10:06:10 -0800335 def test_specs(self, config, args):
Craig Tiller4fc90032015-05-21 10:39:52 -0700336 return [config.job_spec(['tools/run_tests/run_ruby.sh'], None,
Craig Tiller06805272015-06-11 14:46:47 -0700337 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800338
murgatroid99256d3df2015-09-21 16:58:02 -0700339 def pre_build_steps(self):
Nicolas "Pixel" Noblebcf988f2015-10-08 03:00:42 +0200340 return [['tools/run_tests/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700341
Craig Tiller883064c2015-11-04 10:06:10 -0800342 def make_targets(self, test_regex):
murgatroid99a43c14f2015-07-30 13:31:23 -0700343 return ['static_c']
murgatroid996a4c4fa2015-02-27 12:08:57 -0800344
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800345 def make_options(self):
346 return []
347
murgatroid996a4c4fa2015-02-27 12:08:57 -0800348 def build_steps(self):
349 return [['tools/run_tests/build_ruby.sh']]
350
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200351 def post_tests_steps(self):
Nicolas "Pixel" Noble7ef1e532015-12-02 00:55:33 +0100352 return [['tools/run_tests/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200353
murgatroid99a3e244f2015-09-22 11:25:53 -0700354 def makefile_name(self):
355 return 'Makefile'
356
murgatroid99132ce6a2015-03-04 17:29:14 -0800357 def supports_multi_config(self):
358 return False
359
Jan Tattermusch788ee232016-01-26 12:19:44 -0800360 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800361 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800362
murgatroid99132ce6a2015-03-04 17:29:14 -0800363 def __str__(self):
364 return 'ruby'
365
Craig Tillerd625d812015-04-08 15:52:35 -0700366
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800367class CSharpLanguage(object):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700368 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700369 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700370
Craig Tiller883064c2015-11-04 10:06:10 -0800371 def test_specs(self, config, args):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800372 with open('src/csharp/tests.json') as f:
373 tests_json = json.load(f)
374 assemblies = tests_json['assemblies']
375 tests = tests_json['tests']
376
377 msbuild_config = _WINDOWS_CONFIG[config.build_config]
378 assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
379 for a in assemblies]
380
381 extra_args = ['-labels'] + assembly_files
382
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700383 if self.platform == 'windows':
Jan Tattermusch03c01062015-12-11 14:28:56 -0800384 script_name = 'tools\\run_tests\\run_csharp.bat'
385 extra_args += ['-domain=None']
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700386 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800387 script_name = 'tools/run_tests/run_csharp.sh'
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700388
Jan Tattermuschbdf4b2e2015-10-28 08:22:34 -0700389 if config.build_config == 'gcov':
390 # On Windows, we only collect C# code coverage.
391 # On Linux, we only collect coverage for native extension.
392 # For code coverage all tests need to run as one suite.
Jan Tattermusch03c01062015-12-11 14:28:56 -0800393 return [config.job_spec([script_name] + extra_args, None,
394 shortname='csharp.coverage',
395 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jan Tattermusch61c3a832015-10-27 17:54:50 -0700396 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800397 specs = []
398 for test in tests:
399 cmdline = [script_name, '-run=%s' % test] + extra_args
400 if self.platform == 'windows':
401 # use different output directory for each test to prevent
402 # TestResult.xml clash between parallel test runs.
403 cmdline += ['-work=test-result/%s' % uuid.uuid4()]
404 specs.append(config.job_spec(cmdline, None,
405 shortname='csharp.%s' % test,
406 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
407 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800408
murgatroid99256d3df2015-09-21 16:58:02 -0700409 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700410 if self.platform == 'windows':
Jan Tattermusch874aec02015-10-07 19:26:19 -0700411 return [['tools\\run_tests\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700412 else:
413 return [['tools/run_tests/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700414
Craig Tiller883064c2015-11-04 10:06:10 -0800415 def make_targets(self, test_regex):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700416 # For Windows, this target doesn't really build anything,
417 # everything is build by buildall script later.
Craig Tillerd5904822015-08-31 21:30:58 -0700418 if self.platform == 'windows':
419 return []
420 else:
421 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800422
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800423 def make_options(self):
424 if self.platform == 'mac':
425 # On Mac, official distribution of mono is 32bit.
426 return ['CFLAGS=-arch i386', 'LDFLAGS=-arch i386']
427 else:
428 return []
429
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800430 def build_steps(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700431 if self.platform == 'windows':
432 return [['src\\csharp\\buildall.bat']]
433 else:
434 return [['tools/run_tests/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000435
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200436 def post_tests_steps(self):
437 return []
438
murgatroid99a3e244f2015-09-22 11:25:53 -0700439 def makefile_name(self):
440 return 'Makefile'
441
murgatroid99132ce6a2015-03-04 17:29:14 -0800442 def supports_multi_config(self):
443 return False
444
Jan Tattermusch788ee232016-01-26 12:19:44 -0800445 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800446 return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800447
murgatroid99132ce6a2015-03-04 17:29:14 -0800448 def __str__(self):
449 return 'csharp'
450
Craig Tillerd625d812015-04-08 15:52:35 -0700451
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700452class ObjCLanguage(object):
453
Craig Tiller883064c2015-11-04 10:06:10 -0800454 def test_specs(self, config, args):
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700455 return [config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
456 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
457
murgatroid99256d3df2015-09-21 16:58:02 -0700458 def pre_build_steps(self):
459 return []
460
Craig Tiller883064c2015-11-04 10:06:10 -0800461 def make_targets(self, test_regex):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700462 return ['grpc_objective_c_plugin', 'interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700463
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800464 def make_options(self):
465 return []
466
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700467 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700468 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700469
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200470 def post_tests_steps(self):
471 return []
472
murgatroid99a3e244f2015-09-22 11:25:53 -0700473 def makefile_name(self):
474 return 'Makefile'
475
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700476 def supports_multi_config(self):
477 return False
478
Jan Tattermusch788ee232016-01-26 12:19:44 -0800479 def dockerfile_dir(self, config, arch):
480 return None
481
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700482 def __str__(self):
483 return 'objc'
484
485
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100486class Sanity(object):
487
Craig Tiller883064c2015-11-04 10:06:10 -0800488 def test_specs(self, config, args):
Craig Tiller94d04a52016-01-20 10:58:23 -0800489 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800490 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
491 return [config.job_spec(cmd['script'].split(), None,
492 timeout_seconds=None, environ={'TEST': 'true'},
493 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800494 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100495
murgatroid99256d3df2015-09-21 16:58:02 -0700496 def pre_build_steps(self):
497 return []
498
Craig Tiller883064c2015-11-04 10:06:10 -0800499 def make_targets(self, test_regex):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100500 return ['run_dep_checks']
501
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800502 def make_options(self):
503 return []
504
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100505 def build_steps(self):
506 return []
507
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200508 def post_tests_steps(self):
509 return []
510
murgatroid99a3e244f2015-09-22 11:25:53 -0700511 def makefile_name(self):
512 return 'Makefile'
513
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100514 def supports_multi_config(self):
515 return False
516
Jan Tattermusch788ee232016-01-26 12:19:44 -0800517 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800518 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800519
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100520 def __str__(self):
521 return 'sanity'
522
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200523
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100524class Build(object):
525
Craig Tiller883064c2015-11-04 10:06:10 -0800526 def test_specs(self, config, args):
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100527 return []
528
murgatroid99256d3df2015-09-21 16:58:02 -0700529 def pre_build_steps(self):
530 return []
531
Craig Tiller883064c2015-11-04 10:06:10 -0800532 def make_targets(self, test_regex):
Nicolas "Pixel" Noblec23827b2015-04-23 06:17:55 +0200533 return ['static']
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100534
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800535 def make_options(self):
536 return []
537
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100538 def build_steps(self):
539 return []
540
Nicolas "Pixel" Noblefe300452015-10-27 23:05:10 +0100541 def post_tests_steps(self):
542 return []
543
murgatroid99a3e244f2015-09-22 11:25:53 -0700544 def makefile_name(self):
545 return 'Makefile'
546
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100547 def supports_multi_config(self):
548 return True
549
Jan Tattermusch788ee232016-01-26 12:19:44 -0800550 def dockerfile_dir(self, config, arch):
551 return None
552
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100553 def __str__(self):
554 return self.make_target
555
556
Craig Tiller738c3342015-01-12 14:28:33 -0800557# different configurations we can run under
Craig Tillera0f85172016-01-20 15:56:06 -0800558with open('tools/run_tests/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800559 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800560
561
Nicolas "Pixel" Noble1fb5e822015-03-16 06:20:37 +0100562_DEFAULT = ['opt']
Craig Tillerc7449162015-01-16 14:42:10 -0800563_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800564 'c++': CLanguage('cxx', 'c++'),
565 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800566 'node': NodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000567 'php': PhpLanguage(),
568 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800569 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100570 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700571 'objc' : ObjCLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100572 'sanity': Sanity(),
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100573 'build': Build(),
Craig Tillereb272bc2015-01-30 13:13:14 -0800574 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800575
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700576_WINDOWS_CONFIG = {
577 'dbg': 'Debug',
578 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800579 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700580 }
581
David Garcia Quintase90cd372015-05-31 18:15:26 -0700582
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800583def _windows_arch_option(arch):
584 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800585 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800586 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800587 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800588 return '/p:Platform=x64'
589 else:
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800590 print 'Architecture %s not supported.' % arch
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800591 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800592
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800593
594def _check_arch_option(arch):
595 """Checks that architecture option is valid."""
596 if platform_string() == 'windows':
597 _windows_arch_option(arch)
598 elif platform_string() == 'linux':
599 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800600 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800601 if arch == 'default':
602 return
603 elif runtime_arch == '64bit' and arch == 'x64':
604 return
605 elif runtime_arch == '32bit' and arch == 'x86':
606 return
607 else:
608 print 'Architecture %s does not match current runtime architecture.' % arch
609 sys.exit(1)
610 else:
611 if args.arch != 'default':
612 print 'Architecture %s not supported on current platform.' % args.arch
613 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800614
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800615
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800616def _windows_build_bat(compiler):
617 """Returns name of build.bat for selected compiler."""
618 if compiler == 'default' or compiler == 'vs2013':
619 return 'vsprojects\\build_vs2013.bat'
620 elif compiler == 'vs2015':
621 return 'vsprojects\\build_vs2015.bat'
622 elif compiler == 'vs2010':
623 return 'vsprojects\\build_vs2010.bat'
624 else:
625 print 'Compiler %s not supported.' % compiler
626 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800627
628
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800629def _windows_toolset_option(compiler):
630 """Returns msbuild PlatformToolset for selected compiler."""
631 if compiler == 'default' or compiler == 'vs2013':
632 return '/p:PlatformToolset=v120'
633 elif compiler == 'vs2015':
634 return '/p:PlatformToolset=v140'
635 elif compiler == 'vs2010':
636 return '/p:PlatformToolset=v100'
637 else:
638 print 'Compiler %s not supported.' % compiler
639 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800640
641
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800642def _docker_arch_suffix(arch):
643 """Returns suffix to dockerfile dir to use."""
644 if arch == 'default' or arch == 'x64':
645 return 'x64'
646 elif arch == 'x86':
647 return 'x86'
648 else:
649 print 'Architecture %s not supported with current settings.' % arch
650 sys.exit(1)
651
652
Jan Tattermusch788ee232016-01-26 12:19:44 -0800653def _get_dockerfile_dir(language, cfg, arch):
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800654 """Returns dockerfile to use"""
Jan Tattermusch788ee232016-01-26 12:19:44 -0800655 custom = language.dockerfile_dir(cfg, arch)
656 if custom:
657 return custom
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800658 else:
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800659 return 'tools/dockerfile/grpc_tests_multilang_%s' % _docker_arch_suffix(arch)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800660
David Garcia Quintase90cd372015-05-31 18:15:26 -0700661def runs_per_test_type(arg_str):
662 """Auxilary function to parse the "runs_per_test" flag.
663
664 Returns:
665 A positive integer or 0, the latter indicating an infinite number of
666 runs.
667
668 Raises:
669 argparse.ArgumentTypeError: Upon invalid input.
670 """
671 if arg_str == 'inf':
672 return 0
673 try:
674 n = int(arg_str)
675 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -0700676 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -0700677 except:
Adele Zhoue4c35612015-10-16 15:34:23 -0700678 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700679 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700680
681# parse command line
682argp = argparse.ArgumentParser(description='Run grpc tests.')
683argp.add_argument('-c', '--config',
684 choices=['all'] + sorted(_CONFIGS.keys()),
685 nargs='+',
686 default=_DEFAULT)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700687argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
688 help='A positive integer or "inf". If "inf", all tests will run in an '
689 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -0800690argp.add_argument('-r', '--regex', default='.*', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -0800691argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -0800692argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -0800693argp.add_argument('-f', '--forever',
694 default=False,
695 action='store_const',
696 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +0100697argp.add_argument('-t', '--travis',
698 default=False,
699 action='store_const',
700 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -0800701argp.add_argument('--newline_on_success',
702 default=False,
703 action='store_const',
704 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -0800705argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -0700706 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -0800707 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -0700708 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -0700709argp.add_argument('-S', '--stop_on_failure',
710 default=False,
711 action='store_const',
712 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700713argp.add_argument('--use_docker',
714 default=False,
715 action='store_const',
716 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700717 help='Run all the tests under docker. That provides ' +
718 'additional isolation and prevents the need to install ' +
719 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -0700720argp.add_argument('--allow_flakes',
721 default=False,
722 action='store_const',
723 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700724 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800725argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800726 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800727 default='default',
728 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
729argp.add_argument('--compiler',
730 choices=['default', 'vs2010', 'vs2013', 'vs2015'],
731 default='default',
732 help='Selects compiler to use. For some platforms "default" is the only supported choice.')
733argp.add_argument('--build_only',
734 default=False,
735 action='store_const',
736 const=True,
737 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -0800738argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
739 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -0800740argp.add_argument('--update_submodules', default=[], nargs='*',
741 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
742 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -0700743argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +0200744argp.add_argument('-x', '--xml_report', default=None, type=str,
745 help='Generates a JUnit-compatible XML report')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800746args = argp.parse_args()
747
Craig Tiller5f735a62016-01-20 09:31:15 -0800748jobset.measure_cpu_costs = args.measure_cpu_costs
749
Craig Tiller1676f912016-01-05 10:49:44 -0800750# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -0800751need_to_regenerate_projects = False
752for spec in args.update_submodules:
753 spec = spec.split(':', 1)
754 if len(spec) == 1:
755 submodule = spec[0]
756 branch = 'master'
757 elif len(spec) == 2:
758 submodule = spec[0]
759 branch = spec[1]
760 cwd = 'third_party/%s' % submodule
761 def git(cmd, cwd=cwd):
762 print 'in %s: git %s' % (cwd, cmd)
763 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
764 git('fetch')
765 git('checkout %s' % branch)
766 git('pull origin %s' % branch)
767 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
768 need_to_regenerate_projects = True
769if need_to_regenerate_projects:
770 if jobset.platform_string() == 'linux':
771 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
772 else:
773 print 'WARNING: may need to regenerate projects, but since we are not on'
774 print ' Linux this step is being skipped. Compilation MAY fail.'
Craig Tiller1676f912016-01-05 10:49:44 -0800775
776
Nicolas Nobleddef2462015-01-06 18:08:25 -0800777# grab config
Craig Tiller738c3342015-01-12 14:28:33 -0800778run_configs = set(_CONFIGS[cfg]
779 for cfg in itertools.chain.from_iterable(
780 _CONFIGS.iterkeys() if x == 'all' else [x]
781 for x in args.config))
782build_configs = set(cfg.build_config for cfg in run_configs)
Craig Tillerf1973b02015-01-16 12:32:13 -0800783
Craig Tiller06805272015-06-11 14:46:47 -0700784if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -0700785 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -0700786
Adele Zhou6b9527c2015-11-20 15:56:35 -0800787if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -0800788 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -0800789else:
790 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -0800791# We don't support code coverage on some languages
792if 'gcov' in args.config:
793 for bad in ['objc', 'sanity', 'build']:
794 if bad in lang_list:
795 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -0800796
797languages = set(_LANGUAGES[l] for l in lang_list)
murgatroid99132ce6a2015-03-04 17:29:14 -0800798
799if len(build_configs) > 1:
800 for language in languages:
801 if not language.supports_multi_config():
802 print language, 'does not support multiple build configurations'
803 sys.exit(1)
804
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800805language_make_options=[]
806if any(language.make_options() for language in languages):
807 if len(languages) != 1:
808 print 'languages with custom make options cannot be built simultaneously with other languages'
809 sys.exit(1)
810 else:
811 language_make_options = next(iter(languages)).make_options()
812
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800813if len(languages) != 1 or len(build_configs) != 1:
814 print 'Multi-language and multi-config testing is not supported.'
815 sys.exit(1)
816
817if args.use_docker:
818 if not args.travis:
819 print 'Seen --use_docker flag, will run tests under docker.'
820 print
821 print 'IMPORTANT: The changes you are testing need to be locally committed'
822 print 'because only the committed changes in the current branch will be'
823 print 'copied to the docker environment.'
824 time.sleep(5)
825
826 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -0800827 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800828
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800829 env = os.environ.copy()
830 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch788ee232016-01-26 12:19:44 -0800831 env['DOCKERFILE_DIR'] = _get_dockerfile_dir(next(iter(languages)),
832 next(iter(build_configs)),
833 args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800834 env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh'
835 if args.xml_report:
836 env['XML_REPORT'] = args.xml_report
837 if not args.travis:
838 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
839
840 subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'],
841 shell=True,
842 env=env)
843 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800844
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800845if platform_string() != 'windows' and args.compiler != 'default':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800846 print 'Compiler %s not supported on current platform.' % args.compiler
847 sys.exit(1)
848
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800849_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800850
Jan Tattermuschfba65302016-01-25 18:21:14 -0800851def make_jobspec(cfg, targets, makefile='Makefile'):
852 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -0700853 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -0700854 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -0700855 # empirically /m:2 gives the best performance/price and should prevent
856 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -0700857 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -0700858 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -0700859 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -0700860 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800861 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -0700862 'vsprojects\\%s.sln' % target,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800863 '/p:Configuration=%s' % _WINDOWS_CONFIG[cfg],
864 _windows_toolset_option(args.compiler),
865 _windows_arch_option(args.arch)] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800866 extra_args +
867 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -0800868 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -0700869 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -0800870 else:
murgatroid998ae409f2015-10-26 16:39:00 -0700871 if targets:
872 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
873 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -0800874 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -0800875 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
876 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800877 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -0800878 ([] if not args.travis else ['JENKINS_BUILD=1']) +
879 targets,
Craig Tiller590105a2016-01-19 13:03:46 -0800880 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -0700881 else:
882 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -0800883
murgatroid99a3e244f2015-09-22 11:25:53 -0700884make_targets = {}
885for l in languages:
886 makefile = l.makefile_name()
887 make_targets[makefile] = make_targets.get(makefile, set()).union(
Craig Tiller883064c2015-11-04 10:06:10 -0800888 set(l.make_targets(args.regex)))
Craig Tiller5058c692015-04-08 09:42:04 -0700889
Jan Tattermusche4a69182015-12-15 09:53:01 -0800890def build_step_environ(cfg):
891 environ = {'CONFIG': cfg}
Jan Tattermusch68016a12015-12-16 15:31:33 -0800892 msbuild_cfg = _WINDOWS_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -0800893 if msbuild_cfg:
894 environ['MSBUILD_CONFIG'] = msbuild_cfg
895 return environ
896
murgatroid99fddac962015-09-22 09:20:11 -0700897build_steps = list(set(
Jan Tattermusche4a69182015-12-15 09:53:01 -0800898 jobset.JobSpec(cmdline, environ=build_step_environ(cfg), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -0700899 for cfg in build_configs
900 for l in languages
901 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -0700902if make_targets:
murgatroid99a3e244f2015-09-22 11:25:53 -0700903 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 -0700904 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -0700905build_steps.extend(set(
Craig Tiller590105a2016-01-19 13:03:46 -0800906 jobset.JobSpec(cmdline, environ=build_step_environ(cfg), timeout_seconds=None)
murgatroid99132ce6a2015-03-04 17:29:14 -0800907 for cfg in build_configs
Craig Tiller547db2b2015-01-30 14:08:39 -0800908 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -0700909 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -0800910
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200911post_tests_steps = list(set(
Jan Tattermusche4a69182015-12-15 09:53:01 -0800912 jobset.JobSpec(cmdline, environ=build_step_environ(cfg))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200913 for cfg in build_configs
914 for l in languages
915 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -0800916runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -0800917forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -0800918
Nicolas Nobleddef2462015-01-06 18:08:25 -0800919
Craig Tiller71735182015-01-15 17:07:13 -0800920class TestCache(object):
Craig Tillerb50d1662015-01-15 17:28:21 -0800921 """Cache for running tests."""
922
David Klempner25739582015-02-11 15:57:32 -0800923 def __init__(self, use_cache_results):
Craig Tiller71735182015-01-15 17:07:13 -0800924 self._last_successful_run = {}
David Klempner25739582015-02-11 15:57:32 -0800925 self._use_cache_results = use_cache_results
Craig Tiller69cd2372015-06-11 09:38:09 -0700926 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800927
928 def should_run(self, cmdline, bin_hash):
Craig Tiller71735182015-01-15 17:07:13 -0800929 if cmdline not in self._last_successful_run:
930 return True
931 if self._last_successful_run[cmdline] != bin_hash:
932 return True
David Klempner25739582015-02-11 15:57:32 -0800933 if not self._use_cache_results:
934 return True
Craig Tiller71735182015-01-15 17:07:13 -0800935 return False
936
937 def finished(self, cmdline, bin_hash):
Craig Tiller547db2b2015-01-30 14:08:39 -0800938 self._last_successful_run[cmdline] = bin_hash
Craig Tiller69cd2372015-06-11 09:38:09 -0700939 if time.time() - self._last_save > 1:
940 self.save()
Craig Tiller71735182015-01-15 17:07:13 -0800941
942 def dump(self):
Craig Tillerb50d1662015-01-15 17:28:21 -0800943 return [{'cmdline': k, 'hash': v}
944 for k, v in self._last_successful_run.iteritems()]
Craig Tiller71735182015-01-15 17:07:13 -0800945
946 def parse(self, exdump):
947 self._last_successful_run = dict((o['cmdline'], o['hash']) for o in exdump)
948
949 def save(self):
950 with open('.run_tests_cache', 'w') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800951 f.write(json.dumps(self.dump()))
Craig Tiller69cd2372015-06-11 09:38:09 -0700952 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800953
Craig Tiller1cc11db2015-01-15 22:50:50 -0800954 def maybe_load(self):
955 if os.path.exists('.run_tests_cache'):
956 with open('.run_tests_cache') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800957 self.parse(json.loads(f.read()))
Craig Tiller71735182015-01-15 17:07:13 -0800958
959
Craig Tillerf53d9c82015-08-04 14:19:43 -0700960def _start_port_server(port_server_port):
961 # check if a compatible port server is running
962 # if incompatible (version mismatch) ==> start a new one
963 # if not running ==> start a new one
964 # otherwise, leave it up
965 try:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700966 version = int(urllib2.urlopen(
967 'http://localhost:%d/version_number' % port_server_port,
968 timeout=1).read())
969 print 'detected port server running version %d' % version
Craig Tillerf53d9c82015-08-04 14:19:43 -0700970 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -0700971 except Exception as e:
Craig Tiller0d6499e2015-10-05 14:00:47 -0700972 print 'failed to detect port server: %s' % sys.exc_info()[0]
Craig Tillerfe4939f2015-10-06 12:55:36 -0700973 print e.strerror
Craig Tillerf53d9c82015-08-04 14:19:43 -0700974 running = False
975 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700976 current_version = int(subprocess.check_output(
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800977 [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
978 'dump_version']))
Craig Tillerfe4939f2015-10-06 12:55:36 -0700979 print 'my port server is version %d' % current_version
980 running = (version >= current_version)
981 if not running:
982 print 'port_server version mismatch: killing the old one'
983 urllib2.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
984 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -0700985 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -0700986 fd, logfile = tempfile.mkstemp()
987 os.close(fd)
988 print 'starting port_server, with log file %s' % logfile
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800989 args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
990 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -0700991 env = dict(os.environ)
992 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +0100993 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800994 # Working directory of port server needs to be outside of Jenkins
995 # workspace to prevent file lock issues.
996 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -0700997 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -0700998 args,
999 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001000 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -07001001 creationflags = 0x00000008, # detached process
1002 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -07001003 else:
1004 port_server = subprocess.Popen(
1005 args,
Craig Tiller367d41d2015-10-12 13:00:22 -07001006 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -07001007 preexec_fn=os.setsid,
1008 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001009 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001010 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001011 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001012 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001013 if waits > 10:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001014 print 'killing port server due to excessive start up waits'
Craig Tillerabd37fd2015-08-26 07:54:01 -07001015 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001016 if port_server.poll() is not None:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001017 print 'port_server failed to start'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001018 # try one final time: maybe another build managed to start one
1019 time.sleep(1)
1020 try:
1021 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1022 timeout=1).read()
1023 print 'last ditch attempt to contact port server succeeded'
1024 break
1025 except:
1026 traceback.print_exc();
1027 port_log = open(logfile, 'r').read()
1028 print port_log
1029 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001030 try:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001031 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1032 timeout=1).read()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001033 print 'port server is up and ready'
Craig Tillerf53d9c82015-08-04 14:19:43 -07001034 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001035 except socket.timeout:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001036 print 'waiting for port_server: timeout'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001037 traceback.print_exc();
1038 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001039 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001040 except urllib2.URLError:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001041 print 'waiting for port_server: urlerror'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001042 traceback.print_exc();
1043 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001044 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001045 except:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001046 traceback.print_exc();
Craig Tillerf53d9c82015-08-04 14:19:43 -07001047 port_server.kill()
1048 raise
1049
1050
Adele Zhoud5fffa52015-10-23 15:51:42 -07001051def _calculate_num_runs_failures(list_of_results):
1052 """Caculate number of runs and failures for a particular test.
1053
1054 Args:
1055 list_of_results: (List) of JobResult object.
1056 Returns:
1057 A tuple of total number of runs and failures.
1058 """
1059 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1060 num_failures = 0
1061 for jobresult in list_of_results:
1062 if jobresult.retries > 0:
1063 num_runs += jobresult.retries
1064 if jobresult.num_failures > 0:
1065 num_failures += jobresult.num_failures
1066 return num_runs, num_failures
1067
Adele Zhou6b9527c2015-11-20 15:56:35 -08001068
Craig Tillereb9de8b2016-01-08 08:57:41 -08001069# _build_and_run results
1070class BuildAndRunError(object):
1071
1072 BUILD = object()
1073 TEST = object()
1074 POST_TEST = object()
1075
1076
1077# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001078def _build_and_run(
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001079 check_cancelled, newline_on_success, cache, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001080 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001081 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001082 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001083 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001084 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001085 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001086 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001087
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001088 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001089 if xml_report:
1090 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001091 return []
ctiller3040cb72015-01-07 12:13:17 -08001092
Craig Tiller234b6e72015-05-23 10:12:40 -07001093 # start antagonists
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001094 antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001095 for _ in range(0, args.antagonists)]
Craig Tillerfe4939f2015-10-06 12:55:36 -07001096 port_server_port = 32767
Craig Tillerf53d9c82015-08-04 14:19:43 -07001097 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001098 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001099 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001100 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001101 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001102 one_run = set(
1103 spec
1104 for config in run_configs
1105 for language in languages
Craig Tiller883064c2015-11-04 10:06:10 -08001106 for spec in language.test_specs(config, args)
yang-g6c1fdc62015-08-18 11:57:42 -07001107 if re.search(args.regex, spec.shortname))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001108 # When running on travis, we want out test runs to be as similar as possible
1109 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001110 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001111 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1112 else:
1113 # whereas otherwise, we want to shuffle things up to give all tests a
1114 # chance to run.
1115 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1116 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001117 if infinite_runs:
1118 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 -07001119 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1120 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001121 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001122
Adele Zhou803af152015-11-30 15:16:16 -08001123 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001124 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001125 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001126 stop_on_failure=args.stop_on_failure,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001127 cache=cache if not xml_report else None,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001128 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
Adele Zhoud5fffa52015-10-23 15:51:42 -07001129 if resultset:
1130 for k, v in resultset.iteritems():
1131 num_runs, num_failures = _calculate_num_runs_failures(v)
1132 if num_failures == num_runs: # what about infinite_runs???
1133 jobset.message('FAILED', k, do_newline=True)
1134 elif num_failures > 0:
1135 jobset.message(
1136 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1137 do_newline=True)
1138 else:
1139 jobset.message('PASSED', k, do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001140 finally:
1141 for antagonist in antagonists:
1142 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001143 if xml_report and resultset:
Adele Zhou3bc7ba42015-11-05 10:21:58 -08001144 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillerd86a3942015-01-14 12:48:54 -08001145
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001146 number_failures, _ = jobset.run(
1147 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001148 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001149
1150 out = []
1151 if number_failures:
1152 out.append(BuildAndRunError.POST_TEST)
1153 if num_test_failures:
1154 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001155
Craig Tiller69cd2372015-06-11 09:38:09 -07001156 if cache: cache.save()
1157
Craig Tillereb9de8b2016-01-08 08:57:41 -08001158 return out
ctiller3040cb72015-01-07 12:13:17 -08001159
1160
David Klempner25739582015-02-11 15:57:32 -08001161test_cache = TestCache(runs_per_test == 1)
Craig Tiller547db2b2015-01-30 14:08:39 -08001162test_cache.maybe_load()
Craig Tiller71735182015-01-15 17:07:13 -08001163
ctiller3040cb72015-01-07 12:13:17 -08001164if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001165 success = True
ctiller3040cb72015-01-07 12:13:17 -08001166 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001167 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001168 initial_time = dw.most_recent_change()
1169 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001170 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001171 errors = _build_and_run(check_cancelled=have_files_changed,
1172 newline_on_success=False,
1173 cache=test_cache,
1174 build_only=args.build_only) == 0
1175 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001176 jobset.message('SUCCESS',
1177 'All tests are now passing properly',
1178 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001179 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001180 while not have_files_changed():
1181 time.sleep(1)
1182else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001183 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001184 newline_on_success=args.newline_on_success,
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001185 cache=test_cache,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001186 xml_report=args.xml_report,
1187 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001188 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001189 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1190 else:
1191 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001192 exit_code = 0
1193 if BuildAndRunError.BUILD in errors:
1194 exit_code |= 1
Craig Tiller4f2be362016-01-08 08:59:20 -08001195 if BuildAndRunError.TEST in errors and not args.travis:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001196 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001197 if BuildAndRunError.POST_TEST in errors:
1198 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001199 sys.exit(exit_code)
Craig Tillera0f85172016-01-20 15:56:06 -08001200