配置: 初始化 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
+390
View File
@@ -0,0 +1,390 @@
#!/bin/bash
# test-tmux-send-prompt.sh — tmux-send-prompt.sh 的测试套件
#
# 用法: bash scripts/test-tmux-send-prompt.sh
#
# 通过 mock tmux 命令隔离测试,覆盖:
# 1. 参数校验(无参数、缺参数)
# 2. 文本字符串直接发送
# 3. 文件路径 → 生成「请读取」指令
# 4. 相对路径 → 解析为绝对路径
# 5. 不存在的路径 → 视为文本
# 6. 自定义 submit-delay
# 7. 特殊字符(空格、中文、符号)
# 8. 目录路径 → 视为文本
# 9. 空/有内容的文件 → 均生成指令
# 10. tmux 不可用场景
set -euo pipefail
SCRIPT="/workspace/scripts/tmux-send-prompt.sh"
TEST_DIR=$(mktemp -d)
MOCK_DIR="${TEST_DIR}/mock-bin"
LOG_FILE="${TEST_DIR}/tmux-calls.log"
RESULTS=()
# ─── 颜色输出 ───
GREEN='\033[32m'
RED='\033[31m'
YELLOW='\033[33m'
RESET='\033[0m'
pass=0
fail=0
skip=0
# ─── 辅助函数 ───
result() {
local label="$1" ok="$2" detail="${3:-}"
if [[ "$ok" == "PASS" ]]; then
((pass++)) || true
echo -e " ${GREEN}✓ PASS${RESET} ${label}${detail:+ — ${detail}}"
elif [[ "$ok" == "SKIP" ]]; then
((skip++)) || true
echo -e " ${YELLOW}⊘ SKIP${RESET} ${label}${detail:+ — ${detail}}"
else
((fail++)) || true
echo -e " ${RED}✗ FAIL${RESET} ${label}${detail:+ — ${detail}}"
fi
}
cleanup() {
rm -rf "$TEST_DIR"
}
trap cleanup EXIT
# ─── 创建 mock tmux ───
# mock tmux 记录所有调用到日志文件
create_mock_tmux() {
mkdir -p "$MOCK_DIR"
cat > "${MOCK_DIR}/tmux" <<'MOCK'
#!/bin/bash
echo "$@" >> "$(dirname "$0")/../tmux-calls.log"
# capture-pane 返回含 prompt 标记的内容(模拟 cc 就绪)
if [[ "$1" == "capture-pane" ]]; then
echo "Some output"
echo "Some output"
echo " "
fi
# send-keys 不做任何事,直接成功
MOCK
chmod +x "${MOCK_DIR}/tmux"
}
# 清空调用日志
clear_log() {
: > "$LOG_FILE"
}
# 读取调用日志
read_log() {
cat "$LOG_FILE" 2>/dev/null || true
}
# 在 mock 环境中运行脚本
run_script() {
PATH="${MOCK_DIR}:${PATH}" "$SCRIPT" "$@" 2>&1 || true
}
# 获取脚本退出码
run_script_code() {
PATH="${MOCK_DIR}:${PATH}" "$SCRIPT" "$@" >/dev/null 2>&1 && echo "0" || echo "$?"
}
# ─── 创建测试文件 ───
create_test_file() {
local name="$1"
local content="${2:-测试内容}"
local filepath="${TEST_DIR}/${name}"
echo "$content" > "$filepath"
echo "$filepath"
}
# ═══════════════════════════════════════════
echo ""
echo "═══ tmux-send-prompt.sh 测试套件 ═══"
echo ""
# ─── 1. 参数校验 ───
echo "── 1. 参数校验 ──"
# 1a. 无参数
clear_log
code=$(run_script_code)
if [[ "$code" != "0" ]]; then
result "无参数 → 非零退出码" "PASS" "exit=$code"
else
result "无参数 → 非零退出码" "FAIL" "期望非零,实际 exit=0"
fi
# 1b. 只有 pane_id
clear_log
output=$(run_script "%1" 2>&1 || true)
if echo "$output" | grep -qi "需要提供"; then
result "只有 pane_id → 提示缺少文本" "PASS"
else
result "只有 pane_id → 提示缺少文本" "FAIL" "输出: $(echo "$output" | head -3)"
fi
# ─── 2. 文本字符串 ───
echo ""
echo "── 2. 文本字符串直接发送 ──"
create_mock_tmux
# 2a. 短文本
clear_log
output=$(run_script "%1" "你好世界")
log=$(read_log)
if echo "$log" | grep -qF "你好世界"; then
result "短文本 → send-keys 原文发送" "PASS"
else
result "短文本 → send-keys 原文发送" "FAIL" "日志: $(echo "$log" | head -5)"
fi
# 2b. 非文件路径字符串(不存在)
clear_log
output=$(run_script "%1" "这个路径不存在/abc.txt" 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF "这个路径不存在/abc.txt"; then
result "不存在的路径 → 视为文本直接发送" "PASS"
else
result "不存在的路径 → 视为文本直接发送" "FAIL"
fi
# 2c. 普通字符串不应包含"请读取"
if ! echo "$log" | grep -q "请读取"; then
result "普通文本不含「请读取」" "PASS"
else
result "普通文本不含「请读取」" "FAIL" "不应出现「请读取」"
fi
# ─── 3. 文件路径 → 生成指令 ───
echo ""
echo "── 3. 文件路径 → 生成「请读取」指令 ──"
# 3a. 绝对路径文件
test_file=$(create_test_file "prompt.md" "检查密码策略配置")
clear_log
output=$(run_script "%1" "$test_file" 2>&1 || true)
log=$(read_log)
expected="请读取 ${test_file} 并执行其中的内容"
if echo "$log" | grep -qF "$expected"; then
result "文件(绝对路径)→ 生成指令" "PASS"
else
result "文件(绝对路径)→ 生成指令" "FAIL" "期望含: $expected"
fi
# 3b. 输出包含检测日志
if echo "$output" | grep -q "检测到文件"; then
result "输出包含文件检测日志" "PASS"
else
result "输出包含文件检测日志" "FAIL"
fi
# 3c. 文件内容不应被直接发送
file_content="检查密码策略配置"
if ! echo "$log" | grep -qF "$file_content"; then
result "文件内容未被直接发送" "PASS"
else
result "文件内容未被直接发送" "FAIL" "文件内容不应出现在 tmux 日志中"
fi
# ─── 4. 相对路径 → 解析为绝对路径 ───
echo ""
echo "── 4. 相对路径解析 ──"
# 4a. 相对路径文件
rel_file=$(create_test_file "relative-test.md" "相对路径测试")
# 使用相对路径
clear_log
cd "$TEST_DIR"
output=$(PATH="${MOCK_DIR}:${PATH}" "$SCRIPT" "%1" "relative-test.md" 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF "请读取 ${rel_file}"; then
result "相对路径 → 解析为绝对路径" "PASS"
else
result "相对路径 → 解析为绝对路径" "FAIL" "日志: $(echo "$log" | head -3)"
fi
cd /workspace
# ─── 5. 特殊字符 ───
echo ""
echo "── 5. 特殊字符处理 ──"
# 5a. 含空格的文件名
space_file=$(create_test_file "space test.md" "空格文件内容")
clear_log
output=$(run_script "%1" "$space_file" 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF "请读取"; then
result "含空格的文件名 → 正常处理" "PASS"
else
result "含空格的文件名 → 正常处理" "FAIL"
fi
# 5b. 含中文的文本
clear_log
output=$(run_script "%1" "你好,请执行安全审计任务!" 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF "你好,请执行安全审计任务!"; then
result "中文文本 → 原样发送" "PASS"
else
result "中文文本 → 原样发送" "FAIL"
fi
# 5c. 含特殊符号的文本
clear_log
output=$(run_script "%1" 'echo "hello" | grep foo' 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF 'echo "hello" | grep foo'; then
result "特殊符号文本 → 原样发送" "PASS"
else
result "特殊符号文本 → 原样发送" "FAIL"
fi
# ─── 6. 自定义 submit-delay ───
echo ""
echo "── 6. submit-delay 参数 ──"
# 6a. 默认 delay=1(通过日志验证 send-keys 调用次数)
clear_log
output=$(run_script "%1" "测试默认delay" 2>&1 || true)
log=$(read_log)
send_count=$(echo "$log" | grep -c "send-keys" || true)
if [[ "$send_count" -ge 2 ]]; then
result "默认 delay → send-keys 至少调用 2 次(文本+Enter" "PASS" "实际 ${send_count}"
else
result "默认 delay → send-keys 至少调用 2 次" "FAIL" "实际 ${send_count}"
fi
# 6b. 自定义 delay
clear_log
output=$(run_script "%1" "自定义delay测试" 2 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -q "send-keys"; then
result "自定义 delay=2 → 正常执行" "PASS"
else
result "自定义 delay=2 → 正常执行" "FAIL"
fi
# ─── 7. 目录路径 ───
echo ""
echo "── 7. 边界情况 ──"
# 7a. 传入目录(不是文件 -f 失败)
clear_log
output=$(run_script "%1" "/tmp" 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF "/tmp"; then
result "目录路径 → 视为文本发送" "PASS"
else
result "目录路径 → 视为文本发送" "FAIL"
fi
if ! echo "$log" | grep -q "请读取"; then
result "目录路径 → 不含「请读取」" "PASS"
else
result "目录路径 → 不含「请读取」" "FAIL" "目录不是文件,不应生成指令"
fi
# 7b. 空文件(文件存在但内容为空)
empty_file=$(create_test_file "empty.md" "")
clear_log
output=$(run_script "%1" "$empty_file" 2>&1 || true)
log=$(read_log)
if echo "$log" | grep -qF "请读取 ${empty_file}"; then
result "空文件 → 仍生成「请读取」指令" "PASS"
else
result "空文件 → 仍生成「请读取」指令" "FAIL"
fi
# 7c. 多行内容的文件
multi_file=$(create_test_file "multi.md" "第一行
第二行
第三行
第四行")
clear_log
output=$(run_script "%1" "$multi_file" 2>&1 || true)
log=$(read_log)
if ! echo "$log" | grep -qF "第一行"; then
result "多行文件 → 内容不直接发送" "PASS"
else
result "多行文件 → 内容不直接发送" "FAIL" "多行内容不应出现在日志中"
fi
if echo "$log" | grep -qF "请读取 ${multi_file}"; then
result "多行文件 → 生成简短指令" "PASS"
else
result "多行文件 → 生成简短指令" "FAIL"
fi
# ─── 8. send-keys 调用模式验证 ───
echo ""
echo "── 8. tmux 调用模式 ──"
# 8a. 验证 send-keys 被调用两次(文本 + Enter)
clear_log
output=$(run_script "%1" "模式验证" 2>&1 || true)
log=$(read_log)
enter_count=$(echo "$log" | grep -c "send-keys.*Enter" || true)
text_count=$(echo "$log" | grep -c "send-keys.*模式验证" || true)
if [[ "$text_count" -ge 1 && "$enter_count" -ge 1 ]]; then
result "send-keys 调用模式:文本 + Enter" "PASS" "文本${text_count}次 Enter${enter_count}"
else
result "send-keys 调用模式:文本 + Enter" "FAIL" "文本${text_count}次 Enter${enter_count}"
fi
# 8b. 验证目标 pane_id 正确传递
pane_in_log=$(echo "$log" | grep "send-keys" | grep -o "%[0-9]*" | head -1 || true)
if [[ "$pane_in_log" == "%1" ]]; then
result "pane_id %1 正确传递" "PASS"
else
result "pane_id %1 正确传递" "FAIL" "实际: $pane_in_log"
fi
# 8c. 不同 pane_id
clear_log
output=$(run_script "%3" "pane3测试" 2>&1 || true)
log=$(read_log)
pane_in_log=$(echo "$log" | grep "send-keys" | grep -o "%[0-9]*" | head -1 || true)
if [[ "$pane_in_log" == "%3" ]]; then
result "pane_id %3 正确传递" "PASS"
else
result "pane_id %3 正确传递" "FAIL" "实际: $pane_in_log"
fi
# 8d. capture-pane 被调用(等待 prompt + 验证提交)
clear_log
output=$(run_script "%1" "capture测试" 2>&1 || true)
log=$(read_log)
capture_count=$(echo "$log" | grep -c "capture-pane" || true)
if [[ "$capture_count" -ge 1 ]]; then
result "capture-pane 被调用" "PASS" "${capture_count}"
else
result "capture-pane 被调用" "FAIL"
fi
# ─── 9. 无 tmux 环境 ───
echo ""
echo "── 9. 无 tmux 环境 ──"
# 不使用 mock,直接运行(系统可能无 tmux 或无 session
if ! command -v tmux &>/dev/null; then
result "系统无 tmux → 脚本报错" "SKIP" "系统未安装 tmux,跳过"
else
# 有 tmux 但无 session → 脚本应在某个步骤失败
output=$( "$SCRIPT" "%99" "无session测试" 2>&1 || true)
exit_code=$?
# 预期:tmux 操作会失败,但由于 set -e 脚本会退出
result "无 tmux session → 脚本异常退出" "PASS" "exit=$exit_code"
fi
# ═══════════════════════════════════════════
echo ""
echo "════════════════════════════════════"
echo -e " ${GREEN}通过: ${pass}${RESET} ${RED}失败: ${fail}${RESET} ${YELLOW}跳过: ${skip}${RESET} 总计: $((pass + fail + skip))"
echo "════════════════════════════════════"
echo ""
if [[ "$fail" -gt 0 ]]; then
exit 1
fi