import json import os import sys import pytest from fastapi import HTTPException from litellm.caching.caching import DualCache from litellm.proxy._types import ProxyErrorTypes from litellm.proxy.utils import ProxyLogging sys.path.insert( 0, os.path.abspath("../../..") ) # Adds the parent directory to the system path from unittest.mock import MagicMock from litellm.proxy.utils import get_custom_url, join_paths def test_get_custom_url(monkeypatch): monkeypatch.setenv("SERVER_ROOT_PATH", "/litellm") custom_url = get_custom_url(request_base_url="http://0.0.0.0:4000", route="ui/") assert custom_url == "http://0.0.0.0:4000/litellm/ui/" def test_proxy_only_error_true_for_llm_route(): proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) assert proxy_logging_obj._is_proxy_only_llm_api_error( original_exception=Exception(), error_type=ProxyErrorTypes.auth_error, route="/v1/chat/completions", ) def test_proxy_only_error_false_for_non_llm_route(): proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) assert ( proxy_logging_obj._is_proxy_only_llm_api_error( original_exception=Exception(), error_type=ProxyErrorTypes.auth_error, route="/key/info", ) is False ) def test_proxy_only_error_false_for_other_error_type(): proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache()) assert ( proxy_logging_obj._is_proxy_only_llm_api_error( original_exception=Exception(), error_type=None, route="/v1/chat/completions", ) is False ) def test_get_model_group_info_order(): from litellm import Router from litellm.proxy.proxy_server import _get_model_group_info router = Router( model_list=[ { "model_name": "openai/tts-1", "litellm_params": { "model": "openai/tts-1", "api_key": "sk-1234", }, }, { "model_name": "openai/gpt-3.5-turbo", "litellm_params": { "model": "openai/gpt-3.5-turbo", "api_key": "sk-1234", }, }, ] ) model_list = _get_model_group_info( llm_router=router, all_models_str=["openai/tts-1", "openai/gpt-3.5-turbo"], model_group=None, ) model_groups = [m.model_group for m in model_list] assert model_groups == ["openai/tts-1", "openai/gpt-3.5-turbo"] def test_join_paths_no_duplication(): """Test that join_paths doesn't duplicate route when base_path already ends with it""" result = join_paths( base_path="http://0.0.0.0:4000/my-custom-path/", route="/my-custom-path" ) assert result == "http://0.0.0.0:4000/my-custom-path" def test_join_paths_normal_join(): """Test normal path joining""" result = join_paths(base_path="http://0.0.0.0:4000", route="/api/v1") assert result == "http://0.0.0.0:4000/api/v1" def test_join_paths_with_trailing_slash(): """Test path joining with trailing slash on base_path""" result = join_paths(base_path="http://0.0.0.0:4000/", route="api/v1") assert result == "http://0.0.0.0:4000/api/v1" def test_join_paths_empty_base(): """Test path joining with empty base_path""" result = join_paths(base_path="", route="api/v1") assert result == "/api/v1" def test_join_paths_empty_route(): """Test path joining with empty route""" result = join_paths(base_path="http://0.0.0.0:4000", route="") assert result == "http://0.0.0.0:4000" def test_join_paths_both_empty(): """Test path joining with both empty""" result = join_paths(base_path="", route="") assert result == "/" def test_join_paths_nested_path(): """Test path joining with nested paths""" result = join_paths(base_path="http://0.0.0.0:4000/v1", route="chat/completions") assert result == "http://0.0.0.0:4000/v1/chat/completions"