blob: 447d99f88ab6c40736f9a1f036b184afe30670bc [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,
18 PROGRESS_MIN_TIME)
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 Stinnerdad20e42015-09-29 22:48:52 +0200329 self.tracer.runctx(cmd, globals=globals(), locals=vars())
Victor Stinner3844fe52015-09-26 10:38:01 +0200330 else:
331 try:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200332 result = runtest(self.ns, test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200333 except KeyboardInterrupt:
Victor Stinner3909e582015-10-11 10:37:25 +0200334 self.accumulate_result(test, (INTERRUPTED, None))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200335 self.interrupted = True
Victor Stinner3844fe52015-09-26 10:38:01 +0200336 break
Victor Stinner3909e582015-10-11 10:37:25 +0200337 else:
338 self.accumulate_result(test, result)
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200339
Victor Stinner69649f22016-03-23 12:14:10 +0100340 test_time = time.monotonic() - start_time
341 if test_time >= PROGRESS_MIN_TIME:
342 previous_test = '%s took %.0f sec' % (test, test_time)
343 else:
344 previous_test = None
345
Victor Stinnerdad20e42015-09-29 22:48:52 +0200346 if self.ns.findleaks:
Victor Stinner3844fe52015-09-26 10:38:01 +0200347 gc.collect()
348 if gc.garbage:
349 print("Warning: test created", len(gc.garbage), end=' ')
350 print("uncollectable object(s).")
351 # move the uncollectable objects somewhere so we don't see
352 # them again
Victor Stinnerdad20e42015-09-29 22:48:52 +0200353 self.found_garbage.extend(gc.garbage)
Victor Stinner3844fe52015-09-26 10:38:01 +0200354 del gc.garbage[:]
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200355
Victor Stinner3844fe52015-09-26 10:38:01 +0200356 # Unload the newly imported modules (best effort finalization)
357 for module in sys.modules.keys():
358 if module not in save_modules and module.startswith("test."):
359 support.unload(module)
360
Victor Stinner69649f22016-03-23 12:14:10 +0100361 if previous_test:
362 print(previous_test)
363
Victor Stinnerb4084352015-09-30 02:39:22 +0200364 def _test_forever(self, tests):
365 while True:
366 for test in tests:
367 yield test
368 if self.bad:
369 return
Victor Stinner3844fe52015-09-26 10:38:01 +0200370
Victor Stinnerb4084352015-09-30 02:39:22 +0200371 def run_tests(self):
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200372 # For a partial run, we do not need to clutter the output.
373 if (self.ns.verbose
374 or self.ns.header
Brett Cannon11faa212015-10-02 16:20:49 -0700375 or not (self.ns.pgo or self.ns.quiet or self.ns.single
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200376 or self.tests or self.ns.args)):
377 # Print basic platform information
378 print("==", platform.python_implementation(), *sys.version.split())
379 print("== ", platform.platform(aliased=True),
380 "%s-endian" % sys.byteorder)
381 print("== ", "hash algorithm:", sys.hash_info.algorithm,
382 "64bit" if sys.maxsize > 2**32 else "32bit")
383 print("== ", os.getcwd())
384 print("Testing with flags:", sys.flags)
385
386 if self.ns.randomize:
387 print("Using random seed", self.ns.random_seed)
388
Victor Stinnerdad20e42015-09-29 22:48:52 +0200389 if self.ns.forever:
Victor Stinner9a142142015-09-30 13:51:17 +0200390 self.tests = self._test_forever(list(self.selected))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200391 self.test_count = ''
392 self.test_count_width = 3
393 else:
394 self.tests = iter(self.selected)
395 self.test_count = '/{}'.format(len(self.selected))
396 self.test_count_width = len(self.test_count) - 1
397
398 if self.ns.use_mp:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200399 from test.libregrtest.runtest_mp import run_tests_multiprocess
400 run_tests_multiprocess(self)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200401 else:
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200402 self.run_tests_sequential()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200403
404 def finalize(self):
405 if self.next_single_filename:
406 if self.next_single_test:
407 with open(self.next_single_filename, 'w') as fp:
408 fp.write(self.next_single_test + '\n')
Victor Stinner3844fe52015-09-26 10:38:01 +0200409 else:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200410 os.unlink(self.next_single_filename)
Victor Stinner3844fe52015-09-26 10:38:01 +0200411
Victor Stinnerc7eab052015-09-30 00:59:35 +0200412 if self.tracer:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200413 r = self.tracer.results()
414 r.write_results(show_missing=True, summary=True,
415 coverdir=self.ns.coverdir)
Victor Stinner3844fe52015-09-26 10:38:01 +0200416
Victor Stinner622583e2016-03-27 18:28:15 +0200417 print("Total duration: %s" % self.time_delta(ceil=True))
Victor Stinner24f949e2016-03-22 15:14:09 +0100418
Victor Stinnerdad20e42015-09-29 22:48:52 +0200419 if self.ns.runleaks:
420 os.system("leaks %d" % os.getpid())
Victor Stinner3844fe52015-09-26 10:38:01 +0200421
Victor Stinnerdad20e42015-09-29 22:48:52 +0200422 def main(self, tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100423 global TEMPDIR
424
425 if sysconfig.is_python_build():
426 try:
427 os.mkdir(TEMPDIR)
428 except FileExistsError:
429 pass
430
431 # Define a writable temp dir that will be used as cwd while running
432 # the tests. The name of the dir includes the pid to allow parallel
433 # testing (see the -j option).
434 test_cwd = 'test_python_{}'.format(os.getpid())
435 test_cwd = os.path.join(TEMPDIR, test_cwd)
436
437 # Run the tests in a context manager that temporarily changes the CWD to a
438 # temporary and writable directory. If it's not possible to create or
439 # change the CWD, the original CWD will be used. The original CWD is
440 # available from support.SAVEDCWD.
441 with support.temp_cwd(test_cwd, quiet=True):
442 self._main(tests, kwargs)
443
444 def _main(self, tests, kwargs):
Victor Stinner234cbef2015-09-30 01:13:53 +0200445 self.ns = self.parse_args(kwargs)
446
Victor Stinnerdad20e42015-09-29 22:48:52 +0200447 if self.ns.slaveargs is not None:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200448 from test.libregrtest.runtest_mp import run_tests_slave
449 run_tests_slave(self.ns.slaveargs)
Victor Stinnerecef6222015-09-30 01:39:28 +0200450
Victor Stinnerc7eab052015-09-30 00:59:35 +0200451 if self.ns.wait:
452 input("Press any key to continue...")
453
Victor Stinnera2045022015-09-30 02:17:28 +0200454 setup_tests(self.ns)
Victor Stinnerecef6222015-09-30 01:39:28 +0200455
Victor Stinnerdad20e42015-09-29 22:48:52 +0200456 self.find_tests(tests)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200457
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200458 if self.ns.list_tests:
459 self.list_tests()
460 sys.exit(0)
461
462 self.run_tests()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200463 self.display_result()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200464
465 if self.ns.verbose2 and self.bad:
466 self.rerun_failed_tests()
467
Victor Stinnerdad20e42015-09-29 22:48:52 +0200468 self.finalize()
469 sys.exit(len(self.bad) > 0 or self.interrupted)
Victor Stinner3844fe52015-09-26 10:38:01 +0200470
471
Victor Stinner3844fe52015-09-26 10:38:01 +0200472def removepy(names):
473 if not names:
474 return
475 for idx, name in enumerate(names):
476 basename, ext = os.path.splitext(name)
477 if ext == '.py':
478 names[idx] = basename
479
480
481def count(n, word):
482 if n == 1:
483 return "%d %s" % (n, word)
484 else:
485 return "%d %ss" % (n, word)
486
487
488def printlist(x, width=70, indent=4):
489 """Print the elements of iterable x to stdout.
490
491 Optional arg width (default 70) is the maximum line length.
492 Optional arg indent (default 4) is the number of blanks with which to
493 begin each line.
494 """
495
Victor Stinner3844fe52015-09-26 10:38:01 +0200496 blanks = ' ' * indent
497 # Print the sorted list: 'x' may be a '--random' list or a set()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200498 print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width,
499 initial_indent=blanks, subsequent_indent=blanks))
500
501
502def main(tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100503 """Run the Python suite."""
Victor Stinnerdad20e42015-09-29 22:48:52 +0200504 Regrtest().main(tests=tests, **kwargs)