blob: f0c1631509bd9f44f0434335712feeb1e27e8862 [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
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200285
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200286 print()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200287 print("Re-running failed tests in verbose mode")
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200288 self.rerun = self.bad[:]
289 for test in self.rerun:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200290 print("Re-running test %r in verbose mode" % test, flush=True)
291 try:
292 self.ns.verbose = True
293 ok = runtest(self.ns, test)
294 except KeyboardInterrupt:
Victor Stinnerc5a01f82016-08-17 16:00:12 +0200295 self.interrupted = True
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200296 # print a newline separate from the ^C
297 print()
298 break
299 else:
300 if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}:
301 self.bad.remove(test)
302 else:
303 if self.bad:
304 print(count(len(self.bad), 'test'), "failed again:")
305 printlist(self.bad)
306
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200307 self.display_result()
308
Victor Stinnerdad20e42015-09-29 22:48:52 +0200309 def display_result(self):
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200310 # If running the test suite for PGO then no one cares about results.
311 if self.ns.pgo:
312 return
313
314 print()
Victor Stinner9e249302018-06-01 00:48:57 +0200315 print("== Tests result: %s ==" % self.get_tests_result())
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200316
Victor Stinnerdad20e42015-09-29 22:48:52 +0200317 if self.interrupted:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200318 print()
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200319 # print a newline after ^C
Victor Stinnerdad20e42015-09-29 22:48:52 +0200320 print("Test suite interrupted by signal SIGINT.")
Victor Stinner6448b802015-09-29 23:43:33 +0200321 executed = set(self.good) | set(self.bad) | set(self.skipped)
322 omitted = set(self.selected) - executed
Victor Stinnerdad20e42015-09-29 22:48:52 +0200323 print(count(len(omitted), "test"), "omitted:")
324 printlist(omitted)
325
326 if self.good and not self.ns.quiet:
Victor Stinnerc6c05d02018-05-28 21:03:43 +0200327 print()
Victor Stinner6448b802015-09-29 23:43:33 +0200328 if (not self.bad
329 and not self.skipped
330 and not self.interrupted
331 and len(self.good) > 1):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200332 print("All", end=' ')
333 print(count(len(self.good), "test"), "OK.")
334
335 if self.ns.print_slow:
336 self.test_times.sort(reverse=True)
Victor Stinner435eaf42016-08-17 12:22:52 +0200337 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200338 print("10 slowest tests:")
339 for time, test in self.test_times[:10]:
Victor Stinner435eaf42016-08-17 12:22:52 +0200340 print("- %s: %s" % (test, format_duration(time)))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200341
342 if self.bad:
Victor Stinner8f003192016-08-17 15:42:21 +0200343 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200344 print(count(len(self.bad), "test"), "failed:")
345 printlist(self.bad)
346
347 if self.environment_changed:
Victor Stinner8f003192016-08-17 15:42:21 +0200348 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200349 print("{} altered the execution environment:".format(
350 count(len(self.environment_changed), "test")))
351 printlist(self.environment_changed)
352
353 if self.skipped and not self.ns.quiet:
Victor Stinner8f003192016-08-17 15:42:21 +0200354 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200355 print(count(len(self.skipped), "test"), "skipped:")
356 printlist(self.skipped)
357
Victor Stinner9e249302018-06-01 00:48:57 +0200358 if self.rerun:
359 print()
360 print("%s:" % count(len(self.rerun), "re-run test"))
361 printlist(self.rerun)
362
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200363 def run_tests_sequential(self):
Victor Stinnerc7eab052015-09-30 00:59:35 +0200364 if self.ns.trace:
365 import trace
Victor Stinnera53a8182015-10-01 00:53:09 +0200366 self.tracer = trace.Trace(trace=False, count=True)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200367
Victor Stinnerdad20e42015-09-29 22:48:52 +0200368 save_modules = sys.modules.keys()
369
Victor Stinner2b60b722016-03-24 11:55:29 +0100370 print("Run tests sequentially")
371
Victor Stinner69649f22016-03-23 12:14:10 +0100372 previous_test = None
Victor Stinnerdad20e42015-09-29 22:48:52 +0200373 for test_index, test in enumerate(self.tests, 1):
Victor Stinner69649f22016-03-23 12:14:10 +0100374 start_time = time.monotonic()
375
376 text = test
377 if previous_test:
378 text = '%s -- %s' % (text, previous_test)
379 self.display_progress(test_index, text)
380
Victor Stinnerc7eab052015-09-30 00:59:35 +0200381 if self.tracer:
Victor Stinner3844fe52015-09-26 10:38:01 +0200382 # If we're tracing code coverage, then we don't exit with status
383 # if on a false return value from main.
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200384 cmd = ('result = runtest(self.ns, test); '
385 'self.accumulate_result(test, result)')
Victor Stinner1b8b4232016-05-20 13:37:40 +0200386 ns = dict(locals())
387 self.tracer.runctx(cmd, globals=globals(), locals=ns)
388 result = ns['result']
Victor Stinner3844fe52015-09-26 10:38:01 +0200389 else:
390 try:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200391 result = runtest(self.ns, test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200392 except KeyboardInterrupt:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200393 self.interrupted = True
Victor Stinnerc5a01f82016-08-17 16:00:12 +0200394 self.accumulate_result(test, (INTERRUPTED, None))
Victor Stinner3844fe52015-09-26 10:38:01 +0200395 break
Victor Stinner3909e582015-10-11 10:37:25 +0200396 else:
397 self.accumulate_result(test, result)
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200398
Victor Stinner1b8b4232016-05-20 13:37:40 +0200399 previous_test = format_test_result(test, result[0])
Victor Stinner69649f22016-03-23 12:14:10 +0100400 test_time = time.monotonic() - start_time
401 if test_time >= PROGRESS_MIN_TIME:
Victor Stinner435eaf42016-08-17 12:22:52 +0200402 previous_test = "%s in %s" % (previous_test, format_duration(test_time))
Victor Stinner1b8b4232016-05-20 13:37:40 +0200403 elif result[0] == PASSED:
404 # be quiet: say nothing if the test passed shortly
Victor Stinner69649f22016-03-23 12:14:10 +0100405 previous_test = None
406
Victor Stinnerdad20e42015-09-29 22:48:52 +0200407 if self.ns.findleaks:
Victor Stinner3844fe52015-09-26 10:38:01 +0200408 gc.collect()
409 if gc.garbage:
410 print("Warning: test created", len(gc.garbage), end=' ')
411 print("uncollectable object(s).")
412 # move the uncollectable objects somewhere so we don't see
413 # them again
Victor Stinnerdad20e42015-09-29 22:48:52 +0200414 self.found_garbage.extend(gc.garbage)
Victor Stinner3844fe52015-09-26 10:38:01 +0200415 del gc.garbage[:]
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200416
Victor Stinner3844fe52015-09-26 10:38:01 +0200417 # Unload the newly imported modules (best effort finalization)
418 for module in sys.modules.keys():
419 if module not in save_modules and module.startswith("test."):
420 support.unload(module)
421
Victor Stinner69649f22016-03-23 12:14:10 +0100422 if previous_test:
423 print(previous_test)
424
Victor Stinnerb4084352015-09-30 02:39:22 +0200425 def _test_forever(self, tests):
426 while True:
427 for test in tests:
428 yield test
429 if self.bad:
430 return
Victor Stinner5e875922017-07-03 11:15:58 +0200431 if self.ns.fail_env_changed and self.environment_changed:
432 return
Victor Stinner3844fe52015-09-26 10:38:01 +0200433
Victor Stinner3d005682017-05-04 15:21:12 +0200434 def display_header(self):
435 # Print basic platform information
436 print("==", platform.python_implementation(), *sys.version.split())
437 print("==", platform.platform(aliased=True),
438 "%s-endian" % sys.byteorder)
Victor Stinner3d005682017-05-04 15:21:12 +0200439 print("== cwd:", os.getcwd())
440 cpu_count = os.cpu_count()
441 if cpu_count:
442 print("== CPU count:", cpu_count)
443 print("== encodings: locale=%s, FS=%s"
444 % (locale.getpreferredencoding(False),
445 sys.getfilesystemencoding()))
Victor Stinner3d005682017-05-04 15:21:12 +0200446
Victor Stinner9e249302018-06-01 00:48:57 +0200447 def get_tests_result(self):
448 result = []
449 if self.bad:
450 result.append("FAILURE")
451 elif self.ns.fail_env_changed and self.environment_changed:
452 result.append("ENV CHANGED")
453
454 if self.interrupted:
455 result.append("INTERRUPTED")
456
457 if not result:
458 result.append("SUCCESS")
459
460 return ', '.join(result)
461
Victor Stinnerb4084352015-09-30 02:39:22 +0200462 def run_tests(self):
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200463 # For a partial run, we do not need to clutter the output.
Victor Stinner3d005682017-05-04 15:21:12 +0200464 if (self.ns.header
465 or not(self.ns.pgo or self.ns.quiet or self.ns.single
466 or self.tests or self.ns.args)):
467 self.display_header()
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200468
469 if self.ns.randomize:
470 print("Using random seed", self.ns.random_seed)
471
Victor Stinnerdad20e42015-09-29 22:48:52 +0200472 if self.ns.forever:
Victor Stinner9a142142015-09-30 13:51:17 +0200473 self.tests = self._test_forever(list(self.selected))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200474 self.test_count = ''
475 self.test_count_width = 3
476 else:
477 self.tests = iter(self.selected)
478 self.test_count = '/{}'.format(len(self.selected))
479 self.test_count_width = len(self.test_count) - 1
480
481 if self.ns.use_mp:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200482 from test.libregrtest.runtest_mp import run_tests_multiprocess
483 run_tests_multiprocess(self)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200484 else:
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200485 self.run_tests_sequential()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200486
487 def finalize(self):
488 if self.next_single_filename:
489 if self.next_single_test:
490 with open(self.next_single_filename, 'w') as fp:
491 fp.write(self.next_single_test + '\n')
Victor Stinner3844fe52015-09-26 10:38:01 +0200492 else:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200493 os.unlink(self.next_single_filename)
Victor Stinner3844fe52015-09-26 10:38:01 +0200494
Victor Stinnerc7eab052015-09-30 00:59:35 +0200495 if self.tracer:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200496 r = self.tracer.results()
497 r.write_results(show_missing=True, summary=True,
498 coverdir=self.ns.coverdir)
Victor Stinner3844fe52015-09-26 10:38:01 +0200499
Victor Stinner435eaf42016-08-17 12:22:52 +0200500 print()
501 duration = time.monotonic() - self.start_time
502 print("Total duration: %s" % format_duration(duration))
Victor Stinner9e249302018-06-01 00:48:57 +0200503 print("Tests result: %s" % self.get_tests_result())
Victor Stinner63686032016-08-17 16:12:16 +0200504
Victor Stinnerdad20e42015-09-29 22:48:52 +0200505 if self.ns.runleaks:
506 os.system("leaks %d" % os.getpid())
Victor Stinner3844fe52015-09-26 10:38:01 +0200507
Victor Stinnerdad20e42015-09-29 22:48:52 +0200508 def main(self, tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100509 global TEMPDIR
510
511 if sysconfig.is_python_build():
512 try:
513 os.mkdir(TEMPDIR)
514 except FileExistsError:
515 pass
516
517 # Define a writable temp dir that will be used as cwd while running
518 # the tests. The name of the dir includes the pid to allow parallel
519 # testing (see the -j option).
520 test_cwd = 'test_python_{}'.format(os.getpid())
521 test_cwd = os.path.join(TEMPDIR, test_cwd)
522
523 # Run the tests in a context manager that temporarily changes the CWD to a
524 # temporary and writable directory. If it's not possible to create or
525 # change the CWD, the original CWD will be used. The original CWD is
526 # available from support.SAVEDCWD.
527 with support.temp_cwd(test_cwd, quiet=True):
528 self._main(tests, kwargs)
529
530 def _main(self, tests, kwargs):
Victor Stinner234cbef2015-09-30 01:13:53 +0200531 self.ns = self.parse_args(kwargs)
532
Victor Stinnerdad20e42015-09-29 22:48:52 +0200533 if self.ns.slaveargs is not None:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200534 from test.libregrtest.runtest_mp import run_tests_slave
535 run_tests_slave(self.ns.slaveargs)
Victor Stinnerecef6222015-09-30 01:39:28 +0200536
Victor Stinnerc7eab052015-09-30 00:59:35 +0200537 if self.ns.wait:
538 input("Press any key to continue...")
539
Steve Dower22d06982016-09-06 19:38:15 -0700540 support.PGO = self.ns.pgo
541
Victor Stinnera2045022015-09-30 02:17:28 +0200542 setup_tests(self.ns)
Victor Stinnerecef6222015-09-30 01:39:28 +0200543
Victor Stinnerdad20e42015-09-29 22:48:52 +0200544 self.find_tests(tests)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200545
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200546 if self.ns.list_tests:
547 self.list_tests()
548 sys.exit(0)
549
mlouielua49c9352017-06-16 17:36:19 +0800550 if self.ns.list_cases:
551 self.list_cases()
552 sys.exit(0)
553
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200554 self.run_tests()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200555 self.display_result()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200556
557 if self.ns.verbose2 and self.bad:
558 self.rerun_failed_tests()
559
Victor Stinnerdad20e42015-09-29 22:48:52 +0200560 self.finalize()
Victor Stinner63f54c62017-06-26 18:33:19 +0200561 if self.bad:
562 sys.exit(2)
563 if self.interrupted:
564 sys.exit(130)
565 if self.ns.fail_env_changed and self.environment_changed:
566 sys.exit(3)
567 sys.exit(0)
Victor Stinner3844fe52015-09-26 10:38:01 +0200568
569
Victor Stinner3844fe52015-09-26 10:38:01 +0200570def removepy(names):
571 if not names:
572 return
573 for idx, name in enumerate(names):
574 basename, ext = os.path.splitext(name)
575 if ext == '.py':
576 names[idx] = basename
577
578
579def count(n, word):
580 if n == 1:
581 return "%d %s" % (n, word)
582 else:
583 return "%d %ss" % (n, word)
584
585
mlouielua49c9352017-06-16 17:36:19 +0800586def printlist(x, width=70, indent=4, file=None):
Victor Stinner3844fe52015-09-26 10:38:01 +0200587 """Print the elements of iterable x to stdout.
588
589 Optional arg width (default 70) is the maximum line length.
590 Optional arg indent (default 4) is the number of blanks with which to
591 begin each line.
592 """
593
Victor Stinner3844fe52015-09-26 10:38:01 +0200594 blanks = ' ' * indent
595 # Print the sorted list: 'x' may be a '--random' list or a set()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200596 print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width,
mlouielua49c9352017-06-16 17:36:19 +0800597 initial_indent=blanks, subsequent_indent=blanks),
598 file=file)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200599
600
601def main(tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100602 """Run the Python suite."""
Victor Stinnerdad20e42015-09-29 22:48:52 +0200603 Regrtest().main(tests=tests, **kwargs)