Files
Elydora-Python-SDK/tests/test_letta_transaction.py
T

112 lines
3.8 KiB
Python

from __future__ import annotations
import json
import os
from pathlib import Path
from typing import Any
import pytest
from elydora.plugins import _transaction
from elydora.plugins.letta_config import render_letta_document
from elydora.plugins.letta_contract import build_letta_group
from elydora.plugins.letta_installation import (
commit_letta_installation,
preflight_letta_installation,
prepare_letta_installation,
)
from elydora.plugins.letta_sources import read_letta_sources
from letta_support import prepare_fixture, write_json
def _groups(guard_path: str, audit_path: str) -> dict:
return {
"PreToolUse": build_letta_group(guard_path),
"PostToolUse": build_letta_group(audit_path),
"PostToolUseFailure": build_letta_group(audit_path),
}
def test_transaction_aborts_when_read_only_source_changes(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
fixture = prepare_fixture(
monkeypatch, tmp_path, project_settings={"owner": "before"}
)
sources = read_letta_sources()
paths = preflight_letta_installation(fixture.config, sources)
rendered = render_letta_document(
sources.global_settings,
None,
_groups(paths.guard_path, paths.audit_path),
)
changes = prepare_letta_installation(fixture.config, paths, rendered)
write_json(fixture.project_path, {"owner": "after"})
with pytest.raises(OSError, match="project settings changed"):
commit_letta_installation(changes, sources)
assert json.loads(fixture.project_path.read_text()) == {"owner": "after"}
assert not fixture.global_path.exists()
assert not fixture.agent_dir.exists()
def test_transaction_rolls_back_every_runtime_and_settings_change(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
fixture = prepare_fixture(
monkeypatch, tmp_path, global_settings={"owner": "user"}
)
original = fixture.source()
real_replace = _transaction.os.replace
failed = False
def fail_settings_commit(source: Any, destination: Any) -> None:
nonlocal failed
if not failed and Path(destination) == fixture.global_path:
failed = True
raise OSError("simulated Letta settings commit failure")
real_replace(source, destination)
monkeypatch.setattr(_transaction.os, "replace", fail_settings_commit)
with pytest.raises(OSError, match="Install Letta Code hooks"):
fixture.install()
assert failed
assert fixture.source() == original
for file_path in (
fixture.guard_path,
fixture.audit_path,
fixture.runtime_config_path,
fixture.private_key_path,
):
assert not file_path.exists()
assert [
path
for path in fixture.home_dir.rglob("*")
if path.suffix in {".tmp", ".rollback"}
] == []
def test_install_rejects_linked_configuration_directory(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
fixture = prepare_fixture(monkeypatch, tmp_path)
redirected = tmp_path / "redirected-letta"
redirected.mkdir()
fixture.home_dir.mkdir(parents=True)
try:
os.symlink(redirected, fixture.global_path.parent, target_is_directory=True)
except (NotImplementedError, OSError):
pytest.skip("directory links require platform privileges")
with pytest.raises(OSError, match="global configuration directory"):
fixture.install()
assert not fixture.agent_dir.exists()
def test_install_rejects_directory_at_settings_path(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
fixture = prepare_fixture(monkeypatch, tmp_path)
fixture.global_path.mkdir(parents=True)
with pytest.raises(OSError, match="global settings path"):
fixture.install()
assert not fixture.agent_dir.exists()