blob: e503c131acc13258d303008a115abe4325538a16 [file] [log] [blame]
Victor Stinner24f949e2016-03-22 15:14:09 +01001import datetime
Victor Stinner5f9d3ac2015-10-03 00:21:12 +02002import faulthandler
Victor Stinner622583e2016-03-27 18:28:15 +02003import math
Victor Stinner3844fe52015-09-26 10:38:01 +02004import os
Victor Stinner3844fe52015-09-26 10:38:01 +02005import platform
Victor Stinnerdad20e42015-09-29 22:48:52 +02006import random
7import re
Victor Stinnerdad20e42015-09-29 22:48:52 +02008import sys
9import sysconfig
10import tempfile
11import textwrap
Victor Stinner24f949e2016-03-22 15:14:09 +010012import time
Victor Stinner3909e582015-10-11 10:37:25 +020013from test.libregrtest.cmdline import _parse_args
Victor Stinner3844fe52015-09-26 10:38:01 +020014from test.libregrtest.runtest import (
Victor Stinner6f20a2e2015-09-30 02:32:11 +020015 findtests, runtest,
Victor Stinner3909e582015-10-11 10:37:25 +020016 STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED,
Victor Stinner69649f22016-03-23 12:14:10 +010017 INTERRUPTED, CHILD_ERROR,
Victor Stinner1b8b4232016-05-20 13:37:40 +020018 PROGRESS_MIN_TIME, format_test_result)
Victor Stinnera2045022015-09-30 02:17:28 +020019from test.libregrtest.setup import setup_tests
Victor Stinner3844fe52015-09-26 10:38:01 +020020from test import support
21try:
Victor Stinnerdad20e42015-09-29 22:48:52 +020022 import gc
23except ImportError:
24 gc = None
Victor Stinner3844fe52015-09-26 10:38:01 +020025
26
Victor Stinner3844fe52015-09-26 10:38:01 +020027# When tests are run from the Python build directory, it is best practice
28# to keep the test files in a subfolder. This eases the cleanup of leftover
29# files using the "make distclean" command.
30if sysconfig.is_python_build():
31 TEMPDIR = os.path.join(sysconfig.get_config_var('srcdir'), 'build')
32else:
33 TEMPDIR = tempfile.gettempdir()
34TEMPDIR = os.path.abspath(TEMPDIR)
35
36
Victor Stinnerdad20e42015-09-29 22:48:52 +020037class Regrtest:
Victor Stinner3844fe52015-09-26 10:38:01 +020038 """Execute a test suite.
39
40 This also parses command-line options and modifies its behavior
41 accordingly.
42
43 tests -- a list of strings containing test names (optional)
44 testdir -- the directory in which to look for tests (optional)
45
46 Users other than the Python test suite will certainly want to
47 specify testdir; if it's omitted, the directory containing the
48 Python test suite is searched for.
49
50 If the tests argument is omitted, the tests listed on the
51 command-line will be used. If that's empty, too, then all *.py
52 files beginning with test_ will be used.
53
54 The other default arguments (verbose, quiet, exclude,
55 single, randomize, findleaks, use_resources, trace, coverdir,
56 print_slow, and random_seed) allow programmers calling main()
57 directly to set the values that would normally be set by flags
58 on the command line.
59 """
Victor Stinnerdad20e42015-09-29 22:48:52 +020060 def __init__(self):
61 # Namespace of command line options
62 self.ns = None
Victor Stinner3844fe52015-09-26 10:38:01 +020063
Victor Stinnerdad20e42015-09-29 22:48:52 +020064 # tests
65 self.tests = []
66 self.selected = []
Victor Stinner3844fe52015-09-26 10:38:01 +020067
Victor Stinnerdad20e42015-09-29 22:48:52 +020068 # test results
69 self.good = []
70 self.bad = []
71 self.skipped = []
72 self.resource_denieds = []
73 self.environment_changed = []
74 self.interrupted = False
Victor Stinner3844fe52015-09-26 10:38:01 +020075
Victor Stinnerdad20e42015-09-29 22:48:52 +020076 # used by --slow
77 self.test_times = []
Victor Stinner3844fe52015-09-26 10:38:01 +020078
Victor Stinnerdad20e42015-09-29 22:48:52 +020079 # used by --coverage, trace.Trace instance
80 self.tracer = None
Victor Stinner3844fe52015-09-26 10:38:01 +020081
Victor Stinnerdad20e42015-09-29 22:48:52 +020082 # used by --findleaks, store for gc.garbage
83 self.found_garbage = []
Victor Stinner3844fe52015-09-26 10:38:01 +020084
Victor Stinnerdad20e42015-09-29 22:48:52 +020085 # used to display the progress bar "[ 3/100]"
Victor Stinner24f949e2016-03-22 15:14:09 +010086 self.start_time = time.monotonic()
Victor Stinnerdad20e42015-09-29 22:48:52 +020087 self.test_count = ''
88 self.test_count_width = 1
Victor Stinner3844fe52015-09-26 10:38:01 +020089
Victor Stinnerdad20e42015-09-29 22:48:52 +020090 # used by --single
91 self.next_single_test = None
92 self.next_single_filename = None
Victor Stinner3844fe52015-09-26 10:38:01 +020093
Victor Stinnerdad20e42015-09-29 22:48:52 +020094 def accumulate_result(self, test, result):
Victor Stinner3844fe52015-09-26 10:38:01 +020095 ok, test_time = result
Victor Stinner3909e582015-10-11 10:37:25 +020096 if ok not in (CHILD_ERROR, INTERRUPTED):
97 self.test_times.append((test_time, test))
Victor Stinner3844fe52015-09-26 10:38:01 +020098 if ok == PASSED:
Victor Stinnerdad20e42015-09-29 22:48:52 +020099 self.good.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200100 elif ok == FAILED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200101 self.bad.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200102 elif ok == ENV_CHANGED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200103 self.environment_changed.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200104 elif ok == SKIPPED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200105 self.skipped.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200106 elif ok == RESOURCE_DENIED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200107 self.skipped.append(test)
108 self.resource_denieds.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200109
Victor Stinner622583e2016-03-27 18:28:15 +0200110 def time_delta(self, ceil=False):
Victor Stinner24f949e2016-03-22 15:14:09 +0100111 seconds = time.monotonic() - self.start_time
Victor Stinner622583e2016-03-27 18:28:15 +0200112 if ceil:
113 seconds = math.ceil(seconds)
114 else:
115 seconds = int(seconds)
116 return datetime.timedelta(seconds=seconds)
Victor Stinner24f949e2016-03-22 15:14:09 +0100117
Victor Stinnerdad20e42015-09-29 22:48:52 +0200118 def display_progress(self, test_index, test):
119 if self.ns.quiet:
120 return
Brett Cannon11faa212015-10-02 16:20:49 -0700121 if self.bad and not self.ns.pgo:
Victor Stinner24f949e2016-03-22 15:14:09 +0100122 fmt = "{time} [{test_index:{count_width}}{test_count}/{nbad}] {test_name}"
Brett Cannon11faa212015-10-02 16:20:49 -0700123 else:
Victor Stinner24f949e2016-03-22 15:14:09 +0100124 fmt = "{time} [{test_index:{count_width}}{test_count}] {test_name}"
125 line = fmt.format(count_width=self.test_count_width,
126 test_index=test_index,
127 test_count=self.test_count,
128 nbad=len(self.bad),
129 test_name=test,
130 time=self.time_delta())
131 print(line, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200132
Victor Stinner234cbef2015-09-30 01:13:53 +0200133 def parse_args(self, kwargs):
134 ns = _parse_args(sys.argv[1:], **kwargs)
135
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200136 if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'):
137 print("Warning: The timeout option requires "
138 "faulthandler.dump_traceback_later", file=sys.stderr)
139 ns.timeout = None
140
Victor Stinner234cbef2015-09-30 01:13:53 +0200141 if ns.threshold is not None and gc is None:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200142 print('No GC available, ignore --threshold.', file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200143 ns.threshold = None
144
145 if ns.findleaks:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200146 if gc is not None:
147 # Uncomment the line below to report garbage that is not
148 # freeable by reference counting alone. By default only
149 # garbage that is not collectable by the GC is reported.
150 pass
151 #gc.set_debug(gc.DEBUG_SAVEALL)
152 else:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200153 print('No GC available, disabling --findleaks',
154 file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200155 ns.findleaks = False
Victor Stinnerdad20e42015-09-29 22:48:52 +0200156
Victor Stinnerdad20e42015-09-29 22:48:52 +0200157 # Strip .py extensions.
Victor Stinner234cbef2015-09-30 01:13:53 +0200158 removepy(ns.args)
159
160 return ns
Victor Stinnerdad20e42015-09-29 22:48:52 +0200161
Victor Stinnerdad20e42015-09-29 22:48:52 +0200162 def find_tests(self, tests):
163 self.tests = tests
164
165 if self.ns.single:
166 self.next_single_filename = os.path.join(TEMPDIR, 'pynexttest')
167 try:
168 with open(self.next_single_filename, 'r') as fp:
169 next_test = fp.read().strip()
170 self.tests = [next_test]
171 except OSError:
172 pass
173
174 if self.ns.fromfile:
175 self.tests = []
Victor Stinner5de16e82016-03-24 09:43:00 +0100176 # regex to match 'test_builtin' in line:
177 # '0:00:00 [ 4/400] test_builtin -- test_dict took 1 sec'
178 regex = (r'^(?:[0-9]+:[0-9]+:[0-9]+ *)?'
179 r'(?:\[[0-9/ ]+\] *)?'
180 r'(test_[a-zA-Z0-9_]+)')
181 regex = re.compile(regex)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200182 with open(os.path.join(support.SAVEDCWD, self.ns.fromfile)) as fp:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200183 for line in fp:
Victor Stinner5de16e82016-03-24 09:43:00 +0100184 line = line.strip()
185 if line.startswith('#'):
186 continue
187 match = regex.match(line)
188 if match is None:
189 continue
190 self.tests.append(match.group(1))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200191
192 removepy(self.tests)
193
194 stdtests = STDTESTS[:]
195 nottests = NOTTESTS.copy()
196 if self.ns.exclude:
197 for arg in self.ns.args:
198 if arg in stdtests:
199 stdtests.remove(arg)
200 nottests.add(arg)
201 self.ns.args = []
202
Victor Stinnerdad20e42015-09-29 22:48:52 +0200203 # if testdir is set, then we are not running the python tests suite, so
204 # don't add default tests to be executed or skipped (pass empty values)
205 if self.ns.testdir:
206 alltests = findtests(self.ns.testdir, list(), set())
207 else:
208 alltests = findtests(self.ns.testdir, stdtests, nottests)
209
Victor Stinner5de16e82016-03-24 09:43:00 +0100210 if not self.ns.fromfile:
211 self.selected = self.tests or self.ns.args or alltests
212 else:
213 self.selected = self.tests
Victor Stinnerdad20e42015-09-29 22:48:52 +0200214 if self.ns.single:
215 self.selected = self.selected[:1]
216 try:
217 pos = alltests.index(self.selected[0])
218 self.next_single_test = alltests[pos + 1]
219 except IndexError:
220 pass
221
Victor Stinnerc7eab052015-09-30 00:59:35 +0200222 # Remove all the selected tests that precede start if it's set.
Victor Stinnerdad20e42015-09-29 22:48:52 +0200223 if self.ns.start:
224 try:
225 del self.selected[:self.selected.index(self.ns.start)]
226 except ValueError:
Victor Stinner6448b802015-09-29 23:43:33 +0200227 print("Couldn't find starting test (%s), using all tests"
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200228 % self.ns.start, file=sys.stderr)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200229
230 if self.ns.randomize:
231 if self.ns.random_seed is None:
232 self.ns.random_seed = random.randrange(10000000)
233 random.seed(self.ns.random_seed)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200234 random.shuffle(self.selected)
235
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200236 def list_tests(self):
237 for name in self.selected:
238 print(name)
239
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200240 def rerun_failed_tests(self):
241 self.ns.verbose = True
242 self.ns.failfast = False
243 self.ns.verbose3 = False
244 self.ns.match_tests = None
245
246 print("Re-running failed tests in verbose mode")
247 for test in self.bad[:]:
248 print("Re-running test %r in verbose mode" % test, flush=True)
249 try:
250 self.ns.verbose = True
251 ok = runtest(self.ns, test)
252 except KeyboardInterrupt:
253 # print a newline separate from the ^C
254 print()
255 break
256 else:
257 if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}:
258 self.bad.remove(test)
259 else:
260 if self.bad:
261 print(count(len(self.bad), 'test'), "failed again:")
262 printlist(self.bad)
263
Victor Stinnerdad20e42015-09-29 22:48:52 +0200264 def display_result(self):
265 if self.interrupted:
266 # print a newline after ^C
267 print()
268 print("Test suite interrupted by signal SIGINT.")
Victor Stinner6448b802015-09-29 23:43:33 +0200269 executed = set(self.good) | set(self.bad) | set(self.skipped)
270 omitted = set(self.selected) - executed
Victor Stinnerdad20e42015-09-29 22:48:52 +0200271 print(count(len(omitted), "test"), "omitted:")
272 printlist(omitted)
273
Brett Cannon11faa212015-10-02 16:20:49 -0700274 # If running the test suite for PGO then no one cares about
275 # results.
276 if self.ns.pgo:
277 return
278
Victor Stinnerdad20e42015-09-29 22:48:52 +0200279 if self.good and not self.ns.quiet:
Victor Stinner6448b802015-09-29 23:43:33 +0200280 if (not self.bad
281 and not self.skipped
282 and not self.interrupted
283 and len(self.good) > 1):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200284 print("All", end=' ')
285 print(count(len(self.good), "test"), "OK.")
286
287 if self.ns.print_slow:
288 self.test_times.sort(reverse=True)
289 print("10 slowest tests:")
290 for time, test in self.test_times[:10]:
291 print("%s: %.1fs" % (test, time))
292
293 if self.bad:
294 print(count(len(self.bad), "test"), "failed:")
295 printlist(self.bad)
296
297 if self.environment_changed:
298 print("{} altered the execution environment:".format(
299 count(len(self.environment_changed), "test")))
300 printlist(self.environment_changed)
301
302 if self.skipped and not self.ns.quiet:
303 print(count(len(self.skipped), "test"), "skipped:")
304 printlist(self.skipped)
305
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200306 def run_tests_sequential(self):
Victor Stinnerc7eab052015-09-30 00:59:35 +0200307 if self.ns.trace:
308 import trace
Victor Stinnera53a8182015-10-01 00:53:09 +0200309 self.tracer = trace.Trace(trace=False, count=True)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200310
Victor Stinnerdad20e42015-09-29 22:48:52 +0200311 save_modules = sys.modules.keys()
312
Victor Stinner2b60b722016-03-24 11:55:29 +0100313 print("Run tests sequentially")
314
Victor Stinner69649f22016-03-23 12:14:10 +0100315 previous_test = None
Victor Stinnerdad20e42015-09-29 22:48:52 +0200316 for test_index, test in enumerate(self.tests, 1):
Victor Stinner69649f22016-03-23 12:14:10 +0100317 start_time = time.monotonic()
318
319 text = test
320 if previous_test:
321 text = '%s -- %s' % (text, previous_test)
322 self.display_progress(test_index, text)
323
Victor Stinnerc7eab052015-09-30 00:59:35 +0200324 if self.tracer:
Victor Stinner3844fe52015-09-26 10:38:01 +0200325 # If we're tracing code coverage, then we don't exit with status
326 # if on a false return value from main.
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200327 cmd = ('result = runtest(self.ns, test); '
328 'self.accumulate_result(test, result)')
Victor Stinner1b8b4232016-05-20 13:37:40 +0200329 ns = dict(locals())
330 self.tracer.runctx(cmd, globals=globals(), locals=ns)
331 result = ns['result']
Victor Stinner3844fe52015-09-26 10:38:01 +0200332 else:
333 try:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200334 result = runtest(self.ns, test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200335 except KeyboardInterrupt:
Victor Stinner3909e582015-10-11 10:37:25 +0200336 self.accumulate_result(test, (INTERRUPTED, None))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200337 self.interrupted = True
Victor Stinner3844fe52015-09-26 10:38:01 +0200338 break
Victor Stinner3909e582015-10-11 10:37:25 +0200339 else:
340 self.accumulate_result(test, result)
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200341
Victor Stinner1b8b4232016-05-20 13:37:40 +0200342 previous_test = format_test_result(test, result[0])
Victor Stinner69649f22016-03-23 12:14:10 +0100343 test_time = time.monotonic() - start_time
344 if test_time >= PROGRESS_MIN_TIME:
Victor Stinner1b8b4232016-05-20 13:37:40 +0200345 previous_test = "%s in %.0f sec" % (previous_test, test_time)
346 elif result[0] == PASSED:
347 # be quiet: say nothing if the test passed shortly
Victor Stinner69649f22016-03-23 12:14:10 +0100348 previous_test = None
349
Victor Stinnerdad20e42015-09-29 22:48:52 +0200350 if self.ns.findleaks:
Victor Stinner3844fe52015-09-26 10:38:01 +0200351 gc.collect()
352 if gc.garbage:
353 print("Warning: test created", len(gc.garbage), end=' ')
354 print("uncollectable object(s).")
355 # move the uncollectable objects somewhere so we don't see
356 # them again
Victor Stinnerdad20e42015-09-29 22:48:52 +0200357 self.found_garbage.extend(gc.garbage)
Victor Stinner3844fe52015-09-26 10:38:01 +0200358 del gc.garbage[:]
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200359
Victor Stinner3844fe52015-09-26 10:38:01 +0200360 # Unload the newly imported modules (best effort finalization)
361 for module in sys.modules.keys():
362 if module not in save_modules and module.startswith("test."):
363 support.unload(module)
364
Victor Stinner69649f22016-03-23 12:14:10 +0100365 if previous_test:
366 print(previous_test)
367
Victor Stinnerb4084352015-09-30 02:39:22 +0200368 def _test_forever(self, tests):
369 while True:
370 for test in tests:
371 yield test
372 if self.bad:
373 return
Victor Stinner3844fe52015-09-26 10:38:01 +0200374
Victor Stinnerb4084352015-09-30 02:39:22 +0200375 def run_tests(self):
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200376 # For a partial run, we do not need to clutter the output.
377 if (self.ns.verbose
378 or self.ns.header
Brett Cannon11faa212015-10-02 16:20:49 -0700379 or not (self.ns.pgo or self.ns.quiet or self.ns.single
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200380 or self.tests or self.ns.args)):
381 # Print basic platform information
382 print("==", platform.python_implementation(), *sys.version.split())
383 print("== ", platform.platform(aliased=True),
384 "%s-endian" % sys.byteorder)
385 print("== ", "hash algorithm:", sys.hash_info.algorithm,
386 "64bit" if sys.maxsize > 2**32 else "32bit")
387 print("== ", os.getcwd())
388 print("Testing with flags:", sys.flags)
389
390 if self.ns.randomize:
391 print("Using random seed", self.ns.random_seed)
392
Victor Stinnerdad20e42015-09-29 22:48:52 +0200393 if self.ns.forever:
Victor Stinner9a142142015-09-30 13:51:17 +0200394 self.tests = self._test_forever(list(self.selected))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200395 self.test_count = ''
396 self.test_count_width = 3
397 else:
398 self.tests = iter(self.selected)
399 self.test_count = '/{}'.format(len(self.selected))
400 self.test_count_width = len(self.test_count) - 1
401
402 if self.ns.use_mp:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200403 from test.libregrtest.runtest_mp import run_tests_multiprocess
404 run_tests_multiprocess(self)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200405 else:
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200406 self.run_tests_sequential()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200407
408 def finalize(self):
409 if self.next_single_filename:
410 if self.next_single_test:
411 with open(self.next_single_filename, 'w') as fp:
412 fp.write(self.next_single_test + '\n')
Victor Stinner3844fe52015-09-26 10:38:01 +0200413 else:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200414 os.unlink(self.next_single_filename)
Victor Stinner3844fe52015-09-26 10:38:01 +0200415
Victor Stinnerc7eab052015-09-30 00:59:35 +0200416 if self.tracer:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200417 r = self.tracer.results()
418 r.write_results(show_missing=True, summary=True,
419 coverdir=self.ns.coverdir)
Victor Stinner3844fe52015-09-26 10:38:01 +0200420
Victor Stinner622583e2016-03-27 18:28:15 +0200421 print("Total duration: %s" % self.time_delta(ceil=True))
Victor Stinner24f949e2016-03-22 15:14:09 +0100422
Victor Stinnerdad20e42015-09-29 22:48:52 +0200423 if self.ns.runleaks:
424 os.system("leaks %d" % os.getpid())
Victor Stinner3844fe52015-09-26 10:38:01 +0200425
Victor Stinnerdad20e42015-09-29 22:48:52 +0200426 def main(self, tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100427 global TEMPDIR
428
429 if sysconfig.is_python_build():
430 try:
431 os.mkdir(TEMPDIR)
432 except FileExistsError:
433 pass
434
435 # Define a writable temp dir that will be used as cwd while running
436 # the tests. The name of the dir includes the pid to allow parallel
437 # testing (see the -j option).
438 test_cwd = 'test_python_{}'.format(os.getpid())
439 test_cwd = os.path.join(TEMPDIR, test_cwd)
440
441 # Run the tests in a context manager that temporarily changes the CWD to a
442 # temporary and writable directory. If it's not possible to create or
443 # change the CWD, the original CWD will be used. The original CWD is
444 # available from support.SAVEDCWD.
445 with support.temp_cwd(test_cwd, quiet=True):
446 self._main(tests, kwargs)
447
448 def _main(self, tests, kwargs):
Victor Stinner234cbef2015-09-30 01:13:53 +0200449 self.ns = self.parse_args(kwargs)
450
Victor Stinnerdad20e42015-09-29 22:48:52 +0200451 if self.ns.slaveargs is not None:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200452 from test.libregrtest.runtest_mp import run_tests_slave
453 run_tests_slave(self.ns.slaveargs)
Victor Stinnerecef6222015-09-30 01:39:28 +0200454
Victor Stinnerc7eab052015-09-30 00:59:35 +0200455 if self.ns.wait:
456 input("Press any key to continue...")
457
Victor Stinnera2045022015-09-30 02:17:28 +0200458 setup_tests(self.ns)
Victor Stinnerecef6222015-09-30 01:39:28 +0200459
Victor Stinnerdad20e42015-09-29 22:48:52 +0200460 self.find_tests(tests)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200461
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200462 if self.ns.list_tests:
463 self.list_tests()
464 sys.exit(0)
465
466 self.run_tests()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200467 self.display_result()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200468
469 if self.ns.verbose2 and self.bad:
470 self.rerun_failed_tests()
471
Victor Stinnerdad20e42015-09-29 22:48:52 +0200472 self.finalize()
473 sys.exit(len(self.bad) > 0 or self.interrupted)
Victor Stinner3844fe52015-09-26 10:38:01 +0200474
475
Victor Stinner3844fe52015-09-26 10:38:01 +0200476def removepy(names):
477 if not names:
478 return
479 for idx, name in enumerate(names):
480 basename, ext = os.path.splitext(name)
481 if ext == '.py':
482 names[idx] = basename
483
484
485def count(n, word):
486 if n == 1:
487 return "%d %s" % (n, word)
488 else:
489 return "%d %ss" % (n, word)
490
491
492def printlist(x, width=70, indent=4):
493 """Print the elements of iterable x to stdout.
494
495 Optional arg width (default 70) is the maximum line length.
496 Optional arg indent (default 4) is the number of blanks with which to
497 begin each line.
498 """
499
Victor Stinner3844fe52015-09-26 10:38:01 +0200500 blanks = ' ' * indent
501 # Print the sorted list: 'x' may be a '--random' list or a set()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200502 print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width,
503 initial_indent=blanks, subsequent_indent=blanks))
504
505
506def main(tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100507 """Run the Python suite."""
Victor Stinnerdad20e42015-09-29 22:48:52 +0200508 Regrtest().main(tests=tests, **kwargs)