#!/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 ]