From ddb86725b5cfab85b318bda1802c091dbb96daf1 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:25:54 -0700 Subject: [PATCH] test(web): pin per-profile gateway state scoping on /api/status Follow-up for the salvaged #70498 fix: replace the original PR's mock-signature churn (28 lambda **kw edits, needed only because it changed the no-profile call shape) with two targeted regression tests: - ?profile= must pass the profile's gateway.pid / gateway_state.json paths and expected_home to the gateway status readers (HOME-anchored per-profile state under ~/.hermes/profiles//) - ?profile= must 404 via _resolve_profile_dir The production change keeps plain /api/status on the exact zero-arg calls, so every pre-existing test passes unmodified. --- tests/hermes_cli/test_web_server.py | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/hermes_cli/test_web_server.py b/tests/hermes_cli/test_web_server.py index 7f0119ec2bc6..7b22dbf1318f 100644 --- a/tests/hermes_cli/test_web_server.py +++ b/tests/hermes_cli/test_web_server.py @@ -346,6 +346,61 @@ class TestWebServerEndpoints: assert resp.status_code == 200 assert calls["get_running_pid_cached"] == 1 + def test_get_status_profile_scopes_gateway_state_reads(self, monkeypatch): + """?profile= must read gateway identity files from the profile's + home (~/.hermes/profiles//), not the process-level HERMES_HOME. + + Gateway PID/state readers resolve _get_process_hermes_home(), which + deliberately ignores the contextvar override _config_profile_scope + sets (issue #56986) — so the handler must pass explicit per-profile + paths (issue #69143). + """ + import hermes_cli.web_server as web_server + from hermes_cli import profiles as profiles_mod + + worker_home = profiles_mod.get_profile_dir("worker") + worker_home.mkdir(parents=True) + + seen = {} + + def _pid(pid_path=None, **kw): + seen["pid_path"] = pid_path + return None + + def _runtime(path=None): + seen["status_path"] = path + return { + "gateway_state": "running", + "platforms": {}, + "updated_at": "2026-04-12T00:00:00+00:00", + } + + def _runtime_pid(runtime=None, *, expected_home=None): + seen["expected_home"] = expected_home + return 4321 + + monkeypatch.setattr(web_server, "get_running_pid_cached", _pid) + monkeypatch.setattr(web_server, "read_runtime_status", _runtime) + monkeypatch.setattr( + web_server, "get_runtime_status_running_pid", _runtime_pid + ) + monkeypatch.setattr(web_server, "_GATEWAY_HEALTH_URL", None) + + resp = self.client.get("/api/status?profile=worker") + + assert resp.status_code == 200 + data = resp.json() + assert seen["pid_path"] == worker_home / "gateway.pid" + assert seen["status_path"] == worker_home / "gateway_state.json" + assert seen["expected_home"] == worker_home + assert data["gateway_running"] is True + assert data["gateway_pid"] == 4321 + assert data["gateway_state"] == "running" + + def test_get_status_unknown_profile_404s(self): + resp = self.client.get("/api/status?profile=no-such-profile") + assert resp.status_code == 404 + def test_gateway_drain_begin_writes_marker(self): from gateway import drain_control