Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 1 | import faulthandler |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 2 | import functools |
Victor Stinner | 75120d2 | 2019-04-26 09:28:53 +0200 | [diff] [blame] | 3 | import gc |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 4 | import importlib |
| 5 | import io |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 6 | import os |
| 7 | import sys |
| 8 | import time |
| 9 | import traceback |
| 10 | import unittest |
Victor Stinner | 75120d2 | 2019-04-26 09:28:53 +0200 | [diff] [blame] | 11 | |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 12 | from test import support |
Hai Shi | f7ba40b | 2020-06-25 18:38:51 +0800 | [diff] [blame] | 13 | from test.support import os_helper |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 14 | from test.libregrtest.cmdline import Namespace |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 15 | from test.libregrtest.save_env import saved_test_environment |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 16 | from test.libregrtest.utils import clear_caches, format_duration, print_warning |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 17 | |
| 18 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 19 | class TestResult: |
| 20 | def __init__( |
| 21 | self, |
| 22 | name: str, |
| 23 | duration_sec: float = 0.0, |
| 24 | xml_data: list[str] | None = None, |
| 25 | ) -> None: |
| 26 | self.name = name |
| 27 | self.duration_sec = duration_sec |
| 28 | self.xml_data = xml_data |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 29 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 30 | def __str__(self) -> str: |
| 31 | return f"{self.name} finished" |
| 32 | |
| 33 | |
| 34 | class Passed(TestResult): |
| 35 | def __str__(self) -> str: |
| 36 | return f"{self.name} passed" |
| 37 | |
| 38 | |
| 39 | class Failed(TestResult): |
| 40 | def __init__( |
| 41 | self, |
| 42 | name: str, |
| 43 | duration_sec: float = 0.0, |
| 44 | xml_data: list[str] | None = None, |
| 45 | errors: list[tuple[str, str]] | None = None, |
| 46 | failures: list[tuple[str, str]] | None = None, |
| 47 | ) -> None: |
| 48 | super().__init__(name, duration_sec=duration_sec, xml_data=xml_data) |
| 49 | self.errors = errors |
| 50 | self.failures = failures |
| 51 | |
| 52 | def __str__(self) -> str: |
| 53 | if self.errors and self.failures: |
| 54 | le = len(self.errors) |
| 55 | lf = len(self.failures) |
| 56 | error_s = "error" + ("s" if le > 1 else "") |
| 57 | failure_s = "failure" + ("s" if lf > 1 else "") |
| 58 | return f"{self.name} failed ({le} {error_s}, {lf} {failure_s})" |
| 59 | |
| 60 | if self.errors: |
| 61 | le = len(self.errors) |
| 62 | error_s = "error" + ("s" if le > 1 else "") |
| 63 | return f"{self.name} failed ({le} {error_s})" |
| 64 | |
| 65 | if self.failures: |
| 66 | lf = len(self.failures) |
| 67 | failure_s = "failure" + ("s" if lf > 1 else "") |
| 68 | return f"{self.name} failed ({lf} {failure_s})" |
| 69 | |
| 70 | return f"{self.name} failed" |
| 71 | |
| 72 | |
| 73 | class UncaughtException(Failed): |
| 74 | def __str__(self) -> str: |
| 75 | return f"{self.name} failed (uncaught exception)" |
| 76 | |
| 77 | |
| 78 | class EnvChanged(Failed): |
| 79 | def __str__(self) -> str: |
| 80 | return f"{self.name} failed (env changed)" |
| 81 | |
| 82 | |
| 83 | class RefLeak(Failed): |
| 84 | def __str__(self) -> str: |
| 85 | return f"{self.name} failed (reference leak)" |
| 86 | |
| 87 | |
| 88 | class Skipped(TestResult): |
| 89 | def __str__(self) -> str: |
| 90 | return f"{self.name} skipped" |
| 91 | |
| 92 | |
| 93 | class ResourceDenied(Skipped): |
| 94 | def __str__(self) -> str: |
| 95 | return f"{self.name} skipped (resource denied)" |
| 96 | |
| 97 | |
| 98 | class Interrupted(TestResult): |
| 99 | def __str__(self) -> str: |
| 100 | return f"{self.name} interrupted" |
| 101 | |
| 102 | |
| 103 | class ChildError(Failed): |
| 104 | def __str__(self) -> str: |
| 105 | return f"{self.name} crashed" |
| 106 | |
| 107 | |
| 108 | class DidNotRun(TestResult): |
| 109 | def __str__(self) -> str: |
| 110 | return f"{self.name} ran no tests" |
| 111 | |
| 112 | |
| 113 | class Timeout(Failed): |
| 114 | def __str__(self) -> str: |
| 115 | return f"{self.name} timed out ({format_duration(self.duration_sec)})" |
| 116 | |
Victor Stinner | 1b8b423 | 2016-05-20 13:37:40 +0200 | [diff] [blame] | 117 | |
Victor Stinner | 69649f2 | 2016-03-23 12:14:10 +0100 | [diff] [blame] | 118 | # Minimum duration of a test to display its duration or to mention that |
| 119 | # the test is running in background |
| 120 | PROGRESS_MIN_TIME = 30.0 # seconds |
| 121 | |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 122 | # small set of tests to determine if we have a basically functioning interpreter |
| 123 | # (i.e. if any of these fail, then anything else is likely to follow) |
| 124 | STDTESTS = [ |
| 125 | 'test_grammar', |
| 126 | 'test_opcodes', |
| 127 | 'test_dict', |
| 128 | 'test_builtin', |
| 129 | 'test_exceptions', |
| 130 | 'test_types', |
| 131 | 'test_unittest', |
| 132 | 'test_doctest', |
| 133 | 'test_doctest2', |
| 134 | 'test_support' |
| 135 | ] |
| 136 | |
| 137 | # set of tests that we don't want to be executed when using regrtest |
| 138 | NOTTESTS = set() |
| 139 | |
| 140 | |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 141 | # used by --findleaks, store for gc.garbage |
Victor Stinner | 75120d2 | 2019-04-26 09:28:53 +0200 | [diff] [blame] | 142 | FOUND_GARBAGE = [] |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 143 | |
| 144 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 145 | def is_failed(result: TestResult, ns: Namespace) -> bool: |
| 146 | if isinstance(result, EnvChanged): |
Victor Stinner | b0917df | 2019-05-13 19:17:54 +0200 | [diff] [blame] | 147 | return ns.fail_env_changed |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 148 | return isinstance(result, Failed) |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 149 | |
| 150 | |
| 151 | def findtestdir(path=None): |
| 152 | return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir |
Victor Stinner | 1b8b423 | 2016-05-20 13:37:40 +0200 | [diff] [blame] | 153 | |
| 154 | |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 155 | def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): |
| 156 | """Return a list of all applicable test modules.""" |
| 157 | testdir = findtestdir(testdir) |
| 158 | names = os.listdir(testdir) |
| 159 | tests = [] |
| 160 | others = set(stdtests) | nottests |
| 161 | for name in names: |
| 162 | mod, ext = os.path.splitext(name) |
| 163 | if mod[:5] == "test_" and ext in (".py", "") and mod not in others: |
| 164 | tests.append(mod) |
| 165 | return stdtests + sorted(tests) |
| 166 | |
| 167 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 168 | def get_abs_module(ns: Namespace, test_name: str) -> str: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 169 | if test_name.startswith('test.') or ns.testdir: |
| 170 | return test_name |
mlouielu | a49c935 | 2017-06-16 17:36:19 +0800 | [diff] [blame] | 171 | else: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 172 | # Import it from the test package |
| 173 | return 'test.' + test_name |
mlouielu | a49c935 | 2017-06-16 17:36:19 +0800 | [diff] [blame] | 174 | |
| 175 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 176 | def _runtest(ns: Namespace, test_name: str) -> TestResult: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 177 | # Handle faulthandler timeout, capture stdout+stderr, XML serialization |
| 178 | # and measure time. |
| 179 | |
| 180 | output_on_failure = ns.verbose3 |
| 181 | |
| 182 | use_timeout = (ns.timeout is not None) |
| 183 | if use_timeout: |
| 184 | faulthandler.dump_traceback_later(ns.timeout, exit=True) |
| 185 | |
| 186 | start_time = time.perf_counter() |
| 187 | try: |
Pablo Galindo | e0cd8aa | 2019-11-19 23:46:49 +0000 | [diff] [blame] | 188 | support.set_match_tests(ns.match_tests, ns.ignore_tests) |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 189 | support.junit_xml_list = xml_list = [] if ns.xmlpath else None |
| 190 | if ns.failfast: |
| 191 | support.failfast = True |
| 192 | |
| 193 | if output_on_failure: |
| 194 | support.verbose = True |
| 195 | |
| 196 | stream = io.StringIO() |
| 197 | orig_stdout = sys.stdout |
| 198 | orig_stderr = sys.stderr |
| 199 | try: |
| 200 | sys.stdout = stream |
| 201 | sys.stderr = stream |
| 202 | result = _runtest_inner(ns, test_name, |
| 203 | display_failure=False) |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 204 | if not isinstance(result, Passed): |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 205 | output = stream.getvalue() |
| 206 | orig_stderr.write(output) |
| 207 | orig_stderr.flush() |
| 208 | finally: |
| 209 | sys.stdout = orig_stdout |
| 210 | sys.stderr = orig_stderr |
| 211 | else: |
| 212 | # Tell tests to be moderately quiet |
| 213 | support.verbose = ns.verbose |
| 214 | |
| 215 | result = _runtest_inner(ns, test_name, |
| 216 | display_failure=not ns.verbose) |
| 217 | |
| 218 | if xml_list: |
| 219 | import xml.etree.ElementTree as ET |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 220 | result.xml_data = [ |
| 221 | ET.tostring(x).decode('us-ascii') |
| 222 | for x in xml_list |
| 223 | ] |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 224 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 225 | result.duration_sec = time.perf_counter() - start_time |
| 226 | return result |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 227 | finally: |
| 228 | if use_timeout: |
| 229 | faulthandler.cancel_dump_traceback_later() |
| 230 | support.junit_xml_list = None |
| 231 | |
| 232 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 233 | def runtest(ns: Namespace, test_name: str) -> TestResult: |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 234 | """Run a single test. |
| 235 | |
Victor Stinner | ab98367 | 2016-08-22 14:28:52 +0200 | [diff] [blame] | 236 | ns -- regrtest namespace of options |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 237 | test_name -- the name of the test |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 238 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 239 | Returns a TestResult sub-class depending on the kind of result received. |
Steve Dower | d0f49d2 | 2018-09-18 09:10:26 -0700 | [diff] [blame] | 240 | |
| 241 | If ns.xmlpath is not None, xml_data is a list containing each |
| 242 | generated testsuite element. |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 243 | """ |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 244 | try: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 245 | return _runtest(ns, test_name) |
| 246 | except: |
| 247 | if not ns.pgo: |
| 248 | msg = traceback.format_exc() |
| 249 | print(f"test {test_name} crashed -- {msg}", |
| 250 | file=sys.stderr, flush=True) |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 251 | return Failed(test_name) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 252 | |
| 253 | |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 254 | def _test_module(the_module): |
| 255 | loader = unittest.TestLoader() |
| 256 | tests = loader.loadTestsFromModule(the_module) |
| 257 | for error in loader.errors: |
| 258 | print(error, file=sys.stderr) |
| 259 | if loader.errors: |
| 260 | raise Exception("errors while loading tests") |
| 261 | support.run_unittest(tests) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 262 | |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 263 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 264 | def save_env(ns: Namespace, test_name: str): |
Victor Stinner | 532e063 | 2021-03-22 23:52:13 +0100 | [diff] [blame] | 265 | return saved_test_environment(test_name, ns.verbose, ns.quiet, pgo=ns.pgo) |
| 266 | |
| 267 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 268 | def _runtest_inner2(ns: Namespace, test_name: str) -> bool: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 269 | # Load the test function, run the test function, handle huntrleaks |
| 270 | # and findleaks to detect leaks |
| 271 | |
| 272 | abstest = get_abs_module(ns, test_name) |
| 273 | |
| 274 | # remove the module from sys.module to reload it if it was already imported |
Victor Stinner | 0473fb2 | 2021-03-23 01:08:49 +0100 | [diff] [blame] | 275 | try: |
| 276 | del sys.modules[abstest] |
| 277 | except KeyError: |
| 278 | pass |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 279 | |
| 280 | the_module = importlib.import_module(abstest) |
| 281 | |
Victor Stinner | 10417dd | 2021-03-23 00:17:05 +0100 | [diff] [blame] | 282 | if ns.huntrleaks: |
| 283 | from test.libregrtest.refleak import dash_R |
| 284 | |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 285 | # If the test has a test_main, that will run the appropriate |
| 286 | # tests. If not, use normal unittest test loading. |
| 287 | test_runner = getattr(the_module, "test_main", None) |
| 288 | if test_runner is None: |
| 289 | test_runner = functools.partial(_test_module, the_module) |
| 290 | |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 291 | try: |
Victor Stinner | 532e063 | 2021-03-22 23:52:13 +0100 | [diff] [blame] | 292 | with save_env(ns, test_name): |
| 293 | if ns.huntrleaks: |
| 294 | # Return True if the test leaked references |
| 295 | refleak = dash_R(ns, test_name, test_runner) |
| 296 | else: |
| 297 | test_runner() |
| 298 | refleak = False |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 299 | finally: |
| 300 | cleanup_test_droppings(test_name, ns.verbose) |
| 301 | |
Victor Stinner | 75120d2 | 2019-04-26 09:28:53 +0200 | [diff] [blame] | 302 | support.gc_collect() |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 303 | |
Victor Stinner | 75120d2 | 2019-04-26 09:28:53 +0200 | [diff] [blame] | 304 | if gc.garbage: |
| 305 | support.environment_altered = True |
| 306 | print_warning(f"{test_name} created {len(gc.garbage)} " |
| 307 | f"uncollectable object(s).") |
| 308 | |
| 309 | # move the uncollectable objects somewhere, |
| 310 | # so we don't see them again |
| 311 | FOUND_GARBAGE.extend(gc.garbage) |
| 312 | gc.garbage.clear() |
| 313 | |
| 314 | support.reap_children() |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 315 | |
| 316 | return refleak |
| 317 | |
| 318 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 319 | def _runtest_inner( |
| 320 | ns: Namespace, test_name: str, display_failure: bool = True |
| 321 | ) -> TestResult: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 322 | # Detect environment changes, handle exceptions. |
| 323 | |
| 324 | # Reset the environment_altered flag to detect if a test altered |
| 325 | # the environment |
| 326 | support.environment_altered = False |
| 327 | |
| 328 | if ns.pgo: |
| 329 | display_failure = False |
| 330 | |
| 331 | try: |
Serhiy Storchaka | 8391026 | 2016-11-11 11:46:44 +0200 | [diff] [blame] | 332 | clear_caches() |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 333 | |
Victor Stinner | 532e063 | 2021-03-22 23:52:13 +0100 | [diff] [blame] | 334 | with save_env(ns, test_name): |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 335 | refleak = _runtest_inner2(ns, test_name) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 336 | except support.ResourceDenied as msg: |
Victor Stinner | ab98367 | 2016-08-22 14:28:52 +0200 | [diff] [blame] | 337 | if not ns.quiet and not ns.pgo: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 338 | print(f"{test_name} skipped -- {msg}", flush=True) |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 339 | return ResourceDenied(test_name) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 340 | except unittest.SkipTest as msg: |
Victor Stinner | ab98367 | 2016-08-22 14:28:52 +0200 | [diff] [blame] | 341 | if not ns.quiet and not ns.pgo: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 342 | print(f"{test_name} skipped -- {msg}", flush=True) |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 343 | return Skipped(test_name) |
| 344 | except support.TestFailedWithDetails as exc: |
| 345 | msg = f"test {test_name} failed" |
| 346 | if display_failure: |
| 347 | msg = f"{msg} -- {exc}" |
| 348 | print(msg, file=sys.stderr, flush=True) |
| 349 | return Failed(test_name, errors=exc.errors, failures=exc.failures) |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 350 | except support.TestFailed as exc: |
| 351 | msg = f"test {test_name} failed" |
| 352 | if display_failure: |
| 353 | msg = f"{msg} -- {exc}" |
| 354 | print(msg, file=sys.stderr, flush=True) |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 355 | return Failed(test_name) |
Pablo Galindo | 9724348 | 2018-11-29 17:17:44 +0000 | [diff] [blame] | 356 | except support.TestDidNotRun: |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 357 | return DidNotRun(test_name) |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 358 | except KeyboardInterrupt: |
Victor Stinner | 3cde440 | 2019-04-26 08:40:25 +0200 | [diff] [blame] | 359 | print() |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 360 | return Interrupted(test_name) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 361 | except: |
Victor Stinner | ab98367 | 2016-08-22 14:28:52 +0200 | [diff] [blame] | 362 | if not ns.pgo: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 363 | msg = traceback.format_exc() |
| 364 | print(f"test {test_name} crashed -- {msg}", |
| 365 | file=sys.stderr, flush=True) |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 366 | return UncaughtException(test_name) |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 367 | |
| 368 | if refleak: |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 369 | return RefLeak(test_name) |
Victor Stinner | 532e063 | 2021-03-22 23:52:13 +0100 | [diff] [blame] | 370 | if support.environment_altered: |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 371 | return EnvChanged(test_name) |
| 372 | return Passed(test_name) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 373 | |
| 374 | |
Miss Islington (bot) | 9608719 | 2021-07-22 13:30:44 -0700 | [diff] [blame^] | 375 | def cleanup_test_droppings(test_name: str, verbose: int) -> None: |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 376 | # First kill any dangling references to open files etc. |
| 377 | # This can also issue some ResourceWarnings which would otherwise get |
| 378 | # triggered during the following test run, and possibly produce failures. |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 379 | support.gc_collect() |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 380 | |
| 381 | # Try to clean up junk commonly left behind. While tests shouldn't leave |
| 382 | # any files or directories behind, when a test fails that can be tedious |
| 383 | # for it to arrange. The consequences can be especially nasty on Windows, |
| 384 | # since if a test leaves a file open, it cannot be deleted by name (while |
| 385 | # there's nothing we can do about that here either, we can display the |
| 386 | # name of the offending test, which is a real help). |
Hai Shi | f7ba40b | 2020-06-25 18:38:51 +0800 | [diff] [blame] | 387 | for name in (os_helper.TESTFN,): |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 388 | if not os.path.exists(name): |
| 389 | continue |
| 390 | |
| 391 | if os.path.isdir(name): |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 392 | import shutil |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 393 | kind, nuker = "directory", shutil.rmtree |
| 394 | elif os.path.isfile(name): |
| 395 | kind, nuker = "file", os.unlink |
| 396 | else: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 397 | raise RuntimeError(f"os.path says {name!r} exists but is neither " |
| 398 | f"directory nor file") |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 399 | |
| 400 | if verbose: |
Victor Stinner | d663d34 | 2020-04-23 19:03:52 +0200 | [diff] [blame] | 401 | print_warning(f"{test_name} left behind {kind} {name!r}") |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 402 | support.environment_altered = True |
| 403 | |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 404 | try: |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 405 | import stat |
Anthony Sottile | 8377cd4 | 2019-02-25 14:32:27 -0800 | [diff] [blame] | 406 | # fix possible permissions problems that might prevent cleanup |
| 407 | os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) |
Victor Stinner | 3844fe5 | 2015-09-26 10:38:01 +0200 | [diff] [blame] | 408 | nuker(name) |
Victor Stinner | 4d29983 | 2019-04-26 04:08:53 +0200 | [diff] [blame] | 409 | except Exception as exc: |
| 410 | print_warning(f"{test_name} left behind {kind} {name!r} " |
| 411 | f"and it couldn't be removed: {exc}") |