blob: 0b48bebb0d7f1e12d3e828ddfdc6cd26d3cf3f95 [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 = []
91 self.interrupted = False
Victor Stinner3844fe52015-09-26 10:38:01 +020092
Victor Stinnerdad20e42015-09-29 22:48:52 +020093 # used by --slow
94 self.test_times = []
Victor Stinner3844fe52015-09-26 10:38:01 +020095
Victor Stinnerdad20e42015-09-29 22:48:52 +020096 # used by --coverage, trace.Trace instance
97 self.tracer = None
Victor Stinner3844fe52015-09-26 10:38:01 +020098
Victor Stinnerdad20e42015-09-29 22:48:52 +020099 # used by --findleaks, store for gc.garbage
100 self.found_garbage = []
Victor Stinner3844fe52015-09-26 10:38:01 +0200101
Victor Stinnerdad20e42015-09-29 22:48:52 +0200102 # used to display the progress bar "[ 3/100]"
Victor Stinner24f949e2016-03-22 15:14:09 +0100103 self.start_time = time.monotonic()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200104 self.test_count = ''
105 self.test_count_width = 1
Victor Stinner3844fe52015-09-26 10:38:01 +0200106
Victor Stinnerdad20e42015-09-29 22:48:52 +0200107 # used by --single
108 self.next_single_test = None
109 self.next_single_filename = None
Victor Stinner3844fe52015-09-26 10:38:01 +0200110
Victor Stinnerdad20e42015-09-29 22:48:52 +0200111 def accumulate_result(self, test, result):
Victor Stinner3844fe52015-09-26 10:38:01 +0200112 ok, test_time = result
Victor Stinner3909e582015-10-11 10:37:25 +0200113 if ok not in (CHILD_ERROR, INTERRUPTED):
114 self.test_times.append((test_time, test))
Victor Stinner3844fe52015-09-26 10:38:01 +0200115 if ok == PASSED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200116 self.good.append(test)
Victor Stinner5bad70d2017-02-06 12:42:00 +0100117 elif ok in (FAILED, CHILD_ERROR):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200118 self.bad.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200119 elif ok == ENV_CHANGED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200120 self.environment_changed.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200121 elif ok == SKIPPED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200122 self.skipped.append(test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200123 elif ok == RESOURCE_DENIED:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200124 self.skipped.append(test)
125 self.resource_denieds.append(test)
Victor Stinner74683fc2017-05-09 11:34:01 +0200126 elif ok != INTERRUPTED:
127 raise ValueError("invalid test result: %r" % ok)
Victor Stinner3844fe52015-09-26 10:38:01 +0200128
Victor Stinnerdad20e42015-09-29 22:48:52 +0200129 def display_progress(self, test_index, test):
130 if self.ns.quiet:
131 return
Victor Stinner3d005682017-05-04 15:21:12 +0200132
133 # "[ 51/405/1] test_tcl passed"
134 line = f"{test_index:{self.test_count_width}}{self.test_count}"
Victor Stinnerb97d99c2017-08-10 16:19:03 +0200135 fails = len(self.bad) + len(self.environment_changed)
136 if fails and not self.ns.pgo:
137 line = f"{line}/{fails}"
Victor Stinner3d005682017-05-04 15:21:12 +0200138 line = f"[{line}] {test}"
139
140 # add the system load prefix: "load avg: 1.80 "
141 if hasattr(os, 'getloadavg'):
142 load_avg_1min = os.getloadavg()[0]
143 line = f"load avg: {load_avg_1min:.2f} {line}"
144
145 # add the timestamp prefix: "0:01:05 "
Victor Stinner435eaf42016-08-17 12:22:52 +0200146 test_time = time.monotonic() - self.start_time
147 test_time = datetime.timedelta(seconds=int(test_time))
Victor Stinner3d005682017-05-04 15:21:12 +0200148 line = f"{test_time} {line}"
Victor Stinner24f949e2016-03-22 15:14:09 +0100149 print(line, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200150
Victor Stinner234cbef2015-09-30 01:13:53 +0200151 def parse_args(self, kwargs):
152 ns = _parse_args(sys.argv[1:], **kwargs)
153
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200154 if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'):
155 print("Warning: The timeout option requires "
156 "faulthandler.dump_traceback_later", file=sys.stderr)
157 ns.timeout = None
158
Victor Stinner234cbef2015-09-30 01:13:53 +0200159 if ns.threshold is not None and gc is None:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200160 print('No GC available, ignore --threshold.', file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200161 ns.threshold = None
162
163 if ns.findleaks:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200164 if gc is not None:
165 # Uncomment the line below to report garbage that is not
166 # freeable by reference counting alone. By default only
167 # garbage that is not collectable by the GC is reported.
168 pass
169 #gc.set_debug(gc.DEBUG_SAVEALL)
170 else:
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200171 print('No GC available, disabling --findleaks',
172 file=sys.stderr)
Victor Stinner234cbef2015-09-30 01:13:53 +0200173 ns.findleaks = False
Victor Stinnerdad20e42015-09-29 22:48:52 +0200174
Victor Stinnerdad20e42015-09-29 22:48:52 +0200175 # Strip .py extensions.
Victor Stinner234cbef2015-09-30 01:13:53 +0200176 removepy(ns.args)
177
178 return ns
Victor Stinnerdad20e42015-09-29 22:48:52 +0200179
Victor Stinnerdad20e42015-09-29 22:48:52 +0200180 def find_tests(self, tests):
181 self.tests = tests
182
183 if self.ns.single:
184 self.next_single_filename = os.path.join(TEMPDIR, 'pynexttest')
185 try:
186 with open(self.next_single_filename, 'r') as fp:
187 next_test = fp.read().strip()
188 self.tests = [next_test]
189 except OSError:
190 pass
191
192 if self.ns.fromfile:
193 self.tests = []
Victor Stinner5de16e82016-03-24 09:43:00 +0100194 # regex to match 'test_builtin' in line:
195 # '0:00:00 [ 4/400] test_builtin -- test_dict took 1 sec'
Victor Stinnere8cfec52017-01-03 01:38:58 +0100196 regex = re.compile(r'\btest_[a-zA-Z0-9_]+\b')
Victor Stinnerdad20e42015-09-29 22:48:52 +0200197 with open(os.path.join(support.SAVEDCWD, self.ns.fromfile)) as fp:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200198 for line in fp:
Victor Stinnerc24217e2016-12-09 16:05:51 +0100199 line = line.split('#', 1)[0]
Victor Stinner5de16e82016-03-24 09:43:00 +0100200 line = line.strip()
Victor Stinnerc24217e2016-12-09 16:05:51 +0100201 match = regex.search(line)
202 if match is not None:
Victor Stinnere8cfec52017-01-03 01:38:58 +0100203 self.tests.append(match.group())
Victor Stinnerdad20e42015-09-29 22:48:52 +0200204
205 removepy(self.tests)
206
207 stdtests = STDTESTS[:]
208 nottests = NOTTESTS.copy()
209 if self.ns.exclude:
210 for arg in self.ns.args:
211 if arg in stdtests:
212 stdtests.remove(arg)
213 nottests.add(arg)
214 self.ns.args = []
215
Victor Stinnerdad20e42015-09-29 22:48:52 +0200216 # if testdir is set, then we are not running the python tests suite, so
217 # don't add default tests to be executed or skipped (pass empty values)
218 if self.ns.testdir:
219 alltests = findtests(self.ns.testdir, list(), set())
220 else:
221 alltests = findtests(self.ns.testdir, stdtests, nottests)
222
Victor Stinner5de16e82016-03-24 09:43:00 +0100223 if not self.ns.fromfile:
224 self.selected = self.tests or self.ns.args or alltests
225 else:
226 self.selected = self.tests
Victor Stinnerdad20e42015-09-29 22:48:52 +0200227 if self.ns.single:
228 self.selected = self.selected[:1]
229 try:
230 pos = alltests.index(self.selected[0])
231 self.next_single_test = alltests[pos + 1]
232 except IndexError:
233 pass
234
Victor Stinnerc7eab052015-09-30 00:59:35 +0200235 # Remove all the selected tests that precede start if it's set.
Victor Stinnerdad20e42015-09-29 22:48:52 +0200236 if self.ns.start:
237 try:
238 del self.selected[:self.selected.index(self.ns.start)]
239 except ValueError:
Victor Stinner6448b802015-09-29 23:43:33 +0200240 print("Couldn't find starting test (%s), using all tests"
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200241 % self.ns.start, file=sys.stderr)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200242
243 if self.ns.randomize:
244 if self.ns.random_seed is None:
245 self.ns.random_seed = random.randrange(10000000)
246 random.seed(self.ns.random_seed)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200247 random.shuffle(self.selected)
248
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200249 def list_tests(self):
250 for name in self.selected:
251 print(name)
252
mlouielua49c9352017-06-16 17:36:19 +0800253 def _list_cases(self, suite):
254 for test in suite:
255 if isinstance(test, unittest.loader._FailedTest):
256 continue
257 if isinstance(test, unittest.TestSuite):
258 self._list_cases(test)
259 elif isinstance(test, unittest.TestCase):
Victor Stinnerace56d52017-06-26 14:18:51 +0200260 if support._match_test(test):
261 print(test.id())
mlouielua49c9352017-06-16 17:36:19 +0800262
263 def list_cases(self):
Victor Stinnerace56d52017-06-26 14:18:51 +0200264 support.verbose = False
265 support.match_tests = self.ns.match_tests
266
mlouielua49c9352017-06-16 17:36:19 +0800267 for test in self.selected:
268 abstest = get_abs_module(self.ns, test)
269 try:
270 suite = unittest.defaultTestLoader.loadTestsFromName(abstest)
271 self._list_cases(suite)
272 except unittest.SkipTest:
273 self.skipped.append(test)
274
275 if self.skipped:
276 print(file=sys.stderr)
277 print(count(len(self.skipped), "test"), "skipped:", file=sys.stderr)
278 printlist(self.skipped, file=sys.stderr)
279
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200280 def rerun_failed_tests(self):
281 self.ns.verbose = True
282 self.ns.failfast = False
283 self.ns.verbose3 = False
284 self.ns.match_tests = None
285
286 print("Re-running failed tests in verbose mode")
287 for test in self.bad[:]:
288 print("Re-running test %r in verbose mode" % test, flush=True)
289 try:
290 self.ns.verbose = True
291 ok = runtest(self.ns, test)
292 except KeyboardInterrupt:
Victor Stinnerc5a01f82016-08-17 16:00:12 +0200293 self.interrupted = True
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200294 # print a newline separate from the ^C
295 print()
296 break
297 else:
298 if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}:
299 self.bad.remove(test)
300 else:
301 if self.bad:
302 print(count(len(self.bad), 'test'), "failed again:")
303 printlist(self.bad)
304
Victor Stinnerdad20e42015-09-29 22:48:52 +0200305 def display_result(self):
306 if self.interrupted:
307 # print a newline after ^C
308 print()
309 print("Test suite interrupted by signal SIGINT.")
Victor Stinner6448b802015-09-29 23:43:33 +0200310 executed = set(self.good) | set(self.bad) | set(self.skipped)
311 omitted = set(self.selected) - executed
Victor Stinnerdad20e42015-09-29 22:48:52 +0200312 print(count(len(omitted), "test"), "omitted:")
313 printlist(omitted)
314
Brett Cannon11faa212015-10-02 16:20:49 -0700315 # If running the test suite for PGO then no one cares about
316 # results.
317 if self.ns.pgo:
318 return
319
Victor Stinnerdad20e42015-09-29 22:48:52 +0200320 if self.good and not self.ns.quiet:
Victor Stinner6448b802015-09-29 23:43:33 +0200321 if (not self.bad
322 and not self.skipped
323 and not self.interrupted
324 and len(self.good) > 1):
Victor Stinnerdad20e42015-09-29 22:48:52 +0200325 print("All", end=' ')
326 print(count(len(self.good), "test"), "OK.")
327
328 if self.ns.print_slow:
329 self.test_times.sort(reverse=True)
Victor Stinner435eaf42016-08-17 12:22:52 +0200330 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200331 print("10 slowest tests:")
332 for time, test in self.test_times[:10]:
Victor Stinner435eaf42016-08-17 12:22:52 +0200333 print("- %s: %s" % (test, format_duration(time)))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200334
335 if self.bad:
Victor Stinner8f003192016-08-17 15:42:21 +0200336 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200337 print(count(len(self.bad), "test"), "failed:")
338 printlist(self.bad)
339
340 if self.environment_changed:
Victor Stinner8f003192016-08-17 15:42:21 +0200341 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200342 print("{} altered the execution environment:".format(
343 count(len(self.environment_changed), "test")))
344 printlist(self.environment_changed)
345
346 if self.skipped and not self.ns.quiet:
Victor Stinner8f003192016-08-17 15:42:21 +0200347 print()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200348 print(count(len(self.skipped), "test"), "skipped:")
349 printlist(self.skipped)
350
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200351 def run_tests_sequential(self):
Victor Stinnerc7eab052015-09-30 00:59:35 +0200352 if self.ns.trace:
353 import trace
Victor Stinnera53a8182015-10-01 00:53:09 +0200354 self.tracer = trace.Trace(trace=False, count=True)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200355
Victor Stinnerdad20e42015-09-29 22:48:52 +0200356 save_modules = sys.modules.keys()
357
Victor Stinner2b60b722016-03-24 11:55:29 +0100358 print("Run tests sequentially")
359
Victor Stinner69649f22016-03-23 12:14:10 +0100360 previous_test = None
Victor Stinnerdad20e42015-09-29 22:48:52 +0200361 for test_index, test in enumerate(self.tests, 1):
Victor Stinner69649f22016-03-23 12:14:10 +0100362 start_time = time.monotonic()
363
364 text = test
365 if previous_test:
366 text = '%s -- %s' % (text, previous_test)
367 self.display_progress(test_index, text)
368
Victor Stinnerc7eab052015-09-30 00:59:35 +0200369 if self.tracer:
Victor Stinner3844fe52015-09-26 10:38:01 +0200370 # If we're tracing code coverage, then we don't exit with status
371 # if on a false return value from main.
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200372 cmd = ('result = runtest(self.ns, test); '
373 'self.accumulate_result(test, result)')
Victor Stinner1b8b4232016-05-20 13:37:40 +0200374 ns = dict(locals())
375 self.tracer.runctx(cmd, globals=globals(), locals=ns)
376 result = ns['result']
Victor Stinner3844fe52015-09-26 10:38:01 +0200377 else:
378 try:
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200379 result = runtest(self.ns, test)
Victor Stinner3844fe52015-09-26 10:38:01 +0200380 except KeyboardInterrupt:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200381 self.interrupted = True
Victor Stinnerc5a01f82016-08-17 16:00:12 +0200382 self.accumulate_result(test, (INTERRUPTED, None))
Victor Stinner3844fe52015-09-26 10:38:01 +0200383 break
Victor Stinner3909e582015-10-11 10:37:25 +0200384 else:
385 self.accumulate_result(test, result)
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200386
Victor Stinner1b8b4232016-05-20 13:37:40 +0200387 previous_test = format_test_result(test, result[0])
Victor Stinner69649f22016-03-23 12:14:10 +0100388 test_time = time.monotonic() - start_time
389 if test_time >= PROGRESS_MIN_TIME:
Victor Stinner435eaf42016-08-17 12:22:52 +0200390 previous_test = "%s in %s" % (previous_test, format_duration(test_time))
Victor Stinner1b8b4232016-05-20 13:37:40 +0200391 elif result[0] == PASSED:
392 # be quiet: say nothing if the test passed shortly
Victor Stinner69649f22016-03-23 12:14:10 +0100393 previous_test = None
394
Victor Stinnerdad20e42015-09-29 22:48:52 +0200395 if self.ns.findleaks:
Victor Stinner3844fe52015-09-26 10:38:01 +0200396 gc.collect()
397 if gc.garbage:
398 print("Warning: test created", len(gc.garbage), end=' ')
399 print("uncollectable object(s).")
400 # move the uncollectable objects somewhere so we don't see
401 # them again
Victor Stinnerdad20e42015-09-29 22:48:52 +0200402 self.found_garbage.extend(gc.garbage)
Victor Stinner3844fe52015-09-26 10:38:01 +0200403 del gc.garbage[:]
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200404
Victor Stinner3844fe52015-09-26 10:38:01 +0200405 # Unload the newly imported modules (best effort finalization)
406 for module in sys.modules.keys():
407 if module not in save_modules and module.startswith("test."):
408 support.unload(module)
409
Victor Stinner69649f22016-03-23 12:14:10 +0100410 if previous_test:
411 print(previous_test)
412
Victor Stinnerb4084352015-09-30 02:39:22 +0200413 def _test_forever(self, tests):
414 while True:
415 for test in tests:
416 yield test
417 if self.bad:
418 return
Victor Stinner5e875922017-07-03 11:15:58 +0200419 if self.ns.fail_env_changed and self.environment_changed:
420 return
Victor Stinner3844fe52015-09-26 10:38:01 +0200421
Victor Stinner3d005682017-05-04 15:21:12 +0200422 def display_header(self):
423 # Print basic platform information
424 print("==", platform.python_implementation(), *sys.version.split())
425 print("==", platform.platform(aliased=True),
426 "%s-endian" % sys.byteorder)
427 print("== hash algorithm:", sys.hash_info.algorithm,
428 "64bit" if sys.maxsize > 2**32 else "32bit")
429 print("== cwd:", os.getcwd())
430 cpu_count = os.cpu_count()
431 if cpu_count:
432 print("== CPU count:", cpu_count)
433 print("== encodings: locale=%s, FS=%s"
434 % (locale.getpreferredencoding(False),
435 sys.getfilesystemencoding()))
436 print("Testing with flags:", sys.flags)
437
Victor Stinnerb4084352015-09-30 02:39:22 +0200438 def run_tests(self):
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200439 # For a partial run, we do not need to clutter the output.
Victor Stinner3d005682017-05-04 15:21:12 +0200440 if (self.ns.header
441 or not(self.ns.pgo or self.ns.quiet or self.ns.single
442 or self.tests or self.ns.args)):
443 self.display_header()
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200444
445 if self.ns.randomize:
446 print("Using random seed", self.ns.random_seed)
447
Victor Stinnerdad20e42015-09-29 22:48:52 +0200448 if self.ns.forever:
Victor Stinner9a142142015-09-30 13:51:17 +0200449 self.tests = self._test_forever(list(self.selected))
Victor Stinnerdad20e42015-09-29 22:48:52 +0200450 self.test_count = ''
451 self.test_count_width = 3
452 else:
453 self.tests = iter(self.selected)
454 self.test_count = '/{}'.format(len(self.selected))
455 self.test_count_width = len(self.test_count) - 1
456
457 if self.ns.use_mp:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200458 from test.libregrtest.runtest_mp import run_tests_multiprocess
459 run_tests_multiprocess(self)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200460 else:
Victor Stinnerbd1a72c2015-09-29 23:36:27 +0200461 self.run_tests_sequential()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200462
463 def finalize(self):
464 if self.next_single_filename:
465 if self.next_single_test:
466 with open(self.next_single_filename, 'w') as fp:
467 fp.write(self.next_single_test + '\n')
Victor Stinner3844fe52015-09-26 10:38:01 +0200468 else:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200469 os.unlink(self.next_single_filename)
Victor Stinner3844fe52015-09-26 10:38:01 +0200470
Victor Stinnerc7eab052015-09-30 00:59:35 +0200471 if self.tracer:
Victor Stinnerdad20e42015-09-29 22:48:52 +0200472 r = self.tracer.results()
473 r.write_results(show_missing=True, summary=True,
474 coverdir=self.ns.coverdir)
Victor Stinner3844fe52015-09-26 10:38:01 +0200475
Victor Stinner435eaf42016-08-17 12:22:52 +0200476 print()
477 duration = time.monotonic() - self.start_time
478 print("Total duration: %s" % format_duration(duration))
Victor Stinner24f949e2016-03-22 15:14:09 +0100479
Victor Stinner63686032016-08-17 16:12:16 +0200480 if self.bad:
481 result = "FAILURE"
482 elif self.interrupted:
483 result = "INTERRUPTED"
Victor Stinner5e875922017-07-03 11:15:58 +0200484 elif self.ns.fail_env_changed and self.environment_changed:
Victor Stinner63f54c62017-06-26 18:33:19 +0200485 result = "ENV CHANGED"
Victor Stinner63686032016-08-17 16:12:16 +0200486 else:
487 result = "SUCCESS"
Victor Stinnerf2abf5c2016-08-19 17:54:25 +0200488 print("Tests result: %s" % result)
Victor Stinner63686032016-08-17 16:12:16 +0200489
Victor Stinnerdad20e42015-09-29 22:48:52 +0200490 if self.ns.runleaks:
491 os.system("leaks %d" % os.getpid())
Victor Stinner3844fe52015-09-26 10:38:01 +0200492
Victor Stinnerdad20e42015-09-29 22:48:52 +0200493 def main(self, tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100494 global TEMPDIR
495
496 if sysconfig.is_python_build():
497 try:
498 os.mkdir(TEMPDIR)
499 except FileExistsError:
500 pass
501
502 # Define a writable temp dir that will be used as cwd while running
503 # the tests. The name of the dir includes the pid to allow parallel
504 # testing (see the -j option).
505 test_cwd = 'test_python_{}'.format(os.getpid())
506 test_cwd = os.path.join(TEMPDIR, test_cwd)
507
508 # Run the tests in a context manager that temporarily changes the CWD to a
509 # temporary and writable directory. If it's not possible to create or
510 # change the CWD, the original CWD will be used. The original CWD is
511 # available from support.SAVEDCWD.
512 with support.temp_cwd(test_cwd, quiet=True):
513 self._main(tests, kwargs)
514
515 def _main(self, tests, kwargs):
Victor Stinner234cbef2015-09-30 01:13:53 +0200516 self.ns = self.parse_args(kwargs)
517
Victor Stinnerdad20e42015-09-29 22:48:52 +0200518 if self.ns.slaveargs is not None:
Victor Stinner56e05dd2015-09-29 23:15:38 +0200519 from test.libregrtest.runtest_mp import run_tests_slave
520 run_tests_slave(self.ns.slaveargs)
Victor Stinnerecef6222015-09-30 01:39:28 +0200521
Victor Stinnerc7eab052015-09-30 00:59:35 +0200522 if self.ns.wait:
523 input("Press any key to continue...")
524
Steve Dower22d06982016-09-06 19:38:15 -0700525 support.PGO = self.ns.pgo
526
Victor Stinnera2045022015-09-30 02:17:28 +0200527 setup_tests(self.ns)
Victor Stinnerecef6222015-09-30 01:39:28 +0200528
Victor Stinnerdad20e42015-09-29 22:48:52 +0200529 self.find_tests(tests)
Victor Stinnerc7eab052015-09-30 00:59:35 +0200530
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200531 if self.ns.list_tests:
532 self.list_tests()
533 sys.exit(0)
534
mlouielua49c9352017-06-16 17:36:19 +0800535 if self.ns.list_cases:
536 self.list_cases()
537 sys.exit(0)
538
Victor Stinner5f9d3ac2015-10-03 00:21:12 +0200539 self.run_tests()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200540 self.display_result()
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200541
542 if self.ns.verbose2 and self.bad:
543 self.rerun_failed_tests()
544
Victor Stinnerdad20e42015-09-29 22:48:52 +0200545 self.finalize()
Victor Stinner63f54c62017-06-26 18:33:19 +0200546 if self.bad:
547 sys.exit(2)
548 if self.interrupted:
549 sys.exit(130)
550 if self.ns.fail_env_changed and self.environment_changed:
551 sys.exit(3)
552 sys.exit(0)
Victor Stinner3844fe52015-09-26 10:38:01 +0200553
554
Victor Stinner3844fe52015-09-26 10:38:01 +0200555def removepy(names):
556 if not names:
557 return
558 for idx, name in enumerate(names):
559 basename, ext = os.path.splitext(name)
560 if ext == '.py':
561 names[idx] = basename
562
563
564def count(n, word):
565 if n == 1:
566 return "%d %s" % (n, word)
567 else:
568 return "%d %ss" % (n, word)
569
570
mlouielua49c9352017-06-16 17:36:19 +0800571def printlist(x, width=70, indent=4, file=None):
Victor Stinner3844fe52015-09-26 10:38:01 +0200572 """Print the elements of iterable x to stdout.
573
574 Optional arg width (default 70) is the maximum line length.
575 Optional arg indent (default 4) is the number of blanks with which to
576 begin each line.
577 """
578
Victor Stinner3844fe52015-09-26 10:38:01 +0200579 blanks = ' ' * indent
580 # Print the sorted list: 'x' may be a '--random' list or a set()
Victor Stinnerdad20e42015-09-29 22:48:52 +0200581 print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width,
mlouielua49c9352017-06-16 17:36:19 +0800582 initial_indent=blanks, subsequent_indent=blanks),
583 file=file)
Victor Stinnerdad20e42015-09-29 22:48:52 +0200584
585
586def main(tests=None, **kwargs):
Victor Stinner3aac0ad2016-03-24 17:53:20 +0100587 """Run the Python suite."""
Victor Stinnerdad20e42015-09-29 22:48:52 +0200588 Regrtest().main(tests=tests, **kwargs)