"""Tests for the deterministic CRA finding -> Annex I requirement mapper.""" from compliance.services.cra_finding_mapper import ( ScannerFinding, map_finding, assess_findings, assess_findings_payload, ) def test_hardcoded_credentials_cwe_maps_to_credential_requirement(): m = map_finding(ScannerFinding(id="f1", title="Hardcoded API key", cwe="CWE-798", severity="high")) assert m.primary_requirement == "CRA-AI-9" assert "CRA-AI-8" in m.requirement_ids assert not m.unmapped assert m.annex_anchor # spine carries the Annex anchor def test_default_password_is_critical_and_carries_measure_M542(): m = map_finding(ScannerFinding(id="f2", title="Universal default password", cwe="CWE-259", severity="critical")) assert m.primary_requirement == "CRA-AI-8" assert m.risk_level == "CRITICAL" assert "M542" in m.measures # default-password change measure from the spine def test_weak_tls_via_keyword_maps_to_transport_crypto(): m = map_finding(ScannerFinding(id="f3", title="TLS 1.0 enabled", description="weak protocol", severity="high")) assert m.primary_requirement == "CRA-AI-15" assert not m.unmapped def test_dependency_cve_without_cwe_maps_to_dependency_monitoring(): m = map_finding(ScannerFinding(id="f4", title="lodash 4.17.4 has known CVE", category="dependency", severity="high")) assert m.primary_requirement == "CRA-AI-22" def test_severity_derived_from_cvss_when_missing(): m = map_finding(ScannerFinding(id="f5", title="cleartext transmission", cwe="CWE-319", cvss=9.4)) # finding sev (CRITICAL from cvss) escalates over requirement sev assert m.risk_level == "CRITICAL" def test_risk_is_max_of_finding_and_requirement_severity(): # low-severity finding but the requirement (CRA-AI-8, CRITICAL) dominates m = map_finding(ScannerFinding(id="f6", title="default password", severity="low")) assert m.primary_requirement == "CRA-AI-8" assert m.risk_level == "CRITICAL" def test_unmapped_finding_is_flagged_not_invented(): m = map_finding(ScannerFinding(id="f7", title="zzz unrelated note", severity="low")) assert m.unmapped assert m.requirement_ids == [] def test_assessment_aggregates_and_coverage(): findings = [ ScannerFinding(id="a", cwe="CWE-259", severity="critical"), # CRA-AI-8 ScannerFinding(id="b", title="TLS 1.0", severity="high"), # CRA-AI-15 ScannerFinding(id="c", title="zzz nothing", severity="low"), # unmapped ] a = assess_findings(findings) assert a.findings_total == 3 assert sum(a.by_risk.values()) == 3 assert "CRA-AI-8" in a.requirements_touched assert "c" in a.unmapped_findings assert a.coverage_pct == round(100.0 * 2 / 3, 1) assert any(meas["id"] == "M542" for meas in a.open_measures) assert all("description" in meas for meas in a.open_measures) def test_payload_entry_is_json_serializable_and_deterministic(): payload = {"findings": [ {"id": "x", "cwe": "CWE-798", "severity": "high"}, {"id": "y", "type": "dependency", "name": "openssl CVE-2024-x", "severity": "critical"}, ]} r1 = assess_findings_payload(payload) r2 = assess_findings_payload(payload) assert r1 == r2 # deterministic assert r1["findings_total"] == 2 assert isinstance(r1["mapped"], list) and isinstance(r1["mapped"][0], dict) assert r1["mapped"][0]["primary_requirement"] == "CRA-AI-9" def test_empty_payload_is_safe(): r = assess_findings_payload({}) assert r["findings_total"] == 0 assert r["coverage_pct"] == 0.0