blob: 152323ffc8a225a5a1fdb64ba9f3c8469ad87d29 [file] [log] [blame]
#!/usr/bin/env bash
verbose="no"
tap_output="no"
run_all_tests="no" # don't run nodefault tests
if [ ! -f config.mak ]; then
echo "run ./configure && make first. See ./configure -h"
exit 1
fi
source config.mak
source scripts/common.bash
function usage()
{
cat <<EOF
Usage: $0 [-h] [-v] [-a] [-g group] [-j NUM-TASKS] [-t] [-l]
-h, --help Output this help text
-v, --verbose Enables verbose mode
-a, --all Run all tests, including those flagged as 'nodefault'
and those guarded by errata.
-g, --group Only execute tests in the given group
-j, --parallel Execute tests in parallel
-t, --tap13 Output test results in TAP format
-l, --list Only output all tests list
Set the environment variable QEMU=/path/to/qemu-system-ARCH to
specify the appropriate qemu binary for ARCH-run.
EOF
}
RUNTIME_arch_run="./$TEST_SUBDIR/run"
source scripts/runtime.bash
# require enhanced getopt
getopt -T > /dev/null
if [ $? -ne 4 ]; then
echo "Enhanced getopt is not available, add it to your PATH?"
exit 1
fi
only_tests=""
list_tests=""
args=$(getopt -u -o ag:htj:vl -l all,group:,help,tap13,parallel:,verbose,list,probe-maxsmp -- "$@")
# Shellcheck likes to test commands directly rather than with $? but sometimes they
# are too long to put in the same test.
# shellcheck disable=SC2181
[ $? -ne 0 ] && exit 2;
set -- $args;
while [ $# -gt 0 ]; do
case "$1" in
-a | --all)
run_all_tests="yes"
export ERRATA_FORCE=y
;;
-g | --group)
shift
only_group=$1
;;
-h | --help)
usage
exit
;;
-j | --parallel)
shift
unittest_run_queues=$1
if (( $unittest_run_queues <= 0 )); then
echo "Invalid -j option: $unittest_run_queues"
exit 2
fi
;;
-v | --verbose)
verbose="yes"
;;
-t | --tap13)
tap_output="yes"
;;
-l | --list)
list_tests="yes"
;;
--probe-maxsmp)
probe_maxsmp
;;
--)
;;
*)
only_tests="$only_tests $1"
;;
esac
shift
done
# RUNTIME_log_file will be configured later
if [[ $tap_output == "no" ]]; then
process_test_output() { cat >> $RUNTIME_log_file; }
postprocess_suite_output() { cat; }
else
process_test_output() {
local testname="$1"
CR=$'\r'
while read -r line; do
line="${line%"$CR"}"
case "${line:0:4}" in
PASS)
echo "ok TEST_NUMBER - ${testname}: ${line#??????}" >&3
;;
FAIL)
echo "not ok TEST_NUMBER - ${testname}: ${line#??????}" >&3
;;
SKIP)
echo "ok TEST_NUMBER - ${testname}: ${line#??????} # skip" >&3
;;
*)
;;
esac
echo "${line}"
done >> $RUNTIME_log_file
}
postprocess_suite_output() {
test_number=0
while read -r line; do
case "${line}" in
ok*|"not ok"*)
(( test_number++ ))
echo "${line/TEST_NUMBER/${test_number}}" ;;
*) echo "${line}" ;;
esac
done
echo "1..$test_number"
}
fi
RUNTIME_log_stderr () { process_test_output "$1"; }
RUNTIME_log_stdout () {
local testname="$1"
if [ "$PRETTY_PRINT_STACKS" = "yes" ]; then
local kernel="$2"
./scripts/pretty_print_stacks.py "$kernel" | process_test_output "$testname"
else
process_test_output "$testname"
fi
}
function run_task()
{
local testname="$1"
while (( $(jobs | wc -l) == $unittest_run_queues )); do
# wait for any background test to finish
wait -n 2>/dev/null
done
RUNTIME_log_file="${unittest_log_dir}/${testname}.log"
if [ $unittest_run_queues = 1 ]; then
run "$@"
else
run "$@" &
fi
}
: "${unittest_log_dir:=logs}"
: "${unittest_run_queues:=1}"
config=$TEST_DIR/unittests.cfg
print_testname()
{
local testname=$1
local groups=$2
if [ -n "$only_group" ] && ! find_word "$only_group" "$groups"; then
return
fi
echo "$testname"
}
if [[ $list_tests == "yes" ]]; then
for_each_unittest $config print_testname
exit
fi
rm -rf $unittest_log_dir.old
[ -d $unittest_log_dir ] && mv $unittest_log_dir $unittest_log_dir.old
mkdir $unittest_log_dir || exit 2
echo "BUILD_HEAD=$(cat build-head)" > $unittest_log_dir/SUMMARY
if [[ $tap_output == "yes" ]]; then
echo "TAP version 13"
fi
trap "wait; exit 130" SIGINT
(
# preserve stdout so that process_test_output output can write TAP to it
exec 3>&1
test "$tap_output" == "yes" && exec > /dev/null
for_each_unittest $config run_task
) | postprocess_suite_output
# wait until all tasks finish
wait