#!/bin/bash # backup-mysql.sh 参数解析与校验的 dry-run 测试 # 不实际执行 mysqldump,仅验证参数解析、必填校验、默认值、帮助信息等。 # # 运行方式(需要 bash 环境,如 Git Bash / WSL): # bash infra/backup/test-backup-mysql.sh # # 退出码:0 表示全部通过,非 0 表示有失败用例。 set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT="${SCRIPT_DIR}/backup-mysql.sh" PASS=0 FAIL=0 # assertExit assertExit() { local expected="$1" desc="$2" actual="$3" stderr="${4:-}" if [[ "$actual" == "$expected" ]]; then echo "[PASS] $desc (exit=$actual)" PASS=$((PASS + 1)) else echo "[FAIL] $desc: 期望 exit=$expected, 实际 exit=$actual" [[ -n "$stderr" ]] && echo " stderr: $stderr" FAIL=$((FAIL + 1)) fi } # assertContains assertContains() { local needle="$1" desc="$2" haystack="${3:-}" if [[ "$haystack" == *"$needle"* ]]; then echo "[PASS] $desc" PASS=$((PASS + 1)) else echo "[FAIL] $desc: 输出应包含 '$needle'" echo " 实际输出: $haystack" FAIL=$((FAIL + 1)) fi } echo "=== backup-mysql.sh dry-run 测试 ===" # ---------- 用例 1: 无参数应失败并提示 --service 必填 ---------- output="$("$SCRIPT" 2>&1)" code=$? assertExit 1 "无参数应退出 1" "$code" "$output" assertContains "--service 参数必填" "无参数应提示 --service 必填" "$output" # ---------- 用例 2: --help 应退出 0 并输出 Usage ---------- output="$("$SCRIPT" --help 2>&1)" code=$? assertExit 0 "--help 应退出 0" "$code" "$output" assertContains "Usage:" "--help 应输出 Usage" "$output" assertContains "--service" "--help 应说明 --service 参数" "$output" assertContains "--keep" "--help 应说明 --keep 参数" "$output" # ---------- 用例 3: --keep 默认值(未提供时)应在日志中体现 7 天 ---------- # 设置 MYSQL_PASSWORD 让脚本通过环境变量校验,进入主流程打印日志; # 随后会在 mysqldump 阶段失败(CI 环境无 mysqldump)。 output="$(MYSQL_PASSWORD=fake-pass "$SCRIPT" --service iam 2>&1)" code=$? assertExit 1 "无 mysqldump 时应最终退出 1" "$code" "$output" assertContains "保留 7 天" "未提供 --keep 时应使用默认值 7 天" "$output" # ---------- 用例 4: --keep 非数字应失败 ---------- output="$("$SCRIPT" --service iam --keep abc 2>&1)" code=$? assertExit 1 "--keep 非数字应退出 1" "$code" "$output" assertContains "--keep 必须为正整数" "非数字 --keep 应报错" "$output" # ---------- 用例 5: --keep 小于 1 应失败 ---------- output="$("$SCRIPT" --service iam --keep 0 2>&1)" code=$? assertExit 1 "--keep=0 应退出 1" "$code" "$output" assertContains "--keep 必须为正整数" "--keep=0 应报错" "$output" # ---------- 用例 6: 未知参数应失败 ---------- output="$("$SCRIPT" --service iam --unknown-flag 2>&1)" code=$? assertExit 1 "未知参数应退出 1" "$code" "$output" assertContains "未知参数" "未知参数应报错" "$output" # ---------- 用例 7: --keep 自定义值应在日志中体现 ---------- output="$(MYSQL_PASSWORD=fake-pass "$SCRIPT" --service iam --keep 30 2>&1)" code=$? assertExit 1 "无 mysqldump 时应最终退出 1(用例 7 预置)" "$code" "$output" assertContains "保留 30 天" "--keep=30 应在日志中体现" "$output" # ---------- 用例 8: MYSQL_PASSWORD 已设置但 mysqldump 不可用时应优雅失败 ---------- # 此用例验证:参数校验通过后,脚本会尝试调用 mysqldump;若 mysqldump 不存在则失败。 # 在无 MySQL 容器的 CI 环境中,这是最接近真实 dry-run 的验证。 output="$(MYSQL_PASSWORD=fake-pass "$SCRIPT" --service iam 2>&1)" code=$? # mysqldump 不存在时,pipefail + gzip 写入空文件 → 脚本检测到空文件后 exit 1 # 或 mysqldump 命令未找到 → set -e 触发 exit 1 # 任一路径都应是非 0 退出 if [[ "$code" -ne 0 ]]; then echo "[PASS] mysqldump 不可用时应非 0 退出 (exit=$code)" PASS=$((PASS + 1)) else echo "[FAIL] mysqldump 不可用时不应返回 0" FAIL=$((FAIL + 1)) fi echo "=== 测试结果 ===" echo "通过: $PASS 失败: $FAIL" if [[ "$FAIL" -gt 0 ]]; then exit 1 fi exit 0