"""不需要数据库的单元测试:证据校验、格式识别、文字层。"""
from __future__ import annotations
import pytest
from bid_doctor.checklist.extract import check_basis, check_evidence, is_marked
from bid_doctor.core.errors import AppError
from bid_doctor.core.events import _sid # pyright: ignore[reportPrivateUsage]
from bid_doctor.document.formats import detect
from bid_doctor.document.pipeline.text_layer import Sentence, extract
from tests.conftest import FIXTURES
def sent(text: str, runs: list[tuple[int, int, str]] | None = None, seq: int = 1) -> Sentence:
return Sentence(key=f"d:p1:s{seq}", page_no=1, seq=seq, text=text, quads=[[0, 0, 1, 1]], fmt_runs=runs or [])
def test_evidence_checks() -> None:
s = sent("★投标人须具备有效的信息系统集成服务资质证书。")
by_id = {"p1s1": s}
assert check_evidence({"sid": "p1s1", "quote": "投标人须具备有效的信息"}, by_id) is None
assert check_evidence({"sid": "p9s9", "quote": "投标人须具备有效的信息"}, by_id) == "id"
assert check_evidence({"sid": "p1s1", "quote": "投标人须具备"}, by_id) == "quote" # 少于 8 个字
assert check_evidence({"sid": "p1s1", "quote": "这句话是模型改写的"}, by_id) == "quote"
def test_basis_check() -> None:
star = sent("★服务器内存不低于32GB。")
plain = sent("投标人应按要求提供售后服务方案。")
iu = sent("投标人须提供原厂授权书。", [(0, 12, "iu")])
assert check_basis("star", [star], [star], set())
assert not check_basis("star", [plain], [plain], set())
# 斜体下划线只在文件声明过时才算(07 F1)
assert not check_basis("italic_underline", [iu], [iu], set())
assert check_basis("italic_underline", [iu], [iu], {"italic_underline"})
invalid = sent("未提供的,其投标无效。", seq=2)
assert check_basis("explicit_invalid", [plain], [plain, invalid], set())
assert not check_basis("unknown", [star], [star], set())
def test_marker_fallback() -> None:
assert is_marked(sent("★采用国产化CPU芯片。"), set()) == "star"
iu = sent("投标人须提供原厂授权书。", [(0, 12, "iu")])
assert is_marked(iu, set()) is None
assert is_marked(iu, {"italic_underline"}) == "italic_underline"
def test_marked_text_for_model() -> None:
s = sent("须提供授权书,否则无效", [(3, 6, "iu"), (9, 11, "u")])
assert s.marked == "须提供授权书,否则无效"
def test_detect_formats() -> None:
pdf = (FIXTURES / "tender-mini.pdf").read_bytes()
d = detect(pdf, "采购文件.pdf")
assert (d.format, d.page_count, d.extension_mismatch) == ("pdf", 1, False)
assert detect(pdf, "采购文件.doc").extension_mismatch
with pytest.raises(AppError) as e:
detect(b"hello", "a.doc")
assert e.value.code == "file_format_unsupported"
def test_text_layer_normalizes_radicals_and_keys() -> None:
pages = extract("doc1", (FIXTURES / "tender-mini.pdf").read_bytes())
texts = [s.text for s in pages[0].sentences]
assert any("项目" in t for t in texts) and not any("⽬" in t for t in texts) # 「目」不是康熙部首
assert any("彩页" in t for t in texts)
keys = [s.key for s in pages[0].sentences]
assert keys[0] == "doc1:p1:s1" and len(set(keys)) == len(keys)
def test_stream_id_compare() -> None:
assert _sid("1700000000000-1") > _sid("999-5")
assert _sid("bad") == (0, 0)