fix(playable): close release validation lifecycle gaps

This commit is contained in:
shen
2026-09-11 21:23:44 +08:00
parent f39a55fdd5
commit cc5573ddc1
13 changed files with 230 additions and 7 deletions
+44
View File
@@ -27,6 +27,7 @@ fixture="$repo/test/playable"
validate_fixture() { # report log process_code timed_out [extra...]
local report="$1" log="$2" code="$3" timed="$4"
shift 4
rm -f "$tmp_dir/sealed.json"
node script/validate_playable_report.mjs --report "$report" --output "$tmp_dir/sealed.json" --log "$log" \
--process-code "$code" --timed-out "$timed" --run-id fixture-run --suite playable \
--required-cases "$tmp_dir/v/required-cases.json" --build "$tmp_dir/v/build.json" \
@@ -54,6 +55,17 @@ cp "$fixture/report.blocked.json" "$tmp_dir/v/client-report.json"
expect_code 2 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$fixture/clean.log" 0 0)" "validator: BLOCKED case is not releasable"
reset_fixture
expect_code 1 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$fixture/clean.log" 1 0)" "validator: nonzero child exit"
for root_value in null '[]' '"invalid"' 42; do
reset_fixture
printf '%s\n' "$root_value" >"$tmp_dir/v/client-report.json"
expect_code 1 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$fixture/clean.log" 0 0)" "validator: invalid root $root_value"
if [ -f "$tmp_dir/sealed.json" ]; then pass "validator: invalid root sealed as FAIL"; else fail "validator: invalid root crashed before sealing"; fi
done
reset_fixture
printf 'null\n' >"$tmp_dir/v/events.jsonl"
expect_code 1 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$fixture/clean.log" 0 0)" "validator: null event"
[ -f "$tmp_dir/sealed.json" ] && pass "validator: null event sealed as FAIL" || fail "validator: null event crashed before sealing"
reset_fixture
expect_code 1 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$fixture/clean.log" 0 1)" "validator: timed out"
expect_code 1 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$fixture/rid-warning.log" 0 0)" "validator: RID warning in log"
expect_code 1 "$(code_of validate_fixture "$tmp_dir/v/client-report.json" "$tmp_dir/missing.log" 0 0)" "validator: missing log"
@@ -171,6 +183,36 @@ run_gate() { # scenario output [extra args...]
}
report_status() { node -e 'try{process.stdout.write(require(process.argv[1]).status)}catch{process.stdout.write("MISSING")}' "$1/report.json"; }
cancel_gate() { # script output [runner args...]
local runner="$1" out="$2" owner child="" code pid_file
shift 2
MT_FAKE_SCENARIO=cancel bash "$runner" --app "$app" --output "$out" "$@" >"$out.stdout" 2>&1 &
owner=$!
for ((attempt=0; attempt<100; attempt++)); do
pid_file="$(find "$out" -name fake-child.pid -print -quit 2>/dev/null || true)"
if [ -n "$pid_file" ] && [ -s "$pid_file" ]; then child="$(<"$pid_file")"; break; fi
kill -0 "$owner" 2>/dev/null || break
sleep 0.1
done
kill -TERM "$owner" 2>/dev/null || true
set +e
wait "$owner"
code=$?
set -e
expect_code 143 "$code" "cancel: $runner preserves signal exit"
if [ -n "$child" ] && ! kill -0 "$child" 2>/dev/null; then
pass "cancel: $runner reaps its client"
else
fail "cancel: $runner left a client alive or never started one"
if [ -n "$child" ]; then kill -KILL "$child" 2>/dev/null || true; fi
fi
}
cancel_gate script/run_client_gate.sh "$tmp_dir/run-cancel" --config "$tmp_dir/scenario.local.json" \
--assets "$tmp_dir/assets" --serverlist "$tmp_dir/serverlist.txt"
cancel_gate script/forest_map_render_test.sh "$tmp_dir/forest-cancel" --maps "$map_key"
cancel_gate script/playable_test.sh "$tmp_dir/batch-cancel" --config "$tmp_dir/scenario.local.json" \
--assets "$tmp_dir/assets" --serverlist "$tmp_dir/serverlist.txt"
expect_code 0 "$(code_of run_gate pass "$tmp_dir/run-pass")" "runner: PASS"
[ "$(report_status "$tmp_dir/run-pass")" = "PASS" ] && pass "runner: sealed report PASS" || fail "runner: sealed report not PASS"
expect_code 0 "$(code_of run_gate pass "$tmp_dir/run-pass-2")" "runner: second independent PASS"
@@ -365,6 +407,8 @@ expect_code 2 "$(code_of run_soak_gate soak-pass "$tmp_dir/soak-proxy-down" "$tm
[ ! -e "$tmp_dir/soak-proxy-down/client.log" ] && pass "soak runner: client not started when the upstream is down" || fail "soak runner: client started with upstream down"
# ---------- STB-01 public entry: script/playable_soak.sh ----------
cancel_gate script/playable_soak.sh "$tmp_dir/soak-cancel" --config "$tmp_dir/soak.local.json" \
--assets "$tmp_dir/assets" --serverlist "$tmp_dir/serverlist.txt" --allow-gameplay
run_soak() { # scenario output [extra args...]
local scenario="$1" out="$2"
shift 2