286 lines
9.7 KiB
Bash
Executable File
286 lines
9.7 KiB
Bash
Executable File
#!/bin/bash
|
||
# test-tmux-send-prompt-integ.sh — tmux-send-prompt.sh 真实集成测试(可观察模式)
|
||
#
|
||
# 用法: bash scripts/test-tmux-send-prompt-integ.sh
|
||
#
|
||
# 布局:
|
||
# ┌──────────────────┬──────────────────┐
|
||
# │ cc pane (左) │ ctrl pane (右) │
|
||
# │ 接收命令并回复 │ 运行测试、显示 │
|
||
# └──────────────────┴──────────────────┘
|
||
|
||
set -euo pipefail
|
||
|
||
# ─── 配置 ───
|
||
SESSION="test-send"
|
||
SCRIPT="/workspace/scripts/tmux-send-prompt.sh"
|
||
TEST_DIR=$(mktemp -d)
|
||
|
||
# ─── 辅助函数 ───
|
||
|
||
wait_for_prompt() {
|
||
local pane_id="$1" timeout="${2:-120}" desc="${3:-cc prompt}"
|
||
echo -e " \e[36m⏳\e[0m 等待 ${desc}(最多 ${timeout}s)..."
|
||
for i in $(seq 1 "$timeout"); do
|
||
local last_lines
|
||
last_lines=$(tmux capture-pane -t "$pane_id" -p 2>/dev/null | tail -5 || true)
|
||
if echo "$last_lines" | grep -q '❯'; then
|
||
echo -e " \e[36m✓\e[0m ${desc} 就绪(等待 ${i}s)"
|
||
return 0
|
||
fi
|
||
sleep 1
|
||
done
|
||
echo -e " \e[31m✗\e[0m ${desc} 超时"
|
||
return 1
|
||
}
|
||
|
||
# ─── 清理旧 session ───
|
||
tmux kill-session -t "$SESSION" 2>/dev/null || true
|
||
|
||
echo ""
|
||
echo "═══ tmux-send-prompt.sh 集成测试(真实 cc)═══"
|
||
echo ""
|
||
|
||
# ─── 0. 环境检查 ───
|
||
echo "── 0. 环境准备 ──"
|
||
command -v tmux &>/dev/null || { echo " ✗ 系统未安装 tmux"; exit 0; }
|
||
command -v claude &>/dev/null || { echo " ✗ claude 未安装"; exit 0; }
|
||
echo " ✓ tmux + claude 环境就绪"
|
||
|
||
# ─── 1. 创建 tmux session ───
|
||
echo ""
|
||
echo "── 1. 创建测试环境 ──"
|
||
|
||
tmux new-session -d -s "$SESSION" -x 200 -y 50
|
||
CC_PANE=$(tmux display-message -t "$SESSION" -p '#{pane_id}')
|
||
tmux split-window -t "$SESSION" -h
|
||
CTRL_PANE=$(tmux display-message -t "$SESSION" -p '#{pane_id}')
|
||
|
||
echo " ✓ session=$SESSION cc=$CC_PANE ctrl=$CTRL_PANE"
|
||
|
||
echo " → 在 $CC_PANE 启动 claude..."
|
||
tmux send-keys -t "$CC_PANE" "source ~/.bashrc && claude --dangerously-skip-permissions --allow-dangerously-skip-permissions" Enter
|
||
|
||
if ! wait_for_prompt "$CC_PANE" 120 "cc 启动"; then
|
||
echo " ✗ cc 启动失败"
|
||
tmux capture-pane -t "$CC_PANE" -p | tail -10
|
||
exit 1
|
||
fi
|
||
echo " ✓ cc 启动成功"
|
||
|
||
# ─── 2. 生成测试脚本 ───
|
||
echo ""
|
||
echo "── 2. 生成测试脚本 ──"
|
||
|
||
RUNNER="${TEST_DIR}/runner.sh"
|
||
|
||
# 步骤1: 写入 header(单引号 heredoc,不做任何替换)
|
||
cat > "$RUNNER" <<HEADER
|
||
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
CC_PANE="${CC_PANE}"
|
||
SCRIPT="${SCRIPT}"
|
||
TEST_DIR="${TEST_DIR}"
|
||
SESSION="${SESSION}"
|
||
HEADER
|
||
|
||
# 步骤2: 追加颜色定义(用单引号 heredoc 保留 $'...' 原样)
|
||
cat >> "$RUNNER" <<'COLORS'
|
||
|
||
G=$'\e[32m'
|
||
R=$'\e[31m'
|
||
Y=$'\e[33m'
|
||
B=$'\e[1m'
|
||
N=$'\e[0m'
|
||
|
||
pass=0
|
||
fail=0
|
||
|
||
result() {
|
||
local label="$1" ok="$2" detail="${3:-}"
|
||
if [[ "$ok" == "PASS" ]]; then
|
||
((pass++)) || true
|
||
echo " ${G}✓ PASS${N} ${label}${detail:+ — ${detail}}"
|
||
else
|
||
((fail++)) || true
|
||
echo " ${R}✗ FAIL${N} ${label}${detail:+ — ${detail}}"
|
||
fi
|
||
}
|
||
|
||
wait_for_prompt() {
|
||
local pane_id="$1" timeout="${2:-60}"
|
||
for i in $(seq 1 "$timeout"); do
|
||
tmux capture-pane -t "$pane_id" -p 2>/dev/null | tail -5 | grep -q '❯' && return 0
|
||
sleep 1
|
||
done
|
||
return 1
|
||
}
|
||
|
||
wait_for_response() {
|
||
local pane_id="$1" keyword="$2" timeout="${3:-90}"
|
||
for i in $(seq 1 "$timeout"); do
|
||
tmux capture-pane -t "$pane_id" -p -S -50 2>/dev/null | grep -qF "$keyword" && { sleep 2; return 0; }
|
||
sleep 1
|
||
done
|
||
return 1
|
||
}
|
||
|
||
echo ""
|
||
echo "${B}═══ 开始测试 ═══${N}"
|
||
echo ""
|
||
COLORS
|
||
|
||
# 步骤3: 追加测试场景(单引号 heredoc,变量由运行时 bash 解释)
|
||
cat >> "$RUNNER" <<'SCENARIOS'
|
||
|
||
# ── 场景1: 短文本字符串 ──
|
||
echo "${B}── 场景1: 短文本字符串 ──${N}"
|
||
bash "$SCRIPT" "$CC_PANE" "请回复 TEST_OK_短文本" 2>&1 | while read -r line; do echo " $line"; done
|
||
if wait_for_response "$CC_PANE" "TEST_OK_短文本"; then
|
||
result "短文本 → cc 收到并回复" "PASS"
|
||
else
|
||
result "短文本 → cc 收到并回复" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景2: 文件路径 ──
|
||
echo ""
|
||
echo "${B}── 场景2: 文件路径 → cc 自行读取 ──${N}"
|
||
cat > "${TEST_DIR}/test-prompt.md" <<'PROMPT'
|
||
请回复以下确认码:FILE_OK_读取成功
|
||
不要做其他任何事情,只回复确认码。
|
||
PROMPT
|
||
echo " ✓ 测试文件已创建: ${TEST_DIR}/test-prompt.md"
|
||
|
||
bash "$SCRIPT" "$CC_PANE" "${TEST_DIR}/test-prompt.md" 2>&1 | while read -r line; do echo " $line"; done
|
||
sleep 3
|
||
if wait_for_response "$CC_PANE" "FILE_OK"; then
|
||
result "文件路径 → cc 读取文件并回复" "PASS"
|
||
else
|
||
result "文件路径 → cc 读取文件并回复" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景3: 相对路径文件 ──
|
||
echo ""
|
||
echo "${B}── 场景3: 相对路径文件 ──${N}"
|
||
mkdir -p "${TEST_DIR}/subdir"
|
||
cat > "${TEST_DIR}/subdir/relative.md" <<'PROMPT'
|
||
请回复确认码:RELATIVE_OK
|
||
PROMPT
|
||
|
||
pushd "$TEST_DIR" > /dev/null
|
||
bash "$SCRIPT" "$CC_PANE" "subdir/relative.md" 2>&1 | while read -r line; do echo " $line"; done
|
||
popd > /dev/null
|
||
sleep 3
|
||
if wait_for_response "$CC_PANE" "RELATIVE_OK"; then
|
||
result "相对路径 → cc 读取成功" "PASS"
|
||
else
|
||
result "相对路径 → cc 读取成功" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景4: 长文本字符串 ──
|
||
echo ""
|
||
echo "${B}── 场景4: 长文本字符串(200+ 字)──${N}"
|
||
LONG_TEXT="请回复确认码:LONG_OK。以下是一段长文本用于测试:密码管理系统需要满足以下安全要求:第一,所有敏感数据必须使用 AES-256-GCM 加密存储;第二,密码哈希使用 Argon2id 算法,参数为 64MB 内存和 3 次迭代;第三,设备认证使用 Ed25519 椭圆曲线签名;第四,传输层使用 TLS 1.3 双向认证;第五,主密码最少 8 位,必须包含大小写字母、数字和特殊符号。请只回复确认码 LONG_OK。"
|
||
|
||
bash "$SCRIPT" "$CC_PANE" "$LONG_TEXT" 2>&1 | while read -r line; do echo " $line"; done
|
||
if wait_for_response "$CC_PANE" "LONG_OK"; then
|
||
result "长文本(200+字)→ cc 收到并回复" "PASS"
|
||
else
|
||
result "长文本(200+字)→ cc 收到并回复" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景5: 特殊字符 ──
|
||
echo ""
|
||
echo "${B}── 场景5: 特殊字符文本 ──${N}"
|
||
SPECIAL_TEXT='请回复确认码:SPECIAL_OK,包含符号:|、&、$、"hello"、(test)、[array]、{json: true}'
|
||
bash "$SCRIPT" "$CC_PANE" "$SPECIAL_TEXT" 2>&1 | while read -r line; do echo " $line"; done
|
||
if wait_for_response "$CC_PANE" "SPECIAL_OK"; then
|
||
result "特殊字符文本 → cc 收到并回复" "PASS"
|
||
else
|
||
result "特殊字符文本 → cc 收到并回复" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景6: 自定义 submit-delay ──
|
||
echo ""
|
||
echo "${B}── 场景6: 自定义 submit-delay=3 ──${N}"
|
||
bash "$SCRIPT" "$CC_PANE" "请回复确认码:DELAY_OK" 3 2>&1 | while read -r line; do echo " $line"; done
|
||
if wait_for_response "$CC_PANE" "DELAY_OK"; then
|
||
result "自定义 delay=3 → cc 收到并回复" "PASS"
|
||
else
|
||
result "自定义 delay=3 → cc 收到并回复" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景7: 多行内容文件 ──
|
||
echo ""
|
||
echo "${B}── 场景7: 多行内容文件 ──${N}"
|
||
cat > "${TEST_DIR}/multiline.md" <<'PROMPT'
|
||
请按以下步骤回复:
|
||
|
||
1. 回复确认码:MULTI_OK
|
||
2. 不要执行其他任何操作
|
||
3. 直接回复确认码即可
|
||
|
||
感谢配合。
|
||
PROMPT
|
||
|
||
bash "$SCRIPT" "$CC_PANE" "${TEST_DIR}/multiline.md" 2>&1 | while read -r line; do echo " $line"; done
|
||
sleep 3
|
||
if wait_for_response "$CC_PANE" "MULTI_OK"; then
|
||
result "多行文件 → cc 读取并回复" "PASS"
|
||
else
|
||
result "多行文件 → cc 读取并回复" "FAIL"
|
||
fi
|
||
wait_for_prompt "$CC_PANE" 30
|
||
|
||
# ── 场景8: 不存在的路径 ──
|
||
echo ""
|
||
echo "${B}── 场景8: 不存在的路径 → 视为文本 ──${N}"
|
||
bash "$SCRIPT" "$CC_PANE" "请回复确认码:NOTEXIST_OK" 2>&1 | while read -r line; do echo " $line"; done
|
||
if wait_for_response "$CC_PANE" "NOTEXIST_OK"; then
|
||
result "不存在路径字符串 → cc 收到并回复" "PASS"
|
||
else
|
||
result "不存在路径字符串 → cc 收到并回复" "FAIL"
|
||
fi
|
||
|
||
# ── 结果汇总 ──
|
||
echo ""
|
||
echo "════════════════════════════════════"
|
||
echo " ${G}通过: ${pass}${N} ${R}失败: ${fail}${N} 总计: $((pass + fail))"
|
||
echo "════════════════════════════════════"
|
||
echo ""
|
||
echo "提示: 按 Ctrl+B 再按 D 可脱离 session"
|
||
echo " 执行 tmux kill-session -t $SESSION 可清理"
|
||
SCENARIOS
|
||
|
||
chmod +x "$RUNNER"
|
||
echo " ✓ 测试脚本已生成: $RUNNER"
|
||
|
||
# ─── 3. 切换到测试 session ───
|
||
echo ""
|
||
echo "── 3. 启动测试 → 切换到 session ──"
|
||
echo " 左 pane: cc(接收命令)"
|
||
echo " 右 pane: 测试运行器(显示进度)"
|
||
echo ""
|
||
echo " ══════════════════════════════════"
|
||
echo " 即将切换到 tmux session: $SESSION"
|
||
echo " 按 Ctrl+B 再按 s 可切换回原 session"
|
||
echo " ══════════════════════════════════"
|
||
echo ""
|
||
|
||
# 向 ctrl pane 发送执行命令
|
||
tmux send-keys -t "$CTRL_PANE" "sleep 1 && bash $RUNNER" Enter
|
||
|
||
# 切换到测试 session
|
||
if [[ -n "${TMUX:-}" ]]; then
|
||
exec tmux switch-client -t "$SESSION"
|
||
else
|
||
exec tmux attach-session -t "$SESSION"
|
||
fi
|