P2-1(与 P1 同类):licenses/ 与 README 缺失仍会假成功。 - 新增 meta_complete()/verify_meta():MANIFEST + README + 五份许可证副本 (procps COPYING/COPYING.LIB、ncurses、lsof、musl-COPYRIGHT)缺一即不完整 - 纳入 skip 条件与 --verify-only;产物未变但 meta 缺失时就地 write_meta 补全(不重编), 构建树不在则退回全量重建 - 回归测试新增 T6(删 licenses 后 --with-sources 必须恢复)、T7(--verify-only 必须拒绝)、 T8(删 README 后恢复);共 20 项全过 P2-2:README.txt/MANIFEST.txt 的卡上路径全错(写成 ../src、scripts/build/…)。 - 全部改为卡内相对路径:src/、licenses/、MANIFEST.txt、src/DEVKIT.md、src/build_devkit.sh - README 增加「目录内容」段并注明 src/ 是生成目录、勿手放文件 P2-3:valgrind 的排除理由(“无 MIPS32 后端”)是错的 —— 官方支持 MIPS32/Linux。 - 改为「未尝试」:交叉构建需 autotools + 目标 vDSO 细节、产物 10MB+,56MB 单核不实用 P2-4:busybox 1.31 实测有 pgrep/kill/killall,没有 pkill、没有 sysctl。 - 表格改准确;pgrep 保留(增量有限不交付);pkill 写明「busybox 无此 applet, killall 只能部分替代,本轮未做」 - 新增交付 sysctl(procps 4.0.4,148184 B,静态):MANIFEST/verify-only/真机 (sysctl -a 428 键、kernel.hostname/panic 读取、-n)均已验证 P2-5:free -s <小数> 也受 time64 影响(usleep 亚秒被抹平),文档说反了。 - DEVKIT §9 增加一行(free -s 0.5 实测 0s、free -s 1 实测 1s);README 同步; “收益只有 vmstat -t 一列”改为包含 free -s P3: 1. §9 机制改准:内核只写 8 字节 → tv_sec 高 32 位是内核写入的 nsec、offset 8 的 tv_nsec 才是未初始化;nanosleep 是把 tv_sec 高半字当 nsec 读(0) 2. 删掉脚本里 top 的旧错误归因(时长溢出/59.4 GiB),与 DEVKIT 对齐 3. 测试耗时改为「热缓存约 15s,冷启动 1–2 分钟」(实测 28s 含多次构建/修复路径) 4. --verify-only 依赖清单写全(file/readelf/sha256sum/awk/sed/grep/wc/cut/basename) 5. licenses/ 增加 musl-COPYRIGHT(zig env → libc/musl/COPYRIGHT,取不到即失败),§6 补一行 6. htop 说明改准:亚秒刷新走 ncurses halfdelay()(select + 32 位 timeval),大概率不受 time64 影响;受影响的是时钟显示与部分采样(仍注明未做运行时验证) 7. README/脚本注明 src/ 是生成目录 8. LGPL 摘要改为「源码(§6a) 或 共享库(§6b) 或 书面要约(§6c)」 9. ltrace/sysstat 从「不可行」改为「未做(成本高)」,与 perf 的硬阻塞区分 验证:test_build_devkit.sh 20/20;--verify-only 通过(7 个二进制 + MANIFEST + 5 份许可证); 独立工作区离线重建 64s/0 下载,七个 sha256 与前一次逐字节一致;设备实测 sysctl 与其余六项正常。
122 lines
5.6 KiB
Bash
Executable File
122 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
||
# ============================================================================
|
||
# test_build_devkit.sh — build_devkit.sh 的回归测试(不重编)
|
||
#
|
||
# 耗时:热缓存约 15 秒;若需冷启动基线重建(首次运行/源码未缓存)约 1–2 分钟。
|
||
#
|
||
# 覆盖:
|
||
# r1 P1 回归点 —— stamp 命中(跳过编译)时,--with-sources 必须真正产出 src/
|
||
# r2 P2-1 —— licenses/README 被删后 --with-sources 必须恢复,
|
||
# --verify-only 必须拒绝缺许可证的交付
|
||
# MANIFEST 内容漂移检测、src/ 缺文件与内容漂移自愈
|
||
#
|
||
# 前置:MEOW_DEVKIT_WORK 里已有一次构建(脚本会先跑一次增量构建,命中则秒回;
|
||
# 缓存缺失时会联网下载/编译,第一次运行约 1 分钟)。
|
||
#
|
||
# 用法:bash scripts/build/test_build_devkit.sh [-v]
|
||
# 退出码 0 = 全过;非 0 = 用例失败数。
|
||
# ============================================================================
|
||
set -u
|
||
|
||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||
SCRIPT="$ROOT/scripts/build/build_devkit.sh"
|
||
export MEOW_DEVKIT_WORK="${MEOW_DEVKIT_WORK:-$HOME/.cache/meow-devkit}"
|
||
OUT="$ROOT/fw_apps/devkit"
|
||
TMP="$MEOW_DEVKIT_WORK/test-tmp"
|
||
|
||
VERBOSE=0
|
||
[ "${1:-}" = "-v" ] && VERBOSE=1
|
||
|
||
PASS=0
|
||
FAILN=0
|
||
pass() { PASS=$((PASS + 1)); printf 'PASS %s\n' "$*"; }
|
||
fail() { FAILN=$((FAILN + 1)); printf 'FAIL %s\n' "$*"; }
|
||
run() { # run <说明> <命令...>
|
||
local desc="$1"; shift
|
||
local log="$TMP/last.log"
|
||
if "$@" >"$log" 2>&1; then
|
||
[ "$VERBOSE" = 1 ] && sed 's/^/ | /' "$log"
|
||
return 0
|
||
fi
|
||
printf ' 命令失败: %s\n' "$*"
|
||
sed 's/^/ | /' "$log" | tail -20
|
||
return 1
|
||
}
|
||
|
||
mkdir -p "$TMP"
|
||
# 无论成败都恢复现场,别把测试的破坏留在产物目录里
|
||
restore() {
|
||
[ -f "$TMP/MANIFEST.txt.bak" ] && cp "$TMP/MANIFEST.txt.bak" "$OUT/MANIFEST.txt"
|
||
rm -rf "$TMP"
|
||
}
|
||
trap restore EXIT
|
||
|
||
echo "== 0) 确保基线构建(幂等;已构建则秒回)"
|
||
run "基线构建" bash "$SCRIPT" || { echo "!!! 基线构建失败,后续用例无意义"; exit 1; }
|
||
pass "基线构建"
|
||
|
||
echo "== 1) P1 回归:stamp 命中 + --with-sources 必须产出 src/"
|
||
rm -rf "$OUT/src"
|
||
run "普通重跑(应命中 stamp 且不建 src/)" bash "$SCRIPT" || fail "T1a 普通重跑"
|
||
[ ! -d "$OUT/src" ] && pass "T1a 普通重跑不创建 src/(符合预期)" || fail "T1a 普通重跑意外创建了 src/"
|
||
run "--with-sources(stamp 命中路径)" bash "$SCRIPT" --with-sources || fail "T1b --with-sources 退出码非 0"
|
||
for f in ncurses-6.5.tar.gz procps-ng-4.0.4.tar.xz lsof-4.99.4.tar.xz build_devkit.sh DEVKIT.md; do
|
||
[ -s "$OUT/src/$f" ] && pass "T1b src/$f 存在且非空" || fail "T1b 缺 src/$f(P1 未修好)"
|
||
done
|
||
|
||
echo "== 2) 缺文件自愈:删掉构建脚本后再 --with-sources"
|
||
rm -f "$OUT/src/build_devkit.sh"
|
||
run "--with-sources 补齐" bash "$SCRIPT" --with-sources || fail "T2 --with-sources 退出码非 0"
|
||
[ -s "$OUT/src/build_devkit.sh" ] && pass "T2 src/build_devkit.sh 被补回" || fail "T2 未补回 src/build_devkit.sh"
|
||
|
||
echo "== 3) 内容漂移自愈:把 src 里的源码包改坏"
|
||
printf 'tamper\n' >> "$OUT/src/ncurses-6.5.tar.gz"
|
||
run "--with-sources 重铺" bash "$SCRIPT" --with-sources || fail "T3 --with-sources 退出码非 0"
|
||
if cmp -s "$OUT/src/ncurses-6.5.tar.gz" "$MEOW_DEVKIT_WORK/src/ncurses-6.5.tar.gz"; then
|
||
pass "T3 被改坏的源码包已恢复成钉住版本"
|
||
else
|
||
fail "T3 源码包未恢复"
|
||
fi
|
||
|
||
echo "== 4) --verify-only:正常通过"
|
||
run "--verify-only" bash "$SCRIPT" --verify-only && pass "T4a --verify-only 通过" || fail "T4a --verify-only 失败"
|
||
|
||
echo "== 5) --verify-only:能查出 MANIFEST 内容漂移"
|
||
cp "$OUT/MANIFEST.txt" "$TMP/MANIFEST.txt.bak"
|
||
awk 'BEGIN{done=0} { if (!done && $1=="vmstat") { $NF="0000000000000000000000000000000000000000000000000000000000000000"; done=1 } print }' \
|
||
"$TMP/MANIFEST.txt.bak" > "$OUT/MANIFEST.txt"
|
||
if run "--verify-only(MANIFEST 被篡改)" bash "$SCRIPT" --verify-only; then
|
||
fail "T5 --verify-only 未发现 MANIFEST sha 被篡改"
|
||
else
|
||
pass "T5 --verify-only 正确拒绝被篡改的 MANIFEST"
|
||
fi
|
||
cp "$TMP/MANIFEST.txt.bak" "$OUT/MANIFEST.txt"
|
||
run "--verify-only(恢复后)" bash "$SCRIPT" --verify-only && pass "T5b 恢复后重新通过" || fail "T5b 恢复后仍失败"
|
||
|
||
echo "== 6) 交付完整性:删 licenses/ 后 --with-sources 必须恢复"
|
||
LICENSES="procps-ng-4.0.4-COPYING procps-ng-4.0.4-COPYING.LIB ncurses-6.5-COPYING lsof-4.99.4-COPYING musl-COPYRIGHT"
|
||
rm -rf "$OUT/licenses"
|
||
run "--with-sources 补 licenses" bash "$SCRIPT" --with-sources || fail "T6 --with-sources 退出码非 0"
|
||
for f in $LICENSES; do
|
||
[ -s "$OUT/licenses/$f" ] && pass "T6 licenses/$f 已恢复" || fail "T6 缺 licenses/$f"
|
||
done
|
||
|
||
echo "== 7) --verify-only 必须拒绝缺 licenses 的交付"
|
||
rm -rf "$OUT/licenses"
|
||
if run "--verify-only(缺 licenses)" bash "$SCRIPT" --verify-only; then
|
||
fail "T7 --verify-only 未发现 licenses/ 缺失"
|
||
else
|
||
pass "T7 --verify-only 正确拒绝缺 licenses 的交付"
|
||
fi
|
||
run "--with-sources 恢复" bash "$SCRIPT" --with-sources || fail "T7 --with-sources 恢复失败"
|
||
run "--verify-only(恢复后)" bash "$SCRIPT" --verify-only && pass "T7b 恢复后通过" || fail "T7b 恢复后仍失败"
|
||
|
||
echo "== 8) 交付完整性:删 README.txt 后 --with-sources 必须恢复"
|
||
rm -f "$OUT/README.txt"
|
||
run "--with-sources 补 README" bash "$SCRIPT" --with-sources || fail "T8 --with-sources 退出码非 0"
|
||
[ -s "$OUT/README.txt" ] && pass "T8 README.txt 已恢复" || fail "T8 README.txt 未恢复"
|
||
|
||
echo
|
||
printf '== 结果: %d 通过, %d 失败\n' "$PASS" "$FAILN"
|
||
[ "$FAILN" = 0 ]
|