core / tests /test_config.py
tensorus's picture
Upload 83 files
edfa748 verified
import pytest
import os
from typing import List
from tensorus.config import SettingsV1, settings as global_settings
from tensorus.metadata import get_configured_storage_instance, InMemoryStorage, PostgresMetadataStorage, ConfigurationError
from tensorus.metadata.storage_abc import MetadataStorage
# --- Test SettingsV1 Loading ---
def test_settings_default_values():
# Test without any env vars set (relies on defaults in SettingsV1)
# This test is tricky because settings are loaded globally at import time.
# We need to ensure a clean environment or test specific fields not typically overridden by CI.
# For now, let's assume a default state or test fields that are less likely to be in CI env.
s = SettingsV1() # Creates a new instance, re-evaluating defaults if env vars are not set for these specific fields
assert s.STORAGE_BACKEND == "in_memory" # Default
assert s.API_KEY_HEADER_NAME == "X-API-KEY" # Default
assert s.VALID_API_KEYS == [] # Default (before manual parsing from env)
assert s.POSTGRES_PORT == 5432 # Default
def test_settings_from_env(monkeypatch):
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "postgres_test")
monkeypatch.setenv("TENSORUS_API_KEY_HEADER_NAME", "X-CUSTOM-API-KEY")
monkeypatch.setenv("TENSORUS_VALID_API_KEYS", '["key_env1", "key_env2"]')
monkeypatch.setenv("TENSORUS_POSTGRES_HOST", "testhost")
monkeypatch.setenv("TENSORUS_POSTGRES_PORT", "1234")
# Create a new SettingsV1 instance to load these monkeypatched env vars
# Pydantic v1 BaseSettings loads from env at initialization.
s = SettingsV1()
assert s.STORAGE_BACKEND == "postgres_test"
assert s.API_KEY_HEADER_NAME == "X-CUSTOM-API-KEY"
assert s.VALID_API_KEYS == ["key_env1", "key_env2"]
assert s.POSTGRES_HOST == "testhost"
assert s.POSTGRES_PORT == 1234
def test_valid_api_keys_parsing_empty_env(monkeypatch):
# Ensure if TENSORUS_VALID_API_KEYS is not set, it defaults to empty list
monkeypatch.delenv("TENSORUS_VALID_API_KEYS", raising=False)
# global_settings is already loaded. We need to simulate its re-initialization or check its state.
# The manual parsing block in config.py affects the global `settings` instance.
# To test this properly, we might need to re-run that logic or use a new settings instance.
# Create a new instance to test its initialization behavior
s = SettingsV1()
assert s.VALID_API_KEYS == []
def test_valid_api_keys_json_list_in_env(monkeypatch):
monkeypatch.setenv("TENSORUS_VALID_API_KEYS", '["json_key1", "json_key2"]')
s = SettingsV1()
assert s.VALID_API_KEYS == ["json_key1", "json_key2"]
# --- Test Dynamic Storage Instantiation ---
@pytest.fixture(autouse=True)
def reset_global_settings_after_test(monkeypatch):
""" Ensures each test involving settings gets a fresh state relative to env vars,
and attempts to reset global settings to avoid test interference.
This is complex due to Python's import-time evaluation.
"""
original_env = os.environ.copy()
# Store original values of global_settings that might be changed by manual parsing in config.py
original_valid_keys = global_settings.VALID_API_KEYS
yield
os.environ.clear()
os.environ.update(original_env)
# Attempt to restore global_settings to a semblance of its original state
# This is hard because `settings = SettingsV1()` in config.py runs only once.
# A better way would be a settings fixture that provides a fresh SettingsV1 instance.
global_settings.VALID_API_KEYS = original_valid_keys
# Update the global settings list to reflect the restored environment
raw_keys = os.getenv("TENSORUS_VALID_API_KEYS")
if raw_keys:
global_settings.VALID_API_KEYS = [key.strip() for key in raw_keys.split(',')]
else:
global_settings.VALID_API_KEYS = []
def test_get_in_memory_storage_by_default(monkeypatch):
monkeypatch.delenv("TENSORUS_STORAGE_BACKEND", raising=False)
# Temporarily modify global_settings for this test's scope
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "in_memory")
storage = get_configured_storage_instance()
assert isinstance(storage, InMemoryStorage)
def test_get_in_memory_storage_explicitly(monkeypatch):
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "in_memory")
# Update global_settings to reflect the monkeypatched env var for this test
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "in_memory")
storage = get_configured_storage_instance()
assert isinstance(storage, InMemoryStorage)
def test_get_postgres_storage_with_dsn(monkeypatch):
dsn = "postgresql://testuser:testpass@testhost:5432/testdb"
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "postgres")
monkeypatch.setenv("TENSORUS_POSTGRES_DSN", dsn)
# Update global_settings
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "postgres")
monkeypatch.setattr(global_settings, 'POSTGRES_DSN', dsn)
monkeypatch.setattr(global_settings, 'POSTGRES_HOST', None) # Ensure DSN is chosen
# Mock psycopg2.pool.SimpleConnectionPool to avoid actual connection
class MockPool:
def __init__(self, minconn, maxconn, dsn):
assert dsn == "postgresql://testuser:testpass@testhost:5432/testdb"
def getconn(self): pass
def putconn(self, conn): pass
def closeall(self): pass
monkeypatch.setattr("psycopg2.pool.SimpleConnectionPool", MockPool)
storage = get_configured_storage_instance()
assert isinstance(storage, PostgresMetadataStorage)
assert storage.dsn == dsn
def test_get_postgres_storage_with_params(monkeypatch):
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "postgres")
monkeypatch.setenv("TENSORUS_POSTGRES_HOST", "localhost")
monkeypatch.setenv("TENSORUS_POSTGRES_USER", "tensorus_user")
monkeypatch.setenv("TENSORUS_POSTGRES_DB", "tensorus_db")
monkeypatch.setenv("TENSORUS_POSTGRES_PASSWORD", "securepassword") # Optional but good to test
monkeypatch.setenv("TENSORUS_POSTGRES_PORT", "5433")
# Update global_settings
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "postgres")
monkeypatch.setattr(global_settings, 'POSTGRES_HOST', "localhost")
monkeypatch.setattr(global_settings, 'POSTGRES_USER', "tensorus_user")
monkeypatch.setattr(global_settings, 'POSTGRES_DB', "tensorus_db")
monkeypatch.setattr(global_settings, 'POSTGRES_PASSWORD', "securepassword")
monkeypatch.setattr(global_settings, 'POSTGRES_PORT', 5433)
monkeypatch.setattr(global_settings, 'POSTGRES_DSN', None) # Ensure params are chosen
class MockPoolKwargs:
def __init__(self, minconn, maxconn, host, port, user, password, database):
assert host == "localhost"
assert port == 5433
assert user == "tensorus_user"
assert password == "securepassword"
assert database == "tensorus_db"
def getconn(self): pass
def putconn(self, conn): pass
def closeall(self): pass
monkeypatch.setattr("psycopg2.pool.SimpleConnectionPool", MockPoolKwargs)
storage = get_configured_storage_instance()
assert isinstance(storage, PostgresMetadataStorage)
def test_postgres_storage_missing_config_dsn_and_params(monkeypatch):
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "postgres")
# Ensure all relevant PG env vars are unset or None in global_settings
monkeypatch.delenv("TENSORUS_POSTGRES_DSN", raising=False)
monkeypatch.delenv("TENSORUS_POSTGRES_HOST", raising=False)
monkeypatch.delenv("TENSORUS_POSTGRES_USER", raising=False)
monkeypatch.delenv("TENSORUS_POSTGRES_DB", raising=False)
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "postgres")
monkeypatch.setattr(global_settings, 'POSTGRES_DSN', None)
monkeypatch.setattr(global_settings, 'POSTGRES_HOST', None)
monkeypatch.setattr(global_settings, 'POSTGRES_USER', None)
monkeypatch.setattr(global_settings, 'POSTGRES_DB', None)
with pytest.raises(ConfigurationError, match="PostgreSQL backend selected, but required connection details"):
get_configured_storage_instance()
def test_postgres_storage_missing_some_params(monkeypatch):
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "postgres")
monkeypatch.setenv("TENSORUS_POSTGRES_HOST", "localhost") # User and DB missing
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "postgres")
monkeypatch.setattr(global_settings, 'POSTGRES_HOST', "localhost")
monkeypatch.setattr(global_settings, 'POSTGRES_USER', None)
monkeypatch.setattr(global_settings, 'POSTGRES_DB', None)
monkeypatch.setattr(global_settings, 'POSTGRES_DSN', None)
with pytest.raises(ConfigurationError, match="PostgreSQL backend selected, but required connection details"):
get_configured_storage_instance()
def test_unsupported_storage_backend(monkeypatch):
monkeypatch.setenv("TENSORUS_STORAGE_BACKEND", "mongodb")
monkeypatch.setattr(global_settings, 'STORAGE_BACKEND', "mongodb")
with pytest.raises(ConfigurationError, match="Unsupported storage backend: mongodb"):
get_configured_storage_instance()
# Note: psycopg2 is not actually imported or used if mocked correctly.
# These tests verify the configuration logic that *would* pass params to psycopg2.