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

247 lines
6.2 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"
OUTPUT_DIR="./lab2_results"
COMPILER="./build/bin/compiler"
VERIFY_SCRIPT="./scripts/verify_ir.sh"
VERBOSE=false
FORCE=false
RUN_EXEC=false
MAX_CASES=0
INCLUDE_TEST_CASE=false
show_help() {
cat << 'EOF'
用法: ./test2.sh [选项]
说明:
批量执行 Lab2(IR 生成)测试。
默认会递归扫描 ./test 下所有 .sy 文件(自动跳过 test_result 目录),
并调用 scripts/verify_ir.sh 逐个生成 .ll。
选项:
-d, --dir DIR 测试根目录 (默认: ./test)
-o, --output DIR 输出目录 (默认: ./lab2_results)
-c, --compiler FILE 编译器路径 (默认: ./build/bin/compiler)
-s, --script FILE verify_ir脚本路径 (默认: ./scripts/verify_ir.sh)
-r, --run 生成 IR 后继续 llc/clang 运行校验
-f, --force 强制重跑(覆盖已有 .ll
-v, --verbose 显示详细日志
-m, --max N 最多执行 N 个用例0 表示不限制)
--include-test-case 额外包含 test/test_case 下用例(默认不包含)
-h, --help 显示帮助
示例:
./test2.sh
./test2.sh -r
./test2.sh -d ./test -o ./lab2_results -f -v
./test2.sh --max 20
./test2.sh --include-test-case
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--dir)
TEST_ROOT="$2"
shift 2
;;
-o|--output)
OUTPUT_DIR="$2"
shift 2
;;
-c|--compiler)
COMPILER="$2"
shift 2
;;
-s|--script)
VERIFY_SCRIPT="$2"
shift 2
;;
-r|--run)
RUN_EXEC=true
shift
;;
-f|--force)
FORCE=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-m|--max)
MAX_CASES="$2"
shift 2
;;
--include-test-case)
INCLUDE_TEST_CASE=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"
LOG_FILE="$OUTPUT_DIR/lab2_batch.log"
FAIL_FILE="$OUTPUT_DIR/failed_cases.txt"
: > "$LOG_FILE"
: > "$FAIL_FILE"
echo "Lab2 批量测试日志 - $(date)" >> "$LOG_FILE"
echo "TEST_ROOT=$TEST_ROOT" >> "$LOG_FILE"
echo "OUTPUT_DIR=$OUTPUT_DIR" >> "$LOG_FILE"
echo "RUN_EXEC=$RUN_EXEC FORCE=$FORCE MAX_CASES=$MAX_CASES" >> "$LOG_FILE"
echo "================================================" >> "$LOG_FILE"
mapfile -d '' -t CASES < <(find "$TEST_ROOT" -type f -name '*.sy' \
\( -path "$TEST_ROOT/testdata/*" -o -path "$TEST_ROOT/testdata2022/*" -o -path "$TEST_ROOT/testdata2024/*" \) \
-print0 | sort -z)
if [[ "$INCLUDE_TEST_CASE" = true ]]; then
mapfile -d '' -t EXTRA_CASES < <(find "$TEST_ROOT" -type f -name '*.sy' \
-path "$TEST_ROOT/test_case/*" \
-print0 | sort -z)
CASES+=("${EXTRA_CASES[@]}")
fi
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
SKIPPED=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}运行校验: $RUN_EXEC${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"
out_ll="$case_out_dir/$base_name.ll"
TOTAL=$((TOTAL + 1))
if [[ "$FORCE" = false && -s "$out_ll" ]]; then
SKIPPED=$((SKIPPED + 1))
if [[ "$VERBOSE" = true ]]; then
echo -e "${YELLOW}[$TOTAL] 跳过: $rel_path (已存在)${NC}"
else
echo -ne "${YELLOW}[$TOTAL] $filename ... ${NC}"
echo -e "${YELLOW}跳过${NC}"
fi
echo "[SKIPPED] $file" >> "$LOG_FILE"
continue
fi
mkdir -p "$case_out_dir"
if [[ "$VERBOSE" = true ]]; then
echo -e "${YELLOW}[$TOTAL] 测试: $rel_path${NC}"
else
echo -ne "${YELLOW}[$TOTAL] $filename ... ${NC}"
fi
if [[ "$RUN_EXEC" = true ]]; then
"$VERIFY_SCRIPT" "$file" "$case_out_dir" --run >> "$LOG_FILE" 2>&1
code=$?
else
"$VERIFY_SCRIPT" "$file" "$case_out_dir" >> "$LOG_FILE" 2>&1
code=$?
fi
if [[ $code -eq 0 ]]; then
SUCCESS=$((SUCCESS + 1))
if [[ "$VERBOSE" = true ]]; then
echo -e "${GREEN}✓ 成功: $case_out_dir/$base_name.ll${NC}"
else
echo -e "${GREEN}成功${NC}"
fi
echo "[SUCCESS] $file" >> "$LOG_FILE"
else
FAILED=$((FAILED + 1))
echo "$file" >> "$FAIL_FILE"
if [[ "$VERBOSE" = true ]]; then
echo -e "${RED}✗ 失败: $rel_path${NC}"
else
echo -e "${RED}失败${NC}"
fi
echo "[FAILED] $file (exit=$code)" >> "$LOG_FILE"
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 "${YELLOW}跳过: $SKIPPED${NC}"
echo -e "${BLUE}成功率: ${RATE}%${NC}"
echo -e "${BLUE}日志: $LOG_FILE${NC}"
if [[ $FAILED -gt 0 ]]; then
echo -e "${RED}失败清单: $FAIL_FILE${NC}"
fi
echo -e "${BLUE}========================================${NC}"
exit 0