From f6c877b736a4f266c2695ab1bb133b80eaced008 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 23 Oct 2026 09:17:09 +0800 Subject: [PATCH] =?UTF-8?q?test(criteria):=20=E6=94=B6=E7=B4=A7=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E8=AF=AD=E4=B9=89=E5=88=A4=E6=8D=AE=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=8F=AA=E8=AE=A4=E3=80=8C=E6=B2=A1=E8=BF=9B=E5=85=A5=E7=9B=91?= =?UTF-8?q?=E5=90=AC=E3=80=8D=EF=BC=8C=E5=B9=B6=E6=94=B9=E7=94=A8=E7=A9=BA?= =?UTF-8?q?=E9=97=B2=E7=AB=AF=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 复核发现「坏 JSON 静默忽略」这条变异没被咬住:原判据只看退出码,而错误串 里本来就含 invalid JSON、端口又固定在 17699,实现把 Fatal 改成打日志后仍 可能因端口冲突拿到非零退出码,于是被误判为"已正确报错"。 - 新增 assert_died_before_listen:只要日志里出现 "listening on",就判失败。 配置非法时进程必须启动前退出,不能带着默认口令继续提供服务。 - 所有启动分支改用 free_port 分配空闲端口——判据不能依赖宿主机上恰好没有 进程占用固定端口(默认 7500 上通常就有生产实例)。 - 顺带断言配置文件里的 addr 真的生效(必须在该端口上监听),避免"进程活着" 被当成"配置生效"。 --- scripts/criteria/config-startup.sh | 46 +++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/scripts/criteria/config-startup.sh b/scripts/criteria/config-startup.sh index 63b788c..a429ddd 100755 --- a/scripts/criteria/config-startup.sh +++ b/scripts/criteria/config-startup.sh @@ -18,6 +18,25 @@ cleanup() { for p in "${PIDS[@]:-}"; do kill "$p" 2>/dev/null; done; wait 2>/dev trap cleanup EXIT fail() { echo "FAIL: $*"; exit 1; } +# 取一个空闲端口。判据里必须用随机空闲端口:默认 127.0.0.1:7500 上通常已有 +# 生产实例在跑,端口冲突造成的非零退出会被误判成"配置错误已正确报错"。 +free_port() { + python3 -c 'import socket +s = socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1]); s.close()' +} + +# 断言:进程在配置文件非法时"没进入监听"就必须死。 +# 只检查退出码不够——错误串里本来就含 "invalid JSON",实现把 Fatal 改成 +# 打日志后继续跑,退出码可能因为端口冲突等原因仍非零。真正的判据是它不能再 +# 继续提供服务,所以出现 listening 日志即判失败。 +assert_died_before_listen() { + local log="$1" why="$2" + if grep -q 'listening on' "$log"; then + cat "$log" + fail "$why:配置错误被静默忽略后仍进入监听(应启动前就退出)" + fi +} + # ---- 1. 构建与全量测试 ---- go build ./... || fail "go build ./..." go test ./... > "$WORK/test.log" 2>&1 || { cat "$WORK/test.log"; fail "go test ./..."; } @@ -35,13 +54,14 @@ go build -o "$BIN" ./cmd/webui4frpc || fail "构建二进制失败" SECRET="CRIT_SECRET_${RANDOM}_9f3a" printf '%s\n' "$SECRET" > "$WORK/pw" chmod 600 "$WORK/pw" +PORT="$(free_port)" python3 -c ' import json, sys -t = sys.argv[1] -json.dump({"addr": "127.0.0.1:17699", "user": "crituser", +t, addr = sys.argv[1], sys.argv[2] +json.dump({"addr": addr, "user": "crituser", "password": "file:" + t + "/pw", "workdir": t + "/data"}, open(t + "/cfg.json", "w")) -' "$WORK" +' "$WORK" "127.0.0.1:$PORT" # 注意:-config 只是路径,口令来自 file: 引用,命令行本身不含秘密。 "$BIN" -config "$WORK/cfg.json" > "$WORK/run.log" 2>&1 & @@ -57,27 +77,33 @@ if grep -q -- "$SECRET" "$WORK/run.log"; then cat "$WORK/run.log" fail "明文口令出现在启动日志" fi +grep -q "listening on 127.0.0.1:$PORT" "$WORK/run.log" \ + || { cat "$WORK/run.log"; fail "配置文件里的 addr 未生效(未在 $PORT 上监听)"; } kill "$P" 2>/dev/null; wait "$P" 2>/dev/null # ---- 4. 文件存在但 JSON 非法 -> 响亮报错退出 ---- # 用 timeout 兜底:若实现退化成"只记日志继续启动",进程会一直跑而不是报错, # 这里必须把它判成失败,不能把自己挂死。 printf '{"addr":' > "$WORK/bad.json" -timeout 10 "$BIN" -config "$WORK/bad.json" > "$WORK/bad.log" 2>&1 +timeout 10 "$BIN" -config "$WORK/bad.json" \ + -addr "127.0.0.1:$(free_port)" -workdir "$WORK/d_bad" > "$WORK/bad.log" 2>&1 rc=$? -[ "$rc" -eq 124 ] && fail "配置文件 JSON 非法时进程没有退出(静默忽略),判据要求响亮报错" -[ "$rc" -eq 0 ] && fail "配置文件 JSON 非法时应非零退出,实际正常退出" +[ "$rc" -eq 124 ] && { cat "$WORK/bad.log"; fail "配置文件 JSON 非法时进程没有退出(静默忽略),判据要求响亮报错"; } +[ "$rc" -eq 0 ] && { cat "$WORK/bad.log"; fail "配置文件 JSON 非法时应非零退出,实际正常退出"; } +assert_died_before_listen "$WORK/bad.log" "JSON 非法" grep -qi 'invalid JSON' "$WORK/bad.log" || { cat "$WORK/bad.log"; fail "非法 JSON 的报错信息不明确"; } # ---- 5. 未知键(拼写错误)-> 报错退出,不得静默回落到默认口令 ---- printf '{"passwd":"x"}' > "$WORK/typo.json" -timeout 10 "$BIN" -config "$WORK/typo.json" > "$WORK/typo.log" 2>&1 +timeout 10 "$BIN" -config "$WORK/typo.json" \ + -addr "127.0.0.1:$(free_port)" -workdir "$WORK/d_typo" > "$WORK/typo.log" 2>&1 rc=$? -[ "$rc" -eq 124 ] && fail "未知键被静默忽略(进程继续运行),拼错的 password 会回落到默认值" -[ "$rc" -eq 0 ] && fail "未知键应被拒绝(否则拼错的 password 会静默使用默认值)" +[ "$rc" -eq 124 ] && { cat "$WORK/typo.log"; fail "未知键被静默忽略(进程继续运行),拼错的 password 会回落到默认值"; } +[ "$rc" -eq 0 ] && { cat "$WORK/typo.log"; fail "未知键应被拒绝(否则拼错的 password 会静默使用默认值)"; } +assert_died_before_listen "$WORK/typo.log" "未知键" # ---- 6. 配置文件缺失 -> 不算错误,回落到纯 flag 行为 ---- -"$BIN" -config "$WORK/none.json" -addr 127.0.0.1:17698 -workdir "$WORK/d2" > "$WORK/miss.log" 2>&1 & +"$BIN" -config "$WORK/none.json" -addr "127.0.0.1:$(free_port)" -workdir "$WORK/d2" > "$WORK/miss.log" 2>&1 & P2=$! PIDS+=("$P2") sleep 3