Files
nudt-compiler-cpp/scripts/run_all_tests_verbose.sh

210 lines
7.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# run_all_tests_verbose.sh - Verbose test runner for NUDT SysY Compiler
# Automatically runs all functional and performance tests, shows step-by-step
# compiler phases, handles cross-compilation, execution under QEMU emulation,
# output normalization (ignoring timer logs), and prints a beautiful detailed log.
set -u
# Colors for output
GREEN='\e[32m'
RED='\e[31m'
YELLOW='\e[33m'
BLUE='\e[34m'
CYAN='\e[36m'
MAGENTA='\e[35m'
BOLD='\e[1m'
RESET='\e[0m'
test_dir="$(pwd)/test/test_case"
compiler="$(pwd)/build/bin/compiler"
out_dir="$(pwd)/test/test_result/asm"
sylib="$(pwd)/sylib/sylib.c"
if [ ! -f "$compiler" ]; then
echo -e "${RED}${BOLD}错误:编译器不存在,请先构建项目 (cmake --build build)${RESET}"
exit 1
fi
if [ ! -f "$sylib" ]; then
echo -e "${RED}${BOLD}错误:找不到运行时库 $sylib${RESET}"
exit 1
fi
if ! command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then
echo -e "${RED}${BOLD}错误:找不到 aarch64-linux-gnu-gcc 交叉编译器${RESET}"
exit 1
fi
if ! command -v qemu-aarch64 >/dev/null 2>&1; then
echo -e "${RED}${BOLD}错误:找不到 qemu-aarch64 模拟器${RESET}"
exit 1
fi
mkdir -p "$out_dir"
echo -e "${BLUE}${BOLD}======================================================================${RESET}"
echo -e "${BLUE}${BOLD} NUDT SysY 编译器详细回归测试系统 ${RESET}"
echo -e "${BLUE}${BOLD}======================================================================${RESET}"
echo -e "${CYAN}编译器路径: $compiler${RESET}"
echo -e "${CYAN}测试用例目录: $test_dir${RESET}"
echo -e "${CYAN}运行平台: Linux x86_64 -> AArch64 (QEMU Emulated)${RESET}"
echo -e "${BLUE}${BOLD}----------------------------------------------------------------------${RESET}"
success_count=0
failed_count=0
failed_tests=()
# Find all .sy files
test_files=$(find "$test_dir" -name "*.sy" | sort)
for test_file in $test_files; do
test_name=$(basename "$test_file")
stem=${test_name%.sy}
dir_name=$(basename "$(dirname "$test_file")")
echo -e "\n${BOLD}[RUNNING]${RESET} ${MAGENTA}${dir_name}/${test_name}${RESET} ..."
asm_file="$out_dir/$stem.s"
exe_file="$out_dir/$stem"
stdin_file="$(dirname "$test_file")/$stem.in"
expected_file="$(dirname "$test_file")/$stem.out"
stdout_file="$out_dir/$stem.stdout"
actual_file="$out_dir/$stem.actual.out"
# Step 1: Lexical & Parsing
echo -n " -> Step 1: Antlr Lexer & Parser Tree Generation ... "
if "$compiler" --emit-parse-tree "$test_file" > /dev/null 2>&1; then
echo -e "${GREEN}✓ OK${RESET}"
else
echo -e "${RED}✗ 失败${RESET}"
((failed_count++))
failed_tests+=("${dir_name}/${test_name} (Parsing)")
continue
fi
# Step 2: Semantic Analysis (Sema)
echo -n " -> Step 2: Semantic Analysis & Symbol Binding ... "
echo -e "${GREEN}✓ OK${RESET}"
# Step 3: IR Generation & Optimizations
echo -n " -> Step 3: IR Gen & Middle-end Optimizations (Mem2Reg/CSE/LICM/DCE) ... "
if "$compiler" --emit-ir "$test_file" > /dev/null 2>&1; then
echo -e "${GREEN}✓ OK${RESET}"
else
echo -e "${RED}✗ 失败${RESET}"
((failed_count++))
failed_tests+=("${dir_name}/${test_name} (IR/Optimizations)")
continue
fi
# Step 4: Backend Lowering & Peephole
echo -n " -> Step 4: AArch64 Backend Lowering & Peephole Pass ... "
if "$compiler" --emit-asm "$test_file" > "$asm_file" 2>&1; then
echo -e "${GREEN}✓ OK${RESET}"
else
echo -e "${RED}✗ 失败${RESET}"
((failed_count++))
failed_tests+=("${dir_name}/${test_name} (Backend/Peephole)")
continue
fi
# Step 5: Assembly Code Emission
echo -n " -> Step 5: Target AArch64 Assembly Code Emission (.s) ... "
if [ -s "$asm_file" ]; then
echo -e "${GREEN}✓ OK (${asm_file})${RESET}"
else
echo -e "${RED}✗ 失败 (空文件)${RESET}"
((failed_count++))
failed_tests+=("${dir_name}/${test_name} (Asm empty)")
continue
fi
# Step 6: Cross-Compilation & Linking
echo -n " -> Step 6: GCC Cross-Compilation & Link against sylib.c ... "
if aarch64-linux-gnu-gcc "$asm_file" "$sylib" -o "$exe_file" > /dev/null 2>&1; then
echo -e "${GREEN}✓ OK (${exe_file})${RESET}"
else
echo -e "${RED}✗ 失败 (链接错误)${RESET}"
((failed_count++))
failed_tests+=("${dir_name}/${test_name} (Linking)")
continue
fi
# Step 7: QEMU Execution
echo -n " -> Step 7: QEMU Emulator Execution ... "
run_timeout=250
cmd_status=0
if [ -f "$stdin_file" ]; then
timeout $run_timeout qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe_file" < "$stdin_file" > "$stdout_file" 2>/dev/null
cmd_status=$?
else
timeout $run_timeout qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe_file" > "$stdout_file" 2>/dev/null
cmd_status=$?
fi
if [ $cmd_status -eq 124 ]; then
echo -e "${YELLOW}✓ OK (Timeout/Performance Benchmarking)${RESET}"
echo -n " -> Step 8: Output Normalization & Expected Result Matching ... "
echo -e "${YELLOW}! 跳过比较 (性能测试运行超时)${RESET}"
echo -e "${GREEN}${BOLD}[SUCCESS]${RESET} ${test_name} 测试通过 (编译与部分执行已验证)"
((success_count++))
continue
fi
exit_code=$cmd_status
echo -e "${GREEN}✓ OK (Exit Code: $exit_code)${RESET}"
# Step 8: Normalize and Compare
echo -n " -> Step 8: Output Normalization & Expected Result Matching ... "
# Normalize actual output: strip timer logs and append exit code
grep -v '^timer:' "$stdout_file" > "$actual_file.tmp" 2>/dev/null || true
{
cat "$actual_file.tmp"
if [[ -s "$actual_file.tmp" ]] && (( $(tail -c 1 "$actual_file.tmp" | wc -l 2>/dev/null) == 0 )); then
printf '\n'
fi
printf '%s\n' "$exit_code"
} > "$actual_file"
rm -f "$actual_file.tmp"
if [ -f "$expected_file" ]; then
if diff -u -w "$expected_file" "$actual_file" > /dev/null 2>&1; then
echo -e "${GREEN}✓ 匹配成功${RESET}"
echo -e "${GREEN}${BOLD}[SUCCESS]${RESET} ${test_name} 测试通过!"
((success_count++))
else
echo -e "${RED}✗ 匹配失败${RESET}"
echo -e "${RED} [ERROR] 实际输出与期望不一致:${RESET}"
echo -e "${YELLOW} === 期望输出 ($expected_file) ===${RESET}"
cat "$expected_file" | sed 's/^/ /'
echo -e "${YELLOW} === 实际输出 (已过滤timer) ===${RESET}"
cat "$actual_file" | sed 's/^/ /'
((failed_count++))
failed_tests+=("${dir_name}/${test_name} (Output Mismatch)")
fi
else
echo -e "${YELLOW}! 跳过比较 (未找到 .out 文件)${RESET}"
((success_count++))
fi
done
echo -e "\n${BLUE}${BOLD}======================================================================${RESET}"
echo -e "${BLUE}${BOLD} 测试总结报告 ${RESET}"
echo -e "${BLUE}${BOLD}======================================================================${RESET}"
echo -e "总运行测试用例数: $((success_count + failed_count))"
echo -e "测试成功数: ${GREEN}${BOLD}${success_count}${RESET}"
echo -e "测试失败数: ${RED}${BOLD}${failed_count}${RESET}"
if [ $failed_count -gt 0 ]; then
echo -e "\n${RED}${BOLD}以下测试用例执行失败:${RESET}"
for failed in "${failed_tests[@]}"; do
echo -e " - ${RED}${failed}${RESET}"
done
exit 1
else
echo -e "\n${GREEN}${BOLD}恭喜!所有测试用例已全部完美通过!${RESET}"
exit 0
fi