xref: /kvm-unit-tests/run_tests.sh (revision 1d0f08f40d53daa39566842ec46a112db5f7e524)
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:v:l -l all,group:,help,tap13,parallel:,verbose:,list -- $*)
48[ $? -ne 0 ] && exit 2;
49set -- $args;
50while [ $# -gt 0 ]; do
51    case "$1" in
52        -a | --all)
53            run_all_tests="yes"
54            export ERRATA_FORCE=y
55            ;;
56        -g | --group)
57            shift
58            only_group=$1
59            ;;
60        -h | --help)
61            usage
62            exit
63            ;;
64        -j | --parallel)
65            shift
66            unittest_run_queues=$1
67            if (( $unittest_run_queues <= 0 )); then
68                echo "Invalid -j option: $unittest_run_queues"
69                exit 2
70            fi
71            ;;
72        -v | --verbose)
73            verbose="yes"
74            ;;
75        -t | --tap13)
76            tap_output="yes"
77            ;;
78        -l | --list)
79            list_tests="yes"
80            ;;
81        --)
82            ;;
83        *)
84            only_tests="$only_tests $1"
85            ;;
86    esac
87    shift
88done
89
90# RUNTIME_log_file will be configured later
91if [[ $tap_output == "no" ]]; then
92    process_test_output() { cat >> $RUNTIME_log_file; }
93    postprocess_suite_output() { cat; }
94else
95    process_test_output() {
96        local testname="$1"
97        CR=$'\r'
98        while read -r line; do
99            line="${line%$CR}"
100            case "${line:0:4}" in
101                PASS)
102                    echo "ok TEST_NUMBER - ${testname}: ${line#??????}" >&3
103                    ;;
104                FAIL)
105                    echo "not ok TEST_NUMBER - ${testname}: ${line#??????}" >&3
106                    ;;
107                SKIP)
108                    echo "ok TEST_NUMBER - ${testname}: ${line#??????} # skip" >&3
109                    ;;
110                *)
111                    ;;
112            esac
113            echo "${line}"
114        done >> $RUNTIME_log_file
115    }
116    postprocess_suite_output() {
117        test_number=0
118        while read -r line; do
119            case "${line}" in
120                ok*|"not ok"*)
121                    (( test_number++ ))
122                    echo "${line/TEST_NUMBER/${test_number}}" ;;
123                *) echo "${line}" ;;
124            esac
125        done
126        echo "1..$test_number"
127    }
128fi
129
130RUNTIME_log_stderr () { process_test_output "$1"; }
131RUNTIME_log_stdout () {
132    local testname="$1"
133    if [ "$PRETTY_PRINT_STACKS" = "yes" ]; then
134        local kernel="$2"
135        ./scripts/pretty_print_stacks.py "$kernel" | process_test_output "$testname"
136    else
137        process_test_output "$testname"
138    fi
139}
140
141function run_task()
142{
143	local testname="$1"
144
145	while (( $(jobs | wc -l) == $unittest_run_queues )); do
146		# wait for any background test to finish
147		wait -n 2>/dev/null
148	done
149
150	RUNTIME_log_file="${unittest_log_dir}/${testname}.log"
151	if [ $unittest_run_queues = 1 ]; then
152		run "$@"
153	else
154		run "$@" &
155	fi
156}
157
158: ${unittest_log_dir:=logs}
159: ${unittest_run_queues:=1}
160config=$TEST_DIR/unittests.cfg
161
162print_testname()
163{
164    local testname=$1
165    local groups=$2
166    if [ -n "$only_group" ] && ! find_word "$only_group" "$groups"; then
167        return
168    fi
169    echo "$testname"
170}
171if [[ $list_tests == "yes" ]]; then
172    for_each_unittest $config print_testname
173    exit
174fi
175
176rm -rf $unittest_log_dir.old
177[ -d $unittest_log_dir ] && mv $unittest_log_dir $unittest_log_dir.old
178mkdir $unittest_log_dir || exit 2
179
180echo "BUILD_HEAD=$(cat build-head)" > $unittest_log_dir/SUMMARY
181
182if [[ $tap_output == "yes" ]]; then
183    echo "TAP version 13"
184fi
185
186trap "wait; exit 130" SIGINT
187
188(
189   # preserve stdout so that process_test_output output can write TAP to it
190   exec 3>&1
191   test "$tap_output" == "yes" && exec > /dev/null
192   for_each_unittest $config run_task
193) | postprocess_suite_output
194
195# wait until all tasks finish
196wait
197