NODEDC_PLATFORM/infra/deploy-runner/test_engine_mcp_execution_p...

326 lines
13 KiB
Python

import hashlib
import importlib.machinery
import importlib.util
import io
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from contextlib import redirect_stdout
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = (
SCRIPT_DIR / "build-engine-mcp-execution-profile-decoder-artifact.mjs"
)
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-mcp-execution-profile-decoder-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_mcp_execution_profile_decoder",
str(RUNNER_PATH),
)
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
RUNNER = load_runner()
class EngineMcpExecutionProfileDecoderTest(unittest.TestCase):
def require_current_target_source(self):
for relative_path, expected in (
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_TARGET_SHA256.items()
):
path = ENGINE_ROOT / relative_path
if (
not path.is_file()
or hashlib.sha256(path.read_bytes()).hexdigest() != expected
):
self.skipTest(
"execution profile decoder source has advanced "
"to its exact successor"
)
def build(self, artifact_dir):
environment = os.environ.copy()
environment["NODEDC_ENGINE_SOURCE_ROOT"] = str(ENGINE_ROOT)
environment["NODEDC_DEPLOY_ARTIFACT_DIR"] = str(artifact_dir)
completed = subprocess.run(
["node", str(BUILDER_PATH), PATCH_ID],
check=True,
capture_output=True,
text=True,
env=environment,
)
return json.loads(completed.stdout)
def test_builder_emits_exact_deterministic_two_file_slice(self):
self.require_current_target_source()
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-profile-decoder-"
) as directory:
root = Path(directory)
first = self.build(root / "first")
second = self.build(root / "second")
first_artifact = Path(first["artifact"])
second_artifact = Path(second["artifact"])
self.assertEqual(first_artifact.read_bytes(), second_artifact.read_bytes())
self.assertEqual(
first["sha256"],
hashlib.sha256(first_artifact.read_bytes()).hexdigest(),
)
self.assertEqual(first["services"], ["nodedc-backend"])
self.assertEqual(first["valuesIncluded"], False)
self.assertEqual(first["rawExecutionDataIncluded"], False)
self.assertEqual(
tuple(first["entries"]),
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_ARTIFACT_ENTRIES,
)
extract = root / "extract"
with tarfile.open(first_artifact, "r:gz") as archive:
archive.extractall(extract, filter="data")
entries = tuple(
(extract / "files.txt").read_text(encoding="utf-8").splitlines()
)
payload = extract / "payload"
self.assertTrue(
RUNNER.is_engine_mcp_execution_profile_decoder_slice(
"engine",
entries,
)
)
self.assertFalse(
RUNNER.is_engine_provider_target_host_policy_slice(
"engine",
entries,
)
)
self.assertEqual(
RUNNER.component_services("engine", entries),
("nodedc-backend",),
)
self.assertEqual(
RUNNER.component_healthchecks(
"engine",
entries,
("nodedc-backend",),
),
("http://127.0.0.1:3001/health",),
)
RUNNER.validate_engine_mcp_execution_profile_decoder_slice(
payload,
entries,
)
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-profile-plan-"
) as plan_directory:
loaded = RUNNER.load_artifact(
first_artifact,
Path(plan_directory),
)
self.assertEqual(loaded[0]["component"], "engine")
self.assertEqual(tuple(loaded[1]), entries)
def test_preflight_requires_exact_predecessor_and_absent_descriptor(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-profile-preflight-"
) as directory:
root = Path(directory)
relative_path = next(
iter(
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_PREDECESSOR_SHA256
)
)
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("predecessor\n", encoding="utf-8")
expected = (
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_PREDECESSOR_SHA256[
relative_path
]
)
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value=expected),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = (
RUNNER.preflight_engine_mcp_execution_profile_decoder_predecessor()
)
self.assertEqual(
result["mode"],
"exact-flatted-numeric-string-preservation",
)
descriptor = (
root / RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_DESCRIPTOR_REL
)
descriptor.parent.mkdir(parents=True, exist_ok=True)
descriptor.write_text("{}\n", encoding="utf-8")
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value=expected),
):
with self.assertRaises(RUNNER.DeployError):
RUNNER.preflight_engine_mcp_execution_profile_decoder_predecessor()
def test_plan_renders_exact_external_mcp_boundary(self):
self.require_current_target_source()
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-profile-plan-"
) as directory:
root = Path(directory)
built = self.build(root / "artifacts")
artifact = Path(built["artifact"])
live_root = root / "live"
live_root.mkdir()
preflight = {
"mode": "exact-flatted-numeric-string-preservation",
"predecessor_sha256": dict(
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_PREDECESSOR_SHA256
),
"target_sha256": dict(
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_TARGET_SHA256
),
"new_paths": tuple(
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_NEW_PATHS
),
"backend_mode": "verified-derived-retry",
}
output = io.StringIO()
with (
mock.patch.object(RUNNER, "validate_artifact_location"),
mock.patch.object(RUNNER, "ensure_layout"),
mock.patch.object(RUNNER, "TMP_DIR", root),
mock.patch.object(RUNNER, "component_root", return_value=live_root),
mock.patch.object(
RUNNER,
"component_compose_root",
return_value=live_root,
),
mock.patch.object(
RUNNER,
"preflight_engine_mcp_execution_profile_decoder_predecessor",
return_value=preflight,
),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(RUNNER, "state_has_sha", return_value=False),
mock.patch.object(RUNNER, "state_has_patch_id", return_value=False),
redirect_stdout(output),
):
RUNNER.plan_artifact(artifact)
plan = output.getvalue()
self.assertIn("services=nodedc-backend", plan)
self.assertIn(
"engine_mcp_observability_transition="
"exact-flatted-numeric-string-preservation",
plan,
)
self.assertIn("engine_mcp_surface=external-codex", plan)
self.assertIn("engine_mcp_profile_values_included=no", plan)
self.assertIn("mcp_nginx=untouched", plan)
self.assertIn("embedded_ai_workspace=untouched", plan)
self.assertIn(
"engine_mcp_profile_decoder_predecessor_state"
f"[{RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_DESCRIPTOR_REL}]="
"absent",
plan,
)
self.assertIn("state=new", plan)
def test_healthchecks_dispatch_safe_profile_acceptance(self):
entries = RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_ARTIFACT_ENTRIES
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-profile-health-"
) as directory:
root = Path(directory)
for relative_path in entries:
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("target\n", encoding="utf-8")
def target_hash(path):
relative_path = Path(path).relative_to(root).as_posix()
return (
RUNNER.ENGINE_MCP_EXECUTION_PROFILE_DECODER_TARGET_SHA256[
relative_path
]
)
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=target_hash),
mock.patch.object(RUNNER, "healthcheck_compose_service"),
mock.patch.object(RUNNER, "component_healthchecks", return_value=()),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(
RUNNER,
"accept_engine_mcp_execution_profile_decoder_runtime",
return_value={"live": "accepted"},
) as acceptance,
mock.patch.object(RUNNER, "healthcheck_container"),
):
RUNNER.run_healthchecks(
"engine",
entries,
("nodedc-backend",),
)
acceptance.assert_called_once_with()
def test_live_acceptance_uses_safe_profile_contract(self):
self.require_current_target_source()
expected_live = (
"engine-mcp-execution-profile-decoder:"
"flatted-numeric-strings:safe-profile:v1"
)
with (
mock.patch.object(RUNNER, "component_root", return_value=ENGINE_ROOT),
mock.patch.object(
RUNNER,
"engine_backend_container_id",
return_value="backend",
),
mock.patch.object(
RUNNER,
"run_engine_backend_probe",
return_value=expected_live,
) as backend_probe,
):
result = RUNNER.accept_engine_mcp_execution_profile_decoder_runtime()
self.assertEqual(result["live"], expected_live)
self.assertEqual(
backend_probe.call_args.args[1],
"Engine MCP execution profile decoder",
)
probe_source = backend_probe.call_args.args[0][-1]
self.assertIn("module.toSafeNodeOutputProfile", probe_source)
self.assertIn("profile.valuesIncluded!==false", probe_source)
self.assertIn(".json.fact", probe_source)
if __name__ == "__main__":
unittest.main(verbosity=2)