test: add tests for responses api translation

This commit is contained in:
Alexander Grattan 2026-01-26 11:42:59 -05:00
parent 0800cfa102
commit 97e67b0e48

View file

@ -817,3 +817,181 @@ class TestOpenAIResponsesHandlerToolCallExtraction:
assert task_mappings[0] == (0, 0)
assert task_mappings[1] == (0, 1)
assert task_mappings[2] == (0, 2)
class MockPassThroughGuardrail(CustomGuardrail):
"""Mock guardrail that passes through without blocking - for testing streaming fallback behavior"""
async def apply_guardrail(
self,
inputs: GenericGuardrailAPIInputs,
request_data: dict,
input_type: Literal["request", "response"],
logging_obj: Optional[Any] = None,
) -> GenericGuardrailAPIInputs:
"""Simply return inputs unchanged"""
return inputs
class TestOpenAIResponsesHandlerStreamingOutputProcessing:
"""Test streaming output processing functionality"""
@pytest.mark.asyncio
async def test_process_output_streaming_response_empty_output(self):
"""Test that streaming response with empty output doesn't raise IndexError
This test verifies the fix for the bug where accessing model_response_choices[0]
would raise IndexError when the response.completed event has an empty output array.
"""
handler = OpenAIResponsesHandler()
guardrail = MockPassThroughGuardrail(guardrail_name="test")
# Simulate a response.completed streaming event with empty output
responses_so_far = [
{
"type": "response.completed",
"response": {
"id": "resp_123",
"output": [], # Empty output - this was causing the IndexError
"status": "completed",
},
}
]
# This should not raise IndexError
result = await handler.process_output_streaming_response(
responses_so_far=responses_so_far,
guardrail_to_apply=guardrail,
litellm_logging_obj=None,
)
# Should return the responses unchanged
assert result == responses_so_far
@pytest.mark.asyncio
async def test_process_output_streaming_response_missing_output_key(self):
"""Test that streaming response with missing output key doesn't raise IndexError
This test verifies the handler gracefully handles when the response dict
doesn't contain an 'output' key at all.
"""
handler = OpenAIResponsesHandler()
guardrail = MockPassThroughGuardrail(guardrail_name="test")
# Simulate a response.completed streaming event with missing output key
responses_so_far = [
{
"type": "response.completed",
"response": {
"id": "resp_123",
"status": "completed",
# No 'output' key - get() will return []
},
}
]
# This should not raise IndexError
result = await handler.process_output_streaming_response(
responses_so_far=responses_so_far,
guardrail_to_apply=guardrail,
litellm_logging_obj=None,
)
# Should return the responses unchanged
assert result == responses_so_far
@pytest.mark.asyncio
async def test_process_output_streaming_response_unrecognized_output_type(self):
"""Test that streaming response with unrecognized output types doesn't raise IndexError
This test verifies the handler gracefully handles when output items are of
unrecognized types that _convert_response_output_to_choices skips over.
"""
handler = OpenAIResponsesHandler()
guardrail = MockPassThroughGuardrail(guardrail_name="test")
# Simulate a response.completed streaming event with unrecognized output type
responses_so_far = [
{
"type": "response.completed",
"response": {
"id": "resp_123",
"output": [
{
"type": "unknown_type", # Unrecognized type
"id": "item_123",
"data": "some data",
}
],
"status": "completed",
},
}
]
# This should not raise IndexError
result = await handler.process_output_streaming_response(
responses_so_far=responses_so_far,
guardrail_to_apply=guardrail,
litellm_logging_obj=None,
)
# Should return the responses unchanged
assert result == responses_so_far
@pytest.mark.asyncio
async def test_process_output_streaming_response_with_valid_output(self):
"""Test that streaming response with valid output still works correctly"""
handler = OpenAIResponsesHandler()
guardrail = MockPassThroughGuardrail(guardrail_name="test")
# Simulate a response.completed streaming event with valid message output
responses_so_far = [
{
"type": "response.created",
"response": {"id": "resp_123"},
},
{
"type": "response.output_item.added",
"item": {"type": "message", "id": "msg_123"},
},
{
"type": "response.content_part.added",
"part": {"type": "output_text", "text": ""},
},
{
"type": "response.output_text.delta",
"delta": "Hello",
},
{
"type": "response.output_text.delta",
"delta": " world",
},
{
"type": "response.completed",
"response": {
"id": "resp_123",
"output": [
{
"type": "message",
"id": "msg_123",
"status": "completed",
"role": "assistant",
"content": [
{"type": "output_text", "text": "Hello world"},
],
}
],
"status": "completed",
},
},
]
# This should process successfully
result = await handler.process_output_streaming_response(
responses_so_far=responses_so_far,
guardrail_to_apply=guardrail,
litellm_logging_obj=None,
)
# Should return the responses
assert result == responses_so_far