blob: ca459fbdbd2b73254e127338900be8a5d38b3b69 [file] [log] [blame]
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +02001#!/usr/bin/env python2.7
2# Copyright 2015, Google Inc.
3# 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
31"""Run test matrix."""
32
33import argparse
34import jobset
Jan Tattermuscha1906d52016-09-19 18:37:17 +020035import multiprocessing
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020036import os
37import report_utils
38import sys
39
40_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
41os.chdir(_ROOT)
42
Jan Tattermusch060eb872016-09-20 16:06:13 +020043# Set the timeout high to allow enough time for sanitizers and pre-building
44# clang docker.
45_RUNTESTS_TIMEOUT = 2*60*60
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020046
Jan Tattermuscha1906d52016-09-19 18:37:17 +020047# Number of jobs assigned to each run_tests.py instance
48_INNER_JOBS = 2
49
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020050
51def _docker_jobspec(name, runtests_args=[]):
52 """Run a single instance of run_tests.py in a docker container"""
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020053 test_job = jobset.JobSpec(
54 cmdline=['python', 'tools/run_tests/run_tests.py',
55 '--use_docker',
56 '-t',
Jan Tattermuscha1906d52016-09-19 18:37:17 +020057 '-j', str(_INNER_JOBS),
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020058 '-x', 'report_%s.xml' % name] + runtests_args,
59 shortname='run_tests_%s' % name,
60 timeout_seconds=_RUNTESTS_TIMEOUT)
61 return test_job
62
63
64def _workspace_jobspec(name, runtests_args=[], workspace_name=None):
65 """Run a single instance of run_tests.py in a separate workspace"""
Jan Tattermuscha1906d52016-09-19 18:37:17 +020066 if not workspace_name:
67 workspace_name = 'workspace_%s' % name
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020068 env = {'WORKSPACE_NAME': workspace_name}
69 test_job = jobset.JobSpec(
70 cmdline=['tools/run_tests/run_tests_in_workspace.sh',
71 '-t',
Jan Tattermuscha1906d52016-09-19 18:37:17 +020072 '-j', str(_INNER_JOBS),
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020073 '-x', '../report_%s.xml' % name] + runtests_args,
74 environ=env,
75 shortname='run_tests_%s' % name,
76 timeout_seconds=_RUNTESTS_TIMEOUT)
77 return test_job
78
79
80def _generate_jobs(languages, configs, platforms,
81 arch=None, compiler=None,
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +020082 labels=[], extra_args=[]):
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020083 result = []
84 for language in languages:
85 for platform in platforms:
86 for config in configs:
87 name = '%s_%s_%s' % (language, platform, config)
88 runtests_args = ['-l', language,
89 '-c', config]
90 if arch or compiler:
91 name += '_%s_%s' % (arch, compiler)
92 runtests_args += ['--arch', arch,
93 '--compiler', compiler]
94
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +020095 runtests_args += extra_args
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +020096 if platform == 'linux':
97 job = _docker_jobspec(name=name, runtests_args=runtests_args)
98 else:
99 job = _workspace_jobspec(name=name, runtests_args=runtests_args)
100
101 job.labels = [platform, config, language] + labels
102 result.append(job)
103 return result
104
105
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200106def _create_test_jobs(extra_args=[]):
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200107 test_jobs = []
108 # supported on linux only
109 test_jobs += _generate_jobs(languages=['sanity', 'php7'],
110 configs=['dbg', 'opt'],
111 platforms=['linux'],
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200112 labels=['basictests'],
113 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700114
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200115 # supported on all platforms.
116 test_jobs += _generate_jobs(languages=['c', 'csharp', 'node', 'python'],
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200117 configs=['dbg', 'opt'],
118 platforms=['linux', 'macos', 'windows'],
119 labels=['basictests'],
120 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700121
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200122 # supported on linux and mac.
123 test_jobs += _generate_jobs(languages=['c++', 'ruby', 'php'],
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200124 configs=['dbg', 'opt'],
125 platforms=['linux', 'macos'],
126 labels=['basictests'],
127 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700128
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200129 # supported on mac only.
130 test_jobs += _generate_jobs(languages=['objc'],
131 configs=['dbg', 'opt'],
132 platforms=['macos'],
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200133 labels=['basictests'],
134 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700135
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200136 # sanitizers
137 test_jobs += _generate_jobs(languages=['c'],
138 configs=['msan', 'asan', 'tsan'],
139 platforms=['linux'],
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200140 labels=['sanitizers'],
141 extra_args=extra_args)
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200142 test_jobs += _generate_jobs(languages=['c++'],
143 configs=['asan', 'tsan'],
144 platforms=['linux'],
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200145 labels=['sanitizers'],
146 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700147
148 # libuv tests
149 test_jobs += _generate_jobs(languages=['c'],
150 configs=['dbg', 'opt'],
151 platforms=['linux'],
152 labels=['libuv'],
153 extra_args=extra_args + ['--iomgr_platform=uv'])
154
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200155 return test_jobs
156
murgatroid991687cab2016-10-11 11:42:01 -0700157
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200158def _create_portability_test_jobs(extra_args=[]):
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200159 test_jobs = []
160 # portability C x86
161 test_jobs += _generate_jobs(languages=['c'],
162 configs=['dbg'],
163 platforms=['linux'],
164 arch='x86',
165 compiler='default',
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200166 labels=['portability'],
167 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700168
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200169 # portability C and C++ on x64
170 for compiler in ['gcc4.4', 'gcc4.6', 'gcc5.3',
171 'clang3.5', 'clang3.6', 'clang3.7']:
172 test_jobs += _generate_jobs(languages=['c', 'c++'],
173 configs=['dbg'],
174 platforms=['linux'],
175 arch='x64',
176 compiler=compiler,
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200177 labels=['portability'],
178 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700179
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200180 # portability C on Windows
181 for arch in ['x86', 'x64']:
182 for compiler in ['vs2013', 'vs2015']:
183 test_jobs += _generate_jobs(languages=['c'],
184 configs=['dbg'],
185 platforms=['windows'],
186 arch=arch,
187 compiler=compiler,
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200188 labels=['portability'],
189 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700190
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200191 test_jobs += _generate_jobs(languages=['python'],
192 configs=['dbg'],
193 platforms=['linux'],
194 arch='default',
195 compiler='python3.4',
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200196 labels=['portability'],
197 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700198
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200199 test_jobs += _generate_jobs(languages=['csharp'],
200 configs=['dbg'],
201 platforms=['linux'],
202 arch='default',
203 compiler='coreclr',
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200204 labels=['portability'],
205 extra_args=extra_args)
murgatroid991687cab2016-10-11 11:42:01 -0700206 return test_jobs
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200207
208
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200209def _allowed_labels():
210 """Returns a list of existing job labels."""
211 all_labels = set()
212 for job in _create_test_jobs() + _create_portability_test_jobs():
213 for label in job.labels:
214 all_labels.add(label)
215 return sorted(all_labels)
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200216
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200217
218argp = argparse.ArgumentParser(description='Run a matrix of run_tests.py tests.')
Jan Tattermuscha1906d52016-09-19 18:37:17 +0200219argp.add_argument('-j', '--jobs',
220 default=multiprocessing.cpu_count()/_INNER_JOBS,
221 type=int,
222 help='Number of concurrent run_tests.py instances.')
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200223argp.add_argument('-f', '--filter',
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200224 choices=_allowed_labels(),
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200225 nargs='+',
226 default=[],
227 help='Filter targets to run by label with AND semantics.')
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200228argp.add_argument('--build_only',
229 default=False,
230 action='store_const',
231 const=True,
232 help='Pass --build_only flag to run_tests.py instances.')
233argp.add_argument('--force_default_poller', default=False, action='store_const', const=True,
234 help='Pass --force_default_poller to run_tests.py instances.')
Jan Tattermuschc1e44902016-09-22 14:31:10 +0200235argp.add_argument('--dry_run',
236 default=False,
237 action='store_const',
238 const=True,
239 help='Only print what would be run.')
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200240args = argp.parse_args()
241
Jan Tattermusch6d7c6ef2016-09-22 13:40:48 +0200242extra_args = []
243if args.build_only:
244 extra_args.append('--build_only')
245if args.force_default_poller:
246 extra_args.append('--force_default_poller')
247
248all_jobs = _create_test_jobs(extra_args=extra_args) + _create_portability_test_jobs(extra_args=extra_args)
249
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200250jobs = []
251for job in all_jobs:
252 if not args.filter or all(filter in job.labels for filter in args.filter):
253 jobs.append(job)
254
255if not jobs:
256 jobset.message('FAILED', 'No test suites match given criteria.',
257 do_newline=True)
258 sys.exit(1)
murgatroid991687cab2016-10-11 11:42:01 -0700259
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200260print('IMPORTANT: The changes you are testing need to be locally committed')
261print('because only the committed changes in the current branch will be')
262print('copied to the docker environment or into subworkspaces.')
263
murgatroid991687cab2016-10-11 11:42:01 -0700264print
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200265print 'Will run these tests:'
266for job in jobs:
Jan Tattermusch7b9c21a2016-09-22 14:44:27 +0200267 if args.dry_run:
268 print ' %s: "%s"' % (job.shortname, ' '.join(job.cmdline))
269 else:
270 print ' %s' % job.shortname
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200271print
272
Jan Tattermuschc1e44902016-09-22 14:31:10 +0200273if args.dry_run:
274 print '--dry_run was used, exiting'
275 sys.exit(1)
276
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200277jobset.message('START', 'Running test matrix.', do_newline=True)
278num_failures, resultset = jobset.run(jobs,
279 newline_on_success=True,
280 travis=True,
Jan Tattermuscha1906d52016-09-19 18:37:17 +0200281 maxjobs=args.jobs)
Jan Tattermusch9c79e8d2016-09-19 14:33:18 +0200282report_utils.render_junit_xml_report(resultset, 'report.xml')
283
284if num_failures == 0:
285 jobset.message('SUCCESS', 'All run_tests.py instance finished successfully.',
286 do_newline=True)
287else:
288 jobset.message('FAILED', 'Some run_tests.py instance have failed.',
289 do_newline=True)
290 sys.exit(1)