All 13 environment variables from the spec defined with proper defaults. SQLite fallback when DATABASE_URL is unset, in-process queue flag when REDIS_URL is unset, JWT_SECRET auto-generation, empty API_KEY normalization. 13 unit tests covering all configuration paths.
105 lines
3.6 KiB
Python
105 lines
3.6 KiB
Python
"""Tests for backend/config.py."""
|
|
|
|
import os
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from pydantic_settings import BaseSettings
|
|
|
|
from config import Settings
|
|
|
|
|
|
class TestSettings:
|
|
"""Test the Settings configuration class."""
|
|
|
|
def _make_settings(self, **env_vars: str) -> Settings:
|
|
"""Create a Settings instance with specific env vars, ignoring .env file."""
|
|
with patch.dict(os.environ, env_vars, clear=False):
|
|
return Settings(_env_file=None)
|
|
|
|
def test_defaults(self) -> None:
|
|
s = self._make_settings()
|
|
assert s.database_url is None
|
|
assert s.redis_url is None
|
|
assert s.host == "0.0.0.0"
|
|
assert s.port == 8400
|
|
assert s.api_key is None
|
|
assert s.default_endpoint_url is None
|
|
assert s.default_endpoint_key is None
|
|
assert s.max_concurrent_runs == 4
|
|
assert s.max_tokens_per_sweep == 0
|
|
assert s.data_dir == "/data"
|
|
assert s.mcp_enabled is True
|
|
assert s.mcp_port == 8401
|
|
|
|
def test_jwt_secret_auto_generated(self) -> None:
|
|
s = self._make_settings()
|
|
assert len(s.jwt_secret) > 0
|
|
|
|
def test_jwt_secret_auto_generated_unique(self) -> None:
|
|
s1 = self._make_settings()
|
|
s2 = self._make_settings()
|
|
assert s1.jwt_secret != s2.jwt_secret
|
|
|
|
def test_jwt_secret_from_env(self) -> None:
|
|
s = self._make_settings(JWT_SECRET="my-secret-key")
|
|
assert s.jwt_secret == "my-secret-key"
|
|
|
|
def test_sqlite_fallback_when_no_database_url(self) -> None:
|
|
s = self._make_settings(DATA_DIR="/tmp/test")
|
|
url = s.effective_database_url
|
|
assert url.startswith("sqlite:///")
|
|
assert url.endswith("promptlooper.db")
|
|
assert "tmp" in url and "test" in url
|
|
assert s.is_sqlite is True
|
|
|
|
def test_postgres_when_database_url_set(self) -> None:
|
|
url = "postgresql://user:pass@localhost:5432/promptlooper"
|
|
s = self._make_settings(DATABASE_URL=url)
|
|
assert s.effective_database_url == url
|
|
assert s.is_sqlite is False
|
|
|
|
def test_in_process_queue_when_no_redis(self) -> None:
|
|
s = self._make_settings()
|
|
assert s.use_in_process_queue is True
|
|
|
|
def test_celery_queue_when_redis_set(self) -> None:
|
|
s = self._make_settings(REDIS_URL="redis://localhost:6379/0")
|
|
assert s.use_in_process_queue is False
|
|
assert s.redis_url == "redis://localhost:6379/0"
|
|
|
|
def test_empty_api_key_becomes_none(self) -> None:
|
|
s = self._make_settings(API_KEY="")
|
|
assert s.api_key is None
|
|
|
|
def test_whitespace_api_key_becomes_none(self) -> None:
|
|
s = self._make_settings(API_KEY=" ")
|
|
assert s.api_key is None
|
|
|
|
def test_valid_api_key_preserved(self) -> None:
|
|
s = self._make_settings(API_KEY="sk-test-123")
|
|
assert s.api_key == "sk-test-123"
|
|
|
|
def test_env_overrides(self) -> None:
|
|
s = self._make_settings(
|
|
HOST="127.0.0.1",
|
|
PORT="9000",
|
|
MAX_CONCURRENT_RUNS="8",
|
|
MAX_TOKENS_PER_SWEEP="100000",
|
|
MCP_ENABLED="false",
|
|
MCP_PORT="9001",
|
|
)
|
|
assert s.host == "127.0.0.1"
|
|
assert s.port == 9000
|
|
assert s.max_concurrent_runs == 8
|
|
assert s.max_tokens_per_sweep == 100000
|
|
assert s.mcp_enabled is False
|
|
assert s.mcp_port == 9001
|
|
|
|
def test_default_endpoint_config(self) -> None:
|
|
s = self._make_settings(
|
|
DEFAULT_ENDPOINT_URL="http://localhost:11434/v1",
|
|
DEFAULT_ENDPOINT_KEY="sk-key",
|
|
)
|
|
assert s.default_endpoint_url == "http://localhost:11434/v1"
|
|
assert s.default_endpoint_key == "sk-key"
|