Files
hermes-agent/tests/pm/test_store_lock_wait.py
ethernet b728fdd627 refactor(pm): own the lock/atomic-write primitives in pm.filesystem
pm imported runtime_state's private helpers (_lock, _atomic_bytes, _bytes,
_digest) at a dozen sites while runtime_state imports pm.environments at
module top. The primitives are pm's: move them into the stdlib-only
pm.filesystem as lock_fd, durable_write_bytes, read_bytes_or_none and
file_digest, and repoint every pm caller.

runtime_state keeps the private names only as import aliases: it still
calls them through its own globals, and pre-PM updaters load them by these
names mid-swap (tests/compat/old_updater_surface.json).

Boot-subset test fixtures now copy pm/filesystem.py, since runtime_state
imports it at process boot; worker-injection tests patch the name
pm.publication now reads.
2026-09-24 14:08:03 -04:00

33 lines
1015 B
Python

"""A writer queued behind the store lock says so instead of blocking silently."""
import os
import threading
import time
from pm.filesystem import lock_fd
from pm.store import Store
def test_install_lock_reports_what_it_waits_on(tmp_path, capsys):
store = Store(tmp_path / "store")
store.root.mkdir()
holder = os.open(store.root / ".install.lock", os.O_CREAT | os.O_RDWR, 0o600)
assert lock_fd(holder, wait=False)
entered = threading.Event()
def contend():
with store.install_lock():
entered.set()
waiter = threading.Thread(target=contend, daemon=True)
waiter.start()
deadline = time.monotonic() + 15
err = ""
while "waiting for" not in err and time.monotonic() < deadline:
time.sleep(0.1)
err += capsys.readouterr().err
assert str(store.root / ".install.lock") in err
assert not entered.is_set()
os.close(holder)
assert entered.wait(timeout=10), "the message must not replace the wait"
waiter.join(timeout=5)