#!/bin/bash
set -o pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASEPATH="$(cd "${SCRIPT_DIR}/.." && pwd)"
BUILD_OUTPUT_DIR="${BASEPATH}/build"
BUILD_OUT_DIR="${BASEPATH}/build_out"
declare -A TEST_CASES=(
["asys_st"]="pytest"
["asys_ut"]="pytest"
["msaicerr_st"]="pytest"
["msaicerr_ut"]="pytest"
["msprof_ut"]="gtest"
["install_st"]="pytest"
["upgrade_st"]="pytest"
["uninstall_st"]="pytest"
)
VALID_COMPONENTS=("asys" "msaicerr" "msprof" "install" "upgrade" "uninstall" "all")
COV_BASELINE=80
declare -A R_PASSED R_FAILED R_SKIPPED R_COV R_STATUS R_FAILLIST R_NOTES
print_usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --component <name> Specify component to test:"
echo " asys, msaicerr, msprof, install, upgrade, uninstall, all (default: all)"
echo " --ut Run UT tests only"
echo " --st Run ST tests only"
echo " --cov Enable gcov coverage collection for gtest cases"
echo " -h, --help Show this help message"
echo ""
echo "Coverage baseline is fixed at ${COV_BASELINE}%; a suite below it is reported as FAIL."
echo ""
echo "Examples:"
echo " $0 # Run all tests (UT + ST)"
echo " $0 --component asys # Run asys UT + ST"
echo " $0 --component msaicerr --ut # Run msaicerr UT only"
echo " $0 --st # Run all ST tests"
echo " $0 --component msprof --ut # Run msprof UT only"
echo " $0 --component install # Run install ST"
echo " $0 --component upgrade # Run upgrade ST"
echo " $0 --component uninstall # Run uninstall ST"
}
parse_args() {
COMPONENT="all"
RUN_UT=false
RUN_ST=false
RUN_COV=false
if [[ $# -eq 0 ]]; then
RUN_UT=true
RUN_ST=true
return 0
fi
local parsed_args
parsed_args=$(getopt -a -o h -l help,component:,ut,st,cov -- "$@") || {
print_usage
exit 1
}
eval set -- "$parsed_args"
while true; do
case "$1" in
-h|--help)
print_usage
exit 0
;;
--component)
COMPONENT="$2"
shift 2
;;
--ut)
RUN_UT=true
shift
;;
--st)
RUN_ST=true
shift
;;
--cov)
RUN_COV=true
shift
;;
--)
shift
break
;;
*)
echo "Unknown option: $1"
print_usage
exit 1
;;
esac
done
if [[ "$COMPONENT" != "all" ]] && [[ ! " ${VALID_COMPONENTS[*]} " =~ " ${COMPONENT} " ]]; then
echo "ERROR: Invalid component '$COMPONENT'. Valid options: ${VALID_COMPONENTS[*]}"
exit 1
fi
if [[ "$RUN_UT" == "false" ]] && [[ "$RUN_ST" == "false" ]]; then
RUN_UT=true
RUN_ST=true
fi
}
get_test_cases() {
local result=()
local components=()
if [[ "$COMPONENT" == "all" ]]; then
components=("asys" "msaicerr" "msprof" "install" "upgrade" "uninstall")
else
components=("$COMPONENT")
fi
for comp in "${components[@]}"; do
if [[ "$RUN_UT" == "true" ]]; then
case "$comp" in
asys)
result+=("asys_ut")
;;
msaicerr)
result+=("msaicerr_ut")
;;
msprof)
result+=("msprof_ut")
;;
esac
fi
if [[ "$RUN_ST" == "true" ]]; then
case "$comp" in
asys)
result+=("asys_st")
;;
msaicerr)
result+=("msaicerr_st")
;;
msprof)
;;
install)
result+=("install_st")
;;
upgrade)
result+=("upgrade_st")
;;
uninstall)
result+=("uninstall_st")
;;
esac
fi
done
echo "${result[@]}"
}
is_package_st_case() {
case "$1" in
install_st|upgrade_st|uninstall_st)
return 0
;;
*)
return 1
;;
esac
}
find_run_package() {
local pkg
pkg=$(find "${BUILD_OUT_DIR}" -maxdepth 1 -type f -name "cann-oam-tools_*.run" 2>/dev/null \
| sort -V | tail -n 1)
if [[ -n "${pkg}" ]]; then
echo "${pkg}"
return 0
fi
return 1
}
ensure_run_package_for_st_cases() {
local test_cases=("$@")
local case_name
local need_package=false
for case_name in "${test_cases[@]}"; do
if is_package_st_case "${case_name}"; then
need_package=true
break
fi
done
if [[ "${need_package}" != "true" ]]; then
return 0
fi
local run_pkg
run_pkg=$(find_run_package || true)
if [[ -n "${run_pkg}" ]]; then
echo "INFO: Using run package: ${run_pkg}"
return 0
fi
echo "INFO: install/upgrade/uninstall ST requires a cann-oam-tools .run package."
echo "INFO: No cann-oam-tools_*.run found in ${BUILD_OUT_DIR}; building package first."
if ! bash "${BASEPATH}/build.sh" --noexec; then
echo "ERROR: Failed to build run package with bash build.sh --noexec"
return 1
fi
run_pkg=$(find_run_package || true)
if [[ -z "${run_pkg}" ]]; then
echo "ERROR: build.sh finished but no cann-oam-tools_*.run was found in ${BUILD_OUT_DIR}"
return 1
fi
echo "INFO: Prepared run package: ${run_pkg}"
}
record_result() {
R_PASSED["$1"]="$2"
R_FAILED["$1"]="$3"
R_SKIPPED["$1"]="$4"
R_COV["$1"]="$5"
R_STATUS["$1"]="$6"
R_NOTES["$1"]="$7"
}
count_gtest_targets() {
local output_file="$1"
local started finished
started=$(LC_ALL=C grep -ac "^----- running " "$output_file")
finished=$(LC_ALL=C grep -aoE "\[ PASSED \] [0-9]+ test" "$output_file" | wc -l)
echo "${started:-0} ${finished:-0}"
}
validate_gtest_result() {
local output_file="$1"
local case_name="$2"
if [[ ! -f "$output_file" ]]; then
record_result "$case_name" "-" "-" "-" "-" "CRASH" "output file not found: $output_file"
return 1
fi
local exit_code=0
if [[ -f "${BUILD_OUTPUT_DIR}/${case_name}.exitcode" ]]; then
exit_code=$(cat "${BUILD_OUTPUT_DIR}/${case_name}.exitcode")
fi
exit_code=${exit_code:-0}
local cov_ratio="${R_COV[$case_name]:--}"
local crashed=false
if [[ "$exit_code" =~ ^[0-9]+$ ]] && [[ $exit_code -ge 128 ]]; then
crashed=true
fi
if LC_ALL=C grep -qaE "Segmentation fault|core dumped|==ERROR:.*Sanitizer|Aborted|SIGABRT|signal 6" "$output_file"; then
crashed=true
fi
local tgt_started tgt_finished
read -r tgt_started tgt_finished <<< "$(count_gtest_targets "$output_file")"
if [[ "$exit_code" =~ ^[0-9]+$ ]] && [[ $exit_code -ne 0 ]] \
&& [[ ${tgt_started:-0} -gt 0 ]] && [[ ${tgt_finished:-0} -lt ${tgt_started:-0} ]]; then
crashed=true
fi
if [[ "$crashed" == "true" ]]; then
local notes="CRASHED (ExitCode=${exit_code}), statistics unavailable"
local markers
markers=$(LC_ALL=C grep -haoE "Segmentation fault|core dumped|Aborted|SIGABRT|==ERROR:.*Sanitizer|AddressSanitizer|runtime error:" \
"$output_file" 2>/dev/null | sort -u | head -5)
if [[ -n "$markers" ]]; then
notes+=$'\n'"crash marker: $(echo "$markers" | paste -sd', ' -)"
fi
if [[ ${tgt_finished:-0} -lt ${tgt_started:-0} ]]; then
notes+=$'\n'"only ${tgt_finished}/${tgt_started} gtest target(s) reached the summary line"
local last_target
last_target=$(LC_ALL=C grep -a "^----- running " "$output_file" | tail -1 | sed 's/^----- running //; s/ -----$//')
[[ -n "$last_target" ]] && notes+=$'\n'"last target started: ${last_target}"
fi
record_result "$case_name" "-" "-" "-" "$cov_ratio" "CRASH" "$notes"
return 1
fi
local passed_count=0
local failed_count=0
local skipped_count=0
passed_count=$(LC_ALL=C grep -aoE "\[ PASSED \] [0-9]+ test" "$output_file" \
| awk '{s+=$4} END{print s+0}')
passed_count=${passed_count:-0}
failed_count=$(LC_ALL=C grep -aoE "\[ FAILED \] [0-9]+ test" "$output_file" \
| awk '{s+=$4} END{print s+0}')
failed_count=${failed_count:-0}
local gtest_skipped=0
local gtest_disabled=0
gtest_skipped=$(LC_ALL=C grep -aoE "\[ SKIPPED \] [0-9]+ test" "$output_file" \
| awk '{s+=$4} END{print s+0}')
gtest_disabled=$(LC_ALL=C grep -aoE "YOU HAVE [0-9]+ DISABLED TEST" "$output_file" \
| awk '{s+=$3} END{print s+0}')
skipped_count=$(( ${gtest_skipped:-0} + ${gtest_disabled:-0} ))
local notes=""
local status="PASS"
if [[ $exit_code -ne 0 ]]; then
notes+="exited with code ${exit_code} (expected 0)"$'\n'
status="FAIL"
fi
if LC_ALL=C grep -qaE "runtime error:" "$output_file"; then
notes+="has runtime errors"$'\n'
status="FAIL"
fi
if LC_ALL=C grep -qaE "AddressSanitizer|memory leak" "$output_file"; then
notes+="has memory issues"$'\n'
status="FAIL"
fi
if [[ $failed_count -gt 0 ]]; then
status="FAIL"
local names
names=$(LC_ALL=C grep -aoE "\[ FAILED \] [A-Za-z_][A-Za-z0-9_/.]*" "$output_file" \
| sed -E 's/^\[ FAILED \] //' | sort -u)
R_FAILLIST["$case_name"]="$names"
fi
if [[ $passed_count -eq 0 ]] && [[ $failed_count -eq 0 ]]; then
notes+="ran but produced no test results"$'\n'
status="FAIL"
fi
record_result "$case_name" "$passed_count" "$failed_count" "$skipped_count" \
"$cov_ratio" "$status" "${notes%$'\n'}"
[[ "$status" == "PASS" ]]
}
validate_pytest_result() {
local output_file="$1"
local case_name="$2"
if [[ ! -f "$output_file" ]]; then
record_result "$case_name" "-" "-" "-" "-" "CRASH" "output file not found: $output_file"
return 1
fi
local exit_code=0
if [[ -f "${BUILD_OUTPUT_DIR}/${case_name}.exitcode" ]]; then
exit_code=$(cat "${BUILD_OUTPUT_DIR}/${case_name}.exitcode")
fi
exit_code=${exit_code:-0}
local cov_ratio="-"
local coverage_line
coverage_line=$(LC_ALL=C grep -aE "^TOTAL" "$output_file" | tail -1)
if [[ -n "$coverage_line" ]]; then
cov_ratio=$(echo "$coverage_line" | awk '{print $4}' | sed 's/%//')
[[ -n "$cov_ratio" ]] || cov_ratio="-"
fi
local crashed=false
if [[ "$exit_code" =~ ^[0-9]+$ ]] && [[ $exit_code -ge 128 ]]; then
crashed=true
fi
if LC_ALL=C grep -qaE "Segmentation fault|core dumped|Fatal Python error|==ERROR:.*Sanitizer|Aborted|SIGABRT|signal 6" \
"$output_file"; then
crashed=true
fi
if [[ "$crashed" == "true" ]]; then
local notes="CRASHED (ExitCode=${exit_code}), statistics unavailable"
local markers
markers=$(LC_ALL=C grep -haoE "Segmentation fault|core dumped|Fatal Python error|==ERROR:.*Sanitizer|AddressSanitizer|Aborted|SIGABRT" \
"$output_file" 2>/dev/null | sort -u | head -5)
if [[ -n "$markers" ]]; then
notes+=$'\n'"crash marker: $(echo "$markers" | paste -sd', ' -)"
fi
record_result "$case_name" "-" "-" "-" "$cov_ratio" "CRASH" "$notes"
return 1
fi
local summary_line
summary_line=$(LC_ALL=C grep -aE "^=+ .* in [0-9.]+s( \([0-9:]+\))? =+$" "$output_file")
local failed_count passed_count error_count skipped_count
failed_count=$(echo "$summary_line" | grep -oE '[0-9]+ failed' | awk '{print $1}')
passed_count=$(echo "$summary_line" | grep -oE '[0-9]+ passed' | awk '{print $1}')
error_count=$(echo "$summary_line" | grep -oE '[0-9]+ error' | awk '{print $1}')
skipped_count=$(echo "$summary_line" | grep -oE '[0-9]+ skipped' | awk '{print $1}')
passed_count=${passed_count:-0}
failed_count=${failed_count:-0}
error_count=${error_count:-0}
skipped_count=${skipped_count:-0}
local notes=""
local status="PASS"
if [[ $exit_code -ne 0 ]]; then
notes+="exited with code ${exit_code} (expected 0)"$'\n'
status="FAIL"
fi
if [[ $error_count -gt 0 ]]; then
notes+="${error_count} collection/runner error(s)"$'\n'
status="FAIL"
fi
if [[ $failed_count -gt 0 ]] || [[ $error_count -gt 0 ]]; then
status="FAIL"
local names
names=$(LC_ALL=C grep -aE "^(FAILED|ERROR) " "$output_file" \
| sed -E 's/ - .*$//; s/^FAILED //; s/^ERROR (.*)$/\1 (error)/' | sort -u)
R_FAILLIST["$case_name"]="$names"
fi
if [[ $passed_count -eq 0 ]] && [[ $failed_count -eq 0 ]] && [[ $error_count -eq 0 ]]; then
notes+="ran but produced no test results (possible collection failure)"$'\n'
status="FAIL"
fi
record_result "$case_name" "$passed_count" "$failed_count" "$skipped_count" \
"$cov_ratio" "$status" "${notes%$'\n'}"
[[ "$status" == "PASS" ]]
}
run_pytest_with_coverage() {
local case_name="$1"
local source_dir="$2"
local test_dir="$3"
local output_file="$4"
local cov_dir="${BUILD_OUTPUT_DIR}/${case_name}_cov"
rm -rf "${cov_dir}" "${BUILD_OUTPUT_DIR}/${case_name}_html"
mkdir -p "${cov_dir}"
export COVERAGE_FILE="${cov_dir}/.coverage"
python3 -m coverage run --source="${source_dir}" -m pytest "${test_dir}" 2>&1 | tee "${output_file}"
local pytest_rc=${PIPESTATUS[0]}
echo "${pytest_rc}" > "${BUILD_OUTPUT_DIR}/${case_name}.exitcode"
python3 -m coverage report --precision=2 2>&1 | tee -a "${output_file}"
local report_rc=${PIPESTATUS[0]}
if [[ ${report_rc} -ne 0 ]]; then
echo "WARNING: coverage report failed (rc=${report_rc})" | tee -a "${output_file}"
fi
python3 -m coverage html -d "${BUILD_OUTPUT_DIR}/${case_name}_html" 2>&1 | tee -a "${output_file}"
local html_rc=${PIPESTATUS[0]}
if [[ ${html_rc} -ne 0 ]]; then
echo "WARNING: coverage html failed (rc=${html_rc})" | tee -a "${output_file}"
fi
unset COVERAGE_FILE
return "${pytest_rc}"
}
run_pytest_plain() {
local case_name="$1"
local test_dir="$2"
local output_file="$3"
python3 -m pytest "${test_dir}" 2>&1 | tee "${output_file}"
local pytest_rc=${PIPESTATUS[0]}
echo "${pytest_rc}" > "${BUILD_OUTPUT_DIR}/${case_name}.exitcode"
return "${pytest_rc}"
}
collect_gcov_coverage() {
local case_name="$1"
local capture_dir="$2"
local extract_arg="$3"
local output_file="$4"
local cov_dir="${BUILD_OUTPUT_DIR}/${case_name}_cov"
local html_dir="${BUILD_OUTPUT_DIR}/${case_name}_html"
local ign="--ignore-errors=mismatch,gcov,source,negative,unused,empty,inconsistent"
local html_ign="--ignore-errors=source,inconsistent,unmapped,category,corrupt"
rm -rf "${cov_dir}" "${html_dir}"
mkdir -p "${cov_dir}"
lcov -c -i -d "${capture_dir}" -o "${cov_dir}/base.info" ${ign} >> "${output_file}" 2>&1
lcov -c -d "${capture_dir}" -o "${cov_dir}/run.info" ${ign} >> "${output_file}" 2>&1
lcov -a "${cov_dir}/base.info" -a "${cov_dir}/run.info" \
-o "${cov_dir}/total.info" ${ign} >> "${output_file}" 2>&1
if [[ -f "${extract_arg}" ]]; then
local extract_files=()
local _f
while IFS= read -r _f; do
[[ -n "${_f}" ]] && extract_files+=("${_f}")
done < "${extract_arg}"
lcov --extract "${cov_dir}/total.info" "${extract_files[@]}" \
-o "${cov_dir}/coverage.info" ${ign} >> "${output_file}" 2>&1
else
lcov --extract "${cov_dir}/total.info" "${extract_arg}" \
-o "${cov_dir}/coverage.info" ${ign} >> "${output_file}" 2>&1
fi
genhtml "${cov_dir}/coverage.info" -o "${html_dir}" ${html_ign} >> "${output_file}" 2>&1
local cov_ratio
cov_ratio=$(lcov --summary "${cov_dir}/coverage.info" ${ign} 2>&1 \
| grep -E "lines\.+:" | head -1 | grep -oE "[0-9]+\.[0-9]+%" | head -1 | sed 's/%//')
R_COV["${case_name}"]="${cov_ratio:--}"
}
gen_msprof_cov_whitelist() {
local out_file="$1"
local collector_dir="${BASEPATH}/src/msprof/collector"
python3 - "$collector_dir" "$out_file" <<'PYEOF'
import os, re, sys
collector = sys.argv[1]
out_file = sys.argv[2]
dvvp = os.path.join(collector, "dvvp")
varmap = {
"PROF_BASIC_DIR": os.path.join(collector, "basic"),
"MSPROF_SOURCE_DIR": collector,
"MSPROF_DIR": os.path.join(collector, "..", ".."),
}
def resolve(token, cmdir):
m = re.match(r'\$\{([A-Z_]+)\}/(.*)', token)
if m:
var, rest = m.group(1), m.group(2)
if var in varmap:
return os.path.normpath(os.path.join(varmap[var], rest))
return None
if token.startswith("$"):
return None
return os.path.normpath(os.path.join(cmdir, token))
srcs = set()
for cm in [os.path.join(dvvp, "acp", "CMakeLists.txt"),
os.path.join(dvvp, "msprofbin", "CMakeLists.txt")]:
if not os.path.isfile(cm):
continue
cmdir = os.path.dirname(cm)
txt = open(cm).read()
for tok in re.findall(r'[^\s"()]+\.(?:cpp|c)\b', txt):
p = resolve(tok, cmdir)
if p and os.path.isfile(p):
srcs.add(os.path.abspath(p))
with open(out_file, "w") as f:
for s in sorted(srcs):
f.write(s + "\n")
print("msprof cov whitelist: %d source files" % len(srcs))
PYEOF
}
run_test_case() {
local case_name="$1"
local framework="${TEST_CASES[$case_name]}"
local output_file="${BUILD_OUTPUT_DIR}/${case_name}_output.log"
local return_code=0
echo "---"
echo "STARTING TEST: **$case_name** (Framework: $framework)"
cd "${BASEPATH}"
case "$case_name" in
asys_st)
run_pytest_with_coverage "${case_name}" "./src/asys" "./test/st/asys/testcase" "${output_file}"
;;
asys_ut)
run_pytest_with_coverage "${case_name}" "./src/asys" "./test/ut/asys/testcase" "${output_file}"
;;
msaicerr_st)
run_pytest_with_coverage "${case_name}" "./src/msaicerr" "./test/st/msaicerr/testcase" "${output_file}"
;;
msaicerr_ut)
run_pytest_with_coverage "${case_name}" "./src/msaicerr" "./test/ut/msaicerr/testcase" "${output_file}"
;;
msprof_ut)
local msprof_ut_manifest="${BUILD_OUTPUT_DIR}/msprof_ut_targets.txt"
local msprof_ut_capture_dir="${BUILD_OUTPUT_DIR}/test/ut/msprof"
local msprof_ut_rc=0
: > "${output_file}"
if [[ "${RUN_COV}" == "true" && -d "${msprof_ut_capture_dir}" ]]; then
find "${msprof_ut_capture_dir}" -name '*.gcda' -type f -delete 2>/dev/null
fi
if [[ ! -f "${msprof_ut_manifest}" ]]; then
echo "ERROR: msprof ut target manifest not found at ${msprof_ut_manifest}" | tee -a "${output_file}"
echo "1" > "${BUILD_OUTPUT_DIR}/${case_name}.exitcode"
return 1
fi
while IFS= read -r ut_bin; do
[[ -z "${ut_bin}" ]] && continue
if [[ -f "${ut_bin}" ]]; then
printf '\n----- running %s -----\n' "${ut_bin}" >> "${output_file}"
"${ut_bin}" 2>&1 | tee -a "${output_file}"
[[ ${PIPESTATUS[0]} -eq 0 ]] || msprof_ut_rc=1
else
echo "ERROR: msprof_utest binary not found at ${ut_bin}" | tee -a "${output_file}"
msprof_ut_rc=1
fi
done < "${msprof_ut_manifest}"
echo ${msprof_ut_rc} > "${BUILD_OUTPUT_DIR}/${case_name}.exitcode"
if [[ "${RUN_COV}" == "true" ]]; then
local msprof_cov_whitelist="${BUILD_OUTPUT_DIR}/msprof_cov_files.txt"
gen_msprof_cov_whitelist "${msprof_cov_whitelist}" >> "${output_file}" 2>&1
collect_gcov_coverage "${case_name}" \
"${msprof_ut_capture_dir}" \
"${msprof_cov_whitelist}" "${output_file}"
fi
;;
install_st)
run_pytest_plain "${case_name}" "./test/st/install/testcase" "${output_file}"
;;
upgrade_st)
run_pytest_plain "${case_name}" "./test/st/upgrade/testcase" "${output_file}"
;;
uninstall_st)
run_pytest_plain "${case_name}" "./test/st/uninstall/testcase" "${output_file}"
;;
*)
echo "ERROR: Unknown test case: $case_name"
return 1
;;
esac
echo "END TEST: **$case_name**"
if [[ "$framework" == "gtest" ]]; then
validate_gtest_result "$output_file" "$case_name" || return_code=1
elif [[ "$framework" == "pytest" ]]; then
validate_pytest_result "$output_file" "$case_name" || return_code=1
fi
echo "log saved to: **$output_file**"
return $return_code
}
case_expects_coverage() {
case "$1" in
asys_ut|asys_st|msaicerr_ut|msaicerr_st)
return 0
;;
msprof_ut)
[[ "${RUN_COV}" == "true" ]]
;;
*)
return 1
;;
esac
}
apply_cov_baseline() {
local case_name
for case_name in "$@"; do
local cov="${R_COV[$case_name]:--}"
if ! case_expects_coverage "$case_name"; then
continue
fi
if [[ "$cov" == "-" ]] || [[ ! "$cov" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
COV_MISSING+=("$case_name")
R_NOTES["$case_name"]="${R_NOTES[$case_name]:+${R_NOTES[$case_name]}$'\n'}coverage expected but not collected (got '${cov}'); check coverage report / lcov output in the log"
if [[ "${R_STATUS[$case_name]}" == "PASS" ]]; then
R_STATUS["$case_name"]="FAIL"
fi
continue
fi
if [[ ${cov%%.*} -lt $COV_BASELINE ]]; then
COV_BELOW_BASELINE+=("$case_name")
if [[ "${R_STATUS[$case_name]}" == "PASS" ]]; then
R_STATUS["$case_name"]="FAIL"
fi
fi
done
}
print_summary() {
local test_cases=("$@")
local case_name
local total_passed=0 total_failed=0 total_skipped=0
local overall="PASS"
echo ""
echo "========================================================================"
printf " TEST SUMMARY (coverage baseline: %s%%)\n" "$COV_BASELINE"
echo "========================================================================"
printf " %-14s %-10s %7s %7s %8s %5s %s\n" \
"SUITE" "FRAMEWORK" "PASSED" "FAILED" "SKIPPED" "COV" "RESULT"
echo "------------------------------------------------------------------------"
for case_name in "${test_cases[@]}"; do
local status="${R_STATUS[$case_name]:-CRASH}"
local passed="${R_PASSED[$case_name]:--}"
local failed="${R_FAILED[$case_name]:--}"
local skipped="${R_SKIPPED[$case_name]:--}"
local cov="${R_COV[$case_name]:--}"
[[ "$cov" != "-" ]] && cov="${cov%%.*}%"
if [[ "$passed" =~ ^[0-9]+$ ]]; then
total_passed=$((total_passed + passed))
total_failed=$((total_failed + failed))
total_skipped=$((total_skipped + skipped))
fi
[[ "$status" == "PASS" ]] || overall="FAIL"
printf " %-14s %-10s %7s %7s %8s %5s %s\n" \
"$case_name" "${TEST_CASES[$case_name]}" "$passed" "$failed" "$skipped" "$cov" "$status"
done
echo "------------------------------------------------------------------------"
printf " %-14s %-10s %7s %7s %8s %5s %s\n" \
"TOTAL" "" "$total_passed" "$total_failed" "$total_skipped" "" "$overall"
echo "========================================================================"
if [[ "$overall" == "PASS" ]]; then
return 0
fi
echo ""
echo "FAILED CASES"
echo "------------------------------------------------------------------------"
for case_name in "${test_cases[@]}"; do
local status="${R_STATUS[$case_name]:-CRASH}"
[[ "$status" == "PASS" ]] && continue
local faillist="${R_FAILLIST[$case_name]:-}"
if [[ -n "$faillist" ]]; then
printf "[%s] (%s)\n" "$case_name" "$(echo "$faillist" | grep -c .)"
while IFS= read -r name; do
[[ -n "$name" ]] && echo " ${name}"
done <<< "$faillist"
else
printf "[%s]\n" "$case_name"
fi
local notes="${R_NOTES[$case_name]:-}"
if [[ -n "$notes" ]]; then
while IFS= read -r line; do
[[ -n "$line" ]] && echo " ${line}"
done <<< "$notes"
fi
done
echo "------------------------------------------------------------------------"
if [[ ${#COV_BELOW_BASELINE[@]} -gt 0 ]]; then
printf "COVERAGE BELOW BASELINE (%s%%)\n" "$COV_BASELINE"
for case_name in "${COV_BELOW_BASELINE[@]}"; do
printf " %-14s %s%% -> FAIL\n" "$case_name" "${R_COV[$case_name]}"
done
echo "------------------------------------------------------------------------"
fi
if [[ ${#COV_MISSING[@]} -gt 0 ]]; then
echo "COVERAGE EXPECTED BUT NOT COLLECTED"
for case_name in "${COV_MISSING[@]}"; do
printf " %-14s -> FAIL (coverage pipeline failed; see log)\n" "$case_name"
done
echo "------------------------------------------------------------------------"
fi
echo "full logs: ${BUILD_OUTPUT_DIR}/<suite>_output.log"
echo "========================================================================"
return 1
}
main() {
parse_args "$@"
mkdir -p "${BUILD_OUTPUT_DIR}"
if [[ "$COMPONENT" == "asys" || "$COMPONENT" == "all" ]]; then
if [[ ! -f "${BASEPATH}/src/asys/common/chip_handler.py" ]]; then
echo "ERROR: chip_handler.py not found at ${BASEPATH}/src/asys/common/chip_handler.py"
echo "This file is generated by cmake configure from chip_handler.py.in."
echo "Please run cmake configure first:"
echo " mkdir -p build && cd build && cmake .. && cd .."
exit 1
fi
fi
echo "========================================"
echo "Test Configuration:"
echo " Component: $COMPONENT"
echo " Run UT: $RUN_UT"
echo " Run ST: $RUN_ST"
echo " Coverage baseline: ${COV_BASELINE}%"
echo " Output Dir: $BUILD_OUTPUT_DIR"
echo "========================================"
local test_cases=($(get_test_cases))
if [[ ${#test_cases[@]} -eq 0 ]]; then
echo "ERROR: No test cases to run"
exit 1
fi
echo "INFO: Running test cases: ${test_cases[*]}"
ensure_run_package_for_st_cases "${test_cases[@]}" || exit 1
COV_BELOW_BASELINE=()
COV_MISSING=()
for case_name in "${test_cases[@]}"; do
run_test_case "$case_name" || true
done
apply_cov_baseline "${test_cases[@]}"
local overall_return_code=0
print_summary "${test_cases[@]}" || overall_return_code=1
if [[ $overall_return_code -eq 0 ]]; then
echo "RESULT: All test cases passed"
else
echo "RESULT: One or more test cases failed"
fi
exit $overall_return_code
}
main "$@"