| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  | import datetime | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  | import faulthandler | 
					
						
							| 
									
										
										
										
											2016-09-08 21:46:56 -07:00
										 |  |  | import locale | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | import platform | 
					
						
							|  |  |  | import random | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | import re | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import sysconfig | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | import tempfile | 
					
						
							|  |  |  | import textwrap | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2015-10-11 10:37:25 +02:00
										 |  |  | from test.libregrtest.cmdline import _parse_args | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | from test.libregrtest.runtest import ( | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  |     findtests, runtest, | 
					
						
							| 
									
										
										
										
											2015-10-11 10:37:25 +02:00
										 |  |  |     STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED, | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |     INTERRUPTED, CHILD_ERROR, | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  |     PROGRESS_MIN_TIME, format_test_result) | 
					
						
							| 
									
										
										
										
											2015-09-30 02:17:28 +02:00
										 |  |  | from test.libregrtest.setup import setup_tests | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | try: | 
					
						
							|  |  |  |     import gc | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     gc = None | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # When tests are run from the Python build directory, it is best practice | 
					
						
							|  |  |  | # to keep the test files in a subfolder.  This eases the cleanup of leftover | 
					
						
							|  |  |  | # files using the "make distclean" command. | 
					
						
							|  |  |  | if sysconfig.is_python_build(): | 
					
						
							|  |  |  |     TEMPDIR = os.path.join(sysconfig.get_config_var('srcdir'), 'build') | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     TEMPDIR = tempfile.gettempdir() | 
					
						
							|  |  |  | TEMPDIR = os.path.abspath(TEMPDIR) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  | def format_duration(seconds): | 
					
						
							|  |  |  |     if seconds < 1.0: | 
					
						
							|  |  |  |         return '%.0f ms' % (seconds * 1e3) | 
					
						
							|  |  |  |     if seconds < 60.0: | 
					
						
							|  |  |  |         return '%.0f sec' % seconds | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     minutes, seconds = divmod(seconds, 60.0) | 
					
						
							|  |  |  |     return '%.0f min %.0f sec' % (minutes, seconds) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | class Regrtest: | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     """Execute a test suite.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This also parses command-line options and modifies its behavior | 
					
						
							|  |  |  |     accordingly. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tests -- a list of strings containing test names (optional) | 
					
						
							|  |  |  |     testdir -- the directory in which to look for tests (optional) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Users other than the Python test suite will certainly want to | 
					
						
							|  |  |  |     specify testdir; if it's omitted, the directory containing the | 
					
						
							|  |  |  |     Python test suite is searched for. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If the tests argument is omitted, the tests listed on the | 
					
						
							|  |  |  |     command-line will be used.  If that's empty, too, then all *.py | 
					
						
							|  |  |  |     files beginning with test_ will be used. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The other default arguments (verbose, quiet, exclude, | 
					
						
							|  |  |  |     single, randomize, findleaks, use_resources, trace, coverdir, | 
					
						
							|  |  |  |     print_slow, and random_seed) allow programmers calling main() | 
					
						
							|  |  |  |     directly to set the values that would normally be set by flags | 
					
						
							|  |  |  |     on the command line. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         # Namespace of command line options | 
					
						
							|  |  |  |         self.ns = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # tests | 
					
						
							|  |  |  |         self.tests = [] | 
					
						
							|  |  |  |         self.selected = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # test results | 
					
						
							|  |  |  |         self.good = [] | 
					
						
							|  |  |  |         self.bad = [] | 
					
						
							|  |  |  |         self.skipped = [] | 
					
						
							|  |  |  |         self.resource_denieds = [] | 
					
						
							|  |  |  |         self.environment_changed = [] | 
					
						
							|  |  |  |         self.interrupted = False | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used by --slow | 
					
						
							|  |  |  |         self.test_times = [] | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used by --coverage, trace.Trace instance | 
					
						
							|  |  |  |         self.tracer = None | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used by --findleaks, store for gc.garbage | 
					
						
							|  |  |  |         self.found_garbage = [] | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used to display the progress bar "[ 3/100]" | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  |         self.start_time = time.monotonic() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         self.test_count = '' | 
					
						
							|  |  |  |         self.test_count_width = 1 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used by --single | 
					
						
							|  |  |  |         self.next_single_test = None | 
					
						
							|  |  |  |         self.next_single_filename = None | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |     def accumulate_result(self, test, result): | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         ok, test_time = result | 
					
						
							| 
									
										
										
										
											2015-10-11 10:37:25 +02:00
										 |  |  |         if ok not in (CHILD_ERROR, INTERRUPTED): | 
					
						
							|  |  |  |             self.test_times.append((test_time, test)) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         if ok == PASSED: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             self.good.append(test) | 
					
						
							| 
									
										
										
										
											2017-02-06 12:42:00 +01:00
										 |  |  |         elif ok in (FAILED, CHILD_ERROR): | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             self.bad.append(test) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         elif ok == ENV_CHANGED: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             self.environment_changed.append(test) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         elif ok == SKIPPED: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             self.skipped.append(test) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         elif ok == RESOURCE_DENIED: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             self.skipped.append(test) | 
					
						
							|  |  |  |             self.resource_denieds.append(test) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def display_progress(self, test_index, test): | 
					
						
							|  |  |  |         if self.ns.quiet: | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2015-10-02 16:20:49 -07:00
										 |  |  |         if self.bad and not self.ns.pgo: | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  |             fmt = "{time} [{test_index:{count_width}}{test_count}/{nbad}] {test_name}" | 
					
						
							| 
									
										
										
										
											2015-10-02 16:20:49 -07:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  |             fmt = "{time} [{test_index:{count_width}}{test_count}] {test_name}" | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  |         test_time = time.monotonic() - self.start_time | 
					
						
							|  |  |  |         test_time = datetime.timedelta(seconds=int(test_time)) | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  |         line = fmt.format(count_width=self.test_count_width, | 
					
						
							|  |  |  |                           test_index=test_index, | 
					
						
							|  |  |  |                           test_count=self.test_count, | 
					
						
							|  |  |  |                           nbad=len(self.bad), | 
					
						
							|  |  |  |                           test_name=test, | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  |                           time=test_time) | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  |         print(line, flush=True) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 01:13:53 +02:00
										 |  |  |     def parse_args(self, kwargs): | 
					
						
							|  |  |  |         ns = _parse_args(sys.argv[1:], **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |         if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'): | 
					
						
							|  |  |  |             print("Warning: The timeout option requires " | 
					
						
							|  |  |  |                   "faulthandler.dump_traceback_later", file=sys.stderr) | 
					
						
							|  |  |  |             ns.timeout = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 01:13:53 +02:00
										 |  |  |         if ns.threshold is not None and gc is None: | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |             print('No GC available, ignore --threshold.', file=sys.stderr) | 
					
						
							| 
									
										
										
										
											2015-09-30 01:13:53 +02:00
										 |  |  |             ns.threshold = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ns.findleaks: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             if gc is not None: | 
					
						
							|  |  |  |                 # Uncomment the line below to report garbage that is not | 
					
						
							|  |  |  |                 # freeable by reference counting alone.  By default only | 
					
						
							|  |  |  |                 # garbage that is not collectable by the GC is reported. | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |                 #gc.set_debug(gc.DEBUG_SAVEALL) | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |                 print('No GC available, disabling --findleaks', | 
					
						
							|  |  |  |                       file=sys.stderr) | 
					
						
							| 
									
										
										
										
											2015-09-30 01:13:53 +02:00
										 |  |  |                 ns.findleaks = False | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Strip .py extensions. | 
					
						
							| 
									
										
										
										
											2015-09-30 01:13:53 +02:00
										 |  |  |         removepy(ns.args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return ns | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def find_tests(self, tests): | 
					
						
							|  |  |  |         self.tests = tests | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.ns.single: | 
					
						
							|  |  |  |             self.next_single_filename = os.path.join(TEMPDIR, 'pynexttest') | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 with open(self.next_single_filename, 'r') as fp: | 
					
						
							|  |  |  |                     next_test = fp.read().strip() | 
					
						
							|  |  |  |                     self.tests = [next_test] | 
					
						
							|  |  |  |             except OSError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.ns.fromfile: | 
					
						
							|  |  |  |             self.tests = [] | 
					
						
							| 
									
										
										
										
											2016-03-24 09:43:00 +01:00
										 |  |  |             # regex to match 'test_builtin' in line: | 
					
						
							|  |  |  |             # '0:00:00 [  4/400] test_builtin -- test_dict took 1 sec' | 
					
						
							| 
									
										
										
										
											2017-01-03 01:38:58 +01:00
										 |  |  |             regex = re.compile(r'\btest_[a-zA-Z0-9_]+\b') | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             with open(os.path.join(support.SAVEDCWD, self.ns.fromfile)) as fp: | 
					
						
							|  |  |  |                 for line in fp: | 
					
						
							| 
									
										
										
										
											2016-12-09 16:05:51 +01:00
										 |  |  |                     line = line.split('#', 1)[0] | 
					
						
							| 
									
										
										
										
											2016-03-24 09:43:00 +01:00
										 |  |  |                     line = line.strip() | 
					
						
							| 
									
										
										
										
											2016-12-09 16:05:51 +01:00
										 |  |  |                     match = regex.search(line) | 
					
						
							|  |  |  |                     if match is not None: | 
					
						
							| 
									
										
										
										
											2017-01-03 01:38:58 +01:00
										 |  |  |                         self.tests.append(match.group()) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         removepy(self.tests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         stdtests = STDTESTS[:] | 
					
						
							|  |  |  |         nottests = NOTTESTS.copy() | 
					
						
							|  |  |  |         if self.ns.exclude: | 
					
						
							|  |  |  |             for arg in self.ns.args: | 
					
						
							|  |  |  |                 if arg in stdtests: | 
					
						
							|  |  |  |                     stdtests.remove(arg) | 
					
						
							|  |  |  |                 nottests.add(arg) | 
					
						
							|  |  |  |             self.ns.args = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # if testdir is set, then we are not running the python tests suite, so | 
					
						
							|  |  |  |         # don't add default tests to be executed or skipped (pass empty values) | 
					
						
							|  |  |  |         if self.ns.testdir: | 
					
						
							|  |  |  |             alltests = findtests(self.ns.testdir, list(), set()) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             alltests = findtests(self.ns.testdir, stdtests, nottests) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:43:00 +01:00
										 |  |  |         if not self.ns.fromfile: | 
					
						
							|  |  |  |             self.selected = self.tests or self.ns.args or alltests | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.selected = self.tests | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.ns.single: | 
					
						
							|  |  |  |             self.selected = self.selected[:1] | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 pos = alltests.index(self.selected[0]) | 
					
						
							|  |  |  |                 self.next_single_test = alltests[pos + 1] | 
					
						
							|  |  |  |             except IndexError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |         # Remove all the selected tests that precede start if it's set. | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.ns.start: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 del self.selected[:self.selected.index(self.ns.start)] | 
					
						
							|  |  |  |             except ValueError: | 
					
						
							| 
									
										
										
										
											2015-09-29 23:43:33 +02:00
										 |  |  |                 print("Couldn't find starting test (%s), using all tests" | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |                       % self.ns.start, file=sys.stderr) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if self.ns.randomize: | 
					
						
							|  |  |  |             if self.ns.random_seed is None: | 
					
						
							|  |  |  |                 self.ns.random_seed = random.randrange(10000000) | 
					
						
							|  |  |  |             random.seed(self.ns.random_seed) | 
					
						
							|  |  |  |             random.shuffle(self.selected) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |     def list_tests(self): | 
					
						
							|  |  |  |         for name in self.selected: | 
					
						
							|  |  |  |             print(name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  |     def rerun_failed_tests(self): | 
					
						
							|  |  |  |         self.ns.verbose = True | 
					
						
							|  |  |  |         self.ns.failfast = False | 
					
						
							|  |  |  |         self.ns.verbose3 = False | 
					
						
							|  |  |  |         self.ns.match_tests = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         print("Re-running failed tests in verbose mode") | 
					
						
							|  |  |  |         for test in self.bad[:]: | 
					
						
							|  |  |  |             print("Re-running test %r in verbose mode" % test, flush=True) | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self.ns.verbose = True | 
					
						
							|  |  |  |                 ok = runtest(self.ns, test) | 
					
						
							|  |  |  |             except KeyboardInterrupt: | 
					
						
							| 
									
										
										
										
											2016-08-17 16:00:12 +02:00
										 |  |  |                 self.interrupted = True | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  |                 # print a newline separate from the ^C | 
					
						
							|  |  |  |                 print() | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: | 
					
						
							|  |  |  |                     self.bad.remove(test) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if self.bad: | 
					
						
							|  |  |  |                 print(count(len(self.bad), 'test'), "failed again:") | 
					
						
							|  |  |  |                 printlist(self.bad) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |     def display_result(self): | 
					
						
							|  |  |  |         if self.interrupted: | 
					
						
							|  |  |  |             # print a newline after ^C | 
					
						
							|  |  |  |             print() | 
					
						
							|  |  |  |             print("Test suite interrupted by signal SIGINT.") | 
					
						
							| 
									
										
										
										
											2015-09-29 23:43:33 +02:00
										 |  |  |             executed = set(self.good) | set(self.bad) | set(self.skipped) | 
					
						
							|  |  |  |             omitted = set(self.selected) - executed | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             print(count(len(omitted), "test"), "omitted:") | 
					
						
							|  |  |  |             printlist(omitted) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 16:20:49 -07:00
										 |  |  |         # If running the test suite for PGO then no one cares about | 
					
						
							|  |  |  |         # results. | 
					
						
							|  |  |  |         if self.ns.pgo: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.good and not self.ns.quiet: | 
					
						
							| 
									
										
										
										
											2015-09-29 23:43:33 +02:00
										 |  |  |             if (not self.bad | 
					
						
							|  |  |  |                 and not self.skipped | 
					
						
							|  |  |  |                 and not self.interrupted | 
					
						
							|  |  |  |                 and len(self.good) > 1): | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |                 print("All", end=' ') | 
					
						
							|  |  |  |             print(count(len(self.good), "test"), "OK.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.ns.print_slow: | 
					
						
							|  |  |  |             self.test_times.sort(reverse=True) | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  |             print() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             print("10 slowest tests:") | 
					
						
							|  |  |  |             for time, test in self.test_times[:10]: | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  |                 print("- %s: %s" % (test, format_duration(time))) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if self.bad: | 
					
						
							| 
									
										
										
										
											2016-08-17 15:42:21 +02:00
										 |  |  |             print() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             print(count(len(self.bad), "test"), "failed:") | 
					
						
							|  |  |  |             printlist(self.bad) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.environment_changed: | 
					
						
							| 
									
										
										
										
											2016-08-17 15:42:21 +02:00
										 |  |  |             print() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             print("{} altered the execution environment:".format( | 
					
						
							|  |  |  |                      count(len(self.environment_changed), "test"))) | 
					
						
							|  |  |  |             printlist(self.environment_changed) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.skipped and not self.ns.quiet: | 
					
						
							| 
									
										
										
										
											2016-08-17 15:42:21 +02:00
										 |  |  |             print() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             print(count(len(self.skipped), "test"), "skipped:") | 
					
						
							|  |  |  |             printlist(self.skipped) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 23:36:27 +02:00
										 |  |  |     def run_tests_sequential(self): | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |         if self.ns.trace: | 
					
						
							|  |  |  |             import trace | 
					
						
							| 
									
										
										
										
											2015-10-01 00:53:09 +02:00
										 |  |  |             self.tracer = trace.Trace(trace=False, count=True) | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         save_modules = sys.modules.keys() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 11:55:29 +01:00
										 |  |  |         print("Run tests sequentially") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |         previous_test = None | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         for test_index, test in enumerate(self.tests, 1): | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |             start_time = time.monotonic() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             text = test | 
					
						
							|  |  |  |             if previous_test: | 
					
						
							|  |  |  |                 text = '%s -- %s' % (text, previous_test) | 
					
						
							|  |  |  |             self.display_progress(test_index, text) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |             if self.tracer: | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |                 # If we're tracing code coverage, then we don't exit with status | 
					
						
							|  |  |  |                 # if on a false return value from main. | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  |                 cmd = ('result = runtest(self.ns, test); ' | 
					
						
							|  |  |  |                        'self.accumulate_result(test, result)') | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  |                 ns = dict(locals()) | 
					
						
							|  |  |  |                 self.tracer.runctx(cmd, globals=globals(), locals=ns) | 
					
						
							|  |  |  |                 result = ns['result'] | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  |                     result = runtest(self.ns, test) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |                 except KeyboardInterrupt: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |                     self.interrupted = True | 
					
						
							| 
									
										
										
										
											2016-08-17 16:00:12 +02:00
										 |  |  |                     self.accumulate_result(test, (INTERRUPTED, None)) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |                     break | 
					
						
							| 
									
										
										
										
											2015-10-11 10:37:25 +02:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     self.accumulate_result(test, result) | 
					
						
							| 
									
										
										
										
											2015-09-29 23:36:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  |             previous_test = format_test_result(test, result[0]) | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |             test_time = time.monotonic() - start_time | 
					
						
							|  |  |  |             if test_time >= PROGRESS_MIN_TIME: | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  |                 previous_test = "%s in %s" % (previous_test, format_duration(test_time)) | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  |             elif result[0] == PASSED: | 
					
						
							|  |  |  |                 # be quiet: say nothing if the test passed shortly | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |                 previous_test = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             if self.ns.findleaks: | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |                 gc.collect() | 
					
						
							|  |  |  |                 if gc.garbage: | 
					
						
							|  |  |  |                     print("Warning: test created", len(gc.garbage), end=' ') | 
					
						
							|  |  |  |                     print("uncollectable object(s).") | 
					
						
							|  |  |  |                     # move the uncollectable objects somewhere so we don't see | 
					
						
							|  |  |  |                     # them again | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |                     self.found_garbage.extend(gc.garbage) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |                     del gc.garbage[:] | 
					
						
							| 
									
										
										
										
											2015-09-29 23:36:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |             # Unload the newly imported modules (best effort finalization) | 
					
						
							|  |  |  |             for module in sys.modules.keys(): | 
					
						
							|  |  |  |                 if module not in save_modules and module.startswith("test."): | 
					
						
							|  |  |  |                     support.unload(module) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |         if previous_test: | 
					
						
							|  |  |  |             print(previous_test) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 02:39:22 +02:00
										 |  |  |     def _test_forever(self, tests): | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             for test in tests: | 
					
						
							|  |  |  |                 yield test | 
					
						
							|  |  |  |                 if self.bad: | 
					
						
							|  |  |  |                     return | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 02:39:22 +02:00
										 |  |  |     def run_tests(self): | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |         # For a partial run, we do not need to clutter the output. | 
					
						
							|  |  |  |         if (self.ns.verbose | 
					
						
							|  |  |  |             or self.ns.header | 
					
						
							| 
									
										
										
										
											2015-10-02 16:20:49 -07:00
										 |  |  |             or not (self.ns.pgo or self.ns.quiet or self.ns.single | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |                     or self.tests or self.ns.args)): | 
					
						
							|  |  |  |             # Print basic platform information | 
					
						
							|  |  |  |             print("==", platform.python_implementation(), *sys.version.split()) | 
					
						
							|  |  |  |             print("==  ", platform.platform(aliased=True), | 
					
						
							|  |  |  |                           "%s-endian" % sys.byteorder) | 
					
						
							|  |  |  |             print("==  ", "hash algorithm:", sys.hash_info.algorithm, | 
					
						
							|  |  |  |                   "64bit" if sys.maxsize > 2**32 else "32bit") | 
					
						
							| 
									
										
										
										
											2016-09-08 21:46:56 -07:00
										 |  |  |             print("==  cwd:", os.getcwd()) | 
					
						
							|  |  |  |             print("==  encodings: locale=%s, FS=%s" | 
					
						
							|  |  |  |                   % (locale.getpreferredencoding(False), | 
					
						
							|  |  |  |                      sys.getfilesystemencoding())) | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |             print("Testing with flags:", sys.flags) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.ns.randomize: | 
					
						
							|  |  |  |             print("Using random seed", self.ns.random_seed) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.ns.forever: | 
					
						
							| 
									
										
										
										
											2015-09-30 13:51:17 +02:00
										 |  |  |             self.tests = self._test_forever(list(self.selected)) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             self.test_count = '' | 
					
						
							|  |  |  |             self.test_count_width = 3 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.tests = iter(self.selected) | 
					
						
							|  |  |  |             self.test_count = '/{}'.format(len(self.selected)) | 
					
						
							|  |  |  |             self.test_count_width = len(self.test_count) - 1 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.ns.use_mp: | 
					
						
							| 
									
										
										
										
											2015-09-29 23:15:38 +02:00
										 |  |  |             from test.libregrtest.runtest_mp import run_tests_multiprocess | 
					
						
							|  |  |  |             run_tests_multiprocess(self) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2015-09-29 23:36:27 +02:00
										 |  |  |             self.run_tests_sequential() | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |     def finalize(self): | 
					
						
							|  |  |  |         if self.next_single_filename: | 
					
						
							|  |  |  |             if self.next_single_test: | 
					
						
							|  |  |  |                 with open(self.next_single_filename, 'w') as fp: | 
					
						
							|  |  |  |                     fp.write(self.next_single_test + '\n') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 os.unlink(self.next_single_filename) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |         if self.tracer: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             r = self.tracer.results() | 
					
						
							|  |  |  |             r.write_results(show_missing=True, summary=True, | 
					
						
							|  |  |  |                             coverdir=self.ns.coverdir) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 12:22:52 +02:00
										 |  |  |         print() | 
					
						
							|  |  |  |         duration = time.monotonic() - self.start_time | 
					
						
							|  |  |  |         print("Total duration: %s" % format_duration(duration)) | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 16:12:16 +02:00
										 |  |  |         if self.bad: | 
					
						
							|  |  |  |             result = "FAILURE" | 
					
						
							|  |  |  |         elif self.interrupted: | 
					
						
							|  |  |  |             result = "INTERRUPTED" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             result = "SUCCESS" | 
					
						
							| 
									
										
										
										
											2016-08-19 17:54:25 +02:00
										 |  |  |         print("Tests result: %s" % result) | 
					
						
							| 
									
										
										
										
											2016-08-17 16:12:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.ns.runleaks: | 
					
						
							|  |  |  |             os.system("leaks %d" % os.getpid()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def main(self, tests=None, **kwargs): | 
					
						
							| 
									
										
										
										
											2016-03-24 17:53:20 +01:00
										 |  |  |         global TEMPDIR | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if sysconfig.is_python_build(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 os.mkdir(TEMPDIR) | 
					
						
							|  |  |  |             except FileExistsError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Define a writable temp dir that will be used as cwd while running | 
					
						
							|  |  |  |         # the tests. The name of the dir includes the pid to allow parallel | 
					
						
							|  |  |  |         # testing (see the -j option). | 
					
						
							|  |  |  |         test_cwd = 'test_python_{}'.format(os.getpid()) | 
					
						
							|  |  |  |         test_cwd = os.path.join(TEMPDIR, test_cwd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Run the tests in a context manager that temporarily changes the CWD to a | 
					
						
							|  |  |  |         # temporary and writable directory.  If it's not possible to create or | 
					
						
							|  |  |  |         # change the CWD, the original CWD will be used.  The original CWD is | 
					
						
							|  |  |  |         # available from support.SAVEDCWD. | 
					
						
							|  |  |  |         with support.temp_cwd(test_cwd, quiet=True): | 
					
						
							|  |  |  |             self._main(tests, kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _main(self, tests, kwargs): | 
					
						
							| 
									
										
										
										
											2015-09-30 01:13:53 +02:00
										 |  |  |         self.ns = self.parse_args(kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         if self.ns.slaveargs is not None: | 
					
						
							| 
									
										
										
										
											2015-09-29 23:15:38 +02:00
										 |  |  |             from test.libregrtest.runtest_mp import run_tests_slave | 
					
						
							|  |  |  |             run_tests_slave(self.ns.slaveargs) | 
					
						
							| 
									
										
										
										
											2015-09-30 01:39:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |         if self.ns.wait: | 
					
						
							|  |  |  |             input("Press any key to continue...") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 19:38:15 -07:00
										 |  |  |         support.PGO = self.ns.pgo | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 02:17:28 +02:00
										 |  |  |         setup_tests(self.ns) | 
					
						
							| 
									
										
										
										
											2015-09-30 01:39:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         self.find_tests(tests) | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |         if self.ns.list_tests: | 
					
						
							|  |  |  |             self.list_tests() | 
					
						
							|  |  |  |             sys.exit(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_tests() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         self.display_result() | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if self.ns.verbose2 and self.bad: | 
					
						
							|  |  |  |             self.rerun_failed_tests() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         self.finalize() | 
					
						
							|  |  |  |         sys.exit(len(self.bad) > 0 or self.interrupted) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def removepy(names): | 
					
						
							|  |  |  |     if not names: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     for idx, name in enumerate(names): | 
					
						
							|  |  |  |         basename, ext = os.path.splitext(name) | 
					
						
							|  |  |  |         if ext == '.py': | 
					
						
							|  |  |  |             names[idx] = basename | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def count(n, word): | 
					
						
							|  |  |  |     if n == 1: | 
					
						
							|  |  |  |         return "%d %s" % (n, word) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return "%d %ss" % (n, word) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def printlist(x, width=70, indent=4): | 
					
						
							|  |  |  |     """Print the elements of iterable x to stdout.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Optional arg width (default 70) is the maximum line length. | 
					
						
							|  |  |  |     Optional arg indent (default 4) is the number of blanks with which to | 
					
						
							|  |  |  |     begin each line. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     blanks = ' ' * indent | 
					
						
							|  |  |  |     # Print the sorted list: 'x' may be a '--random' list or a set() | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |     print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width, | 
					
						
							|  |  |  |                         initial_indent=blanks, subsequent_indent=blanks)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(tests=None, **kwargs): | 
					
						
							| 
									
										
										
										
											2016-03-24 17:53:20 +01:00
										 |  |  |     """Run the Python suite.""" | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |     Regrtest().main(tests=tests, **kwargs) |