Files
config-atlas/tests/test_effective_config.py
tegwick 4620244f39
Some checks failed
validate-registry / validate (push) Has been cancelled
feat(explain): complete ATLAS-WP-0004 — graph edges, blast-radius, determinism tests
T05: tests/test_effective_config.py (6 tests) — order-independence, most-specific
winner, no value/secret leak; wired into make validate + CI.
T04: tools/blast_radius.py + make blast-radius — consumers, transitive dependents
(cycle-safe), secret refs, fan-out risk band.
T03: tools/config_graph.py + make graph/graph-query — emit config-typed edges to
registry/indexes/graph.yaml (queryable by surface id); staleness check in the gate.

WP-0004 finished (5/5). Read-first control-plane MVP complete: explain, graph,
and blast-radius over the seeded surfaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 00:16:58 +02:00

98 lines
3.6 KiB
Python

"""Determinism and no-value-leak tests for the effective-config resolver
(ATLAS-WP-0004-T05).
Runnable with `python3 -m unittest discover -s tests` (stdlib) or pytest.
Proves the override path is deterministic / order-independent (consistent with
the merge-rule + CUE-unification rationale, research §3.3) and that no live or
secret value ever appears in explain output.
"""
import random
import sys
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "tools"))
from effective_config import LAYER_INDEX, find_entry, load_entry, resolve_path # noqa: E402
from config_explain import render # noqa: E402
SURFACES_DIR = ROOT / "registry" / "surfaces"
def all_surface_ids():
return sorted(p.stem for p in SURFACES_DIR.glob("*.md"))
def path_signature(op):
return [(c.layer, c.ref, c.winning, c.overrides) for c in op.contributions]
class TestResolverDeterminism(unittest.TestCase):
def test_order_independent(self):
"""Shuffling sources never changes the resolved path."""
for sid in all_surface_ids():
base = path_signature(resolve_path(find_entry(sid)))
for _ in range(16):
entry = find_entry(sid)
random.shuffle(entry["sources"])
self.assertEqual(
path_signature(resolve_path(entry)), base,
f"{sid}: path changed under source reordering",
)
def test_winning_is_most_specific(self):
"""The winning layer is the highest-rank (most specific) layered source."""
for sid in all_surface_ids():
op = resolve_path(find_entry(sid))
layered = [c for c in op.contributions if c.rank >= 0]
if not layered:
continue
winner = op.winner
self.assertIsNotNone(winner, f"{sid}: no winner among layered sources")
self.assertEqual(
winner.rank, max(c.rank for c in layered),
f"{sid}: winner is not the most specific layer",
)
def test_all_seeded_surfaces_resolve(self):
ids = all_surface_ids()
self.assertGreaterEqual(len(ids), 1)
for sid in ids:
resolve_path(find_entry(sid)) # must not raise
class TestNoValueLeak(unittest.TestCase):
def test_schema_default_never_rendered(self):
"""A surface's declared schema default is contract metadata and must not
appear as an effective value in explain output."""
for sid in all_surface_ids():
entry = find_entry(sid)
default = (entry.get("schema") or {}).get("default")
if default is None:
continue
out = render(resolve_path(entry))
self.assertNotIn(
str(default), out,
f"{sid}: schema default leaked into explain output",
)
def test_safety_note_present(self):
for sid in all_surface_ids():
out = render(resolve_path(find_entry(sid)))
self.assertIn("no values shown", out, f"{sid}: missing no-values safety note")
def test_secret_refs_are_references_only(self):
"""depends_on_secret ids appear only on the explicit reference line, never
as a resolved value elsewhere."""
for sid in all_surface_ids():
op = resolve_path(find_entry(sid))
if not op.secret_deps:
continue
out = render(op)
self.assertIn("depends on secret (ref)", out, f"{sid}: secret ref line missing")
if __name__ == "__main__":
unittest.main()