90 lines
3.8 KiB
Python
90 lines
3.8 KiB
Python
"""材料装配的必读优先、UTF-8 字节预算与省略原因;离线纯函数合同。
|
||
|
||
字节期望值按 UTF-8 逐字写死,不由被测函数自身推算,避免同源计算自证。
|
||
"""
|
||
|
||
import dataclasses
|
||
|
||
import pytest
|
||
|
||
from muse.上下文.接口 import 上下文错误, 装配材料
|
||
|
||
|
||
def test_必读优先且可选按原顺序整项加入__1c4a9e() -> None:
|
||
材料 = {"可选甲": "甲文", "必读": "必读文", "可选乙": "乙文"}
|
||
结果 = 装配材料(材料, ("必读",), 字节上限=64)
|
||
assert 结果.入选来源 == ("必读", "可选甲", "可选乙")
|
||
assert 结果.文本 == "必读文\n\n甲文\n\n乙文"
|
||
assert 结果.字节数 == 25 # 三个片段 9+6+6 字节加两处分隔符
|
||
assert 结果.省略 == ()
|
||
with pytest.raises(dataclasses.FrozenInstanceError):
|
||
结果.文本 = "改写"
|
||
|
||
|
||
def test_中文与emoji按utf8字节计数含分隔符__5d1c47() -> None:
|
||
原文 = "第1章:雨。🌧"
|
||
仅必读 = 装配材料({"历史": 原文}, ("历史",), 字节上限=20)
|
||
assert 仅必读.文本 == 原文
|
||
assert 仅必读.字节数 == 20 # 含四字节 emoji
|
||
|
||
材料 = {"历史": 原文, "旁观": "他站着"}
|
||
齐 = 装配材料(材料, ("历史",), 字节上限=31)
|
||
assert 齐.入选来源 == ("历史", "旁观")
|
||
assert 齐.字节数 == 31 # 20 + 分隔符 2 + 9
|
||
assert 齐.文本 == f"{原文}\n\n他站着"
|
||
|
||
缺一字节 = 装配材料(材料, ("历史",), 字节上限=30)
|
||
assert 缺一字节.入选来源 == ("历史",)
|
||
assert 缺一字节.文本 == 原文
|
||
assert 缺一字节.省略 == (("旁观", "BUDGET_EXCEEDED"),)
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
("材料", "必读"),
|
||
[({}, ("孤本第三章",)), ({"孤本第三章": " \n "}, ("孤本第三章",))],
|
||
ids=["missing", "blank"],
|
||
)
|
||
def test_必读缺失或空白拒绝__a7e903(材料: dict[str, str], 必读: tuple[str, ...]) -> None:
|
||
with pytest.raises(上下文错误) as 异常:
|
||
装配材料(材料, 必读, 字节上限=64)
|
||
assert 异常.value.错误码 == "CONTEXT_REQUIRED_MISSING"
|
||
assert "孤本第三章" in 异常.value.说明
|
||
|
||
|
||
def test_必读整体超预算拒绝__c9e51f() -> None:
|
||
材料 = {"甲": "必读甲", "乙": "必读乙", "可选": "可选丙"}
|
||
with pytest.raises(上下文错误) as 异常:
|
||
装配材料(材料, ("甲", "乙"), 字节上限=19)
|
||
assert 异常.value.错误码 == "CONTEXT_BUDGET_EXCEEDED"
|
||
assert "20" in 异常.value.说明
|
||
|
||
恰好 = 装配材料(材料, ("甲", "乙"), 字节上限=20) # 9 + 分隔符 2 + 9
|
||
assert 恰好.入选来源 == ("甲", "乙")
|
||
assert 恰好.字节数 == 20
|
||
assert 恰好.省略 == (("可选", "BUDGET_EXCEEDED"),)
|
||
|
||
|
||
def test_可选空白与超预算分别给出省略原因__4f8ab2() -> None:
|
||
材料 = {"必读": "必读文", "空白": " ", "太长": "长" * 40, "入选": "短文"}
|
||
结果 = 装配材料(材料, ("必读",), 字节上限=17) # 9 + 分隔符 2 + 6
|
||
assert 结果.入选来源 == ("必读", "入选")
|
||
assert 结果.省略 == (("空白", "EMPTY"), ("太长", "BUDGET_EXCEEDED"))
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
("字节上限", "必读"),
|
||
[(0, ("必读",)), (-3, ("必读",)), (True, ("必读",)), (64, ("必读", "必读"))],
|
||
ids=["zero", "negative", "boolean", "duplicate"],
|
||
)
|
||
def test_非法预算或重复必读身份拒绝__e2168c(字节上限: int, 必读: tuple[str, ...]) -> None:
|
||
with pytest.raises(上下文错误) as 异常:
|
||
装配材料({"必读": "必读文"}, 必读, 字节上限=字节上限)
|
||
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
|
||
|
||
|
||
def test_原文不裁剪空白且按原字节保留__b4d7a1() -> None:
|
||
原文 = " 第1章 \n雨还在下。\t\n"
|
||
结果 = 装配材料({"历史": 原文}, ("历史",), 字节上限=29)
|
||
assert 结果.文本 == 原文
|
||
assert 结果.字节数 == 29
|