mirror of
https://gitcode.com/JianFeeeee/webui4frpc.git
synced 2026-10-31 06:17:20 +00:00
test(criteria): 收紧失败语义判据——只认「没进入监听」,并改用空闲端口
复核发现「坏 JSON 静默忽略」这条变异没被咬住:原判据只看退出码,而错误串 里本来就含 invalid JSON、端口又固定在 17699,实现把 Fatal 改成打日志后仍 可能因端口冲突拿到非零退出码,于是被误判为"已正确报错"。 - 新增 assert_died_before_listen:只要日志里出现 "listening on",就判失败。 配置非法时进程必须启动前退出,不能带着默认口令继续提供服务。 - 所有启动分支改用 free_port 分配空闲端口——判据不能依赖宿主机上恰好没有 进程占用固定端口(默认 7500 上通常就有生产实例)。 - 顺带断言配置文件里的 addr 真的生效(必须在该端口上监听),避免"进程活着" 被当成"配置生效"。
This commit is contained in:
@ -18,6 +18,25 @@ cleanup() { for p in "${PIDS[@]:-}"; do kill "$p" 2>/dev/null; done; wait 2>/dev
|
|||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
fail() { echo "FAIL: $*"; exit 1; }
|
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. 构建与全量测试 ----
|
# ---- 1. 构建与全量测试 ----
|
||||||
go build ./... || fail "go build ./..."
|
go build ./... || fail "go build ./..."
|
||||||
go test ./... > "$WORK/test.log" 2>&1 || { cat "$WORK/test.log"; fail "go test ./..."; }
|
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"
|
SECRET="CRIT_SECRET_${RANDOM}_9f3a"
|
||||||
printf '%s\n' "$SECRET" > "$WORK/pw"
|
printf '%s\n' "$SECRET" > "$WORK/pw"
|
||||||
chmod 600 "$WORK/pw"
|
chmod 600 "$WORK/pw"
|
||||||
|
PORT="$(free_port)"
|
||||||
python3 -c '
|
python3 -c '
|
||||||
import json, sys
|
import json, sys
|
||||||
t = sys.argv[1]
|
t, addr = sys.argv[1], sys.argv[2]
|
||||||
json.dump({"addr": "127.0.0.1:17699", "user": "crituser",
|
json.dump({"addr": addr, "user": "crituser",
|
||||||
"password": "file:" + t + "/pw", "workdir": t + "/data"},
|
"password": "file:" + t + "/pw", "workdir": t + "/data"},
|
||||||
open(t + "/cfg.json", "w"))
|
open(t + "/cfg.json", "w"))
|
||||||
' "$WORK"
|
' "$WORK" "127.0.0.1:$PORT"
|
||||||
|
|
||||||
# 注意:-config 只是路径,口令来自 file: 引用,命令行本身不含秘密。
|
# 注意:-config 只是路径,口令来自 file: 引用,命令行本身不含秘密。
|
||||||
"$BIN" -config "$WORK/cfg.json" > "$WORK/run.log" 2>&1 &
|
"$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"
|
cat "$WORK/run.log"
|
||||||
fail "明文口令出现在启动日志"
|
fail "明文口令出现在启动日志"
|
||||||
fi
|
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
|
kill "$P" 2>/dev/null; wait "$P" 2>/dev/null
|
||||||
|
|
||||||
# ---- 4. 文件存在但 JSON 非法 -> 响亮报错退出 ----
|
# ---- 4. 文件存在但 JSON 非法 -> 响亮报错退出 ----
|
||||||
# 用 timeout 兜底:若实现退化成"只记日志继续启动",进程会一直跑而不是报错,
|
# 用 timeout 兜底:若实现退化成"只记日志继续启动",进程会一直跑而不是报错,
|
||||||
# 这里必须把它判成失败,不能把自己挂死。
|
# 这里必须把它判成失败,不能把自己挂死。
|
||||||
printf '{"addr":' > "$WORK/bad.json"
|
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=$?
|
||||||
[ "$rc" -eq 124 ] && fail "配置文件 JSON 非法时进程没有退出(静默忽略),判据要求响亮报错"
|
[ "$rc" -eq 124 ] && { cat "$WORK/bad.log"; fail "配置文件 JSON 非法时进程没有退出(静默忽略),判据要求响亮报错"; }
|
||||||
[ "$rc" -eq 0 ] && 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 的报错信息不明确"; }
|
grep -qi 'invalid JSON' "$WORK/bad.log" || { cat "$WORK/bad.log"; fail "非法 JSON 的报错信息不明确"; }
|
||||||
|
|
||||||
# ---- 5. 未知键(拼写错误)-> 报错退出,不得静默回落到默认口令 ----
|
# ---- 5. 未知键(拼写错误)-> 报错退出,不得静默回落到默认口令 ----
|
||||||
printf '{"passwd":"x"}' > "$WORK/typo.json"
|
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=$?
|
||||||
[ "$rc" -eq 124 ] && fail "未知键被静默忽略(进程继续运行),拼错的 password 会回落到默认值"
|
[ "$rc" -eq 124 ] && { cat "$WORK/typo.log"; fail "未知键被静默忽略(进程继续运行),拼错的 password 会回落到默认值"; }
|
||||||
[ "$rc" -eq 0 ] && fail "未知键应被拒绝(否则拼错的 password 会静默使用默认值)"
|
[ "$rc" -eq 0 ] && { cat "$WORK/typo.log"; fail "未知键应被拒绝(否则拼错的 password 会静默使用默认值)"; }
|
||||||
|
assert_died_before_listen "$WORK/typo.log" "未知键"
|
||||||
|
|
||||||
# ---- 6. 配置文件缺失 -> 不算错误,回落到纯 flag 行为 ----
|
# ---- 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=$!
|
P2=$!
|
||||||
PIDS+=("$P2")
|
PIDS+=("$P2")
|
||||||
sleep 3
|
sleep 3
|
||||||
|
|||||||
Reference in New Issue
Block a user