stage-14: pytest test suite over the worker lines

38 tests covering the pure worker-line logic: Classifyline rules, Routeline
TLP/country/incident-type gates, Sealine seal/unseal round-trip, Proofline
confidence scoring, Mapline CVEResolver escalation, Trainline dataset
well-posedness (the v1/v3 input-signal bugs are now regression-guarded), and
the Scoutline feed parsers. pytest added as a dev extra.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
m17hr1l
2026-05-18 23:36:41 +02:00
parent bc61b9a3a1
commit e504b3dbcf
9 changed files with 403 additions and 0 deletions

55
tests/test_train.py Normal file
View File

@@ -0,0 +1,55 @@
"""Trainline dataset-builder tests — the well-posedness properties."""
from __future__ import annotations
import json
from psyc.lines.train import (
_ex_ioc_extraction,
_ex_severity_classification,
quality_gate,
)
from psyc.models import IncidentType, Severity, TLP
from conftest import make_case
def test_ioc_extraction_is_well_posed():
"""Every IOC in the output must also appear in the input — the v1 bug."""
case = make_case(feed="urlhaus", urls=["http://1.2.3.4:8080/x"], domains=["1.2.3.4"], ips=["1.2.3.4"])
ex = _ex_ioc_extraction(case)
assert ex is not None
output = json.loads(ex.output)
for bucket in output.values():
for ioc in bucket:
assert ioc in ex.input, f"{ioc!r} not derivable from the input"
def test_ioc_extraction_includes_cve_only_cases():
case = make_case(feed="cisa-kev", cves=["CVE-2026-0001"])
ex = _ex_ioc_extraction(case)
assert ex is not None
assert "CVE-2026-0001" in ex.input
def test_severity_input_carries_status_signal():
"""The severity task input must contain the online/offline status (v3 bug)."""
case = make_case(feed="feodo", ips=["1.2.3.4"], severity=Severity.HIGH,
incident_type=IncidentType.BOTNET)
case.source_metadata["status"] = "online"
ex = _ex_severity_classification(case)
assert ex is not None
assert "online" in ex.input
def test_quality_gate_drops_tlp_red():
case = make_case(tlp=TLP.RED, urls=["http://1.2.3.4/x"])
ex = _ex_ioc_extraction(case)
assert ex is not None
assert quality_gate(ex, case) == "tlp_red"
def test_quality_gate_passes_clean_example():
case = make_case(feed="urlhaus", tlp=TLP.GREEN, urls=["http://1.2.3.4/x"], ips=["1.2.3.4"])
ex = _ex_ioc_extraction(case)
assert ex is not None
assert quality_gate(ex, case) is None