Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/tests/report-test823.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# report-test823 — L1 concurrency cap gate

Date: 2026-08-13 (Asia/Shanghai)
Base: 034f00647d42d38d5086d7fc057eb7824a441791
Source: 76c12e98379b67eb074a2a42e2a170e6aa94db1f
run.sh blob: 7c4e3ebb4ecf13710d166d9a0d3f26eb43d8d9d1 (容器内就地重算并比对,不只验 SHA 格式)
Run: docker build --build-arg SOURCE_COMMIT=$SRC --build-arg RUNSH_BLOB=$BLOB … && docker run --rm --network none …
Exit: 0

## 本次运行
```
- cap=2 峰值=2 生效值=2 告警=0
ok cap2: 生效上限 (= 2)
ok cap2: 峰值 2 ≤ 2
- 非法值 two 峰值=8 生效值=8 告警=1
ok bad_warn: 必须告警 (= 1)
ok bad_eff: 退回默认(不是静默不限) (= 8)
- 前导零 08 峰值=8 生效值=8 告警=0
ok octal_eff: 按十进制解释,不是八进制报错/不限 (= 8)
- 0(不限) 峰值=13 生效值=0 告警=0
ok zero_eff: 0 保留为「不限」的逃生口 (= 0)
ok zero_conc: 不限时峰值 13 > cap2 的 2,确实放开了并发
failures=0
RESULT: PASS
- cap=2 峰值=2 生效值=2 告警=0
```

## 见证红(三种)
```
1. 去掉 qa.sh 的取值校验段:
FAIL bad_warn: 必须告警 —— 期望 1,实测 0
FAIL bad_eff: 退回默认(不是静默不限) —— 期望 8,实测 ?
FAIL octal_eff: 按十进制解释,不是八进制报错/不限 —— 期望 8,实测 08
2. 传错的 run.sh blob 哈希 → FAIL: 镜像里的 run.sh 与 SOURCE_COMMIT 声称的不是同一份 (exit 1)
3. blob 参数对但文件被篡改 → 同上 (exit 1)
```
39 changes: 31 additions & 8 deletions scripts/qa.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ L0_TESTS=(
# 它的 CI 归属是会安装依赖的层级;本地跑法见该文件头注释的门禁命令。
)
L1_TESTS=(
# 这道闸门自己的回归。放在最前:它跑的是本脚本,若闸门坏了应当最先暴露。
# (注册这一步不是可选的 —— 一个没被任何东西调用的套件等于不存在。)
"test823-l1-concurrency-cap"
"qa-cli-01-hub-start"
"qa-cli-02-network-create"
"qa-dash-07-auth-boundary"
Expand Down Expand Up @@ -159,15 +162,35 @@ if [[ $RUN_L1 -eq 1 ]]; then
for t in "${L1_TESTS[@]}"; do
# Build (cached if recent)
note "build $t"
# 🔴 原来这里是一串逐套件的 elif。那正是本 PR 撞红的成因:
# test823 被加进 L1_TESTS,却没人记得在这里也加一条,于是
# TEST823_SOURCE_COMMIT 是空串,门 fail-closed:
# FAIL: TEST823_SOURCE_COMMIT 必须是一个完整的小写 SHA(收到 '')
# 「注册了套件但忘了在供给侧登记」会一直复发,所以改成按套件名推导:
# testNNN-... → --build-arg TESTNNN_SOURCE_COMMIT=<HEAD>
# qa-*-... 形态不匹配,和以前一样不传(它们的门不要这个变量)。
build_args=""
if [[ "$t" == "test686-rest-shape-golden" ]]; then
build_args="--build-arg TEST686_SOURCE_COMMIT=$(git rev-parse HEAD)"
elif [[ "$t" == "test765-batch-runtime-gate" ]]; then
build_args="--build-arg TEST765_SOURCE_COMMIT=$(git rev-parse HEAD)"
elif [[ "$t" == "test766-bunx-preflight" ]]; then
build_args="--build-arg TEST766_SOURCE_COMMIT=$(git rev-parse HEAD)"
elif [[ "$t" == "test746-setup-bun-pin" ]]; then
build_args="--build-arg TEST746_SOURCE_COMMIT=$(git rev-parse HEAD)"
if [[ "$t" =~ ^test([0-9]+)- ]]; then
# 🔴 仓里并存两套 build-arg 命名,必须都供给,否则名字对不上就是空串:
# 旧:test686/765/766/746 的 Dockerfile 收 TESTNNN_SOURCE_COMMIT
# 新:test823(以及 test798/test831)的 Dockerfile 收 SOURCE_COMMIT + RUNSH_BLOB
# 我上一版只按套件名推导出 TESTNNN_SOURCE_COMMIT,test823 收的是 SOURCE_COMMIT,
# 于是照旧红在 "TEST823_SOURCE_COMMIT 收到 ''"。
# 未被 Dockerfile 声明的 build-arg 只会产生一条警告,不影响构建,所以两套都传。
# 🔴 git 调用必须是非致命的。qa.sh 头部是 `set -euo pipefail`,而 test823
# 会在一个**只装了 bash/coreutils/procps、没有 git** 的容器里重放这个脚本
# (它桩了 docker 和 npm,但没桩 git)。上一版我直接写 $(git rev-parse HEAD),
# 容器里 git 不存在 → 127 → set -e 当场中断 → docker 桩一次都没被调用 →
# 峰值恒为 0 → 闸门自己的回归失败。这是我改出来的回归,不是被测代码的问题。
_qa_sha="$(git rev-parse HEAD 2>/dev/null || true)"
if [ -n "$_qa_sha" ]; then
build_args="--build-arg TEST${BASH_REMATCH[1]}_SOURCE_COMMIT=$_qa_sha --build-arg SOURCE_COMMIT=$_qa_sha"
# blob 绑定:把 SOURCE_COMMIT 钉到被测的那份 run.sh 字节上(git blob object id)
if [ -f "tests/$t/run.sh" ]; then
_qa_blob="$(git rev-parse "HEAD:tests/$t/run.sh" 2>/dev/null || true)"
[ -n "$_qa_blob" ] && build_args="$build_args --build-arg RUNSH_BLOB=$_qa_blob"
fi
fi
fi
if ! dockerrun "docker build -q $build_args -t anet-$t -f tests/$t/Dockerfile ." >/tmp/qa-l1-$t-build.log 2>&1; then
fail "L1 $t — build failed, see /tmp/qa-l1-$t-build.log"
Expand Down
23 changes: 23 additions & 0 deletions tests/test823-l1-concurrency-cap/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
ARG SOURCE_COMMIT
FROM node:22-bookworm-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends bash ca-certificates coreutils procps \
&& rm -rf /var/lib/apt/lists/*

ARG SOURCE_COMMIT
ARG RUNSH_BLOB
ENV TEST823_SOURCE_COMMIT=${SOURCE_COMMIT}
Comment on lines +8 to +10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify the source commit against the copied test inputs

When this image is built from a dirty checkout or from a revision other than the supplied SOURCE_COMMIT, the container still prints and accepts that SHA because it is merely copied into an environment variable and run.sh checks only its syntax. This can archive a PASS under a commit that does not contain the code actually exercised, defeating the report's reproducibility claim; compare the copied inputs byte-for-byte with the named revision or embed and verify their authoritative hashes.

AGENTS.md reference: AGENTS.md:L25-L25

Useful? React with 👍 / 👎.

# 把 run.sh 在 SOURCE_COMMIT 下的 git blob 哈希带进来,让容器内能验证
# "报告里的 SHA 确实对应镜像里被测的字节",而不是只验 SHA 的格式。
ENV TEST823_RUNSH_BLOB=${RUNSH_BLOB}

WORKDIR /workspace
COPY scripts/qa.sh /workspace/scripts/qa.sh
COPY tests/test823-l1-concurrency-cap/run.sh /workspace/run.sh

# 非 root:与本仓其它套件一致
RUN chown -R node:node /workspace
USER node

ENTRYPOINT ["bash", "/workspace/run.sh"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the regression suite to an automated workflow

When a later scripts/qa.sh change regresses this gate, no repository workflow executes this entrypoint: .github/workflows/qa.yml only invokes bash scripts/qa.sh --l1, whose L1_TESTS inventory does not contain test823-l1-concurrency-cap, while e2e-docker.yml never builds this Dockerfile. The test therefore cannot catch regressions unless someone remembers to run it manually; add a dedicated CI build/run step rather than inserting it into the inner L1 list, which would recursively invoke itself.

Useful? React with 👍 / 👎.

143 changes: 143 additions & 0 deletions tests/test823-l1-concurrency-cap/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/usr/bin/env bash
# test823 — scripts/qa.sh 的 L1 并发上限闸门
#
# 这道闸门的失效方向是 fail-open:QA_L1_MAX_PAR 拿到非数字时,bash 在算术
# 上下文里把它当 0,而 0 的语义恰好是「不限」—— 于是一个笔误会静默恢复
# 无上限运行。无上限时实测宿主 load1 顶到 58(8 核,同时跑着生产 hub、
# dashboard 与约 200 个 session),所以这条不是形式主义。
#
# 🔴 本套件跑的是**真的 scripts/qa.sh**,不是逻辑副本。
# 做法:把 `docker` 换成 PATH 上的桩。qa.sh 的 dockerrun() 是
# `bash -c "$*"`,所以它会解析到桩;真实的闸门代码原样执行。
# 在副本上测只能证明副本自洽 —— 那正是本仓反复栽过的坑。
#
# 峰值用**事件流**算,不用采样:每次桩调用写下精确的 START / END 纳秒
# 时间戳,事后排序求最大重叠。采样会漏掉峰值,事件流不会。
set -uo pipefail

ROOT=/workspace
SRC=${TEST823_SOURCE_COMMIT:-}
[[ "$SRC" =~ ^[0-9a-f]{40}$ ]] || { echo "FAIL: TEST823_SOURCE_COMMIT 必须是一个完整的小写 SHA(收到 '${SRC}')" >&2; exit 1; }

# 🔴 光验格式不够 —— 任何 40 位十六进制都能通过,而报告里那个 SHA 可能
# 根本不含镜像里被测的文件。这正是 #801 上那条 P1 说的病,我建这个
# 套件时原样犯了一遍。
# 做法:构建时把 run.sh 在该 commit 下的 git blob 哈希作为 build-arg
# 传进来,这里就地重算镜像内文件的 blob 哈希并比对。git blob 哈希 =
# sha1("blob <len>\0" + 内容),不需要容器里装 git。
EXPECT=${TEST823_RUNSH_BLOB:-}
[[ "$EXPECT" =~ ^[0-9a-f]{40}$ ]] || { echo "FAIL: TEST823_RUNSH_BLOB 缺失或格式不对 —— 无法把 SOURCE_COMMIT 绑到被测字节" >&2; exit 1; }
self=/workspace/run.sh
actual=$( { printf 'blob %d\0' "$(wc -c < "$self")"; cat "$self"; } | sha1sum | cut -d" " -f1 )
if [[ "$actual" != "$EXPECT" ]]; then
echo "FAIL: 镜像里的 run.sh 与 SOURCE_COMMIT=$SRC 声称的不是同一份" >&2
echo " 期望 blob $EXPECT,实际 $actual" >&2
exit 1
fi

BIN=/tmp/t823-bin
EV=/tmp/t823-events
mkdir -p "$BIN"

# ── docker 桩 ────────────────────────────────────────────────────────────
# build 是同步的,run 是后台的 —— 只有 run 会重叠。两者都记事件,
# 这样如果哪天 build 也被后台化,峰值会立刻反映出来。
cat > "$BIN/docker" <<'STUB'
#!/usr/bin/env bash
# build 是同步的、run 是后台的 —— 只有 run 会重叠。若两者同样耗时,
# run 之间几乎不重叠,峰值恒为 1,高上限下断言就失去分辨力(第一版如此)。
# 所以 build 尽量快,run 拉长,让并发真正显现出来。
# 只有真正的 `docker run` 才记事件。任何其它子命令(build/ps/rmi…)
# 都不该计入并发峰值 —— 否则峰值会被无关调用抬高,断言就不再是在测闸门。
[ "${1:-}" = "run" ] || exit 0
printf 'S %s %s\n' "$(date +%s%N)" "$$" >> "$T823_EV"
sleep 1.2
printf 'E %s %s\n' "$(date +%s%N)" "$$" >> "$T823_EV"
exit 0
STUB
chmod +x "$BIN/docker"

# npm 也要桩:qa.sh 会跑 `npm view … dist-tags.preview` 做 registry 快照。
# 容器是 --network none,真 npm 会一直等 DNS/连接超时,而不是快速失败 ——
# 第一版就是这么跑成超时的。桩掉它,让被测的闸门成为唯一的耗时来源。
cat > "$BIN/npm" <<'NPMSTUB'
#!/usr/bin/env bash
echo "0.0.0-stub"
exit 0
NPMSTUB
chmod +x "$BIN/npm"

export PATH="$BIN:$PATH"
export T823_EV="$EV"

peak() { # 从事件流算最大重叠
sort -k2,2n "$1" | awk '
$1=="S" { c++; if (c>m) m=c }
$1=="E" { c-- }
END { print m+0 }'
}

nproc_val=$(nproc 2>/dev/null || echo 4)
fails=0
report=/tmp/report-test823.txt
: > "$report"

say() { echo "$*" | tee -a "$report"; }

say "# test823 — L1 concurrency cap gate"
say "source_commit=$SRC"
say "nproc=$nproc_val"
say ""

run_case() { # $1=用例名 $2=QA_L1_MAX_PAR 取值(空=不设)
local name=$1 val=${2-}
: > "$EV"
local out=/tmp/t823-$name.log
if [[ -n "${val:-}" || "${2+set}" == "set" ]]; then
QA_L1_MAX_PAR="$val" bash "$ROOT/scripts/qa.sh" --l1 > "$out" 2>&1 || true
else
bash "$ROOT/scripts/qa.sh" --l1 > "$out" 2>&1 || true
fi
local p; p=$(peak "$EV")
# 只取 `= ` 之后那个数。原来用 grep -oE '[0-9]+' 会先命中 "L1" 里的 1 ——
# 判据没在已知输入上校准过,于是四个用例全部报 1。
local eff; eff=$(sed -n 's/.*L1 并发上限 = \([0-9][0-9]*\).*/\1/p' "$out" | head -1)
[[ -n "$eff" ]] || eff="?"
local warned=0; grep -q '不是非负整数' "$out" && warned=1
echo "$p|$eff|$warned"
}

check() { # $1=用例 $2=实测 $3=期望 $4=说明
if [[ "$2" == "$3" ]]; then say " ok $1: $4 (= $2)"
else say " FAIL $1: $4 —— 期望 $3,实测 $2"; fails=$((fails+1)); fi
}

say "## 用例"

IFS='|' read -r p eff warned <<< "$(run_case cap2 2)"
say "- cap=2 峰值=$p 生效值=$eff 告警=$warned"
check cap2 "$eff" 2 "生效上限"
[[ "$p" -le 2 && "$p" -ge 1 ]] && say " ok cap2: 峰值 $p ≤ 2" || { say " FAIL cap2: 峰值 $p 超过上限 2"; fails=$((fails+1)); }

IFS='|' read -r p eff warned <<< "$(run_case bad two)"
say "- 非法值 two 峰值=$p 生效值=$eff 告警=$warned"
check bad_warn "$warned" 1 "必须告警"
check bad_eff "$eff" "$nproc_val" "退回默认(不是静默不限)"

IFS='|' read -r p eff warned <<< "$(run_case octal 08)"
say "- 前导零 08 峰值=$p 生效值=$eff 告警=$warned"
check octal_eff "$eff" 8 "按十进制解释,不是八进制报错/不限"

IFS='|' read -r p eff warned <<< "$(run_case zero 0)"
say "- 0(不限) 峰值=$p 生效值=$eff 告警=$warned"
check zero_eff "$eff" 0 "0 保留为「不限」的逃生口"
Comment on lines +131 to +133

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Assert that a zero cap actually permits concurrency

If the 0 = unlimited behavior regresses to a serial or otherwise capped execution while the status message still prints 0, this case passes because it only checks the parsed effective value and never checks the measured peak. That leaves the advertised escape hatch unprotected; compare this case's peak with the capped case (or otherwise require observable overlap) rather than treating the printed configuration as proof of behavior.

Useful? React with 👍 / 👎.

# 只断言"生效值是 0"不够 —— 那只证明它被这么解析,没证明它真的放开了并发。
# 拿 cap=2 的峰值当对照:不限时必须明显更高。
if [[ "$p" -gt 2 ]]; then say " ok zero_conc: 不限时峰值 $p > cap2 的 2,确实放开了并发"
else say " FAIL zero_conc: 不限时峰值只有 $p,与 cap=2 无区别 —— 「不限」没有被验证"; fails=$((fails+1)); fi

say ""
say "failures=$fails"
if [[ "$fails" -eq 0 ]]; then say "RESULT: PASS"; else say "RESULT: FAIL"; fi
cat "$report"
[[ "$fails" -eq 0 ]]
Loading