|
10 | 10 | import socket
|
11 | 11 | import subprocess
|
12 | 12 | import sys
|
| 13 | +import threading |
13 | 14 | import uuid
|
14 | 15 | from typing import Any, Dict, List, Optional, Union
|
15 | 16 |
|
16 | 17 | TEST_DATA_PATH = pathlib.Path(__file__).parent / ".data"
|
17 | 18 | from typing_extensions import TypedDict
|
18 | 19 |
|
19 | 20 |
|
20 |
| -@contextlib.contextmanager |
21 |
| -def test_output_file(root: pathlib.Path, ext: str = ".txt"): |
22 |
| - """Creates a temporary python file with a random name.""" |
23 |
| - basename = ( |
24 |
| - "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(9)) + ext |
25 |
| - ) |
26 |
| - fullpath = root / basename |
27 |
| - try: |
28 |
| - fullpath.write_text("", encoding="utf-8") |
29 |
| - yield fullpath |
30 |
| - finally: |
31 |
| - os.unlink(str(fullpath)) |
32 |
| - |
33 |
| - |
34 | 21 | def create_server(
|
35 | 22 | host: str = "127.0.0.1",
|
36 | 23 | port: int = 0,
|
@@ -116,31 +103,51 @@ def runner(args: List[str]) -> Optional[Dict[str, Any]]:
|
116 | 103 | "-p",
|
117 | 104 | "vscode_pytest",
|
118 | 105 | ] + args
|
| 106 | + listener: socket.socket = create_server() |
| 107 | + _, port = listener.getsockname() |
| 108 | + listener.listen() |
| 109 | + |
| 110 | + env = os.environ.copy() |
| 111 | + env.update( |
| 112 | + { |
| 113 | + "TEST_UUID": str(uuid.uuid4()), |
| 114 | + "TEST_PORT": str(port), |
| 115 | + "PYTHONPATH": os.fspath(pathlib.Path(__file__).parent.parent.parent), |
| 116 | + } |
| 117 | + ) |
| 118 | + |
| 119 | + result: list = [] |
| 120 | + t1: threading.Thread = threading.Thread( |
| 121 | + target=_listen_on_socket, args=(listener, result) |
| 122 | + ) |
| 123 | + t1.start() |
| 124 | + |
| 125 | + t2 = threading.Thread( |
| 126 | + target=lambda proc_args, proc_env, proc_cwd: subprocess.run( |
| 127 | + proc_args, env=proc_env, cwd=proc_cwd |
| 128 | + ), |
| 129 | + args=(process_args, env, TEST_DATA_PATH), |
| 130 | + ) |
| 131 | + t2.start() |
| 132 | + |
| 133 | + t1.join() |
| 134 | + t2.join() |
| 135 | + |
| 136 | + return process_rpc_json(result[0]) if result else None |
| 137 | + |
119 | 138 |
|
120 |
| - with test_output_file(TEST_DATA_PATH) as output_path: |
121 |
| - env = os.environ.copy() |
122 |
| - env.update( |
123 |
| - { |
124 |
| - "TEST_UUID": str(uuid.uuid4()), |
125 |
| - "TEST_PORT": str(12345), # port is not used for tests |
126 |
| - "PYTHONPATH": os.fspath(pathlib.Path(__file__).parent.parent.parent), |
127 |
| - "TEST_OUTPUT_FILE": os.fspath(output_path), |
128 |
| - } |
129 |
| - ) |
130 |
| - |
131 |
| - result = subprocess.run( |
132 |
| - process_args, |
133 |
| - env=env, |
134 |
| - cwd=os.fspath(TEST_DATA_PATH), |
135 |
| - stdout=subprocess.PIPE, |
136 |
| - stderr=subprocess.PIPE, |
137 |
| - ) |
138 |
| - if result.returncode != 0: |
139 |
| - print("Subprocess Run failed with:") |
140 |
| - print(result.stdout.decode(encoding="utf-8")) |
141 |
| - print(result.stderr.decode(encoding="utf-8")) |
142 |
| - |
143 |
| - return process_rpc_json(output_path.read_text(encoding="utf-8")) |
| 139 | +def _listen_on_socket(listener: socket.socket, result: List[str]): |
| 140 | + """Listen on the socket for the JSON data from the server. |
| 141 | + Created as a seperate function for clarity in threading. |
| 142 | + """ |
| 143 | + sock, (other_host, other_port) = listener.accept() |
| 144 | + all_data: list = [] |
| 145 | + while True: |
| 146 | + data: bytes = sock.recv(1024 * 1024) |
| 147 | + if not data: |
| 148 | + break |
| 149 | + all_data.append(data.decode("utf-8")) |
| 150 | + result.append("".join(all_data)) |
144 | 151 |
|
145 | 152 |
|
146 | 153 | def find_test_line_number(test_name: str, test_file_path) -> str:
|
|
0 commit comments