Files
zerto-ai-rewind/tests/test_catalog.py
T

72 lines
2.6 KiB
Python

import json
from pathlib import Path
from zerto_rewind_mcp.catalog import CatalogEntry, MutatingCatalog, entry_from_dict
def test_add_and_get(tmp_path: Path):
path = tmp_path / "config.json"
path.write_text(
json.dumps({"zerto_url": "https://zvm", "mutating_tools": []}),
encoding="utf-8",
)
cat = MutatingCatalog(path=path)
cat.add(CatalogEntry(server="ssh", tool="exec", vm_arg="host", notes="guest shell"))
found = cat.get("SSH", "Exec")
assert found is not None
assert found.vm_arg == "host"
saved = json.loads(path.read_text(encoding="utf-8"))
assert saved["zerto_url"] == "https://zvm"
assert saved["mutating_tools"][0]["tool"] == "exec"
def test_unlisted_is_missing():
cat = MutatingCatalog()
assert cat.get("foo", "bar") is None
def test_entry_requires_fields():
try:
entry_from_dict({"server": "ssh"})
raise AssertionError("expected ValueError")
except ValueError:
pass
def test_example_config_covers_windows_and_linux():
"""The starter catalog must not be Linux-only.
The catalog is opt-in: an unlisted tool passes through unguarded. A
Windows-only shop taking the shipped defaults would therefore mutate
protected guests with no checkpoint at all.
"""
example = Path(__file__).resolve().parent.parent / "config.example.json"
data = json.loads(example.read_text(encoding="utf-8"))
cat = MutatingCatalog.from_config(data)
assert cat.get("ssh", "exec") is not None
assert cat.get("winrm", "run_command") is not None
assert cat.get("winrm", "run_ps") is not None
assert cat.get("powershell", "invoke_command") is not None
# every entry must name the arg holding the VM, or the guard cannot resolve one
for entry in cat.list():
assert entry.vm_arg, f"{entry.server}/{entry.tool} has no vm_arg"
def test_classify_three_way():
data = {
"mutating_tools": [{"server": "winrm", "tool": "run_ps", "vm_arg": "host"}],
"read_only_tools": [{"server": "ssh", "tool": "read_file"}],
}
cat = MutatingCatalog.from_config(data)
assert cat.classify("winrm", "run_ps") == "mutating"
assert cat.classify("SSH", "Read_File") == "read_only"
# unknown is not safe; it means nobody classified it
assert cat.classify("anything", "else") == "unknown"
def test_read_only_entries_need_no_vm_arg():
data = {"read_only_tools": [{"server": "ssh", "tool": "stat"}]}
cat = MutatingCatalog.from_config(data)
assert cat.classify("ssh", "stat") == "read_only"
assert [e.tool for e in cat.read_only()] == ["stat"]