Skip to content

Commit 488b373

Browse files
committed
test: add unit tests for response api bug fixes
1 parent 9fcad03 commit 488b373

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

tests/test_litellm/litellm_core_utils/test_litellm_logging.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,97 @@ async def test_e2e_generate_cold_storage_object_key_successful():
438438
assert isinstance(result, str)
439439

440440

441+
@pytest.mark.asyncio
442+
async def test_e2e_generate_cold_storage_object_key_with_custom_logger_s3_path():
443+
"""
444+
Test that _generate_cold_storage_object_key uses s3_path from custom logger instance.
445+
"""
446+
from datetime import datetime, timezone
447+
from unittest.mock import MagicMock, patch
448+
449+
from litellm.litellm_core_utils.litellm_logging import StandardLoggingPayloadSetup
450+
451+
# Create test data
452+
start_time = datetime(2025, 1, 15, 10, 30, 45, 123456, timezone.utc)
453+
response_id = "chatcmpl-test-12345"
454+
455+
# Create mock custom logger with s3_path
456+
mock_custom_logger = MagicMock()
457+
mock_custom_logger.s3_path = "storage"
458+
459+
with patch("litellm.configured_cold_storage_logger", "s3_v2"), \
460+
patch("litellm.logging_callback_manager.get_active_custom_logger_for_callback_name") as mock_get_logger, \
461+
patch("litellm.integrations.s3.get_s3_object_key") as mock_get_s3_key:
462+
463+
# Setup mocks
464+
mock_get_logger.return_value = mock_custom_logger
465+
mock_get_s3_key.return_value = "storage/2025-01-15/time-10-30-45-123456_chatcmpl-test-12345.json"
466+
467+
# Call the function
468+
result = StandardLoggingPayloadSetup._generate_cold_storage_object_key(
469+
start_time=start_time,
470+
response_id=response_id
471+
)
472+
473+
# Verify logger was queried correctly
474+
mock_get_logger.assert_called_once_with("s3_v2")
475+
476+
# Verify the S3 function was called with the custom logger's s3_path
477+
mock_get_s3_key.assert_called_once_with(
478+
s3_path="storage", # Should use custom logger's s3_path
479+
team_alias_prefix="",
480+
start_time=start_time,
481+
s3_file_name="time-10-30-45-123456_chatcmpl-test-12345"
482+
)
483+
484+
# Verify the result
485+
assert result == "storage/2025-01-15/time-10-30-45-123456_chatcmpl-test-12345.json"
486+
487+
488+
@pytest.mark.asyncio
489+
async def test_e2e_generate_cold_storage_object_key_with_logger_no_s3_path():
490+
"""
491+
Test that _generate_cold_storage_object_key falls back to empty s3_path when logger has no s3_path.
492+
"""
493+
from datetime import datetime, timezone
494+
from unittest.mock import MagicMock, patch
495+
496+
from litellm.litellm_core_utils.litellm_logging import StandardLoggingPayloadSetup
497+
498+
# Create test data
499+
start_time = datetime(2025, 1, 15, 10, 30, 45, 123456, timezone.utc)
500+
response_id = "chatcmpl-test-12345"
501+
502+
# Create mock custom logger without s3_path
503+
mock_custom_logger = MagicMock()
504+
mock_custom_logger.s3_path = None # or could be missing attribute
505+
506+
with patch("litellm.configured_cold_storage_logger", "s3_v2"), \
507+
patch("litellm.logging_callback_manager.get_active_custom_logger_for_callback_name") as mock_get_logger, \
508+
patch("litellm.integrations.s3.get_s3_object_key") as mock_get_s3_key:
509+
510+
# Setup mocks
511+
mock_get_logger.return_value = mock_custom_logger
512+
mock_get_s3_key.return_value = "2025-01-15/time-10-30-45-123456_chatcmpl-test-12345.json"
513+
514+
# Call the function
515+
result = StandardLoggingPayloadSetup._generate_cold_storage_object_key(
516+
start_time=start_time,
517+
response_id=response_id
518+
)
519+
520+
# Verify the S3 function was called with empty s3_path (fallback)
521+
mock_get_s3_key.assert_called_once_with(
522+
s3_path="", # Should fall back to empty string
523+
team_alias_prefix="",
524+
start_time=start_time,
525+
s3_file_name="time-10-30-45-123456_chatcmpl-test-12345"
526+
)
527+
528+
# Verify the result
529+
assert result == "2025-01-15/time-10-30-45-123456_chatcmpl-test-12345.json"
530+
531+
441532
@pytest.mark.asyncio
442533
async def test_e2e_generate_cold_storage_object_key_not_configured():
443534
"""

tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,53 @@ async def test_should_check_cold_storage_for_full_payload():
364364
with patch.object(litellm, 'configured_cold_storage_logger', None):
365365
result5 = ResponsesSessionHandler._should_check_cold_storage_for_full_payload(proxy_request_with_truncated_pdf)
366366
assert result5 == False, "Should return False when cold storage is not configured, even with truncated content"
367+
368+
369+
@pytest.mark.asyncio
370+
async def test_get_chat_completion_message_history_empty_response_dict():
371+
"""
372+
Test that empty response dict is handled correctly without processing.
373+
This tests the fix for response validation to check for empty dict responses.
374+
"""
375+
from unittest.mock import AsyncMock, patch
376+
377+
# Mock spend logs with empty response dict
378+
mock_spend_logs = [
379+
{
380+
"request_id": "chatcmpl-test-empty-response",
381+
"call_type": "aresponses",
382+
"api_key": "test_key",
383+
"spend": 0.001,
384+
"total_tokens": 0,
385+
"prompt_tokens": 0,
386+
"completion_tokens": 0,
387+
"startTime": "2025-01-15T10:30:00.000+00:00",
388+
"endTime": "2025-01-15T10:30:01.000+00:00",
389+
"model": "gpt-4",
390+
"session_id": "test-session",
391+
"proxy_server_request": {
392+
"input": "test input",
393+
"model": "gpt-4"
394+
},
395+
"response": {} # Empty dict - should not be processed
396+
}
397+
]
398+
399+
with patch.object(ResponsesSessionHandler, "get_all_spend_logs_for_previous_response_id") as mock_get_spend_logs:
400+
mock_get_spend_logs.return_value = mock_spend_logs
401+
402+
# Call the function
403+
result = await ResponsesSessionHandler.get_chat_completion_message_history_for_previous_response_id(
404+
"chatcmpl-test-empty-response"
405+
)
406+
407+
# Verify that user message was added but no assistant response
408+
# Since response is empty dict, no assistant response should be processed
409+
# But user input from proxy_server_request should still be included
410+
messages = result["messages"]
411+
assert len(messages) == 1 # Only user message, no assistant response
412+
assert messages[0]["role"] == "user"
413+
assert messages[0]["content"] == "test input"
414+
415+
# Verify the session was still created correctly
416+
assert result["litellm_session_id"] == "test-session"

0 commit comments

Comments
 (0)