Files
syndarix/mcp-servers/llm-gateway/tests/test_config.py
Felipe Cardoso 6e8b0b022a feat(llm-gateway): implement LLM Gateway MCP Server (#56)
Implements complete LLM Gateway MCP Server with:
- FastMCP server with 4 tools: chat_completion, list_models, get_usage, count_tokens
- LiteLLM Router with multi-provider failover chains
- Circuit breaker pattern for fault tolerance
- Redis-based cost tracking per project/agent
- Comprehensive test suite (209 tests, 92% coverage)

Model groups defined per ADR-004:
- reasoning: claude-opus-4 → gpt-4.1 → gemini-2.5-pro
- code: claude-sonnet-4 → gpt-4.1 → deepseek-coder
- fast: claude-haiku → gpt-4.1-mini → gemini-2.0-flash

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 20:31:19 +01:00

201 lines
6.6 KiB
Python

"""
Tests for config module.
"""
import os
from unittest.mock import patch
import pytest
from config import Settings, get_settings
class TestSettings:
"""Tests for Settings class."""
def test_default_values(self) -> None:
"""Test default configuration values."""
settings = Settings()
assert settings.host == "0.0.0.0"
assert settings.port == 8001
assert settings.debug is False
assert settings.redis_url == "redis://localhost:6379/0"
assert settings.litellm_timeout == 120
assert settings.circuit_failure_threshold == 5
def test_custom_values(self) -> None:
"""Test custom configuration values."""
settings = Settings(
host="127.0.0.1",
port=9000,
debug=True,
redis_url="redis://custom:6380/1",
litellm_timeout=60,
)
assert settings.host == "127.0.0.1"
assert settings.port == 9000
assert settings.debug is True
assert settings.redis_url == "redis://custom:6380/1"
assert settings.litellm_timeout == 60
def test_port_validation_valid(self) -> None:
"""Test valid port numbers."""
settings = Settings(port=1)
assert settings.port == 1
settings = Settings(port=65535)
assert settings.port == 65535
settings = Settings(port=8080)
assert settings.port == 8080
def test_port_validation_invalid(self) -> None:
"""Test invalid port numbers."""
with pytest.raises(ValueError, match="Port must be between"):
Settings(port=0)
with pytest.raises(ValueError, match="Port must be between"):
Settings(port=65536)
with pytest.raises(ValueError, match="Port must be between"):
Settings(port=-1)
def test_ttl_validation_valid(self) -> None:
"""Test valid TTL values."""
settings = Settings(redis_ttl_hours=1)
assert settings.redis_ttl_hours == 1
settings = Settings(redis_ttl_hours=168) # 1 week
assert settings.redis_ttl_hours == 168
def test_ttl_validation_invalid(self) -> None:
"""Test invalid TTL values."""
with pytest.raises(ValueError, match="Redis TTL must be positive"):
Settings(redis_ttl_hours=0)
with pytest.raises(ValueError, match="Redis TTL must be positive"):
Settings(redis_ttl_hours=-1)
def test_failure_threshold_validation(self) -> None:
"""Test circuit failure threshold validation."""
settings = Settings(circuit_failure_threshold=1)
assert settings.circuit_failure_threshold == 1
settings = Settings(circuit_failure_threshold=100)
assert settings.circuit_failure_threshold == 100
with pytest.raises(ValueError, match="Failure threshold must be between"):
Settings(circuit_failure_threshold=0)
with pytest.raises(ValueError, match="Failure threshold must be between"):
Settings(circuit_failure_threshold=101)
def test_timeout_validation(self) -> None:
"""Test timeout validation."""
settings = Settings(litellm_timeout=1)
assert settings.litellm_timeout == 1
settings = Settings(litellm_timeout=600)
assert settings.litellm_timeout == 600
with pytest.raises(ValueError, match="Timeout must be between"):
Settings(litellm_timeout=0)
with pytest.raises(ValueError, match="Timeout must be between"):
Settings(litellm_timeout=601)
def test_get_available_providers_none(self) -> None:
"""Test getting available providers with none configured."""
settings = Settings()
providers = settings.get_available_providers()
assert providers == []
def test_get_available_providers_some(self) -> None:
"""Test getting available providers with some configured."""
settings = Settings(
anthropic_api_key="test-key",
openai_api_key="test-key",
)
providers = settings.get_available_providers()
assert "anthropic" in providers
assert "openai" in providers
assert "google" not in providers
assert len(providers) == 2
def test_get_available_providers_all(self) -> None:
"""Test getting available providers with all configured."""
settings = Settings(
anthropic_api_key="test-key",
openai_api_key="test-key",
google_api_key="test-key",
alibaba_api_key="test-key",
deepseek_api_key="test-key",
)
providers = settings.get_available_providers()
assert len(providers) == 5
assert "anthropic" in providers
assert "openai" in providers
assert "google" in providers
assert "alibaba" in providers
assert "deepseek" in providers
def test_has_any_provider_false(self) -> None:
"""Test has_any_provider when none configured."""
settings = Settings()
assert settings.has_any_provider() is False
def test_has_any_provider_true(self) -> None:
"""Test has_any_provider when at least one configured."""
settings = Settings(anthropic_api_key="test-key")
assert settings.has_any_provider() is True
def test_deepseek_base_url_counts_as_provider(self) -> None:
"""Test that DeepSeek base URL alone counts as provider."""
settings = Settings(deepseek_base_url="http://localhost:8000")
providers = settings.get_available_providers()
assert "deepseek" in providers
class TestGetSettings:
"""Tests for get_settings function."""
def test_get_settings_returns_settings(self) -> None:
"""Test that get_settings returns a Settings instance."""
# Clear the cache first
get_settings.cache_clear()
settings = get_settings()
assert isinstance(settings, Settings)
def test_get_settings_is_cached(self) -> None:
"""Test that get_settings returns cached instance."""
get_settings.cache_clear()
settings1 = get_settings()
settings2 = get_settings()
assert settings1 is settings2
def test_env_var_override(self) -> None:
"""Test that environment variables override defaults."""
get_settings.cache_clear()
with patch.dict(
os.environ,
{
"LLM_GATEWAY_HOST": "192.168.1.1",
"LLM_GATEWAY_PORT": "9999",
"LLM_GATEWAY_DEBUG": "true",
},
):
get_settings.cache_clear()
settings = get_settings()
assert settings.host == "192.168.1.1"
assert settings.port == 9999
assert settings.debug is True