#!/usr/bin/env bash # 实验 2 全量测试脚本 (改进版) # 逻辑参考 verify_ir.sh 与 verify_asm.sh # 增加了批量测试与统计功能,并确保链接 SysY 运行库 (sylib.c) set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" COMPILER="$PROJECT_ROOT/build/bin/compiler" SYLIB="$PROJECT_ROOT/sylib/sylib.c" RESULT_DIR="$PROJECT_ROOT/test/test_result/lab2_full" # 检查依赖 if [[ ! -x "$COMPILER" ]]; then echo "错误:编译器不存在,请先构建项目。" exit 1 fi if [[ ! -f "$SYLIB" ]]; then echo "错误:未找到运行库 $SYLIB" exit 1 fi # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' mkdir -p "$RESULT_DIR" total=0 passed=0 failed=0 run_test() { local input=$1 local base=$(basename "$input") local stem=${base%.sy} local input_dir=$(dirname "$input") local out_file="$RESULT_DIR/$stem.ll" local obj_file="$RESULT_DIR/$stem.o" local exe_file="$RESULT_DIR/$stem" local stdin_file="$input_dir/$stem.in" local expected_file="$input_dir/$stem.out" local actual_file="$RESULT_DIR/$stem.actual.out" local stdout_file="$RESULT_DIR/$stem.stdout" ((total++)) || true echo -n "[$total] 测试 $base ... " # 1. 生成 IR if ! "$COMPILER" --emit-ir "$input" > "$out_file" 2>&1; then echo -e "${RED}IR 生成失败${NC}" ((failed++)) || true return 1 fi # 2. 编译 IR 到对象文件 (llc) if ! llc -filetype=obj "$out_file" -o "$obj_file" > /dev/null 2>&1; then echo -e "${RED}LLVM 编译失败 (llc)${NC}" ((failed++)) || true return 1 fi # 3. 链接运行库 (借鉴 verify_asm.sh 逻辑,但明确包含 sylib.c) if ! clang "$obj_file" "$SYLIB" -o "$exe_file" > /dev/null 2>&1; then echo -e "${RED}链接失败 (clang)${NC}" ((failed++)) || true return 1 fi # 4. 运行程序并捕获输出与退出码 (增加栈空间限制) local status=0 ulimit -s unlimited 2>/dev/null || true if [[ -f "$stdin_file" ]]; then "$exe_file" < "$stdin_file" > "$stdout_file" 2>/dev/null || status=$? else "$exe_file" > "$stdout_file" 2>/dev/null || status=$? fi # 格式化实际输出 (借鉴 verify_ir.sh 格式) { cat "$stdout_file" if [[ -s "$stdout_file" ]] && [[ "$(tail -c 1 "$stdout_file" | wc -l)" -eq 0 ]]; then printf '\n' fi printf '%s\n' "$status" } > "$actual_file" # 5. 比对结果 if [[ -f "$expected_file" ]]; then # 忽略空格差异 (-b -w) if diff -q -b -w "$expected_file" "$actual_file" > /dev/null 2>&1; then echo -e "${GREEN} 通过${NC}" ((passed++)) || true else echo -e "${RED} 输出不匹配${NC}" ((failed++)) || true fi else echo -e "${YELLOW}! 缺少预期输出文件${NC}" ((passed++)) || true fi } # 批量运行 echo "=========================================" echo "实验 2 全量测试开始 (IR 语义验证)" echo "=========================================" echo "" run_batch() { local dir=$1 if [[ ! -d "$dir" ]]; then return; fi echo "正在测试目录: $dir" for sy_file in $(ls "$dir"/*.sy | sort); do run_test "$sy_file" done echo "" } run_batch "$PROJECT_ROOT/test/test_case/functional" run_batch "$PROJECT_ROOT/test/test_case/performance" echo "=========================================" echo "测试结果统计" echo "=========================================" echo -e "总数:$total" echo -e "通过:${GREEN}$passed${NC}" echo -e "失败:${RED}$failed${NC}" echo "" if [[ $failed -eq 0 ]]; then echo -e "${GREEN} 所有测试通过!实验 2 任务完成。${NC}" exit 0 else echo -e "${RED} 有 $failed 个测试失败,请检查逻辑。${NC}" exit 1 fi