test(P70): add CAP-013 regression tests — terraform validate + dedup unit assertions (P1 remediation)
--- ci--- project: acdl phase: 70 milestone: v1.12 status: verify --- /ci--- Code review (P70) flagged 2 P1 testing gaps: 1. No end-to-end terraform validate test for the microservice (the real CAP-013 surface). A future refactor could re-break the dedup and the suite would stay green. 2. No unit test for the _child_id helper / id_remap / dedup merge. Added 6 tests (38 adapter tests total, 522 suite total): - test_microservice_dedup_names_modules_by_child_id: asserts module 'alb' + 'service' appear, expanded sub-ids do NOT. - test_microservice_dedup_rewrites_stack_outputs: service_arn -> module.service, lb_arn -> module.alb. - test_microservice_dedup_rewrites_cross_module_refs: lb_target_group_arn -> module.alb.target_group_arn (not module.alb-targetgroup). - test_microservice_emits_valid_terraform: end-to-end terraform init + validate on the microservice main.tf (locks in CAP-013). - test_single_resource_returns_id_verbatim / test_multi_resource_returns_common_prefix: unit tests for _child_id. P2 nits (noted, not fixed): the ci-vpc-apply/destroy 'if' uses != 'plan' rather than == 'full' (stricter but not exploitable); _child_id docstring could note commonprefix is character-wise. Both are post-hoc.
This commit is contained in:
+91
-2
@@ -9,7 +9,7 @@ import pytest
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from adapters.terraform.adapter import adapt, _tf_value, _ref_expr, _module_name
|
||||
from adapters.terraform.adapter import adapt, _tf_value, _ref_expr, _module_name, _child_id
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
@@ -241,4 +241,93 @@ class TestAdapterEmitsValidTerraform:
|
||||
["terraform", "validate"],
|
||||
cwd=str(tmp_path), capture_output=True, text=True
|
||||
)
|
||||
assert result.returncode == 0, f"terraform validate failed: {result.stderr}"
|
||||
assert result.returncode == 0, f"terraform validate failed: {result.stderr}"
|
||||
|
||||
|
||||
class TestAdapterDedupMultiResourceL1:
|
||||
"""CAP-013 (v1.12, REQ-129): multi-resource L1s (ecs-service, alb) with
|
||||
stack outputs + cross-module refs must dedup to ONE module block named by
|
||||
the composition child id, with all expanded sub-ids rewritten. This is the
|
||||
regression test that locks in the fix — a future refactor that re-breaks
|
||||
the dedup must turn this red."""
|
||||
|
||||
def test_microservice_dedup_names_modules_by_child_id(self, tmp_path):
|
||||
import sys
|
||||
sys.path.insert(0, str(ROOT))
|
||||
from core.contract_resolver import resolve
|
||||
stack = resolve(str(ROOT / "contracts/microservice.yml"))
|
||||
adapt(stack, str(tmp_path))
|
||||
main_tf = (tmp_path / "main.tf").read_text()
|
||||
# The merged modules are named by the child id (alb, service), not the
|
||||
# expanded sub-ids (alb-loadbalancer, service-service, ...).
|
||||
assert 'module "alb" {' in main_tf
|
||||
assert 'module "service" {' in main_tf
|
||||
# Expanded sub-ids must NOT appear as module names.
|
||||
assert 'module "alb-loadbalancer"' not in main_tf
|
||||
assert 'module "alb-targetgroup"' not in main_tf
|
||||
assert 'module "alb-listener"' not in main_tf
|
||||
assert 'module "service-task-definition"' not in main_tf
|
||||
assert 'module "service-service"' not in main_tf
|
||||
|
||||
def test_microservice_dedup_rewrites_stack_outputs(self, tmp_path):
|
||||
"""Stack outputs reference the expanded sub-ids; after dedup they
|
||||
must resolve to the child-id module name."""
|
||||
import sys
|
||||
sys.path.insert(0, str(ROOT))
|
||||
from core.contract_resolver import resolve
|
||||
stack = resolve(str(ROOT / "contracts/microservice.yml"))
|
||||
adapt(stack, str(tmp_path))
|
||||
main_tf = (tmp_path / "main.tf").read_text()
|
||||
# service_arn output references service-service -> module.service
|
||||
assert 'output "service_arn" {\n value = module.service.service_arn' in main_tf
|
||||
# lb_arn output references alb-loadbalancer -> module.alb
|
||||
assert 'output "lb_arn" {\n value = module.alb.lb_arn' in main_tf
|
||||
|
||||
def test_microservice_dedup_rewrites_cross_module_refs(self, tmp_path):
|
||||
"""A ref: input that targets an expanded sub-id (e.g.
|
||||
ref:alb-targetgroup.target_group_arn) must be rewritten to the
|
||||
child-id module (module.alb.target_group_arn)."""
|
||||
import sys
|
||||
sys.path.insert(0, str(ROOT))
|
||||
from core.contract_resolver import resolve
|
||||
stack = resolve(str(ROOT / "contracts/microservice.yml"))
|
||||
adapt(stack, str(tmp_path))
|
||||
main_tf = (tmp_path / "main.tf").read_text()
|
||||
assert "lb_target_group_arn = module.alb.target_group_arn" in main_tf
|
||||
# The un-rewritten expanded form must NOT appear.
|
||||
assert "module.alb-targetgroup" not in main_tf
|
||||
assert "module.service-service" not in main_tf
|
||||
|
||||
def test_microservice_emits_valid_terraform(self, tmp_path):
|
||||
"""CAP-013 end-to-end: the microservice (multi-resource L1s) main.tf
|
||||
passes terraform init + validate. This is the real regression — the
|
||||
v1.11 dedup produced 'No module call name' here."""
|
||||
import sys
|
||||
sys.path.insert(0, str(ROOT))
|
||||
from core.contract_resolver import resolve
|
||||
stack = resolve(str(ROOT / "contracts/microservice.yml"))
|
||||
adapt(stack, str(tmp_path))
|
||||
result = subprocess.run(
|
||||
["terraform", "init", "-backend=false", "-input=false"],
|
||||
cwd=str(tmp_path), capture_output=True, text=True
|
||||
)
|
||||
assert result.returncode == 0, f"terraform init failed: {result.stderr}"
|
||||
result = subprocess.run(
|
||||
["terraform", "validate"],
|
||||
cwd=str(tmp_path), capture_output=True, text=True
|
||||
)
|
||||
assert result.returncode == 0, f"terraform validate failed (CAP-013 regression): {result.stderr}"
|
||||
|
||||
|
||||
class TestChildIdHelper:
|
||||
"""Unit tests for _child_id (the common-prefix heuristic)."""
|
||||
|
||||
def test_single_resource_returns_id_verbatim(self):
|
||||
assert _child_id(["cluster"]) == "cluster"
|
||||
assert _child_id(["kms-key"]) == "kms-key"
|
||||
|
||||
def test_multi_resource_returns_common_prefix(self):
|
||||
# ecs-service expands to service-task-definition + service-service
|
||||
assert _child_id(["service-task-definition", "service-service"]) == "service"
|
||||
# alb expands to alb-loadbalancer + alb-targetgroup + alb-listener
|
||||
assert _child_id(["alb-loadbalancer", "alb-targetgroup", "alb-listener"]) == "alb"
|
||||
Reference in New Issue
Block a user