11# test_sse.py
22import re
3+ import socket
34import time
45import json
56import anyio
2526
2627@pytest .fixture
2728def server_port () -> int :
28- import socket
29-
30- s = socket .socket ()
31- s .bind (('' , 0 ))
32- port = s .getsockname ()[1 ]
33- s .close ()
34- return port
29+ with socket .socket () as s :
30+ s .bind (('127.0.0.1' , 0 ))
31+ return s .getsockname ()[1 ]
3532
3633@pytest .fixture
3734def server_url (server_port : int ) -> str :
@@ -89,6 +86,12 @@ async def handle_sse(request):
8986
9087 return app
9188
89+ @pytest .fixture (autouse = True )
90+ def space_around_test ():
91+ time .sleep (0.1 )
92+ yield
93+ time .sleep (0.1 )
94+
9295@pytest .fixture ()
9396def server (server_app : Starlette , server_port : int ):
9497 server = uvicorn .Server (config = uvicorn .Config (app = server_app , host = "127.0.0.1" , port = server_port , log_level = "error" ))
@@ -99,9 +102,27 @@ def server(server_app: Starlette, server_port: int):
99102 while not server .started :
100103 print ('waiting for server to start' )
101104 time .sleep (0.5 )
102- yield
103- print ('killing server' )
104- server_thread .join (timeout = 0.1 )
105+
106+ try :
107+ yield
108+ finally :
109+ print ('killing server' )
110+ # Signal the server to stop
111+ server .should_exit = True
112+
113+ # Force close the server's main socket
114+ if hasattr (server .servers , "servers" ):
115+ for s in server .servers :
116+ print (f'closing { s } ' )
117+ s .close ()
118+
119+ # Wait for thread to finish
120+ server_thread .join (timeout = 2 )
121+ if server_thread .is_alive ():
122+ print ("Warning: Server thread did not exit cleanly" )
123+ # Optionally, you could add more aggressive cleanup here
124+ import _thread
125+ _thread .interrupt_main ()
105126
106127@pytest .fixture ()
107128async def http_client (server , server_url ) -> AsyncGenerator [httpx .AsyncClient , None ]:
@@ -167,3 +188,6 @@ async def test_sse_client_exception_handling(initialized_sse_client_session: Cli
167188 session = initialized_sse_client_session
168189 with pytest .raises (McpError , match = "OOPS! no resource with that URI was found" ):
169190 await session .read_resource (uri = AnyUrl ("xxx://will-not-work" ))
191+
192+
193+ # TODO: test that timeouts are respected and that the error comes back
0 commit comments