| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | import subprocess | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2023-09-12 15:13:29 +02:00
										 |  |  | from typing import NoReturn | 
					
						
							| 
									
										
										
										
											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 .setup import setup_process, setup_test_dir | 
					
						
							|  |  |  | from .runtests import RunTests | 
					
						
							|  |  |  | from .single import run_single_test | 
					
						
							|  |  |  | from .utils import ( | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |     StrPath, StrJSON, FilterTuple, MS_WINDOWS, | 
					
						
							| 
									
										
										
										
											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")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create_worker_process(runtests: RunTests, | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |                           output_fd: int, json_fd: int, | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |                           tmp_dir: StrPath | None = None) -> subprocess.Popen: | 
					
						
							|  |  |  |     python_cmd = runtests.python_cmd | 
					
						
							|  |  |  |     worker_json = runtests.as_json() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if python_cmd is not None: | 
					
						
							|  |  |  |         executable = python_cmd | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         executable = [sys.executable] | 
					
						
							|  |  |  |     cmd = [*executable, *support.args_from_interpreter_flags(), | 
					
						
							|  |  |  |            '-u',    # Unbuffered stdout and stderr | 
					
						
							|  |  |  |            '-m', 'test.libregrtest.worker', | 
					
						
							|  |  |  |            worker_json] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     env = dict(os.environ) | 
					
						
							|  |  |  |     if tmp_dir is not None: | 
					
						
							|  |  |  |         env['TMPDIR'] = tmp_dir | 
					
						
							|  |  |  |         env['TEMP'] = tmp_dir | 
					
						
							|  |  |  |         env['TMP'] = tmp_dir | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-11 01:11: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-11 19:33:42 +02:00
										 |  |  |     kwargs = 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
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |     if not MS_WINDOWS: | 
					
						
							|  |  |  |         kwargs['pass_fds'] = [json_fd] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         startupinfo = subprocess.STARTUPINFO() | 
					
						
							|  |  |  |         startupinfo.lpAttributeList = {"handle_list": [json_fd]} | 
					
						
							|  |  |  |         kwargs['startupinfo'] = startupinfo | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |     if USE_PROCESS_GROUP: | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |         kwargs['start_new_session'] = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if MS_WINDOWS: | 
					
						
							|  |  |  |         os.set_handle_inheritable(json_fd, True) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         return subprocess.Popen(cmd, **kwargs) | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         if MS_WINDOWS: | 
					
						
							|  |  |  |             os.set_handle_inheritable(json_fd, False) | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def worker_process(worker_json: StrJSON) -> NoReturn: | 
					
						
							|  |  |  |     runtests = RunTests.from_json(worker_json) | 
					
						
							|  |  |  |     test_name = runtests.tests[0] | 
					
						
							|  |  |  |     match_tests: FilterTuple | None = runtests.match_tests | 
					
						
							| 
									
										
										
										
											2023-09-11 19:33:42 +02:00
										 |  |  |     json_fd: int = runtests.json_fd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if MS_WINDOWS: | 
					
						
							|  |  |  |         import msvcrt | 
					
						
							|  |  |  |         json_fd = msvcrt.open_osfhandle(json_fd, os.O_WRONLY) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							|  |  |  |             matching = "matching: " + ", ".join(match_tests) | 
					
						
							|  |  |  |             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-09-11 19:33:42 +02:00
										 |  |  |     with open(json_fd, 'w', encoding='utf-8') as json_file: | 
					
						
							|  |  |  |         result.write_json_into(json_file) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 01:11:22 +02:00
										 |  |  |     sys.exit(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     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() |