Files
blackbird/mtc/tests/test_e2e.py
qing 01126a5786 feat(mtc): .mt 脚本编译器落地 + pybot 扬声器静音语义
mtc 新模块:命令式动作脚本(Python DSL)→ .mt 矩阵编译器,非阻塞时间轴 IR(重叠截断/rest 静止值)+ 10ms 栅格化,产物可由 pybot/bot4cj 直接执行;34 测试全绿(含 pybot parser e2e)。

pybot speaker.py:frequency<=0 改为静音节拍(仅 sleep 保时序,不再钳到 min_f 低鸣),对齐仓颉版 sleep 占位语义;mtc Beep 通道 rest=0,段前/段间/段后回落静音,两侧语义闭环。

修复 test_actpred_compatibility 过时断言(99c1bc1 首行分解为重复微步 19→20 帧时漏改,14→15)。

文档三处同步:根 README 回填 memdb/pybot/actpred 并新增 mtc(模块表+端口一览+章节),MODULES/ARCHITECTURE 同步 mtc,新建 mtc/README.md。
2026-08-15 13:54:47 +08:00

65 lines
2.3 KiB
Python
Raw Permalink 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.
"""端到端:mtc 编译产物 → pybot MatrixParser 解析断言
验证闭环:编译产物必须被 pybot 零修改解析(列数一致、Q05 表头
'设备.参数' 校验、栅格行数与数值逐一比对)。
"""
from mtc.dsl import compile_script
from tests.conftest import load_pybot_parser
from tests.test_emit import EXAMPLE
def _parse(mt_text):
parser_mod = load_pybot_parser()
parser = parser_mod.MatrixParser(mt_text)
objects = []
while True:
obj = parser.parse()
if obj is None:
break
objects.append(obj)
return objects
def test_compiled_mt_parses_with_pybot():
objs = _parse(compile_script(EXAMPLE)[0])
names = [o.name for o in objs]
assert names == ["Servo", "Speaker", "Action"]
action = objs[names.index("Action")]
assert action.size == 11 # 表头 + 10 栅格行
assert action.col == 4 # s1/s2 + spk.frequency + spk.delay
for row in action.values: # 列数一致(DoesNotSync 不触发)
assert len(row) == action.col
def test_compiled_action_grid_values():
objs = _parse(compile_script(EXAMPLE)[0])
action = [o for o in objs if o.name == "Action"][0]
assert action.values[0] == ["s1.angle", "s2.angle",
"spk.frequency", "spk.delay"]
grid = action.values[1:]
assert [r[0] for r in grid] == [str(i) for i in range(1, 11)]
assert [r[1] for r in grid] == ["0"] * 5 + ["4", "8", "12", "16", "20"]
assert {r[2] for r in grid} == {"0"} # 无 Beep:frequency 恒 0
assert {r[3] for r in grid} == {"10"}
def test_compiled_mt_roundtrips_through_pybot():
"""编译产物经 pybot 解析→序列化→再解析等价(roundtrip 自检)"""
import io
parser_mod = load_pybot_parser()
objs = _parse(compile_script(EXAMPLE)[0])
out = io.StringIO()
parser_mod.MatrixSaver(out).save(objs)
objs2 = _parse(out.getvalue())
assert [(a.name, a.values) for a in objs] == \
[(b.name, b.values) for b in objs2]
def test_q05_header_contract_holds():
"""@Action 全部列名恰含一个 '.'(pybot robot._validate_action 契约)"""
objs = _parse(compile_script(EXAMPLE)[0])
action = [o for o in objs if o.name == "Action"][0]
for col in action.values[0]:
assert col.count(".") == 1