#!/bin/bash
set -euo pipefail
BIN="${XWCODE_BIN:-./target/release/xwcode}"
TIMEOUT=60
PASS=0; FAIL=0
RUN_ID="test_$(date +%Y%m%d_%H%M%S)"
LOG_DIR="${XWCODE_LOG_DIR:-./.xwcode/test_runs/$RUN_ID}"
EVENT_SRC="${XWCODE_EVENT_DIR:-./.xwcode/events}"
green() { echo -e "\033[32m$1\033[0m"; }
red() { echo -e "\033[31m$1\033[0m"; }
dim() { echo -e "\033[2m$1\033[0m"; }
test_oneshot() {
local id="$1" desc="$2" prompt="$3" grep_for="$4" grep_not="${5:-}"
echo -n " [$id] $desc ... "
local start=$(date +%s)
local output
output=$(timeout $TIMEOUT "$BIN" -p "$prompt" --max-steps 5 --no-tui 2>&1) || true
local elapsed=$(($(date +%s) - start))
echo "$output" > "$LOG_DIR/${id}_output.txt"
local result="PASS"
if [ -n "$grep_for" ] && ! echo "$output" | grep "$grep_for" >/dev/null; then
result="FAIL: expected '$grep_for' not found"
fi
if [ -n "$grep_not" ] && echo "$output" | grep "$grep_not" >/dev/null; then
result="FAIL: unwanted '$grep_not' found"
fi
if [ "$result" = "PASS" ]; then
green "PASS (${elapsed}s)"; PASS=$((PASS+1))
else
red "$result (${elapsed}s)"; FAIL=$((FAIL+1))
dim " prompt: $prompt"
dim " output: $(echo "$output" | grep -E '\[tool\]|tool err|tool ok|Error|未知工具|权限' | head -5)"
fi
}
mkdir -p "$LOG_DIR"
echo "=== xwcode 功能验证 ($(date '+%Y-%m-%d %H:%M:%S')) ===" | tee "$LOG_DIR/summary.txt"
echo "Binary: $BIN" | tee -a "$LOG_DIR/summary.txt"
echo "Log: $LOG_DIR" | tee -a "$LOG_DIR/summary.txt"
echo "" | tee -a "$LOG_DIR/summary.txt"
echo "── P0: 基础交互 ──" | tee -a "$LOG_DIR/summary.txt"
test_oneshot "T01" "问候不调工具" \
"你好,简单打个招呼" \
"" \
"\[tool\]"
test_oneshot "T02" "简单问答不调工具" \
"Rust 中 Vec 和数组有什么区别?用文字简要回答即可" \
"" \
"\[tool\]"
test_oneshot "T03" "代码阅读可用 tree_view" \
"tree_view ." \
"tool ok"
test_oneshot "T04" "代码阅读可用 read_file" \
"读取 Cargo.toml 文件内容" \
"tool ok"
test_oneshot "T05" "代码搜索可用 grep_search" \
"搜索项目中 main 函数的定义" \
"tool ok"
echo "── P1: 无回归 ──" | tee -a "$LOG_DIR/summary.txt"
test_oneshot "T11" "tree_view 不报未知工具" \
"调用 tree_view . 查看目录" \
"" \
"未知工具.*tree_view"
test_oneshot "T12" "不报权限拒绝" \
"记住测试项:xwcode 冒烟测试通过" \
"" \
"权限拒绝\|DangerFullAccess"
echo "── P2: 分析连续性 ──" | tee -a "$LOG_DIR/summary.txt"
test_oneshot "T21" "分析任务允许多次调用" \
"分析 Cargo.toml 和 Cargo.lock 两个文件,总结项目依赖" \
"tool ok" \
""
echo "" | tee -a "$LOG_DIR/summary.txt"
echo "── 采集 EventLog ──" | tee -a "$LOG_DIR/summary.txt"
if [ -d "$EVENT_SRC" ]; then
if [ -f "$EVENT_SRC/model_calls.jsonl" ]; then
tail -50 "$EVENT_SRC/model_calls.jsonl" > "$LOG_DIR/model_calls.jsonl" 2>/dev/null || true
echo " model_calls: $(wc -l < "$LOG_DIR/model_calls.jsonl") lines" | tee -a "$LOG_DIR/summary.txt"
fi
if [ -f "$EVENT_SRC/tool_outputs.jsonl" ]; then
tail -50 "$EVENT_SRC/tool_outputs.jsonl" > "$LOG_DIR/tool_outputs.jsonl" 2>/dev/null || true
echo " tool_outputs: $(wc -l < "$LOG_DIR/tool_outputs.jsonl") lines" | tee -a "$LOG_DIR/summary.txt"
fi
if [ -f "$EVENT_SRC/phase_timing.jsonl" ]; then
tail -20 "$EVENT_SRC/phase_timing.jsonl" > "$LOG_DIR/phase_timing.jsonl" 2>/dev/null || true
echo " phase_timing: $(wc -l < "$LOG_DIR/phase_timing.jsonl") lines" | tee -a "$LOG_DIR/summary.txt"
fi
fi
echo "" | tee -a "$LOG_DIR/summary.txt"
echo "=== 结果: $PASS/8 pass ===" | tee -a "$LOG_DIR/summary.txt"
[ $FAIL -eq 0 ] && green "全部通过 ✅" || red "有 $FAIL 项失败 ❌"
cat > "$LOG_DIR/report.json" << EOF
{
"run_id": "$RUN_ID",
"timestamp": "$(date -Iseconds)",
"binary": "$BIN",
"passed": $PASS,
"failed": $FAIL,
"total": 8,
"log_dir": "$LOG_DIR"
}
EOF
echo "报告: $LOG_DIR/report.json"
exit $FAIL