| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2016-03-22 15:14:09 +01:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | from test import support | 
					
						
							|  |  |  | from test.support import os_helper | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 09:02:35 +02:00
										 |  |  | from .cmdline import _parse_args, Namespace | 
					
						
							|  |  |  | from .findtests import findtests, split_test_packages | 
					
						
							|  |  |  | from .logger import Logger | 
					
						
							|  |  |  | from .result import State | 
					
						
							|  |  |  | from .runtests import RunTests, HuntRefleak | 
					
						
							|  |  |  | from .setup import setup_process, setup_test_dir | 
					
						
							|  |  |  | from .single import run_single_test, PROGRESS_MIN_TIME | 
					
						
							|  |  |  | from .pgo import setup_pgo_tests | 
					
						
							|  |  |  | from .results import TestResults | 
					
						
							|  |  |  | from .utils import ( | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     StrPath, StrJSON, TestName, TestList, TestTuple, FilterTuple, | 
					
						
							| 
									
										
										
										
											2023-09-11 02:07:18 +02:00
										 |  |  |     strip_py_suffix, count, format_duration, | 
					
						
							|  |  |  |     printlist, get_build_info, get_temp_dir, get_work_dir, exit_timeout, | 
					
						
							|  |  |  |      abs_module_name) | 
					
						
							| 
									
										
										
										
											2019-09-18 08:29:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							| 
									
										
										
										
											2021-11-12 16:19:09 +01:00
										 |  |  |     single, randomize, use_resources, trace, coverdir, | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  |     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. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-09-09 00:41:26 +02:00
										 |  |  |     def __init__(self, ns: Namespace): | 
					
						
							| 
									
										
										
										
											2023-09-11 03:46:26 +02:00
										 |  |  |         # Log verbosity | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         self.verbose: int = int(ns.verbose) | 
					
						
							| 
									
										
										
										
											2023-09-11 03:46:26 +02:00
										 |  |  |         self.quiet: bool = ns.quiet | 
					
						
							|  |  |  |         self.pgo: bool = ns.pgo | 
					
						
							|  |  |  |         self.pgo_extended: bool = ns.pgo_extended | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Test results | 
					
						
							|  |  |  |         self.results: TestResults = TestResults() | 
					
						
							|  |  |  |         self.first_state: str | None = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Logger | 
					
						
							|  |  |  |         self.logger = Logger(self.results, self.quiet, self.pgo) | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         # Actions | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         self.want_header: bool = ns.header | 
					
						
							|  |  |  |         self.want_list_tests: bool = ns.list_tests | 
					
						
							|  |  |  |         self.want_list_cases: bool = ns.list_cases | 
					
						
							|  |  |  |         self.want_wait: bool = ns.wait | 
					
						
							|  |  |  |         self.want_cleanup: bool = ns.cleanup | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.want_rerun: bool = ns.rerun | 
					
						
							|  |  |  |         self.want_run_leaks: bool = ns.runleaks | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Select tests | 
					
						
							|  |  |  |         if ns.match_tests: | 
					
						
							|  |  |  |             self.match_tests: FilterTuple = tuple(ns.match_tests) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.match_tests = None | 
					
						
							|  |  |  |         if ns.ignore_tests: | 
					
						
							|  |  |  |             self.ignore_tests: FilterTuple = tuple(ns.ignore_tests) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.ignore_tests = None | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         self.exclude: bool = ns.exclude | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.fromfile: StrPath | None = ns.fromfile | 
					
						
							|  |  |  |         self.starting_test: TestName | None = ns.start | 
					
						
							|  |  |  |         self.cmdline_args: TestList = ns.args | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         # Workers | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |         if ns.use_mp is None: | 
					
						
							|  |  |  |             num_workers = 0  # run sequentially | 
					
						
							|  |  |  |         elif ns.use_mp <= 0: | 
					
						
							|  |  |  |             num_workers = -1  # use the number of CPUs | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             num_workers = ns.use_mp | 
					
						
							|  |  |  |         self.num_workers: int = num_workers | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.worker_json: StrJSON | None = ns.worker_json | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         # Options to run tests | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         self.fail_fast: bool = ns.failfast | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |         self.fail_env_changed: bool = ns.fail_env_changed | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.fail_rerun: bool = ns.fail_rerun | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         self.forever: bool = ns.forever | 
					
						
							|  |  |  |         self.randomize: bool = ns.randomize | 
					
						
							|  |  |  |         self.random_seed: int | None = ns.random_seed | 
					
						
							|  |  |  |         self.output_on_failure: bool = ns.verbose3 | 
					
						
							|  |  |  |         self.timeout: float | None = ns.timeout | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |         if ns.huntrleaks: | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |             warmups, runs, filename = ns.huntrleaks | 
					
						
							|  |  |  |             filename = os.path.abspath(filename) | 
					
						
							|  |  |  |             self.hunt_refleak: HuntRefleak = HuntRefleak(warmups, runs, filename) | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |         else: | 
					
						
							|  |  |  |             self.hunt_refleak = None | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.test_dir: StrPath | None = ns.testdir | 
					
						
							|  |  |  |         self.junit_filename: StrPath | None = ns.xmlpath | 
					
						
							| 
									
										
										
										
											2023-09-10 01:41:21 +02:00
										 |  |  |         self.memory_limit: str | None = ns.memlimit | 
					
						
							|  |  |  |         self.gc_threshold: int | None = ns.threshold | 
					
						
							|  |  |  |         self.use_resources: list[str] = ns.use_resources | 
					
						
							|  |  |  |         self.python_cmd: list[str] | None = ns.python | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.coverage: bool = ns.trace | 
					
						
							|  |  |  |         self.coverage_dir: StrPath | None = ns.coverdir | 
					
						
							|  |  |  |         self.tmp_dir: StrPath | None = ns.tempdir | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # tests | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         self.first_runtests: RunTests | None = None | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         # used by --slowest | 
					
						
							|  |  |  |         self.print_slowest: bool = ns.print_slow | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used to display the progress bar "[ 3/100]" | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  |         self.start_time = time.perf_counter() | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         # used by --single | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         self.single_test_run: bool = ns.single | 
					
						
							|  |  |  |         self.next_single_test: TestName | None = None | 
					
						
							|  |  |  |         self.next_single_filename: StrPath | None = None | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 16:15:16 +02:00
										 |  |  |     def log(self, line=''): | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         self.logger.log(line) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     def find_tests(self, tests: TestList | None = None) -> tuple[TestTuple, TestList | None]: | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         if self.single_test_run: | 
					
						
							| 
									
										
										
										
											2019-05-14 15:49:16 +02:00
										 |  |  |             self.next_single_filename = os.path.join(self.tmp_dir, 'pynexttest') | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 with open(self.next_single_filename, 'r') as fp: | 
					
						
							|  |  |  |                     next_test = fp.read().strip() | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |                     tests = [next_test] | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             except OSError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if self.fromfile: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             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') | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |             with open(os.path.join(os_helper.SAVEDCWD, self.fromfile)) as fp: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |                 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: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |                         tests.append(match.group()) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         strip_py_suffix(tests) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         if self.pgo: | 
					
						
							| 
									
										
										
										
											2019-07-23 21:33:48 -07:00
										 |  |  |             # add default PGO tests if no tests are specified | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |             setup_pgo_tests(self.cmdline_args, self.pgo_extended) | 
					
						
							| 
									
										
										
										
											2019-07-22 12:54:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         exclude_tests = set() | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if self.exclude: | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |             for arg in self.cmdline_args: | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |                 exclude_tests.add(arg) | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |             self.cmdline_args = [] | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |         alltests = findtests(testdir=self.test_dir, | 
					
						
							|  |  |  |                              exclude=exclude_tests) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if not self.fromfile: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             selected = tests or self.cmdline_args | 
					
						
							|  |  |  |             if selected: | 
					
						
							|  |  |  |                 selected = split_test_packages(selected) | 
					
						
							| 
									
										
										
										
											2023-08-24 04:44:58 +02:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |                 selected = alltests | 
					
						
							| 
									
										
										
										
											2016-03-24 09:43:00 +01:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             selected = tests | 
					
						
							| 
									
										
										
										
											2023-08-24 04:44:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         if self.single_test_run: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             selected = selected[:1] | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |                 pos = alltests.index(selected[0]) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |                 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. | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if self.starting_test: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |                 del selected[:selected.index(self.starting_test)] | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             except ValueError: | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |                 print(f"Cannot find starting test: {self.starting_test}") | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |                 sys.exit(1) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if self.randomize: | 
					
						
							|  |  |  |             if self.random_seed is None: | 
					
						
							|  |  |  |                 self.random_seed = random.randrange(100_000_000) | 
					
						
							|  |  |  |             random.seed(self.random_seed) | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             random.shuffle(selected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return (tuple(selected), tests) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     def list_tests(tests: TestTuple): | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         for name in tests: | 
					
						
							| 
									
										
										
										
											2015-10-03 00:21:12 +02:00
										 |  |  |             print(name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  |     def _list_cases(self, suite): | 
					
						
							|  |  |  |         for test in suite: | 
					
						
							|  |  |  |             if isinstance(test, unittest.loader._FailedTest): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if isinstance(test, unittest.TestSuite): | 
					
						
							|  |  |  |                 self._list_cases(test) | 
					
						
							|  |  |  |             elif isinstance(test, unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2017-11-21 15:34:02 -08:00
										 |  |  |                 if support.match_test(test): | 
					
						
							| 
									
										
										
										
											2017-06-26 14:18:51 +02:00
										 |  |  |                     print(test.id()) | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     def list_cases(self, tests: TestTuple): | 
					
						
							| 
									
										
										
										
											2017-06-26 14:18:51 +02:00
										 |  |  |         support.verbose = False | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         support.set_match_tests(self.match_tests, self.ignore_tests) | 
					
						
							| 
									
										
										
										
											2017-06-26 14:18:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         skipped = [] | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         for test_name in tests: | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |             module_name = abs_module_name(test_name, self.test_dir) | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |                 suite = unittest.defaultTestLoader.loadTestsFromName(module_name) | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  |                 self._list_cases(suite) | 
					
						
							|  |  |  |             except unittest.SkipTest: | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |                 skipped.append(test_name) | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         if skipped: | 
					
						
							|  |  |  |             sys.stdout.flush() | 
					
						
							|  |  |  |             stderr = sys.stderr | 
					
						
							|  |  |  |             print(file=stderr) | 
					
						
							|  |  |  |             print(count(len(skipped), "test"), "skipped:", file=stderr) | 
					
						
							|  |  |  |             printlist(skipped, file=stderr) | 
					
						
							| 
									
										
										
										
											2017-06-16 17:36:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |     def _rerun_failed_tests(self, runtests: RunTests): | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         # Configure the runner to re-run tests | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |         if self.num_workers == 0: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             # Always run tests in fresh processes to have more deterministic | 
					
						
							|  |  |  |             # initial state. Don't re-run tests in parallel but limit to a | 
					
						
							|  |  |  |             # single worker process to have side effects (on the system load | 
					
						
							|  |  |  |             # and timings) between tests. | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |             self.num_workers = 1 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         tests, match_tests_dict = self.results.prepare_rerun() | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Re-run failed tests | 
					
						
							|  |  |  |         self.log(f"Re-running {len(tests)} failed tests in verbose mode in subprocesses") | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         runtests = runtests.copy( | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |             tests=tests, | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |             rerun=True, | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |             verbose=True, | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |             forever=False, | 
					
						
							|  |  |  |             fail_fast=False, | 
					
						
							|  |  |  |             match_tests_dict=match_tests_dict, | 
					
						
							|  |  |  |             output_on_failure=False) | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         self.logger.set_tests(runtests) | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |         self._run_tests_mp(runtests, self.num_workers) | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         return runtests | 
					
						
							| 
									
										
										
										
											2022-06-21 14:42:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |     def rerun_failed_tests(self, runtests: RunTests): | 
					
						
							| 
									
										
										
										
											2023-09-10 01:41:21 +02:00
										 |  |  |         if self.python_cmd: | 
					
						
							| 
									
										
										
										
											2022-06-21 14:42:32 +02:00
										 |  |  |             # Temp patch for https://github.com/python/cpython/issues/94052 | 
					
						
							|  |  |  |             self.log( | 
					
						
							|  |  |  |                 "Re-running failed tests is not supported with --python " | 
					
						
							|  |  |  |                 "host runner option." | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         self.first_state = self.get_state() | 
					
						
							| 
									
										
										
										
											2021-09-07 18:21:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         print() | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         rerun_runtests = self._rerun_failed_tests(runtests) | 
					
						
							| 
									
										
										
										
											2019-04-26 09:28:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         if self.results.bad: | 
					
						
							|  |  |  |             print(count(len(self.results.bad), 'test'), "failed again:") | 
					
						
							|  |  |  |             printlist(self.results.bad) | 
					
						
							| 
									
										
										
										
											2015-09-30 02:32:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         self.display_result(rerun_runtests) | 
					
						
							| 
									
										
										
										
											2018-05-28 21:03:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |     def display_result(self, runtests): | 
					
						
							| 
									
										
										
										
											2018-05-28 21:03:43 +02:00
										 |  |  |         # If running the test suite for PGO then no one cares about results. | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         if runtests.pgo: | 
					
						
							| 
									
										
										
										
											2018-05-28 21:03:43 +02:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         state = self.get_state() | 
					
						
							| 
									
										
										
										
											2018-05-28 21:03:43 +02:00
										 |  |  |         print() | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         print(f"== Tests result: {state} ==") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         self.results.display_result(runtests.tests, | 
					
						
							|  |  |  |                                     self.quiet, self.print_slowest) | 
					
						
							| 
									
										
										
										
											2018-11-29 17:17:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |     def run_test(self, test_name: TestName, runtests: RunTests, tracer): | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |         if tracer is not None: | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |             # If we're tracing code coverage, then we don't exit with status | 
					
						
							|  |  |  |             # if on a false return value from main. | 
					
						
							| 
									
										
										
										
											2023-09-10 01:41:21 +02:00
										 |  |  |             cmd = ('result = run_single_test(test_name, runtests)') | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |             namespace = dict(locals()) | 
					
						
							|  |  |  |             tracer.runctx(cmd, globals=globals(), locals=namespace) | 
					
						
							|  |  |  |             result = namespace['result'] | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2023-09-10 01:41:21 +02:00
										 |  |  |             result = run_single_test(test_name, runtests) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         self.results.accumulate_result(result, runtests) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def run_tests_sequentially(self, runtests): | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         if self.coverage: | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |             import trace | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |             tracer = trace.Trace(trace=False, count=True) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             tracer = None | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         save_modules = sys.modules.keys() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 18:29:44 +02:00
										 |  |  |         msg = "Run tests sequentially" | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |         if runtests.timeout: | 
					
						
							|  |  |  |             msg += " (timeout: %s)" % format_duration(runtests.timeout) | 
					
						
							| 
									
										
										
										
											2020-04-14 18:29:44 +02:00
										 |  |  |         self.log(msg) | 
					
						
							| 
									
										
										
										
											2016-03-24 11:55:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |         previous_test = None | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         tests_iter = runtests.iter_tests() | 
					
						
							|  |  |  |         for test_index, test_name in enumerate(tests_iter, 1): | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  |             start_time = time.perf_counter() | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |             text = test_name | 
					
						
							|  |  |  |             if previous_test: | 
					
						
							|  |  |  |                 text = '%s -- %s' % (text, previous_test) | 
					
						
							| 
									
										
										
										
											2023-09-11 03:46:26 +02:00
										 |  |  |             self.logger.display_progress(test_index, text) | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             result = self.run_test(test_name, runtests, tracer) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # 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) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |             if result.must_stop(self.fail_fast, self.fail_env_changed): | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:25:58 +02:00
										 |  |  |             previous_test = str(result) | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  |             test_time = time.perf_counter() - start_time | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |             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)) | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  |             elif result.state == State.PASSED: | 
					
						
							| 
									
										
										
										
											2016-05-20 13:37:40 +02:00
										 |  |  |                 # be quiet: say nothing if the test passed shortly | 
					
						
							| 
									
										
										
										
											2016-03-23 12:14:10 +01:00
										 |  |  |                 previous_test = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if previous_test: | 
					
						
							|  |  |  |             print(previous_test) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |         return tracer | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def display_header(): | 
					
						
							| 
									
										
										
										
											2017-05-04 15:21:12 +02:00
										 |  |  |         # Print basic platform information | 
					
						
							|  |  |  |         print("==", platform.python_implementation(), *sys.version.split()) | 
					
						
							|  |  |  |         print("==", platform.platform(aliased=True), | 
					
						
							|  |  |  |                       "%s-endian" % sys.byteorder) | 
					
						
							| 
									
										
										
										
											2022-12-08 01:38:47 +01:00
										 |  |  |         print("== Python build:", ' '.join(get_build_info())) | 
					
						
							| 
									
										
										
										
											2017-05-04 15:21:12 +02:00
										 |  |  |         print("== cwd:", os.getcwd()) | 
					
						
							|  |  |  |         cpu_count = os.cpu_count() | 
					
						
							|  |  |  |         if cpu_count: | 
					
						
							|  |  |  |             print("== CPU count:", cpu_count) | 
					
						
							|  |  |  |         print("== encodings: locale=%s, FS=%s" | 
					
						
							| 
									
										
										
										
											2022-04-22 10:39:24 +09:00
										 |  |  |               % (locale.getencoding(), sys.getfilesystemencoding())) | 
					
						
							| 
									
										
										
										
											2023-08-23 01:39:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # This makes it easier to remember what to set in your local | 
					
						
							|  |  |  |         # environment when trying to reproduce a sanitizer failure. | 
					
						
							| 
									
										
										
										
											2023-06-05 23:36:36 -07:00
										 |  |  |         asan = support.check_sanitizer(address=True) | 
					
						
							|  |  |  |         msan = support.check_sanitizer(memory=True) | 
					
						
							|  |  |  |         ubsan = support.check_sanitizer(ub=True) | 
					
						
							| 
									
										
										
										
											2023-08-23 01:39:50 +02:00
										 |  |  |         sanitizers = [] | 
					
						
							|  |  |  |         if asan: | 
					
						
							|  |  |  |             sanitizers.append("address") | 
					
						
							|  |  |  |         if msan: | 
					
						
							|  |  |  |             sanitizers.append("memory") | 
					
						
							|  |  |  |         if ubsan: | 
					
						
							|  |  |  |             sanitizers.append("undefined behavior") | 
					
						
							|  |  |  |         if not sanitizers: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         print(f"== sanitizers: {', '.join(sanitizers)}") | 
					
						
							|  |  |  |         for sanitizer, env_var in ( | 
					
						
							|  |  |  |             (asan, "ASAN_OPTIONS"), | 
					
						
							|  |  |  |             (msan, "MSAN_OPTIONS"), | 
					
						
							|  |  |  |             (ubsan, "UBSAN_OPTIONS"), | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             options= os.environ.get(env_var) | 
					
						
							|  |  |  |             if sanitizer and options is not None: | 
					
						
							|  |  |  |                 print(f"== {env_var}={options!r}") | 
					
						
							| 
									
										
										
										
											2017-05-04 15:21:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |     def get_state(self): | 
					
						
							|  |  |  |         state = self.results.get_state(self.fail_env_changed) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         if self.first_state: | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |             state = f'{self.first_state} then {state}' | 
					
						
							|  |  |  |         return state | 
					
						
							| 
									
										
										
										
											2018-06-01 00:48:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 02:24:38 +02:00
										 |  |  |     def _run_tests_mp(self, runtests: RunTests, num_workers: int) -> None: | 
					
						
							| 
									
										
										
										
											2023-09-11 09:02:35 +02:00
										 |  |  |         from .run_workers import RunWorkers | 
					
						
							| 
									
										
										
										
											2023-09-11 03:46:26 +02:00
										 |  |  |         RunWorkers(num_workers, runtests, self.logger, self.results).run() | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |     def finalize_tests(self, tracer): | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |         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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |         if tracer is not None: | 
					
						
							|  |  |  |             results = tracer.results() | 
					
						
							|  |  |  |             results.write_results(show_missing=True, summary=True, | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |                                   coverdir=self.coverage_dir) | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         if self.want_run_leaks: | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  |             os.system("leaks %d" % os.getpid()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         if self.junit_filename: | 
					
						
							|  |  |  |             self.results.write_junit(self.junit_filename) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  |     def display_summary(self): | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         duration = time.perf_counter() - self.logger.start_time | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         filtered = bool(self.match_tests) or bool(self.ignore_tests) | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Total duration | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         print() | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  |         print("Total duration: %s" % format_duration(duration)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         self.results.display_summary(self.first_runtests, filtered) | 
					
						
							| 
									
										
										
										
											2023-09-02 18:09:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Result | 
					
						
							| 
									
										
										
										
											2023-09-10 04:30:43 +02:00
										 |  |  |         state = self.get_state() | 
					
						
							|  |  |  |         print(f"Result: {state}") | 
					
						
							| 
									
										
										
										
											2018-09-18 09:10:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def cleanup_temp_dir(tmp_dir: StrPath): | 
					
						
							| 
									
										
										
										
											2019-06-24 12:03:00 +02:00
										 |  |  |         import glob | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 03:07:05 +02:00
										 |  |  |         path = os.path.join(glob.escape(tmp_dir), 'test_python_*') | 
					
						
							|  |  |  |         print("Cleanup %s directory" % tmp_dir) | 
					
						
							| 
									
										
										
										
											2019-06-24 12:03:00 +02:00
										 |  |  |         for name in glob.glob(path): | 
					
						
							|  |  |  |             if os.path.isdir(name): | 
					
						
							| 
									
										
										
										
											2019-06-24 13:19:48 +02:00
										 |  |  |                 print("Remove directory: %s" % name) | 
					
						
							| 
									
										
										
										
											2020-06-30 21:46:06 +08:00
										 |  |  |                 os_helper.rmtree(name) | 
					
						
							| 
									
										
										
										
											2019-06-24 12:03:00 +02:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 print("Remove file: %s" % name) | 
					
						
							| 
									
										
										
										
											2020-06-30 21:46:06 +08:00
										 |  |  |                 os_helper.unlink(name) | 
					
						
							| 
									
										
										
										
											2019-06-24 12:03:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     def create_run_tests(self, tests: TestTuple): | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         return RunTests( | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             tests, | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  |             fail_fast=self.fail_fast, | 
					
						
							|  |  |  |             match_tests=self.match_tests, | 
					
						
							|  |  |  |             ignore_tests=self.ignore_tests, | 
					
						
							|  |  |  |             forever=self.forever, | 
					
						
							|  |  |  |             pgo=self.pgo, | 
					
						
							|  |  |  |             pgo_extended=self.pgo_extended, | 
					
						
							|  |  |  |             output_on_failure=self.output_on_failure, | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |             timeout=self.timeout, | 
					
						
							|  |  |  |             verbose=self.verbose, | 
					
						
							|  |  |  |             quiet=self.quiet, | 
					
						
							|  |  |  |             hunt_refleak=self.hunt_refleak, | 
					
						
							|  |  |  |             test_dir=self.test_dir, | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |             use_junit=(self.junit_filename is not None), | 
					
						
							| 
									
										
										
										
											2023-09-10 01:41:21 +02:00
										 |  |  |             memory_limit=self.memory_limit, | 
					
						
							|  |  |  |             gc_threshold=self.gc_threshold, | 
					
						
							|  |  |  |             use_resources=self.use_resources, | 
					
						
							|  |  |  |             python_cmd=self.python_cmd, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int: | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         if self.hunt_refleak and self.hunt_refleak.warmups < 3: | 
					
						
							|  |  |  |             msg = ("WARNING: Running tests with --huntrleaks/-R and " | 
					
						
							|  |  |  |                    "less than 3 warmup repetitions can give false positives!") | 
					
						
							|  |  |  |             print(msg, file=sys.stdout, flush=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.num_workers < 0: | 
					
						
							|  |  |  |             # Use all CPUs + 2 extra worker processes for tests | 
					
						
							|  |  |  |             # that like to sleep | 
					
						
							|  |  |  |             self.num_workers = (os.cpu_count() or 1) + 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # For a partial run, we do not need to clutter the output. | 
					
						
							|  |  |  |         if (self.want_header | 
					
						
							|  |  |  |             or not(self.pgo or self.quiet or self.single_test_run | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |                    or tests or self.cmdline_args)): | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |             self.display_header() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.randomize: | 
					
						
							|  |  |  |             print("Using random seed", self.random_seed) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         runtests = self.create_run_tests(selected) | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         self.first_runtests = runtests | 
					
						
							|  |  |  |         self.logger.set_tests(runtests) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         setup_process() | 
					
						
							| 
									
										
										
										
											2023-09-09 03:37:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         self.logger.start_load_tracker() | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             if self.num_workers: | 
					
						
							|  |  |  |                 self._run_tests_mp(runtests, self.num_workers) | 
					
						
							|  |  |  |                 tracer = None | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 tracer = self.run_tests_sequentially(runtests) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |             self.display_result(runtests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if self.want_rerun and self.results.need_rerun(): | 
					
						
							|  |  |  |                 self.rerun_failed_tests(runtests) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             self.logger.stop_load_tracker() | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.display_summary() | 
					
						
							| 
									
										
										
										
											2023-09-09 02:30:28 +02:00
										 |  |  |         self.finalize_tests(tracer) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 05:04:26 +02:00
										 |  |  |         return self.results.get_exitcode(self.fail_env_changed, | 
					
						
							|  |  |  |                                          self.fail_rerun) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     def run_tests(self, selected: TestTuple, tests: TestList | None) -> int: | 
					
						
							|  |  |  |         os.makedirs(self.tmp_dir, exist_ok=True) | 
					
						
							|  |  |  |         work_dir = get_work_dir(parent_dir=self.tmp_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Put a timeout on Python exit | 
					
						
							|  |  |  |         with exit_timeout(): | 
					
						
							|  |  |  |             # 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 os_helper.SAVEDCWD. | 
					
						
							|  |  |  |             with os_helper.temp_cwd(work_dir, quiet=True): | 
					
						
							|  |  |  |                 # When using multiprocessing, worker processes will use | 
					
						
							|  |  |  |                 # work_dir as their parent temporary directory. So when the | 
					
						
							|  |  |  |                 # main process exit, it removes also subdirectories of worker | 
					
						
							|  |  |  |                 # processes. | 
					
						
							|  |  |  |                 return self._run_tests(selected, tests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def main(self, tests: TestList | None = None): | 
					
						
							|  |  |  |         if self.junit_filename and not os.path.isabs(self.junit_filename): | 
					
						
							|  |  |  |             self.junit_filename = os.path.abspath(self.junit_filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         strip_py_suffix(self.cmdline_args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.tmp_dir = get_temp_dir(self.tmp_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.want_cleanup: | 
					
						
							|  |  |  |             self.cleanup_temp_dir(self.tmp_dir) | 
					
						
							|  |  |  |             sys.exit(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if self.want_wait: | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  |             input("Press any key to continue...") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-09 11:18:14 +02:00
										 |  |  |         setup_test_dir(self.test_dir) | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |         selected, tests = self.find_tests(tests) | 
					
						
							| 
									
										
										
										
											2015-09-30 00:59:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         exitcode = 0 | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         if self.want_list_tests: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             self.list_tests(selected) | 
					
						
							| 
									
										
										
										
											2023-09-09 01:48:54 +02:00
										 |  |  |         elif self.want_list_cases: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             self.list_cases(selected) | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |             exitcode = self.run_tests(selected, tests) | 
					
						
							| 
									
										
										
										
											2018-09-18 09:10:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 23:37:15 +02:00
										 |  |  |         sys.exit(exitcode) | 
					
						
							| 
									
										
										
										
											2015-09-26 10:38:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 22:48:52 +02:00
										 |  |  | def main(tests=None, **kwargs): | 
					
						
							| 
									
										
										
										
											2016-03-24 17:53:20 +01:00
										 |  |  |     """Run the Python suite.""" | 
					
						
							| 
									
										
										
										
											2023-09-09 00:41:26 +02:00
										 |  |  |     ns = _parse_args(sys.argv[1:], **kwargs) | 
					
						
							|  |  |  |     Regrtest(ns).main(tests=tests) |