""" 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