Files
framebridge/source/tests/test_health.py
T
FrameBridge release automation cdd980e1eb FrameBridge 0.3.4 corresponding-source release
Snapshot assembled only from the signed corresponding-source archive.
Source archive SHA-256: db91a270cdefc4be79056ed38a0b4a16747e1ab130592645eac40fa3809809df
2026-10-29 11:53:40 -04:00

197 lines
9.8 KiB
Python

import copy
import json
from pathlib import Path
import sys
import tempfile
import unittest
from unittest import mock
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "expanded"))
from framebridge_expanded import health
NODE_ID = "51f0acf5-3633-41f6-aea7-4fed5cffcb01"
def snapshots():
return ({"ok": True, "configured": True, "role": "central", "name": "gateway",
"runtime": {"running": True, "ready": True, "node_id": NODE_ID,
"display_context": {"kind": "text"},
"capabilities": {"fbexec": True, "fbterm": True, "cua_tty_module": True, "graphical_cua": False}},
"connection": {"verified": True, "state": "ready"},
"boot": {"configured": True, "enabled": False, "service_state": "active"},
"desired_connection": "connected"},
{"ok": True, "platform_compatibility": {"ok": True, "profile_id": "debian13-amd64-py313", "validation_status": "validated", "issues": []},
"issues": [], "missing_commands": [], "capabilities": {"fbexec": True, "fbterm": True, "cua_tty_module": True, "graphical_cua": False}})
class HealthTests(unittest.TestCase):
def test_release_build_identity_is_retained_without_relabelling_it_validated(self):
status, doctor = snapshots()
doctor["platform_compatibility"]["validation_status"] = "release_build"
value = health.build_report(status, doctor)
self.assertTrue(value["ok"])
self.assertEqual(value["prerequisites"]["validation_status"], "release_build")
self.assertNotEqual(value["prerequisites"]["validation_status"], "validated")
def test_healthy_text_mode_does_not_require_graphical_tools_or_boot_enabled(self):
status, doctor = snapshots()
value = health.build_report(status, doctor, observed_at="2026-10-28T12:00:00+00:00", host="gateway")
self.assertTrue(value["ok"])
self.assertEqual(value["health"], {"state": "healthy", "healthy": True, "issues": []})
self.assertEqual(value["boot"]["policy"], "disabled")
self.assertEqual(value["effective_target"]["node_id"], NODE_ID)
self.assertFalse(value["desktop"]["capture_verified_by_this_report"])
self.assertIsNone(value["software"]["runtime_version"])
def test_query_success_is_not_readiness(self):
status, doctor = snapshots()
status["runtime"].update(running=False, ready=False)
status["connection"].update(verified=False, state="stopped")
value = health.build_report(status, doctor)
self.assertTrue(value["ok"])
self.assertEqual(value["health"]["state"], "degraded")
self.assertFalse(value["health"]["healthy"])
self.assertIn("LOCAL_TOOLS_NOT_READY", value["health"]["issues"])
def test_paused_connection_is_distinct_from_failure(self):
status, doctor = snapshots()
status["desired_connection"] = "disconnected"
status["connection"].update(verified=False, state="stopped")
value = health.build_report(status, doctor)
self.assertEqual(value["health"]["state"], "paused")
self.assertTrue(value["health"]["healthy"])
self.assertEqual(value["health"]["issues"], [])
def test_node_does_not_claim_central_connection_verified(self):
status, doctor = snapshots()
status.update(role="node", desired_connection="not_applicable")
value = health.build_report(status, doctor)
self.assertEqual(value["connection"]["state"], "managed_by_central")
self.assertIsNone(value["connection"]["verified"])
self.assertEqual(value["health"]["state"], "healthy")
def test_requested_pause_does_not_hide_a_still_running_tunnel(self):
status, doctor = snapshots()
status["desired_connection"] = "disconnected"
value = health.build_report(status, doctor)
self.assertEqual(value["health"]["state"], "degraded")
self.assertIn("CONNECTION_INTENT_MISMATCH", value["health"]["issues"])
status["connection"].update(verified=False, state="stopped", alive=True)
value = health.build_report(status, doctor)
self.assertFalse(value["health"]["healthy"])
def test_failed_connection_query_cannot_certify_a_healthy_profile(self):
status, doctor = snapshots()
status["connection"]["ok"] = False
value = health.build_report(status, doctor)
self.assertFalse(value["ok"])
self.assertIsNone(value["health"]["healthy"])
self.assertIn("CONNECTION_STATUS_UNAVAILABLE", value["health"]["issues"])
def test_missing_boot_policy_is_unknown_rather_than_healthy(self):
status, doctor = snapshots()
status["boot"] = {}
value = health.build_report(status, doctor)
self.assertFalse(value["ok"])
self.assertEqual(value["health"]["state"], "unavailable")
def test_missing_runtime_status_is_not_a_stopped_runtime(self):
status, doctor = snapshots()
status["runtime"] = {"status_unavailable": True, "running": False, "ready": False}
value = health.build_report(status, doctor)
self.assertFalse(value["ok"])
self.assertEqual(value["runtime"]["state"], "unavailable")
self.assertEqual(value["health"]["state"], "unavailable")
self.assertIsNone(value["health"]["healthy"])
def test_failed_runtime_query_cannot_certify_ready(self):
status, doctor = snapshots()
status["runtime"]["ok"] = False
value = health.build_report(status, doctor)
self.assertFalse(value["ok"])
self.assertEqual(value["health"]["state"], "unavailable")
def test_failed_profile_query_cannot_claim_unconfigured(self):
value = health.build_report({"ok": False, "configured": False}, None)
self.assertFalse(value["ok"])
self.assertEqual(value["health"]["state"], "unavailable")
def test_missing_diagnostic_result_is_unavailable_not_passed(self):
status, _ = snapshots()
value = health.build_report(status, {})
self.assertFalse(value["ok"])
self.assertEqual(value["health"]["state"], "unavailable")
def test_unconfigured_profile_is_observed_without_running_doctor_or_creating_files(self):
with tempfile.TemporaryDirectory() as directory:
state = Path(directory) / "not-created"
with mock.patch.object(health.runtime, "doctor", side_effect=AssertionError("doctor must not run")):
value = health.collect(state)
self.assertFalse(state.exists())
self.assertTrue(value["ok"])
self.assertEqual(value["health"]["state"], "unconfigured")
self.assertEqual(value["health"]["issues"], [])
self.assertEqual(value["prerequisites"]["state"], "not_run")
def test_diagnostics_failure_retains_status_without_leaking_exception(self):
status, _ = snapshots()
with mock.patch.object(health.lifecycle, "status", return_value=status), \
mock.patch.object(health.runtime, "doctor", side_effect=RuntimeError("secret-access-key")):
value = health.collect(Path("/unused"))
self.assertFalse(value["ok"])
self.assertEqual(value["runtime"]["state"], "ready")
self.assertEqual(value["health"]["state"], "unavailable")
self.assertNotIn("secret-access-key", json.dumps(value))
def test_partial_invalid_profile_does_not_guess_it_is_unconfigured(self):
with mock.patch.object(health.lifecycle, "status", side_effect=ValueError("private-input")), \
mock.patch.object(health.runtime, "doctor") as doctor:
value = health.collect(Path("/unused"))
doctor.assert_not_called()
self.assertFalse(value["ok"])
self.assertEqual(value["health"]["state"], "unavailable")
self.assertNotIn("private-input", json.dumps(value))
def test_allowlist_excludes_connection_material_paths_and_untrusted_free_text(self):
status, doctor = snapshots()
status["tunnel_id"] = "secret-tunnel"
status["runtime"].update(state_dir="/private/secret-path", error="secret-error", access_key="secret-key")
status["runtime"]["display_context"]["authority"] = "/private/secret-authority"
status["connection"].update(message="secret-message", log="/private/secret-log", token="secret-token")
doctor.update(network={"token": "secret-network"}, issues=["secret-issue"])
doctor["platform_compatibility"]["issues"] = ["secret-compatibility"]
result = health.build_report(status, doctor, host="host")
self.assertNotIn("secret-", json.dumps(result))
self.assertEqual(result["prerequisites"]["issue_count"], 1)
self.assertEqual(result["prerequisites"]["compatibility_issue_count"], 1)
def test_prerequisite_failure_is_degraded_without_claiming_no_runtime(self):
status, doctor = snapshots()
doctor.update(ok=False, missing_commands=["tmux"])
value = health.build_report(status, doctor)
self.assertTrue(value["ok"])
self.assertEqual(value["health"]["state"], "degraded")
self.assertEqual(value["runtime"]["state"], "ready")
self.assertEqual(value["prerequisites"]["missing_commands"], ["tmux"])
def test_reports_do_not_modify_snapshots(self):
status, doctor = snapshots()
before = copy.deepcopy((status, doctor))
health.build_report(status, doctor)
self.assertEqual((status, doctor), before)
def test_terminal_output_is_explicit_about_target_and_observation_limit(self):
status, doctor = snapshots()
value = health.build_report(status, doctor, host="gateway")
text = health.render(value)
self.assertIn("Target: LOCAL = this computer (gateway)", text)
self.assertIn(NODE_ID, text)
self.assertIn("capture/input not tested", text)
self.assertIn("not proof of the running version", text)
self.assertIn("not a fleet scan", text)
if __name__ == "__main__":
unittest.main()