blob: 1ab47bf58d6733b66bd5cbe53ea6d69ec10761e1 [file] [log] [blame]
Victor Stinner24f949e2016-03-22 15:14:09 +01001import datetime
Victor Stinner5f9d3ac2015-10-03 00:21:12 +02002import faulthandler
Victor Stinnerb96ef552016-09-08 21:46:56 -07003import locale
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
mlouielua49c9352017-06-16 17:36:19 +080013import unittest
Victor Stinner3909e582015-10-11 10:37:25 +020014from test.libregrtest.cmdline import _parse_args
Victor Stinner3844fe52015-09-26 10:38:01 +020015from test.libregrtest.runtest import (
mlouielua49c9352017-06-16 17:36:19 +080016 findtests, runtest, get_abs_module,
Victor Stinner3909e582015-10-11 10:37:25 +020017 STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED,
Victor Stinner69649f22016-03-23 12:14:10 +010018 INTERRUPTED, CHILD_ERROR,
Victor Stinner1b8b4232016-05-20 13:37:40 +020019 PROGRESS_MIN_TIME, format_test_result)
Victor Stinnera2045022015-09-30 02:17:28 +020020from test.libregrtest.setup import setup_tests
Victor Stinner3844fe52015-09-26 10:38:01 +020021from test import support
22try:
Victor Stinnerdad20e42015-09-29 22:48:52 +020023 import gc
24except ImportError:
25 gc = None
Victor Stinner3844fe52015-09-26 10:38:01 +020026
27
Victor Stinner3844fe52015-09-26 10:38:01 +020028# When tests are run from the Python build directory, it is best practice
29# to keep the test files in a subfolder. This eases the cleanup of leftover
30# files using the "make distclean" command.
31if sysconfig.is_python_build():
Victor Stinnerf7e07842017-06-15 00:44:05 +020032 TEMPDIR = sysconfig.get_config_var('abs_builddir')
33 if TEMPDIR is None:
34 # bpo-30284: On Windows, only srcdir is available. Using abs_builddir
35 # mostly matters on UNIX when building Python out of the source tree,
36 # especially when the source tree is read only.
37 TEMPDIR = sysconfig.get_config_var('srcdir')
38 TEMPDIR = os.path.join(TEMPDIR, 'build')
Victor Stinner3844fe52015-09-26 10:38:01 +020039else:
40 TEMPDIR = tempfile.gettempdir()
41TEMPDIR = os.path.abspath(TEMPDIR)
42
43
Victor Stinner435eaf42016-08-17 12:22:52 +020044def format_duration(seconds):
45 if seconds < 1.0:
46 return '%.0f ms' % (seconds * 1e3)
47 if seconds < 60.0:
48 return '%.0f sec' % seconds
49
50 minutes, seconds = divmod(seconds, 60.0)
51 return '%.0f min %.0f sec' % (minutes, seconds)
52
53
Victor Stinnerdad20e42015-09-29 22:48:52 +020054class Regrtest:
Victor Stinner3844fe52015-09-26 10:38:01 +020055 """Execute a test suite.
56
57 This also parses command-line options and modifies its behavior
58 accordingly.
59
60 tests -- a list of strings containing test names (optional)
61 testdir -- the directory in which to look for tests (optional)
62
63 Users other than the Python test suite will certainly want to
64 specify testdir; if it's omitted, the directory containing the
65 Python test suite is searched for.
66
67 If the tests argument is omitted, the tests listed on the
68 command-line will be used. If that's empty, too, then all *.py
69 files beginning with test_ will be used.
70
71 The other default arguments (verbose, quiet, exclude,
72 single, randomize, findleaks, use_resources, trace, coverdir,
73 print_slow, and random_seed) allow programmers calling main()
74 directly to set the values that would normally be set by flags
75 on the command line.
76 """
Victor Stinnerdad20e42015-09-29 22:48:52 +020077 def __init__(self):
78 # Namespace of command line options
79 self.ns = None
Victor Stinner3844fe52015-09-26 10:38:01 +020080
Victor Stinnerdad20e42015-09-29 22:48:52 +020081 # tests
82 self.tests = []
83 self.selected = []
Victor Stinner3844fe52015-09-26 10:38:01 +020084
Victor Stinnerdad20e42015-09-29 22:48:52 +020085 # test results
86 self.good = []
87 self.bad = []
88 self.skipped = []
89 self.resource_denieds = []
90 self.environment_changed = []
Victor Stinnerc6c05d02018-05-28 21:03:43 +020091 self.rerun = []
Victor Stinnerdad20e42015-09-29 22:48:52 +020092 self.interrupted = False
Victor Stinner3844fe52015-09-26 10:38:01 +020093
Victor Stinnerdad20e42015-09-29 22:48:52 +020094 # used by --slow
95 self.test_times = []
Victor Stinner3844fe52015-09-26 10:38:01 +020096
Victor Stinnerdad20e42015-09-29 22:48:52 +020097 # used by --coverage, trace.Trace instance
98 self.tracer = None
Victor Stinner3844fe52015-09-26 10:38:01 +020099
Victor Stinnerdad20e42015-09-29 22:48:52 +0200100 # used by --findleaks, store for gc.garbage
101 self.found_garbage = []
Victor Stinner3844fe52015-09-26 10:38:01 +0200102
Victor Stinnerdad20e42015-09-29 22:48:52 +0200103 # used to display the progress bar "[ 3/100]"
Victor Stinner24f949e2016-03-22 15:14:09 +0100104 self.start_time = time.monotonic()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200105 self.test_count = ''
106 self.test_count_width = 1
Victor Stinner3844fe52015-09-26 10:38:01 +0200107
Victor Stinnerdad20e42015-09-29 22:48:52 +0200108 # used by --single
109 self.next_single_test = None
110 self.next_single_filename = None
Victor Stinner3844fe52015-09-26 10:38:01 +0200111
Victor Stinnerdad20e42015-09-29 22:48:52 +0200112 def accumulate_result(self, test, result):
Victor Stinner3844fe52015-09-26 10:38:01 +0200113 ok, test_time = result
Victor Stinner3909e582015-10-11 10:37:25 +0200114 if ok not in (CHILD_ERROR, INTERRUPTED):
115 self.test_times.append((test_time, test))
Victor Stinner3844fe52015-09-26 10:38:01 +0200116 if ok == PASSED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200117 self.good.append(test)
Victor Stinner5bad70d2017-02-06 12:42:00 +0100118 elif ok in (FAILED, CHILD_ERROR):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200119 self.bad.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200120 elif ok == ENV_CHANGED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200121 self.environment_changed.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200122 elif ok == SKIPPED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200123 self.skipped.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200124 elif ok == RESOURCE_DENIED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200125 self.skipped.append(test)
126 self.resource_denieds.append(test)
Victor Stinner74683fc2017-05-09 11:34:01 +0200127 elif ok != INTERRUPTED:
128 raise ValueError("invalid test result: %r" % ok)
Victor Stinner3844fe52015-09-26 10:38:01 +0200129
Victor Stinnerdad20e42015-09-29 22:48:52 +0200130 def display_progress(self, test_index, test):
131 if self.ns.quiet:
132 return
Victor Stinner3d005682017-05-04 15:21:12 +0200133
134 # "[ 51/405/1] test_tcl passed"
135 line = f"{test_index:{self.test_count_width}}{self.test_count}"
Victor Stinnerb97d99c2017-08-10 16:19:03 +0200136 fails = len(self.bad) + len(self.environment_changed)
137 if fails and not self.ns.pgo:
138 line = f"{line}/{fails}"
Victor Stinner3d005682017-05-04 15:21:12 +0200139 line = f"[{line}] {test}"
140
141 # add the system load prefix: "load avg: 1.80 "
142 if hasattr(os, 'getloadavg'):
143 load_avg_1min = os.getloadavg()[0]
144 line = f"load avg: {load_avg_1min:.2f} {line}"
145
146 # add the timestamp prefix: "0:01:05 "
Victor Stinner435eaf42016-08-17 12:22:52 +0200147 test_time = time.monotonic() - self.start_time
148 test_time = datetime.timedelta(seconds=int(test_time))
Victor Stinner3d005682017-05-04 15:21:12 +0200149 line = f"{test_time} {line}"
Victor Stinner24f949e2016-03-22 15:14:09 +0100150 print(line, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200151
Victor Stinner234cbef2015-09-30 01:13:53 +0200152 def parse_args(self, kwargs):
153 ns = _parse_args(sys.argv[1:], **kwargs)
154
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200155 if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'):
156 print("Warning: The timeout option requires "
157 "faulthandler.dump_traceback_later", file=sys.stderr)
158 ns.timeout = None
159
Victor Stinner234cbef2015-09-30 01:13:53 +0200160 if ns.threshold is not None and gc is None:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200161 print('No GC available, ignore --threshold.', file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200162 ns.threshold = None
163
164 if ns.findleaks:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200165 if gc is not None:
166 # Uncomment the line below to report garbage that is not
167 # freeable by reference counting alone. By default only
168 # garbage that is not collectable by the GC is reported.
169 pass
170 #gc.set_debug(gc.DEBUG_SAVEALL)
171 else:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200172 print('No GC available, disabling --findleaks',
173 file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200174 ns.findleaks = False
Victor Stinnerdad20e42015-09-29 22:48:52 +0200175
Victor Stinnerdad20e42015-09-29 22:48:52 +0200176 # Strip .py extensions.
Victor Stinner234cbef2015-09-30 01:13:53 +0200177 removepy(ns.args)
178
179 return ns
Victor Stinnerdad20e42015-09-29 22:48:52 +0200180
Victor Stinnerdad20e42015-09-29 22:48:52 +0200181 def find_tests(self, tests):
182 self.tests = tests
183
184 if self.ns.single:
185 self.next_single_filename = os.path.join(TEMPDIR, 'pynexttest')
186 try:
187 with open(self.next_single_filename, 'r') as fp:
188 next_test = fp.read().strip()
189 self.tests = [next_test]
190 except OSError:
191 pass
192
193 if self.ns.fromfile:
194 self.tests = []
Victor Stinner5de16e82016-03-24 09:43:00 +0100195 # regex to match 'test_builtin' in line:
196 # '0:00:00 [ 4/400] test_builtin -- test_dict took 1 sec'
Victor Stinnere8cfec52017-01-03 01:38:58 +0100197 regex = re.compile(r'\btest_[a-zA-Z0-9_]+\b')
Victor Stinnerdad20e42015-09-29 22:48:52 +0200198 with open(os.path.join(support.SAVEDCWD, self.ns.fromfile)) as fp:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200199 for line in fp:
Victor Stinnerc24217e2016-12-09 16:05:51 +0100200 line = line.split('#', 1)[0]
Victor Stinner5de16e82016-03-24 09:43:00 +0100201 line = line.strip()
Victor Stinnerc24217e2016-12-09 16:05:51 +0100202 match = regex.search(line)
203 if match is not None:
Victor Stinnere8cfec52017-01-03 01:38:58 +0100204 self.tests.append(match.group())
Victor Stinnerdad20e42015-09-29 22:48:52 +0200205
206 removepy(self.tests)
207
208 stdtests = STDTESTS[:]
209 nottests = NOTTESTS.copy()
210 if self.ns.exclude:
211 for arg in self.ns.args:
212 if arg in stdtests:
213 stdtests.remove(arg)
214 nottests.add(arg)
215 self.ns.args = []
216
Victor Stinnerdad20e42015-09-29 22:48:52 +0200217 # if testdir is set, then we are not running the python tests suite, so
218 # don't add default tests to be executed or skipped (pass empty values)
219 if self.ns.testdir:
220 alltests = findtests(self.ns.testdir, list(), set())
221 else:
222 alltests = findtests(self.ns.testdir, stdtests, nottests)
223
Victor Stinner5de16e82016-03-24 09:43:00 +0100224 if not self.ns.fromfile:
225 self.selected = self.tests or self.ns.args or alltests
226 else:
227 self.selected = self.tests
Victor Stinnerdad20e42015-09-29 22:48:52 +0200228 if self.ns.single:
229 self.selected = self.selected[:1]
230 try:
231 pos = alltests.index(self.selected[0])
232 self.next_single_test = alltests[pos + 1]
233 except IndexError:
234 pass
235
Victor Stinnerc7eab052015-09-30 00:59:35 +0200236 # Remove all the selected tests that precede start if it's set.
Victor Stinnerdad20e42015-09-29 22:48:52 +0200237 if self.ns.start:
238 try:
239 del self.selected[:self.selected.index(self.ns.start)]
240 except ValueError:
Victor Stinner6448b802015-09-29 23:43:33 +0200241 print("Couldn't find starting test (%s), using all tests"
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200242 % self.ns.start, file=sys.stderr)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200243
244 if self.ns.randomize:
245 if self.ns.random_seed is None:
246 self.ns.random_seed = random.randrange(10000000)
247 random.seed(self.ns.random_seed)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200248 random.shuffle(self.selected)
249
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200250 def list_tests(self):
251 for name in self.selected:
252 print(name)
253
mlouielua49c9352017-06-16 17:36:19 +0800254 def _list_cases(self, suite):
255 for test in suite:
256 if isinstance(test, unittest.loader._FailedTest):
257 continue
258 if isinstance(test, unittest.TestSuite):
259 self._list_cases(test)
260 elif isinstance(test, unittest.TestCase):
Victor Stinner803ddd82017-11-21 15:34:02 -0800261 if support.match_test(test):
Victor Stinnerace56d52017-06-26 14:18:51 +0200262 print(test.id())
mlouielua49c9352017-06-16 17:36:19 +0800263
264 def list_cases(self):
Victor Stinnerace56d52017-06-26 14:18:51 +0200265 support.verbose = False
Victor Stinner803ddd82017-11-21 15:34:02 -0800266 support.set_match_tests(self.ns.match_tests)
Victor Stinnerace56d52017-06-26 14:18:51 +0200267
mlouielua49c9352017-06-16 17:36:19 +0800268 for test in self.selected:
269 abstest = get_abs_module(self.ns, test)
270 try:
271 suite = unittest.defaultTestLoader.loadTestsFromName(abstest)
272 self._list_cases(suite)
273 except unittest.SkipTest:
274 self.skipped.append(test)
275
276 if self.skipped:
277 print(file=sys.stderr)
278 print(count(len(self.skipped), "test"), "skipped:", file=sys.stderr)
279 printlist(self.skipped, file=sys.stderr)
280
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200281 def rerun_failed_tests(self):
282 self.ns.verbose = True
283 self.ns.failfast = False
284 self.ns.verbose3 = False
285 self.ns.match_tests = None
286
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200287 print()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200288 print("Re-running failed tests in verbose mode")
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200289 self.rerun = self.bad[:]
290 for test in self.rerun:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200291 print("Re-running test %r in verbose mode" % test, flush=True)
292 try:
293 self.ns.verbose = True
294 ok = runtest(self.ns, test)
295 except KeyboardInterrupt:
Victor Stinnerc5a01f82016-08-17 16:00:12 +0200296 self.interrupted = True
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200297 # print a newline separate from the ^C
298 print()
299 break
300 else:
301 if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}:
302 self.bad.remove(test)
303 else:
304 if self.bad:
305 print(count(len(self.bad), 'test'), "failed again:")
306 printlist(self.bad)
307
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200308 self.display_result()
309
Victor Stinnerdad20e42015-09-29 22:48:52 +0200310 def display_result(self):
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200311 # If running the test suite for PGO then no one cares about results.
312 if self.ns.pgo:
313 return
314
315 print()
316 print("== Tests result ==")
317
Victor Stinnerdad20e42015-09-29 22:48:52 +0200318 if self.interrupted:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200319 print()
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200320 # print a newline after ^C
Victor Stinnerdad20e42015-09-29 22:48:52 +0200321 print("Test suite interrupted by signal SIGINT.")
Victor Stinner6448b802015-09-29 23:43:33 +0200322 executed = set(self.good) | set(self.bad) | set(self.skipped)
323 omitted = set(self.selected) - executed
Victor Stinnerdad20e42015-09-29 22:48:52 +0200324 print(count(len(omitted), "test"), "omitted:")
325 printlist(omitted)
326
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200327 if self.rerun:
328 print()
329 print(count(len(self.rerun), "test"), "re-run tests:")
330 printlist(self.rerun)
Brett Cannon11faa212015-10-02 16:20:49 -0700331
Victor Stinnerdad20e42015-09-29 22:48:52 +0200332 if self.good and not self.ns.quiet:
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200333 print()
Victor Stinner6448b802015-09-29 23:43:33 +0200334 if (not self.bad
335 and not self.skipped
336 and not self.interrupted
337 and len(self.good) > 1):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200338 print("All", end=' ')
339 print(count(len(self.good), "test"), "OK.")
340
341 if self.ns.print_slow:
342 self.test_times.sort(reverse=True)
Victor Stinner435eaf42016-08-17 12:22:52 +0200343 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200344 print("10 slowest tests:")
345 for time, test in self.test_times[:10]:
Victor Stinner435eaf42016-08-17 12:22:52 +0200346 print("- %s: %s" % (test, format_duration(time)))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200347
348 if self.bad:
Victor Stinner8f003192016-08-17 15:42:21 +0200349 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200350 print(count(len(self.bad), "test"), "failed:")
351 printlist(self.bad)
352
353 if self.environment_changed:
Victor Stinner8f003192016-08-17 15:42:21 +0200354 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200355 print("{} altered the execution environment:".format(
356 count(len(self.environment_changed), "test")))
357 printlist(self.environment_changed)
358
359 if self.skipped and not self.ns.quiet:
Victor Stinner8f003192016-08-17 15:42:21 +0200360 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200361 print(count(len(self.skipped), "test"), "skipped:")
362 printlist(self.skipped)
363
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200364 def run_tests_sequential(self):
Victor Stinnerc7eab052015-09-30 00:59:35 +0200365 if self.ns.trace:
366 import trace
Victor Stinnera53a8182015-10-01 00:53:09 +0200367 self.tracer = trace.Trace(trace=False, count=True)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200368
Victor Stinnerdad20e42015-09-29 22:48:52 +0200369 save_modules = sys.modules.keys()
370
Victor Stinner2b60b722016-03-24 11:55:29 +0100371 print("Run tests sequentially")
372
Victor Stinner69649f22016-03-23 12:14:10 +0100373 previous_test = None
Victor Stinnerdad20e42015-09-29 22:48:52 +0200374 for test_index, test in enumerate(self.tests, 1):
Victor Stinner69649f22016-03-23 12:14:10 +0100375 start_time = time.monotonic()
376
377 text = test
378 if previous_test:
379 text = '%s -- %s' % (text, previous_test)
380 self.display_progress(test_index, text)
381
Victor Stinnerc7eab052015-09-30 00:59:35 +0200382 if self.tracer:
Victor Stinner3844fe52015-09-26 10:38:01 +0200383 # If we're tracing code coverage, then we don't exit with status
384 # if on a false return value from main.
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200385 cmd = ('result = runtest(self.ns, test); '
386 'self.accumulate_result(test, result)')
Victor Stinner1b8b4232016-05-20 13:37:40 +0200387 ns = dict(locals())
388 self.tracer.runctx(cmd, globals=globals(), locals=ns)
389 result = ns['result']
Victor Stinner3844fe52015-09-26 10:38:01 +0200390 else:
391 try:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200392 result = runtest(self.ns, test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200393 except KeyboardInterrupt:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200394 self.interrupted = True
Victor Stinnerc5a01f82016-08-17 16:00:12 +0200395 self.accumulate_result(test, (INTERRUPTED, None))
Victor Stinner3844fe52015-09-26 10:38:01 +0200396 break
Victor Stinner3909e582015-10-11 10:37:25 +0200397 else:
398 self.accumulate_result(test, result)
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200399
Victor Stinner1b8b4232016-05-20 13:37:40 +0200400 previous_test = format_test_result(test, result[0])
Victor Stinner69649f22016-03-23 12:14:10 +0100401 test_time = time.monotonic() - start_time
402 if test_time >= PROGRESS_MIN_TIME:
Victor Stinner435eaf42016-08-17 12:22:52 +0200403 previous_test = "%s in %s" % (previous_test, format_duration(test_time))
Victor Stinner1b8b4232016-05-20 13:37:40 +0200404 elif result[0] == PASSED:
405 # be quiet: say nothing if the test passed shortly
Victor Stinner69649f22016-03-23 12:14:10 +0100406 previous_test = None
407
Victor Stinnerdad20e42015-09-29 22:48:52 +0200408 if self.ns.findleaks:
Victor Stinner3844fe52015-09-26 10:38:01 +0200409 gc.collect()
410 if gc.garbage:
411 print("Warning: test created", len(gc.garbage), end=' ')
412 print("uncollectable object(s).")
413 # move the uncollectable objects somewhere so we don't see
414 # them again
Victor Stinnerdad20e42015-09-29 22:48:52 +0200415 self.found_garbage.extend(gc.garbage)
Victor Stinner3844fe52015-09-26 10:38:01 +0200416 del gc.garbage[:]
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200417
Victor Stinner3844fe52015-09-26 10:38:01 +0200418 # Unload the newly imported modules (best effort finalization)
419 for module in sys.modules.keys():
420 if module not in save_modules and module.startswith("test."):
421 support.unload(module)
422
Victor Stinner69649f22016-03-23 12:14:10 +0100423 if previous_test:
424 print(previous_test)
425
Victor Stinnerb4084352015-09-30 02:39:22 +0200426 def _test_forever(self, tests):
427 while True:
428 for test in tests:
429 yield test
430 if self.bad:
431 return
Victor Stinner5e875922017-07-03 11:15:58 +0200432 if self.ns.fail_env_changed and self.environment_changed:
433 return
Victor Stinner3844fe52015-09-26 10:38:01 +0200434
Victor Stinner3d005682017-05-04 15:21:12 +0200435 def display_header(self):
436 # Print basic platform information
437 print("==", platform.python_implementation(), *sys.version.split())
438 print("==", platform.platform(aliased=True),
439 "%s-endian" % sys.byteorder)
Victor Stinner3d005682017-05-04 15:21:12 +0200440 print("== cwd:", os.getcwd())
441 cpu_count = os.cpu_count()
442 if cpu_count:
443 print("== CPU count:", cpu_count)
444 print("== encodings: locale=%s, FS=%s"
445 % (locale.getpreferredencoding(False),
446 sys.getfilesystemencoding()))
Victor Stinner3d005682017-05-04 15:21:12 +0200447
Victor Stinnerb4084352015-09-30 02:39:22 +0200448 def run_tests(self):
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200449 # For a partial run, we do not need to clutter the output.
Victor Stinner3d005682017-05-04 15:21:12 +0200450 if (self.ns.header
451 or not(self.ns.pgo or self.ns.quiet or self.ns.single
452 or self.tests or self.ns.args)):
453 self.display_header()
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200454
455 if self.ns.randomize:
456 print("Using random seed", self.ns.random_seed)
457
Victor Stinnerdad20e42015-09-29 22:48:52 +0200458 if self.ns.forever:
Victor Stinner9a142142015-09-30 13:51:17 +0200459 self.tests = self._test_forever(list(self.selected))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200460 self.test_count = ''
461 self.test_count_width = 3
462 else:
463 self.tests = iter(self.selected)
464 self.test_count = '/{}'.format(len(self.selected))
465 self.test_count_width = len(self.test_count) - 1
466
467 if self.ns.use_mp:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200468 from test.libregrtest.runtest_mp import run_tests_multiprocess
469 run_tests_multiprocess(self)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200470 else:
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200471 self.run_tests_sequential()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200472
473 def finalize(self):
474 if self.next_single_filename:
475 if self.next_single_test:
476 with open(self.next_single_filename, 'w') as fp:
477 fp.write(self.next_single_test + '\n')
Victor Stinner3844fe52015-09-26 10:38:01 +0200478 else:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200479 os.unlink(self.next_single_filename)
Victor Stinner3844fe52015-09-26 10:38:01 +0200480
Victor Stinnerc7eab052015-09-30 00:59:35 +0200481 if self.tracer:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200482 r = self.tracer.results()
483 r.write_results(show_missing=True, summary=True,
484 coverdir=self.ns.coverdir)
Victor Stinner3844fe52015-09-26 10:38:01 +0200485
Victor Stinner435eaf42016-08-17 12:22:52 +0200486 print()
487 duration = time.monotonic() - self.start_time
488 print("Total duration: %s" % format_duration(duration))
Victor Stinner24f949e2016-03-22 15:14:09 +0100489
Victor Stinner63686032016-08-17 16:12:16 +0200490 if self.bad:
491 result = "FAILURE"
492 elif self.interrupted:
493 result = "INTERRUPTED"
Victor Stinner5e875922017-07-03 11:15:58 +0200494 elif self.ns.fail_env_changed and self.environment_changed:
Victor Stinner63f54c62017-06-26 18:33:19 +0200495 result = "ENV CHANGED"
Victor Stinner63686032016-08-17 16:12:16 +0200496 else:
497 result = "SUCCESS"
Victor Stinnerf2abf5c2016-08-19 17:54:25 +0200498 print("Tests result: %s" % result)
Victor Stinner63686032016-08-17 16:12:16 +0200499
Victor Stinnerdad20e42015-09-29 22:48:52 +0200500 if self.ns.runleaks:
501 os.system("leaks %d" % os.getpid())
Victor Stinner3844fe52015-09-26 10:38:01 +0200502
Victor Stinnerdad20e42015-09-29 22:48:52 +0200503 def main(self, tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100504 global TEMPDIR
505
506 if sysconfig.is_python_build():
507 try:
508 os.mkdir(TEMPDIR)
509 except FileExistsError:
510 pass
511
512 # Define a writable temp dir that will be used as cwd while running
513 # the tests. The name of the dir includes the pid to allow parallel
514 # testing (see the -j option).
515 test_cwd = 'test_python_{}'.format(os.getpid())
516 test_cwd = os.path.join(TEMPDIR, test_cwd)
517
518 # Run the tests in a context manager that temporarily changes the CWD to a
519 # temporary and writable directory. If it's not possible to create or
520 # change the CWD, the original CWD will be used. The original CWD is
521 # available from support.SAVEDCWD.
522 with support.temp_cwd(test_cwd, quiet=True):
523 self._main(tests, kwargs)
524
525 def _main(self, tests, kwargs):
Victor Stinner234cbef2015-09-30 01:13:53 +0200526 self.ns = self.parse_args(kwargs)
527
Victor Stinnerdad20e42015-09-29 22:48:52 +0200528 if self.ns.slaveargs is not None:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200529 from test.libregrtest.runtest_mp import run_tests_slave
530 run_tests_slave(self.ns.slaveargs)
Victor Stinnerecef6222015-09-30 01:39:28 +0200531
Victor Stinnerc7eab052015-09-30 00:59:35 +0200532 if self.ns.wait:
533 input("Press any key to continue...")
534
Steve Dower22d06982016-09-06 19:38:15 -0700535 support.PGO = self.ns.pgo
536
Victor Stinnera2045022015-09-30 02:17:28 +0200537 setup_tests(self.ns)
Victor Stinnerecef6222015-09-30 01:39:28 +0200538
Victor Stinnerdad20e42015-09-29 22:48:52 +0200539 self.find_tests(tests)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200540
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200541 if self.ns.list_tests:
542 self.list_tests()
543 sys.exit(0)
544
mlouielua49c9352017-06-16 17:36:19 +0800545 if self.ns.list_cases:
546 self.list_cases()
547 sys.exit(0)
548
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200549 self.run_tests()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200550 self.display_result()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200551
552 if self.ns.verbose2 and self.bad:
553 self.rerun_failed_tests()
554
Victor Stinnerdad20e42015-09-29 22:48:52 +0200555 self.finalize()
Victor Stinner63f54c62017-06-26 18:33:19 +0200556 if self.bad:
557 sys.exit(2)
558 if self.interrupted:
559 sys.exit(130)
560 if self.ns.fail_env_changed and self.environment_changed:
561 sys.exit(3)
562 sys.exit(0)
Victor Stinner3844fe52015-09-26 10:38:01 +0200563
564
Victor Stinner3844fe52015-09-26 10:38:01 +0200565def removepy(names):
566 if not names:
567 return
568 for idx, name in enumerate(names):
569 basename, ext = os.path.splitext(name)
570 if ext == '.py':
571 names[idx] = basename
572
573
574def count(n, word):
575 if n == 1:
576 return "%d %s" % (n, word)
577 else:
578 return "%d %ss" % (n, word)
579
580
mlouielua49c9352017-06-16 17:36:19 +0800581def printlist(x, width=70, indent=4, file=None):
Victor Stinner3844fe52015-09-26 10:38:01 +0200582 """Print the elements of iterable x to stdout.
583
584 Optional arg width (default 70) is the maximum line length.
585 Optional arg indent (default 4) is the number of blanks with which to
586 begin each line.
587 """
588
Victor Stinner3844fe52015-09-26 10:38:01 +0200589 blanks = ' ' * indent
590 # Print the sorted list: 'x' may be a '--random' list or a set()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200591 print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width,
mlouielua49c9352017-06-16 17:36:19 +0800592 initial_indent=blanks, subsequent_indent=blanks),
593 file=file)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200594
595
596def main(tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100597 """Run the Python suite."""
Victor Stinnerdad20e42015-09-29 22:48:52 +0200598 Regrtest().main(tests=tests, **kwargs)