Files
hermes-agent/tests/pm/test_uv_cache_publication.py
Riccardo Vecchi 44c32dfa79 fix(pm): publish seeded cache files atomically
Follow up the shared-cache copy observation on PR #135458 with behavioral regression coverage and a sibling staging file. Make the lock-change fixture independent of timestamp granularity.

Prepared with OpenAI Codex assistance; no human review claimed.
2026-10-09 12:56:40 -04:00

80 lines
2.8 KiB
Python

"""Cache readers must never see an unfinished payload seed copy."""
from pathlib import Path
import pytest
import hermes_constants
from pm import packages, paths
@pytest.fixture
def seed_paths(tmp_path, monkeypatch):
machine = tmp_path / "machine"
monkeypatch.setattr(hermes_constants, "get_default_hermes_root", lambda: machine)
payload = tmp_path / "payload"
store = payload / "tools"
store.mkdir(parents=True)
source = payload / "uv-cache" / "entry"
source.parent.mkdir()
source.write_bytes(b"complete-new-payload")
monkeypatch.setattr(paths, "store_root", lambda: store)
repo = tmp_path / "repo"
repo.mkdir()
(repo / "uv.lock").write_text("version = 1\n", encoding="utf-8")
monkeypatch.setattr(paths, "repo_root", lambda: repo)
return source, machine / "cache" / "uv" / "entry"
@pytest.mark.parametrize("previous", [None, b"old"])
def test_seed_publishes_only_a_complete_file(seed_paths, monkeypatch, previous):
source, destination = seed_paths
destination.parent.mkdir(parents=True)
if previous is not None:
destination.write_bytes(previous)
real_copy = packages.shutil.copy2
observed = []
def observe_copy(src, dst):
Path(dst).write_bytes(b"partial")
observed.append(destination.read_bytes() if destination.exists() else None)
return real_copy(src, dst)
monkeypatch.setattr(packages.shutil, "copy2", observe_copy)
packages.uv_cache_dir()
assert observed == [previous]
assert destination.read_bytes() == source.read_bytes()
assert (destination.parent / ".seeded").is_file()
assert {p.name for p in destination.parent.iterdir()} == {"entry", ".seeded"}
@pytest.mark.parametrize("previous", [None, b"old"])
def test_interrupted_seed_preserves_readers_and_retries(seed_paths, monkeypatch, previous):
source, destination = seed_paths
destination.parent.mkdir(parents=True)
if previous is not None:
destination.write_bytes(previous)
real_copy = packages.shutil.copy2
attempts = []
def interrupted_copy(src, dst):
attempts.append(1)
if len(attempts) == 1:
Path(dst).write_bytes(b"partial")
raise OSError("synthetic copy interruption")
return real_copy(src, dst)
monkeypatch.setattr(packages.shutil, "copy2", interrupted_copy)
packages.uv_cache_dir()
assert (destination.read_bytes() if destination.exists() else None) == previous
assert not (destination.parent / ".seeded").exists()
assert {p.name for p in destination.parent.iterdir()} == ({"entry"} if previous else set())
packages.uv_cache_dir()
assert destination.read_bytes() == source.read_bytes()
assert (destination.parent / ".seeded").is_file()
assert {p.name for p in destination.parent.iterdir()} == {"entry", ".seeded"}