改动面 112 文件 572+/572-:game/tests/** 与 game/probe/** 共 106 件 545 行 `# oracle:`→`# 判据出处:`;tools/capability_audit.py 正则字面量换中文+ORACLE_*→CRITERION_*/check_oracle_markers→check_criterion_markers/oracle_marked(flagged)→criterion_* 共 11 行;test-conventions.md:119 格式句+:155 措辞;待办清单与需求卡片-QA覆盖余量收口批各 1 处字面量;coverage_enum.py:21 与 camp_scene_layout_test.gd:101 旁支措辞;ui_click_probe.gd 对拍局部变量 oracle→expected 7 处;auto_player.gd 三处 safe_set 真值措辞。不动:历史审计报告两份、test-oracle-anchor 分支名、git 史、生成日志;指针格式/扫描面/判红条件/验收义务全不变。 读数(区内实跑):改前 capability_audit --strict「417 注记函数·红项 0」→改后「417 判据出处注记函数·红项 0」exit=0;新标记 545 行/106 文件,现行义务面 oracle 残留 0(在册沿革除外);diff 自检 game/ 非注释新增行仅 6 行且全在 ui_click_probe.gd 的 expected 变量段;112 改动文件 CRLF=0;py_compile tools/capability_audit.py OK;--docs exit=0【验收通过】无新增红;--gates exit=0(静态扫描绿、闸壳 bash -n ×13 失败 0)。
74 lines
3.7 KiB
GDScript
74 lines
3.7 KiB
GDScript
# 致命类用例(独立进程,期望退出码 1)
|
||
# 卡② V9/E1——计数器前缀合法性 + 引用闭合加载期致命双断言:
|
||
# ①向 feats.tres 注入 kind=counter_add 但 counter_id 前缀非法(meta_ 出域)的行 → validate_trigger_row 须拦;
|
||
# ②注入读点(when fact=counter id)指向无同名写入行的悬空 id → config_db_cross_validator 引用闭合须拦。
|
||
# 任一违规被放行即回归(退出码 2)。两夹具目录各跑一次 load_tables,均须拒绝。
|
||
# 运行:godot --headless --path game --script res://tests/unit/data_config/counter_prefix_fatal_test.gd
|
||
extends SceneTree
|
||
|
||
const ConfigDBScript := preload("res://core/config_db.gd")
|
||
const Kit := preload("res://tests/unit/test_kit.gd")
|
||
|
||
const SRC_DIR := "res://data/tables"
|
||
const BAD_PREFIX_DIR := "user://counter_fixture_prefix"
|
||
const BAD_REF_DIR := "user://counter_fixture_ref"
|
||
|
||
# 注入探针:非法前缀写入行(meta_probe 无 meta_ 合法归桶 → counter_id_legal false)
|
||
const PROBE_PREFIX := ' {\n "feat_id": "prefix_probe",\n "display_name": "前缀探针",\n "rarity": "common",\n "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "counter_add", "counter_id": "meta_probe", "value": 1 } } ],\n "desc": "夹具探针——非法前缀"\n},\n'
|
||
# 注入探针:悬空读点(when counter id=pain_layer 单数,全表无同名写入行 → 引用闭合拦)
|
||
const PROBE_REF := ' {\n "feat_id": "ref_probe",\n "display_name": "引用探针",\n "rarity": "common",\n "triggers": [ { "on": "dig_reveal", "when": [ { "fact": "counter", "id": "pain_layer", "op": "lt", "value": 1 } ], "do": { "kind": "grant_ap", "mode": "queue", "value": 1 } } ],\n "desc": "夹具探针——悬空读点"\n},\n'
|
||
|
||
|
||
func _inject(dir: String, probe: String) -> bool:
|
||
# 判据出处: design/gdd/systems/表现与支撑/数据配置.md:199 校验类别全覆盖:前缀违规夹具注入(前缀夹具组)
|
||
var path := dir + "/feats.tres"
|
||
var f := FileAccess.open(path, FileAccess.READ)
|
||
if f == null:
|
||
push_error("注入失败:读不到 %s" % path)
|
||
return false
|
||
var s := f.get_as_text()
|
||
f.close()
|
||
var anchor := "rows = ["
|
||
var idx := s.find(anchor)
|
||
if idx < 0:
|
||
push_error("注入失败:锚点 '%s' 未找到(len=%d)" % [anchor, s.length()])
|
||
return false
|
||
var cut := idx + anchor.length()
|
||
s = s.substr(0, cut) + "\n" + probe + s.substr(cut)
|
||
var w := FileAccess.open(path, FileAccess.WRITE)
|
||
if w == null:
|
||
push_error("注入失败:写不开 %s" % path)
|
||
return false
|
||
w.store_string(s)
|
||
w.close()
|
||
return true
|
||
|
||
|
||
func _assert_rejected(bad_dir: String, probe: String, label: String) -> bool:
|
||
# 判据出处: design/gdd/systems/表现与支撑/数据配置.md:200 致命真的会死:违规表拒绝且进程非 0(拒绝判定组)
|
||
# 返回 true=正确拒绝;false=放行或夹具失败(调用方据此退出 2)
|
||
if not Kit.copy_tables(SRC_DIR, bad_dir) or not _inject(bad_dir, probe):
|
||
push_error("[%s] 夹具目录准备失败" % label)
|
||
return false
|
||
var db = ConfigDBScript.new()
|
||
var ok: bool = db.load_tables(bad_dir, false)
|
||
if ok:
|
||
push_error("[%s] 违规表被放行——加载期校验失守(回归)" % label)
|
||
return false
|
||
if db.diagnostics_count("error") < 1:
|
||
push_error("[%s] 加载被拒但零 error 诊断——校验通道静默化(回归)" % label)
|
||
return false
|
||
print("[%s] 正确拒绝(error 诊断在案)" % label)
|
||
return true
|
||
|
||
|
||
func _init() -> void:
|
||
if not _assert_rejected(BAD_PREFIX_DIR, PROBE_PREFIX, "counter_prefix_fatal_test/①非法前缀"):
|
||
quit(2)
|
||
return
|
||
if not _assert_rejected(BAD_REF_DIR, PROBE_REF, "counter_prefix_fatal_test/②悬空读点"):
|
||
quit(2)
|
||
return
|
||
print("[counter_prefix_fatal_test] 双断言均正确拒绝(前缀合法性 + 引用闭合)〔无状态化 V9〕")
|
||
quit(1)
|