"""Tests for the surgical-rehost harness (harness/rehost.py, docs/46). Fixtures: the demo firmware (built by ``make demo``) is rehosted offline. The real-image probes are skipped when the firmware is absent, and are bounded to one short call each. No hardware, no module, no guest, no network. Run:: python3 -m unittest tests.test_rehost -v """ from __future__ import annotations import contextlib import io import json import os import sys import unittest HERE = os.path.dirname(os.path.abspath(__file__)) TOOL_ROOT = os.path.abspath(os.path.join(HERE, "..")) if TOOL_ROOT not in sys.path: sys.path.insert(0, TOOL_ROOT) from harness.rehost import ( # noqa: E402 DEFAULT_IMAGE, DEMO_ELF, DEMO_FORMAT, REHOST_FORMAT, RehostError, main, parse_hex_bytes, parse_mem_spec, parse_snap_spec, rehost, run_demo, ) def _run_main(argv: list[str]) -> tuple[int, str, str]: out, err = io.StringIO(), io.StringIO() with contextlib.redirect_stdout(out), contextlib.redirect_stderr(err): rc = main(argv) return rc, out.getvalue(), err.getvalue() class SpecTests(unittest.TestCase): def test_parse_hex_bytes_and_mem_spec(self): self.assertEqual(parse_hex_bytes("aa bb cc"), b"\xaa\xbb\xcc") addr, data = parse_mem_spec("0x1000=0102") self.assertEqual((addr, data), (0x1000, b"\x01\x02")) def test_bad_specs_are_clean_errors(self): with self.assertRaises(RehostError): parse_hex_bytes("abc") with self.assertRaises(RehostError): parse_mem_spec("0x1000") with self.assertRaises(RehostError): parse_snap_spec("0x1000") def test_missing_image_is_clean_error(self): with self.assertRaises(RehostError): rehost(image="/nonexistent/fw.bin", entry=0x1000) @unittest.skipUnless(os.path.isfile(DEMO_ELF), "demo firmware not built") class DemoRehostTests(unittest.TestCase): def test_demo_rehost_is_deterministic_and_correct(self): payload = run_demo() self.assertEqual(payload["format"], DEMO_FORMAT) self.assertTrue(payload["ok"]) self.assertEqual(payload["first"]["status"], "return") self.assertEqual(payload["first"]["retval"], payload["expected"]) self.assertEqual(payload["first"]["retval"], payload["second"]["retval"]) def test_rehost_writes_report_and_session(self): import tempfile with tempfile.TemporaryDirectory() as tmp: report = rehost( image=DEMO_ELF, entry="rpc_sum", args=(0x80012000, 4), mem=((0x80012000, b"\x01\x02\x03\x04"),), snap=((0x80012000, 4),), budget=50_000, timeout=20.0, out=tmp, record=True, name="rehost-test", ) self.assertEqual(report["format"], REHOST_FORMAT) self.assertEqual(report["status"], "return") self.assertEqual(report["retval"], 10) self.assertTrue(os.path.isfile(report["report_json"])) self.assertEqual(len(report["snapshots"]), 1) self.assertEqual(report["snapshots"][0]["changed_bytes"], 0) self.assertTrue(report["snapshots"][0]["before_sha256"]) self.assertIn("fidelity", " ".join(report["limits"]).lower()) def test_cli_demo_returns_zero(self): rc, out, _ = _run_main(["demo"]) self.assertEqual(rc, 0) self.assertTrue(json.loads(out)["ok"]) def test_cli_missing_image_returns_two(self): rc, _, err = _run_main(["run", "--image", "/nonexistent/fw.bin", "--entry", "0x1000"]) self.assertEqual(rc, 2) self.assertIn("error:", err) class RealImageProbeTests(unittest.TestCase): """Bounded probes on the shipped 570.144 image; skipped without it.""" @unittest.skipUnless(os.path.isfile(DEFAULT_IMAGE), "570.144 firmware absent") def test_gate_probe_reproduces_invalid_state_without_state(self): report = rehost( image=DEFAULT_IMAGE, profile_path=os.path.join(TOOL_ROOT, "sim", "profiles", "tu104-570.144.json"), entry=0x5B01210, # per-buffer commit gate (from live analysis; numeric only) args=(0,), budget=50_000, timeout=20.0, record=False, name="probe-gate-test", ) self.assertEqual(report["format"], REHOST_FORMAT) self.assertIn(report["status"], ("return", "fault", "budget", "ecall")) # With no engine-context state the gate family returns NV_ERR_INVALID_STATE. self.assertEqual(report["retval"], 0x40) self.assertIn("Not a boot", report["limits"][0]) if __name__ == "__main__": unittest.main()