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

357 lines
14 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-plan-materialization-artifact.mjs"
)
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-mcp-execution-plan-materialization-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_mcp_execution_plan_materialization",
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 EngineMcpExecutionPlanMaterializationTest(unittest.TestCase):
def require_current_target_source(self):
for relative_path, expected in (
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_TARGET_SHA256.items()
):
if relative_path == RUNNER.ENGINE_NODE_INTELLIGENCE_DESCRIPTOR_REL:
continue
path = ENGINE_ROOT / relative_path
if (
not path.is_file()
or hashlib.sha256(path.read_bytes()).hexdigest() != expected
):
self.skipTest(
"execution plan materialization source has advanced"
)
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_backend_only_slice(self):
self.require_current_target_source()
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-execution-plan-materialization-"
) 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["services"], ["nodedc-backend"])
self.assertEqual(first["mcpVersion"], "0.9.0")
self.assertEqual(
first["providerLogicAuthority"],
"trusted-provider-package",
)
self.assertEqual(
first["unmanagedGraphPolicy"],
"explicit-adoption-required",
)
self.assertEqual(
tuple(first["entries"]),
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_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_plan_materialization_slice(
"engine",
entries,
)
)
self.assertFalse(
RUNNER.is_engine_mcp_telemetry_catalog_slice("engine", entries)
)
self.assertEqual(
RUNNER.component_services("engine", entries),
("nodedc-backend",),
)
RUNNER.validate_engine_mcp_execution_plan_materialization_slice(
payload,
entries,
)
node_intelligence_descriptor = json.loads(
(
payload / RUNNER.ENGINE_NODE_INTELLIGENCE_DESCRIPTOR_REL
).read_text(encoding="utf-8")
)
self.assertEqual(
node_intelligence_descriptor["source"]["gatewaySha256"],
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_TARGET_SHA256[
RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
],
)
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-execution-plan-load-"
) as load_directory:
loaded = RUNNER.load_artifact(
first_artifact,
Path(load_directory),
)
self.assertEqual(tuple(loaded[1]), entries)
def test_preflight_requires_035_foundation_and_absent_new_paths(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-execution-plan-preflight-"
) as directory:
root = Path(directory)
hashes = {}
for mapping in (
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_PREDECESSOR_SHA256,
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_FOUNDATION_SHA256,
):
for relative_path, expected in mapping.items():
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("installed\n", encoding="utf-8")
hashes[path] = expected
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(
RUNNER,
"sha256_file",
side_effect=lambda path: hashes[Path(path)],
),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = (
RUNNER
.preflight_engine_mcp_execution_plan_materialization_predecessor()
)
self.assertEqual(
result["mode"],
"telemetry-catalog-v1-to-execution-plan-materialization-v1",
)
self.assertEqual(
result["foundation_sha256"],
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_FOUNDATION_SHA256,
)
new_path = (
root
/ RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_NEW_PATHS[0]
)
new_path.parent.mkdir(parents=True, exist_ok=True)
new_path.write_text("{}\n", encoding="utf-8")
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(
RUNNER,
"sha256_file",
side_effect=lambda path: hashes[Path(path)],
),
):
with self.assertRaises(RUNNER.DeployError):
(
RUNNER
.preflight_engine_mcp_execution_plan_materialization_predecessor()
)
def test_plan_renders_external_two_phase_boundary(self):
self.require_current_target_source()
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-execution-plan-plan-"
) as directory:
root = Path(directory)
artifact = Path(self.build(root / "artifacts")["artifact"])
live_root = root / "live"
live_root.mkdir()
preflight = {
"mode": "telemetry-catalog-v1-to-execution-plan-materialization-v1",
"predecessor_sha256": dict(
RUNNER
.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_PREDECESSOR_SHA256
),
"foundation_sha256": dict(
RUNNER
.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_FOUNDATION_SHA256
),
"target_sha256": dict(
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_TARGET_SHA256
),
"new_paths": tuple(
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_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_plan_materialization_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_version=0.9.0", plan)
self.assertIn("engine_mcp_surface=external-codex", plan)
self.assertIn(
"engine_mcp_provider_logic_authority=trusted-provider-package",
plan,
)
self.assertIn(
"engine_mcp_unmanaged_graph_policy=explicit-adoption-required",
plan,
)
self.assertIn("engine_mcp_plan_phase=read-only", plan)
self.assertIn("engine_mcp_apply_phase=opaque-plan-ref-only", plan)
self.assertIn("l2_graph=untouched", plan)
self.assertIn("embedded_ai_workspace=untouched", plan)
self.assertIn("state=new", plan)
def test_healthchecks_dispatch_materialization_acceptance(self):
entries = (
RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_ARTIFACT_ENTRIES
)
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-mcp-execution-plan-health-"
) as directory:
root = Path(directory)
all_hashes = {
**RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_TARGET_SHA256,
**RUNNER.ENGINE_MCP_EXECUTION_PLAN_MATERIALIZATION_FOUNDATION_SHA256,
}
for relative_path in all_hashes:
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 all_hashes[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_plan_materialization_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_probes_provider_neutral_two_phase_contract(self):
expected_live = (
"engine-mcp-execution-plan-materialization:"
"0.9.0:provider-package-authority:two-phase:v1"
)
with (
mock.patch.object(RUNNER, "component_root", return_value=ENGINE_ROOT),
mock.patch.object(
RUNNER,
"validate_engine_mcp_execution_plan_materialization_slice",
),
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_plan_materialization_runtime()
)
self.assertEqual(result["live"], expected_live)
self.assertEqual(
backend_probe.call_args.args[1],
"Engine MCP execution plan materialization",
)
probe_source = backend_probe.call_args.args[0][-1]
self.assertIn(
"engine_plan_l2_execution_plan_materialization",
probe_source,
)
self.assertIn("unmanaged_existing", probe_source)
self.assertIn("additionalProperties!==false", probe_source)
if __name__ == "__main__":
unittest.main(verbosity=2)