配置: 初始化 ISOS Agent Teams 软件研发模板
CI / lint (push) Successful in 6s

This commit is contained in:
2026-04-19 21:47:08 +08:00
parent 3ab6fe6504
commit 34346be862
202 changed files with 23544 additions and 0 deletions
+285
View File
@@ -0,0 +1,285 @@
#!/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