mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 05:17:15 +00:00
test(deadline): pin review cases for poll_until callers and the sweep
From review: document that poll_until bounds only its sleeps, not time spent in the predicate; pin that unlink_files_older_than keeps sweeping after one unlink raises PermissionError; pin that _wait_for_user_dbus_socket exports the systemd env exactly once when the socket appears only on the final check, made at the deadline after a cut last sleep. Both new tests fail against a mutated implementation (the per-file suppress removed; main's loop shape).
This commit is contained in:
1 parent
a4baee29de
commit
fa59cb998a
3 files changed
+44
No files matched your search
@@ -143,6 +143,8 @@ def poll_until(predicate: Callable[[], _T], timeout: float, interval: float) ->
|
||||
|
||||
The first check runs at once and the last sleep is cut to the time left, so a condition that
|
||||
holds when the deadline arrives still counts. ``timeout <= 0`` means exactly one check.
|
||||
Only the sleeps are bounded: time spent inside ``predicate`` is not, so a predicate that blocks
|
||||
(socket probes, subprocess calls) can carry the final check past the deadline.
|
||||
"""
|
||||
deadline = time.monotonic() + timeout
|
||||
while True:
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
"""``_wait_for_user_dbus_socket``: readiness found on poll_until's final check still exports the env."""
|
||||
|
||||
import pytest
|
||||
|
||||
pytest.importorskip("pwd") # POSIX systemd helper, same gate as test_gateway_service
|
||||
|
||||
import hermes_cli.gateway as gateway_cli
|
||||
|
||||
|
||||
def test_ready_only_on_final_check_exports_env_once(monkeypatch):
|
||||
calls, slept = [], []
|
||||
checks = iter([False, True])
|
||||
# Deadline at 1.0. After the first miss the clock reads 0.9, so the last sleep is cut to 0.1
|
||||
# and the second check is the final one, made at the deadline.
|
||||
clock = iter([0.0, 0.9, 1.0])
|
||||
monkeypatch.setattr(gateway_cli, "_ensure_user_systemd_env", lambda: calls.append("env"))
|
||||
monkeypatch.setattr(gateway_cli, "_user_systemd_socket_ready", lambda: next(checks))
|
||||
monkeypatch.setattr("agent.deadline.time.monotonic", lambda: next(clock))
|
||||
monkeypatch.setattr("agent.deadline.time.sleep", slept.append)
|
||||
|
||||
assert gateway_cli._wait_for_user_dbus_socket(timeout=1.0) is True
|
||||
assert slept == [pytest.approx(0.1)]
|
||||
assert calls == ["env"]
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from utils import unlink_files_older_than
|
||||
|
||||
@@ -28,3 +29,21 @@ def test_removes_only_matching_files_older_than_the_age(tmp_path):
|
||||
|
||||
def test_missing_directory_is_zero_not_an_error(tmp_path):
|
||||
assert unlink_files_older_than(tmp_path / "absent", "*", 0) == 0
|
||||
|
||||
|
||||
def test_unlink_failure_skips_that_file_and_keeps_sweeping(tmp_path, monkeypatch):
|
||||
now = time.time()
|
||||
stuck = _aged(tmp_path / "a.json", 120, now)
|
||||
later = _aged(tmp_path / "b.json", 120, now)
|
||||
real_unlink = Path.unlink
|
||||
|
||||
def unlink(self, *args, **kwargs):
|
||||
if self.name == "a.json":
|
||||
raise PermissionError("locked")
|
||||
return real_unlink(self, *args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(Path, "unlink", unlink)
|
||||
monkeypatch.setattr(Path, "glob", lambda self, pattern: iter([self / "a.json", self / "b.json"])) # fail first
|
||||
|
||||
assert unlink_files_older_than(tmp_path, "*.json", 60, now=now) == 1
|
||||
assert stuck.exists() and not later.exists()
|
||||
Reference in new issue
Block a user