mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-05 08:07:05 +00:00
test(router): fake the upstream with respx in the retry policy attempt test
The test-quality gate rejects patching litellm.acompletion, and faking the HTTP boundary is the stronger test anyway: the 503, 500 and 502 responses now travel through the real OpenAI SDK and exception mapping before the router decides how many times to retry. Adds a case showing that a 503 key does not govern a 502.
This commit is contained in:
parent
b29f9a94bc
commit
541ab50c04
1 changed files with 26 additions and 13 deletions
|
|
@ -12,6 +12,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||
import httpx
|
||||
import openai
|
||||
import pytest
|
||||
import respx
|
||||
|
||||
|
||||
|
||||
|
|
@ -567,7 +568,6 @@ async def test_async_router_acancel_batch_does_not_fall_back_across_model_groups
|
|||
model string, and the fallback provider is then asked to cancel a batch it never
|
||||
issued, which can only answer not-found. The router re-raises the owner's error after
|
||||
that wasted round trip, so the pin's observable is the foreign call never happening."""
|
||||
import respx
|
||||
|
||||
monkeypatch.setattr(litellm, "disable_aiohttp_transport", True)
|
||||
router = litellm.Router(
|
||||
|
|
@ -716,7 +716,6 @@ async def test_async_router_acreate_file_litellm_proxy_sends_target_model_names_
|
|||
from io import BytesIO
|
||||
|
||||
import httpx
|
||||
import respx
|
||||
|
||||
jsonl_file = BytesIO(
|
||||
json.dumps({"body": {"model": "chained-batch", "messages": [{"role": "user", "content": "hi"}]}}).encode(
|
||||
|
|
@ -12897,31 +12896,45 @@ async def test_prompt_management_factory_marks_injection_for_every_deployment(mo
|
|||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"retry_policy,error_type,expected_calls",
|
||||
"retry_policy,upstream_status,error_type,expected_upstream_calls",
|
||||
[
|
||||
({"ServiceUnavailableErrorRetries": 0}, litellm.ServiceUnavailableError, 1),
|
||||
({"ServiceUnavailableErrorRetries": 1}, litellm.ServiceUnavailableError, 2),
|
||||
({"InternalServerErrorRetries": 0}, litellm.InternalServerError, 1),
|
||||
({"DefaultRetries": 0}, litellm.BadGatewayError, 1),
|
||||
({"DefaultRetries": 0, "ServiceUnavailableErrorRetries": 1}, litellm.ServiceUnavailableError, 2),
|
||||
({"ServiceUnavailableErrorRetries": 0}, 503, litellm.ServiceUnavailableError, 1),
|
||||
({"ServiceUnavailableErrorRetries": 1}, 503, litellm.ServiceUnavailableError, 2),
|
||||
({"InternalServerErrorRetries": 0}, 500, litellm.InternalServerError, 1),
|
||||
({"DefaultRetries": 0}, 502, litellm.BadGatewayError, 1),
|
||||
({"DefaultRetries": 0, "ServiceUnavailableErrorRetries": 1}, 503, litellm.ServiceUnavailableError, 2),
|
||||
({"ServiceUnavailableErrorRetries": 0}, 502, litellm.BadGatewayError, 3),
|
||||
],
|
||||
)
|
||||
async def test_router_retry_policy_controls_attempt_count(retry_policy, error_type, expected_calls):
|
||||
async def test_router_retry_policy_controls_upstream_attempt_count(
|
||||
monkeypatch: pytest.MonkeyPatch, retry_policy, upstream_status, error_type, expected_upstream_calls
|
||||
):
|
||||
monkeypatch.setattr(litellm, "disable_aiohttp_transport", True)
|
||||
router = litellm.Router(
|
||||
model_list=[
|
||||
{
|
||||
"model_name": "gpt-5.6",
|
||||
"litellm_params": {"model": "openai/gpt-5.6", "api_key": "fake-key"},
|
||||
"litellm_params": {
|
||||
"model": "openai/gpt-5.6",
|
||||
"api_key": "sk-fake",
|
||||
"api_base": "https://retry-policy.local/v1",
|
||||
},
|
||||
}
|
||||
],
|
||||
num_retries=2,
|
||||
retry_policy=retry_policy,
|
||||
disable_cooldowns=True,
|
||||
)
|
||||
error = error_type(message="model is down", llm_provider="openai", model="gpt-5.6")
|
||||
|
||||
with patch.object(litellm, "acompletion", AsyncMock(side_effect=error)) as mock_acompletion:
|
||||
with respx.mock(assert_all_called=True) as respx_mock:
|
||||
upstream = respx_mock.post("https://retry-policy.local/v1/chat/completions").mock(
|
||||
return_value=httpx.Response(
|
||||
upstream_status,
|
||||
headers={"retry-after": "0"},
|
||||
json={"error": {"message": "model is down", "type": "server_error"}},
|
||||
)
|
||||
)
|
||||
with pytest.raises(error_type):
|
||||
await router.acompletion(model="gpt-5.6", messages=[{"role": "user", "content": "hi"}])
|
||||
|
||||
assert mock_acompletion.call_count == expected_calls
|
||||
assert upstream.call_count == expected_upstream_calls
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue