Build order steps 1-2 of docs/PLAN.md: - pyproject.toml (llm-ingestion-guard, stdlib-only core, extras [ml]/[judge]/[dev]), LICENSE (MIT) - report: Finding/Report/Severity/Source shared type (pure data) - sanitize: carrier stripping (zero-width, BIDI, Unicode-tag, HTML comment, data: URI) with the byte-identical / removes-only invariant - docs/PLAN.md: v1 implementation plan (positioning A, gap-expanded scope, llm-security reuse map) 15 tests passing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K8GmKRCdsPjWYAKWsNgeQS
61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
"""Tests for the shared findings/report type (build order step 1)."""
|
|
from llm_ingestion_guard.report import Finding, Report, Severity, Source, severity_rank
|
|
|
|
|
|
def test_finding_defaults():
|
|
f = Finding(
|
|
label="override:ignore-previous",
|
|
severity=Severity.CRITICAL,
|
|
source=Source.INPUT,
|
|
detector="lexicon",
|
|
)
|
|
assert f.count == 1
|
|
assert f.offset is None
|
|
assert f.evidence is None
|
|
assert f.severity is Severity.CRITICAL
|
|
assert f.source is Source.INPUT
|
|
|
|
|
|
def test_finding_is_frozen():
|
|
f = Finding(label="x", severity=Severity.LOW, source=Source.OUTPUT, detector="d")
|
|
try:
|
|
f.label = "y" # type: ignore[misc]
|
|
except Exception:
|
|
return
|
|
raise AssertionError("Finding must be immutable (frozen)")
|
|
|
|
|
|
def test_report_empty():
|
|
r = Report()
|
|
assert r.found is False
|
|
assert r.max_severity() is None
|
|
assert r.counts()[Severity.CRITICAL] == 0
|
|
|
|
|
|
def test_report_found_and_max_severity():
|
|
r = Report()
|
|
r.add(Finding(label="a", severity=Severity.LOW, source=Source.INPUT, detector="d"))
|
|
r.add(Finding(label="b", severity=Severity.CRITICAL, source=Source.INPUT, detector="d"))
|
|
r.add(Finding(label="c", severity=Severity.HIGH, source=Source.INPUT, detector="d"))
|
|
assert r.found is True
|
|
assert r.max_severity() is Severity.CRITICAL
|
|
|
|
|
|
def test_report_counts():
|
|
r = Report()
|
|
r.extend([
|
|
Finding(label="a", severity=Severity.HIGH, source=Source.INPUT, detector="d"),
|
|
Finding(label="b", severity=Severity.HIGH, source=Source.INPUT, detector="d"),
|
|
Finding(label="c", severity=Severity.LOW, source=Source.OUTPUT, detector="d"),
|
|
])
|
|
counts = r.counts()
|
|
assert counts[Severity.HIGH] == 2
|
|
assert counts[Severity.LOW] == 1
|
|
assert counts[Severity.CRITICAL] == 0
|
|
|
|
|
|
def test_severity_rank_ordering():
|
|
assert severity_rank(Severity.CRITICAL) > severity_rank(Severity.HIGH)
|
|
assert severity_rank(Severity.HIGH) > severity_rank(Severity.MEDIUM)
|
|
assert severity_rank(Severity.MEDIUM) > severity_rank(Severity.LOW)
|
|
assert severity_rank(Severity.LOW) > severity_rank(Severity.INFO)
|