blob: 0b3efa29e3a0bc027b1fd4a0a3ce47bbdeb1dff9 [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,
murgatroid997d243df2016-02-18 09:58:05 -0800337 timeout_seconds=10*60,
Craig Tiller06805272015-06-11 14:46:47 -0700338 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800339
murgatroid99256d3df2015-09-21 16:58:02 -0700340 def pre_build_steps(self):
Nicolas "Pixel" Noblebcf988f2015-10-08 03:00:42 +0200341 return [['tools/run_tests/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700342
Craig Tiller883064c2015-11-04 10:06:10 -0800343 def make_targets(self, test_regex):
murgatroid997d243df2016-02-18 09:58:05 -0800344 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800345
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800346 def make_options(self):
347 return []
348
murgatroid996a4c4fa2015-02-27 12:08:57 -0800349 def build_steps(self):
350 return [['tools/run_tests/build_ruby.sh']]
351
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200352 def post_tests_steps(self):
Nicolas "Pixel" Noble7ef1e532015-12-02 00:55:33 +0100353 return [['tools/run_tests/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200354
murgatroid99a3e244f2015-09-22 11:25:53 -0700355 def makefile_name(self):
356 return 'Makefile'
357
murgatroid99132ce6a2015-03-04 17:29:14 -0800358 def supports_multi_config(self):
359 return False
360
Jan Tattermusch788ee232016-01-26 12:19:44 -0800361 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800362 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800363
murgatroid99132ce6a2015-03-04 17:29:14 -0800364 def __str__(self):
365 return 'ruby'
366
Craig Tillerd625d812015-04-08 15:52:35 -0700367
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800368class CSharpLanguage(object):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700369 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700370 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700371
Craig Tiller883064c2015-11-04 10:06:10 -0800372 def test_specs(self, config, args):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800373 with open('src/csharp/tests.json') as f:
374 tests_json = json.load(f)
375 assemblies = tests_json['assemblies']
376 tests = tests_json['tests']
377
378 msbuild_config = _WINDOWS_CONFIG[config.build_config]
379 assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
380 for a in assemblies]
381
382 extra_args = ['-labels'] + assembly_files
383
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700384 if self.platform == 'windows':
Jan Tattermusch03c01062015-12-11 14:28:56 -0800385 script_name = 'tools\\run_tests\\run_csharp.bat'
386 extra_args += ['-domain=None']
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700387 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800388 script_name = 'tools/run_tests/run_csharp.sh'
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700389
Jan Tattermuschbdf4b2e2015-10-28 08:22:34 -0700390 if config.build_config == 'gcov':
391 # On Windows, we only collect C# code coverage.
392 # On Linux, we only collect coverage for native extension.
393 # For code coverage all tests need to run as one suite.
Jan Tattermusch03c01062015-12-11 14:28:56 -0800394 return [config.job_spec([script_name] + extra_args, None,
395 shortname='csharp.coverage',
396 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jan Tattermusch61c3a832015-10-27 17:54:50 -0700397 else:
Jan Tattermusch03c01062015-12-11 14:28:56 -0800398 specs = []
399 for test in tests:
400 cmdline = [script_name, '-run=%s' % test] + extra_args
401 if self.platform == 'windows':
402 # use different output directory for each test to prevent
403 # TestResult.xml clash between parallel test runs.
404 cmdline += ['-work=test-result/%s' % uuid.uuid4()]
405 specs.append(config.job_spec(cmdline, None,
406 shortname='csharp.%s' % test,
407 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
408 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800409
murgatroid99256d3df2015-09-21 16:58:02 -0700410 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700411 if self.platform == 'windows':
Jan Tattermusch874aec02015-10-07 19:26:19 -0700412 return [['tools\\run_tests\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700413 else:
414 return [['tools/run_tests/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700415
Craig Tiller883064c2015-11-04 10:06:10 -0800416 def make_targets(self, test_regex):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700417 # For Windows, this target doesn't really build anything,
418 # everything is build by buildall script later.
Craig Tillerd5904822015-08-31 21:30:58 -0700419 if self.platform == 'windows':
420 return []
421 else:
422 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800423
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800424 def make_options(self):
425 if self.platform == 'mac':
426 # On Mac, official distribution of mono is 32bit.
427 return ['CFLAGS=-arch i386', 'LDFLAGS=-arch i386']
428 else:
429 return []
430
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800431 def build_steps(self):
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700432 if self.platform == 'windows':
433 return [['src\\csharp\\buildall.bat']]
434 else:
435 return [['tools/run_tests/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000436
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200437 def post_tests_steps(self):
438 return []
439
murgatroid99a3e244f2015-09-22 11:25:53 -0700440 def makefile_name(self):
441 return 'Makefile'
442
murgatroid99132ce6a2015-03-04 17:29:14 -0800443 def supports_multi_config(self):
444 return False
445
Jan Tattermusch788ee232016-01-26 12:19:44 -0800446 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800447 return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800448
murgatroid99132ce6a2015-03-04 17:29:14 -0800449 def __str__(self):
450 return 'csharp'
451
Craig Tillerd625d812015-04-08 15:52:35 -0700452
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700453class ObjCLanguage(object):
454
Craig Tiller883064c2015-11-04 10:06:10 -0800455 def test_specs(self, config, args):
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700456 return [config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
457 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
458
murgatroid99256d3df2015-09-21 16:58:02 -0700459 def pre_build_steps(self):
460 return []
461
Craig Tiller883064c2015-11-04 10:06:10 -0800462 def make_targets(self, test_regex):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700463 return ['grpc_objective_c_plugin', 'interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700464
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800465 def make_options(self):
466 return []
467
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700468 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700469 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700470
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200471 def post_tests_steps(self):
472 return []
473
murgatroid99a3e244f2015-09-22 11:25:53 -0700474 def makefile_name(self):
475 return 'Makefile'
476
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700477 def supports_multi_config(self):
478 return False
479
Jan Tattermusch788ee232016-01-26 12:19:44 -0800480 def dockerfile_dir(self, config, arch):
481 return None
482
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700483 def __str__(self):
484 return 'objc'
485
486
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100487class Sanity(object):
488
Craig Tiller883064c2015-11-04 10:06:10 -0800489 def test_specs(self, config, args):
Craig Tiller94d04a52016-01-20 10:58:23 -0800490 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800491 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
492 return [config.job_spec(cmd['script'].split(), None,
493 timeout_seconds=None, environ={'TEST': 'true'},
494 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800495 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100496
murgatroid99256d3df2015-09-21 16:58:02 -0700497 def pre_build_steps(self):
498 return []
499
Craig Tiller883064c2015-11-04 10:06:10 -0800500 def make_targets(self, test_regex):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100501 return ['run_dep_checks']
502
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800503 def make_options(self):
504 return []
505
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100506 def build_steps(self):
507 return []
508
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200509 def post_tests_steps(self):
510 return []
511
murgatroid99a3e244f2015-09-22 11:25:53 -0700512 def makefile_name(self):
513 return 'Makefile'
514
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100515 def supports_multi_config(self):
516 return False
517
Jan Tattermusch788ee232016-01-26 12:19:44 -0800518 def dockerfile_dir(self, config, arch):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800519 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800520
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100521 def __str__(self):
522 return 'sanity'
523
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200524
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100525class Build(object):
526
Craig Tiller883064c2015-11-04 10:06:10 -0800527 def test_specs(self, config, args):
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100528 return []
529
murgatroid99256d3df2015-09-21 16:58:02 -0700530 def pre_build_steps(self):
531 return []
532
Craig Tiller883064c2015-11-04 10:06:10 -0800533 def make_targets(self, test_regex):
Nicolas "Pixel" Noblec23827b2015-04-23 06:17:55 +0200534 return ['static']
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100535
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800536 def make_options(self):
537 return []
538
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100539 def build_steps(self):
540 return []
541
Nicolas "Pixel" Noblefe300452015-10-27 23:05:10 +0100542 def post_tests_steps(self):
543 return []
544
murgatroid99a3e244f2015-09-22 11:25:53 -0700545 def makefile_name(self):
546 return 'Makefile'
547
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100548 def supports_multi_config(self):
549 return True
550
Jan Tattermusch788ee232016-01-26 12:19:44 -0800551 def dockerfile_dir(self, config, arch):
552 return None
553
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100554 def __str__(self):
555 return self.make_target
556
557
Craig Tiller738c3342015-01-12 14:28:33 -0800558# different configurations we can run under
Craig Tillera0f85172016-01-20 15:56:06 -0800559with open('tools/run_tests/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800560 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800561
562
Nicolas "Pixel" Noble1fb5e822015-03-16 06:20:37 +0100563_DEFAULT = ['opt']
Craig Tillerc7449162015-01-16 14:42:10 -0800564_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800565 'c++': CLanguage('cxx', 'c++'),
566 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800567 'node': NodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000568 'php': PhpLanguage(),
569 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800570 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100571 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700572 'objc' : ObjCLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100573 'sanity': Sanity(),
Nicolas "Pixel" Noblefd2b0932015-03-26 00:26:29 +0100574 'build': Build(),
Craig Tillereb272bc2015-01-30 13:13:14 -0800575 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800576
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700577_WINDOWS_CONFIG = {
578 'dbg': 'Debug',
579 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800580 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700581 }
582
David Garcia Quintase90cd372015-05-31 18:15:26 -0700583
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800584def _windows_arch_option(arch):
585 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800586 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800587 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800588 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800589 return '/p:Platform=x64'
590 else:
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800591 print 'Architecture %s not supported.' % arch
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800592 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800593
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800594
595def _check_arch_option(arch):
596 """Checks that architecture option is valid."""
597 if platform_string() == 'windows':
598 _windows_arch_option(arch)
599 elif platform_string() == 'linux':
600 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800601 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800602 if arch == 'default':
603 return
604 elif runtime_arch == '64bit' and arch == 'x64':
605 return
606 elif runtime_arch == '32bit' and arch == 'x86':
607 return
608 else:
609 print 'Architecture %s does not match current runtime architecture.' % arch
610 sys.exit(1)
611 else:
612 if args.arch != 'default':
613 print 'Architecture %s not supported on current platform.' % args.arch
614 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800615
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800616
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800617def _windows_build_bat(compiler):
618 """Returns name of build.bat for selected compiler."""
619 if compiler == 'default' or compiler == 'vs2013':
620 return 'vsprojects\\build_vs2013.bat'
621 elif compiler == 'vs2015':
622 return 'vsprojects\\build_vs2015.bat'
623 elif compiler == 'vs2010':
624 return 'vsprojects\\build_vs2010.bat'
625 else:
626 print 'Compiler %s not supported.' % compiler
627 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800628
629
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800630def _windows_toolset_option(compiler):
631 """Returns msbuild PlatformToolset for selected compiler."""
632 if compiler == 'default' or compiler == 'vs2013':
633 return '/p:PlatformToolset=v120'
634 elif compiler == 'vs2015':
635 return '/p:PlatformToolset=v140'
636 elif compiler == 'vs2010':
637 return '/p:PlatformToolset=v100'
638 else:
639 print 'Compiler %s not supported.' % compiler
640 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800641
642
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800643def _docker_arch_suffix(arch):
644 """Returns suffix to dockerfile dir to use."""
645 if arch == 'default' or arch == 'x64':
646 return 'x64'
647 elif arch == 'x86':
648 return 'x86'
649 else:
650 print 'Architecture %s not supported with current settings.' % arch
651 sys.exit(1)
652
653
Jan Tattermusch788ee232016-01-26 12:19:44 -0800654def _get_dockerfile_dir(language, cfg, arch):
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800655 """Returns dockerfile to use"""
Jan Tattermusch788ee232016-01-26 12:19:44 -0800656 custom = language.dockerfile_dir(cfg, arch)
657 if custom:
658 return custom
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800659 else:
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800660 return 'tools/dockerfile/grpc_tests_multilang_%s' % _docker_arch_suffix(arch)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800661
David Garcia Quintase90cd372015-05-31 18:15:26 -0700662def runs_per_test_type(arg_str):
663 """Auxilary function to parse the "runs_per_test" flag.
664
665 Returns:
666 A positive integer or 0, the latter indicating an infinite number of
667 runs.
668
669 Raises:
670 argparse.ArgumentTypeError: Upon invalid input.
671 """
672 if arg_str == 'inf':
673 return 0
674 try:
675 n = int(arg_str)
676 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -0700677 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -0700678 except:
Adele Zhoue4c35612015-10-16 15:34:23 -0700679 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700680 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700681
682# parse command line
683argp = argparse.ArgumentParser(description='Run grpc tests.')
684argp.add_argument('-c', '--config',
685 choices=['all'] + sorted(_CONFIGS.keys()),
686 nargs='+',
687 default=_DEFAULT)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700688argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
689 help='A positive integer or "inf". If "inf", all tests will run in an '
690 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -0800691argp.add_argument('-r', '--regex', default='.*', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -0800692argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -0800693argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -0800694argp.add_argument('-f', '--forever',
695 default=False,
696 action='store_const',
697 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +0100698argp.add_argument('-t', '--travis',
699 default=False,
700 action='store_const',
701 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -0800702argp.add_argument('--newline_on_success',
703 default=False,
704 action='store_const',
705 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -0800706argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -0700707 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -0800708 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -0700709 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -0700710argp.add_argument('-S', '--stop_on_failure',
711 default=False,
712 action='store_const',
713 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700714argp.add_argument('--use_docker',
715 default=False,
716 action='store_const',
717 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700718 help='Run all the tests under docker. That provides ' +
719 'additional isolation and prevents the need to install ' +
720 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -0700721argp.add_argument('--allow_flakes',
722 default=False,
723 action='store_const',
724 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700725 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800726argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800727 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800728 default='default',
729 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
730argp.add_argument('--compiler',
731 choices=['default', 'vs2010', 'vs2013', 'vs2015'],
732 default='default',
733 help='Selects compiler to use. For some platforms "default" is the only supported choice.')
734argp.add_argument('--build_only',
735 default=False,
736 action='store_const',
737 const=True,
738 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -0800739argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
740 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -0800741argp.add_argument('--update_submodules', default=[], nargs='*',
742 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
743 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -0700744argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +0200745argp.add_argument('-x', '--xml_report', default=None, type=str,
746 help='Generates a JUnit-compatible XML report')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800747args = argp.parse_args()
748
Craig Tiller5f735a62016-01-20 09:31:15 -0800749jobset.measure_cpu_costs = args.measure_cpu_costs
750
Craig Tiller1676f912016-01-05 10:49:44 -0800751# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -0800752need_to_regenerate_projects = False
753for spec in args.update_submodules:
754 spec = spec.split(':', 1)
755 if len(spec) == 1:
756 submodule = spec[0]
757 branch = 'master'
758 elif len(spec) == 2:
759 submodule = spec[0]
760 branch = spec[1]
761 cwd = 'third_party/%s' % submodule
762 def git(cmd, cwd=cwd):
763 print 'in %s: git %s' % (cwd, cmd)
764 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
765 git('fetch')
766 git('checkout %s' % branch)
767 git('pull origin %s' % branch)
768 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
769 need_to_regenerate_projects = True
770if need_to_regenerate_projects:
771 if jobset.platform_string() == 'linux':
772 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
773 else:
774 print 'WARNING: may need to regenerate projects, but since we are not on'
775 print ' Linux this step is being skipped. Compilation MAY fail.'
Craig Tiller1676f912016-01-05 10:49:44 -0800776
777
Nicolas Nobleddef2462015-01-06 18:08:25 -0800778# grab config
Craig Tiller738c3342015-01-12 14:28:33 -0800779run_configs = set(_CONFIGS[cfg]
780 for cfg in itertools.chain.from_iterable(
781 _CONFIGS.iterkeys() if x == 'all' else [x]
782 for x in args.config))
783build_configs = set(cfg.build_config for cfg in run_configs)
Craig Tillerf1973b02015-01-16 12:32:13 -0800784
Craig Tiller06805272015-06-11 14:46:47 -0700785if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -0700786 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -0700787
Adele Zhou6b9527c2015-11-20 15:56:35 -0800788if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -0800789 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -0800790else:
791 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -0800792# We don't support code coverage on some languages
793if 'gcov' in args.config:
794 for bad in ['objc', 'sanity', 'build']:
795 if bad in lang_list:
796 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -0800797
798languages = set(_LANGUAGES[l] for l in lang_list)
murgatroid99132ce6a2015-03-04 17:29:14 -0800799
800if len(build_configs) > 1:
801 for language in languages:
802 if not language.supports_multi_config():
803 print language, 'does not support multiple build configurations'
804 sys.exit(1)
805
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800806language_make_options=[]
807if any(language.make_options() for language in languages):
808 if len(languages) != 1:
809 print 'languages with custom make options cannot be built simultaneously with other languages'
810 sys.exit(1)
811 else:
812 language_make_options = next(iter(languages)).make_options()
813
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800814if len(languages) != 1 or len(build_configs) != 1:
815 print 'Multi-language and multi-config testing is not supported.'
816 sys.exit(1)
817
818if args.use_docker:
819 if not args.travis:
820 print 'Seen --use_docker flag, will run tests under docker.'
821 print
822 print 'IMPORTANT: The changes you are testing need to be locally committed'
823 print 'because only the committed changes in the current branch will be'
824 print 'copied to the docker environment.'
825 time.sleep(5)
826
827 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -0800828 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800829
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800830 env = os.environ.copy()
831 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch788ee232016-01-26 12:19:44 -0800832 env['DOCKERFILE_DIR'] = _get_dockerfile_dir(next(iter(languages)),
833 next(iter(build_configs)),
834 args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800835 env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh'
836 if args.xml_report:
837 env['XML_REPORT'] = args.xml_report
838 if not args.travis:
839 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
840
841 subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'],
842 shell=True,
843 env=env)
844 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800845
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800846if platform_string() != 'windows' and args.compiler != 'default':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800847 print 'Compiler %s not supported on current platform.' % args.compiler
848 sys.exit(1)
849
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800850_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800851
Jan Tattermuschfba65302016-01-25 18:21:14 -0800852def make_jobspec(cfg, targets, makefile='Makefile'):
853 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -0700854 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -0700855 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -0700856 # empirically /m:2 gives the best performance/price and should prevent
857 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -0700858 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -0700859 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -0700860 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -0700861 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800862 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -0700863 'vsprojects\\%s.sln' % target,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800864 '/p:Configuration=%s' % _WINDOWS_CONFIG[cfg],
865 _windows_toolset_option(args.compiler),
866 _windows_arch_option(args.arch)] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800867 extra_args +
868 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -0800869 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -0700870 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -0800871 else:
murgatroid998ae409f2015-10-26 16:39:00 -0700872 if targets:
873 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
874 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -0800875 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -0800876 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
877 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800878 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -0800879 ([] if not args.travis else ['JENKINS_BUILD=1']) +
880 targets,
Craig Tiller590105a2016-01-19 13:03:46 -0800881 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -0700882 else:
883 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -0800884
murgatroid99a3e244f2015-09-22 11:25:53 -0700885make_targets = {}
886for l in languages:
887 makefile = l.makefile_name()
888 make_targets[makefile] = make_targets.get(makefile, set()).union(
Craig Tiller883064c2015-11-04 10:06:10 -0800889 set(l.make_targets(args.regex)))
Craig Tiller5058c692015-04-08 09:42:04 -0700890
Jan Tattermusche4a69182015-12-15 09:53:01 -0800891def build_step_environ(cfg):
892 environ = {'CONFIG': cfg}
Jan Tattermusch68016a12015-12-16 15:31:33 -0800893 msbuild_cfg = _WINDOWS_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -0800894 if msbuild_cfg:
895 environ['MSBUILD_CONFIG'] = msbuild_cfg
896 return environ
897
murgatroid99fddac962015-09-22 09:20:11 -0700898build_steps = list(set(
Jan Tattermusche4a69182015-12-15 09:53:01 -0800899 jobset.JobSpec(cmdline, environ=build_step_environ(cfg), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -0700900 for cfg in build_configs
901 for l in languages
902 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -0700903if make_targets:
murgatroid99a3e244f2015-09-22 11:25:53 -0700904 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 -0700905 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -0700906build_steps.extend(set(
Craig Tiller590105a2016-01-19 13:03:46 -0800907 jobset.JobSpec(cmdline, environ=build_step_environ(cfg), timeout_seconds=None)
murgatroid99132ce6a2015-03-04 17:29:14 -0800908 for cfg in build_configs
Craig Tiller547db2b2015-01-30 14:08:39 -0800909 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -0700910 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -0800911
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200912post_tests_steps = list(set(
Jan Tattermusche4a69182015-12-15 09:53:01 -0800913 jobset.JobSpec(cmdline, environ=build_step_environ(cfg))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200914 for cfg in build_configs
915 for l in languages
916 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -0800917runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -0800918forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -0800919
Nicolas Nobleddef2462015-01-06 18:08:25 -0800920
Craig Tiller71735182015-01-15 17:07:13 -0800921class TestCache(object):
Craig Tillerb50d1662015-01-15 17:28:21 -0800922 """Cache for running tests."""
923
David Klempner25739582015-02-11 15:57:32 -0800924 def __init__(self, use_cache_results):
Craig Tiller71735182015-01-15 17:07:13 -0800925 self._last_successful_run = {}
David Klempner25739582015-02-11 15:57:32 -0800926 self._use_cache_results = use_cache_results
Craig Tiller69cd2372015-06-11 09:38:09 -0700927 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800928
929 def should_run(self, cmdline, bin_hash):
Craig Tiller71735182015-01-15 17:07:13 -0800930 if cmdline not in self._last_successful_run:
931 return True
932 if self._last_successful_run[cmdline] != bin_hash:
933 return True
David Klempner25739582015-02-11 15:57:32 -0800934 if not self._use_cache_results:
935 return True
Craig Tiller71735182015-01-15 17:07:13 -0800936 return False
937
938 def finished(self, cmdline, bin_hash):
Craig Tiller547db2b2015-01-30 14:08:39 -0800939 self._last_successful_run[cmdline] = bin_hash
Craig Tiller69cd2372015-06-11 09:38:09 -0700940 if time.time() - self._last_save > 1:
941 self.save()
Craig Tiller71735182015-01-15 17:07:13 -0800942
943 def dump(self):
Craig Tillerb50d1662015-01-15 17:28:21 -0800944 return [{'cmdline': k, 'hash': v}
945 for k, v in self._last_successful_run.iteritems()]
Craig Tiller71735182015-01-15 17:07:13 -0800946
947 def parse(self, exdump):
948 self._last_successful_run = dict((o['cmdline'], o['hash']) for o in exdump)
949
950 def save(self):
951 with open('.run_tests_cache', 'w') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800952 f.write(json.dumps(self.dump()))
Craig Tiller69cd2372015-06-11 09:38:09 -0700953 self._last_save = time.time()
Craig Tiller71735182015-01-15 17:07:13 -0800954
Craig Tiller1cc11db2015-01-15 22:50:50 -0800955 def maybe_load(self):
956 if os.path.exists('.run_tests_cache'):
957 with open('.run_tests_cache') as f:
Craig Tiller261dd982015-01-16 16:41:45 -0800958 self.parse(json.loads(f.read()))
Craig Tiller71735182015-01-15 17:07:13 -0800959
960
Craig Tillerf53d9c82015-08-04 14:19:43 -0700961def _start_port_server(port_server_port):
962 # check if a compatible port server is running
963 # if incompatible (version mismatch) ==> start a new one
964 # if not running ==> start a new one
965 # otherwise, leave it up
966 try:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700967 version = int(urllib2.urlopen(
968 'http://localhost:%d/version_number' % port_server_port,
969 timeout=1).read())
970 print 'detected port server running version %d' % version
Craig Tillerf53d9c82015-08-04 14:19:43 -0700971 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -0700972 except Exception as e:
Craig Tiller0d6499e2015-10-05 14:00:47 -0700973 print 'failed to detect port server: %s' % sys.exc_info()[0]
Craig Tillerfe4939f2015-10-06 12:55:36 -0700974 print e.strerror
Craig Tillerf53d9c82015-08-04 14:19:43 -0700975 running = False
976 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -0700977 current_version = int(subprocess.check_output(
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800978 [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
979 'dump_version']))
Craig Tillerfe4939f2015-10-06 12:55:36 -0700980 print 'my port server is version %d' % current_version
981 running = (version >= current_version)
982 if not running:
983 print 'port_server version mismatch: killing the old one'
984 urllib2.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
985 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -0700986 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -0700987 fd, logfile = tempfile.mkstemp()
988 os.close(fd)
989 print 'starting port_server, with log file %s' % logfile
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800990 args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
991 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -0700992 env = dict(os.environ)
993 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +0100994 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -0800995 # Working directory of port server needs to be outside of Jenkins
996 # workspace to prevent file lock issues.
997 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -0700998 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -0700999 args,
1000 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001001 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -07001002 creationflags = 0x00000008, # detached process
1003 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -07001004 else:
1005 port_server = subprocess.Popen(
1006 args,
Craig Tiller367d41d2015-10-12 13:00:22 -07001007 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -07001008 preexec_fn=os.setsid,
1009 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001010 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001011 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001012 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001013 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001014 if waits > 10:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001015 print 'killing port server due to excessive start up waits'
Craig Tillerabd37fd2015-08-26 07:54:01 -07001016 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001017 if port_server.poll() is not None:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001018 print 'port_server failed to start'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001019 # try one final time: maybe another build managed to start one
1020 time.sleep(1)
1021 try:
1022 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1023 timeout=1).read()
1024 print 'last ditch attempt to contact port server succeeded'
1025 break
1026 except:
1027 traceback.print_exc();
1028 port_log = open(logfile, 'r').read()
1029 print port_log
1030 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001031 try:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001032 urllib2.urlopen('http://localhost:%d/get' % port_server_port,
1033 timeout=1).read()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001034 print 'port server is up and ready'
Craig Tillerf53d9c82015-08-04 14:19:43 -07001035 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001036 except socket.timeout:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001037 print 'waiting for port_server: timeout'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001038 traceback.print_exc();
1039 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001040 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001041 except urllib2.URLError:
Craig Tiller0d6499e2015-10-05 14:00:47 -07001042 print 'waiting for port_server: urlerror'
Craig Tillerf0a293e2015-10-12 10:05:50 -07001043 traceback.print_exc();
1044 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001045 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001046 except:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001047 traceback.print_exc();
Craig Tillerf53d9c82015-08-04 14:19:43 -07001048 port_server.kill()
1049 raise
1050
1051
Adele Zhoud5fffa52015-10-23 15:51:42 -07001052def _calculate_num_runs_failures(list_of_results):
1053 """Caculate number of runs and failures for a particular test.
1054
1055 Args:
1056 list_of_results: (List) of JobResult object.
1057 Returns:
1058 A tuple of total number of runs and failures.
1059 """
1060 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1061 num_failures = 0
1062 for jobresult in list_of_results:
1063 if jobresult.retries > 0:
1064 num_runs += jobresult.retries
1065 if jobresult.num_failures > 0:
1066 num_failures += jobresult.num_failures
1067 return num_runs, num_failures
1068
Adele Zhou6b9527c2015-11-20 15:56:35 -08001069
Craig Tillereb9de8b2016-01-08 08:57:41 -08001070# _build_and_run results
1071class BuildAndRunError(object):
1072
1073 BUILD = object()
1074 TEST = object()
1075 POST_TEST = object()
1076
1077
1078# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001079def _build_and_run(
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001080 check_cancelled, newline_on_success, cache, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001081 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001082 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001083 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001084 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001085 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001086 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001087 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001088
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001089 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001090 if xml_report:
1091 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001092 return []
ctiller3040cb72015-01-07 12:13:17 -08001093
Craig Tiller234b6e72015-05-23 10:12:40 -07001094 # start antagonists
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001095 antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001096 for _ in range(0, args.antagonists)]
Craig Tillerfe4939f2015-10-06 12:55:36 -07001097 port_server_port = 32767
Craig Tillerf53d9c82015-08-04 14:19:43 -07001098 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001099 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001100 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001101 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001102 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001103 one_run = set(
1104 spec
1105 for config in run_configs
1106 for language in languages
Craig Tiller883064c2015-11-04 10:06:10 -08001107 for spec in language.test_specs(config, args)
yang-g6c1fdc62015-08-18 11:57:42 -07001108 if re.search(args.regex, spec.shortname))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001109 # When running on travis, we want out test runs to be as similar as possible
1110 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001111 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001112 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1113 else:
1114 # whereas otherwise, we want to shuffle things up to give all tests a
1115 # chance to run.
1116 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1117 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001118 if infinite_runs:
1119 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 -07001120 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1121 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001122 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001123
Adele Zhou803af152015-11-30 15:16:16 -08001124 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001125 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001126 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001127 stop_on_failure=args.stop_on_failure,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001128 cache=cache if not xml_report else None,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001129 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
Adele Zhoud5fffa52015-10-23 15:51:42 -07001130 if resultset:
1131 for k, v in resultset.iteritems():
1132 num_runs, num_failures = _calculate_num_runs_failures(v)
1133 if num_failures == num_runs: # what about infinite_runs???
1134 jobset.message('FAILED', k, do_newline=True)
1135 elif num_failures > 0:
1136 jobset.message(
1137 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1138 do_newline=True)
1139 else:
1140 jobset.message('PASSED', k, do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001141 finally:
1142 for antagonist in antagonists:
1143 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001144 if xml_report and resultset:
Adele Zhou3bc7ba42015-11-05 10:21:58 -08001145 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillerd86a3942015-01-14 12:48:54 -08001146
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001147 number_failures, _ = jobset.run(
1148 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001149 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001150
1151 out = []
1152 if number_failures:
1153 out.append(BuildAndRunError.POST_TEST)
1154 if num_test_failures:
1155 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001156
Craig Tiller69cd2372015-06-11 09:38:09 -07001157 if cache: cache.save()
1158
Craig Tillereb9de8b2016-01-08 08:57:41 -08001159 return out
ctiller3040cb72015-01-07 12:13:17 -08001160
1161
David Klempner25739582015-02-11 15:57:32 -08001162test_cache = TestCache(runs_per_test == 1)
Craig Tiller547db2b2015-01-30 14:08:39 -08001163test_cache.maybe_load()
Craig Tiller71735182015-01-15 17:07:13 -08001164
ctiller3040cb72015-01-07 12:13:17 -08001165if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001166 success = True
ctiller3040cb72015-01-07 12:13:17 -08001167 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001168 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001169 initial_time = dw.most_recent_change()
1170 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001171 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001172 errors = _build_and_run(check_cancelled=have_files_changed,
1173 newline_on_success=False,
1174 cache=test_cache,
1175 build_only=args.build_only) == 0
1176 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001177 jobset.message('SUCCESS',
1178 'All tests are now passing properly',
1179 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001180 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001181 while not have_files_changed():
1182 time.sleep(1)
1183else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001184 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001185 newline_on_success=args.newline_on_success,
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001186 cache=test_cache,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001187 xml_report=args.xml_report,
1188 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001189 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001190 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1191 else:
1192 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001193 exit_code = 0
1194 if BuildAndRunError.BUILD in errors:
1195 exit_code |= 1
Craig Tiller4f2be362016-01-08 08:59:20 -08001196 if BuildAndRunError.TEST in errors and not args.travis:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001197 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001198 if BuildAndRunError.POST_TEST in errors:
1199 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001200 sys.exit(exit_code)