From 0edbe6b3dc830152b49b8344f7dbe57ef83204f6 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 2 May 2026 00:18:45 +0000 Subject: [PATCH] test(router): cover _try_early_resolve_deployments_for_model_not_in_names The router_code_coverage CI check requires every function in router.py to be referenced by at least one test under tests/{local_testing, router_unit_tests,test_litellm} in a file with "router" in its name. The recently-extracted helper had no direct test, so the check failed with "0.45% of functions in router.py are not tested". Add a focused test that exercises the four return paths: model already in self.model_names, no fallback applies, pattern-router match, and default_deployment substitution (also asserting the stored default isn't mutated). https://claude.ai/code/session_019AVp1XL7RT9RxRe4qRLkay --- tests/test_litellm/test_router.py | 95 +++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/tests/test_litellm/test_router.py b/tests/test_litellm/test_router.py index b6ea6b374e..48facace52 100644 --- a/tests/test_litellm/test_router.py +++ b/tests/test_litellm/test_router.py @@ -3602,3 +3602,98 @@ def test_access_group_block_via_litellm_model_branch_does_not_use_default_fallba } }, ) + + +def test_try_early_resolve_deployments_for_model_not_in_names(): + """ + Direct coverage for ``_try_early_resolve_deployments_for_model_not_in_names``: + + - Returns ``None`` when the requested model is already in ``self.model_names`` + (the by-name lookup path will handle it). + - Returns ``None`` when there are no team deployments, no pattern matches, and + no default deployment to fall back to. + - Returns the pattern-router match when the model matches a wildcard route. + - Returns the default deployment with the request model substituted in when one + is configured, without mutating the stored default. + """ + router_in_names = litellm.Router( + model_list=[ + { + "model_name": "gpt-5", + "litellm_params": { + "model": "openai/gpt-5", + "api_key": "key1", + }, + }, + ] + ) + + assert ( + router_in_names._try_early_resolve_deployments_for_model_not_in_names( + model="gpt-5", request_team_id=None + ) + is None + ) + assert ( + router_in_names._try_early_resolve_deployments_for_model_not_in_names( + model="some-unknown-model", request_team_id=None + ) + is None + ) + + pattern_router = litellm.Router( + model_list=[ + { + "model_name": "openai/*", + "litellm_params": { + "model": "openai/*", + "api_key": "key-pattern", + }, + }, + ] + ) + + pattern_result = ( + pattern_router._try_early_resolve_deployments_for_model_not_in_names( + model="openai/gpt-4o-mini", request_team_id=None + ) + ) + assert pattern_result is not None + resolved_model, pattern_deployments = pattern_result + assert resolved_model == "openai/gpt-4o-mini" + assert isinstance(pattern_deployments, list) and len(pattern_deployments) == 1 + + default_router = litellm.Router( + model_list=[ + { + "model_name": "named-model", + "litellm_params": { + "model": "openai/gpt-4o", + "api_key": "key-named", + }, + }, + ] + ) + default_router.default_deployment = { + "model_name": "default", + "litellm_params": { + "model": "openai/will-be-overridden", + "api_key": "key-default", + }, + } + + default_result = ( + default_router._try_early_resolve_deployments_for_model_not_in_names( + model="brand-new-model", request_team_id=None + ) + ) + assert default_result is not None + resolved_model, default_deployment = default_result + assert resolved_model == "brand-new-model" + assert isinstance(default_deployment, dict) + assert default_deployment["litellm_params"]["model"] == "brand-new-model" + # The original default_deployment must not be mutated. + assert ( + default_router.default_deployment["litellm_params"]["model"] + == "openai/will-be-overridden" + )