|
1 | 1 | """Test that stdio server exits when stdin reaches EOF.""" |
2 | | -import asyncio |
3 | | -import sys |
4 | | -from io import StringIO |
5 | | - |
6 | 2 | import anyio |
7 | 3 | import pytest |
| 4 | +from io import TextIOWrapper, BytesIO |
8 | 5 |
|
9 | 6 | from mcp.server.stdio import stdio_server |
10 | 7 |
|
11 | 8 |
|
12 | 9 | @pytest.mark.anyio |
13 | 10 | async def test_stdio_server_exits_on_eof(): |
14 | 11 | """Server should exit gracefully when stdin is closed (EOF).""" |
15 | | - # Create a closed stdin (simulating parent death) |
16 | | - closed_stdin = StringIO() # Empty, immediate EOF |
17 | | - |
| 12 | + # Create a stdin that immediately returns EOF |
| 13 | + empty_stdin = anyio.wrap_file(TextIOWrapper(BytesIO(b""), encoding="utf-8")) |
| 14 | + empty_stdout = anyio.wrap_file(TextIOWrapper(BytesIO(), encoding="utf-8")) |
| 15 | + |
18 | 16 | # This should complete without hanging |
19 | | - with anyio.move_on_after(5): # 5 second timeout |
20 | | - async with stdio_server() as (read_stream, write_stream): |
21 | | - # Try to read from stream - should get EOF quickly |
| 17 | + with anyio.move_on_after(5): |
| 18 | + async with stdio_server(stdin=empty_stdin, stdout=empty_stdout) as ( |
| 19 | + read_stream, |
| 20 | + write_stream, |
| 21 | + ): |
| 22 | + # Try to read from stream - should get EndOfStream quickly |
22 | 23 | try: |
23 | 24 | await read_stream.receive() |
24 | 25 | except anyio.EndOfStream: |
25 | | - pass # Expected - stream closed |
26 | | - |
27 | | - # If we get here without timeout, test passes |
28 | | - |
29 | | - |
30 | | -@pytest.mark.anyio |
31 | | -async def test_stdio_server_parent_death_simulation(): |
32 | | - """Simulate parent process death by closing stdin.""" |
33 | | - # Create pipes to simulate stdin/stdout |
34 | | - stdin_reader, stdin_writer = anyio.create_memory_object_stream[str](10) |
35 | | - |
36 | | - async with stdio_server() as (read_stream, write_stream): |
37 | | - # Close the input to simulate parent death |
38 | | - await stdin_writer.aclose() |
39 | | - |
40 | | - # Server should detect EOF and exit gracefully |
41 | | - with pytest.raises(anyio.EndOfStream): |
42 | | - await asyncio.wait_for(read_stream.receive(), timeout=5.0) |
| 26 | + pass # Expected - stream closed due to EOF |
0 commit comments