aps-agent/tests/golden/test_evidence_item.py

80 lines
3.0 KiB
Python
Raw Permalink Normal View History

# 统一 EvidenceItem 与可追溯链黄金测试(plan.md §3.4 / 矩阵 114 行)
# ============================================================
# 覆盖:构造/序列化、链确定性、元素变化断链、ref 解析、schedule-version 兼容。
from __future__ import annotations
import pytest
from server.agent_core.evidence import (
EvidenceItem, evidence_ref, parse_evidence_ref, trace_chain, verify_chain,
schedule_version_item,
)
def test_evidence_ref_roundtrip():
"""证据引用:<kind>:<id> 生成与解析往返。"""
ref = evidence_ref("schedule-version", 12)
assert ref == "schedule-version:12"
assert parse_evidence_ref(ref) == ("schedule-version", "12")
with pytest.raises(ValueError):
parse_evidence_ref("no-colon")
def test_evidence_ref_kind_whitelist():
"""未知 kind 拒绝(白名单防注入)。"""
with pytest.raises(ValueError):
evidence_ref("../../etc", "x")
with pytest.raises(ValueError):
EvidenceItem(kind="hack", ref="x")
def test_trace_chain_deterministic():
"""链确定性:同输入同哈希;数量变化断链。"""
items = [
EvidenceItem(kind="run", ref="run-1", engine="CP", seed=42),
EvidenceItem(kind="knowledge", ref="kb-1", knowledgeVersion="v3"),
EvidenceItem(kind="confirm", ref="c-1", confirmId="abc123"),
]
a = trace_chain(items)
b = trace_chain(items)
assert a["chainHash"] == b["chainHash"]
assert a["count"] == 3
assert verify_chain(items, a["chainHash"]) is True
assert verify_chain(items[:-1], a["chainHash"]) is False # 数量变化断链
def test_trace_chain_sensitive_to_content_and_order():
"""内容/顺序变化断链(可复算可追溯)。"""
items = [
EvidenceItem(kind="run", ref="run-1", engine="CP", seed=42),
EvidenceItem(kind="algorithm", ref="alg-1", version="1.2"),
]
base = trace_chain(items)["chainHash"]
# 内容变化(seed 改)
changed = [EvidenceItem(kind="run", ref="run-1", engine="CP", seed=99),
EvidenceItem(kind="algorithm", ref="alg-1", version="1.2")]
assert trace_chain(changed)["chainHash"] != base
# 顺序变化
swapped = list(reversed(items))
assert trace_chain(swapped)["chainHash"] != base
def test_schedule_version_item_compatible():
"""schedule-version 证据项与既有协议兼容。"""
item = schedule_version_item(7, runId="run-9")
assert item.kind == "schedule-version"
assert item.ref == "7"
assert item.version == "7"
ref = evidence_ref(item.kind, item.ref)
assert parse_evidence_ref(ref) == ("schedule-version", "7")
def test_trace_chain_serializes_items():
"""trace_chain 输出 items 为规范化 dict 列表(可复算输入)。"""
items = [EvidenceItem(kind="report", ref="rpt-1", meta={"x": 1})]
out = trace_chain(items)
assert out["items"][0]["kind"] == "report"
assert out["items"][0]["meta"] == {"x": 1}
# 用输出 dict 复算同链
assert trace_chain(out["items"])["chainHash"] == out["chainHash"]