mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
test(proxy): cover every /v1/files route error type and param
This commit is contained in:
parent
57fd8f6f49
commit
edde95197a
1 changed files with 99 additions and 0 deletions
|
|
@ -4666,3 +4666,102 @@ def test_create_file_path_traversal_filename_rejected_before_forwarding(monkeypa
|
|||
assert error["param"] == "file"
|
||||
assert "traversal" in error["message"].lower()
|
||||
assert forwarded_calls == []
|
||||
|
||||
|
||||
def _setup_managed_file_route_answering_404(mocker: MockerFixture, monkeypatch, llm_router: Router):
|
||||
"""Wire the single-file routes to a managed file store that knows no file, the way the
|
||||
managed files hook answers once a file has been deleted or was never the caller's."""
|
||||
import litellm.proxy.proxy_server as ps
|
||||
from fastapi import HTTPException
|
||||
from litellm.llms.base_llm.files.transformation import BaseFileEndpoints
|
||||
from litellm.proxy._types import LitellmUserRoles
|
||||
|
||||
async def _file_not_found(file_id: str, **kwargs):
|
||||
raise HTTPException(status_code=404, detail=f"File not found: {file_id}")
|
||||
|
||||
proxy_logging_obj = setup_proxy_logging_object(monkeypatch, llm_router)
|
||||
managed_files = mocker.MagicMock(spec=BaseFileEndpoints)
|
||||
managed_files.afile_retrieve = mocker.AsyncMock(side_effect=_file_not_found)
|
||||
managed_files.afile_delete = mocker.AsyncMock(side_effect=_file_not_found)
|
||||
managed_files.afile_content = mocker.AsyncMock(side_effect=_file_not_found)
|
||||
proxy_logging_obj.proxy_hook_mapping["managed_files"] = managed_files
|
||||
monkeypatch.setattr("litellm.proxy.proxy_server.llm_router", llm_router)
|
||||
|
||||
app.dependency_overrides[ps.user_api_key_auth] = lambda: UserAPIKeyAuth(
|
||||
api_key="test-key",
|
||||
user_role=LitellmUserRoles.INTERNAL_USER,
|
||||
user_id="test-user",
|
||||
)
|
||||
|
||||
|
||||
def _call_managed_file_route(method: str, path: str):
|
||||
try:
|
||||
return client.request(method, path, headers={"Authorization": "Bearer test-key"})
|
||||
finally:
|
||||
import litellm.proxy.proxy_server as ps
|
||||
|
||||
app.dependency_overrides.pop(ps.user_api_key_auth, None)
|
||||
|
||||
|
||||
def _missing_managed_file_error(file_id: str) -> dict:
|
||||
return {
|
||||
"error": {
|
||||
"message": f"File not found: {file_id}",
|
||||
"type": "invalid_request_error",
|
||||
"param": None,
|
||||
"code": "404",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_create_file_reports_a_half_specified_expires_after_as_a_400(monkeypatch, llm_router: Router):
|
||||
"""A 400 raised inside the route answers with the type a 400 stands for and a JSON null
|
||||
param, not the literal string "None" in both fields, so a client can classify it."""
|
||||
setup_proxy_logging_object(monkeypatch, llm_router)
|
||||
monkeypatch.setattr("litellm.proxy.proxy_server.llm_router", llm_router)
|
||||
|
||||
response = client.post(
|
||||
"/v1/files",
|
||||
files={"file": ("mydata.jsonl", VALID_BATCH_LINE, "application/jsonl")},
|
||||
data={"purpose": "batch", "target_model_names": "gpt-3.5-turbo", "expires_after[anchor]": "created_at"},
|
||||
headers={"Authorization": "Bearer test-key"},
|
||||
)
|
||||
|
||||
assert response.status_code == 400, response.text
|
||||
error = response.json()["error"]
|
||||
assert "expires_after[seconds]" in error["message"]
|
||||
assert error["type"] == "invalid_request_error"
|
||||
assert error["param"] is None
|
||||
assert error["code"] == "400"
|
||||
|
||||
|
||||
def test_get_file_reports_a_missing_managed_file_as_a_404(mocker: MockerFixture, monkeypatch, llm_router: Router):
|
||||
_setup_managed_file_route_answering_404(mocker, monkeypatch, llm_router)
|
||||
file_id = _unified_managed_file_id()
|
||||
|
||||
response = _call_managed_file_route("GET", f"/v1/files/{file_id}")
|
||||
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == _missing_managed_file_error(file_id)
|
||||
|
||||
|
||||
def test_delete_file_reports_a_missing_managed_file_as_a_404(mocker: MockerFixture, monkeypatch, llm_router: Router):
|
||||
_setup_managed_file_route_answering_404(mocker, monkeypatch, llm_router)
|
||||
file_id = _unified_managed_file_id()
|
||||
|
||||
response = _call_managed_file_route("DELETE", f"/v1/files/{file_id}")
|
||||
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == _missing_managed_file_error(file_id)
|
||||
|
||||
|
||||
def test_get_file_content_reports_a_missing_managed_file_as_a_404(
|
||||
mocker: MockerFixture, monkeypatch, llm_router: Router
|
||||
):
|
||||
_setup_managed_file_route_answering_404(mocker, monkeypatch, llm_router)
|
||||
file_id = _unified_managed_file_id()
|
||||
|
||||
response = _call_managed_file_route("GET", f"/v1/files/{file_id}/content")
|
||||
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == _missing_managed_file_error(file_id)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue