forked from NUDT-compiler/nudt-compiler-cpp
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.
143 lines
3.7 KiB
143 lines
3.7 KiB
#!/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
|