muse-agent-example/tests/单元/test_方法绑定身份.py
zizi d909d1bd1b 后端实现与用例身份:19 包集成落地并修复收尾缺陷
实现侧:
- 上下文:任务范围拆分为 范围校验/范围授权;索引按可发现口径重建、索引新鲜度改对称差;依赖校验统一快照漂移说明。
- 知识方法:方法与材料读取口径统一;超限方法材料按可选省略,核对路径不再二次计费;删除无合同的读时重算。
- 任务运行:新增 context.usage/tool.denied 事件类型;连接池常驻并在装配生命周期内开关;调用结算与核对分列。
- 效果评测/审校修订/交付连载/作者经验/作品规划:凭据冻结、标定消费、导出补证、事实引文核对等收尾修复。
- 资源加载:能力正文不再夹带索引用的导航注记(该注记此前进入角色与技能的模型提示)。
- 元数据:受保护骨架与代码保护属性对齐;字段校验与内置结构口径同步。
- 基础设施:环境预检进入装配生命周期;数据库连接运行期字段不参与相等比较;索引指纹归一化 jsonb 浮点。
- 删除被替代实现:7 份旧提示词模板与空壳 资料来源 读取器。

用例侧:
- 用例身份与导航元信息迁移;夹具补生命周期、同库暴露与模板封存;
- 本轮定向修复:方法材料省略、事实引文、迁移回执、额度与暂停用例、慢用例超时预算等。
2026-09-18 01:15:00 +08:00

121 lines
4.6 KiB
Python

"""绑定目标的无歧义编解码与旧命令兼容边界。"""
import json
from dataclasses import replace
from types import SimpleNamespace
import pytest
from muse.正式变更.接口 import 作者动作, 变更命令, 固定哈希
from muse.知识方法.方法版本 import 绑定对象依赖
from muse.知识方法.模型 import 方法错误, 绑定命令
from muse.知识方法.绑定身份 import 编码绑定身份, 解析绑定身份
@pytest.mark.case_id("NC-O09-BINDING-ROUNDTRIP")
@pytest.mark.parametrize(
"work,target",
[
("simple", "work"),
("synthetic:demo", "work:synthetic:demo"),
("作品:甲:乙", "https://example.invalid/a:b?x=1&y=%3A#z"),
("work:long", "x:" + "界" * 10000),
("work", '["target:with,quotes"]'),
],
)
def test_长度中文URL和序列化都原样往返(work, target):
key = 编码绑定身份(work, target)
assert 解析绑定身份(json.loads(json.dumps(key))) == (work, target)
calls = []
conn = SimpleNamespace(
execute=lambda sql, params: calls.append(params) or SimpleNamespace(fetchone=lambda: (4,))
)
assert 绑定对象依赖().锁定当前(conn, key) == "4"
assert calls == [(work, target)]
@pytest.mark.case_id("NC-O09-BINDING-LEGACY")
def test_旧简单命令哈希不变而歧义旧目标不猜拆():
请求 = 绑定命令("work", "work", "target", "method", "version")
旧 = 变更命令(
"old-command", "B04.bind_method", "binding:work:target", 作者动作.人工保存, 0, 请求
)
assert 固定哈希(replace(旧, 目标=编码绑定身份("work", "target"))) == 固定哈希(旧)
歧义 = "binding:synthetic:demo:work:synthetic:demo"
with pytest.raises(方法错误) as 错误:
解析绑定身份(歧义)
assert 错误.value.错误码 == "SOURCE_STALE"
assert 编码绑定身份("synthetic:demo", "work:synthetic:demo") != 歧义
@pytest.mark.case_id("NC-O09-BINDING-COLLISION")
def test_不同作品与目标组合不能碰撞():
a = 编码绑定身份("w:a", "target")
b = 编码绑定身份("w", "a:target")
assert a != b
assert 解析绑定身份(a) == ("w:a", "target")
assert 解析绑定身份(b) == ("w", "a:target")
with pytest.raises(方法错误):
解析绑定身份('binding-v2:["w","a:target","extra"]')
@pytest.mark.case_id("NC-O09-BINDING-SCOPE")
def test_绑定查看先由作品owner拒绝跨作者再读取方法(monkeypatch):
import muse.作品规划.接口 as 作品
import muse.知识方法.方法版本 as 方法
from muse.作品规划.模型 import 作品错误
checked = []
def scope(conn, author, work):
checked.append((author, work))
raise 作品错误("SCOPE_DENIED", "作品不属于该作者")
monkeypatch.setattr(作品, "读取作品范围", scope)
monkeypatch.setattr(方法, "方法存储", lambda *a: pytest.fail("跨作用域后不应读方法"))
请求 = 绑定命令("other:work", "work", "https://example.invalid/target", "m", "v")
with pytest.raises(作品错误) as 错误:
方法.方法绑定入口().查看(
None, SimpleNamespace(作者="actor"), SimpleNamespace(业务请求=请求)
)
assert 错误.value.错误码 == "SCOPE_DENIED"
assert checked == [("actor", "other:work")]
@pytest.mark.case_id("NC-O09-BINDING-OLD-RECEIPT")
def test_旧命令回执不被新目标静默重写():
from muse.共享.调用身份 import 用途
from muse.正式变更.存储 import 变更存储
from muse.正式变更.接口 import 变更错误
请求 = 绑定命令("synthetic:demo", "work", "work:synthetic:demo", "m", "v")
旧 = 变更命令(
"old",
"B04.bind_method",
"binding:synthetic:demo:work:synthetic:demo",
作者动作.人工保存,
0,
请求,
)
新 = replace(旧, 目标=编码绑定身份(请求.work_id, 请求.target_ref))
receipt = {"command_id": "old", "target_ref": 旧.目标}
class Conn:
def cursor(self, **kwargs):
return self
def execute(self, sql, params):
assert not sql.lstrip().startswith("UPDATE ")
return self
def fetchone(self):
return {"request_hash": 固定哈希(旧), "receipt": receipt}
store = 变更存储(Conn())
actor = SimpleNamespace(作者="author", 用途=用途.生产)
assert store.占用命令(actor, 旧) is receipt
with pytest.raises(变更错误) as 错误:
store.占用命令(actor, 新)
assert 错误.value.错误码 == "COMMAND_PAYLOAD_MISMATCH"
assert receipt["target_ref"] == 旧.目标