mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
test: cover the model_validate conversion sites flagged by codecov
Add regression tests for the db-fetch paths whose converted construction lines were uncovered: the auth_checks getters (default end user budget, end user, team membership, access group, team by alias, org by alias, object permission, managed vector stores, project), get_all_team_memberships and list_available_teams in team_endpoints, and the proxy admin user info helper. Each test feeds a mocked prisma row through the real function and asserts the validated model's fields, so a bad model_validate conversion on any of these paths now fails a test instead of only dropping coverage.
This commit is contained in:
parent
44e091aedb
commit
095364fd04
3 changed files with 351 additions and 0 deletions
|
|
@ -4762,3 +4762,254 @@ async def test_skip_user_budget_on_team_key_flag_restores_old_behavior():
|
|||
request=MagicMock(spec=Request),
|
||||
)
|
||||
assert result is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_default_end_user_budget_db_fetch_returns_validated_budget(monkeypatch):
|
||||
from litellm.proxy.auth.auth_checks import get_default_end_user_budget
|
||||
|
||||
monkeypatch.setattr(litellm, "max_end_user_budget_id", "budget-default-1")
|
||||
|
||||
budget_row = MagicMock()
|
||||
budget_row.dict = lambda: {"budget_id": "budget-default-1", "max_budget": 12.5, "tpm_limit": 100}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_budgettable.find_unique = AsyncMock(return_value=budget_row)
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_default_end_user_budget(
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_BudgetTable)
|
||||
assert result.max_budget == 12.5
|
||||
assert result.tpm_limit == 100
|
||||
mock_cache.async_set_cache.assert_awaited_once()
|
||||
assert mock_cache.async_set_cache.call_args.kwargs["value"] is result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_end_user_object_db_fetch_returns_validated_end_user():
|
||||
from litellm.proxy.auth.auth_checks import get_end_user_object
|
||||
|
||||
end_user_row = MagicMock()
|
||||
end_user_row.dict = lambda: {"user_id": "eu-1", "blocked": False, "spend": 3.0}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_endusertable.find_unique = AsyncMock(return_value=end_user_row)
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_end_user_object(
|
||||
end_user_id="eu-1",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_EndUserTable)
|
||||
assert result.user_id == "eu-1"
|
||||
assert result.blocked is False
|
||||
assert result.spend == 3.0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_team_membership_db_fetch_returns_validated_membership():
|
||||
from litellm.proxy._types import LiteLLM_TeamMembership
|
||||
from litellm.proxy.auth.auth_checks import get_team_membership
|
||||
|
||||
membership_row = MagicMock()
|
||||
membership_row.dict = lambda: {"user_id": "u-1", "team_id": "t-1", "spend": 1.5}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_teammembership.find_unique = AsyncMock(return_value=membership_row)
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_team_membership(
|
||||
user_id="u-1",
|
||||
team_id="t-1",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_TeamMembership)
|
||||
assert result.user_id == "u-1"
|
||||
assert result.team_id == "t-1"
|
||||
assert result.spend == 1.5
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_access_object_db_fetch_returns_validated_access_group():
|
||||
from litellm.proxy._types import LiteLLM_AccessGroupTable
|
||||
from litellm.proxy.auth.auth_checks import get_access_object
|
||||
|
||||
access_row = MagicMock()
|
||||
access_row.dict = lambda: {
|
||||
"access_group_id": "ag-1",
|
||||
"access_group_name": "group one",
|
||||
"access_model_names": ["gpt-4"],
|
||||
}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_accessgrouptable.find_unique = AsyncMock(return_value=access_row)
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_access_object(
|
||||
access_group_id="ag-1",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
proxy_logging_obj=None,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_AccessGroupTable)
|
||||
assert result.access_group_id == "ag-1"
|
||||
assert result.access_model_names == ["gpt-4"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_team_object_by_alias_db_fetch_returns_cached_obj():
|
||||
from litellm.proxy._types import LiteLLM_TeamTableCachedObj
|
||||
from litellm.proxy.auth.auth_checks import get_team_object_by_alias
|
||||
|
||||
team_row = MagicMock()
|
||||
team_row.model_dump = lambda: {"team_id": "t-9", "team_alias": "alias-9", "models": ["gpt-4"]}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_teamtable.find_many = AsyncMock(return_value=[team_row])
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_team_object_by_alias(
|
||||
team_alias="alias-9",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_TeamTableCachedObj)
|
||||
assert result.team_id == "t-9"
|
||||
assert result.team_alias == "alias-9"
|
||||
assert result.models == ["gpt-4"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_org_object_by_alias_db_fetch_returns_validated_org():
|
||||
from litellm.proxy._types import LiteLLM_OrganizationTable
|
||||
from litellm.proxy.auth.auth_checks import get_org_object_by_alias
|
||||
|
||||
org_row = MagicMock()
|
||||
org_row.model_dump = lambda: {
|
||||
"organization_id": "org-1",
|
||||
"organization_alias": "org-alias",
|
||||
"budget_id": "b-1",
|
||||
"created_by": "admin",
|
||||
"updated_by": "admin",
|
||||
"models": [],
|
||||
}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_organizationtable.find_many = AsyncMock(return_value=[org_row])
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_org_object_by_alias(
|
||||
org_alias="org-alias",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_OrganizationTable)
|
||||
assert result.organization_id == "org-1"
|
||||
assert result.budget_id == "b-1"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_object_permission_db_fetch_returns_validated_permission():
|
||||
from litellm.proxy.auth.auth_checks import get_object_permission
|
||||
|
||||
perm_row = MagicMock()
|
||||
perm_row.dict = lambda: {"object_permission_id": "op-1", "vector_stores": ["vs-1"]}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_objectpermissiontable.find_unique = AsyncMock(return_value=perm_row)
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_object_permission(
|
||||
object_permission_id="op-1",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_ObjectPermissionTable)
|
||||
assert result.object_permission_id == "op-1"
|
||||
assert result.vector_stores == ["vs-1"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_managed_vector_store_rows_by_uuids_db_fetch_validates_rows():
|
||||
from litellm.proxy._types import LiteLLM_ManagedVectorStoresTable
|
||||
from litellm.proxy.auth.auth_checks import get_managed_vector_store_rows_by_uuids
|
||||
|
||||
vs_row = MagicMock()
|
||||
vs_row.model_dump = lambda: {"vector_store_id": "vs-7", "custom_llm_provider": "openai"}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_managedvectorstorestable.find_many = AsyncMock(return_value=[vs_row])
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_managed_vector_store_rows_by_uuids(
|
||||
uuids=["vs-7"],
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert len(result) == 1
|
||||
assert isinstance(result[0], LiteLLM_ManagedVectorStoresTable)
|
||||
assert result[0].vector_store_id == "vs-7"
|
||||
assert result[0].custom_llm_provider == "openai"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_project_object_db_fetch_returns_cached_obj():
|
||||
from litellm.proxy._types import LiteLLM_ProjectTableCachedObj
|
||||
from litellm.proxy.auth.auth_checks import get_project_object
|
||||
|
||||
project_row = MagicMock()
|
||||
project_row.model_dump = lambda: {"project_id": "p-1", "project_alias": "proj", "team_id": "t-1"}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_projecttable.find_unique = AsyncMock(return_value=project_row)
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.async_get_cache = AsyncMock(return_value=None)
|
||||
mock_cache.async_set_cache = AsyncMock()
|
||||
|
||||
result = await get_project_object(
|
||||
project_id="p-1",
|
||||
prisma_client=mock_prisma_client,
|
||||
user_api_key_cache=mock_cache,
|
||||
)
|
||||
|
||||
assert isinstance(result, LiteLLM_ProjectTableCachedObj)
|
||||
assert result.project_id == "p-1"
|
||||
assert result.project_alias == "proj"
|
||||
|
|
|
|||
|
|
@ -3667,3 +3667,38 @@ async def test_add_user_to_team_keeps_already_a_member_quiet(mocker, caplog):
|
|||
)
|
||||
|
||||
assert [r.getMessage() for r in caplog.records if r.levelno >= logging.ERROR] == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_info_for_proxy_admin_validates_keys_and_teams():
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from litellm.proxy._types import LiteLLM_TeamTable, UserAPIKeyAuth
|
||||
from litellm.proxy.management_endpoints.internal_user_endpoints import (
|
||||
_get_user_info_for_proxy_admin,
|
||||
)
|
||||
|
||||
raw_rows = [
|
||||
{
|
||||
"teams": [
|
||||
{"team_id": "team-b", "team_alias": "beta"},
|
||||
{"team_id": "team-a", "team_alias": "alpha"},
|
||||
],
|
||||
"keys": [
|
||||
{"token": "hashed-token-1", "team_id": "team-a", "models": None, "spend": 1.0},
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.query_raw = AsyncMock(return_value=raw_rows)
|
||||
|
||||
with patch("litellm.proxy.proxy_server.prisma_client", mock_prisma_client):
|
||||
result = await _get_user_info_for_proxy_admin(user_api_key_dict=UserAPIKeyAuth(user_id=None))
|
||||
|
||||
assert all(isinstance(team, LiteLLM_TeamTable) for team in result.teams)
|
||||
assert [team.team_alias for team in result.teams] == ["alpha", "beta"]
|
||||
assert len(result.keys) == 1
|
||||
returned_key = result.keys[0]
|
||||
assert returned_key["team_id"] == "team-a"
|
||||
assert returned_key["models"] == []
|
||||
|
|
|
|||
|
|
@ -10223,3 +10223,68 @@ def test_patch_team_route_publishes_its_request_body_schema():
|
|||
assert schema == {"$ref": "#/components/schemas/PatchTeamRequest"}
|
||||
properties = app.openapi()["components"]["schemas"]["PatchTeamRequest"]["properties"]
|
||||
assert "tpm_limit" in properties and "metadata" in properties
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_all_team_memberships_validates_rows():
|
||||
from litellm.proxy._types import LiteLLM_TeamMembership
|
||||
from litellm.proxy.management_endpoints.team_endpoints import (
|
||||
get_all_team_memberships,
|
||||
)
|
||||
|
||||
membership_row = MagicMock()
|
||||
membership_row.model_dump = lambda: {
|
||||
"user_id": "member-1",
|
||||
"team_id": "team-1",
|
||||
"spend": 2.5,
|
||||
}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_teammembership.find_many = AsyncMock(return_value=[membership_row])
|
||||
|
||||
result = await get_all_team_memberships(mock_prisma_client, ["team-1"], user_id="member-1")
|
||||
|
||||
assert len(result) == 1
|
||||
assert isinstance(result[0], LiteLLM_TeamMembership)
|
||||
assert result[0].user_id == "member-1"
|
||||
assert result[0].team_id == "team-1"
|
||||
assert result[0].spend == 2.5
|
||||
find_many_kwargs = mock_prisma_client.db.litellm_teammembership.find_many.call_args.kwargs
|
||||
assert find_many_kwargs["where"] == {"team_id": {"in": ["team-1"]}, "user_id": {"in": ["member-1"]}}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_available_teams_filters_joined_and_validates_rows(monkeypatch):
|
||||
from fastapi import Request
|
||||
|
||||
import litellm
|
||||
from litellm.proxy.management_endpoints.team_endpoints import list_available_teams
|
||||
|
||||
monkeypatch.setattr(
|
||||
litellm,
|
||||
"default_internal_user_params",
|
||||
{"available_teams": ["team-open", "team-joined"]},
|
||||
)
|
||||
|
||||
user_row = MagicMock()
|
||||
user_row.model_dump = lambda: {"user_id": "u-1", "teams": ["team-joined"]}
|
||||
|
||||
open_team_row = MagicMock()
|
||||
open_team_row.model_dump = lambda: {"team_id": "team-open", "team_alias": "open team"}
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
mock_prisma_client.db.litellm_usertable.find_unique = AsyncMock(return_value=user_row)
|
||||
mock_prisma_client.db.litellm_teamtable.find_many = AsyncMock(return_value=[open_team_row])
|
||||
|
||||
with patch("litellm.proxy.proxy_server.prisma_client", mock_prisma_client):
|
||||
result = await list_available_teams(
|
||||
http_request=MagicMock(spec=Request),
|
||||
user_api_key_dict=UserAPIKeyAuth(user_id="u-1"),
|
||||
)
|
||||
|
||||
assert len(result) == 1
|
||||
assert isinstance(result[0], LiteLLM_TeamTable)
|
||||
assert result[0].team_id == "team-open"
|
||||
assert result[0].team_alias == "open team"
|
||||
find_many_kwargs = mock_prisma_client.db.litellm_teamtable.find_many.call_args.kwargs
|
||||
assert find_many_kwargs["where"] == {"team_id": {"in": ["team-open"]}}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue