consolidation of some of the modules, localization fixes, product advisories work, qa work
This commit is contained in:
Binary file not shown.
Binary file not shown.
64
tests/supply-chain/tools/canonicalize_json.py
Normal file
64
tests/supply-chain/tools/canonicalize_json.py
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Deterministic JSON parsing and canonicalization helpers for supply-chain tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
class DuplicateKeyError(ValueError):
|
||||
"""Raised when JSON object contains duplicate keys."""
|
||||
|
||||
|
||||
def _strict_object_pairs_hook(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
|
||||
seen: set[str] = set()
|
||||
result: dict[str, Any] = {}
|
||||
for key, value in pairs:
|
||||
if key in seen:
|
||||
raise DuplicateKeyError(f"Duplicate key detected: {key}")
|
||||
seen.add(key)
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def parse_json_strict(text: str) -> Any:
|
||||
"""Parse JSON and reject duplicate keys deterministically."""
|
||||
return json.loads(text, object_pairs_hook=_strict_object_pairs_hook)
|
||||
|
||||
|
||||
def canonicalize_value(value: Any) -> str:
|
||||
"""
|
||||
Canonicalize JSON value with deterministic ordering.
|
||||
|
||||
This is a strict deterministic serializer used for test invariants.
|
||||
"""
|
||||
return json.dumps(
|
||||
value,
|
||||
ensure_ascii=False,
|
||||
separators=(",", ":"),
|
||||
sort_keys=True,
|
||||
)
|
||||
|
||||
|
||||
def canonicalize_text(text: str) -> str:
|
||||
"""Parse and canonicalize a JSON document."""
|
||||
return canonicalize_value(parse_json_strict(text))
|
||||
|
||||
|
||||
def sha256_hex(value: str) -> str:
|
||||
"""Compute hex SHA-256 digest for canonical payload tracking."""
|
||||
return hashlib.sha256(value.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CanonicalResult:
|
||||
canonical_json: str
|
||||
sha256: str
|
||||
|
||||
|
||||
def canonical_result_from_text(text: str) -> CanonicalResult:
|
||||
canonical = canonicalize_text(text)
|
||||
return CanonicalResult(canonical_json=canonical, sha256=sha256_hex(canonical))
|
||||
102
tests/supply-chain/tools/emit_artifacts.py
Normal file
102
tests/supply-chain/tools/emit_artifacts.py
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Artifact and JUnit emitters for deterministic supply-chain hardening lanes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import pathlib
|
||||
import xml.etree.ElementTree as et
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterable
|
||||
|
||||
|
||||
def _write_json(path: pathlib.Path, payload: Any) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("w", encoding="utf-8", newline="\n") as handle:
|
||||
json.dump(payload, handle, sort_keys=True, indent=2, ensure_ascii=False)
|
||||
handle.write("\n")
|
||||
|
||||
|
||||
def _write_text(path: pathlib.Path, content: str) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(content, encoding="utf-8", newline="\n")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestCaseResult:
|
||||
suite: str
|
||||
name: str
|
||||
passed: bool
|
||||
duration_seconds: float = 0.0
|
||||
failure_message: str | None = None
|
||||
|
||||
|
||||
def write_junit(path: pathlib.Path, test_cases: Iterable[TestCaseResult]) -> None:
|
||||
cases = list(test_cases)
|
||||
failures = sum(0 if case.passed else 1 for case in cases)
|
||||
|
||||
suite = et.Element(
|
||||
"testsuite",
|
||||
attrib={
|
||||
"name": "supply-chain-hardening",
|
||||
"tests": str(len(cases)),
|
||||
"failures": str(failures),
|
||||
"errors": "0",
|
||||
"skipped": "0",
|
||||
},
|
||||
)
|
||||
|
||||
for case in sorted(cases, key=lambda item: (item.suite, item.name)):
|
||||
node = et.SubElement(
|
||||
suite,
|
||||
"testcase",
|
||||
attrib={
|
||||
"classname": case.suite,
|
||||
"name": case.name,
|
||||
"time": f"{case.duration_seconds:.3f}",
|
||||
},
|
||||
)
|
||||
if not case.passed:
|
||||
failure = et.SubElement(node, "failure", attrib={"type": "assertion"})
|
||||
failure.text = case.failure_message or "failure"
|
||||
|
||||
tree = et.ElementTree(suite)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
tree.write(path, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
|
||||
def record_failure(
|
||||
*,
|
||||
lane_output_dir: pathlib.Path,
|
||||
case_id: str,
|
||||
seed: int,
|
||||
payload_text: str,
|
||||
error_class: str,
|
||||
message: str,
|
||||
details: dict[str, Any] | None = None,
|
||||
canonical_diff_patch: str | None = None,
|
||||
) -> pathlib.Path:
|
||||
"""
|
||||
Write deterministic failure artifacts for replay.
|
||||
|
||||
Returns the failure directory path.
|
||||
"""
|
||||
failure_dir = lane_output_dir / "failures" / case_id
|
||||
failure_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
_write_text(failure_dir / "failing_case.json", payload_text)
|
||||
_write_text(failure_dir / "hypothesis_seed.txt", f"{seed}\n")
|
||||
|
||||
diagnostic_payload: dict[str, Any] = {
|
||||
"caseId": case_id,
|
||||
"errorClass": error_class,
|
||||
"message": message,
|
||||
}
|
||||
if details:
|
||||
diagnostic_payload["details"] = details
|
||||
_write_json(failure_dir / "diagnostic_blob.json", diagnostic_payload)
|
||||
|
||||
if canonical_diff_patch is not None:
|
||||
_write_text(failure_dir / "canonical_diff.patch", canonical_diff_patch)
|
||||
|
||||
return failure_dir
|
||||
Reference in New Issue
Block a user