Skip to content

Commit c7c39ba

Browse files
committed
test(jsonrpc): add tests for stream_send_timeout in JSONRPCApplication
1 parent 4d54c28 commit c7c39ba

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

tests/server/apps/jsonrpc/test_jsonrpc_app.py

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,192 @@ def build(
184184
):
185185
_app = DummyJSONRPCApp(**mock_app_params)
186186

187+
@pytest.mark.asyncio
188+
async def test_stream_send_timeout_applied_to_event_source_response(
189+
self, mock_app_params: dict
190+
):
191+
"""Test that stream_send_timeout is correctly applied to EventSourceResponse."""
192+
from unittest.mock import patch
193+
194+
class DummyJSONRPCApp(JSONRPCApplication):
195+
def __init__(self, **kwargs):
196+
# Skip parent __init__ to avoid package checks
197+
self.stream_send_timeout = kwargs.get(
198+
'stream_send_timeout', None
199+
)
200+
self.agent_card = kwargs.get('agent_card')
201+
self.extended_agent_card = kwargs.get('extended_agent_card')
202+
self.card_modifier = kwargs.get('card_modifier')
203+
self.extended_card_modifier = kwargs.get(
204+
'extended_card_modifier'
205+
)
206+
self.max_content_length = kwargs.get(
207+
'max_content_length', 10 * 1024 * 1024
208+
)
209+
self.handler = kwargs.get('http_handler')
210+
211+
def build(self, **kwargs):
212+
return object()
213+
214+
# Test with app-level timeout
215+
app = DummyJSONRPCApp(stream_send_timeout=30.0, **mock_app_params)
216+
217+
# Mock context
218+
context = MagicMock(spec=ServerCallContext)
219+
context.state = {}
220+
context.activated_extensions = None
221+
222+
# Mock streaming handler result
223+
async def mock_generator():
224+
yield SendMessageResponse(
225+
root=SendMessageSuccessResponse(
226+
message=Message(
227+
message_id='1',
228+
role=Role.assistant,
229+
parts=[Part(TextPart(text='test'))],
230+
)
231+
)
232+
)
233+
234+
handler_result = mock_generator()
235+
236+
with patch(
237+
'a2a.server.apps.jsonrpc.jsonrpc_app.EventSourceResponse'
238+
) as mock_esr:
239+
mock_esr.return_value = MagicMock()
240+
241+
# Call the method
242+
response = app._create_response(context, handler_result)
243+
244+
# Assert EventSourceResponse was called with correct timeout
245+
mock_esr.assert_called_once()
246+
call_args = mock_esr.call_args
247+
assert call_args[1]['send_timeout'] == 30.0
248+
249+
@pytest.mark.asyncio
250+
async def test_stream_send_timeout_none_disables_timeout(
251+
self, mock_app_params: dict
252+
):
253+
"""Test that stream_send_timeout=None disables the timeout."""
254+
from unittest.mock import patch
255+
256+
class DummyJSONRPCApp(JSONRPCApplication):
257+
def __init__(self, **kwargs):
258+
# Skip parent __init__ to avoid package checks
259+
self.stream_send_timeout = kwargs.get(
260+
'stream_send_timeout', None
261+
)
262+
self.agent_card = kwargs.get('agent_card')
263+
self.extended_agent_card = kwargs.get('extended_agent_card')
264+
self.card_modifier = kwargs.get('card_modifier')
265+
self.extended_card_modifier = kwargs.get(
266+
'extended_card_modifier'
267+
)
268+
self.max_content_length = kwargs.get(
269+
'max_content_length', 10 * 1024 * 1024
270+
)
271+
self.handler = kwargs.get('http_handler')
272+
273+
def build(self, **kwargs):
274+
return object()
275+
276+
# Test with None timeout (default)
277+
app = DummyJSONRPCApp(stream_send_timeout=None, **mock_app_params)
278+
279+
# Mock context
280+
context = MagicMock(spec=ServerCallContext)
281+
context.state = {}
282+
context.activated_extensions = None
283+
284+
# Mock streaming handler result
285+
async def mock_generator():
286+
yield SendMessageResponse(
287+
root=SendMessageSuccessResponse(
288+
message=Message(
289+
message_id='1',
290+
role=Role.assistant,
291+
parts=[Part(TextPart(text='test'))],
292+
)
293+
)
294+
)
295+
296+
handler_result = mock_generator()
297+
298+
with patch(
299+
'a2a.server.apps.jsonrpc.jsonrpc_app.EventSourceResponse'
300+
) as mock_esr:
301+
mock_esr.return_value = MagicMock()
302+
303+
# Call the method
304+
response = app._create_response(context, handler_result)
305+
306+
# Assert EventSourceResponse was called with None (disabled timeout)
307+
mock_esr.assert_called_once()
308+
call_args = mock_esr.call_args
309+
assert call_args[1]['send_timeout'] is None
310+
311+
@pytest.mark.asyncio
312+
async def test_stream_send_timeout_context_override(
313+
self, mock_app_params: dict
314+
):
315+
"""Test that context.state can override the app-level stream_send_timeout."""
316+
from unittest.mock import patch
317+
318+
class DummyJSONRPCApp(JSONRPCApplication):
319+
def __init__(self, **kwargs):
320+
# Skip parent __init__ to avoid package checks
321+
self.stream_send_timeout = kwargs.get(
322+
'stream_send_timeout', None
323+
)
324+
self.agent_card = kwargs.get('agent_card')
325+
self.extended_agent_card = kwargs.get('extended_agent_card')
326+
self.card_modifier = kwargs.get('card_modifier')
327+
self.extended_card_modifier = kwargs.get(
328+
'extended_card_modifier'
329+
)
330+
self.max_content_length = kwargs.get(
331+
'max_content_length', 10 * 1024 * 1024
332+
)
333+
self.handler = kwargs.get('http_handler')
334+
335+
def build(self, **kwargs):
336+
return object()
337+
338+
# Test with app-level timeout
339+
app = DummyJSONRPCApp(stream_send_timeout=30.0, **mock_app_params)
340+
341+
# Mock context with override
342+
context = MagicMock(spec=ServerCallContext)
343+
context.state = {'stream_send_timeout': 60.0}
344+
context.activated_extensions = None
345+
346+
# Mock streaming handler result
347+
async def mock_generator():
348+
yield SendMessageResponse(
349+
root=SendMessageSuccessResponse(
350+
message=Message(
351+
message_id='1',
352+
role=Role.assistant,
353+
parts=[Part(TextPart(text='test'))],
354+
)
355+
)
356+
)
357+
358+
handler_result = mock_generator()
359+
360+
with patch(
361+
'a2a.server.apps.jsonrpc.jsonrpc_app.EventSourceResponse'
362+
) as mock_esr:
363+
mock_esr.return_value = MagicMock()
364+
365+
# Call the method
366+
response = app._create_response(context, handler_result)
367+
368+
# Assert EventSourceResponse was called with context override
369+
mock_esr.assert_called_once()
370+
call_args = mock_esr.call_args
371+
assert call_args[1]['send_timeout'] == 60.0
372+
187373

188374
class TestJSONRPCExtensions:
189375
@pytest.fixture

0 commit comments

Comments
 (0)