Files
derp/tests/test_config.py
user 668d7f89b8 test: add channel filter and JSON log tests
TestChannelFilter: allowed/denied/PM/no-config/core-exempt/ampersand.
TestChannelConfig: TOML loading, defaults. TestJsonFormatter: fields,
exception, unicode, single-line, timestamp format.
2026-02-15 04:16:49 +01:00

113 lines
3.7 KiB
Python

"""Tests for configuration loading and merging."""
import copy
from pathlib import Path
import pytest
from derp.config import DEFAULTS, _merge, load, resolve_config
class TestMerge:
"""Test deep merge logic."""
def test_flat_override(self):
base = {"a": 1, "b": 2}
result = _merge(base, {"b": 99})
assert result == {"a": 1, "b": 99}
def test_nested_merge(self):
base = {"server": {"host": "a", "port": 1}}
result = _merge(base, {"server": {"port": 2}})
assert result == {"server": {"host": "a", "port": 2}}
def test_list_replacement(self):
base = {"channels": ["#old"]}
result = _merge(base, {"channels": ["#new"]})
assert result == {"channels": ["#new"]}
def test_empty_override(self):
base = {"a": 1, "b": 2}
result = _merge(base, {})
assert result == {"a": 1, "b": 2}
def test_new_keys(self):
base = {"a": 1}
result = _merge(base, {"b": 2})
assert result == {"a": 1, "b": 2}
def test_base_not_mutated(self):
base = {"server": {"host": "original"}}
original = copy.deepcopy(base)
_merge(base, {"server": {"host": "changed"}})
assert base == original
class TestLoad:
"""Test TOML file loading."""
def test_minimal_toml(self, tmp_path: Path):
config_file = tmp_path / "test.toml"
config_file.write_text('[server]\nnick = "testbot"\n')
result = load(config_file)
# Overridden value
assert result["server"]["nick"] == "testbot"
# Default preserved
assert result["server"]["host"] == "irc.libera.chat"
assert result["server"]["port"] == 6697
def test_full_override(self, tmp_path: Path):
config_file = tmp_path / "test.toml"
config_file.write_text(
'[server]\nhost = "custom.irc"\nport = 6667\n'
'[bot]\nprefix = "."\n'
)
result = load(config_file)
assert result["server"]["host"] == "custom.irc"
assert result["server"]["port"] == 6667
assert result["bot"]["prefix"] == "."
# Unset defaults still present
assert result["bot"]["channels"] == ["#test"]
class TestChannelConfig:
"""Test channel-level configuration merging."""
def test_channel_config_loaded(self, tmp_path: Path):
config_file = tmp_path / "test.toml"
config_file.write_text(
'[channels."#ops"]\nplugins = ["core", "dns"]\n'
)
result = load(config_file)
assert "#ops" in result["channels"]
assert result["channels"]["#ops"]["plugins"] == ["core", "dns"]
def test_default_channels_empty(self):
assert DEFAULTS["channels"] == {}
def test_default_logging_format(self):
assert DEFAULTS["logging"]["format"] == "text"
class TestResolveConfig:
"""Test config path resolution and fallback."""
def test_explicit_path(self, tmp_path: Path):
config_file = tmp_path / "explicit.toml"
config_file.write_text('[server]\nnick = "explicit"\n')
result = resolve_config(str(config_file))
assert result["server"]["nick"] == "explicit"
def test_no_file_fallback(self, tmp_path: Path, monkeypatch: "pytest.MonkeyPatch"):
# Run from tmp_path so config/derp.toml isn't found
monkeypatch.chdir(tmp_path)
result = resolve_config(str(tmp_path / "nonexistent.toml"))
# Should fall back to DEFAULTS
assert result["server"]["host"] == DEFAULTS["server"]["host"]
assert result["bot"]["prefix"] == DEFAULTS["bot"]["prefix"]
def test_defaults_not_mutated(self):
original = copy.deepcopy(DEFAULTS)
resolve_config(None)
assert DEFAULTS == original