Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 20s
- Add section 9 to PHASE-Z-PIPELINE-STATUS-BOARD.md carving section 3 item (j)
into 8 IMP-95 sub-axes (j1-j8). j1-j5 = trace-only, j6-j8 = guarded.
- Marker grammar: <!-- IMP-95:<axis> -->VALUE<!-- /IMP-95 --> (distinct from
IMP-91 grammar so scripts/update_status_board.py MARKER_RE cannot rewrite
IMP-95 cells).
- Allowed value enum: {pending, trace-only, guarded, active}.
- tests/scripts/test_update_status_board.py: +1 import, +4 module-level
constants, +3 test functions verifying marker presence/count (8), value
domain enum, IMP-91 updater isolation against IMP-95 cells, and IMP-95
regex rewrite idempotence. IMP-91 tests untouched.
- No production-code touched. Default-OFF flag posture preserved; all cells
trace-only or guarded.
113 lines
4.0 KiB
Python
113 lines
4.0 KiB
Python
"""IMP-#91 u14 — unit tests for the status-board marker updater.
|
|
|
|
Exercises ``parse_outcomes`` (nodeid → axis/mdx outcome mapping) and
|
|
``update_board_text`` (idempotent marker rewrite). u15 will wire the CLI
|
|
into the GitHub Actions workflow; these tests guard the contract.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
|
|
import update_status_board as usb # noqa: E402
|
|
|
|
IMP95_BOARD_PATH = (
|
|
REPO_ROOT / "docs" / "architecture" / "PHASE-Z-PIPELINE-STATUS-BOARD.md"
|
|
)
|
|
IMP95_MARKER_RE = re.compile(
|
|
r"(<!-- IMP-95:(j\d+) -->)(.*?)(<!-- /IMP-95 -->)", re.DOTALL
|
|
)
|
|
IMP95_EXPECTED_AXES = {"j1", "j2", "j3", "j4", "j5", "j6", "j7", "j8"}
|
|
IMP95_ALLOWED_VALUES = {"pending", "trace-only", "guarded", "active"}
|
|
|
|
|
|
SAMPLE_REPORT = {
|
|
"tests": [
|
|
{
|
|
"nodeid": "tests/integration/test_multi_mdx_regression.py::test_normalize_snapshot_matches[01]",
|
|
"outcome": "passed",
|
|
},
|
|
{
|
|
"nodeid": "tests/integration/test_multi_mdx_regression.py::test_v4_ranking_snapshot_matches[02]",
|
|
"outcome": "passed",
|
|
},
|
|
{
|
|
"nodeid": "tests/integration/test_multi_mdx_regression.py::test_layout_snapshot_matches[03]",
|
|
"outcome": "failed",
|
|
},
|
|
{
|
|
"nodeid": "tests/integration/test_multi_mdx_regression.py::test_pipeline_run_produces_step20_status[02]",
|
|
"outcome": "passed",
|
|
},
|
|
]
|
|
}
|
|
|
|
|
|
def test_parse_outcomes_maps_known_axes_only() -> None:
|
|
outcomes = usb.parse_outcomes(SAMPLE_REPORT)
|
|
assert outcomes == {
|
|
("F0", "01"): "PASS",
|
|
("F1", "02"): "PASS",
|
|
("F4", "03"): "FAIL",
|
|
}
|
|
|
|
|
|
def test_update_board_text_rewrites_markers() -> None:
|
|
board = "F0/01: <!-- IMP-91:F0:01 -->?<!-- /IMP-91 --> F1/02: <!-- IMP-91:F1:02 -->old<!-- /IMP-91 -->"
|
|
outcomes = {("F0", "01"): "PASS"}
|
|
result = usb.update_board_text(board, outcomes)
|
|
assert "<!-- IMP-91:F0:01 -->PASS<!-- /IMP-91 -->" in result
|
|
assert "<!-- IMP-91:F1:02 -->?<!-- /IMP-91 -->" in result
|
|
|
|
|
|
def test_update_board_text_is_idempotent() -> None:
|
|
board = "<!-- IMP-91:F2:05 -->old<!-- /IMP-91 -->"
|
|
outcomes = {("F2", "05"): "PASS"}
|
|
once = usb.update_board_text(board, outcomes)
|
|
twice = usb.update_board_text(once, outcomes)
|
|
assert once == twice == "<!-- IMP-91:F2:05 -->PASS<!-- /IMP-91 -->"
|
|
|
|
|
|
def test_imp95_markers_present_and_well_formed() -> None:
|
|
"""IMP-95 sub-axis markers all present in section 9 with allowed values."""
|
|
board = IMP95_BOARD_PATH.read_text(encoding="utf-8")
|
|
matches = IMP95_MARKER_RE.findall(board)
|
|
axes = {axis for _, axis, _, _ in matches}
|
|
assert axes == IMP95_EXPECTED_AXES, (
|
|
f"IMP-95 axes drift: expected {IMP95_EXPECTED_AXES}, got {axes}"
|
|
)
|
|
for _, axis, value, _ in matches:
|
|
assert value in IMP95_ALLOWED_VALUES, (
|
|
f"IMP-95 {axis} value {value!r} outside allowed set {IMP95_ALLOWED_VALUES}"
|
|
)
|
|
|
|
|
|
def test_imp95_markers_isolated_from_imp91_updater() -> None:
|
|
"""`update_board_text` (IMP-91) MUST NOT rewrite IMP-95 markers — distinct closing tag."""
|
|
sample = (
|
|
"<!-- IMP-95:j1 -->trace-only<!-- /IMP-95 --> "
|
|
"<!-- IMP-91:F0:01 -->?<!-- /IMP-91 -->"
|
|
)
|
|
outcomes = {("F0", "01"): "PASS"}
|
|
rewritten = usb.update_board_text(sample, outcomes)
|
|
assert "<!-- IMP-95:j1 -->trace-only<!-- /IMP-95 -->" in rewritten
|
|
assert "<!-- IMP-91:F0:01 -->PASS<!-- /IMP-91 -->" in rewritten
|
|
|
|
|
|
def test_imp95_marker_rewrite_is_idempotent() -> None:
|
|
"""Regex-driven IMP-95 cell rewrite is byte-identical on second application."""
|
|
board = "<!-- IMP-95:j1 -->pending<!-- /IMP-95 -->"
|
|
|
|
def rewrite(text: str, value: str) -> str:
|
|
return IMP95_MARKER_RE.sub(
|
|
lambda m: f"{m.group(1)}{value}{m.group(4)}", text
|
|
)
|
|
|
|
once = rewrite(board, "trace-only")
|
|
twice = rewrite(once, "trace-only")
|
|
assert once == twice == "<!-- IMP-95:j1 -->trace-only<!-- /IMP-95 -->"
|