TCP server context manager that... 1. Exits only after all handlers have returned. 2. Ensures that all handlers are closed properly. If we don't do that, we get ghost errors in others tests from StreamWriter.__del__. Spawning a TCP server is relatively slow. Consider using in-me
(handle_conn, **server_args)
| 17 | |
| 18 | @asynccontextmanager |
| 19 | async def tcp_server(handle_conn, **server_args) -> Address: |
| 20 | """TCP server context manager that... |
| 21 | |
| 22 | 1. Exits only after all handlers have returned. |
| 23 | 2. Ensures that all handlers are closed properly. If we don't do that, |
| 24 | we get ghost errors in others tests from StreamWriter.__del__. |
| 25 | |
| 26 | Spawning a TCP server is relatively slow. Consider using in-memory networking for faster tests. |
| 27 | """ |
| 28 | if not hasattr(asyncio, "TaskGroup"): |
| 29 | pytest.skip("Skipped because asyncio.TaskGroup is unavailable.") |
| 30 | |
| 31 | tasks = asyncio.TaskGroup() |
| 32 | |
| 33 | async def handle_conn_wrapper( |
| 34 | reader: asyncio.StreamReader, |
| 35 | writer: asyncio.StreamWriter, |
| 36 | ) -> None: |
| 37 | try: |
| 38 | await handle_conn(reader, writer) |
| 39 | except Exception as e: |
| 40 | print(f"!!! TCP handler failed: {e}") |
| 41 | raise |
| 42 | finally: |
| 43 | if not writer.is_closing(): |
| 44 | writer.close() |
| 45 | await writer.wait_closed() |
| 46 | |
| 47 | async def _handle(r, w): |
| 48 | tasks.create_task(handle_conn_wrapper(r, w)) |
| 49 | |
| 50 | server = await asyncio.start_server(_handle, "127.0.0.1", 0, **server_args) |
| 51 | await server.start_serving() |
| 52 | async with server: |
| 53 | async with tasks: |
| 54 | yield server.sockets[0].getsockname() |
| 55 | |
| 56 | |
| 57 | @pytest.mark.parametrize("mode", ["http", "https", "upstream", "err"]) |
no outgoing calls
no test coverage detected
searching dependent graphs…