|
|
#!/usr/bin/env bash
|
|
|
# test2.sh - Lab2(IR生成)批量测试脚本
|
|
|
|
|
|
set -u
|
|
|
set -o pipefail
|
|
|
|
|
|
RED='\033[0;31m'
|
|
|
GREEN='\033[0;32m'
|
|
|
YELLOW='\033[1;33m'
|
|
|
BLUE='\033[0;34m'
|
|
|
NC='\033[0m'
|
|
|
|
|
|
TEST_ROOT="./test_todo"
|
|
|
OUTPUT_DIR="./lab2_results"
|
|
|
COMPILER="./build/bin/compiler"
|
|
|
VERIFY_SCRIPT="./scripts/verify_ir.sh"
|
|
|
MAX_CASES=0
|
|
|
STOP_ON_FIRST_FAILURE=false
|
|
|
|
|
|
show_help() {
|
|
|
cat << 'EOF'
|
|
|
用法: ./test2.sh [选项]
|
|
|
|
|
|
说明:
|
|
|
批量执行 Lab2(IR 生成)测试。
|
|
|
默认会递归扫描 test/test_case 下所有 .sy 文件,
|
|
|
调用 scripts/verify_ir.sh 生成 IR 并运行校验。
|
|
|
|
|
|
选项:
|
|
|
-m, --max N 最多执行 N 个用例(0 表示不限制,默认: 0)
|
|
|
-x, --stop-on-fail 遇到第一个失败时停止
|
|
|
-h, --help 显示帮助
|
|
|
|
|
|
示例:
|
|
|
./test2.sh
|
|
|
./test2.sh --max 20
|
|
|
./test2.sh --stop-on-fail
|
|
|
EOF
|
|
|
}
|
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
case "$1" in
|
|
|
-m|--max)
|
|
|
MAX_CASES="$2"
|
|
|
shift 2
|
|
|
;;
|
|
|
-x|--stop-on-fail)
|
|
|
STOP_ON_FIRST_FAILURE=true
|
|
|
shift
|
|
|
;;
|
|
|
-h|--help)
|
|
|
show_help
|
|
|
exit 0
|
|
|
;;
|
|
|
*)
|
|
|
echo -e "${RED}错误: 未知选项 $1${NC}"
|
|
|
show_help
|
|
|
exit 1
|
|
|
;;
|
|
|
esac
|
|
|
done
|
|
|
|
|
|
if [[ ! -d "$TEST_ROOT" ]]; then
|
|
|
echo -e "${RED}错误: 测试目录不存在: $TEST_ROOT${NC}"
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
if [[ ! -x "$COMPILER" ]]; then
|
|
|
echo -e "${RED}错误: 编译器不可执行: $COMPILER${NC}"
|
|
|
echo -e "${YELLOW}提示: 请先构建: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j \"\$(nproc)\"${NC}"
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
if [[ ! -x "$VERIFY_SCRIPT" ]]; then
|
|
|
echo -e "${RED}错误: verify脚本不可执行: $VERIFY_SCRIPT${NC}"
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
if ! [[ "$MAX_CASES" =~ ^[0-9]+$ ]]; then
|
|
|
echo -e "${RED}错误: --max 需要非负整数${NC}"
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
|
|
# 删除旧的输出目录,确保每次运行都是全新的
|
|
|
if [[ -d "$OUTPUT_DIR" ]]; then
|
|
|
echo "正在删除旧的输出目录..."
|
|
|
rm -rf "$OUTPUT_DIR"/*
|
|
|
echo "已删除旧的输出目录"
|
|
|
fi
|
|
|
|
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
|
|
LOG_FILE="$OUTPUT_DIR/lab2_batch.log"
|
|
|
FAIL_FILE="$OUTPUT_DIR/failed_cases.txt"
|
|
|
ERROR_LOG_FILE="$OUTPUT_DIR/error_log.txt"
|
|
|
: > "$LOG_FILE"
|
|
|
: > "$FAIL_FILE"
|
|
|
: > "$ERROR_LOG_FILE"
|
|
|
|
|
|
echo "Lab2 批量测试日志 - $(date)" >> "$LOG_FILE"
|
|
|
echo "TEST_ROOT=$TEST_ROOT" >> "$LOG_FILE"
|
|
|
echo "OUTPUT_DIR=$OUTPUT_DIR" >> "$LOG_FILE"
|
|
|
echo "MAX_CASES=$MAX_CASES" >> "$LOG_FILE"
|
|
|
echo "================================================" >> "$LOG_FILE"
|
|
|
|
|
|
mapfile -d '' -t CASES < <(find "$TEST_ROOT" -type f -name '*.sy' -print0 | sort -z)
|
|
|
|
|
|
TOTAL_FOUND=${#CASES[@]}
|
|
|
if [[ $TOTAL_FOUND -eq 0 ]]; then
|
|
|
echo -e "${YELLOW}未找到任何 .sy 用例,请检查目录: $TEST_ROOT${NC}"
|
|
|
exit 0
|
|
|
fi
|
|
|
|
|
|
TOTAL=0
|
|
|
SUCCESS=0
|
|
|
FAILED=0
|
|
|
|
|
|
echo -e "${BLUE}========================================${NC}"
|
|
|
echo -e "${BLUE}Lab2 批量测试开始${NC}"
|
|
|
echo -e "${BLUE}测试根目录: $TEST_ROOT${NC}"
|
|
|
echo -e "${BLUE}找到用例数: $TOTAL_FOUND${NC}"
|
|
|
echo -e "${BLUE}输出目录: $OUTPUT_DIR${NC}"
|
|
|
echo -e "${BLUE}========================================${NC}"
|
|
|
|
|
|
for file in "${CASES[@]}"; do
|
|
|
if [[ $MAX_CASES -gt 0 && $TOTAL -ge $MAX_CASES ]]; then
|
|
|
break
|
|
|
fi
|
|
|
|
|
|
rel_path="${file#$TEST_ROOT/}"
|
|
|
filename="$(basename "$file")"
|
|
|
base_name="${filename%.sy}"
|
|
|
rel_dir="$(dirname "$rel_path")"
|
|
|
case_out_dir="$OUTPUT_DIR/$rel_dir"
|
|
|
|
|
|
TOTAL=$((TOTAL + 1))
|
|
|
|
|
|
mkdir -p "$case_out_dir"
|
|
|
|
|
|
# 删除已有的输出文件,确保重新生成
|
|
|
rm -f "$case_out_dir/$base_name.ll"
|
|
|
rm -f "$case_out_dir/$base_name.o"
|
|
|
rm -f "$case_out_dir/$base_name"
|
|
|
rm -f "$case_out_dir/$base_name.stdout"
|
|
|
rm -f "$case_out_dir/$base_name.actual.out"
|
|
|
|
|
|
echo -ne "${YELLOW}[$TOTAL] $filename ... ${NC}"
|
|
|
|
|
|
# 捕获验证脚本的输出,用于错误日志
|
|
|
"$VERIFY_SCRIPT" "$file" "$case_out_dir" --run >> "$LOG_FILE" 2>&1
|
|
|
code=$?
|
|
|
|
|
|
if [[ $code -eq 0 ]]; then
|
|
|
SUCCESS=$((SUCCESS + 1))
|
|
|
echo -e "${GREEN}成功${NC}"
|
|
|
echo "[SUCCESS] $file" >> "$LOG_FILE"
|
|
|
else
|
|
|
FAILED=$((FAILED + 1))
|
|
|
echo "$file" >> "$FAIL_FILE"
|
|
|
echo -e "${RED}失败${NC}"
|
|
|
echo "[FAILED] $file (exit=$code)" >> "$LOG_FILE"
|
|
|
|
|
|
# 写入详细错误信息到错误日志
|
|
|
echo "========================================" >> "$ERROR_LOG_FILE"
|
|
|
echo "测试失败: $file" >> "$ERROR_LOG_FILE"
|
|
|
echo "退出码: $code" >> "$ERROR_LOG_FILE"
|
|
|
echo "时间: $(date)" >> "$ERROR_LOG_FILE"
|
|
|
echo "详细输出:" >> "$ERROR_LOG_FILE"
|
|
|
"$VERIFY_SCRIPT" "$file" "$case_out_dir" --run 2>&1 >> "$ERROR_LOG_FILE"
|
|
|
echo "========================================" >> "$ERROR_LOG_FILE"
|
|
|
|
|
|
if [[ "$STOP_ON_FIRST_FAILURE" = true ]]; then
|
|
|
echo -e "${RED}========================================${NC}"
|
|
|
echo -e "${RED}在第一个失败处停止测试${NC}"
|
|
|
echo -e "${RED}失败文件: $file${NC}"
|
|
|
echo -e "${RED}日志: $LOG_FILE${NC}"
|
|
|
echo -e "${RED}错误日志: $ERROR_LOG_FILE${NC}"
|
|
|
echo -e "${RED}========================================${NC}"
|
|
|
break
|
|
|
fi
|
|
|
fi
|
|
|
done
|
|
|
|
|
|
RATE="0.00"
|
|
|
if [[ $TOTAL -gt 0 ]]; then
|
|
|
RATE=$(awk -v s="$SUCCESS" -v t="$TOTAL" 'BEGIN { printf "%.2f", (s*100.0)/t }')
|
|
|
fi
|
|
|
|
|
|
echo -e "${BLUE}========================================${NC}"
|
|
|
echo -e "${BLUE}Lab2 批量测试完成${NC}"
|
|
|
echo -e "${BLUE}执行用例: $TOTAL${NC}"
|
|
|
echo -e "${GREEN}成功: $SUCCESS${NC}"
|
|
|
echo -e "${RED}失败: $FAILED${NC}"
|
|
|
echo -e "${BLUE}成功率: ${RATE}%${NC}"
|
|
|
echo -e "${BLUE}日志: $LOG_FILE${NC}"
|
|
|
if [[ $FAILED -gt 0 ]]; then
|
|
|
echo -e "${RED}失败清单: $FAIL_FILE${NC}"
|
|
|
echo -e "${RED}错误日志: $ERROR_LOG_FILE${NC}"
|
|
|
fi
|
|
|
echo -e "${BLUE}========================================${NC}"
|
|
|
|
|
|
exit 0 |