from __future__ import annotations import importlib.util import json from pathlib import Path import subprocess import sys import tempfile import unittest from unittest.mock import patch ROOT = Path(__file__).resolve().parents[1] SCRIPT = ROOT / "tools/checks/runtime-image-smoke.py" SPEC = importlib.util.spec_from_file_location("runtime_image_smoke", SCRIPT) assert SPEC is not None and SPEC.loader is not None MODULE = importlib.util.module_from_spec(SPEC) sys.modules[SPEC.name] = MODULE SPEC.loader.exec_module(MODULE) class RuntimeImageSmokeTests(unittest.TestCase): def test_selects_the_exact_platform_digest(self) -> None: with tempfile.TemporaryDirectory(prefix="govoplan-runtime-smoke-") as value: path = Path(value) / "metadata.json" path.write_text( json.dumps( { "index": "registry.example/api@sha256:" + "a" * 64, "platforms": { "linux/amd64": "registry.example/api@sha256:" + "1" * 64, "linux/arm64": "registry.example/api@sha256:" + "2" * 64, }, } ), encoding="utf-8", ) self.assertEqual( "registry.example/api@sha256:" + "2" * 64, MODULE.platform_image(path, "linux/arm64", "API"), ) def test_rejects_mutable_or_missing_platform_images(self) -> None: with tempfile.TemporaryDirectory(prefix="govoplan-runtime-smoke-") as value: path = Path(value) / "metadata.json" path.write_text( json.dumps({"platforms": {"linux/amd64": "registry.example/api:latest"}}), encoding="utf-8", ) with self.assertRaisesRegex(MODULE.SmokeError, "exact sha256"): MODULE.platform_image(path, "linux/amd64", "API") with self.assertRaisesRegex(MODULE.SmokeError, "exact sha256"): MODULE.platform_image(path, "linux/arm64", "API") def test_readiness_fails_immediately_when_container_exits(self) -> None: exited = subprocess.CompletedProcess([], 0, "false\n", "") logs = subprocess.CompletedProcess([], 0, "fatal startup error\n", "") with patch.object(MODULE, "_run", side_effect=(exited, logs)): with self.assertRaisesRegex( MODULE.SmokeError, "container exited before readiness: fatal startup error", ): MODULE._wait_for( "WebUI", lambda: self.fail("probe must not run for an exited container"), timeout=60, container="web", ) def test_smoke_supplies_the_packaged_web_upstream_and_schema_contract(self) -> None: source = SCRIPT.read_text(encoding="utf-8") self.assertIn('"--network-alias",\n "load-balancer"', source) self.assertIn("'core_system_settings'", source) self.assertIn("'core_runtime_nodes'", source) if __name__ == "__main__": unittest.main()