muse-agent-example/tests/单元/test_上下文回放清单形状.py

124 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""探索清单形状校验纯函数:顺序、身份、类型与来源绑定的确定性拒绝;离线不连库。"""
from dataclasses import replace
import pytest
from muse.上下文.接口 import 上下文错误, 探索条目, 校验清单, 记录探索
from muse.任务运行.接口 import 工具来源, 工具结果
范围 = {
"work_id": "work-a",
"as_of": 2,
"source_ids": ["doc-1", "plan-1", "fact-lin"],
"documents": [
{
"chapter_id": "ch-1",
"branch_id": "main",
"revision": 1,
"document_id": "doc-1",
"document_hash": "hash-doc-1",
"position": 1,
}
],
"directory_revision": 3,
"authorized_by": "author-a",
"run_purpose": "production",
"content_purpose": "generation",
"target_plan": {
"chapter_id": "ch-3",
"plan_id": "plan-1",
"revision": 1,
"content_hash": "hash-plan-1",
},
"facts": {"system_revision": 5},
}
读取结果 = 工具结果(
内容={"chapter_id": "ch-1", "text": "林深停在码头"},
来源=(
工具来源("doc-1", "1", "hash-doc-1", "visible-text-codepoints/v1:production:generation"),
),
)
def 条目(调用ID: str = "call-1", 工具名: str = "read_history_document", 参数: dict | None = None):
"""用真实读取结果形状构建顺序为 1 的清单条目;覆盖字段由用例自行 replace。"""
return 记录探索(
(),
调用ID,
工具名,
参数 if 参数 is not None else {"chapter_id": "ch-1", "revision": 1},
读取结果,
)[0]
def 顺序清单(*调用: tuple[str, str, dict]) -> tuple[探索条目, ...]:
"""按调用次序经记录探索构建顺序连续的合法清单。"""
清单: tuple[探索条目, ...] = ()
for 调用ID, 工具名, 参数 in 调用:
清单 = 记录探索(清单, 调用ID, 工具名, 参数, 读取结果)
return 清单
def test_顺序断裂拒绝__b7e0b1() -> None:
跳号 = (条目("call-1"), replace(条目("call-2"), 顺序=3))
with pytest.raises(上下文错误) as 异常:
校验清单(跳号, 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
assert "顺序" in 异常.value.说明
倒序 = (replace(条目("call-1"), 顺序=2), replace(条目("call-2"), 顺序=1))
with pytest.raises(上下文错误) as 异常:
校验清单(倒序, 范围)
assert "顺序" in 异常.value.说明
def test_重复调用ID拒绝__b7e0b2() -> None:
重复 = (条目("call-1"), replace(条目("call-1"), 顺序=2))
with pytest.raises(上下文错误) as 异常:
校验清单(重复, 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
assert "call-1" in 异常.value.说明 and "重复" in 异常.value.说明
def test_布尔与类型混淆拒绝__b7e0b3() -> None:
# 顺序是 bool 而不是 int:True 不能冒充 1
with pytest.raises(上下文错误) as 异常:
校验清单((replace(条目("call-1"), 顺序=True),), 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
# 参数里的版本是 bool:JSON Schema 的 integer 不接受布尔
with pytest.raises(上下文错误) as 异常:
校验清单((条目("call-1", 参数={"chapter_id": "ch-1", "revision": True}),), 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
# 条目本身不是探索条目对象:字典形状不能冒充
with pytest.raises(上下文错误) as 异常:
校验清单(({"call_id": "call-1", "tool": "read_history_document"},), 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
def test_缺来源绑定与非法消费哈希拒绝__b7e0b4() -> None:
缺绑定 = (replace(条目("call-1"), 来源引用=()),)
with pytest.raises(上下文错误) as 异常:
校验清单(缺绑定, 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
assert "来源绑定" in 异常.value.说明
非法哈希 = (replace(条目("call-1"), 消费哈希="不是十六进制"),)
with pytest.raises(上下文错误) as 异常:
校验清单(非法哈希, 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"
assert "消费哈希" in 异常.value.说明
def test_合法清单按序通过且空清单拒绝__b7e0b5() -> None:
清单 = 顺序清单(
("call-1", "query_work_plan", {}),
("call-2", "query_facts_as_of", {}),
("call-3", "read_history_document", {"chapter_id": "ch-1", "revision": 1}),
("call-4", "read_history_document", {"chapter_id": "ch-1", "revision": 1, "end": 6}),
)
assert [项.顺序 for 项 in 清单] == [1, 2, 3, 4]
校验清单(清单, 范围) # 不抛异常即通过
with pytest.raises(上下文错误) as 异常:
校验清单((), 范围)
assert 异常.value.错误码 == "CONTEXT_INPUT_INVALID"