Rewrite normalize, cross-IC dedupe, and billing seam (2.49.0).
Downgrade-only clamp and fail-soft coverage stay in src. Inherited copies remain on disk. Self-host billing is NullBilling.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Post-review services load from src; Emmaforo clamp contracts stay downgrade-only."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.models import Finding
|
||||
from backend.services.billing_hook import NullBilling, get_billing
|
||||
from backend.services.dedupe_findings import _build_deduped
|
||||
from backend.services.normalize_findings import _build_normalized
|
||||
import backend.services.billing_hook as billing_hook
|
||||
import backend.services.dedupe_findings as dedupe_findings
|
||||
import backend.services.normalize_findings as normalize_findings
|
||||
|
||||
|
||||
def test_postpass_modules_are_src():
|
||||
for mod, name in (
|
||||
(normalize_findings, "normalize_findings.py"),
|
||||
(dedupe_findings, "dedupe_findings.py"),
|
||||
(billing_hook, "billing_hook.py"),
|
||||
):
|
||||
path = Path(mod.__file__).resolve()
|
||||
assert path.name == name
|
||||
assert "src" in path.parts
|
||||
assert "Native Periscope overlay" not in path.read_text(encoding="utf-8")[:500]
|
||||
|
||||
|
||||
def test_self_host_billing_is_null():
|
||||
hook = get_billing()
|
||||
assert isinstance(hook, NullBilling)
|
||||
assert hook.credits_for_api_cost(12.0) == 0.0
|
||||
|
||||
|
||||
def test_emmaforo_uart_normalize_cannot_promote_warning():
|
||||
"""U2-001 class: hedged UART abs-max must stay WARNING."""
|
||||
originals = [
|
||||
Finding(
|
||||
designator="U2",
|
||||
mpn="CH340E",
|
||||
finding="5V UART into MCU",
|
||||
why="Unverified: abs-max for PA14 not confirmed",
|
||||
status="WARNING",
|
||||
recommendation="level shift",
|
||||
source_page=11,
|
||||
source_quote="",
|
||||
reference="",
|
||||
)
|
||||
]
|
||||
raw = [{
|
||||
"merged_from": [1],
|
||||
"finding": "CH340E 5V will damage the MCU",
|
||||
"why": "will damage the MCU",
|
||||
"status": "ERROR",
|
||||
"recommendation": "level shift",
|
||||
"change_rationale": "graded ERROR",
|
||||
}]
|
||||
built = _build_normalized(raw, [], originals)
|
||||
assert built is not None
|
||||
kept, _ = built
|
||||
assert kept[0].status == "WARNING"
|
||||
assert kept[0].why.lower().startswith("unverified:")
|
||||
|
||||
|
||||
def test_emmaforo_uart_dedupe_collapses_both_endpoints():
|
||||
originals = [
|
||||
Finding(
|
||||
designator="U2", mpn="CH340E", finding="5V out on UART",
|
||||
why="w", status="ERROR", recommendation="", source_page=11,
|
||||
source_quote="q2", reference="r2",
|
||||
),
|
||||
Finding(
|
||||
designator="U3", mpn="ESP32", finding="PA14 overvoltage",
|
||||
why="w", status="ERROR", recommendation="", source_page=25,
|
||||
source_quote="q3", reference="r3",
|
||||
),
|
||||
]
|
||||
groups = [{
|
||||
"member_indices": [1, 2],
|
||||
"primary_index": 2,
|
||||
"finding": "CH340E 5V into MCU UART pin",
|
||||
"why": "same UART interface",
|
||||
"status": "ERROR",
|
||||
"recommendation": "level shift",
|
||||
"change_rationale": "merged 1+2",
|
||||
}]
|
||||
built = _build_deduped(groups, originals)
|
||||
assert built is not None
|
||||
assert len(built) == 1
|
||||
assert built[0].designator == "U3"
|
||||
assert built[0].source_page == 25
|
||||
Reference in New Issue
Block a user