mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
fix test models
This commit is contained in:
parent
f755b70528
commit
81d96b9ffe
1 changed files with 139 additions and 121 deletions
|
|
@ -3,6 +3,7 @@ import sys
|
|||
|
||||
import pytest
|
||||
import requests
|
||||
import responses
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../../..")
|
||||
|
|
@ -23,10 +24,6 @@ def base_url():
|
|||
def api_key():
|
||||
return "test-api-key"
|
||||
|
||||
@pytest.fixture
|
||||
def requests_mock():
|
||||
return requests_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(base_url, api_key):
|
||||
|
|
@ -80,7 +77,8 @@ def test_list_url_variants(base_url, expected):
|
|||
assert request.url == expected
|
||||
|
||||
|
||||
def test_list_with_mock_response(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_list_with_mock_response(client):
|
||||
"""Test the full list execution with a mocked response"""
|
||||
mock_data = {
|
||||
"data": [
|
||||
|
|
@ -88,7 +86,12 @@ def test_list_with_mock_response(client, requests_mock):
|
|||
{"id": "gpt-3.5-turbo", "type": "model"},
|
||||
]
|
||||
}
|
||||
requests_mock.get("http://localhost:8000/models", json=mock_data)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://localhost:8000/models",
|
||||
json=mock_data,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.list()
|
||||
assert response == mock_data["data"]
|
||||
|
|
@ -96,11 +99,13 @@ def test_list_with_mock_response(client, requests_mock):
|
|||
assert response[0]["id"] == "gpt-4"
|
||||
|
||||
|
||||
def test_list_unauthorized_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_list_unauthorized_error(client):
|
||||
"""Test that list raises UnauthorizedError for 401 responses"""
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://localhost:8000/models",
|
||||
status_code=401,
|
||||
status=401,
|
||||
json={"error": "Invalid API key"},
|
||||
)
|
||||
|
||||
|
|
@ -109,11 +114,13 @@ def test_list_unauthorized_error(client, requests_mock):
|
|||
assert exc_info.value.orig_exception.response.status_code == 401
|
||||
|
||||
|
||||
def test_list_other_errors(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_list_other_errors(client):
|
||||
"""Test that list raises normal HTTPError for non-401 errors"""
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://localhost:8000/models",
|
||||
status_code=500,
|
||||
status=500,
|
||||
json={"error": "Internal Server Error"},
|
||||
)
|
||||
|
||||
|
|
@ -142,62 +149,6 @@ def test_client_initialization_strips_trailing_slash():
|
|||
assert client._base_url == "http://localhost:8000"
|
||||
|
||||
|
||||
def test_list_with_mock_response(client, requests_mock):
|
||||
"""Test the full list execution with a mocked response"""
|
||||
mock_data = {
|
||||
"data": [
|
||||
{"id": "gpt-4", "type": "model"},
|
||||
{"id": "gpt-3.5-turbo", "type": "model"},
|
||||
]
|
||||
}
|
||||
requests_mock.get("http://localhost:8000/models", json=mock_data)
|
||||
|
||||
response = client.list()
|
||||
assert response == mock_data["data"]
|
||||
assert len(response) == 2
|
||||
assert response[0]["id"] == "gpt-4"
|
||||
|
||||
|
||||
def test_list_unauthorized_error(client, requests_mock):
|
||||
"""Test that list raises UnauthorizedError for 401 responses"""
|
||||
requests_mock.get(
|
||||
"http://localhost:8000/models",
|
||||
status_code=401,
|
||||
json={"error": "Invalid API key"},
|
||||
)
|
||||
|
||||
with pytest.raises(UnauthorizedError) as exc_info:
|
||||
client.list()
|
||||
assert exc_info.value.orig_exception.response.status_code == 401
|
||||
|
||||
|
||||
def test_list_other_errors(client, requests_mock):
|
||||
"""Test that list raises normal HTTPError for non-401 errors"""
|
||||
requests_mock.get(
|
||||
"http://localhost:8000/models",
|
||||
status_code=500,
|
||||
json={"error": "Internal Server Error"},
|
||||
)
|
||||
|
||||
with pytest.raises(requests.exceptions.HTTPError) as exc_info:
|
||||
client.list()
|
||||
assert exc_info.value.response.status_code == 500
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"api_key",
|
||||
[
|
||||
"", # Empty string
|
||||
None, # None value
|
||||
],
|
||||
)
|
||||
def test_list_invalid_api_keys(base_url, api_key):
|
||||
"""Test that the client handles invalid API keys appropriately"""
|
||||
client = ModelsManagementClient(base_url=base_url, api_key=api_key)
|
||||
request = client.list(return_request=True)
|
||||
assert "Authorization" not in request.headers
|
||||
|
||||
|
||||
def test_client_initialization(base_url, api_key):
|
||||
"""Test that the Client is properly initialized with all resource clients"""
|
||||
client = Client(base_url=base_url, api_key=api_key)
|
||||
|
|
@ -271,28 +222,38 @@ def test_new_without_model_info(client):
|
|||
assert request.json == {"model_name": model_name, "litellm_params": model_params}
|
||||
|
||||
|
||||
def test_new_mock_response(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_new_mock_response(client):
|
||||
"""Test new with a mocked successful response"""
|
||||
model_name = "gpt-4"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
mock_response = {"model_id": "123", "status": "success"}
|
||||
|
||||
# Mock the POST request
|
||||
requests_mock.post(f"{client._base_url}/model/new", json=mock_response)
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/new",
|
||||
json=mock_response,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.new(model_name=model_name, model_params=model_params)
|
||||
|
||||
assert response == mock_response
|
||||
|
||||
|
||||
def test_new_unauthorized_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_new_unauthorized_error(client):
|
||||
"""Test that new raises UnauthorizedError for 401 responses"""
|
||||
model_name = "gpt-4"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
|
||||
# Mock a 401 response
|
||||
requests_mock.post(
|
||||
f"{client._base_url}/model/new", status_code=401, json={"error": "Unauthorized"}
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/new",
|
||||
status=401,
|
||||
json={"error": "Unauthorized"},
|
||||
)
|
||||
|
||||
with pytest.raises(UnauthorizedError):
|
||||
|
|
@ -317,26 +278,34 @@ def test_delete_request_creation(client, base_url, api_key):
|
|||
assert request.json == {"id": model_id}
|
||||
|
||||
|
||||
def test_delete_mock_response(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_delete_mock_response(client):
|
||||
"""Test delete with a mocked successful response"""
|
||||
model_id = "model-123"
|
||||
mock_response = {"message": "Model: model-123 deleted successfully"}
|
||||
|
||||
# Mock the POST request
|
||||
requests_mock.post(f"{client._base_url}/model/delete", json=mock_response)
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/delete",
|
||||
json=mock_response,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.delete(model_id=model_id)
|
||||
assert response == mock_response
|
||||
|
||||
|
||||
def test_delete_unauthorized_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_delete_unauthorized_error(client):
|
||||
"""Test that delete raises UnauthorizedError for 401 responses"""
|
||||
model_id = "model-123"
|
||||
|
||||
# Mock a 401 response
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/delete",
|
||||
status_code=401,
|
||||
status=401,
|
||||
json={"error": "Unauthorized"},
|
||||
)
|
||||
|
||||
|
|
@ -344,14 +313,16 @@ def test_delete_unauthorized_error(client, requests_mock):
|
|||
client.delete(model_id=model_id)
|
||||
|
||||
|
||||
def test_delete_404_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_delete_404_error(client):
|
||||
"""Test that delete raises NotFoundError for 404 responses"""
|
||||
model_id = "model-123"
|
||||
|
||||
# Mock a 404 response
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/delete",
|
||||
status_code=404,
|
||||
status=404,
|
||||
json={"error": "Model not found"},
|
||||
)
|
||||
|
||||
|
|
@ -360,14 +331,16 @@ def test_delete_404_error(client, requests_mock):
|
|||
assert exc_info.value.orig_exception.response.status_code == 404
|
||||
|
||||
|
||||
def test_delete_not_found_in_text(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_delete_not_found_in_text(client):
|
||||
"""Test that delete raises NotFoundError when response contains 'not found'"""
|
||||
model_id = "model-123"
|
||||
|
||||
# Mock a response with "not found" in text but different status code
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/delete",
|
||||
status_code=400, # Different status code
|
||||
status=400, # Different status code
|
||||
json={"error": "The specified model was not found in the system"},
|
||||
)
|
||||
|
||||
|
|
@ -376,14 +349,16 @@ def test_delete_not_found_in_text(client, requests_mock):
|
|||
assert "not found" in exc_info.value.orig_exception.response.text.lower()
|
||||
|
||||
|
||||
def test_delete_other_errors(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_delete_other_errors(client):
|
||||
"""Test that delete raises normal HTTPError for other error responses"""
|
||||
model_id = "model-123"
|
||||
|
||||
# Mock a 500 response
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/delete",
|
||||
status_code=500,
|
||||
status=500,
|
||||
json={"error": "Internal Server Error"},
|
||||
)
|
||||
|
||||
|
|
@ -404,7 +379,8 @@ def test_info_request_creation(client, base_url, api_key):
|
|||
assert request.headers["Authorization"] == f"Bearer {api_key}"
|
||||
|
||||
|
||||
def test_info_success(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_info_success(client):
|
||||
"""Test info with a successful response"""
|
||||
mock_response = {
|
||||
"data": [
|
||||
|
|
@ -424,7 +400,12 @@ def test_info_success(client, requests_mock):
|
|||
]
|
||||
}
|
||||
|
||||
requests_mock.get(f"{client._base_url}/v1/model/info", json=mock_response)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
json=mock_response,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.info()
|
||||
assert response == mock_response["data"]
|
||||
|
|
@ -433,11 +414,13 @@ def test_info_success(client, requests_mock):
|
|||
assert response[1]["model_name"] == "gpt-3.5-turbo"
|
||||
|
||||
|
||||
def test_info_unauthorized(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_info_unauthorized(client):
|
||||
"""Test that info raises UnauthorizedError for unauthorized requests"""
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
status_code=401,
|
||||
status=401,
|
||||
json={"error": "Unauthorized"},
|
||||
)
|
||||
|
||||
|
|
@ -446,11 +429,13 @@ def test_info_unauthorized(client, requests_mock):
|
|||
assert exc_info.value.orig_exception.response.status_code == 401
|
||||
|
||||
|
||||
def test_info_server_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_info_server_error(client):
|
||||
"""Test that info raises HTTPError for server errors"""
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
status_code=500,
|
||||
status=500,
|
||||
json={"error": "Internal Server Error"},
|
||||
)
|
||||
|
||||
|
|
@ -501,7 +486,8 @@ def test_get_invalid_params():
|
|||
)
|
||||
|
||||
|
||||
def test_get_success_by_id(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_get_success_by_id(client):
|
||||
"""Test get successfully finding a model by ID"""
|
||||
model_id = "model-123"
|
||||
mock_models = {
|
||||
|
|
@ -518,14 +504,20 @@ def test_get_success_by_id(client, requests_mock):
|
|||
]
|
||||
}
|
||||
|
||||
requests_mock.get(f"{client._base_url}/v1/model/info", json=mock_models)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
json=mock_models,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.get(model_id=model_id)
|
||||
assert response["model_info"]["id"] == model_id
|
||||
assert response["model_name"] == "gpt-4"
|
||||
|
||||
|
||||
def test_get_success_by_name(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_get_success_by_name(client):
|
||||
"""Test get successfully finding a model by name"""
|
||||
model_name = "gpt-4"
|
||||
mock_models = {
|
||||
|
|
@ -538,24 +530,32 @@ def test_get_success_by_name(client, requests_mock):
|
|||
]
|
||||
}
|
||||
|
||||
requests_mock.get(f"{client._base_url}/v1/model/info", json=mock_models)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
json=mock_models,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.get(model_name=model_name)
|
||||
assert response["model_name"] == model_name
|
||||
|
||||
|
||||
def test_get_not_found(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_get_not_found(client):
|
||||
"""Test that get raises NotFoundError when model is not found"""
|
||||
model_name = "nonexistent-model"
|
||||
|
||||
# Mock successful response but with no matching model
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
json={
|
||||
"data": [
|
||||
{"model_name": "gpt-3.5-turbo", "model_info": {"id": "other-model"}}
|
||||
]
|
||||
},
|
||||
status=200,
|
||||
)
|
||||
|
||||
with pytest.raises(NotFoundError) as exc_info:
|
||||
|
|
@ -564,13 +564,15 @@ def test_get_not_found(client, requests_mock):
|
|||
assert "model_name=" + model_name in str(exc_info.value)
|
||||
|
||||
|
||||
def test_get_unauthorized(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_get_unauthorized(client):
|
||||
"""Test that get raises UnauthorizedError for unauthorized requests"""
|
||||
model_id = "model-123"
|
||||
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
status_code=401,
|
||||
status=401,
|
||||
json={"error": "Unauthorized"},
|
||||
)
|
||||
|
||||
|
|
@ -579,13 +581,15 @@ def test_get_unauthorized(client, requests_mock):
|
|||
assert exc_info.value.orig_exception.response.status_code == 401
|
||||
|
||||
|
||||
def test_get_server_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_get_server_error(client):
|
||||
"""Test that get raises HTTPError for server errors"""
|
||||
model_id = "model-123"
|
||||
|
||||
requests_mock.get(
|
||||
responses.add(
|
||||
responses.GET,
|
||||
f"{client._base_url}/v1/model/info",
|
||||
status_code=500,
|
||||
status=500,
|
||||
json={"error": "Internal Server Error"},
|
||||
)
|
||||
|
||||
|
|
@ -636,7 +640,8 @@ def test_update_without_model_info(client):
|
|||
assert request.json == {"id": model_id, "litellm_params": model_params}
|
||||
|
||||
|
||||
def test_update_mock_response(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_update_mock_response(client):
|
||||
"""Test update with a mocked successful response"""
|
||||
model_id = "model-123"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
|
|
@ -647,22 +652,29 @@ def test_update_mock_response(client, requests_mock):
|
|||
}
|
||||
|
||||
# Mock the POST request
|
||||
requests_mock.post(f"{client._base_url}/model/update", json=mock_response)
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/update",
|
||||
json=mock_response,
|
||||
status=200,
|
||||
)
|
||||
|
||||
response = client.update(model_id=model_id, model_params=model_params)
|
||||
|
||||
assert response == mock_response
|
||||
|
||||
|
||||
def test_update_unauthorized_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_update_unauthorized_error(client):
|
||||
"""Test that update raises UnauthorizedError for 401 responses"""
|
||||
model_id = "model-123"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
|
||||
# Mock a 401 response
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/update",
|
||||
status_code=401,
|
||||
status=401,
|
||||
json={"error": "Unauthorized"},
|
||||
)
|
||||
|
||||
|
|
@ -670,15 +682,17 @@ def test_update_unauthorized_error(client, requests_mock):
|
|||
client.update(model_id=model_id, model_params=model_params)
|
||||
|
||||
|
||||
def test_update_404_error(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_update_404_error(client):
|
||||
"""Test that update raises NotFoundError for 404 responses"""
|
||||
model_id = "model-123"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
|
||||
# Mock a 404 response
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/update",
|
||||
status_code=404,
|
||||
status=404,
|
||||
json={"error": "Model not found"},
|
||||
)
|
||||
|
||||
|
|
@ -687,15 +701,17 @@ def test_update_404_error(client, requests_mock):
|
|||
assert exc_info.value.orig_exception.response.status_code == 404
|
||||
|
||||
|
||||
def test_update_not_found_in_text(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_update_not_found_in_text(client):
|
||||
"""Test that update raises NotFoundError when response contains 'not found'"""
|
||||
model_id = "model-123"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
|
||||
# Mock a response with "not found" in text but different status code
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/update",
|
||||
status_code=400, # Different status code
|
||||
status=400, # Different status code
|
||||
json={"error": "The specified model was not found in the system"},
|
||||
)
|
||||
|
||||
|
|
@ -704,15 +720,17 @@ def test_update_not_found_in_text(client, requests_mock):
|
|||
assert "not found" in exc_info.value.orig_exception.response.text.lower()
|
||||
|
||||
|
||||
def test_update_other_errors(client, requests_mock):
|
||||
@responses.activate
|
||||
def test_update_other_errors(client):
|
||||
"""Test that update raises normal HTTPError for other error responses"""
|
||||
model_id = "model-123"
|
||||
model_params = {"model": "openai/gpt-4"}
|
||||
|
||||
# Mock a 500 response
|
||||
requests_mock.post(
|
||||
responses.add(
|
||||
responses.POST,
|
||||
f"{client._base_url}/model/update",
|
||||
status_code=500,
|
||||
status=500,
|
||||
json={"error": "Internal Server Error"},
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue