| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | import faulthandler | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | import functools | 
					
						
							| 
									
										
										
										
											2019-04-26 09:28:53 +02:00
										 |  |  | import gc | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | import importlib | 
					
						
							|  |  |  | import io | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | import traceback | 
					
						
							|  |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2019-04-26 09:28:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2020-06-25 18:38:51 +08:00
										 |  |  | from test.support import os_helper | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | from test.libregrtest.cmdline import Namespace | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | from test.libregrtest.save_env import saved_test_environment | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | from test.libregrtest.utils import clear_caches, format_duration, print_warning | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestResult: | 
					
						
							|  |  |  |     def __init__( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         name: str, | 
					
						
							|  |  |  |         duration_sec: float = 0.0, | 
					
						
							|  |  |  |         xml_data: list[str] | None = None, | 
					
						
							|  |  |  |     ) -> None: | 
					
						
							|  |  |  |         self.name = name | 
					
						
							|  |  |  |         self.duration_sec = duration_sec | 
					
						
							|  |  |  |         self.xml_data = xml_data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} finished" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Passed(TestResult): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} passed" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Failed(TestResult): | 
					
						
							|  |  |  |     def __init__( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         name: str, | 
					
						
							|  |  |  |         duration_sec: float = 0.0, | 
					
						
							|  |  |  |         xml_data: list[str] | None = None, | 
					
						
							|  |  |  |         errors: list[tuple[str, str]] | None = None, | 
					
						
							|  |  |  |         failures: list[tuple[str, str]] | None = None, | 
					
						
							|  |  |  |     ) -> None: | 
					
						
							|  |  |  |         super().__init__(name, duration_sec=duration_sec, xml_data=xml_data) | 
					
						
							|  |  |  |         self.errors = errors | 
					
						
							|  |  |  |         self.failures = failures | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         if self.errors and self.failures: | 
					
						
							|  |  |  |             le = len(self.errors) | 
					
						
							|  |  |  |             lf = len(self.failures) | 
					
						
							|  |  |  |             error_s = "error" + ("s" if le > 1 else "") | 
					
						
							|  |  |  |             failure_s = "failure" + ("s" if lf > 1 else "") | 
					
						
							|  |  |  |             return f"{self.name} failed ({le} {error_s}, {lf} {failure_s})" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.errors: | 
					
						
							|  |  |  |             le = len(self.errors) | 
					
						
							|  |  |  |             error_s = "error" + ("s" if le > 1 else "") | 
					
						
							|  |  |  |             return f"{self.name} failed ({le} {error_s})" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.failures: | 
					
						
							|  |  |  |             lf = len(self.failures) | 
					
						
							|  |  |  |             failure_s = "failure" + ("s" if lf > 1 else "") | 
					
						
							|  |  |  |             return f"{self.name} failed ({lf} {failure_s})" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return f"{self.name} failed" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class UncaughtException(Failed): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} failed (uncaught exception)" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EnvChanged(Failed): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} failed (env changed)" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RefLeak(Failed): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} failed (reference leak)" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Skipped(TestResult): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} skipped" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ResourceDenied(Skipped): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} skipped (resource denied)" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Interrupted(TestResult): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} interrupted" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ChildError(Failed): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} crashed" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DidNotRun(TestResult): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} ran no tests" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Timeout(Failed): | 
					
						
							|  |  |  |     def __str__(self) -> str: | 
					
						
							|  |  |  |         return f"{self.name} timed out ({format_duration(self.duration_sec)})" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  | # Minimum duration of a test to display its duration or to mention that | 
					
						
							|  |  |  | # the test is running in background | 
					
						
							|  |  |  | PROGRESS_MIN_TIME = 30.0   # seconds | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | # small set of tests to determine if we have a basically functioning interpreter | 
					
						
							|  |  |  | # (i.e. if any of these fail, then anything else is likely to follow) | 
					
						
							|  |  |  | STDTESTS = [ | 
					
						
							|  |  |  |     'test_grammar', | 
					
						
							|  |  |  |     'test_opcodes', | 
					
						
							|  |  |  |     'test_dict', | 
					
						
							|  |  |  |     'test_builtin', | 
					
						
							|  |  |  |     'test_exceptions', | 
					
						
							|  |  |  |     'test_types', | 
					
						
							|  |  |  |     'test_unittest', | 
					
						
							|  |  |  |     'test_doctest', | 
					
						
							|  |  |  |     'test_doctest2', | 
					
						
							|  |  |  |     'test_support' | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # set of tests that we don't want to be executed when using regrtest | 
					
						
							|  |  |  | NOTTESTS = set() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | # used by --findleaks, store for gc.garbage | 
					
						
							| 
									
										
										
										
											2019-04-26 09:28:53 +02:00
										 |  |  | FOUND_GARBAGE = [] | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def is_failed(result: TestResult, ns: Namespace) -> bool: | 
					
						
							|  |  |  |     if isinstance(result, EnvChanged): | 
					
						
							| 
									
										
										
										
											2019-05-13 19:17:54 +02:00
										 |  |  |         return ns.fail_env_changed | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |     return isinstance(result, Failed) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def findtestdir(path=None): | 
					
						
							|  |  |  |     return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): | 
					
						
							|  |  |  |     """Return a list of all applicable test modules.""" | 
					
						
							|  |  |  |     testdir = findtestdir(testdir) | 
					
						
							|  |  |  |     names = os.listdir(testdir) | 
					
						
							|  |  |  |     tests = [] | 
					
						
							|  |  |  |     others = set(stdtests) | nottests | 
					
						
							|  |  |  |     for name in names: | 
					
						
							|  |  |  |         mod, ext = os.path.splitext(name) | 
					
						
							|  |  |  |         if mod[:5] == "test_" and ext in (".py", "") and mod not in others: | 
					
						
							|  |  |  |             tests.append(mod) | 
					
						
							|  |  |  |     return stdtests + sorted(tests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def get_abs_module(ns: Namespace, test_name: str) -> str: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     if test_name.startswith('test.') or ns.testdir: | 
					
						
							|  |  |  |         return test_name | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |         # Import it from the test package | 
					
						
							|  |  |  |         return 'test.' + test_name | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def _runtest(ns: Namespace, test_name: str) -> TestResult: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     # Handle faulthandler timeout, capture stdout+stderr, XML serialization | 
					
						
							|  |  |  |     # and measure time. | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  |     output_on_failure = ns.verbose3 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  |     use_timeout = (ns.timeout is not None) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     if use_timeout: | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  |         faulthandler.dump_traceback_later(ns.timeout, exit=True) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     start_time = time.perf_counter() | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2019-11-19 23:46:49 +00:00
										 |  |  |         support.set_match_tests(ns.match_tests, ns.ignore_tests) | 
					
						
							| 
									
										
										
										
											2018-09-18 09:10:26 -07:00
										 |  |  |         support.junit_xml_list = xml_list = [] if ns.xmlpath else None | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  |         if ns.failfast: | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |             support.failfast = True | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         if output_on_failure: | 
					
						
							|  |  |  |             support.verbose = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 14:08:18 +02:00
										 |  |  |             stream = io.StringIO() | 
					
						
							|  |  |  |             orig_stdout = sys.stdout | 
					
						
							|  |  |  |             orig_stderr = sys.stderr | 
					
						
							| 
									
										
										
										
											2021-10-13 17:35:21 +02:00
										 |  |  |             print_warning = support.print_warning | 
					
						
							|  |  |  |             orig_print_warnings_stderr = print_warning.orig_stderr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 01:52:22 +02:00
										 |  |  |             output = None | 
					
						
							| 
									
										
										
										
											2021-10-13 14:08:18 +02:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 sys.stdout = stream | 
					
						
							|  |  |  |                 sys.stderr = stream | 
					
						
							| 
									
										
										
										
											2021-10-13 17:35:21 +02:00
										 |  |  |                 # print_warning() writes into the temporary stream to preserve | 
					
						
							|  |  |  |                 # messages order. If support.environment_altered becomes true, | 
					
						
							|  |  |  |                 # warnings will be written to sys.stderr below. | 
					
						
							|  |  |  |                 print_warning.orig_stderr = stream | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |                 result = _runtest_inner(ns, test_name, | 
					
						
							|  |  |  |                                         display_failure=False) | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |                 if not isinstance(result, Passed): | 
					
						
							| 
									
										
										
										
											2021-10-13 14:08:18 +02:00
										 |  |  |                     output = stream.getvalue() | 
					
						
							|  |  |  |             finally: | 
					
						
							|  |  |  |                 sys.stdout = orig_stdout | 
					
						
							|  |  |  |                 sys.stderr = orig_stderr | 
					
						
							| 
									
										
										
										
											2021-10-13 17:35:21 +02:00
										 |  |  |                 print_warning.orig_stderr = orig_print_warnings_stderr | 
					
						
							| 
									
										
										
										
											2021-10-13 01:52:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if output is not None: | 
					
						
							|  |  |  |                 sys.stderr.write(output) | 
					
						
							|  |  |  |                 sys.stderr.flush() | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             # Tell tests to be moderately quiet | 
					
						
							|  |  |  |             support.verbose = ns.verbose | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             result = _runtest_inner(ns, test_name, | 
					
						
							|  |  |  |                                     display_failure=not ns.verbose) | 
					
						
							| 
									
										
										
										
											2018-09-18 09:10:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if xml_list: | 
					
						
							|  |  |  |             import xml.etree.ElementTree as ET | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |             result.xml_data = [ | 
					
						
							|  |  |  |                 ET.tostring(x).decode('us-ascii') | 
					
						
							|  |  |  |                 for x in xml_list | 
					
						
							|  |  |  |             ] | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         result.duration_sec = time.perf_counter() - start_time | 
					
						
							|  |  |  |         return result | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     finally: | 
					
						
							|  |  |  |         if use_timeout: | 
					
						
							|  |  |  |             faulthandler.cancel_dump_traceback_later() | 
					
						
							| 
									
										
										
										
											2018-09-18 09:10:26 -07:00
										 |  |  |         support.junit_xml_list = None | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def runtest(ns: Namespace, test_name: str) -> TestResult: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     """Run a single test.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ns -- regrtest namespace of options | 
					
						
							|  |  |  |     test_name -- the name of the test | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |     Returns a TestResult sub-class depending on the kind of result received. | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     If ns.xmlpath is not None, xml_data is a list containing each | 
					
						
							|  |  |  |     generated testsuite element. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         return _runtest(ns, test_name) | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         if not ns.pgo: | 
					
						
							|  |  |  |             msg = traceback.format_exc() | 
					
						
							|  |  |  |             print(f"test {test_name} crashed -- {msg}", | 
					
						
							|  |  |  |                   file=sys.stderr, flush=True) | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return Failed(test_name) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _test_module(the_module): | 
					
						
							|  |  |  |     loader = unittest.TestLoader() | 
					
						
							|  |  |  |     tests = loader.loadTestsFromModule(the_module) | 
					
						
							|  |  |  |     for error in loader.errors: | 
					
						
							|  |  |  |         print(error, file=sys.stderr) | 
					
						
							|  |  |  |     if loader.errors: | 
					
						
							|  |  |  |         raise Exception("errors while loading tests") | 
					
						
							|  |  |  |     support.run_unittest(tests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def save_env(ns: Namespace, test_name: str): | 
					
						
							| 
									
										
										
										
											2021-03-22 23:52:13 +01:00
										 |  |  |     return saved_test_environment(test_name, ns.verbose, ns.quiet, pgo=ns.pgo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def _runtest_inner2(ns: Namespace, test_name: str) -> bool: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     # Load the test function, run the test function, handle huntrleaks | 
					
						
							|  |  |  |     # and findleaks to detect leaks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     abstest = get_abs_module(ns, test_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # remove the module from sys.module to reload it if it was already imported | 
					
						
							| 
									
										
										
										
											2021-03-23 01:08:49 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         del sys.modules[abstest] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     the_module = importlib.import_module(abstest) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 00:17:05 +01:00
										 |  |  |     if ns.huntrleaks: | 
					
						
							|  |  |  |         from test.libregrtest.refleak import dash_R | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     # If the test has a test_main, that will run the appropriate | 
					
						
							|  |  |  |     # tests.  If not, use normal unittest test loading. | 
					
						
							|  |  |  |     test_runner = getattr(the_module, "test_main", None) | 
					
						
							|  |  |  |     if test_runner is None: | 
					
						
							|  |  |  |         test_runner = functools.partial(_test_module, the_module) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2021-03-22 23:52:13 +01:00
										 |  |  |         with save_env(ns, test_name): | 
					
						
							|  |  |  |             if ns.huntrleaks: | 
					
						
							|  |  |  |                 # Return True if the test leaked references | 
					
						
							|  |  |  |                 refleak = dash_R(ns, test_name, test_runner) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 test_runner() | 
					
						
							|  |  |  |                 refleak = False | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     finally: | 
					
						
							| 
									
										
										
										
											2021-09-01 17:45:27 +02:00
										 |  |  |         # First kill any dangling references to open files etc. | 
					
						
							|  |  |  |         # This can also issue some ResourceWarnings which would otherwise get | 
					
						
							|  |  |  |         # triggered during the following test run, and possibly produce | 
					
						
							|  |  |  |         # failures. | 
					
						
							|  |  |  |         support.gc_collect() | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 17:45:27 +02:00
										 |  |  |         cleanup_test_droppings(test_name, ns.verbose) | 
					
						
							| 
									
										
										
										
											2019-04-26 09:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if gc.garbage: | 
					
						
							|  |  |  |         support.environment_altered = True | 
					
						
							|  |  |  |         print_warning(f"{test_name} created {len(gc.garbage)} " | 
					
						
							|  |  |  |                       f"uncollectable object(s).") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # move the uncollectable objects somewhere, | 
					
						
							|  |  |  |         # so we don't see them again | 
					
						
							|  |  |  |         FOUND_GARBAGE.extend(gc.garbage) | 
					
						
							|  |  |  |         gc.garbage.clear() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     support.reap_children() | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return refleak | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def _runtest_inner( | 
					
						
							|  |  |  |     ns: Namespace, test_name: str, display_failure: bool = True | 
					
						
							|  |  |  | ) -> TestResult: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     # Detect environment changes, handle exceptions. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Reset the environment_altered flag to detect if a test altered | 
					
						
							|  |  |  |     # the environment | 
					
						
							|  |  |  |     support.environment_altered = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.pgo: | 
					
						
							|  |  |  |         display_failure = False | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2016-11-11 11:46:44 +02:00
										 |  |  |         clear_caches() | 
					
						
							| 
									
										
										
										
											2021-09-01 17:45:27 +02:00
										 |  |  |         support.gc_collect() | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-22 23:52:13 +01:00
										 |  |  |         with save_env(ns, test_name): | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             refleak = _runtest_inner2(ns, test_name) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     except support.ResourceDenied as msg: | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  |         if not ns.quiet and not ns.pgo: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             print(f"{test_name} skipped -- {msg}", flush=True) | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return ResourceDenied(test_name) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     except unittest.SkipTest as msg: | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  |         if not ns.quiet and not ns.pgo: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             print(f"{test_name} skipped -- {msg}", flush=True) | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return Skipped(test_name) | 
					
						
							|  |  |  |     except support.TestFailedWithDetails as exc: | 
					
						
							|  |  |  |         msg = f"test {test_name} failed" | 
					
						
							|  |  |  |         if display_failure: | 
					
						
							|  |  |  |             msg = f"{msg} -- {exc}" | 
					
						
							|  |  |  |         print(msg, file=sys.stderr, flush=True) | 
					
						
							|  |  |  |         return Failed(test_name, errors=exc.errors, failures=exc.failures) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     except support.TestFailed as exc: | 
					
						
							|  |  |  |         msg = f"test {test_name} failed" | 
					
						
							|  |  |  |         if display_failure: | 
					
						
							|  |  |  |             msg = f"{msg} -- {exc}" | 
					
						
							|  |  |  |         print(msg, file=sys.stderr, flush=True) | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return Failed(test_name) | 
					
						
							| 
									
										
										
										
											2018-11-29 17:17:44 +00:00
										 |  |  |     except support.TestDidNotRun: | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return DidNotRun(test_name) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     except KeyboardInterrupt: | 
					
						
							| 
									
										
										
										
											2019-04-26 08:40:25 +02:00
										 |  |  |         print() | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return Interrupted(test_name) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     except: | 
					
						
							| 
									
										
										
										
											2016-08-22 14:28:52 +02:00
										 |  |  |         if not ns.pgo: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             msg = traceback.format_exc() | 
					
						
							|  |  |  |             print(f"test {test_name} crashed -- {msg}", | 
					
						
							|  |  |  |                   file=sys.stderr, flush=True) | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return UncaughtException(test_name) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |     if refleak: | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return RefLeak(test_name) | 
					
						
							| 
									
										
										
										
											2021-03-22 23:52:13 +01:00
										 |  |  |     if support.environment_altered: | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |         return EnvChanged(test_name) | 
					
						
							|  |  |  |     return Passed(test_name) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  | def cleanup_test_droppings(test_name: str, verbose: int) -> None: | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     # Try to clean up junk commonly left behind.  While tests shouldn't leave | 
					
						
							|  |  |  |     # any files or directories behind, when a test fails that can be tedious | 
					
						
							|  |  |  |     # for it to arrange.  The consequences can be especially nasty on Windows, | 
					
						
							|  |  |  |     # since if a test leaves a file open, it cannot be deleted by name (while | 
					
						
							|  |  |  |     # there's nothing we can do about that here either, we can display the | 
					
						
							|  |  |  |     # name of the offending test, which is a real help). | 
					
						
							| 
									
										
										
										
											2020-06-25 18:38:51 +08:00
										 |  |  |     for name in (os_helper.TESTFN,): | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         if not os.path.exists(name): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if os.path.isdir(name): | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             import shutil | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |             kind, nuker = "directory", shutil.rmtree | 
					
						
							|  |  |  |         elif os.path.isfile(name): | 
					
						
							|  |  |  |             kind, nuker = "file", os.unlink | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             raise RuntimeError(f"os.path says {name!r} exists but is neither " | 
					
						
							|  |  |  |                                f"directory nor file") | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if verbose: | 
					
						
							| 
									
										
										
										
											2020-04-23 19:03:52 +02:00
										 |  |  |             print_warning(f"{test_name} left behind {kind} {name!r}") | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             support.environment_altered = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |             import stat | 
					
						
							| 
									
										
										
										
											2019-02-25 14:32:27 -08:00
										 |  |  |             # fix possible permissions problems that might prevent cleanup | 
					
						
							|  |  |  |             os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |             nuker(name) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |         except Exception as exc: | 
					
						
							|  |  |  |             print_warning(f"{test_name} left behind {kind} {name!r} " | 
					
						
							|  |  |  |                           f"and it couldn't be removed: {exc}") |