[backend]更新脚本和库以支持性能测试用例

This commit is contained in:
Lixuanwang
2025-07-31 16:42:41 +08:00
parent 0727d5a6d8
commit e8699d6d25
177 changed files with 610979 additions and 63 deletions

View File

@ -23,7 +23,7 @@ EXECUTE_MODE=false
CLEAN_MODE=false
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=600 # qemu 自动化执行超时 (秒)
EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒)
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
SY_FILES=() # 存储用户提供的 .sy 文件列表
PASSED_CASES=0
@ -68,66 +68,60 @@ display_file_content() {
fi
}
# --- 参数解析 ---
# 从参数中分离出 .sy 文件和选项
for arg in "$@"; do
case "$arg" in
-e|--executable)
EXECUTE_MODE=true
;;
-c|--clean)
CLEAN_MODE=true
shift
;;
-sct|-gct|-et|-ml|--max-lines)
# 选项和其值将在下一个循环中处理
;;
-h|--help)
show_help
exit 0
;;
-*)
# 检查是否是带值的选项
if ! [[ ${args_processed+x} ]]; then
args_processed=true # 标记已处理过参数
# 重新处理所有参数
while [[ "$#" -gt 0 ]]; do
case "$1" in
-sct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi ;;
-gct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi ;;
-et) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi ;;
-ml|--max-lines) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi ;;
*.sy) SY_FILES+=("$1") ;;
-e|--executable) ;; # 已在外部处理
*) if ! [[ "$1" =~ ^[0-9]+$ ]]; then echo "未知选项或无效文件: $1"; show_help; exit 1; fi ;;
esac
shift
done
fi
;;
*.sy)
if [[ -f "$arg" ]]; then
SY_FILES+=("$arg")
else
echo "警告: 文件不存在,已忽略: $arg"
fi
;;
esac
# --- 本次修改点: 整个参数解析逻辑被重写 ---
# 使用标准的 while 循环来健壮地处理任意顺序的参数
while [[ "$#" -gt 0 ]]; do
case "$1" in
-e|--executable)
EXECUTE_MODE=true
shift # 消耗选项
;;
-c|--clean)
CLEAN_MODE=true
shift # 消耗选项
;;
-sct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
;;
-gct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift 2; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi
;;
-et)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift 2; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi
;;
-ml|--max-lines)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift 2; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi
;;
-h|--help)
show_help
exit 0
;;
-*) # 未知选项
echo "未知选项: $1"
show_help
exit 1
;;
*) # 其他参数被视为文件路径
if [[ -f "$1" && "$1" == *.sy ]]; then
SY_FILES+=("$1")
else
echo "警告: 无效文件或不是 .sy 文件,已忽略: $1"
fi
shift # 消耗文件参数
;;
esac
done
if ${CLEAN_MODE}; then
echo "检测到 -c/--clean 选项,正在清空 ${TMP_DIR}..."
if [ -d "${TMP_DIR}" ]; then
# 使用 * 而不是 . 来确保只删除内容,不删除目录本身
# 忽略 rm 可能因目录为空而报告的错误
rm -rf "${TMP_DIR}"/* 2>/dev/null
echo "清理完成。"
else
echo "临时目录 ${TMP_DIR} 不存在,无需清理。"
fi
# 如果只提供了 -c 选项而没有其他 .sy 文件,则在清理后退出
if [ ${#SY_FILES[@]} -eq 0 ] && ! ${EXECUTE_MODE}; then
exit 0
fi
@ -218,7 +212,6 @@ for sy_file in "${SY_FILES[@]}"; do
is_passed=0
else
if [ -f "${output_reference_file}" ]; then
# 此处逻辑与 runit.sh 相同
LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]')
if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
@ -226,7 +219,6 @@ for sy_file in "${SY_FILES[@]}"; do
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
if [ "$ACTUAL_RETURN_CODE" -ne "$EXPECTED_RETURN_CODE" ]; then echo -e "\e[31m 返回码测试失败: 期望 ${EXPECTED_RETURN_CODE}, 实际 ${ACTUAL_RETURN_CODE}\e[0m"; is_passed=0; fi
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if ! diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[31m 标准输出测试失败。\e[0m"
is_passed=0
@ -235,7 +227,6 @@ for sy_file in "${SY_FILES[@]}"; do
echo -e " \e[36m----------------\e[0m"
fi
else
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 标准输出测试成功。\e[0m"
else

View File

@ -22,6 +22,7 @@ SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # qemu 执行超时 (秒)
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
TEST_SETS=() # 用于存储要运行的测试集
TOTAL_CASES=0
PASSED_CASES=0
FAILED_CASES_LIST="" # 用于存储未通过的测例列表
@ -34,6 +35,7 @@ show_help() {
echo "选项:"
echo " -e, --executable 编译为可执行文件并运行测试。"
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
echo " -set [f|h|p|all]... 指定要运行的测试集 (functional, h_functional, performance)。可多选,默认为 all。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
echo " -et N 设置 qemu 执行超时为 N 秒 (默认: 5)。"
@ -77,22 +79,31 @@ while [[ "$#" -gt 0 ]]; do
case "$1" in
-e|--executable)
EXECUTE_MODE=true
shift
;;
-c|--clean)
clean_tmp
exit 0
;;
-set)
shift # 移过 '-set'
# 消耗所有后续参数直到遇到下一个选项
while [[ "$#" -gt 0 && ! "$1" =~ ^- ]]; do
TEST_SETS+=("$1")
shift
done
;;
-sct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
;;
-gct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift 2; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi
;;
-et)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift 2; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi
;;
-ml|--max-lines)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift 2; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi
;;
-h|--help)
show_help
@ -104,11 +115,37 @@ while [[ "$#" -gt 0 ]]; do
exit 1
;;
esac
shift
done
# --- 本次修改点: 根据 -set 参数构建查找路径 ---
declare -A SET_MAP
SET_MAP[f]="functional"
SET_MAP[h]="h_functional"
SET_MAP[p]="performance"
SEARCH_PATHS=()
# 如果未指定测试集,或指定了 'all',则搜索所有目录
if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then
SEARCH_PATHS+=("${TESTDATA_DIR}")
else
for set in "${TEST_SETS[@]}"; do
if [[ -v SET_MAP[$set] ]]; then
SEARCH_PATHS+=("${TESTDATA_DIR}/${SET_MAP[$set]}")
else
echo -e "\e[33m警告: 未知的测试集 '$set',已忽略。\e[0m"
fi
done
fi
# 如果没有有效的搜索路径,则退出
if [ ${#SEARCH_PATHS[@]} -eq 0 ]; then
echo -e "\e[31m错误: 没有找到有效的测试集目录,测试中止。\e[0m"
exit 1
fi
echo "SysY 测试运行器启动..."
echo "输入目录: ${TESTDATA_DIR}"
echo "输入目录: ${SEARCH_PATHS[@]}"
echo "临时目录: ${TMP_DIR}"
echo "执行模式: ${EXECUTE_MODE}"
if ${EXECUTE_MODE}; then
@ -117,8 +154,12 @@ if ${EXECUTE_MODE}; then
fi
echo ""
# --- 修改点: 查找所有 .sy 文件并按文件名前缀数字排序 ---
sy_files=$(find "${TESTDATA_DIR}" -name "*.sy" | sort -V)
# 使用构建好的路径查找 .sy 文件并排序
sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V)
if [ -z "$sy_files" ]; then
echo "在指定目录中未找到任何 .sy 文件。"
exit 0
fi
TOTAL_CASES=$(echo "$sy_files" | wc -w)
# --- 修复: 使用 here-string (<<<) 代替管道 (|) 来避免子 shell 问题 ---
@ -204,7 +245,6 @@ while IFS= read -r sy_file; do
is_passed=0
fi
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if ! diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[31m 标准输出测试失败\e[0m"
is_passed=0
@ -217,7 +257,6 @@ while IFS= read -r sy_file; do
echo -e "\e[33m警告: 程序以非零状态 ${ACTUAL_RETURN_CODE} 退出 (纯输出比较模式)。\e[0m"
fi
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 成功: 输出与参考输出匹配\e[0m"
else