Files
hermes-agent/tests/hermes_platform/test_resolver_app.py
teknium1 8f6109e493 test: purge low-value tests, lane py14 (360 removed)
Change-detectors, tautologies, source-reading tests, redundant duplicates,
mock-echo tests and dead/unrunnable tests. Per-test rationale in the lane
ledger (category + reason for every removal).
2026-09-23 03:15:26 -07:00

227 lines
8.4 KiB
Python

from __future__ import annotations
import dataclasses
import json
import os
import plistlib
import socket
import sys
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
import pytest
from hermes_platform.resolver import CheckState, Effort
from hermes_platform.resolver.app import AppDef, AppResolver, Endpoint
TOKEN = "tok-3e1f9c-unique-fixture-value"
def _bundle(tmp_path, version="9.8.7"):
app = tmp_path / "Applications" / "Thing.app"
(app / "Contents").mkdir(parents=True)
with open(app / "Contents" / "Info.plist", "wb") as fh:
plistlib.dump({"CFBundleShortVersionString": version}, fh)
return app
def _server_json(tmp_path, *, url, pid=None):
p = tmp_path / "server.json"
p.write_text(json.dumps({"pid": os.getpid() if pid is None else pid, "http": url, "token": TOKEN}), encoding="utf-8")
return p
def _resolver(tmp_path, exe, server_json=None):
return AppResolver(AppDef(
"thing", sys.platform, "executable", str(exe),
liveness_kind="server_json" if server_json else "none",
liveness_path=str(server_json) if server_json else "",
))
def test_locate_reports_expanded_path_when_missing(tmp_path, monkeypatch):
monkeypatch.setenv("THINGROOT", str(tmp_path))
r = AppResolver(AppDef("thing", sys.platform, "executable", "$THINGROOT/bin/thing"))
res = r.locate()
assert res.kind == "missing"
assert res.candidates[0].value == str(tmp_path / "bin" / "thing")
def test_bundle_presence_and_plist_version(tmp_path):
app = _bundle(tmp_path)
r = AppResolver(AppDef("thing", "darwin", "bundle", str(app), version_kind="plist"))
res = r.locate()
assert res.kind == "known_path" and res.command == (str(app),)
insp = r.inspect(res)
assert insp.version.state is CheckState.PRESENT and insp.version.value == "9.8.7"
assert insp.signer.state is CheckState.NOT_CHECKED
def test_inspect_on_missing_is_not_checked(tmp_path):
r = AppResolver(AppDef("thing", sys.platform, "executable", str(tmp_path / "none"), version_kind="plist"))
insp = r.inspect(r.locate())
assert insp.version.state is CheckState.NOT_CHECKED
def test_probe_without_liveness_source_is_all_not_checked(tmp_path):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
r = _resolver(tmp_path, exe)
pr = r.probe(r.locate(), effort=Effort.NETWORK)
assert pr.running.state is pr.answering.state is pr.endpoint.state is CheckState.NOT_CHECKED
def test_probe_local_reads_pid_and_endpoint_but_never_connects(tmp_path):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url="http://127.0.0.1:1/mcp")
r = _resolver(tmp_path, exe, sj)
pr = r.probe(r.locate(), effort=Effort.LOCAL)
assert pr.running.state is CheckState.PRESENT and pr.running.value is True
assert pr.endpoint.value == "http://127.0.0.1:1/mcp"
assert pr.answering.state is CheckState.NOT_CHECKED
def test_probe_is_not_a_boolean(tmp_path):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
pr = _resolver(tmp_path, exe).probe(_resolver(tmp_path, exe).locate(), effort=Effort.LOCAL)
with pytest.raises(TypeError):
bool(pr)
def test_token_never_appears_in_any_public_result(tmp_path):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url="http://127.0.0.1:1/mcp")
r = _resolver(tmp_path, exe, sj)
res = r.locate()
pr = r.probe(res, effort=Effort.LOCAL)
for obj in (res, r.inspect(res), pr):
assert TOKEN not in repr(obj)
assert TOKEN not in json.dumps(dataclasses.asdict(obj), default=str)
assert "token" not in {f.name for f in dataclasses.fields(obj)}
@pytest.mark.parametrize("url", [
"http://[::1",
"https://127.0.0.1:1234/mcp",
"http://user:pw@127.0.0.1:1234/mcp",
"http://example.com:1234/mcp",
"http://127.0.0.1/mcp",
"http://127.0.0.1:99999/mcp",
])
def test_non_loopback_or_malformed_endpoint_is_unavailable_and_never_contacted(tmp_path, url, monkeypatch):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url=url)
r = _resolver(tmp_path, exe, sj)
monkeypatch.setattr(socket, "create_connection", lambda *a, **k: pytest.fail("no socket allowed"))
pr = r.probe(r.locate(), effort=Effort.NETWORK)
assert pr.endpoint.state is CheckState.UNAVAILABLE
assert pr.answering.state is CheckState.NOT_CHECKED
def test_dead_pid_is_absent_and_skips_network(tmp_path, monkeypatch):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url="http://127.0.0.1:1/mcp", pid=2**22 + 12345)
r = _resolver(tmp_path, exe, sj)
monkeypatch.setattr(socket, "create_connection", lambda *a, **k: pytest.fail("no socket allowed"))
pr = r.probe(r.locate(), effort=Effort.NETWORK)
assert pr.running.state is CheckState.ABSENT
assert pr.answering.state is CheckState.NOT_CHECKED
class _Handler(BaseHTTPRequestHandler):
seen: list[tuple[str, str]] = []
def do_POST(self):
length = int(self.headers.get("Content-Length", "0"))
body = json.loads(self.rfile.read(length) or b"{}")
_Handler.seen.append((self.path, self.headers.get("Authorization", "")))
self.send_response(200 if body.get("method") == "initialize" else 400)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(b'{"jsonrpc":"2.0","id":1,"result":{}}')
def log_message(self, format, *args): # noqa: A002
pass
@pytest.fixture
def loopback_mcp():
srv = HTTPServer(("127.0.0.1", 0), _Handler)
t = threading.Thread(target=srv.serve_forever, daemon=True)
t.start()
_Handler.seen.clear()
yield srv.server_address[1]
srv.shutdown()
def test_endpoint_reads_server_json_every_call(tmp_path):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url="http://127.0.0.1:1111/ignored")
resolver = _resolver(tmp_path, exe, sj)
assert resolver.endpoint() == Endpoint("http://127.0.0.1:1111/mcp", TOKEN)
sj.write_text(json.dumps({"pid": os.getpid(), "http": "http://127.0.0.1:2222/ignored", "token": "next"}))
assert resolver.endpoint() == Endpoint("http://127.0.0.1:2222/mcp", "next")
assert TOKEN not in repr(resolver.endpoint())
def test_network_probe_reads_server_json_every_call_and_answers(tmp_path, loopback_mcp):
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url=f"http://127.0.0.1:{loopback_mcp}/ignored")
r = _resolver(tmp_path, exe, sj)
res = r.locate()
first = r.probe(res, effort=Effort.NETWORK)
assert first.answering.state is CheckState.PRESENT and first.answering.value is True
assert _Handler.seen[-1] == ("/mcp", f"Bearer {TOKEN}")
# the vendor moves the port: the next probe must follow without any caller action
sj.write_text(json.dumps({"pid": os.getpid(), "http": "http://127.0.0.1:1/x", "token": TOKEN}), encoding="utf-8")
second = r.probe(res, effort=Effort.NETWORK)
assert second.endpoint.value == "http://127.0.0.1:1/mcp"
assert second.answering.state is CheckState.ABSENT
class _SlowDrip(BaseHTTPRequestHandler):
"""Fast 200 and headers, then one body byte every 0.3 s: each receive is under any per-socket timeout."""
def do_POST(self):
import time as _t
self.send_response(200)
self.send_header("Content-Length", "64")
self.end_headers()
for _ in range(64):
try:
self.wfile.write(b"x")
self.wfile.flush()
except OSError:
return
_t.sleep(0.3)
def log_message(self, format, *args): # noqa: A002
pass
def test_network_probe_honors_one_absolute_deadline(tmp_path):
import time as _t
srv = HTTPServer(("127.0.0.1", 0), _SlowDrip)
threading.Thread(target=srv.serve_forever, daemon=True).start()
try:
exe = tmp_path / "thing"
exe.write_text("", encoding="utf-8")
sj = _server_json(tmp_path, url=f"http://127.0.0.1:{srv.server_address[1]}/x")
r = _resolver(tmp_path, exe, sj)
t0 = _t.monotonic()
pr = r.probe(r.locate(), effort=Effort.NETWORK, deadline_s=0.5)
elapsed = _t.monotonic() - t0
assert elapsed < 2.0, elapsed
assert pr.answering.state is CheckState.PRESENT
finally:
srv.shutdown()