blob: c6d9ad05bc9f95a21df9559651247ec0f3220d92 [file] [log] [blame]
Victor Stinner24f949e2016-03-22 15:14:09 +01001import datetime
Victor Stinner5f9d3ac2015-10-03 00:21:12 +02002import faulthandler
Victor Stinner3844fe52015-09-26 10:38:01 +02003import os
Victor Stinner3844fe52015-09-26 10:38:01 +02004import platform
Victor Stinnerdad20e42015-09-29 22:48:52 +02005import random
6import re
Victor Stinnerdad20e42015-09-29 22:48:52 +02007import sys
8import sysconfig
9import tempfile
10import textwrap
Victor Stinner24f949e2016-03-22 15:14:09 +010011import time
Victor Stinner3909e582015-10-11 10:37:25 +020012from test.libregrtest.cmdline import _parse_args
Victor Stinner3844fe52015-09-26 10:38:01 +020013from test.libregrtest.runtest import (
Victor Stinner6f20a2e2015-09-30 02:32:11 +020014 findtests, runtest,
Victor Stinner3909e582015-10-11 10:37:25 +020015 STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED,
Victor Stinner69649f22016-03-23 12:14:10 +010016 INTERRUPTED, CHILD_ERROR,
17 PROGRESS_MIN_TIME)
Victor Stinnera2045022015-09-30 02:17:28 +020018from test.libregrtest.setup import setup_tests
Victor Stinner3844fe52015-09-26 10:38:01 +020019from test import support
20try:
Victor Stinnerdad20e42015-09-29 22:48:52 +020021 import gc
22except ImportError:
23 gc = None
Victor Stinner3844fe52015-09-26 10:38:01 +020024
25
Victor Stinner3844fe52015-09-26 10:38:01 +020026# When tests are run from the Python build directory, it is best practice
27# to keep the test files in a subfolder. This eases the cleanup of leftover
28# files using the "make distclean" command.
29if sysconfig.is_python_build():
30 TEMPDIR = os.path.join(sysconfig.get_config_var('srcdir'), 'build')
31else:
32 TEMPDIR = tempfile.gettempdir()
33TEMPDIR = os.path.abspath(TEMPDIR)
34
35
Victor Stinnerdad20e42015-09-29 22:48:52 +020036class Regrtest:
Victor Stinner3844fe52015-09-26 10:38:01 +020037 """Execute a test suite.
38
39 This also parses command-line options and modifies its behavior
40 accordingly.
41
42 tests -- a list of strings containing test names (optional)
43 testdir -- the directory in which to look for tests (optional)
44
45 Users other than the Python test suite will certainly want to
46 specify testdir; if it's omitted, the directory containing the
47 Python test suite is searched for.
48
49 If the tests argument is omitted, the tests listed on the
50 command-line will be used. If that's empty, too, then all *.py
51 files beginning with test_ will be used.
52
53 The other default arguments (verbose, quiet, exclude,
54 single, randomize, findleaks, use_resources, trace, coverdir,
55 print_slow, and random_seed) allow programmers calling main()
56 directly to set the values that would normally be set by flags
57 on the command line.
58 """
Victor Stinnerdad20e42015-09-29 22:48:52 +020059 def __init__(self):
60 # Namespace of command line options
61 self.ns = None
Victor Stinner3844fe52015-09-26 10:38:01 +020062
Victor Stinnerdad20e42015-09-29 22:48:52 +020063 # tests
64 self.tests = []
65 self.selected = []
Victor Stinner3844fe52015-09-26 10:38:01 +020066
Victor Stinnerdad20e42015-09-29 22:48:52 +020067 # test results
68 self.good = []
69 self.bad = []
70 self.skipped = []
71 self.resource_denieds = []
72 self.environment_changed = []
73 self.interrupted = False
Victor Stinner3844fe52015-09-26 10:38:01 +020074
Victor Stinnerdad20e42015-09-29 22:48:52 +020075 # used by --slow
76 self.test_times = []
Victor Stinner3844fe52015-09-26 10:38:01 +020077
Victor Stinnerdad20e42015-09-29 22:48:52 +020078 # used by --coverage, trace.Trace instance
79 self.tracer = None
Victor Stinner3844fe52015-09-26 10:38:01 +020080
Victor Stinnerdad20e42015-09-29 22:48:52 +020081 # used by --findleaks, store for gc.garbage
82 self.found_garbage = []
Victor Stinner3844fe52015-09-26 10:38:01 +020083
Victor Stinnerdad20e42015-09-29 22:48:52 +020084 # used to display the progress bar "[ 3/100]"
Victor Stinner24f949e2016-03-22 15:14:09 +010085 self.start_time = time.monotonic()
Victor Stinnerdad20e42015-09-29 22:48:52 +020086 self.test_count = ''
87 self.test_count_width = 1
Victor Stinner3844fe52015-09-26 10:38:01 +020088
Victor Stinnerdad20e42015-09-29 22:48:52 +020089 # used by --single
90 self.next_single_test = None
91 self.next_single_filename = None
Victor Stinner3844fe52015-09-26 10:38:01 +020092
Victor Stinnerdad20e42015-09-29 22:48:52 +020093 def accumulate_result(self, test, result):
Victor Stinner3844fe52015-09-26 10:38:01 +020094 ok, test_time = result
Victor Stinner3909e582015-10-11 10:37:25 +020095 if ok not in (CHILD_ERROR, INTERRUPTED):
96 self.test_times.append((test_time, test))
Victor Stinner3844fe52015-09-26 10:38:01 +020097 if ok == PASSED:
Victor Stinnerdad20e42015-09-29 22:48:52 +020098 self.good.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +020099 elif ok == FAILED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200100 self.bad.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200101 elif ok == ENV_CHANGED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200102 self.environment_changed.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200103 elif ok == SKIPPED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200104 self.skipped.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200105 elif ok == RESOURCE_DENIED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200106 self.skipped.append(test)
107 self.resource_denieds.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200108
Victor Stinner24f949e2016-03-22 15:14:09 +0100109 def time_delta(self):
110 seconds = time.monotonic() - self.start_time
111 return datetime.timedelta(seconds=int(seconds))
112
Victor Stinnerdad20e42015-09-29 22:48:52 +0200113 def display_progress(self, test_index, test):
114 if self.ns.quiet:
115 return
Brett Cannon11faa212015-10-02 16:20:49 -0700116 if self.bad and not self.ns.pgo:
Victor Stinner24f949e2016-03-22 15:14:09 +0100117 fmt = "{time} [{test_index:{count_width}}{test_count}/{nbad}] {test_name}"
Brett Cannon11faa212015-10-02 16:20:49 -0700118 else:
Victor Stinner24f949e2016-03-22 15:14:09 +0100119 fmt = "{time} [{test_index:{count_width}}{test_count}] {test_name}"
120 line = fmt.format(count_width=self.test_count_width,
121 test_index=test_index,
122 test_count=self.test_count,
123 nbad=len(self.bad),
124 test_name=test,
125 time=self.time_delta())
126 print(line, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200127
Victor Stinner234cbef2015-09-30 01:13:53 +0200128 def parse_args(self, kwargs):
129 ns = _parse_args(sys.argv[1:], **kwargs)
130
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200131 if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'):
132 print("Warning: The timeout option requires "
133 "faulthandler.dump_traceback_later", file=sys.stderr)
134 ns.timeout = None
135
Victor Stinner234cbef2015-09-30 01:13:53 +0200136 if ns.threshold is not None and gc is None:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200137 print('No GC available, ignore --threshold.', file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200138 ns.threshold = None
139
140 if ns.findleaks:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200141 if gc is not None:
142 # Uncomment the line below to report garbage that is not
143 # freeable by reference counting alone. By default only
144 # garbage that is not collectable by the GC is reported.
145 pass
146 #gc.set_debug(gc.DEBUG_SAVEALL)
147 else:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200148 print('No GC available, disabling --findleaks',
149 file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200150 ns.findleaks = False
Victor Stinnerdad20e42015-09-29 22:48:52 +0200151
Victor Stinnerdad20e42015-09-29 22:48:52 +0200152 # Strip .py extensions.
Victor Stinner234cbef2015-09-30 01:13:53 +0200153 removepy(ns.args)
154
155 return ns
Victor Stinnerdad20e42015-09-29 22:48:52 +0200156
Victor Stinnerdad20e42015-09-29 22:48:52 +0200157 def find_tests(self, tests):
158 self.tests = tests
159
160 if self.ns.single:
161 self.next_single_filename = os.path.join(TEMPDIR, 'pynexttest')
162 try:
163 with open(self.next_single_filename, 'r') as fp:
164 next_test = fp.read().strip()
165 self.tests = [next_test]
166 except OSError:
167 pass
168
169 if self.ns.fromfile:
170 self.tests = []
Victor Stinner5de16e82016-03-24 09:43:00 +0100171 # regex to match 'test_builtin' in line:
172 # '0:00:00 [ 4/400] test_builtin -- test_dict took 1 sec'
173 regex = (r'^(?:[0-9]+:[0-9]+:[0-9]+ *)?'
174 r'(?:\[[0-9/ ]+\] *)?'
175 r'(test_[a-zA-Z0-9_]+)')
176 regex = re.compile(regex)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200177 with open(os.path.join(support.SAVEDCWD, self.ns.fromfile)) as fp:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200178 for line in fp:
Victor Stinner5de16e82016-03-24 09:43:00 +0100179 line = line.strip()
180 if line.startswith('#'):
181 continue
182 match = regex.match(line)
183 if match is None:
184 continue
185 self.tests.append(match.group(1))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200186
187 removepy(self.tests)
188
189 stdtests = STDTESTS[:]
190 nottests = NOTTESTS.copy()
191 if self.ns.exclude:
192 for arg in self.ns.args:
193 if arg in stdtests:
194 stdtests.remove(arg)
195 nottests.add(arg)
196 self.ns.args = []
197
Victor Stinnerdad20e42015-09-29 22:48:52 +0200198 # if testdir is set, then we are not running the python tests suite, so
199 # don't add default tests to be executed or skipped (pass empty values)
200 if self.ns.testdir:
201 alltests = findtests(self.ns.testdir, list(), set())
202 else:
203 alltests = findtests(self.ns.testdir, stdtests, nottests)
204
Victor Stinner5de16e82016-03-24 09:43:00 +0100205 if not self.ns.fromfile:
206 self.selected = self.tests or self.ns.args or alltests
207 else:
208 self.selected = self.tests
Victor Stinnerdad20e42015-09-29 22:48:52 +0200209 if self.ns.single:
210 self.selected = self.selected[:1]
211 try:
212 pos = alltests.index(self.selected[0])
213 self.next_single_test = alltests[pos + 1]
214 except IndexError:
215 pass
216
Victor Stinnerc7eab052015-09-30 00:59:35 +0200217 # Remove all the selected tests that precede start if it's set.
Victor Stinnerdad20e42015-09-29 22:48:52 +0200218 if self.ns.start:
219 try:
220 del self.selected[:self.selected.index(self.ns.start)]
221 except ValueError:
Victor Stinner6448b802015-09-29 23:43:33 +0200222 print("Couldn't find starting test (%s), using all tests"
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200223 % self.ns.start, file=sys.stderr)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200224
225 if self.ns.randomize:
226 if self.ns.random_seed is None:
227 self.ns.random_seed = random.randrange(10000000)
228 random.seed(self.ns.random_seed)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200229 random.shuffle(self.selected)
230
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200231 def list_tests(self):
232 for name in self.selected:
233 print(name)
234
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200235 def rerun_failed_tests(self):
236 self.ns.verbose = True
237 self.ns.failfast = False
238 self.ns.verbose3 = False
239 self.ns.match_tests = None
240
241 print("Re-running failed tests in verbose mode")
242 for test in self.bad[:]:
243 print("Re-running test %r in verbose mode" % test, flush=True)
244 try:
245 self.ns.verbose = True
246 ok = runtest(self.ns, test)
247 except KeyboardInterrupt:
248 # print a newline separate from the ^C
249 print()
250 break
251 else:
252 if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}:
253 self.bad.remove(test)
254 else:
255 if self.bad:
256 print(count(len(self.bad), 'test'), "failed again:")
257 printlist(self.bad)
258
Victor Stinnerdad20e42015-09-29 22:48:52 +0200259 def display_result(self):
260 if self.interrupted:
261 # print a newline after ^C
262 print()
263 print("Test suite interrupted by signal SIGINT.")
Victor Stinner6448b802015-09-29 23:43:33 +0200264 executed = set(self.good) | set(self.bad) | set(self.skipped)
265 omitted = set(self.selected) - executed
Victor Stinnerdad20e42015-09-29 22:48:52 +0200266 print(count(len(omitted), "test"), "omitted:")
267 printlist(omitted)
268
Brett Cannon11faa212015-10-02 16:20:49 -0700269 # If running the test suite for PGO then no one cares about
270 # results.
271 if self.ns.pgo:
272 return
273
Victor Stinnerdad20e42015-09-29 22:48:52 +0200274 if self.good and not self.ns.quiet:
Victor Stinner6448b802015-09-29 23:43:33 +0200275 if (not self.bad
276 and not self.skipped
277 and not self.interrupted
278 and len(self.good) > 1):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200279 print("All", end=' ')
280 print(count(len(self.good), "test"), "OK.")
281
282 if self.ns.print_slow:
283 self.test_times.sort(reverse=True)
284 print("10 slowest tests:")
285 for time, test in self.test_times[:10]:
286 print("%s: %.1fs" % (test, time))
287
288 if self.bad:
289 print(count(len(self.bad), "test"), "failed:")
290 printlist(self.bad)
291
292 if self.environment_changed:
293 print("{} altered the execution environment:".format(
294 count(len(self.environment_changed), "test")))
295 printlist(self.environment_changed)
296
297 if self.skipped and not self.ns.quiet:
298 print(count(len(self.skipped), "test"), "skipped:")
299 printlist(self.skipped)
300
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200301 def run_tests_sequential(self):
Victor Stinnerc7eab052015-09-30 00:59:35 +0200302 if self.ns.trace:
303 import trace
Victor Stinnera53a8182015-10-01 00:53:09 +0200304 self.tracer = trace.Trace(trace=False, count=True)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200305
Victor Stinnerdad20e42015-09-29 22:48:52 +0200306 save_modules = sys.modules.keys()
307
Victor Stinner2b60b722016-03-24 11:55:29 +0100308 print("Run tests sequentially")
309
Victor Stinner69649f22016-03-23 12:14:10 +0100310 previous_test = None
Victor Stinnerdad20e42015-09-29 22:48:52 +0200311 for test_index, test in enumerate(self.tests, 1):
Victor Stinner69649f22016-03-23 12:14:10 +0100312 start_time = time.monotonic()
313
314 text = test
315 if previous_test:
316 text = '%s -- %s' % (text, previous_test)
317 self.display_progress(test_index, text)
318
Victor Stinnerc7eab052015-09-30 00:59:35 +0200319 if self.tracer:
Victor Stinner3844fe52015-09-26 10:38:01 +0200320 # If we're tracing code coverage, then we don't exit with status
321 # if on a false return value from main.
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200322 cmd = ('result = runtest(self.ns, test); '
323 'self.accumulate_result(test, result)')
Victor Stinnerdad20e42015-09-29 22:48:52 +0200324 self.tracer.runctx(cmd, globals=globals(), locals=vars())
Victor Stinner3844fe52015-09-26 10:38:01 +0200325 else:
326 try:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200327 result = runtest(self.ns, test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200328 except KeyboardInterrupt:
Victor Stinner3909e582015-10-11 10:37:25 +0200329 self.accumulate_result(test, (INTERRUPTED, None))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200330 self.interrupted = True
Victor Stinner3844fe52015-09-26 10:38:01 +0200331 break
Victor Stinner3909e582015-10-11 10:37:25 +0200332 else:
333 self.accumulate_result(test, result)
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200334
Victor Stinner69649f22016-03-23 12:14:10 +0100335 test_time = time.monotonic() - start_time
336 if test_time >= PROGRESS_MIN_TIME:
337 previous_test = '%s took %.0f sec' % (test, test_time)
338 else:
339 previous_test = None
340
Victor Stinnerdad20e42015-09-29 22:48:52 +0200341 if self.ns.findleaks:
Victor Stinner3844fe52015-09-26 10:38:01 +0200342 gc.collect()
343 if gc.garbage:
344 print("Warning: test created", len(gc.garbage), end=' ')
345 print("uncollectable object(s).")
346 # move the uncollectable objects somewhere so we don't see
347 # them again
Victor Stinnerdad20e42015-09-29 22:48:52 +0200348 self.found_garbage.extend(gc.garbage)
Victor Stinner3844fe52015-09-26 10:38:01 +0200349 del gc.garbage[:]
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200350
Victor Stinner3844fe52015-09-26 10:38:01 +0200351 # Unload the newly imported modules (best effort finalization)
352 for module in sys.modules.keys():
353 if module not in save_modules and module.startswith("test."):
354 support.unload(module)
355
Victor Stinner69649f22016-03-23 12:14:10 +0100356 if previous_test:
357 print(previous_test)
358
Victor Stinnerb4084352015-09-30 02:39:22 +0200359 def _test_forever(self, tests):
360 while True:
361 for test in tests:
362 yield test
363 if self.bad:
364 return
Victor Stinner3844fe52015-09-26 10:38:01 +0200365
Victor Stinnerb4084352015-09-30 02:39:22 +0200366 def run_tests(self):
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200367 # For a partial run, we do not need to clutter the output.
368 if (self.ns.verbose
369 or self.ns.header
Brett Cannon11faa212015-10-02 16:20:49 -0700370 or not (self.ns.pgo or self.ns.quiet or self.ns.single
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200371 or self.tests or self.ns.args)):
372 # Print basic platform information
373 print("==", platform.python_implementation(), *sys.version.split())
374 print("== ", platform.platform(aliased=True),
375 "%s-endian" % sys.byteorder)
376 print("== ", "hash algorithm:", sys.hash_info.algorithm,
377 "64bit" if sys.maxsize > 2**32 else "32bit")
378 print("== ", os.getcwd())
379 print("Testing with flags:", sys.flags)
380
381 if self.ns.randomize:
382 print("Using random seed", self.ns.random_seed)
383
Victor Stinnerdad20e42015-09-29 22:48:52 +0200384 if self.ns.forever:
Victor Stinner9a142142015-09-30 13:51:17 +0200385 self.tests = self._test_forever(list(self.selected))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200386 self.test_count = ''
387 self.test_count_width = 3
388 else:
389 self.tests = iter(self.selected)
390 self.test_count = '/{}'.format(len(self.selected))
391 self.test_count_width = len(self.test_count) - 1
392
393 if self.ns.use_mp:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200394 from test.libregrtest.runtest_mp import run_tests_multiprocess
395 run_tests_multiprocess(self)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200396 else:
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200397 self.run_tests_sequential()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200398
399 def finalize(self):
400 if self.next_single_filename:
401 if self.next_single_test:
402 with open(self.next_single_filename, 'w') as fp:
403 fp.write(self.next_single_test + '\n')
Victor Stinner3844fe52015-09-26 10:38:01 +0200404 else:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200405 os.unlink(self.next_single_filename)
Victor Stinner3844fe52015-09-26 10:38:01 +0200406
Victor Stinnerc7eab052015-09-30 00:59:35 +0200407 if self.tracer:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200408 r = self.tracer.results()
409 r.write_results(show_missing=True, summary=True,
410 coverdir=self.ns.coverdir)
Victor Stinner3844fe52015-09-26 10:38:01 +0200411
Victor Stinner24f949e2016-03-22 15:14:09 +0100412 print("Total duration: %s" % self.time_delta())
413
Victor Stinnerdad20e42015-09-29 22:48:52 +0200414 if self.ns.runleaks:
415 os.system("leaks %d" % os.getpid())
Victor Stinner3844fe52015-09-26 10:38:01 +0200416
Victor Stinnerdad20e42015-09-29 22:48:52 +0200417 def main(self, tests=None, **kwargs):
Victor Stinner234cbef2015-09-30 01:13:53 +0200418 self.ns = self.parse_args(kwargs)
419
Victor Stinnerdad20e42015-09-29 22:48:52 +0200420 if self.ns.slaveargs is not None:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200421 from test.libregrtest.runtest_mp import run_tests_slave
422 run_tests_slave(self.ns.slaveargs)
Victor Stinnerecef6222015-09-30 01:39:28 +0200423
Victor Stinnerc7eab052015-09-30 00:59:35 +0200424 if self.ns.wait:
425 input("Press any key to continue...")
426
Victor Stinnera2045022015-09-30 02:17:28 +0200427 setup_tests(self.ns)
Victor Stinnerecef6222015-09-30 01:39:28 +0200428
Victor Stinnerdad20e42015-09-29 22:48:52 +0200429 self.find_tests(tests)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200430
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200431 if self.ns.list_tests:
432 self.list_tests()
433 sys.exit(0)
434
435 self.run_tests()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200436 self.display_result()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200437
438 if self.ns.verbose2 and self.bad:
439 self.rerun_failed_tests()
440
Victor Stinnerdad20e42015-09-29 22:48:52 +0200441 self.finalize()
442 sys.exit(len(self.bad) > 0 or self.interrupted)
Victor Stinner3844fe52015-09-26 10:38:01 +0200443
444
Victor Stinner3844fe52015-09-26 10:38:01 +0200445def removepy(names):
446 if not names:
447 return
448 for idx, name in enumerate(names):
449 basename, ext = os.path.splitext(name)
450 if ext == '.py':
451 names[idx] = basename
452
453
454def count(n, word):
455 if n == 1:
456 return "%d %s" % (n, word)
457 else:
458 return "%d %ss" % (n, word)
459
460
461def printlist(x, width=70, indent=4):
462 """Print the elements of iterable x to stdout.
463
464 Optional arg width (default 70) is the maximum line length.
465 Optional arg indent (default 4) is the number of blanks with which to
466 begin each line.
467 """
468
Victor Stinner3844fe52015-09-26 10:38:01 +0200469 blanks = ' ' * indent
470 # Print the sorted list: 'x' may be a '--random' list or a set()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200471 print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width,
472 initial_indent=blanks, subsequent_indent=blanks))
473
474
475def main(tests=None, **kwargs):
476 Regrtest().main(tests=tests, **kwargs)
Victor Stinner3844fe52015-09-26 10:38:01 +0200477
478
479def main_in_temp_cwd():
480 """Run main() in a temporary working directory."""
481 if sysconfig.is_python_build():
482 try:
483 os.mkdir(TEMPDIR)
484 except FileExistsError:
485 pass
486
487 # Define a writable temp dir that will be used as cwd while running
488 # the tests. The name of the dir includes the pid to allow parallel
489 # testing (see the -j option).
490 test_cwd = 'test_python_{}'.format(os.getpid())
491 test_cwd = os.path.join(TEMPDIR, test_cwd)
492
493 # Run the tests in a context manager that temporarily changes the CWD to a
494 # temporary and writable directory. If it's not possible to create or
495 # change the CWD, the original CWD will be used. The original CWD is
496 # available from support.SAVEDCWD.
497 with support.temp_cwd(test_cwd, quiet=True):
498 main()