You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nudt-compiler-cpp/test2.sh

204 lines
5.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/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