test(issue-45): review - the real-server tests run on macOS, and the bootstrap config check follows the bootstrap's python3
claude round 1, B2 and B3 (B1 was the previous commit). - B2, tests/test_issue45_restore.py: the throwaway root is resolved, because on macOS /tmp links to /private/tmp and herdr reports real paths (two B tests compared /tmp/... with /private/tmp/...). The server's environment is read from /proc on Linux and from `ps -E` elsewhere (macOS has no /proc; two A tests failed with FileNotFoundError). - B3, tests/test_issue9_server_env.py: the bootstrap builds the config with the python3 on PATH, which here is 3.9 without tomllib, so the test's merged-settings expectation could not hold and its own `import tomllib` failed. The test now parses the result with that same python3; when it has no tomllib, it expects the key-only config and the bootstrap's "no tomllib" warning instead. macOS, Python 3.9 venv: test_issue45_restore, test_issue9_server_env and test_issue45_herdr_config 42 passed / 29 skipped (the tomllib-only checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
36f0b8dfd6
commit
e8d9151226
2 files changed
+30
-6
No files matched your search
@@ -157,10 +157,22 @@ class Rig:
|
||||
return self.argv_log.exists() and f"--resume {session_id}" in self.argv_log.read_text()
|
||||
|
||||
|
||||
def _process_env(pid: int) -> list:
|
||||
"""A process's environment as KEY=VALUE strings: /proc on Linux; on macOS
|
||||
`ps -E` appends it to the command line, so the entries are matched there."""
|
||||
proc = Path(f"/proc/{pid}/environ")
|
||||
if proc.exists():
|
||||
return [e.decode(errors="replace") for e in proc.read_bytes().split(b"\0") if e]
|
||||
out = subprocess.run(["ps", "-E", "-ww", "-o", "command=", "-p", str(pid)],
|
||||
capture_output=True, text=True, timeout=10).stdout
|
||||
return out.split()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rig(mam_sandbox, monkeypatch):
|
||||
# A pytest tmp_path is too long for a unix socket path under it.
|
||||
root = Path(tempfile.mkdtemp(prefix="m45", dir="/tmp"))
|
||||
# Resolved: on macOS /tmp is a link to /private/tmp and herdr reports real paths.
|
||||
root = Path(tempfile.mkdtemp(prefix="m45", dir="/tmp")).resolve()
|
||||
session = f"mamt45-{os.getpid()}-{uuid.uuid4().hex[:4]}"
|
||||
for k in SCOPE_ENV:
|
||||
monkeypatch.delenv(k, raising=False)
|
||||
@@ -224,8 +236,8 @@ def test_a_mam_server_does_not_relaunch_saved_agents(rig, user_session_table):
|
||||
info = rig.hd("pane", "process-info", "--pane", pane["pane_id"])["process_info"]
|
||||
assert info["foreground_process_group_id"] == info["shell_pid"], info
|
||||
# and it got there through HERDR_CONFIG_PATH
|
||||
environ = Path(f"/proc/{rig.server_pids()[0]}/environ").read_bytes().split(b"\0")
|
||||
assert f"HERDR_CONFIG_PATH={rig.user_cfg.parent / herdr_config.OUTPUT_NAME}".encode() in environ
|
||||
want = f"HERDR_CONFIG_PATH={rig.user_cfg.parent / herdr_config.OUTPUT_NAME}"
|
||||
assert want in _process_env(rig.server_pids()[0]), want
|
||||
|
||||
# Positive control: the same saved layout under a plain server relaunches
|
||||
# the agent, so the "not resumed" above is not vacuous.
|
||||
|
||||
@@ -154,7 +154,6 @@ def test_bootstrap_hands_the_server_a_no_restore_config(mam_sandbox):
|
||||
"""Issue #45: the server starts with HERDR_CONFIG_PATH = the user's herdr
|
||||
config plus [session] resume_agents_on_restore = false (that herdr obeys it
|
||||
is test_issue45_restore.py, on a real server)."""
|
||||
import tomllib
|
||||
env = _install_fake_herdr(mam_sandbox)
|
||||
user_cfg = mam_sandbox / ".config" / "herdr" / "config.toml"
|
||||
user_cfg.parent.mkdir(parents=True)
|
||||
@@ -167,8 +166,21 @@ def test_bootstrap_hands_the_server_a_no_restore_config(mam_sandbox):
|
||||
server_env = json.loads(Path(env["FAKE_HERDR_ENV_DUMP"]).read_text())
|
||||
assert server_env.get("HERDR_CONFIG_PATH") == str(user_cfg.parent / "mam-server-config.toml")
|
||||
assert "MAM_SERVER_CFG" not in server_env
|
||||
cfg = tomllib.loads(Path(server_env["HERDR_CONFIG_PATH"]).read_text())
|
||||
assert cfg == {"ui": {"confirm_close": False}, "session": {"resume_agents_on_restore": False}}
|
||||
# The bootstrap builds the file with the python3 on PATH; parse it with that
|
||||
# same python3. Without tomllib there (Python < 3.11, macOS's 3.9) the file is
|
||||
# the key-only config and the bootstrap warns that the other settings are gone.
|
||||
out = Path(server_env["HERDR_CONFIG_PATH"])
|
||||
parse = subprocess.run(["python3", "-c", "import json, sys, tomllib; "
|
||||
"print(json.dumps(tomllib.loads(open(sys.argv[1]).read())))", str(out)],
|
||||
capture_output=True, text=True, env=env, timeout=30)
|
||||
if parse.returncode == 0:
|
||||
assert json.loads(parse.stdout) == {"ui": {"confirm_close": False},
|
||||
"session": {"resume_agents_on_restore": False}}
|
||||
else:
|
||||
assert "No module named 'tomllib'" in parse.stderr, parse.stderr
|
||||
text = out.read_text()
|
||||
assert "resume_agents_on_restore = false" in text and "confirm_close" not in text, text
|
||||
assert "no tomllib" in res.stderr, res.stderr
|
||||
|
||||
|
||||
def test_no_autostart_skips_bootstrap_but_still_routes_the_call(mam_sandbox):
|
||||
|
||||
Reference in new issue
Block a user