95 lines
3.1 KiB
Python
95 lines
3.1 KiB
Python
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from syncvito.config_store import ConfigError, ConfigStore
|
|
from syncvito.models import AppConfig, AppSettings, SyncDirection, SyncTask
|
|
|
|
|
|
def test_config_roundtrip(tmp_path: Path) -> None:
|
|
path = tmp_path / "config.json"
|
|
config = AppConfig(
|
|
tasks=[
|
|
SyncTask(
|
|
name="Archiv",
|
|
source=str(tmp_path / "quelle"),
|
|
target=str(tmp_path / "ziel"),
|
|
direction=SyncDirection.BIDIRECTIONAL,
|
|
selected_paths=["Dokumente"],
|
|
)
|
|
],
|
|
settings=AppSettings(font_size=12, ui_scale=110, check_updates_on_start=False),
|
|
)
|
|
ConfigStore(path).save(config)
|
|
|
|
loaded = ConfigStore(path).load()
|
|
|
|
assert loaded.settings.font_size == 12
|
|
assert loaded.settings.ui_scale == 110
|
|
assert loaded.settings.check_updates_on_start is False
|
|
assert loaded.tasks[0].name == "Archiv"
|
|
assert loaded.tasks[0].direction is SyncDirection.BIDIRECTIONAL
|
|
assert loaded.tasks[0].selected_paths == ["Dokumente"]
|
|
|
|
|
|
def test_config_corrupt_json_creates_backup(tmp_path: Path) -> None:
|
|
path = tmp_path / "config.json"
|
|
path.write_text("{ unvollstaendiges json...", encoding="utf-8")
|
|
|
|
store = ConfigStore(path)
|
|
with pytest.raises(ConfigError, match="syntaktisch beschädigt"):
|
|
store.load()
|
|
|
|
defekt_files = list(tmp_path.glob("config.defekt-*.json"))
|
|
assert len(defekt_files) == 1
|
|
assert not path.exists()
|
|
|
|
|
|
def test_config_read_locked_does_not_rename_file(tmp_path: Path) -> None:
|
|
path = tmp_path / "config.json"
|
|
path.write_text('{"schema_version": 1, "tasks": [], "settings": {}}', encoding="utf-8")
|
|
|
|
store = ConfigStore(path)
|
|
with (
|
|
patch.object(Path, "read_text", side_effect=PermissionError(13, "Permission denied")),
|
|
pytest.raises(ConfigError, match="konnte nicht gelesen werden"),
|
|
):
|
|
store.load()
|
|
|
|
# Originaldatei darf bei Lese-/Sperrfehler NICHT umbenannt/gelöscht werden!
|
|
assert path.exists()
|
|
assert list(tmp_path.glob("config.defekt-*.json")) == []
|
|
|
|
|
|
def test_config_load_with_invalid_task_keeps_task_disabled() -> None:
|
|
data = {
|
|
"schema_version": 1,
|
|
"tasks": [
|
|
{
|
|
"name": "Ungültig",
|
|
"source": "C:\\Ordner",
|
|
"target": "C:\\Ordner", # Gleiche Quelle und Ziel -> ValueError bei validate()
|
|
"interval_minutes": 30,
|
|
}
|
|
],
|
|
"settings": {},
|
|
}
|
|
config = AppConfig.from_dict(data)
|
|
assert len(config.tasks) == 1
|
|
assert config.tasks[0].name == "Ungültig"
|
|
assert config.tasks[0].enabled is False
|
|
|
|
|
|
def test_sync_task_safe_resolve_network_oserror(tmp_path: Path) -> None:
|
|
task = SyncTask(
|
|
name="Netzwerk-Task",
|
|
source=str(tmp_path / "lokal"),
|
|
target=r"\\UnerreichbarerServer\Freigabe\Ordner",
|
|
)
|
|
with patch.object(Path, "resolve", side_effect=OSError("Network unreachable")):
|
|
task.validate()
|
|
|
|
assert task.source == str((tmp_path / "lokal").resolve())
|
|
assert r"\\UnerreichbarerServer\Freigabe\Ordner" in task.target
|