| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | import subprocess | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2023-09-14 19:33:18 +01:00
										 |  |  | from typing import Any, NoReturn | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-10 18:17:45 +01:00
										 |  |  | from test.support import os_helper, Py_DEBUG | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 09:02:35 +02:00
										 |  |  | from .setup import setup_process, setup_test_dir | 
					
						
							| 
									
										
										
										
											2023-12-01 14:46:50 +01:00
										 |  |  | from .runtests import WorkerRunTests, JsonFile, JsonFileType | 
					
						
							| 
									
										
										
										
											2023-09-11 09:02:35 +02:00
										 |  |  | from .single import run_single_test | 
					
						
							|  |  |  | from .utils import ( | 
					
						
							| 
									
										
										
										
											2023-10-21 17:44:46 +03:00
										 |  |  |     StrPath, StrJSON, TestFilter, | 
					
						
							| 
									
										
										
										
											2023-09-12 15:13:29 +02:00
										 |  |  |     get_temp_dir, get_work_dir, exit_timeout) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg")) | 
					
						
							| 
									
										
										
										
											2024-06-03 18:34:36 +02:00
										 |  |  | NEED_TTY = { | 
					
						
							|  |  |  |     'test_ioctl', | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 14:46:50 +01:00
										 |  |  | def create_worker_process(runtests: WorkerRunTests, output_fd: int, | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |                           tmp_dir: StrPath | None = None) -> subprocess.Popen: | 
					
						
							|  |  |  |     worker_json = runtests.as_json() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-18 21:06:39 +01:00
										 |  |  |     cmd = runtests.create_python_cmd() | 
					
						
							|  |  |  |     cmd.extend(['-m', 'test.libregrtest.worker', worker_json]) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     env = dict(os.environ) | 
					
						
							|  |  |  |     if tmp_dir is not None: | 
					
						
							|  |  |  |         env['TMPDIR'] = tmp_dir | 
					
						
							|  |  |  |         env['TEMP'] = tmp_dir | 
					
						
							|  |  |  |         env['TMP'] = tmp_dir | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 02:51:22 +02:00
										 |  |  |     # Running the child from the same working directory as regrtest's original | 
					
						
							|  |  |  |     # invocation ensures that TEMPDIR for the child is the same when | 
					
						
							|  |  |  |     # sysconfig.is_python_build() is true. See issue 15300. | 
					
						
							|  |  |  |     # | 
					
						
							| 
									
										
										
										
											2023-09-12 15:13:29 +02:00
										 |  |  |     # Emscripten and WASI Python must start in the Python source code directory | 
					
						
							|  |  |  |     # to get 'python.js' or 'python.wasm' file. Then worker_process() changes | 
					
						
							|  |  |  |     # to a temporary directory created to run tests. | 
					
						
							|  |  |  |     work_dir = os_helper.SAVEDCWD | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-14 19:33:18 +01:00
										 |  |  |     kwargs: dict[str, Any] = dict( | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |         env=env, | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |         stdout=output_fd, | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |         # bpo-45410: Write stderr into stdout to keep messages order | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |         stderr=output_fd, | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |         text=True, | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |         close_fds=True, | 
					
						
							| 
									
										
										
										
											2023-09-12 15:13:29 +02:00
										 |  |  |         cwd=work_dir, | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2024-05-29 14:44:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Don't use setsid() in tests using TTY | 
					
						
							|  |  |  |     test_name = runtests.tests[0] | 
					
						
							|  |  |  |     if USE_PROCESS_GROUP and test_name not in NEED_TTY: | 
					
						
							| 
									
										
										
										
											2023-09-29 02:51:22 +02:00
										 |  |  |         kwargs['start_new_session'] = True | 
					
						
							| 
									
										
										
										
											2023-09-13 00:41:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Pass json_file to the worker process | 
					
						
							|  |  |  |     json_file = runtests.json_file | 
					
						
							|  |  |  |     json_file.configure_subprocess(kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with json_file.inherit_subprocess(): | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |         return subprocess.Popen(cmd, **kwargs) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def worker_process(worker_json: StrJSON) -> NoReturn: | 
					
						
							| 
									
										
										
										
											2023-12-01 14:46:50 +01:00
										 |  |  |     runtests = WorkerRunTests.from_json(worker_json) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |     test_name = runtests.tests[0] | 
					
						
							| 
									
										
										
										
											2023-10-21 17:44:46 +03:00
										 |  |  |     match_tests: TestFilter = runtests.match_tests | 
					
						
							| 
									
										
										
										
											2023-09-13 00:41:25 +02:00
										 |  |  |     json_file: JsonFile = runtests.json_file | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     setup_test_dir(runtests.test_dir) | 
					
						
							| 
									
										
										
										
											2023-09-11 05:27:37 +02:00
										 |  |  |     setup_process() | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if runtests.rerun: | 
					
						
							|  |  |  |         if match_tests: | 
					
						
							| 
									
										
										
										
											2023-10-21 17:44:46 +03:00
										 |  |  |             matching = "matching: " + ", ".join(pattern for pattern, result in match_tests if result) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |             print(f"Re-running {test_name} in verbose mode ({matching})", flush=True) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             print(f"Re-running {test_name} in verbose mode", flush=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = run_single_test(test_name, runtests) | 
					
						
							| 
									
										
										
										
											2023-11-10 18:17:45 +01:00
										 |  |  |     if runtests.coverage: | 
					
						
							|  |  |  |         if "test.cov" in sys.modules:  # imported by -Xpresite= | 
					
						
							|  |  |  |             result.covered_lines = list(sys.modules["test.cov"].coverage) | 
					
						
							|  |  |  |         elif not Py_DEBUG: | 
					
						
							|  |  |  |             print( | 
					
						
							|  |  |  |                 "Gathering coverage in worker processes requires --with-pydebug", | 
					
						
							|  |  |  |                 flush=True, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise LookupError( | 
					
						
							|  |  |  |                 "`test.cov` not found in sys.modules but coverage wanted" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-13 02:24:43 +02:00
										 |  |  |     if json_file.file_type == JsonFileType.STDOUT: | 
					
						
							|  |  |  |         print() | 
					
						
							|  |  |  |         result.write_json_into(sys.stdout) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         with json_file.open('w', encoding='utf-8') as json_fp: | 
					
						
							|  |  |  |             result.write_json_into(json_fp) | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |     sys.exit(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 13:15:57 +03:00
										 |  |  | def main() -> NoReturn: | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |     if len(sys.argv) != 2: | 
					
						
							|  |  |  |         print("usage: python -m test.libregrtest.worker JSON") | 
					
						
							|  |  |  |         sys.exit(1) | 
					
						
							|  |  |  |     worker_json = sys.argv[1] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-12 15:13:29 +02:00
										 |  |  |     tmp_dir = get_temp_dir() | 
					
						
							|  |  |  |     work_dir = get_work_dir(tmp_dir, worker=True) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     with exit_timeout(): | 
					
						
							|  |  |  |         with os_helper.temp_cwd(work_dir, quiet=True): | 
					
						
							|  |  |  |             worker_process(worker_json) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main() |