xref: /kvm-unit-tests/run_tests.sh (revision 3b4b978a27f6f7df37875f97470d19d647b2c179)
1#!/usr/bin/env bash
2
3verbose="no"
4tap_output="no"
5run_all_tests="no" # don't run nodefault tests
6
7if [ ! -f config.mak ]; then
8    echo "run ./configure && make first. See ./configure -h"
9    exit 1
10fi
11source config.mak
12source scripts/common.bash
13
14function usage()
15{
16cat <<EOF
17
18Usage: $0 [-h] [-v] [-a] [-g group] [-j NUM-TASKS] [-t] [-l]
19
20    -h, --help      Output this help text
21    -v, --verbose   Enables verbose mode
22    -a, --all       Run all tests, including those flagged as 'nodefault'
23                    and those guarded by errata.
24    -g, --group     Only execute tests in the given group
25    -j, --parallel  Execute tests in parallel
26    -t, --tap13     Output test results in TAP format
27    -l, --list      Only output all tests list
28
29Set the environment variable QEMU=/path/to/qemu-system-ARCH to
30specify the appropriate qemu binary for ARCH-run.
31
32EOF
33}
34
35RUNTIME_arch_run="./$TEST_SUBDIR/run"
36source scripts/runtime.bash
37
38# require enhanced getopt
39getopt -T > /dev/null
40if [ $? -ne 4 ]; then
41    echo "Enhanced getopt is not available, add it to your PATH?"
42    exit 1
43fi
44
45only_tests=""
46list_tests=""
47args=$(getopt -u -o ag:htj:vl -l all,group:,help,tap13,parallel:,verbose,list,probe-maxsmp -- "$@")
48# Shellcheck likes to test commands directly rather than with $? but sometimes they
49# are too long to put in the same test.
50# shellcheck disable=SC2181
51[ $? -ne 0 ] && exit 2;
52set -- $args;
53while [ $# -gt 0 ]; do
54    case "$1" in
55        -a | --all)
56            run_all_tests="yes"
57            export ERRATA_FORCE=y
58            ;;
59        -g | --group)
60            shift
61            only_group=$1
62            ;;
63        -h | --help)
64            usage
65            exit
66            ;;
67        -j | --parallel)
68            shift
69            unittest_run_queues=$1
70            if (( $unittest_run_queues <= 0 )); then
71                echo "Invalid -j option: $unittest_run_queues"
72                exit 2
73            fi
74            ;;
75        -v | --verbose)
76            verbose="yes"
77            ;;
78        -t | --tap13)
79            tap_output="yes"
80            ;;
81        -l | --list)
82            list_tests="yes"
83            ;;
84        --probe-maxsmp)
85            probe_maxsmp
86            ;;
87        --)
88            ;;
89        *)
90            only_tests="$only_tests $1"
91            ;;
92    esac
93    shift
94done
95
96# RUNTIME_log_file will be configured later
97if [[ $tap_output == "no" ]]; then
98    process_test_output() { cat >> $RUNTIME_log_file; }
99    postprocess_suite_output() { cat; }
100else
101    process_test_output() {
102        local testname="$1"
103        CR=$'\r'
104        while read -r line; do
105            line="${line%"$CR"}"
106            case "${line:0:4}" in
107                PASS)
108                    echo "ok TEST_NUMBER - ${testname}: ${line#??????}" >&3
109                    ;;
110                FAIL)
111                    echo "not ok TEST_NUMBER - ${testname}: ${line#??????}" >&3
112                    ;;
113                SKIP)
114                    echo "ok TEST_NUMBER - ${testname}: ${line#??????} # skip" >&3
115                    ;;
116                *)
117                    ;;
118            esac
119            echo "${line}"
120        done >> $RUNTIME_log_file
121    }
122    postprocess_suite_output() {
123        test_number=0
124        while read -r line; do
125            case "${line}" in
126                ok*|"not ok"*)
127                    (( test_number++ ))
128                    echo "${line/TEST_NUMBER/${test_number}}" ;;
129                *) echo "${line}" ;;
130            esac
131        done
132        echo "1..$test_number"
133    }
134fi
135
136RUNTIME_log_stderr () { process_test_output "$1"; }
137RUNTIME_log_stdout () {
138    local testname="$1"
139    if [ "$PRETTY_PRINT_STACKS" = "yes" ]; then
140        local kernel="$2"
141        ./scripts/pretty_print_stacks.py "$kernel" | process_test_output "$testname"
142    else
143        process_test_output "$testname"
144    fi
145}
146
147function run_task()
148{
149	local testname="$1"
150
151	while (( $(jobs | wc -l) == $unittest_run_queues )); do
152		# wait for any background test to finish
153		wait -n 2>/dev/null
154	done
155
156	RUNTIME_log_file="${unittest_log_dir}/${testname}.log"
157	if [ $unittest_run_queues = 1 ]; then
158		run "$@"
159	else
160		run "$@" &
161	fi
162}
163
164: "${unittest_log_dir:=logs}"
165: "${unittest_run_queues:=1}"
166config=$TEST_DIR/unittests.cfg
167
168print_testname()
169{
170    local testname=$1
171    local groups=$2
172    if [ -n "$only_group" ] && ! find_word "$only_group" "$groups"; then
173        return
174    fi
175    echo "$testname"
176}
177if [[ $list_tests == "yes" ]]; then
178    for_each_unittest $config print_testname
179    exit
180fi
181
182rm -rf $unittest_log_dir.old
183[ -d $unittest_log_dir ] && mv $unittest_log_dir $unittest_log_dir.old
184mkdir $unittest_log_dir || exit 2
185
186echo "BUILD_HEAD=$(cat build-head)" > $unittest_log_dir/SUMMARY
187
188if [[ $tap_output == "yes" ]]; then
189    echo "TAP version 13"
190fi
191
192trap "wait; exit 130" SIGINT
193
194(
195   # preserve stdout so that process_test_output output can write TAP to it
196   exec 3>&1
197   test "$tap_output" == "yes" && exec > /dev/null
198   for_each_unittest $config run_task
199) | postprocess_suite_output
200
201# wait until all tasks finish
202wait
203