Skip to content

Commit 9be413a

Browse files
Add timeout tests for stdio client cleanup
Add comprehensive tests that validate stdio client cleanup behavior: - Universal timeout test ensures cleanup completes within reasonable time even with long-running processes - Immediate completion test ensures fast processes remain fast and timeout mechanism doesn't introduce delays - Cross-platform compatibility with different commands for Windows vs Unix These tests will help ensure PR #555's timeout mechanism works correctly without regressing normal operation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent dced223 commit 9be413a

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

tests/client/test_stdio.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import shutil
2+
import sys
3+
import time
24

35
import pytest
46

@@ -90,3 +92,93 @@ async def test_stdio_client_nonexistent_command():
9092
or "not found" in error_message.lower()
9193
or "cannot find the file" in error_message.lower() # Windows error message
9294
)
95+
96+
97+
@pytest.mark.anyio
98+
async def test_stdio_client_universal_timeout():
99+
"""
100+
Test that stdio_client completes cleanup within reasonable time
101+
even when connected to processes that exit slowly.
102+
"""
103+
104+
# Use a simple sleep command that's available on all platforms
105+
# This simulates a process that takes time to terminate
106+
if sys.platform == "win32":
107+
# Windows: use ping with timeout to simulate a running process
108+
server_params = StdioServerParameters(
109+
command="ping",
110+
args=["127.0.0.1", "-n", "10"], # Ping 10 times, takes ~10 seconds
111+
)
112+
else:
113+
# Unix: use sleep command
114+
server_params = StdioServerParameters(
115+
command="sleep",
116+
args=["10"], # Sleep for 10 seconds
117+
)
118+
119+
start_time = time.time()
120+
121+
try:
122+
async with stdio_client(server_params) as (read_stream, write_stream):
123+
# Immediately exit - this triggers cleanup while process is still running
124+
pass
125+
126+
end_time = time.time()
127+
elapsed = end_time - start_time
128+
129+
# Key assertion: Should complete quickly due to timeout mechanism
130+
# Before PR #555, Unix systems might hang for the full 10 seconds
131+
# After PR #555, all platforms should complete within ~2-3 seconds
132+
assert elapsed < 5.0, (
133+
f"stdio_client cleanup took {elapsed:.1f} seconds, expected < 5.0 seconds. "
134+
f"This suggests the timeout mechanism may not be working properly."
135+
)
136+
137+
except Exception as e:
138+
end_time = time.time()
139+
elapsed = end_time - start_time
140+
print(f"❌ Test failed after {elapsed:.1f} seconds: {e}")
141+
raise
142+
143+
144+
@pytest.mark.anyio
145+
async def test_stdio_client_immediate_completion():
146+
"""
147+
Test that stdio_client doesn't introduce unnecessary delays
148+
when processes exit normally and quickly.
149+
150+
This ensures PR #555's timeout mechanism doesn't slow down normal operation.
151+
"""
152+
153+
# Use a command that exits immediately
154+
if sys.platform == "win32":
155+
server_params = StdioServerParameters(
156+
command="cmd",
157+
args=["/c", "echo", "hello"], # Windows: echo and exit
158+
)
159+
else:
160+
server_params = StdioServerParameters(
161+
command="echo",
162+
args=["hello"], # Unix: echo and exit
163+
)
164+
165+
start_time = time.time()
166+
167+
try:
168+
async with stdio_client(server_params) as (read_stream, write_stream):
169+
pass
170+
171+
end_time = time.time()
172+
elapsed = end_time - start_time
173+
174+
# Should complete very quickly when process exits normally
175+
assert elapsed < 2.0, (
176+
f"stdio_client took {elapsed:.1f} seconds for fast-exiting process, "
177+
f"expected < 2.0 seconds. Timeout mechanism may be introducing delays."
178+
)
179+
180+
except Exception as e:
181+
end_time = time.time()
182+
elapsed = end_time - start_time
183+
print(f"❌ Test failed after {elapsed:.1f} seconds: {e}")
184+
raise

0 commit comments

Comments
 (0)