mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
* test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): stub HIBP through respx by disabling the aiohttp transport Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): share the httpx transport fixture across proxy unit tests Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): restore proxy globals without a missing-value sentinel Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): package moved dirs and stub the login breach check at the HTTP boundary Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): isolate the mcp server manager per test Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): reuse the shared httpx transport fixture in moved proxy tests Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): stub outbound HTTP and package moved test dirs Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): restore the config server hostname in the mcp resolution test Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(proxy): pin the completion tokenizer model in the straiker screening test Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: yuneng <yuneng@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
100 lines
3.6 KiB
Python
100 lines
3.6 KiB
Python
"""Unit tests for the at-rest encryption-migration HTTP endpoints.
|
|
|
|
The endpoint bodies are exercised directly with the migration engine mocked, so
|
|
the admin guard, db-not-connected guard, and success path are all covered
|
|
without touching a live DB. The live ASGI/auth contract is covered separately in
|
|
``tests/proxy_behavior/management/test_credential_migration_endpoint.py``.
|
|
"""
|
|
|
|
from types import SimpleNamespace
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from litellm.proxy import proxy_server
|
|
from litellm.proxy._types import LitellmUserRoles
|
|
from litellm.proxy.management_endpoints import credential_migration as cm
|
|
from litellm.proxy.management_endpoints.key_management_endpoints import (
|
|
check_encryption_endpoint,
|
|
migrate_encryption_endpoint,
|
|
)
|
|
|
|
ADMIN = SimpleNamespace(user_role=LitellmUserRoles.PROXY_ADMIN.value)
|
|
NONADMIN = SimpleNamespace(user_role=LitellmUserRoles.INTERNAL_USER.value)
|
|
|
|
|
|
def _sample_report() -> cm.MigrationReport:
|
|
report = cm.MigrationReport()
|
|
report.add(
|
|
cm.LocationReport(location="model_table", scanned=2, migrated=1, legacy=0)
|
|
)
|
|
return report
|
|
|
|
|
|
# ------------------------------- check endpoint -------------------------------
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_check_endpoint_success(monkeypatch):
|
|
monkeypatch.setattr(proxy_server, "prisma_client", object())
|
|
monkeypatch.setattr(
|
|
cm, "check_encryption", AsyncMock(return_value=_sample_report())
|
|
)
|
|
|
|
out = await check_encryption_endpoint(user_api_key_dict=ADMIN)
|
|
|
|
assert out["status"] == "success"
|
|
assert out["report"]["residual_legacy"] == 0
|
|
assert out["report"]["locations"]["model_table"]["scanned"] == 2
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_check_endpoint_requires_admin(monkeypatch):
|
|
monkeypatch.setattr(proxy_server, "prisma_client", object())
|
|
with pytest.raises(HTTPException) as exc:
|
|
await check_encryption_endpoint(user_api_key_dict=NONADMIN)
|
|
assert exc.value.status_code == 403
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_check_endpoint_db_not_connected(monkeypatch):
|
|
monkeypatch.setattr(proxy_server, "prisma_client", None)
|
|
with pytest.raises(HTTPException) as exc:
|
|
await check_encryption_endpoint(user_api_key_dict=ADMIN)
|
|
assert exc.value.status_code == 500
|
|
|
|
|
|
# ------------------------------ migrate endpoint ------------------------------
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("dry_run", [False, True])
|
|
async def test_migrate_endpoint_success(monkeypatch, dry_run):
|
|
monkeypatch.setattr(proxy_server, "prisma_client", object())
|
|
fake = AsyncMock(return_value=_sample_report())
|
|
monkeypatch.setattr(cm, "migrate_encryption", fake)
|
|
|
|
out = await migrate_encryption_endpoint(user_api_key_dict=ADMIN, dry_run=dry_run)
|
|
|
|
assert out["status"] == "success"
|
|
assert out["dry_run"] is dry_run
|
|
assert out["report"]["locations"]["model_table"]["migrated"] == 1
|
|
# dry_run is threaded through to the engine unchanged.
|
|
assert fake.await_args.kwargs["dry_run"] is dry_run
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_migrate_endpoint_requires_admin(monkeypatch):
|
|
monkeypatch.setattr(proxy_server, "prisma_client", object())
|
|
with pytest.raises(HTTPException) as exc:
|
|
await migrate_encryption_endpoint(user_api_key_dict=NONADMIN)
|
|
assert exc.value.status_code == 403
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_migrate_endpoint_db_not_connected(monkeypatch):
|
|
monkeypatch.setattr(proxy_server, "prisma_client", None)
|
|
with pytest.raises(HTTPException) as exc:
|
|
await migrate_encryption_endpoint(user_api_key_dict=ADMIN)
|
|
assert exc.value.status_code == 500
|