Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

347 lines
12 KiB
Python

"""High-value tests for settings/env_definitions/db_config.py.
Tests the DB_CONFIG_SETTINGS list: IntegerSetting and EnumSetting instances,
their defaults, boundaries, env-var resolution, deprecated aliases, and
validation of invalid values.
"""
import pytest
from local_deep_research.settings.env_definitions.db_config import (
DB_CONFIG_SETTINGS,
)
from local_deep_research.settings.env_settings import (
IntegerSetting,
EnumSetting,
SettingsRegistry,
)
def _find(key: str):
"""Return the setting object with the given key."""
for s in DB_CONFIG_SETTINGS:
if s.key == key:
return s
raise KeyError(f"Setting {key!r} not found in DB_CONFIG_SETTINGS")
class TestDbConfigRegistry:
"""Tests for registering DB_CONFIG_SETTINGS in a SettingsRegistry."""
def test_register_all_settings(self):
"""All settings can be registered under the db_config category."""
registry = SettingsRegistry()
registry.register_category("db_config", DB_CONFIG_SETTINGS)
for s in DB_CONFIG_SETTINGS:
assert registry.is_env_only(s.key)
def test_setting_count(self):
"""DB_CONFIG_SETTINGS contains the expected number of settings."""
assert len(DB_CONFIG_SETTINGS) == 9
def test_all_keys_start_with_db_config(self):
"""Every key should use the 'db_config.' prefix."""
for s in DB_CONFIG_SETTINGS:
assert s.key.startswith("db_config."), f"{s.key} missing prefix"
class TestEnvVarNaming:
"""Verify that the auto-generated env_var matches the canonical form."""
@pytest.mark.parametrize(
"key, expected_env_var",
[
("db_config.cache_size_mb", "LDR_DB_CONFIG_CACHE_SIZE_MB"),
("db_config.journal_mode", "LDR_DB_CONFIG_JOURNAL_MODE"),
("db_config.synchronous", "LDR_DB_CONFIG_SYNCHRONOUS"),
(
"db_config.wal_autocheckpoint",
"LDR_DB_CONFIG_WAL_AUTOCHECKPOINT",
),
("db_config.page_size", "LDR_DB_CONFIG_PAGE_SIZE"),
("db_config.kdf_iterations", "LDR_DB_CONFIG_KDF_ITERATIONS"),
("db_config.kdf_algorithm", "LDR_DB_CONFIG_KDF_ALGORITHM"),
("db_config.hmac_algorithm", "LDR_DB_CONFIG_HMAC_ALGORITHM"),
(
"db_config.cipher_memory_security",
"LDR_DB_CONFIG_CIPHER_MEMORY_SECURITY",
),
],
)
def test_canonical_env_var(self, key, expected_env_var):
s = _find(key)
assert s.env_var == expected_env_var
class TestDeprecatedEnvVars:
"""Settings that have a deprecated alias should resolve via it."""
@pytest.mark.parametrize(
"key, deprecated_var",
[
("db_config.cache_size_mb", "LDR_DB_CACHE_SIZE_MB"),
("db_config.journal_mode", "LDR_DB_JOURNAL_MODE"),
("db_config.synchronous", "LDR_DB_SYNCHRONOUS"),
("db_config.page_size", "LDR_DB_PAGE_SIZE"),
("db_config.kdf_iterations", "LDR_DB_KDF_ITERATIONS"),
("db_config.kdf_algorithm", "LDR_DB_KDF_ALGORITHM"),
("db_config.hmac_algorithm", "LDR_DB_HMAC_ALGORITHM"),
],
)
def test_deprecated_alias_stored(self, key, deprecated_var):
"""The deprecated_env_var attribute matches expectations."""
s = _find(key)
assert s.deprecated_env_var == deprecated_var
def test_cipher_memory_security_has_no_deprecated_alias(self):
s = _find("db_config.cipher_memory_security")
assert s.deprecated_env_var is None
def test_deprecated_alias_fallback_returns_value(self, monkeypatch):
"""When only the deprecated alias is set, the value should be resolved."""
s = _find("db_config.cache_size_mb")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.setenv(s.deprecated_env_var, "128")
assert s.get_value() == 128
def test_canonical_takes_precedence_over_deprecated(self, monkeypatch):
"""When both canonical and deprecated vars are set, canonical wins."""
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "32")
monkeypatch.setenv(s.deprecated_env_var, "999")
assert s.get_value() == 32
class TestCacheSizeMb:
"""Tests for db_config.cache_size_mb."""
def test_type(self):
assert isinstance(_find("db_config.cache_size_mb"), IntegerSetting)
def test_default_value(self, monkeypatch):
s = _find("db_config.cache_size_mb")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.delenv(s.deprecated_env_var, raising=False)
assert s.get_value() == 64
def test_valid_value(self, monkeypatch):
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "256")
assert s.get_value() == 256
def test_min_boundary(self, monkeypatch):
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "1")
assert s.get_value() == 1
def test_below_min_raises(self, monkeypatch):
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "0")
with pytest.raises(ValueError, match="below minimum"):
s.get_value()
def test_max_boundary(self, monkeypatch):
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "10000")
assert s.get_value() == 10000
def test_above_max_raises(self, monkeypatch):
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "10001")
with pytest.raises(ValueError, match="above maximum"):
s.get_value()
def test_non_integer_returns_default(self, monkeypatch):
"""Non-integer strings fall back to the default value."""
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "not_a_number")
assert s.get_value() == s.default
def test_negative_value_raises(self, monkeypatch):
"""Negative values are below the minimum."""
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "-10")
with pytest.raises(ValueError, match="below minimum"):
s.get_value()
class TestPageSize:
"""Tests for db_config.page_size."""
def test_default(self, monkeypatch):
s = _find("db_config.page_size")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.delenv(s.deprecated_env_var, raising=False)
assert s.get_value() == 16384
def test_min_boundary(self, monkeypatch):
s = _find("db_config.page_size")
monkeypatch.setenv(s.env_var, "512")
assert s.get_value() == 512
def test_below_min_raises(self, monkeypatch):
s = _find("db_config.page_size")
monkeypatch.setenv(s.env_var, "256")
with pytest.raises(ValueError, match="below minimum"):
s.get_value()
def test_max_boundary(self, monkeypatch):
s = _find("db_config.page_size")
monkeypatch.setenv(s.env_var, "65536")
assert s.get_value() == 65536
def test_above_max_raises(self, monkeypatch):
s = _find("db_config.page_size")
monkeypatch.setenv(s.env_var, "65537")
with pytest.raises(ValueError, match="above maximum"):
s.get_value()
class TestJournalMode:
"""Tests for db_config.journal_mode."""
def test_type(self):
assert isinstance(_find("db_config.journal_mode"), EnumSetting)
def test_default(self, monkeypatch):
s = _find("db_config.journal_mode")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.delenv(s.deprecated_env_var, raising=False)
assert s.get_value() == "WAL"
@pytest.mark.parametrize(
"raw_input, expected",
[
("WAL", "WAL"),
("wal", "WAL"),
("DELETE", "DELETE"),
("TRUNCATE", "TRUNCATE"),
("PERSIST", "PERSIST"),
("MEMORY", "MEMORY"),
("OFF", "OFF"),
],
)
def test_valid_values_case_insensitive(
self, monkeypatch, raw_input, expected
):
s = _find("db_config.journal_mode")
monkeypatch.setenv(s.env_var, raw_input)
assert s.get_value() == expected
def test_invalid_value_raises(self, monkeypatch):
s = _find("db_config.journal_mode")
monkeypatch.setenv(s.env_var, "INVALID_MODE")
with pytest.raises(ValueError, match="not in allowed values"):
s.get_value()
class TestSynchronous:
"""Tests for db_config.synchronous."""
def test_default(self, monkeypatch):
s = _find("db_config.synchronous")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.delenv(s.deprecated_env_var, raising=False)
assert s.get_value() == "NORMAL"
@pytest.mark.parametrize("value", ["OFF", "NORMAL", "FULL", "EXTRA"])
def test_all_valid_values(self, monkeypatch, value):
s = _find("db_config.synchronous")
monkeypatch.setenv(s.env_var, value)
assert s.get_value() == value
def test_invalid_raises(self, monkeypatch):
s = _find("db_config.synchronous")
monkeypatch.setenv(s.env_var, "LAZY")
with pytest.raises(ValueError, match="not in allowed values"):
s.get_value()
class TestKdfAlgorithm:
"""Tests for db_config.kdf_algorithm."""
def test_default(self, monkeypatch):
s = _find("db_config.kdf_algorithm")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.delenv(s.deprecated_env_var, raising=False)
assert s.get_value() == "PBKDF2_HMAC_SHA512"
@pytest.mark.parametrize(
"value",
["PBKDF2_HMAC_SHA512", "PBKDF2_HMAC_SHA256", "PBKDF2_HMAC_SHA1"],
)
def test_all_valid_values(self, monkeypatch, value):
s = _find("db_config.kdf_algorithm")
monkeypatch.setenv(s.env_var, value)
assert s.get_value() == value
def test_invalid_raises(self, monkeypatch):
s = _find("db_config.kdf_algorithm")
monkeypatch.setenv(s.env_var, "SCRYPT")
with pytest.raises(ValueError, match="not in allowed values"):
s.get_value()
class TestCipherMemorySecurity:
"""Tests for db_config.cipher_memory_security."""
def test_default(self, monkeypatch):
s = _find("db_config.cipher_memory_security")
monkeypatch.delenv(s.env_var, raising=False)
assert s.get_value() == "OFF"
@pytest.mark.parametrize(
"raw_input, expected",
[("ON", "ON"), ("on", "ON"), ("OFF", "OFF"), ("off", "OFF")],
)
def test_valid_values(self, monkeypatch, raw_input, expected):
s = _find("db_config.cipher_memory_security")
monkeypatch.setenv(s.env_var, raw_input)
assert s.get_value() == expected
def test_invalid_raises(self, monkeypatch):
s = _find("db_config.cipher_memory_security")
monkeypatch.setenv(s.env_var, "YES")
with pytest.raises(ValueError, match="not in allowed values"):
s.get_value()
class TestRegistryGetIntegration:
"""Test SettingsRegistry.get() for db_config settings."""
def _make_registry(self):
r = SettingsRegistry()
r.register_category("db_config", DB_CONFIG_SETTINGS)
return r
def test_get_returns_default_when_env_not_set(self, monkeypatch):
"""When no env var is set, registry.get() returns the setting default."""
r = self._make_registry()
s = _find("db_config.cache_size_mb")
monkeypatch.delenv(s.env_var, raising=False)
monkeypatch.delenv(s.deprecated_env_var, raising=False)
assert r.get("db_config.cache_size_mb") == 64
def test_get_returns_override_default_for_unknown_key(self):
"""Unknown key returns the caller-supplied default."""
r = self._make_registry()
assert r.get("db_config.nonexistent", default=42) == 42
def test_get_returns_caller_default_on_validation_error(self, monkeypatch):
"""When the env var fails validation, get() returns the caller default."""
r = self._make_registry()
s = _find("db_config.cache_size_mb")
monkeypatch.setenv(s.env_var, "0") # below minimum
assert r.get("db_config.cache_size_mb", default=99) == 99
def test_get_env_var_for_known_key(self):
r = self._make_registry()
assert (
r.get_env_var("db_config.cache_size_mb")
== "LDR_DB_CONFIG_CACHE_SIZE_MB"
)
def test_get_env_var_for_unknown_key(self):
r = self._make_registry()
assert r.get_env_var("no.such.key") is None