""" test_compare.py — U6 对比逻辑单测(mock verdict + 产物形态识别,不依赖真跑)。 跑:cheap-worker/.venv/bin/python cheap-worker/tests/test_compare.py """ import sys import tempfile from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) # → cheap-worker/ import compare_node as C def test_gates_from_verdict(): v = {"pass": True, "guards": {"A_boot": {"pass": True}, "H_progress": {"pass": False}}} assert C.gates_from_verdict(v) == {"A_boot": True, "H_progress": False} assert C.gates_from_verdict(None) == {} def test_compare_equivalent(): """两路九门全过 + Python 真 src/ → spike 成功。""" r = C.compare_logic({"A": True, "B": True}, {"A": True, "B": True}, py_real_src=True) assert r["spikePass"] is True assert r["pyPassRate"] == 1.0 and r["nodePassRate"] == 1.0 def test_compare_py_better(): """Python 过门率高于 Node → spike 成功,delta>0。""" r = C.compare_logic({"A": True, "B": True}, {"A": True, "B": False}, py_real_src=True) assert r["spikePass"] is True and r["rateDelta"] > 0 def test_compare_py_worse(): """Python 过门率低于 Node → 未达标,delta<0。""" r = C.compare_logic({"A": True, "B": False}, {"A": True, "B": True}, py_real_src=True) assert r["spikePass"] is False and r["rateDelta"] < 0 def test_compare_py_not_real_src(): """Python 非真 src/ 多文件 → 即使过门率相等也判未达标(doc↔code 兑现门)。""" r = C.compare_logic({"A": True, "B": True}, {"A": True, "B": True}, py_real_src=False) assert r["spikePass"] is False def test_src_shape_real_multifile(): with tempfile.TemporaryDirectory() as d: src = Path(d) / "src" src.mkdir() (src / "game-logic.js").write_text("x", encoding="utf-8") (src / "host-config.js").write_text("y", encoding="utf-8") s = C.src_shape(Path(d)) assert s["realSrcMultifile"] is True and s["jsCount"] == 2 def test_src_shape_single_file(): with tempfile.TemporaryDirectory() as d: src = Path(d) / "src" src.mkdir() (src / "game-logic.js").write_text("x", encoding="utf-8") # 单文件 → 非"多文件" s = C.src_shape(Path(d)) assert s["realSrcMultifile"] is False and s["jsCount"] == 1 def test_src_shape_empty(): with tempfile.TemporaryDirectory() as d: s = C.src_shape(Path(d)) # 无 src/ → 空壳 assert s["realSrcMultifile"] is False and s["jsCount"] == 0 if __name__ == "__main__": _fns = [v for k, v in sorted(globals().items()) if k.startswith("test_") and callable(v)] _failed = 0 for _fn in _fns: try: _fn() print(f" PASS {_fn.__name__}") except Exception as e: # noqa: BLE001 _failed += 1 print(f" FAIL {_fn.__name__}: {type(e).__name__}: {e}") print(f"\n{len(_fns) - _failed}/{len(_fns)} passed") sys.exit(1 if _failed else 0)