blob: 18674b7a559e17a6469ddb57763f4d60afec0fc7 [file] [log] [blame]
Nathaniel Manistaae4fbcd2015-09-23 16:29:44 +00001#!/usr/bin/env python2.7
Craig Tiller6169d5f2016-03-31 07:46:18 -07002# Copyright 2015, 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
siddharthshukla0589e532016-07-07 16:08:01 +020033from __future__ import print_function
34
Nicolas Nobleddef2462015-01-06 18:08:25 -080035import argparse
Craig Tiller9279ac22016-01-20 17:05:23 -080036import ast
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070037import collections
Nicolas Nobleddef2462015-01-06 18:08:25 -080038import glob
39import itertools
Craig Tiller261dd982015-01-16 16:41:45 -080040import json
Nicolas Nobleddef2462015-01-06 18:08:25 -080041import multiprocessing
Craig Tiller1cc11db2015-01-15 22:50:50 -080042import os
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -070043import os.path
David Garcia Quintas79e389f2015-06-02 17:49:42 -070044import platform
45import random
Craig Tillerfe406ec2015-02-24 13:55:12 -080046import re
Craig Tiller82875232015-09-25 13:57:34 -070047import socket
David Garcia Quintas79e389f2015-06-02 17:49:42 -070048import subprocess
Nicolas Nobleddef2462015-01-06 18:08:25 -080049import sys
Craig Tillerf0a293e2015-10-12 10:05:50 -070050import tempfile
51import traceback
ctiller3040cb72015-01-07 12:13:17 -080052import time
siddharthshukla0589e532016-07-07 16:08:01 +020053from six.moves import urllib
Jan Tattermusch03c01062015-12-11 14:28:56 -080054import uuid
Nicolas Nobleddef2462015-01-06 18:08:25 -080055
56import jobset
Adele Zhoua30f8292015-11-02 13:15:46 -080057import report_utils
ctiller3040cb72015-01-07 12:13:17 -080058import watch_dirs
Nicolas Nobleddef2462015-01-06 18:08:25 -080059
Craig Tillerb361b4e2016-01-06 11:44:17 -080060
Jan Tattermusch3b5121b2016-02-22 17:41:05 -080061_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
62os.chdir(_ROOT)
Craig Tiller2cc2b842015-02-27 11:38:31 -080063
64
Craig Tiller06805272015-06-11 14:46:47 -070065_FORCE_ENVIRON_FOR_WRAPPERS = {}
66
67
Craig Tiller123f1372016-06-15 15:06:14 -070068_POLLING_STRATEGIES = {
Sree Kuchibhotlac3a9fae2016-06-21 16:31:08 -070069 'linux': ['epoll', 'poll', 'legacy']
Craig Tiller123f1372016-06-15 15:06:14 -070070}
71
72
Craig Tillerd50993d2015-08-05 08:04:36 -070073def platform_string():
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +010074 return jobset.platform_string()
Craig Tillerd50993d2015-08-05 08:04:36 -070075
76
Craig Tiller738c3342015-01-12 14:28:33 -080077# SimpleConfig: just compile with CONFIG=config, and run the binary to test
Craig Tillera0f85172016-01-20 15:56:06 -080078class Config(object):
Craig Tillerb50d1662015-01-15 17:28:21 -080079
Craig Tillera0f85172016-01-20 15:56:06 -080080 def __init__(self, config, environ=None, timeout_multiplier=1, tool_prefix=[]):
murgatroid99132ce6a2015-03-04 17:29:14 -080081 if environ is None:
82 environ = {}
Craig Tiller738c3342015-01-12 14:28:33 -080083 self.build_config = config
Craig Tiller547db2b2015-01-30 14:08:39 -080084 self.environ = environ
murgatroid99132ce6a2015-03-04 17:29:14 -080085 self.environ['CONFIG'] = config
Craig Tillera0f85172016-01-20 15:56:06 -080086 self.tool_prefix = tool_prefix
Masood Malekghassemi26ea9e22015-10-09 15:19:17 -070087 self.timeout_multiplier = timeout_multiplier
Craig Tiller738c3342015-01-12 14:28:33 -080088
Craig Tiller74189cd2016-06-23 15:39:06 -070089 def job_spec(self, cmdline, timeout_seconds=5*60,
Craig Tillerde7edf82016-03-20 09:12:16 -070090 shortname=None, environ={}, cpu_cost=1.0, flaky=False):
Craig Tiller49f61322015-03-03 13:02:11 -080091 """Construct a jobset.JobSpec for a test under this config
92
93 Args:
94 cmdline: a list of strings specifying the command line the test
95 would like to run
Craig Tiller49f61322015-03-03 13:02:11 -080096 """
Craig Tiller4fc90032015-05-21 10:39:52 -070097 actual_environ = self.environ.copy()
siddharthshukla0589e532016-07-07 16:08:01 +020098 for k, v in environ.items():
Craig Tiller4fc90032015-05-21 10:39:52 -070099 actual_environ[k] = v
Craig Tillera0f85172016-01-20 15:56:06 -0800100 return jobset.JobSpec(cmdline=self.tool_prefix + cmdline,
Jan Tattermusch9a7d30c2015-04-23 16:12:55 -0700101 shortname=shortname,
Craig Tiller4fc90032015-05-21 10:39:52 -0700102 environ=actual_environ,
Craig Tiller56c6b6a2016-01-20 08:27:37 -0800103 cpu_cost=cpu_cost,
Craig Tiller94d04a52016-01-20 10:58:23 -0800104 timeout_seconds=(self.timeout_multiplier * timeout_seconds if timeout_seconds else None),
Craig Tillerde7edf82016-03-20 09:12:16 -0700105 flake_retries=5 if flaky or args.allow_flakes else 0,
Craig Tiller35505de2015-10-08 13:31:33 -0700106 timeout_retries=3 if args.allow_flakes else 0)
Craig Tiller738c3342015-01-12 14:28:33 -0800107
108
murgatroid99cf08daf2015-09-21 15:33:16 -0700109def get_c_tests(travis, test_lang) :
110 out = []
111 platforms_str = 'ci_platforms' if travis else 'platforms'
112 with open('tools/run_tests/tests.json') as f:
murgatroid9989899b12015-09-22 09:14:48 -0700113 js = json.load(f)
murgatroid99a3e244f2015-09-22 11:25:53 -0700114 return [tgt
115 for tgt in js
116 if tgt['language'] == test_lang and
117 platform_string() in tgt[platforms_str] and
118 not (travis and tgt['flaky'])]
murgatroid99cf08daf2015-09-21 15:33:16 -0700119
murgatroid99fafeeb32015-09-22 09:13:03 -0700120
Jan Tattermusch77db4322016-02-20 20:19:35 -0800121def _check_compiler(compiler, supported_compilers):
122 if compiler not in supported_compilers:
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700123 raise Exception('Compiler %s not supported (on this platform).' % compiler)
124
125
126def _check_arch(arch, supported_archs):
127 if arch not in supported_archs:
128 raise Exception('Architecture %s not supported.' % arch)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800129
130
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800131def _is_use_docker_child():
132 """Returns True if running running as a --use_docker child."""
133 return True if os.getenv('RUN_TESTS_COMMAND') else False
134
135
Craig Tillerc7449162015-01-16 14:42:10 -0800136class CLanguage(object):
137
Craig Tillere9c959d2015-01-18 10:23:26 -0800138 def __init__(self, make_target, test_lang):
Craig Tillerc7449162015-01-16 14:42:10 -0800139 self.make_target = make_target
Craig Tillerd50993d2015-08-05 08:04:36 -0700140 self.platform = platform_string()
Craig Tiller711bbe62015-08-19 12:35:16 -0700141 self.test_lang = test_lang
Craig Tillerc7449162015-01-16 14:42:10 -0800142
Jan Tattermusch77db4322016-02-20 20:19:35 -0800143 def configure(self, config, args):
144 self.config = config
145 self.args = args
146 if self.platform == 'windows':
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800147 self._make_options = [_windows_toolset_option(self.args.compiler),
148 _windows_arch_option(self.args.arch)]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800149 else:
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800150 self._docker_distro, self._make_options = self._compiler_options(self.args.use_docker,
151 self.args.compiler)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800152
153 def test_specs(self):
Craig Tiller547db2b2015-01-30 14:08:39 -0800154 out = []
Jan Tattermusch77db4322016-02-20 20:19:35 -0800155 binaries = get_c_tests(self.args.travis, self.test_lang)
Craig Tiller946ce7a2016-04-06 10:35:58 -0700156 for target in binaries:
Craig Tiller123f1372016-06-15 15:06:14 -0700157 polling_strategies = (_POLLING_STRATEGIES.get(self.platform, ['all'])
Craig Tiller946ce7a2016-04-06 10:35:58 -0700158 if target.get('uses_polling', True)
159 else ['all'])
160 for polling_strategy in polling_strategies:
161 env={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
162 _ROOT + '/src/core/lib/tsi/test_creds/ca.pem',
Craig Tillered735102016-04-06 12:59:23 -0700163 'GRPC_POLL_STRATEGY': polling_strategy}
Craig Tiller946ce7a2016-04-06 10:35:58 -0700164 shortname_ext = '' if polling_strategy=='all' else ' polling=%s' % polling_strategy
Craig Tillerb38197e2016-02-26 10:14:54 -0800165 if self.config.build_config in target['exclude_configs']:
166 continue
167 if self.platform == 'windows':
168 binary = 'vsprojects/%s%s/%s.exe' % (
169 'x64/' if self.args.arch == 'x64' else '',
170 _MSBUILD_CONFIG[self.config.build_config],
171 target['name'])
Craig Tillerca62ff02016-02-24 22:22:57 -0800172 else:
Craig Tillerb38197e2016-02-26 10:14:54 -0800173 binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
174 if os.path.isfile(binary):
175 if 'gtest' in target and target['gtest']:
176 # here we parse the output of --gtest_list_tests to build up a
177 # complete list of the tests contained in a binary
178 # for each test, we then add a job to run, filtering for just that
179 # test
180 with open(os.devnull, 'w') as fnull:
181 tests = subprocess.check_output([binary, '--gtest_list_tests'],
182 stderr=fnull)
183 base = None
184 for line in tests.split('\n'):
185 i = line.find('#')
186 if i >= 0: line = line[:i]
187 if not line: continue
188 if line[0] != ' ':
189 base = line.strip()
190 else:
191 assert base is not None
192 assert line[1] == ' '
193 test = base + line.strip()
194 cmdline = [binary] + ['--gtest_filter=%s' % test]
195 out.append(self.config.job_spec(cmdline, [binary],
Craig Tiller334db352016-02-26 15:19:49 -0800196 shortname='%s:%s %s' % (binary, test, shortname_ext),
Craig Tillerb38197e2016-02-26 10:14:54 -0800197 cpu_cost=target['cpu_cost'],
198 environ=env))
199 else:
200 cmdline = [binary] + target['args']
201 out.append(self.config.job_spec(cmdline, [binary],
202 shortname=' '.join(cmdline) + shortname_ext,
203 cpu_cost=target['cpu_cost'],
Craig Tillerc2278152016-03-21 08:59:54 -0700204 flaky=target.get('flaky', False),
Craig Tillerb38197e2016-02-26 10:14:54 -0800205 environ=env))
206 elif self.args.regex == '.*' or self.platform == 'windows':
siddharthshukla0589e532016-07-07 16:08:01 +0200207 print('\nWARNING: binary not found, skipping', binary)
Nicolas Noblee1445362015-05-11 17:40:26 -0700208 return sorted(out)
Craig Tillerc7449162015-01-16 14:42:10 -0800209
Jan Tattermusch77db4322016-02-20 20:19:35 -0800210 def make_targets(self):
211 test_regex = self.args.regex
212 if self.platform != 'windows' and self.args.regex != '.*':
Craig Tiller883064c2015-11-04 10:06:10 -0800213 # use the regex to minimize the number of things to build
Craig Tillerb0f275e2016-01-27 10:45:50 -0800214 return [os.path.basename(target['name'])
Craig Tiller883064c2015-11-04 10:06:10 -0800215 for target in get_c_tests(False, self.test_lang)
Craig Tillerb0f275e2016-01-27 10:45:50 -0800216 if re.search(test_regex, '/' + target['name'])]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800217 if self.platform == 'windows':
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700218 # don't build tools on windows just yet
219 return ['buildtests_%s' % self.make_target]
Craig Tiller7552f0f2015-06-19 17:46:20 -0700220 return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
Craig Tillerc7449162015-01-16 14:42:10 -0800221
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800222 def make_options(self):
Jan Tattermuschc96caf82016-02-22 17:31:02 -0800223 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800224
murgatroid99256d3df2015-09-21 16:58:02 -0700225 def pre_build_steps(self):
Jan Tattermusch874aec02015-10-07 19:26:19 -0700226 if self.platform == 'windows':
227 return [['tools\\run_tests\\pre_build_c.bat']]
228 else:
229 return []
murgatroid99256d3df2015-09-21 16:58:02 -0700230
Craig Tillerc7449162015-01-16 14:42:10 -0800231 def build_steps(self):
232 return []
233
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200234 def post_tests_steps(self):
235 if self.platform == 'windows':
236 return []
237 else:
238 return [['tools/run_tests/post_tests_c.sh']]
239
murgatroid99a3e244f2015-09-22 11:25:53 -0700240 def makefile_name(self):
241 return 'Makefile'
242
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700243 def _clang_make_options(self, version_suffix=''):
244 return ['CC=clang%s' % version_suffix,
245 'CXX=clang++%s' % version_suffix,
246 'LD=clang%s' % version_suffix,
247 'LDXX=clang++%s' % version_suffix]
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800248
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700249 def _gcc_make_options(self, version_suffix):
250 return ['CC=gcc%s' % version_suffix,
251 'CXX=g++%s' % version_suffix,
252 'LD=gcc%s' % version_suffix,
253 'LDXX=g++%s' % version_suffix]
Jan Tattermusch9bb70622016-03-18 10:28:54 -0700254
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800255 def _compiler_options(self, use_docker, compiler):
256 """Returns docker distro and make options to use for given compiler."""
Jan Tattermuschfd3857b2016-06-03 12:24:03 -0700257 if not use_docker and not _is_use_docker_child():
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800258 _check_compiler(compiler, ['default'])
259
260 if compiler == 'gcc4.9' or compiler == 'default':
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800261 return ('jessie', [])
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800262 elif compiler == 'gcc4.4':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700263 return ('wheezy', self._gcc_make_options(version_suffix='-4.4'))
264 elif compiler == 'gcc4.6':
265 return ('wheezy', self._gcc_make_options(version_suffix='-4.6'))
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800266 elif compiler == 'gcc5.3':
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800267 return ('ubuntu1604', [])
268 elif compiler == 'clang3.4':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700269 # on ubuntu1404, clang-3.4 alias doesn't exist, just use 'clang'
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800270 return ('ubuntu1404', self._clang_make_options())
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700271 elif compiler == 'clang3.5':
272 return ('jessie', self._clang_make_options(version_suffix='-3.5'))
Jan Tattermuschd4726c12016-02-23 16:57:36 -0800273 elif compiler == 'clang3.6':
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700274 return ('ubuntu1604', self._clang_make_options(version_suffix='-3.6'))
275 elif compiler == 'clang3.7':
276 return ('ubuntu1604', self._clang_make_options(version_suffix='-3.7'))
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800277 else:
278 raise Exception('Compiler %s not supported.' % compiler)
279
Jan Tattermusch77db4322016-02-20 20:19:35 -0800280 def dockerfile_dir(self):
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800281 return 'tools/dockerfile/test/cxx_%s_%s' % (self._docker_distro,
282 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800283
murgatroid99132ce6a2015-03-04 17:29:14 -0800284 def __str__(self):
285 return self.make_target
286
Craig Tillercc0535d2015-12-08 15:14:47 -0800287
murgatroid992c8d5162015-01-26 10:41:21 -0800288class NodeLanguage(object):
289
Jan Tattermusche477b842016-02-06 22:19:01 -0800290 def __init__(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800291 self.platform = platform_string()
Jan Tattermusche477b842016-02-06 22:19:01 -0800292
Jan Tattermusch77db4322016-02-20 20:19:35 -0800293 def configure(self, config, args):
294 self.config = config
295 self.args = args
murgatroid999fab4382016-04-29 15:05:00 -0700296 _check_compiler(self.args.compiler, ['default', 'node0.12',
297 'node4', 'node5'])
298 if self.args.compiler == 'default':
299 self.node_version = '4'
300 else:
301 # Take off the word "node"
302 self.node_version = self.args.compiler[4:]
Jan Tattermusch77db4322016-02-20 20:19:35 -0800303
304 def test_specs(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800305 if self.platform == 'windows':
Jan Tattermusch77db4322016-02-20 20:19:35 -0800306 return [self.config.job_spec(['tools\\run_tests\\run_node.bat'], None)]
Michael Lumishaaa876a2016-02-10 15:27:58 -0800307 else:
Jan Tattermusch77db4322016-02-20 20:19:35 -0800308 return [self.config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
309 None,
310 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid992c8d5162015-01-26 10:41:21 -0800311
murgatroid99256d3df2015-09-21 16:58:02 -0700312 def pre_build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800313 if self.platform == 'windows':
314 return [['tools\\run_tests\\pre_build_node.bat']]
315 else:
316 return [['tools/run_tests/pre_build_node.sh', self.node_version]]
murgatroid99256d3df2015-09-21 16:58:02 -0700317
Jan Tattermusch77db4322016-02-20 20:19:35 -0800318 def make_targets(self):
murgatroid99db5b1602015-10-01 13:20:11 -0700319 return []
murgatroid992c8d5162015-01-26 10:41:21 -0800320
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800321 def make_options(self):
322 return []
323
murgatroid992c8d5162015-01-26 10:41:21 -0800324 def build_steps(self):
Michael Lumishaaa876a2016-02-10 15:27:58 -0800325 if self.platform == 'windows':
326 return [['tools\\run_tests\\build_node.bat']]
327 else:
328 return [['tools/run_tests/build_node.sh', self.node_version]]
Craig Tillerc7449162015-01-16 14:42:10 -0800329
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200330 def post_tests_steps(self):
331 return []
332
murgatroid99a3e244f2015-09-22 11:25:53 -0700333 def makefile_name(self):
334 return 'Makefile'
335
Jan Tattermusch77db4322016-02-20 20:19:35 -0800336 def dockerfile_dir(self):
337 return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800338
murgatroid99132ce6a2015-03-04 17:29:14 -0800339 def __str__(self):
340 return 'node'
341
Craig Tiller99775822015-01-30 13:07:16 -0800342
Craig Tillerc7449162015-01-16 14:42:10 -0800343class PhpLanguage(object):
344
Jan Tattermusch77db4322016-02-20 20:19:35 -0800345 def configure(self, config, args):
346 self.config = config
347 self.args = args
348 _check_compiler(self.args.compiler, ['default'])
349
350 def test_specs(self):
351 return [self.config.job_spec(['src/php/bin/run_tests.sh'], None,
352 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Craig Tillerc7449162015-01-16 14:42:10 -0800353
murgatroid99256d3df2015-09-21 16:58:02 -0700354 def pre_build_steps(self):
355 return []
356
Jan Tattermusch77db4322016-02-20 20:19:35 -0800357 def make_targets(self):
Craig Tilleraf7cf542015-05-22 10:07:34 -0700358 return ['static_c', 'shared_c']
Craig Tillerc7449162015-01-16 14:42:10 -0800359
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800360 def make_options(self):
361 return []
362
Craig Tillerc7449162015-01-16 14:42:10 -0800363 def build_steps(self):
364 return [['tools/run_tests/build_php.sh']]
365
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200366 def post_tests_steps(self):
Stanley Cheunga6b95482016-01-13 16:10:48 -0800367 return [['tools/run_tests/post_tests_php.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200368
murgatroid99a3e244f2015-09-22 11:25:53 -0700369 def makefile_name(self):
370 return 'Makefile'
371
Jan Tattermusch77db4322016-02-20 20:19:35 -0800372 def dockerfile_dir(self):
373 return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800374
murgatroid99132ce6a2015-03-04 17:29:14 -0800375 def __str__(self):
376 return 'php'
377
Craig Tillerc7449162015-01-16 14:42:10 -0800378
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700379class PythonConfig(collections.namedtuple('PythonConfig', [
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700380 'name', 'build', 'run'])):
381 """Tuple of commands (named s.t. 'what it says on the tin' applies)"""
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700382
Nathaniel Manista840615e2015-01-22 20:31:47 +0000383class PythonLanguage(object):
384
Jan Tattermusch77db4322016-02-20 20:19:35 -0800385 def configure(self, config, args):
386 self.config = config
387 self.args = args
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700388 self.pythons = self._get_pythons(self.args)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800389
390 def test_specs(self):
Jan Tattermusch072ebaa2016-03-01 18:33:12 -0800391 # load list of known test suites
Masood Malekghassemi1ff429d2016-06-02 16:39:20 -0700392 with open('src/python/grpcio_tests/tests/tests.json') as tests_json_file:
Jan Tattermusch072ebaa2016-03-01 18:33:12 -0800393 tests_json = json.load(tests_json_file)
Masood Malekghassemi2b841622015-07-28 17:39:02 -0700394 environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700395 return [self.config.job_spec(
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700396 config.run,
Masood Malekghassemie6a23e22016-06-28 13:58:42 -0700397 timeout_seconds=5*60,
siddharthshukla0589e532016-07-07 16:08:01 +0200398 environ=dict(list(environment.items()) +
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700399 [('GRPC_PYTHON_TESTRUNNER_FILTER', suite_name)]),
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700400 shortname='%s.test.%s' % (config.name, suite_name),)
Masood Malekghassemi1c062bd2016-06-13 18:41:36 -0700401 for suite_name in tests_json
402 for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000403
murgatroid99256d3df2015-09-21 16:58:02 -0700404 def pre_build_steps(self):
405 return []
406
Jan Tattermusch77db4322016-02-20 20:19:35 -0800407 def make_targets(self):
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700408 return []
Nathaniel Manista840615e2015-01-22 20:31:47 +0000409
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800410 def make_options(self):
411 return []
412
Nathaniel Manista840615e2015-01-22 20:31:47 +0000413 def build_steps(self):
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700414 return [config.build for config in self.pythons]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000415
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200416 def post_tests_steps(self):
417 return []
418
murgatroid99a3e244f2015-09-22 11:25:53 -0700419 def makefile_name(self):
420 return 'Makefile'
421
Jan Tattermusch77db4322016-02-20 20:19:35 -0800422 def dockerfile_dir(self):
423 return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800424
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700425 def _get_pythons(self, args):
426 if args.arch == 'x86':
427 bits = '32'
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700428 else:
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700429 bits = '64'
430 if os.name == 'nt':
431 shell = ['bash']
432 builder = [os.path.abspath('tools/run_tests/build_python_msys2.sh')]
433 builder_prefix_arguments = ['MINGW{}'.format(bits)]
434 venv_relative_python = ['Scripts/python.exe']
435 toolchain = ['mingw32']
436 python_pattern_function = lambda major, minor, bits: (
437 '/c/Python{major}{minor}/python.exe'.format(major=major, minor=minor, bits=bits)
438 if bits == '64' else
439 '/c/Python{major}{minor}_{bits}bits/python.exe'.format(
440 major=major, minor=minor, bits=bits))
441 else:
442 shell = []
443 builder = [os.path.abspath('tools/run_tests/build_python.sh')]
444 builder_prefix_arguments = []
445 venv_relative_python = ['bin/python']
446 toolchain = ['unix']
447 # Bit-ness is handled by the test machine's environment
448 python_pattern_function = lambda major, minor, bits: 'python{major}.{minor}'.format(major=major, minor=minor)
449 runner = [os.path.abspath('tools/run_tests/run_python.sh')]
450 python_config_generator = lambda name, major, minor, bits: PythonConfig(
451 name,
452 shell + builder + builder_prefix_arguments
453 + [python_pattern_function(major=major, minor=minor, bits=bits)]
454 + [name] + venv_relative_python + toolchain,
455 shell + runner + [os.path.join(name, venv_relative_python[0])])
456 python27_config = python_config_generator(name='py27', major='2', minor='7', bits=bits)
457 python34_config = python_config_generator(name='py34', major='3', minor='4', bits=bits)
458 if args.compiler == 'default':
459 if os.name == 'nt':
460 return (python27_config,)
461 else:
462 return (python27_config, python34_config,)
463 elif args.compiler == 'python2.7':
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700464 return (python27_config,)
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700465 elif args.compiler == 'python3.4':
Masood Malekghassemi3b5b2062016-06-02 20:27:20 -0700466 return (python34_config,)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700467 else:
Masood Malekghassemicab9d4f2016-06-28 09:09:31 -0700468 raise Exception('Compiler %s not supported.' % args.compiler)
Jan Tattermusch825471c2016-04-25 16:52:25 -0700469
murgatroid99132ce6a2015-03-04 17:29:14 -0800470 def __str__(self):
471 return 'python'
472
Craig Tillerd625d812015-04-08 15:52:35 -0700473
murgatroid996a4c4fa2015-02-27 12:08:57 -0800474class RubyLanguage(object):
475
Jan Tattermusch77db4322016-02-20 20:19:35 -0800476 def configure(self, config, args):
477 self.config = config
478 self.args = args
479 _check_compiler(self.args.compiler, ['default'])
480
481 def test_specs(self):
Craig Tillereb5e4372016-06-23 16:16:10 -0700482 return [self.config.job_spec(['tools/run_tests/run_ruby.sh'],
Jan Tattermusch77db4322016-02-20 20:19:35 -0800483 timeout_seconds=10*60,
484 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
murgatroid996a4c4fa2015-02-27 12:08:57 -0800485
murgatroid99256d3df2015-09-21 16:58:02 -0700486 def pre_build_steps(self):
Nicolas "Pixel" Noblebcf988f2015-10-08 03:00:42 +0200487 return [['tools/run_tests/pre_build_ruby.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700488
Jan Tattermusch4651bef2016-02-23 08:31:25 -0800489 def make_targets(self):
murgatroid997d243df2016-02-18 09:58:05 -0800490 return []
murgatroid996a4c4fa2015-02-27 12:08:57 -0800491
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800492 def make_options(self):
493 return []
494
murgatroid996a4c4fa2015-02-27 12:08:57 -0800495 def build_steps(self):
496 return [['tools/run_tests/build_ruby.sh']]
497
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200498 def post_tests_steps(self):
Nicolas "Pixel" Noble7ef1e532015-12-02 00:55:33 +0100499 return [['tools/run_tests/post_tests_ruby.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200500
murgatroid99a3e244f2015-09-22 11:25:53 -0700501 def makefile_name(self):
502 return 'Makefile'
503
Jan Tattermusch77db4322016-02-20 20:19:35 -0800504 def dockerfile_dir(self):
505 return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(self.args.arch)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800506
murgatroid99132ce6a2015-03-04 17:29:14 -0800507 def __str__(self):
508 return 'ruby'
509
Craig Tillerd625d812015-04-08 15:52:35 -0700510
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800511class CSharpLanguage(object):
Jan Tattermusch77db4322016-02-20 20:19:35 -0800512
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700513 def __init__(self):
Craig Tillerd50993d2015-08-05 08:04:36 -0700514 self.platform = platform_string()
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700515
Jan Tattermusch77db4322016-02-20 20:19:35 -0800516 def configure(self, config, args):
517 self.config = config
518 self.args = args
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700519 if self.platform == 'windows':
Jan Tattermuschb2531e22016-03-25 16:14:41 -0700520 # Explicitly choosing between x86 and x64 arch doesn't work yet
521 _check_arch(self.args.arch, ['default'])
Jan Tattermusch6e2f88c2016-06-21 10:52:40 -0700522 # CoreCLR use 64bit runtime by default.
523 arch_option = 'x64' if self.args.compiler == 'coreclr' else self.args.arch
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700524 self._make_options = [_windows_toolset_option(self.args.compiler),
Jan Tattermusch6e2f88c2016-06-21 10:52:40 -0700525 _windows_arch_option(arch_option)]
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700526 else:
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700527 _check_compiler(self.args.compiler, ['default', 'coreclr'])
528 if self.platform == 'linux' and self.args.compiler == 'coreclr':
529 self._docker_distro = 'coreclr'
Jan Tattermusch743decd2016-06-21 11:40:47 -0700530 else:
531 self._docker_distro = 'jessie'
Jan Tattermusch76511a52016-06-17 14:00:57 -0700532
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700533 if self.platform == 'mac':
Jan Tattermusch2a322c22016-03-30 13:55:07 -0700534 # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
Jan Tattermusch6d082202016-06-21 10:03:38 -0700535 self._make_options = ['EMBED_OPENSSL=true']
536 if self.args.compiler != 'coreclr':
537 # On Mac, official distribution of mono is 32bit.
538 self._make_options += ['CFLAGS=-m32', 'LDFLAGS=-m32']
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700539 else:
540 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
Jan Tattermusch77db4322016-02-20 20:19:35 -0800541
542 def test_specs(self):
Jan Tattermusch03c01062015-12-11 14:28:56 -0800543 with open('src/csharp/tests.json') as f:
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700544 tests_by_assembly = json.load(f)
Jan Tattermusch03c01062015-12-11 14:28:56 -0800545
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800546 msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700547 nunit_args = ['--labels=All']
Jan Tattermusch76511a52016-06-17 14:00:57 -0700548 assembly_subdir = 'bin/%s' % msbuild_config
549 assembly_extension = '.exe'
550
551 if self.args.compiler == 'coreclr':
Jan Tattermusch64c137c2016-06-20 17:54:19 -0700552 if self.platform == 'linux':
553 assembly_subdir += '/netstandard1.5/debian.8-x64'
554 assembly_extension = ''
Jan Tattermusch14a301d2016-06-27 17:45:29 -0700555 elif self.platform == 'mac':
Jan Tattermusch6d082202016-06-21 10:03:38 -0700556 assembly_subdir += '/netstandard1.5/osx.10.11-x64'
557 assembly_extension = ''
Jan Tattermusch64c137c2016-06-20 17:54:19 -0700558 else:
559 assembly_subdir += '/netstandard1.5/win7-x64'
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700560 runtime_cmd = []
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700561 else:
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700562 nunit_args += ['--noresult', '--workers=1']
563 if self.platform == 'windows':
564 runtime_cmd = []
565 else:
566 runtime_cmd = ['mono']
Jan Tattermuschbf3b1532015-10-26 10:24:42 -0700567
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700568 specs = []
569 for assembly in tests_by_assembly.iterkeys():
Jan Tattermusch76511a52016-06-17 14:00:57 -0700570 assembly_file = 'src/csharp/%s/%s/%s%s' % (assembly,
571 assembly_subdir,
572 assembly,
573 assembly_extension)
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700574 if self.config.build_config != 'gcov' or self.platform != 'windows':
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700575 # normally, run each test as a separate process
576 for test in tests_by_assembly[assembly]:
577 cmdline = runtime_cmd + [assembly_file, '--test=%s' % test] + nunit_args
578 specs.append(self.config.job_spec(cmdline,
579 None,
580 shortname='csharp.%s' % test,
581 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
582 else:
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700583 # For C# test coverage, run all tests from the same assembly at once
584 # using OpenCover.Console (only works on Windows).
585 cmdline = ['src\\csharp\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe',
586 '-target:%s' % assembly_file,
587 '-targetdir:src\\csharp',
588 '-targetargs:%s' % ' '.join(nunit_args),
589 '-filter:+[Grpc.Core]*',
590 '-register:user',
591 '-output:src\\csharp\\coverage_csharp_%s.xml' % assembly]
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700592
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700593 # set really high cpu_cost to make sure instances of OpenCover.Console run exclusively
594 # to prevent problems with registering the profiler.
595 run_exclusive = 1000000
Jan Tattermusch35e608f2016-04-09 16:35:06 -0700596 specs.append(self.config.job_spec(cmdline,
597 None,
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700598 shortname='csharp.coverage.%s' % assembly,
Jan Tattermuscha5f1f122016-04-11 15:49:56 -0700599 cpu_cost=run_exclusive,
Jan Tattermusch77db4322016-02-20 20:19:35 -0800600 environ=_FORCE_ENVIRON_FOR_WRAPPERS))
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700601 return specs
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800602
murgatroid99256d3df2015-09-21 16:58:02 -0700603 def pre_build_steps(self):
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700604 if self.platform == 'windows':
Jan Tattermusch874aec02015-10-07 19:26:19 -0700605 return [['tools\\run_tests\\pre_build_csharp.bat']]
Jan Tattermusch48423fc2015-10-07 18:59:16 -0700606 else:
607 return [['tools/run_tests/pre_build_csharp.sh']]
murgatroid99256d3df2015-09-21 16:58:02 -0700608
Jan Tattermusch77db4322016-02-20 20:19:35 -0800609 def make_targets(self):
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700610 return ['grpc_csharp_ext']
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800611
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800612 def make_options(self):
Jan Tattermusch6d28d352016-03-25 15:07:22 -0700613 return self._make_options;
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800614
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800615 def build_steps(self):
Jan Tattermusch76511a52016-06-17 14:00:57 -0700616 if self.args.compiler == 'coreclr':
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700617 if self.platform == 'windows':
618 return [['tools\\run_tests\\build_csharp_coreclr.bat']]
619 else:
620 return [['tools/run_tests/build_csharp_coreclr.sh']]
Jan Tattermuschb00aa672015-06-01 15:48:03 -0700621 else:
Jan Tattermusch76511a52016-06-17 14:00:57 -0700622 if self.platform == 'windows':
623 return [[_windows_build_bat(self.args.compiler),
624 'src/csharp/Grpc.sln',
625 '/p:Configuration=%s' % _MSBUILD_CONFIG[self.config.build_config]]]
626 else:
627 return [['tools/run_tests/build_csharp.sh']]
Nathaniel Manista840615e2015-01-22 20:31:47 +0000628
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200629 def post_tests_steps(self):
Jan Tattermusch38ed2cf2016-04-09 16:24:16 -0700630 if self.platform == 'windows':
631 return [['tools\\run_tests\\post_tests_csharp.bat']]
632 else:
633 return [['tools/run_tests/post_tests_csharp.sh']]
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200634
murgatroid99a3e244f2015-09-22 11:25:53 -0700635 def makefile_name(self):
636 return 'Makefile'
637
Jan Tattermusch77db4322016-02-20 20:19:35 -0800638 def dockerfile_dir(self):
Jan Tattermusch76511a52016-06-17 14:00:57 -0700639 return 'tools/dockerfile/test/csharp_%s_%s' % (self._docker_distro,
640 _docker_arch_suffix(self.args.arch))
Jan Tattermusch788ee232016-01-26 12:19:44 -0800641
murgatroid99132ce6a2015-03-04 17:29:14 -0800642 def __str__(self):
643 return 'csharp'
644
Craig Tillerd625d812015-04-08 15:52:35 -0700645
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700646class ObjCLanguage(object):
647
Jan Tattermusch77db4322016-02-20 20:19:35 -0800648 def configure(self, config, args):
649 self.config = config
650 self.args = args
651 _check_compiler(self.args.compiler, ['default'])
652
653 def test_specs(self):
Jorge Canizales6ec3b532016-07-01 11:34:32 -0700654 return [self.config.job_spec(['src/objective-c/tests/run_tests.sh'],
655 timeout_seconds=None,
656 shortname='objc-tests',
657 environ=_FORCE_ENVIRON_FOR_WRAPPERS),
Yuchen Zengf95a4892016-06-21 23:27:46 -0700658 self.config.job_spec(['src/objective-c/tests/build_example_test.sh'],
Jorge Canizales6ec3b532016-07-01 11:34:32 -0700659 timeout_seconds=15*60,
660 shortname='objc-examples-build',
Yuchen Zengc0668c82016-06-22 01:30:47 -0700661 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700662
murgatroid99256d3df2015-09-21 16:58:02 -0700663 def pre_build_steps(self):
664 return []
665
Jan Tattermusch77db4322016-02-20 20:19:35 -0800666 def make_targets(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700667 return ['grpc_objective_c_plugin', 'interop_server']
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700668
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800669 def make_options(self):
670 return []
671
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700672 def build_steps(self):
Jorge Canizalesd0b32e92015-07-30 23:08:43 -0700673 return [['src/objective-c/tests/build_tests.sh']]
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700674
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +0200675 def post_tests_steps(self):
676 return []
677
murgatroid99a3e244f2015-09-22 11:25:53 -0700678 def makefile_name(self):
679 return 'Makefile'
680
Jan Tattermusch77db4322016-02-20 20:19:35 -0800681 def dockerfile_dir(self):
Jan Tattermusch788ee232016-01-26 12:19:44 -0800682 return None
683
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700684 def __str__(self):
685 return 'objc'
686
687
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100688class Sanity(object):
689
Jan Tattermusch77db4322016-02-20 20:19:35 -0800690 def configure(self, config, args):
691 self.config = config
692 self.args = args
693 _check_compiler(self.args.compiler, ['default'])
694
695 def test_specs(self):
Craig Tiller94d04a52016-01-20 10:58:23 -0800696 import yaml
Jan Tattermusch788ee232016-01-26 12:19:44 -0800697 with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
Craig Tiller34226af2016-06-24 16:46:25 -0700698 return [self.config.job_spec(cmd['script'].split(),
Jan Tattermusch77db4322016-02-20 20:19:35 -0800699 timeout_seconds=None, environ={'TEST': 'true'},
700 cpu_cost=cmd.get('cpu_cost', 1))
Craig Tiller94d04a52016-01-20 10:58:23 -0800701 for cmd in yaml.load(f)]
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100702
murgatroid99256d3df2015-09-21 16:58:02 -0700703 def pre_build_steps(self):
704 return []
705
Jan Tattermusch77db4322016-02-20 20:19:35 -0800706 def make_targets(self):
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100707 return ['run_dep_checks']
708
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800709 def make_options(self):
710 return []
711
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100712 def build_steps(self):
713 return []
714
Nicolas "Pixel" Noble87879b32015-10-12 23:28:53 +0200715 def post_tests_steps(self):
716 return []
717
murgatroid99a3e244f2015-09-22 11:25:53 -0700718 def makefile_name(self):
719 return 'Makefile'
720
Jan Tattermusch77db4322016-02-20 20:19:35 -0800721 def dockerfile_dir(self):
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800722 return 'tools/dockerfile/test/sanity'
Jan Tattermusch788ee232016-01-26 12:19:44 -0800723
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100724 def __str__(self):
725 return 'sanity'
726
Nicolas "Pixel" Noblee55cd7f2015-04-14 17:59:13 +0200727
Craig Tiller738c3342015-01-12 14:28:33 -0800728# different configurations we can run under
Craig Tillera0f85172016-01-20 15:56:06 -0800729with open('tools/run_tests/configs.json') as f:
Craig Tiller1dce9062016-01-20 17:01:56 -0800730 _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
Craig Tiller738c3342015-01-12 14:28:33 -0800731
732
Craig Tillerc7449162015-01-16 14:42:10 -0800733_LANGUAGES = {
Craig Tillere9c959d2015-01-18 10:23:26 -0800734 'c++': CLanguage('cxx', 'c++'),
735 'c': CLanguage('c', 'c'),
murgatroid992c8d5162015-01-26 10:41:21 -0800736 'node': NodeLanguage(),
Nathaniel Manista840615e2015-01-22 20:31:47 +0000737 'php': PhpLanguage(),
738 'python': PythonLanguage(),
Jan Tattermusch1970a5b2015-03-03 15:17:25 -0800739 'ruby': RubyLanguage(),
Nicolas "Pixel" Noble9f728642015-03-24 18:50:30 +0100740 'csharp': CSharpLanguage(),
Jorge Canizalesa0b3bfa2015-07-30 19:25:52 -0700741 'objc' : ObjCLanguage(),
Jan Tattermusch70a57e42016-02-20 18:50:27 -0800742 'sanity': Sanity()
Craig Tillereb272bc2015-01-30 13:13:14 -0800743 }
Nicolas Nobleddef2462015-01-06 18:08:25 -0800744
Jan Tattermusch77db4322016-02-20 20:19:35 -0800745
Jan Tattermuscha2d964c2016-02-22 17:33:09 -0800746_MSBUILD_CONFIG = {
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700747 'dbg': 'Debug',
748 'opt': 'Release',
Jan Tattermusche4a69182015-12-15 09:53:01 -0800749 'gcov': 'Debug',
Craig Tiller7bb3efd2015-09-01 08:04:03 -0700750 }
751
David Garcia Quintase90cd372015-05-31 18:15:26 -0700752
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800753def _windows_arch_option(arch):
754 """Returns msbuild cmdline option for selected architecture."""
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800755 if arch == 'default' or arch == 'x86':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800756 return '/p:Platform=Win32'
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800757 elif arch == 'x64':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800758 return '/p:Platform=x64'
759 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200760 print('Architecture %s not supported.' % arch)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800761 sys.exit(1)
Jan Tattermusch788ee232016-01-26 12:19:44 -0800762
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800763
764def _check_arch_option(arch):
765 """Checks that architecture option is valid."""
766 if platform_string() == 'windows':
767 _windows_arch_option(arch)
768 elif platform_string() == 'linux':
769 # On linux, we need to be running under docker with the right architecture.
Jan Tattermusch07fb0422016-01-26 10:46:56 -0800770 runtime_arch = platform.architecture()[0]
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800771 if arch == 'default':
772 return
773 elif runtime_arch == '64bit' and arch == 'x64':
774 return
775 elif runtime_arch == '32bit' and arch == 'x86':
776 return
777 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200778 print('Architecture %s does not match current runtime architecture.' % arch)
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800779 sys.exit(1)
780 else:
781 if args.arch != 'default':
siddharthshukla0589e532016-07-07 16:08:01 +0200782 print('Architecture %s not supported on current platform.' % args.arch)
Jan Tattermuschf08018a2016-01-26 08:22:09 -0800783 sys.exit(1)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800784
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800785
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800786def _windows_build_bat(compiler):
787 """Returns name of build.bat for selected compiler."""
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700788 # For CoreCLR, fall back to the default compiler for C core
789 if compiler == 'default' or compiler == 'vs2013' or compiler == 'coreclr':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800790 return 'vsprojects\\build_vs2013.bat'
791 elif compiler == 'vs2015':
792 return 'vsprojects\\build_vs2015.bat'
793 elif compiler == 'vs2010':
794 return 'vsprojects\\build_vs2010.bat'
795 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200796 print('Compiler %s not supported.' % compiler)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800797 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800798
799
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800800def _windows_toolset_option(compiler):
801 """Returns msbuild PlatformToolset for selected compiler."""
Jan Tattermuschbc98af12016-06-17 18:38:27 -0700802 # For CoreCLR, fall back to the default compiler for C core
803 if compiler == 'default' or compiler == 'vs2013' or compiler == 'coreclr':
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800804 return '/p:PlatformToolset=v120'
805 elif compiler == 'vs2015':
806 return '/p:PlatformToolset=v140'
807 elif compiler == 'vs2010':
808 return '/p:PlatformToolset=v100'
809 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200810 print('Compiler %s not supported.' % compiler)
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800811 sys.exit(1)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800812
813
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800814def _docker_arch_suffix(arch):
815 """Returns suffix to dockerfile dir to use."""
816 if arch == 'default' or arch == 'x64':
817 return 'x64'
818 elif arch == 'x86':
819 return 'x86'
820 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200821 print('Architecture %s not supported with current settings.' % arch)
Jan Tattermusche70b3c52016-02-07 20:21:02 -0800822 sys.exit(1)
823
824
David Garcia Quintase90cd372015-05-31 18:15:26 -0700825def runs_per_test_type(arg_str):
826 """Auxilary function to parse the "runs_per_test" flag.
827
828 Returns:
829 A positive integer or 0, the latter indicating an infinite number of
830 runs.
831
832 Raises:
833 argparse.ArgumentTypeError: Upon invalid input.
834 """
835 if arg_str == 'inf':
836 return 0
837 try:
838 n = int(arg_str)
839 if n <= 0: raise ValueError
Craig Tiller50e53e22015-06-01 20:18:21 -0700840 return n
David Garcia Quintase90cd372015-05-31 18:15:26 -0700841 except:
Adele Zhoue4c35612015-10-16 15:34:23 -0700842 msg = '\'{}\' is not a positive integer or \'inf\''.format(arg_str)
David Garcia Quintase90cd372015-05-31 18:15:26 -0700843 raise argparse.ArgumentTypeError(msg)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700844
845# parse command line
846argp = argparse.ArgumentParser(description='Run grpc tests.')
847argp.add_argument('-c', '--config',
Jan Tattermusch77db4322016-02-20 20:19:35 -0800848 choices=sorted(_CONFIGS.keys()),
849 default='opt')
David Garcia Quintase90cd372015-05-31 18:15:26 -0700850argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
851 help='A positive integer or "inf". If "inf", all tests will run in an '
852 'infinite loop. Especially useful in combination with "-f"')
Craig Tillerfe406ec2015-02-24 13:55:12 -0800853argp.add_argument('-r', '--regex', default='.*', type=str)
Vijay Pai488fd0e2016-06-13 12:37:12 -0700854argp.add_argument('--regex_exclude', default='', type=str)
Craig Tiller5f735a62016-01-20 09:31:15 -0800855argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Craig Tiller8451e872015-02-27 09:25:51 -0800856argp.add_argument('-s', '--slowdown', default=1.0, type=float)
ctiller3040cb72015-01-07 12:13:17 -0800857argp.add_argument('-f', '--forever',
858 default=False,
859 action='store_const',
860 const=True)
Nicolas "Pixel" Noblea7df3f92015-02-26 22:07:04 +0100861argp.add_argument('-t', '--travis',
862 default=False,
863 action='store_const',
864 const=True)
Nicolas Noble044db742015-01-14 16:57:24 -0800865argp.add_argument('--newline_on_success',
866 default=False,
867 action='store_const',
868 const=True)
Craig Tiller686fb262015-01-15 07:39:09 -0800869argp.add_argument('-l', '--language',
Craig Tiller60f15e62015-05-13 09:05:17 -0700870 choices=['all'] + sorted(_LANGUAGES.keys()),
Craig Tiller686fb262015-01-15 07:39:09 -0800871 nargs='+',
Craig Tiller60f15e62015-05-13 09:05:17 -0700872 default=['all'])
Craig Tillercd43da82015-05-29 08:41:29 -0700873argp.add_argument('-S', '--stop_on_failure',
874 default=False,
875 action='store_const',
876 const=True)
Jan Tattermuschc95eead2015-09-18 13:03:50 -0700877argp.add_argument('--use_docker',
878 default=False,
879 action='store_const',
880 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700881 help='Run all the tests under docker. That provides ' +
882 'additional isolation and prevents the need to install ' +
883 'language specific prerequisites. Only available on Linux.')
Craig Tillerd4509a12015-09-28 09:18:40 -0700884argp.add_argument('--allow_flakes',
885 default=False,
886 action='store_const',
887 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700888 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800889argp.add_argument('--arch',
Jan Tattermusch9be594f2016-01-25 18:08:47 -0800890 choices=['default', 'x86', 'x64'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800891 default='default',
892 help='Selects architecture to target. For some platforms "default" is the only supported choice.')
893argp.add_argument('--compiler',
Jan Tattermuschc4cbe392016-02-22 19:29:38 -0800894 choices=['default',
Jan Tattermusch6d258c52016-06-10 09:36:51 -0700895 'gcc4.4', 'gcc4.6', 'gcc4.9', 'gcc5.3',
896 'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7',
Jan Tattermusch825471c2016-04-25 16:52:25 -0700897 'vs2010', 'vs2013', 'vs2015',
murgatroid999fab4382016-04-29 15:05:00 -0700898 'python2.7', 'python3.4',
Jan Tattermusch76511a52016-06-17 14:00:57 -0700899 'node0.12', 'node4', 'node5',
900 'coreclr'],
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800901 default='default',
Jan Tattermusch77db4322016-02-20 20:19:35 -0800902 help='Selects compiler to use. Allowed values depend on the platform and language.')
Jan Tattermusch2dd156e2015-12-04 18:26:17 -0800903argp.add_argument('--build_only',
904 default=False,
905 action='store_const',
906 const=True,
907 help='Perform all the build steps but dont run any tests.')
Craig Tiller5f735a62016-01-20 09:31:15 -0800908argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True,
909 help='Measure the cpu costs of tests')
Craig Tiller1676f912016-01-05 10:49:44 -0800910argp.add_argument('--update_submodules', default=[], nargs='*',
911 help='Update some submodules before building. If any are updated, also run generate_projects. ' +
912 'Submodules are specified as SUBMODULE_NAME:BRANCH; if BRANCH is omitted, master is assumed.')
Craig Tiller234b6e72015-05-23 10:12:40 -0700913argp.add_argument('-a', '--antagonists', default=0, type=int)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +0200914argp.add_argument('-x', '--xml_report', default=None, type=str,
915 help='Generates a JUnit-compatible XML report')
Craig Tiller123f1372016-06-15 15:06:14 -0700916argp.add_argument('--force_default_poller', default=False, action='store_const', const=True,
917 help='Dont try to iterate over many polling strategies when they exist')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800918args = argp.parse_args()
919
Craig Tiller123f1372016-06-15 15:06:14 -0700920if args.force_default_poller:
921 _POLLING_STRATEGIES = {}
922
Craig Tiller5f735a62016-01-20 09:31:15 -0800923jobset.measure_cpu_costs = args.measure_cpu_costs
924
Craig Tiller1676f912016-01-05 10:49:44 -0800925# update submodules if necessary
Craig Tillerb361b4e2016-01-06 11:44:17 -0800926need_to_regenerate_projects = False
927for spec in args.update_submodules:
928 spec = spec.split(':', 1)
929 if len(spec) == 1:
930 submodule = spec[0]
931 branch = 'master'
932 elif len(spec) == 2:
933 submodule = spec[0]
934 branch = spec[1]
935 cwd = 'third_party/%s' % submodule
936 def git(cmd, cwd=cwd):
siddharthshukla0589e532016-07-07 16:08:01 +0200937 print('in %s: git %s' % (cwd, cmd))
Craig Tillerb361b4e2016-01-06 11:44:17 -0800938 subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
939 git('fetch')
940 git('checkout %s' % branch)
941 git('pull origin %s' % branch)
942 if os.path.exists('src/%s/gen_build_yaml.py' % submodule):
943 need_to_regenerate_projects = True
944if need_to_regenerate_projects:
945 if jobset.platform_string() == 'linux':
946 subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
947 else:
siddharthshukla0589e532016-07-07 16:08:01 +0200948 print('WARNING: may need to regenerate projects, but since we are not on')
949 print(' Linux this step is being skipped. Compilation MAY fail.')
Craig Tiller1676f912016-01-05 10:49:44 -0800950
951
Nicolas Nobleddef2462015-01-06 18:08:25 -0800952# grab config
Jan Tattermusch77db4322016-02-20 20:19:35 -0800953run_config = _CONFIGS[args.config]
954build_config = run_config.build_config
Craig Tillerf1973b02015-01-16 12:32:13 -0800955
Craig Tiller06805272015-06-11 14:46:47 -0700956if args.travis:
murgatroid99d3b5b7f2015-10-06 17:02:03 -0700957 _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
Craig Tiller06805272015-06-11 14:46:47 -0700958
Adele Zhou6b9527c2015-11-20 15:56:35 -0800959if 'all' in args.language:
Craig Tiller1676f912016-01-05 10:49:44 -0800960 lang_list = _LANGUAGES.keys()
Adele Zhou6b9527c2015-11-20 15:56:35 -0800961else:
962 lang_list = args.language
Craig Tiller16900662016-01-07 19:30:54 -0800963# We don't support code coverage on some languages
964if 'gcov' in args.config:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800965 for bad in ['objc', 'sanity']:
Craig Tiller16900662016-01-07 19:30:54 -0800966 if bad in lang_list:
967 lang_list.remove(bad)
Adele Zhou6b9527c2015-11-20 15:56:35 -0800968
969languages = set(_LANGUAGES[l] for l in lang_list)
Jan Tattermusch77db4322016-02-20 20:19:35 -0800970for l in languages:
971 l.configure(run_config, args)
murgatroid99132ce6a2015-03-04 17:29:14 -0800972
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800973language_make_options=[]
974if any(language.make_options() for language in languages):
Adele Zhou3b6ab812016-05-18 17:04:20 -0700975 if not 'gcov' in args.config and len(languages) != 1:
siddharthshukla0589e532016-07-07 16:08:01 +0200976 print('languages with custom make options cannot be built simultaneously with other languages')
Jan Tattermuschc895fe02016-01-20 09:13:09 -0800977 sys.exit(1)
978 else:
979 language_make_options = next(iter(languages)).make_options()
980
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800981if args.use_docker:
982 if not args.travis:
siddharthshukla0589e532016-07-07 16:08:01 +0200983 print('Seen --use_docker flag, will run tests under docker.')
984 print('')
985 print('IMPORTANT: The changes you are testing need to be locally committed')
986 print('because only the committed changes in the current branch will be')
987 print('copied to the docker environment.')
Jan Tattermusch4dc9e722016-01-25 17:00:54 -0800988 time.sleep(5)
989
Jan Tattermusch3b5121b2016-02-22 17:41:05 -0800990 dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
991 if len(dockerfile_dirs) > 1:
Adele Zhou9506ef22016-03-02 13:53:34 -0800992 if 'gcov' in args.config:
993 dockerfile_dir = 'tools/dockerfile/test/multilang_jessie_x64'
994 print ('Using multilang_jessie_x64 docker image for code coverage for '
995 'all languages.')
996 else:
997 print ('Languages to be tested require running under different docker '
998 'images.')
999 sys.exit(1)
1000 else:
1001 dockerfile_dir = next(iter(dockerfile_dirs))
Craig Tillerde7edf82016-03-20 09:12:16 -07001002
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001003 child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
Jan Tattermusched342b12016-01-26 14:40:31 -08001004 run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001005
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001006 env = os.environ.copy()
1007 env['RUN_TESTS_COMMAND'] = run_tests_cmd
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001008 env['DOCKERFILE_DIR'] = dockerfile_dir
Jan Tattermusch9835d4b2016-04-29 15:05:05 -07001009 env['DOCKER_RUN_SCRIPT'] = 'tools/run_tests/dockerize/docker_run_tests.sh'
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001010 if args.xml_report:
1011 env['XML_REPORT'] = args.xml_report
1012 if not args.travis:
1013 env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins.
1014
Jan Tattermusch9835d4b2016-04-29 15:05:05 -07001015 subprocess.check_call(['tools/run_tests/dockerize/build_docker_and_run_tests.sh'],
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001016 shell=True,
1017 env=env)
1018 sys.exit(0)
Jan Tattermusch788ee232016-01-26 12:19:44 -08001019
Jan Tattermuschf08018a2016-01-26 08:22:09 -08001020_check_arch_option(args.arch)
Jan Tattermusch4dc9e722016-01-25 17:00:54 -08001021
Jan Tattermuschfba65302016-01-25 18:21:14 -08001022def make_jobspec(cfg, targets, makefile='Makefile'):
1023 if platform_string() == 'windows':
Craig Tillerfc3c0c42015-09-01 16:47:54 -07001024 extra_args = []
Craig Tillerb5391e12015-09-03 14:35:18 -07001025 # better do parallel compilation
Jan Tattermusch47eeb2b2015-10-07 14:09:18 -07001026 # empirically /m:2 gives the best performance/price and should prevent
1027 # overloading the windows workers.
Adele Zhoue4c35612015-10-16 15:34:23 -07001028 extra_args.extend(['/m:2'])
Craig Tillerb5391e12015-09-03 14:35:18 -07001029 # disable PDB generation: it's broken, and we don't need it during CI
Adele Zhoue4c35612015-10-16 15:34:23 -07001030 extra_args.extend(['/p:Jenkins=true'])
Craig Tiller6fd23842015-09-01 07:36:31 -07001031 return [
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001032 jobset.JobSpec([_windows_build_bat(args.compiler),
murgatroid99cf08daf2015-09-21 15:33:16 -07001033 'vsprojects\\%s.sln' % target,
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001034 '/p:Configuration=%s' % _MSBUILD_CONFIG[cfg]] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001035 extra_args +
1036 language_make_options,
Craig Tiller590105a2016-01-19 13:03:46 -08001037 shell=True, timeout_seconds=None)
Craig Tiller6fd23842015-09-01 07:36:31 -07001038 for target in targets]
Jan Tattermuschfba65302016-01-25 18:21:14 -08001039 else:
murgatroid998ae409f2015-10-26 16:39:00 -07001040 if targets:
1041 return [jobset.JobSpec([os.getenv('MAKE', 'make'),
1042 '-f', makefile,
Craig Tillerdd6f7ed2016-01-21 12:54:42 -08001043 '-j', '%d' % args.jobs,
Craig Tiller71a86042016-01-15 14:59:58 -08001044 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown,
1045 'CONFIG=%s' % cfg] +
Jan Tattermuschc895fe02016-01-20 09:13:09 -08001046 language_make_options +
Craig Tiller71a86042016-01-15 14:59:58 -08001047 ([] if not args.travis else ['JENKINS_BUILD=1']) +
1048 targets,
Craig Tiller590105a2016-01-19 13:03:46 -08001049 timeout_seconds=None)]
murgatroid998ae409f2015-10-26 16:39:00 -07001050 else:
1051 return []
Jan Tattermuschfba65302016-01-25 18:21:14 -08001052
murgatroid99a3e244f2015-09-22 11:25:53 -07001053make_targets = {}
1054for l in languages:
1055 makefile = l.makefile_name()
1056 make_targets[makefile] = make_targets.get(makefile, set()).union(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001057 set(l.make_targets()))
Craig Tiller5058c692015-04-08 09:42:04 -07001058
Jan Tattermusche4a69182015-12-15 09:53:01 -08001059def build_step_environ(cfg):
1060 environ = {'CONFIG': cfg}
Jan Tattermuscha2d964c2016-02-22 17:33:09 -08001061 msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
Jan Tattermusche4a69182015-12-15 09:53:01 -08001062 if msbuild_cfg:
1063 environ['MSBUILD_CONFIG'] = msbuild_cfg
1064 return environ
1065
murgatroid99fddac962015-09-22 09:20:11 -07001066build_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001067 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
murgatroid99256d3df2015-09-21 16:58:02 -07001068 for l in languages
1069 for cmdline in l.pre_build_steps()))
Craig Tillerbd4e3782015-09-01 06:48:55 -07001070if make_targets:
siddharthshukla0589e532016-07-07 16:08:01 +02001071 make_commands = itertools.chain.from_iterable(make_jobspec(build_config, list(targets), makefile) for (makefile, targets) in make_targets.items())
Craig Tiller6fd23842015-09-01 07:36:31 -07001072 build_steps.extend(set(make_commands))
Craig Tiller5058c692015-04-08 09:42:04 -07001073build_steps.extend(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001074 jobset.JobSpec(cmdline, environ=build_step_environ(build_config), timeout_seconds=None)
Craig Tiller547db2b2015-01-30 14:08:39 -08001075 for l in languages
Craig Tiller533b1a22015-05-29 08:41:29 -07001076 for cmdline in l.build_steps()))
Craig Tillerf1973b02015-01-16 12:32:13 -08001077
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001078post_tests_steps = list(set(
Jan Tattermusch77db4322016-02-20 20:19:35 -08001079 jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001080 for l in languages
1081 for cmdline in l.post_tests_steps()))
Nicolas Nobleddef2462015-01-06 18:08:25 -08001082runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -08001083forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -08001084
Nicolas Nobleddef2462015-01-06 18:08:25 -08001085
Ken Paysonfa51de52016-06-30 23:50:48 -07001086def _shut_down_legacy_server(legacy_server_port):
1087 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001088 version = int(urllib.request.urlopen(
Ken Paysonfa51de52016-06-30 23:50:48 -07001089 'http://localhost:%d/version_number' % legacy_server_port,
1090 timeout=10).read())
1091 except:
1092 pass
1093 else:
siddharthshukla0589e532016-07-07 16:08:01 +02001094 urllib.request.urlopen(
Ken Paysonfa51de52016-06-30 23:50:48 -07001095 'http://localhost:%d/quitquitquit' % legacy_server_port).read()
1096
1097
Craig Tillerf53d9c82015-08-04 14:19:43 -07001098def _start_port_server(port_server_port):
1099 # check if a compatible port server is running
1100 # if incompatible (version mismatch) ==> start a new one
1101 # if not running ==> start a new one
1102 # otherwise, leave it up
1103 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001104 version = int(urllib.request.urlopen(
Craig Tillerfe4939f2015-10-06 12:55:36 -07001105 'http://localhost:%d/version_number' % port_server_port,
Jan Tattermusch292d0102016-06-28 10:29:41 -07001106 timeout=10).read())
siddharthshukla0589e532016-07-07 16:08:01 +02001107 print('detected port server running version %d' % version)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001108 running = True
Craig Tillerfe4939f2015-10-06 12:55:36 -07001109 except Exception as e:
siddharthshukla0589e532016-07-07 16:08:01 +02001110 print('failed to detect port server: %s' % sys.exc_info()[0])
1111 print(e.strerror)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001112 running = False
1113 if running:
Craig Tillerfe4939f2015-10-06 12:55:36 -07001114 current_version = int(subprocess.check_output(
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001115 [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
1116 'dump_version']))
siddharthshukla0589e532016-07-07 16:08:01 +02001117 print('my port server is version %d' % current_version)
Craig Tillerfe4939f2015-10-06 12:55:36 -07001118 running = (version >= current_version)
1119 if not running:
siddharthshukla0589e532016-07-07 16:08:01 +02001120 print('port_server version mismatch: killing the old one')
1121 urllib.request.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
Craig Tillerfe4939f2015-10-06 12:55:36 -07001122 time.sleep(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001123 if not running:
Craig Tillerf0a293e2015-10-12 10:05:50 -07001124 fd, logfile = tempfile.mkstemp()
1125 os.close(fd)
siddharthshukla0589e532016-07-07 16:08:01 +02001126 print('starting port_server, with log file %s' % logfile)
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001127 args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
1128 '-p', '%d' % port_server_port, '-l', logfile]
Craig Tiller367d41d2015-10-12 13:00:22 -07001129 env = dict(os.environ)
1130 env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
Nicolas "Pixel" Noblef72d7b52015-12-03 03:07:43 +01001131 if platform_string() == 'windows':
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001132 # Working directory of port server needs to be outside of Jenkins
1133 # workspace to prevent file lock issues.
1134 tempdir = tempfile.mkdtemp()
Craig Tillerd2c39712015-10-12 11:08:49 -07001135 port_server = subprocess.Popen(
Craig Tiller367d41d2015-10-12 13:00:22 -07001136 args,
1137 env=env,
Jan Tattermusch3bd08272015-11-04 19:24:37 -08001138 cwd=tempdir,
Craig Tiller367d41d2015-10-12 13:00:22 -07001139 creationflags = 0x00000008, # detached process
1140 close_fds=True)
Craig Tillerd2c39712015-10-12 11:08:49 -07001141 else:
1142 port_server = subprocess.Popen(
1143 args,
Craig Tiller367d41d2015-10-12 13:00:22 -07001144 env=env,
Craig Tillerd2c39712015-10-12 11:08:49 -07001145 preexec_fn=os.setsid,
1146 close_fds=True)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001147 time.sleep(1)
Craig Tiller8b5f4dc2015-08-26 08:02:01 -07001148 # ensure port server is up
Craig Tillerabd37fd2015-08-26 07:54:01 -07001149 waits = 0
Craig Tillerf53d9c82015-08-04 14:19:43 -07001150 while True:
Craig Tillerabd37fd2015-08-26 07:54:01 -07001151 if waits > 10:
siddharthshukla0589e532016-07-07 16:08:01 +02001152 print('killing port server due to excessive start up waits')
Craig Tillerabd37fd2015-08-26 07:54:01 -07001153 port_server.kill()
Craig Tillera2f38b02015-09-24 11:19:17 -07001154 if port_server.poll() is not None:
siddharthshukla0589e532016-07-07 16:08:01 +02001155 print('port_server failed to start')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001156 # try one final time: maybe another build managed to start one
1157 time.sleep(1)
1158 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001159 urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
Craig Tillerf0a293e2015-10-12 10:05:50 -07001160 timeout=1).read()
siddharthshukla0589e532016-07-07 16:08:01 +02001161 print('last ditch attempt to contact port server succeeded')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001162 break
1163 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001164 traceback.print_exc()
Craig Tillerf0a293e2015-10-12 10:05:50 -07001165 port_log = open(logfile, 'r').read()
siddharthshukla0589e532016-07-07 16:08:01 +02001166 print(port_log)
Craig Tillerf0a293e2015-10-12 10:05:50 -07001167 sys.exit(1)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001168 try:
siddharthshukla0589e532016-07-07 16:08:01 +02001169 urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
Craig Tillerabd37fd2015-08-26 07:54:01 -07001170 timeout=1).read()
siddharthshukla0589e532016-07-07 16:08:01 +02001171 print('port server is up and ready')
Craig Tillerf53d9c82015-08-04 14:19:43 -07001172 break
Craig Tiller31fdaa42015-09-25 13:09:59 -07001173 except socket.timeout:
siddharthshukla0589e532016-07-07 16:08:01 +02001174 print('waiting for port_server: timeout')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001175 traceback.print_exc();
1176 time.sleep(1)
Craig Tiller31fdaa42015-09-25 13:09:59 -07001177 waits += 1
siddharthshukla0589e532016-07-07 16:08:01 +02001178 except urllib.error.URLError:
1179 print('waiting for port_server: urlerror')
Craig Tillerf0a293e2015-10-12 10:05:50 -07001180 traceback.print_exc();
1181 time.sleep(1)
Craig Tillerabd37fd2015-08-26 07:54:01 -07001182 waits += 1
Craig Tillerf53d9c82015-08-04 14:19:43 -07001183 except:
Jan Tattermusch3b5121b2016-02-22 17:41:05 -08001184 traceback.print_exc()
Craig Tillerf53d9c82015-08-04 14:19:43 -07001185 port_server.kill()
1186 raise
1187
1188
Adele Zhoud5fffa52015-10-23 15:51:42 -07001189def _calculate_num_runs_failures(list_of_results):
1190 """Caculate number of runs and failures for a particular test.
1191
1192 Args:
1193 list_of_results: (List) of JobResult object.
1194 Returns:
1195 A tuple of total number of runs and failures.
1196 """
1197 num_runs = len(list_of_results) # By default, there is 1 run per JobResult.
1198 num_failures = 0
1199 for jobresult in list_of_results:
1200 if jobresult.retries > 0:
1201 num_runs += jobresult.retries
1202 if jobresult.num_failures > 0:
1203 num_failures += jobresult.num_failures
1204 return num_runs, num_failures
1205
Adele Zhou6b9527c2015-11-20 15:56:35 -08001206
Craig Tillereb9de8b2016-01-08 08:57:41 -08001207# _build_and_run results
1208class BuildAndRunError(object):
1209
1210 BUILD = object()
1211 TEST = object()
1212 POST_TEST = object()
1213
1214
1215# returns a list of things that failed (or an empty list on success)
Craig Tillerf53d9c82015-08-04 14:19:43 -07001216def _build_and_run(
Craig Tiller74189cd2016-06-23 15:39:06 -07001217 check_cancelled, newline_on_success, xml_report=None, build_only=False):
ctiller3040cb72015-01-07 12:13:17 -08001218 """Do one pass of building & running tests."""
murgatroid99666450e2015-01-26 13:03:31 -08001219 # build latest sequentially
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001220 num_failures, resultset = jobset.run(
Adele Zhoue4c35612015-10-16 15:34:23 -07001221 build_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001222 newline_on_success=newline_on_success, travis=args.travis)
Adele Zhoue4c35612015-10-16 15:34:23 -07001223 if num_failures:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001224 return [BuildAndRunError.BUILD]
Craig Tillerb361b4e2016-01-06 11:44:17 -08001225
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001226 if build_only:
Jan Tattermuschaab1e512016-01-28 09:30:44 -08001227 if xml_report:
1228 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001229 return []
ctiller3040cb72015-01-07 12:13:17 -08001230
Craig Tiller234b6e72015-05-23 10:12:40 -07001231 # start antagonists
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001232 antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py'])
Craig Tiller234b6e72015-05-23 10:12:40 -07001233 for _ in range(0, args.antagonists)]
Ken Paysonfa51de52016-06-30 23:50:48 -07001234 port_server_port = 32766
Craig Tillerf53d9c82015-08-04 14:19:43 -07001235 _start_port_server(port_server_port)
Adele Zhou7cf72112015-11-04 11:18:43 -08001236 resultset = None
Adele Zhou803af152015-11-30 15:16:16 -08001237 num_test_failures = 0
Craig Tiller234b6e72015-05-23 10:12:40 -07001238 try:
David Garcia Quintase90cd372015-05-31 18:15:26 -07001239 infinite_runs = runs_per_test == 0
yang-g6c1fdc62015-08-18 11:57:42 -07001240 one_run = set(
1241 spec
yang-g6c1fdc62015-08-18 11:57:42 -07001242 for language in languages
Jan Tattermusch77db4322016-02-20 20:19:35 -08001243 for spec in language.test_specs()
Vijay Pai488fd0e2016-06-13 12:37:12 -07001244 if (re.search(args.regex, spec.shortname) and
1245 (args.regex_exclude == '' or
1246 not re.search(args.regex_exclude, spec.shortname))))
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001247 # When running on travis, we want out test runs to be as similar as possible
1248 # for reproducibility purposes.
Craig Tiller883064c2015-11-04 10:06:10 -08001249 if args.travis:
David Garcia Quintas79e389f2015-06-02 17:49:42 -07001250 massaged_one_run = sorted(one_run, key=lambda x: x.shortname)
1251 else:
1252 # whereas otherwise, we want to shuffle things up to give all tests a
1253 # chance to run.
1254 massaged_one_run = list(one_run) # random.shuffle needs an indexable seq.
1255 random.shuffle(massaged_one_run) # which it modifies in-place.
Craig Tillerf7b7c892015-06-22 14:33:25 -07001256 if infinite_runs:
1257 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 -07001258 runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
1259 else itertools.repeat(massaged_one_run, runs_per_test))
David Garcia Quintase90cd372015-05-31 18:15:26 -07001260 all_runs = itertools.chain.from_iterable(runs_sequence)
Nicolas "Pixel" Noble5937b5b2015-06-26 02:04:12 +02001261
Adele Zhou803af152015-11-30 15:16:16 -08001262 num_test_failures, resultset = jobset.run(
Adele Zhou2271ab52015-10-28 13:59:14 -07001263 all_runs, check_cancelled, newline_on_success=newline_on_success,
Craig Tiller883064c2015-11-04 10:06:10 -08001264 travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
murgatroid998ae409f2015-10-26 16:39:00 -07001265 stop_on_failure=args.stop_on_failure,
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001266 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
Adele Zhoud5fffa52015-10-23 15:51:42 -07001267 if resultset:
Craig Tiller2b59dbc2016-05-13 15:59:09 -07001268 for k, v in sorted(resultset.items()):
Adele Zhoud5fffa52015-10-23 15:51:42 -07001269 num_runs, num_failures = _calculate_num_runs_failures(v)
1270 if num_failures == num_runs: # what about infinite_runs???
1271 jobset.message('FAILED', k, do_newline=True)
1272 elif num_failures > 0:
1273 jobset.message(
1274 'FLAKE', '%s [%d/%d runs flaked]' % (k, num_failures, num_runs),
1275 do_newline=True)
1276 else:
1277 jobset.message('PASSED', k, do_newline=True)
Craig Tiller234b6e72015-05-23 10:12:40 -07001278 finally:
1279 for antagonist in antagonists:
1280 antagonist.kill()
Adele Zhou7cf72112015-11-04 11:18:43 -08001281 if xml_report and resultset:
Adele Zhou3bc7ba42015-11-05 10:21:58 -08001282 report_utils.render_junit_xml_report(resultset, xml_report)
Craig Tillerd86a3942015-01-14 12:48:54 -08001283
Adele Zhouf2ca7bc2015-10-23 15:38:00 -07001284 number_failures, _ = jobset.run(
1285 post_tests_steps, maxjobs=1, stop_on_failure=True,
Craig Tiller883064c2015-11-04 10:06:10 -08001286 newline_on_success=newline_on_success, travis=args.travis)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001287
1288 out = []
1289 if number_failures:
1290 out.append(BuildAndRunError.POST_TEST)
1291 if num_test_failures:
1292 out.append(BuildAndRunError.TEST)
Nicolas "Pixel" Noble3fcd3bf2015-10-10 02:30:38 +02001293
Craig Tillereb9de8b2016-01-08 08:57:41 -08001294 return out
ctiller3040cb72015-01-07 12:13:17 -08001295
1296
1297if forever:
Nicolas Noble044db742015-01-14 16:57:24 -08001298 success = True
ctiller3040cb72015-01-07 12:13:17 -08001299 while True:
Craig Tiller42bc87c2015-02-23 08:50:19 -08001300 dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples'])
ctiller3040cb72015-01-07 12:13:17 -08001301 initial_time = dw.most_recent_change()
1302 have_files_changed = lambda: dw.most_recent_change() != initial_time
Nicolas Noble044db742015-01-14 16:57:24 -08001303 previous_success = success
Craig Tillereb9de8b2016-01-08 08:57:41 -08001304 errors = _build_and_run(check_cancelled=have_files_changed,
1305 newline_on_success=False,
Craig Tillereb9de8b2016-01-08 08:57:41 -08001306 build_only=args.build_only) == 0
1307 if not previous_success and not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001308 jobset.message('SUCCESS',
1309 'All tests are now passing properly',
1310 do_newline=True)
Nicolas Noble044db742015-01-14 16:57:24 -08001311 jobset.message('IDLE', 'No change detected')
ctiller3040cb72015-01-07 12:13:17 -08001312 while not have_files_changed():
1313 time.sleep(1)
1314else:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001315 errors = _build_and_run(check_cancelled=lambda: False,
Craig Tiller71735182015-01-15 17:07:13 -08001316 newline_on_success=args.newline_on_success,
Jan Tattermusch2dd156e2015-12-04 18:26:17 -08001317 xml_report=args.xml_report,
1318 build_only=args.build_only)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001319 if not errors:
Nicolas Nobleb09078f2015-01-14 18:06:05 -08001320 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
1321 else:
1322 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Craig Tillereb9de8b2016-01-08 08:57:41 -08001323 exit_code = 0
1324 if BuildAndRunError.BUILD in errors:
1325 exit_code |= 1
Craig Tiller4f2be362016-01-08 08:59:20 -08001326 if BuildAndRunError.TEST in errors and not args.travis:
Craig Tillereb9de8b2016-01-08 08:57:41 -08001327 exit_code |= 2
Craig Tiller4f2be362016-01-08 08:59:20 -08001328 if BuildAndRunError.POST_TEST in errors:
1329 exit_code |= 4
Craig Tillereb9de8b2016-01-08 08:57:41 -08001330 sys.exit(exit_code)