mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-02 02:11:58 +00:00
test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015)
Co-authored-by: yuneng <yuneng@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
24584d3d3d
commit
a76b59db9f
198 changed files with 363 additions and 25 deletions
102
.github/workflows/test-unit.yml
vendored
102
.github/workflows/test-unit.yml
vendored
|
|
@ -199,17 +199,103 @@ jobs:
|
|||
tests/unit/proxy/db
|
||||
--ignore=tests/unit/proxy/db/db_transaction_queue/test_e2e_pod_lock_manager.py
|
||||
--ignore=tests/unit/proxy/db/test_update_daily_tag_spend.py
|
||||
tests/test_litellm/proxy/middleware
|
||||
tests/test_litellm/proxy/spend_tracking
|
||||
tests/unit/proxy/middleware
|
||||
--ignore=tests/unit/proxy/middleware/test_request_size_limit_middleware.py
|
||||
tests/unit/proxy/spend_tracking
|
||||
--ignore=tests/unit/proxy/spend_tracking/test_search_api_logging.py
|
||||
tests/unit/proxy/pass_through_endpoints
|
||||
tests/test_litellm/proxy/pass_through_endpoints
|
||||
tests/unit/proxy/_experimental
|
||||
--ignore=tests/unit/proxy/_experimental/mcp_server
|
||||
tests/test_litellm/proxy/experimental
|
||||
tests/test_litellm/proxy/common_utils
|
||||
tests/test_litellm/proxy/enterprise_billing
|
||||
tests/test_litellm/proxy/types_utils
|
||||
tests/test_litellm/proxy/logging_endpoints
|
||||
tests/test_litellm/proxy/test_*.py
|
||||
tests/unit/proxy/experimental
|
||||
tests/unit/proxy/common_utils
|
||||
--ignore=tests/unit/proxy/common_utils/test_cache_aware_routing.py
|
||||
--ignore=tests/unit/proxy/common_utils/test_check_batch_cost.py
|
||||
--ignore=tests/unit/proxy/common_utils/test_check_responses_cost.py
|
||||
--ignore=tests/unit/proxy/common_utils/test_proxy_encrypt_decrypt.py
|
||||
--ignore=tests/unit/proxy/common_utils/test_realtime_cache.py
|
||||
tests/unit/proxy/enterprise_billing
|
||||
tests/unit/proxy/types_utils
|
||||
tests/unit/proxy/logging_endpoints
|
||||
tests/unit/proxy/test__types.py
|
||||
tests/unit/proxy/test_aiohttp_cleanup_closed.py
|
||||
tests/unit/proxy/test_aiohttp_session_recovery.py
|
||||
tests/unit/proxy/test_api_key_masking_in_errors.py
|
||||
tests/unit/proxy/test_audio_speech_prometheus_hooks.py
|
||||
tests/unit/proxy/test_batch_expiry.py
|
||||
tests/unit/proxy/test_batch_metadata_none_fix.py
|
||||
tests/unit/proxy/test_batch_retrieve_bedrock.py
|
||||
tests/unit/proxy/test_batch_x_litellm_model_encoding.py
|
||||
tests/unit/proxy/test_blocked_response_usage.py
|
||||
tests/unit/proxy/test_body_snapshot_callback_params.py
|
||||
tests/unit/proxy/test_budget_reservation.py
|
||||
tests/unit/proxy/test_bug_report_config.py
|
||||
tests/unit/proxy/test_caching_routes.py
|
||||
tests/unit/proxy/test_chat_completion_metadata.py
|
||||
tests/unit/proxy/test_claude_code_marketplace.py
|
||||
tests/unit/proxy/test_collector.py
|
||||
tests/unit/proxy/test_common_request_processing.py
|
||||
tests/unit/proxy/test_component_allowlists.py
|
||||
tests/unit/proxy/test_conftest.py
|
||||
tests/unit/proxy/test_cors_config.py
|
||||
tests/unit/proxy/test_custom_proxy.py
|
||||
tests/unit/proxy/test_dynamic_mcp_route.py
|
||||
tests/unit/proxy/test_empty_model_list.py
|
||||
tests/unit/proxy/test_enforce_user_param.py
|
||||
tests/unit/proxy/test_fallback_management_endpoints.py
|
||||
tests/unit/proxy/test_fastapi_offline_routes.py
|
||||
tests/unit/proxy/test_filter_models_by_team_access_group.py
|
||||
tests/unit/proxy/test_health_check_functions.py
|
||||
tests/unit/proxy/test_health_check_max_tokens.py
|
||||
tests/unit/proxy/test_init_litellm_callbacks.py
|
||||
tests/unit/proxy/test_langfuse_passthrough_security.py
|
||||
tests/unit/proxy/test_lazy_openapi_snapshot.py
|
||||
tests/unit/proxy/test_litellm_pre_call_utils.py
|
||||
tests/unit/proxy/test_max_budget_env_var.py
|
||||
tests/unit/proxy/test_mcp_asgi_response.py
|
||||
tests/unit/proxy/test_model_based_routing_files_batches.py
|
||||
tests/unit/proxy/test_model_deprecations_endpoint.py
|
||||
tests/unit/proxy/test_model_dump_with_preserved_fields.py
|
||||
tests/unit/proxy/test_model_id_header_propagation.py
|
||||
tests/unit/proxy/test_model_info_default_limits.py
|
||||
tests/unit/proxy/test_model_level_guardrails.py
|
||||
tests/unit/proxy/test_model_list_aliases.py
|
||||
tests/unit/proxy/test_model_list_callback_filter.py
|
||||
tests/unit/proxy/test_model_list_discoverable.py
|
||||
tests/unit/proxy/test_model_list_healthy_only.py
|
||||
tests/unit/proxy/test_modify_response_streaming_passthrough.py
|
||||
tests/unit/proxy/test_native_compaction.py
|
||||
tests/unit/proxy/test_openai_ws_passthrough_routes.py
|
||||
tests/unit/proxy/test_openapi_schema_validation.py
|
||||
tests/unit/proxy/test_plugin_routes.py
|
||||
tests/unit/proxy/test_pointfive_dashboard_config.py
|
||||
tests/unit/proxy/test_pointfive_ui_callback.py
|
||||
tests/unit/proxy/test_pricing_field_strip.py
|
||||
tests/unit/proxy/test_prisma_engine_watchdog.py
|
||||
tests/unit/proxy/test_prisma_migration.py
|
||||
tests/unit/proxy/test_prometheus_cleanup.py
|
||||
tests/unit/proxy/test_prometheus_metrics_server.py
|
||||
tests/unit/proxy/test_provider_url_destination_guard.py
|
||||
tests/unit/proxy/test_proxy_cli.py
|
||||
tests/unit/proxy/test_proxy_logging_hook_detection.py
|
||||
tests/unit/proxy/test_proxy_types.py
|
||||
tests/unit/proxy/test_pyroscope.py
|
||||
tests/unit/proxy/test_read_model_list.py
|
||||
tests/unit/proxy/test_redis_auth_cache_flag.py
|
||||
tests/unit/proxy/test_response_model_sanitization.py
|
||||
tests/unit/proxy/test_route_a2a_models.py
|
||||
tests/unit/proxy/test_route_llm_request.py
|
||||
tests/unit/proxy/test_route_priority.py
|
||||
tests/unit/proxy/test_sensitive_route_auth.py
|
||||
tests/unit/proxy/test_shared_health_check.py
|
||||
tests/unit/proxy/test_spend_log_cleanup.py
|
||||
tests/unit/proxy/test_swagger_chat_completions.py
|
||||
tests/unit/proxy/test_team_member_update.py
|
||||
tests/unit/proxy/test_team_org_move.py
|
||||
tests/unit/proxy/test_tools_allowlist_enforcement.py
|
||||
tests/unit/proxy/test_tracing_endpoints.py
|
||||
tests/unit/proxy/test_update_llm_router_resilience.py
|
||||
tests/unit/proxy/test_zerobus_dashboard_config.py
|
||||
tests/unit/proxy/test_proxy_server_endpoints_and_startup.py
|
||||
tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py
|
||||
unit-flag: proxy-infra
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ Add your tests to the [`tests/unit/` directory](https://github.com/BerriAI/litel
|
|||
|
||||
The `tests/unit/` directory follows the same structure as `litellm/`:
|
||||
|
||||
- `litellm/proxy/caching_routes.py` → `tests/test_litellm/proxy/test_caching_routes.py`
|
||||
- `litellm/proxy/caching_routes.py` → `tests/unit/proxy/test_caching_routes.py`
|
||||
- `litellm/utils.py` → `tests/unit/test_utils.py`
|
||||
|
||||
### Example Test
|
||||
|
|
|
|||
83
Makefile
83
Makefile
|
|
@ -326,8 +326,89 @@ test-unit-proxy-guardrails: install-test-deps
|
|||
test-unit-proxy-core: install-test-deps
|
||||
$(UV_RUN) pytest tests/unit/proxy/auth tests/unit/proxy/client tests/unit/proxy/db tests/unit/proxy/hooks tests/unit/proxy/policy_engine --ignore=tests/unit/proxy/db/db_transaction_queue/test_e2e_pod_lock_manager.py --ignore=tests/unit/proxy/db/test_update_daily_tag_spend.py --tb=short -vv -n 4 --durations=20
|
||||
|
||||
PROXY_INFRA_ROOT_TESTS := \
|
||||
tests/unit/proxy/test__types.py \
|
||||
tests/unit/proxy/test_aiohttp_cleanup_closed.py \
|
||||
tests/unit/proxy/test_aiohttp_session_recovery.py \
|
||||
tests/unit/proxy/test_api_key_masking_in_errors.py \
|
||||
tests/unit/proxy/test_audio_speech_prometheus_hooks.py \
|
||||
tests/unit/proxy/test_batch_expiry.py \
|
||||
tests/unit/proxy/test_batch_metadata_none_fix.py \
|
||||
tests/unit/proxy/test_batch_retrieve_bedrock.py \
|
||||
tests/unit/proxy/test_batch_x_litellm_model_encoding.py \
|
||||
tests/unit/proxy/test_blocked_response_usage.py \
|
||||
tests/unit/proxy/test_body_snapshot_callback_params.py \
|
||||
tests/unit/proxy/test_budget_reservation.py \
|
||||
tests/unit/proxy/test_bug_report_config.py \
|
||||
tests/unit/proxy/test_caching_routes.py \
|
||||
tests/unit/proxy/test_chat_completion_metadata.py \
|
||||
tests/unit/proxy/test_claude_code_marketplace.py \
|
||||
tests/unit/proxy/test_collector.py \
|
||||
tests/unit/proxy/test_common_request_processing.py \
|
||||
tests/unit/proxy/test_component_allowlists.py \
|
||||
tests/unit/proxy/test_conftest.py \
|
||||
tests/unit/proxy/test_cors_config.py \
|
||||
tests/unit/proxy/test_custom_proxy.py \
|
||||
tests/unit/proxy/test_dynamic_mcp_route.py \
|
||||
tests/unit/proxy/test_empty_model_list.py \
|
||||
tests/unit/proxy/test_enforce_user_param.py \
|
||||
tests/unit/proxy/test_fallback_management_endpoints.py \
|
||||
tests/unit/proxy/test_fastapi_offline_routes.py \
|
||||
tests/unit/proxy/test_filter_models_by_team_access_group.py \
|
||||
tests/unit/proxy/test_health_check_functions.py \
|
||||
tests/unit/proxy/test_health_check_max_tokens.py \
|
||||
tests/unit/proxy/test_init_litellm_callbacks.py \
|
||||
tests/unit/proxy/test_langfuse_passthrough_security.py \
|
||||
tests/unit/proxy/test_lazy_openapi_snapshot.py \
|
||||
tests/unit/proxy/test_litellm_pre_call_utils.py \
|
||||
tests/unit/proxy/test_max_budget_env_var.py \
|
||||
tests/unit/proxy/test_mcp_asgi_response.py \
|
||||
tests/unit/proxy/test_model_based_routing_files_batches.py \
|
||||
tests/unit/proxy/test_model_deprecations_endpoint.py \
|
||||
tests/unit/proxy/test_model_dump_with_preserved_fields.py \
|
||||
tests/unit/proxy/test_model_id_header_propagation.py \
|
||||
tests/unit/proxy/test_model_info_default_limits.py \
|
||||
tests/unit/proxy/test_model_level_guardrails.py \
|
||||
tests/unit/proxy/test_model_list_aliases.py \
|
||||
tests/unit/proxy/test_model_list_callback_filter.py \
|
||||
tests/unit/proxy/test_model_list_discoverable.py \
|
||||
tests/unit/proxy/test_model_list_healthy_only.py \
|
||||
tests/unit/proxy/test_modify_response_streaming_passthrough.py \
|
||||
tests/unit/proxy/test_native_compaction.py \
|
||||
tests/unit/proxy/test_openai_ws_passthrough_routes.py \
|
||||
tests/unit/proxy/test_openapi_schema_validation.py \
|
||||
tests/unit/proxy/test_plugin_routes.py \
|
||||
tests/unit/proxy/test_pointfive_dashboard_config.py \
|
||||
tests/unit/proxy/test_pointfive_ui_callback.py \
|
||||
tests/unit/proxy/test_pricing_field_strip.py \
|
||||
tests/unit/proxy/test_prisma_engine_watchdog.py \
|
||||
tests/unit/proxy/test_prisma_migration.py \
|
||||
tests/unit/proxy/test_prometheus_cleanup.py \
|
||||
tests/unit/proxy/test_prometheus_metrics_server.py \
|
||||
tests/unit/proxy/test_provider_url_destination_guard.py \
|
||||
tests/unit/proxy/test_proxy_cli.py \
|
||||
tests/unit/proxy/test_proxy_logging_hook_detection.py \
|
||||
tests/unit/proxy/test_proxy_types.py \
|
||||
tests/unit/proxy/test_pyroscope.py \
|
||||
tests/unit/proxy/test_read_model_list.py \
|
||||
tests/unit/proxy/test_redis_auth_cache_flag.py \
|
||||
tests/unit/proxy/test_response_model_sanitization.py \
|
||||
tests/unit/proxy/test_route_a2a_models.py \
|
||||
tests/unit/proxy/test_route_llm_request.py \
|
||||
tests/unit/proxy/test_route_priority.py \
|
||||
tests/unit/proxy/test_sensitive_route_auth.py \
|
||||
tests/unit/proxy/test_shared_health_check.py \
|
||||
tests/unit/proxy/test_spend_log_cleanup.py \
|
||||
tests/unit/proxy/test_swagger_chat_completions.py \
|
||||
tests/unit/proxy/test_team_member_update.py \
|
||||
tests/unit/proxy/test_team_org_move.py \
|
||||
tests/unit/proxy/test_tools_allowlist_enforcement.py \
|
||||
tests/unit/proxy/test_tracing_endpoints.py \
|
||||
tests/unit/proxy/test_update_llm_router_resilience.py \
|
||||
tests/unit/proxy/test_zerobus_dashboard_config.py
|
||||
|
||||
test-unit-proxy-misc: install-test-deps
|
||||
$(UV_RUN) pytest tests/unit/proxy/agent_endpoints tests/unit/proxy/anthropic_endpoints tests/test_litellm/proxy/common_utils tests/unit/proxy/discovery_endpoints tests/test_litellm/proxy/experimental tests/unit/proxy/google_endpoints tests/unit/proxy/health_endpoints tests/unit/proxy/image_endpoints tests/test_litellm/proxy/middleware tests/unit/proxy/openai_files_endpoint tests/test_litellm/proxy/pass_through_endpoints tests/unit/proxy/prompts tests/unit/proxy/public_endpoints tests/unit/proxy/response_api_endpoints tests/unit/proxy/shutdown tests/test_litellm/proxy/spend_tracking tests/unit/proxy/ui_crud_endpoints tests/unit/proxy/vector_store_endpoints tests/test_litellm/proxy/test_*.py tests/unit/proxy/test_proxy_server_endpoints_and_startup.py tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py tests/unit/proxy/_experimental/mcp_server/test_mcp_server_tool_calls_and_headers.py --ignore=tests/unit/proxy/google_endpoints/test_gemini_agents_endpoints.py --ignore=tests/unit/proxy/google_endpoints/test_google_endpoint_routing.py --ignore=tests/unit/proxy/google_endpoints/test_google_gemini_proxy_request.py --ignore=tests/unit/proxy/public_endpoints/test_blog_posts_endpoint.py --tb=short -vv -n 4 --durations=20
|
||||
$(UV_RUN) pytest tests/unit/proxy/agent_endpoints tests/unit/proxy/anthropic_endpoints tests/unit/proxy/common_utils --ignore=tests/unit/proxy/common_utils/test_cache_aware_routing.py --ignore=tests/unit/proxy/common_utils/test_check_batch_cost.py --ignore=tests/unit/proxy/common_utils/test_check_responses_cost.py --ignore=tests/unit/proxy/common_utils/test_proxy_encrypt_decrypt.py --ignore=tests/unit/proxy/common_utils/test_realtime_cache.py tests/unit/proxy/discovery_endpoints tests/unit/proxy/experimental tests/unit/proxy/google_endpoints tests/unit/proxy/health_endpoints tests/unit/proxy/image_endpoints tests/unit/proxy/middleware --ignore=tests/unit/proxy/middleware/test_request_size_limit_middleware.py tests/unit/proxy/openai_files_endpoint tests/unit/proxy/pass_through_endpoints tests/test_litellm/proxy/pass_through_endpoints tests/unit/proxy/prompts tests/unit/proxy/public_endpoints tests/unit/proxy/response_api_endpoints tests/unit/proxy/shutdown tests/unit/proxy/spend_tracking --ignore=tests/unit/proxy/spend_tracking/test_search_api_logging.py tests/unit/proxy/ui_crud_endpoints tests/unit/proxy/vector_store_endpoints $(PROXY_INFRA_ROOT_TESTS) tests/unit/proxy/test_proxy_server_endpoints_and_startup.py tests/unit/proxy/test_proxy_utils_model_creation_and_error_logging.py tests/unit/proxy/_experimental/mcp_server/test_mcp_server_tool_calls_and_headers.py --ignore=tests/unit/proxy/google_endpoints/test_gemini_agents_endpoints.py --ignore=tests/unit/proxy/google_endpoints/test_google_endpoint_routing.py --ignore=tests/unit/proxy/google_endpoints/test_google_gemini_proxy_request.py --ignore=tests/unit/proxy/public_endpoints/test_blog_posts_endpoint.py --tb=short -vv -n 4 --durations=20
|
||||
|
||||
test-unit-integrations: install-test-deps
|
||||
$(UV_RUN) pytest tests/unit/integrations --tb=short -vv -n 4 --durations=20
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Run from repo root:
|
|||
uv run python scripts/test_tool_allowlist_script.py
|
||||
|
||||
Or run the unit tests:
|
||||
uv run pytest tests/test_litellm/proxy/test_tools_allowlist_enforcement.py -v
|
||||
uv run pytest tests/unit/proxy/test_tools_allowlist_enforcement.py -v
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
|
@ -148,7 +148,7 @@ def main():
|
|||
asyncio.run(test_check_tools_allowlist())
|
||||
print("Done. For full unit tests run:")
|
||||
print(
|
||||
" uv run pytest tests/test_litellm/proxy/test_tools_allowlist_enforcement.py -v"
|
||||
" uv run pytest tests/unit/proxy/test_tools_allowlist_enforcement.py -v"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ that would catch a regression.
|
|||
|
||||
Companion: live suite `test_spend_tracking_e2e.py` + route breadth
|
||||
`test_spend_routes.py` (this directory). Offline regression suite:
|
||||
`tests/test_litellm/proxy/spend_tracking/`. Reference PR: BerriAI/litellm#29956.
|
||||
`tests/unit/proxy/spend_tracking/`. Reference PR: BerriAI/litellm#29956.
|
||||
|
||||
Levels: `unit` mocked; `integration` real DB/cost-map; `live` real provider +
|
||||
proxy + SpendLogs rows. Status: `covered` / `partial` / `gap`.
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ async def get_spend_logs(session, request_id=None, api_key=None):
|
|||
|
||||
|
||||
@pytest.mark.skip(
|
||||
reason="Flaky in CI: /spend/logs?request_id=... returns 500 even after a 20s wait for the spend log to be written. Spend-log accuracy is covered by tests/test_litellm/proxy/spend_tracking/ and the proxy_spend_accuracy_tests CircleCI job."
|
||||
reason="Flaky in CI: /spend/logs?request_id=... returns 500 even after a 20s wait for the spend log to be written. Spend-log accuracy is covered by tests/unit/proxy/spend_tracking/ and the proxy_spend_accuracy_tests CircleCI job."
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_spend_logs():
|
||||
|
|
@ -159,7 +159,7 @@ async def generate_team(session: aiohttp.ClientSession, org_id: str) -> dict:
|
|||
|
||||
|
||||
@pytest.mark.skip(
|
||||
reason="Flaky in CI: /spend/logs?request_id=... returns 500 even after a 20s wait for the spend log to be written. Same write-then-read race against the spend logs DB as test_spend_logs. Spend-log accuracy is covered by tests/test_litellm/proxy/spend_tracking/ and the proxy_spend_accuracy_tests CircleCI job."
|
||||
reason="Flaky in CI: /spend/logs?request_id=... returns 500 even after a 20s wait for the spend log to be written. Same write-then-read race against the spend logs DB as test_spend_logs. Spend-log accuracy is covered by tests/unit/proxy/spend_tracking/ and the proxy_spend_accuracy_tests CircleCI job."
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_spend_logs_with_org_id():
|
||||
|
|
|
|||
|
|
@ -3,11 +3,15 @@
|
|||
import asyncio
|
||||
import copy
|
||||
import inspect
|
||||
import os
|
||||
import tempfile
|
||||
import warnings
|
||||
from collections.abc import Iterator
|
||||
from typing import Dict
|
||||
from typing import Dict, Optional
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from fastapi.testclient import TestClient
|
||||
from prisma.errors import ClientNotConnectedError
|
||||
|
||||
|
||||
|
|
@ -245,3 +249,168 @@ def _reset_graceful_shutdown_state():
|
|||
GracefulShutdownManager.reset()
|
||||
yield
|
||||
GracefulShutdownManager.reset()
|
||||
|
||||
|
||||
def build_cache_config(enable_cache: bool = True) -> Optional[Dict]:
|
||||
"""
|
||||
Build Redis cache configuration from environment variables.
|
||||
|
||||
Args:
|
||||
enable_cache: Whether to enable cache (default: True)
|
||||
|
||||
Returns:
|
||||
dict: Cache configuration dict with 'cache' and 'cache_params' keys, or None
|
||||
"""
|
||||
if not enable_cache:
|
||||
return None
|
||||
|
||||
redis_host = os.getenv("REDIS_HOST")
|
||||
if not redis_host:
|
||||
return None
|
||||
|
||||
redis_port = os.getenv("REDIS_PORT", "6379")
|
||||
cache_params = {
|
||||
"type": "redis",
|
||||
"host": redis_host,
|
||||
"port": int(redis_port) if redis_port.isdigit() else redis_port,
|
||||
}
|
||||
|
||||
redis_password = os.getenv("REDIS_PASSWORD")
|
||||
if redis_password:
|
||||
cache_params["password"] = redis_password
|
||||
|
||||
return {"cache": True, "cache_params": cache_params}
|
||||
|
||||
|
||||
def build_minimal_proxy_config(
|
||||
database_url: Optional[str] = None, **init_options
|
||||
) -> Dict:
|
||||
"""
|
||||
Build a minimal proxy configuration YAML.
|
||||
|
||||
Args:
|
||||
database_url: Optional database URL (falls back to DATABASE_URL env var)
|
||||
**init_options: Additional configuration options:
|
||||
- master_key: API key for authentication (default: "sk-1234")
|
||||
- enable_cache: Whether to enable Redis cache (default: True)
|
||||
- success_callback: Callback function for success events
|
||||
|
||||
Returns:
|
||||
dict: Configuration dictionary ready to be written as YAML
|
||||
"""
|
||||
config = {
|
||||
"general_settings": {"master_key": init_options.get("master_key", "sk-1234")},
|
||||
"litellm_settings": {},
|
||||
}
|
||||
|
||||
db_url = database_url or os.getenv("DATABASE_URL")
|
||||
if db_url:
|
||||
config["general_settings"]["database_url"] = db_url
|
||||
|
||||
enable_cache = init_options.get("enable_cache", True)
|
||||
cache_config = build_cache_config(enable_cache=enable_cache)
|
||||
if cache_config:
|
||||
config["litellm_settings"].update(cache_config)
|
||||
|
||||
if init_options.get("success_callback") is not None:
|
||||
config["litellm_settings"]["success_callback"] = init_options[
|
||||
"success_callback"
|
||||
]
|
||||
|
||||
excluded_keys = {
|
||||
"master_key",
|
||||
"debug",
|
||||
"success_callback",
|
||||
"database_url",
|
||||
"enable_cache",
|
||||
}
|
||||
for key, value in init_options.items():
|
||||
if key not in excluded_keys and key not in config["litellm_settings"]:
|
||||
config["litellm_settings"][key] = value
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def set_proxy_environment_variables(
|
||||
monkeypatch, database_url: Optional[str] = None
|
||||
) -> None:
|
||||
"""
|
||||
Set environment variables for database and Redis.
|
||||
|
||||
Args:
|
||||
monkeypatch: pytest monkeypatch fixture
|
||||
database_url: Optional database URL (falls back to DATABASE_URL env var)
|
||||
"""
|
||||
db_url = database_url or os.getenv("DATABASE_URL")
|
||||
if db_url:
|
||||
monkeypatch.setenv("DATABASE_URL", db_url)
|
||||
|
||||
redis_host = os.getenv("REDIS_HOST")
|
||||
if redis_host:
|
||||
monkeypatch.setenv("REDIS_HOST", redis_host)
|
||||
monkeypatch.setenv("REDIS_PORT", os.getenv("REDIS_PORT", "6379"))
|
||||
redis_password = os.getenv("REDIS_PASSWORD")
|
||||
if redis_password:
|
||||
monkeypatch.setenv("REDIS_PASSWORD", redis_password)
|
||||
|
||||
|
||||
def create_proxy_test_client(
|
||||
monkeypatch, database_url: Optional[str] = None, **init_options
|
||||
) -> TestClient:
|
||||
"""
|
||||
Create a proxy TestClient with optional database and Redis cache configuration.
|
||||
|
||||
Args:
|
||||
monkeypatch: pytest monkeypatch fixture
|
||||
database_url: Optional database URL (falls back to DATABASE_URL env var)
|
||||
**init_options: Additional configuration options:
|
||||
- master_key: API key for authentication (default: "sk-1234")
|
||||
- enable_cache: Whether to enable Redis cache (default: True)
|
||||
- success_callback: Callback function for success events
|
||||
- debug: Enable debug mode
|
||||
|
||||
Returns:
|
||||
TestClient: FastAPI test client for the proxy server
|
||||
"""
|
||||
from litellm.proxy.proxy_server import (
|
||||
cleanup_router_config_variables,
|
||||
initialize,
|
||||
app,
|
||||
)
|
||||
|
||||
cleanup_router_config_variables()
|
||||
|
||||
filepath = os.path.dirname(os.path.abspath(__file__))
|
||||
default_config_fp = os.path.join(
|
||||
filepath, "test_configs", "test_config_hosted_vllm_embedding.yaml"
|
||||
)
|
||||
|
||||
enable_cache = init_options.get("enable_cache", True)
|
||||
needs_redis = enable_cache and os.getenv("REDIS_HOST") is not None
|
||||
needs_db = (database_url or os.getenv("DATABASE_URL")) is not None
|
||||
|
||||
if not os.path.exists(default_config_fp) or needs_redis or needs_db:
|
||||
minimal_config = build_minimal_proxy_config(
|
||||
database_url=database_url, **init_options
|
||||
)
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
||||
yaml.dump(minimal_config, f)
|
||||
config_fp = f.name
|
||||
else:
|
||||
config_fp = default_config_fp
|
||||
|
||||
set_proxy_environment_variables(monkeypatch, database_url=database_url)
|
||||
monkeypatch.setenv("LITELLM_DANGEROUSLY_PERMIT_WEAK_OR_UNSET_MASTER_KEY", "true")
|
||||
|
||||
asyncio.run(initialize(config=config_fp, debug=init_options.get("debug", False)))
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fresh_agent_read_through(monkeypatch):
|
||||
from litellm.proxy.common_utils import registry_read_through
|
||||
|
||||
read_through = registry_read_through.RegistryReadThrough(resync=registry_read_through._resync_agents)
|
||||
monkeypatch.setattr(registry_read_through, "agent_registry_read_through", read_through)
|
||||
return read_through
|
||||
|
|
|
|||
0
tests/unit/proxy/experimental/__init__.py
Normal file
0
tests/unit/proxy/experimental/__init__.py
Normal file
0
tests/unit/proxy/experimental/mcp_server/__init__.py
Normal file
0
tests/unit/proxy/experimental/mcp_server/__init__.py
Normal file
|
|
@ -59,7 +59,7 @@ def test_load_tools_from_config():
|
|||
"name": "config_tool",
|
||||
"description": "A tool from config",
|
||||
"input_schema": {"type": "object"},
|
||||
"handler": "test_tool_registry.example_handler",
|
||||
"handler": "tests.unit.proxy.experimental.mcp_server.test_tool_registry.example_handler",
|
||||
}
|
||||
]
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ from litellm.proxy.health_endpoints._health_endpoints import (
|
|||
)
|
||||
|
||||
# Import shared proxy test helpers from conftest
|
||||
from tests.test_litellm.proxy.conftest import create_proxy_test_client
|
||||
from tests.unit.proxy.conftest import create_proxy_test_client
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
0
tests/unit/proxy/logging_endpoints/__init__.py
Normal file
0
tests/unit/proxy/logging_endpoints/__init__.py
Normal file
0
tests/unit/proxy/pass_through_endpoints/__init__.py
Normal file
0
tests/unit/proxy/pass_through_endpoints/__init__.py
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue