Files
odysseus/tests/test_manage_sft_fixture_state.py
T

98 lines
4.2 KiB
Python

import importlib.util
import json
import sqlite3
import sys
from pathlib import Path
PATH = Path(__file__).resolve().parents[1] / "scripts" / "manage_sft_fixture_state.py"
SPEC = importlib.util.spec_from_file_location("manage_sft_fixture_state", PATH)
MODULE = importlib.util.module_from_spec(SPEC)
assert SPEC and SPEC.loader
sys.modules[SPEC.name] = MODULE
SPEC.loader.exec_module(MODULE)
def make_db(path: Path) -> None:
db = sqlite3.connect(path)
db.executescript("""
CREATE TABLE notes (id TEXT PRIMARY KEY, owner TEXT, title TEXT);
CREATE TABLE documents (id TEXT PRIMARY KEY, owner TEXT, title TEXT);
CREATE TABLE document_versions (id TEXT PRIMARY KEY, document_id TEXT, content TEXT);
CREATE TABLE sessions (id TEXT PRIMARY KEY, owner TEXT, name TEXT);
""")
db.executemany("INSERT INTO notes VALUES (?,?,?)", [
("a", "alex", "baseline"), ("p", "pewds", "untouched"),
])
db.execute("INSERT INTO documents VALUES ('d', 'alex', 'doc')")
db.execute("INSERT INTO document_versions VALUES ('v', 'd', 'baseline body')")
db.execute("INSERT INTO sessions VALUES ('s', 'alex', 'evidence')")
db.commit()
db.close()
def test_owner_restore_is_scoped_and_preserves_sessions(tmp_path):
path = tmp_path / "app.db"
make_db(path)
snapshot = MODULE.snapshot_owner(path, "alex")
db = sqlite3.connect(path)
db.execute("DELETE FROM notes WHERE id='a'")
db.execute("INSERT INTO notes VALUES ('junk', 'alex', 'audit junk')")
db.execute("INSERT INTO sessions VALUES ('new', 'alex', 'new evidence')")
db.commit()
db.close()
MODULE.restore_owner(path, snapshot, "alex")
db = sqlite3.connect(path)
assert db.execute("SELECT id,title FROM notes WHERE owner='alex'").fetchall() == [("a", "baseline")]
assert db.execute("SELECT title FROM notes WHERE owner='pewds'").fetchone() == ("untouched",)
assert db.execute("SELECT id FROM sessions WHERE owner='alex' ORDER BY id").fetchall() == [("new",), ("s",)]
assert db.execute("SELECT content FROM document_versions").fetchone() == ("baseline body",)
db.close()
def test_restore_rejects_cross_owner_snapshot(tmp_path):
path = tmp_path / "app.db"
make_db(path)
snapshot = MODULE.snapshot_owner(path, "alex")
try:
MODULE.restore_owner(path, snapshot, "pewds")
except ValueError as exc:
assert "owner" in str(exc)
else:
raise AssertionError("cross-owner restore was accepted")
def test_owner_restore_includes_external_fixture_state(tmp_path):
path = tmp_path / "app.db"
make_db(path)
(tmp_path / "user_prefs.json").write_text(
'{"_users":{"alex":{"theme":"dark"},"pewds":{"theme":"light"}}}', encoding="utf-8",
)
(tmp_path / "fixture_email_messages.json").write_text(
'{"messages":[{"owner":"alex","uid":"a"},{"owner":"pewds","uid":"p"}]}', encoding="utf-8",
)
(tmp_path / "email_blocked_senders.json").write_text(
'{"owners":{"alex":["bad@example.com"],"pewds":[]}}', encoding="utf-8",
)
skill_dir = tmp_path / "skills" / "general" / "alex-skill"
skill_dir.mkdir(parents=True)
(skill_dir / "SKILL.md").write_text("---\nname: alex-skill\nowner: alex\n---\nbody", encoding="utf-8")
(tmp_path / "skills" / "_usage.json").write_text(
'{"alex::alex-skill":{"uses":2},"pewds::other":{"uses":1}}', encoding="utf-8",
)
snapshot = MODULE.snapshot_owner(path, "alex", tmp_path)
(tmp_path / "user_prefs.json").write_text('{"_users":{"alex":{"theme":"wrong"}}}', encoding="utf-8")
(tmp_path / "fixture_email_messages.json").write_text('{"messages":[]}', encoding="utf-8")
(skill_dir / "SKILL.md").write_text("---\nname: alex-skill\nowner: alex\n---\nwrong", encoding="utf-8")
MODULE.restore_owner(path, snapshot, "alex", tmp_path)
assert json.loads((tmp_path / "user_prefs.json").read_text())["_users"]["alex"] == {"theme": "dark"}
emails = json.loads((tmp_path / "fixture_email_messages.json").read_text())["messages"]
assert emails == [{"owner": "alex", "uid": "a"}]
assert (skill_dir / "SKILL.md").read_text().endswith("body")
usage = json.loads((tmp_path / "skills" / "_usage.json").read_text())
assert usage["alex::alex-skill"] == {"uses": 2}