57 lines
2.3 KiB
Python
57 lines
2.3 KiB
Python
# ============================================================
|
||
# Explore 边界扩展黄金测试(plan.md §5.1 / 矩阵 55 行剩余项)
|
||
# 覆盖:run_sensitivity 与 run_monte_carlo 经统一 Explore 通道执行,
|
||
# 主干零污染(readonly 语义保持)。
|
||
# ============================================================
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
from pathlib import Path
|
||
|
||
from server.aps_domain.robustness import run_monte_carlo
|
||
from server.aps_domain.sensitivity import run_sensitivity
|
||
|
||
FIXTURE = Path(__file__).resolve().parents[2] / "server" / "data" / "world.json"
|
||
|
||
|
||
def _load_world() -> dict:
|
||
import json as _json
|
||
if FIXTURE.exists():
|
||
return _json.loads(FIXTURE.read_text(encoding="utf-8"))
|
||
from server.state.seed import seed_world
|
||
return seed_world()
|
||
|
||
|
||
def test_sensitivity_through_unified_channel_no_mutation():
|
||
"""run_sensitivity 经 run_explore:主干世界逐字节不变(Explore 铁律)。"""
|
||
world = _load_world()
|
||
before = json.dumps(world, ensure_ascii=False, sort_keys=True)
|
||
report = run_sensitivity(world, strategy="COMPREHENSIVE")
|
||
assert "rows" in report and "baseline" in report
|
||
after = json.dumps(world, ensure_ascii=False, sort_keys=True)
|
||
assert before == after, "sensitivity 不得污染主干"
|
||
|
||
|
||
def test_monte_carlo_through_unified_channel_no_mutation():
|
||
"""run_monte_carlo 经 run_explore:主干零污染,输出含 outcomes。"""
|
||
world = _load_world()
|
||
before = json.dumps(world, ensure_ascii=False, sort_keys=True)
|
||
result = run_monte_carlo(world, strategy="COMPREHENSIVE", engine_type="RULE", trials=3)
|
||
assert result["method"] == "fixed-seed-monte-carlo"
|
||
assert len(result["outcomes"]) == 3
|
||
after = json.dumps(world, ensure_ascii=False, sort_keys=True)
|
||
assert before == after, "monte carlo 不得污染主干"
|
||
|
||
|
||
def test_sensitivity_readonly_world_blocks_write():
|
||
"""Explore 工具若尝试写主干(经 readonly_view)必须 fail closed。"""
|
||
from server.aps_domain.explore_boundary import readonly_view
|
||
world = _load_world()
|
||
view = readonly_view(world)
|
||
try:
|
||
view["salesOrders"] = []
|
||
raise AssertionError("应抛 PermissionError")
|
||
except PermissionError:
|
||
pass
|
||
assert world.get("salesOrders") is not None
|