Files
EDMarketConnector/tests/test_config.py
T

194 lines
5.9 KiB
Python

# flake8: noqa
# mypy: ignore-errors
"""Test the Config system."""
import sys
import tomli_w
import semantic_version
from unittest.mock import patch, MagicMock, mock_open
import config
from config import (
Config,
git_shorthash_from_head,
appversion,
appversion_nobuild,
)
class TestGitFunctions:
@patch("subprocess.run")
def test_git_shorthash_success(self, mock_run):
mock_run.side_effect = [
MagicMock(stdout="a1b2c3d\n", stderr=None), # rev-parse
MagicMock(stdout="", stderr=None), # diff (clean)
]
assert git_shorthash_from_head() == "a1b2c3d"
@patch("subprocess.run")
@patch("os.path.exists")
def test_git_shorthash_dirty(self, mock_exists, mock_run):
mock_exists.return_value = True
# Simulate the single call to git describe --dirty
mock_run.return_value = MagicMock(
stdout="a1b2c3d.DIRTY\n",
stderr="",
returncode=0
)
assert git_shorthash_from_head() == "a1b2c3d.DIRTY"
@patch("subprocess.run")
def test_git_shorthash_failure(self, mock_run):
mock_run.side_effect = FileNotFoundError("git not found")
assert git_shorthash_from_head() is None
class TestAppVersion:
def setup_method(self):
# Reset cached version before each test
config._cached_version = None
class TestConfigClass:
def test_init_creates_default_toml(self, mock_app_dir):
"""Test that initializing Config creates config.toml if missing."""
toml_file = mock_app_dir / "config.toml"
assert not toml_file.exists()
with patch("config.Config._init_platform"):
Config(mock_app_dir)
assert toml_file.exists()
assert "generated" in toml_file.read_text()
def test_load_existing_settings(self, mock_app_dir):
toml_file = mock_app_dir / "config.toml"
data = {
"settings": {
"theme": "dark",
# Need plugin_dir or __init__ will auto-add it
"plugin_dir": str(mock_app_dir / "plugins"),
}
}
with open(toml_file, "wb") as f:
tomli_w.dump(data, f)
with patch("config.Config._init_platform"):
cfg = Config(mock_app_dir)
assert cfg.get("theme") == "dark"
def test_set_saves_to_disk(self, mock_app_dir):
"""Test that set() updates memory and writes to disk."""
with patch("config.Config._init_platform"):
c = Config(mock_app_dir)
toml_path = c.toml_path
c.set("saved_value", "persistence_check")
# Read file directly to verify
with open(toml_path, "rb") as f:
import tomllib
data = tomllib.load(f)
assert data["settings"]["saved_value"] == "persistence_check"
def test_recovery_broken_toml(self, mock_app_dir):
"""Test that the system recovers from a corrupted TOML file."""
toml_path = mock_app_dir / "config.toml"
# Write garbage
with open(toml_path, "w") as f:
f.write("This is not valid TOML { [ } ]")
with patch("config.Config._init_platform"):
cfg = Config(mock_app_dir)
assert "plugin_dir" in cfg.settings
# The broken file should be renamed
broken_files = list(mock_app_dir.glob("config.toml.broken.*"))
assert len(broken_files) > 0
def test_recovery_from_backup(self, mock_app_dir):
"""Test recovering from .bak if .toml is broken."""
toml_path = mock_app_dir / "config.toml"
bak_path = mock_app_dir / "config.toml.bak"
with open(toml_path, "w") as f:
f.write("Garbage")
valid_data = {
"settings": {"recovered": True, "plugin_dir": str(mock_app_dir / "plugins")}
}
with open(bak_path, "wb") as f:
tomli_w.dump(valid_data, f)
with patch("config.Config._init_platform"):
cfg = Config(mock_app_dir)
assert cfg.get_bool("recovered") is True
# This confirms that the rename `bak.replace(self.toml_path)` inside `_load` worked.
# If this fails, it means `tomllib.load` on the backup file failed.
assert not bak_path.exists()
assert toml_path.exists()
def test_reload_from_path(self, mock_app_dir, tmp_path):
"""Test hot-swapping the config file."""
with patch("config.Config._init_platform"):
c = Config(mock_app_dir)
# Create a second config file elsewhere
alt_dir = tmp_path / "alt"
alt_dir.mkdir()
alt_config = alt_dir / "alternate.toml"
data = {
"settings": {
"mode": "alternate",
"plugin_dir": str(mock_app_dir / "plugins"),
}
}
with open(alt_config, "wb") as f:
tomli_w.dump(data, f)
# Reload
c.reload_from_path(alt_config)
assert c.toml_path == alt_config
assert c.get("mode") == "alternate"
def test_init_platform_calls_linux_helper(mock_app_dir):
with patch("sys.platform", "linux"):
mock_module = sys.modules["config.linux"]
# We must NOT patch _init_platform here, because we want it to run
# and call the mocked module
Config(mock_app_dir)
mock_module.linux_helper.assert_called_once()
def test_set_none_deletes_key(mock_app_dir):
"""Test that calling set(key, None) deletes the key from config."""
with patch("config.Config._init_platform"):
cfg = Config(mock_app_dir)
# Set a key first
cfg.set("some_temp_key", "value")
assert cfg.get("some_temp_key") == "value"
# Set it to None, which should delete it
cfg.set("some_temp_key", None)
assert cfg.get("some_temp_key") is None
# Verify disk persistence does not have it either
with open(cfg.toml_path, "rb") as f:
import tomllib
data = tomllib.load(f)
assert "some_temp_key" not in data["settings"]