xref: /kvm-unit-tests/scripts/runtime.bash (revision f3f338619e4938c2509f5c691adc1f331b07c203)
1: "${RUNTIME_arch_run?}"
2: "${MAX_SMP:=$(getconf _NPROCESSORS_ONLN)}"
3: "${TIMEOUT:=90s}"
4
5PASS() { echo -ne "\e[32mPASS\e[0m"; }
6SKIP() { echo -ne "\e[33mSKIP\e[0m"; }
7FAIL() { echo -ne "\e[31mFAIL\e[0m"; }
8
9extract_summary()
10{
11    local cr=$'\r'
12    tail -5 | grep '^SUMMARY: ' | sed 's/^SUMMARY: /(/;s/'"$cr"'\{0,1\}$/)/'
13}
14
15# We assume that QEMU is going to work if it tried to load the kernel
16premature_failure()
17{
18    local log
19
20    log="$(eval "$(get_cmdline _NO_FILE_4Uhere_)" 2>&1)"
21
22    vmm_parse_premature_failure "$log" || return 1
23
24    RUNTIME_log_stderr <<< "$log"
25
26    echo "$log"
27    return 0
28}
29
30get_cmdline()
31{
32    local kernel=$1
33    echo "TESTNAME=$testname TIMEOUT=$timeout MACHINE=$machine ACCEL=$accel $RUNTIME_arch_run $kernel $smp $test_args $opts"
34}
35
36skip_nodefault()
37{
38    [ "$run_all_tests" = "yes" ] && return 1
39    [ "$KUT_STANDALONE" != "yes" ] && return 0
40
41    while true; do
42        read -r -p "Test marked not to be run by default, are you sure (y/N)? " yn
43        case $yn in
44            "Y" | "y" | "Yes" | "yes")
45                return 1
46                ;;
47            "" | "N" | "n" | "No" | "no" | "q" | "quit" | "exit")
48                return 0
49                ;;
50        esac
51    done
52}
53
54function print_result()
55{
56    local status="$1"
57    local testname="$2"
58    local summary="$3"
59    local reason="$4"
60
61    if [ -z "$reason" ]; then
62        echo "$($status) $testname $summary"
63    else
64        echo "$($status) $testname ($reason)"
65    fi
66}
67
68function find_word()
69{
70    grep -Fq " $1 " <<< " $2 "
71}
72
73function run()
74{
75    local testname="$1"
76    local groups="$2"
77    local smp="$3"
78    local kernel="$4"
79    local test_args="$5"
80    local opts="$6"
81    local arch="$7"
82    local machine="$8"
83    local check="${CHECK:-$9}"
84    local accel="${10}"
85    local timeout="${11:-$TIMEOUT}" # unittests.cfg overrides the default
86    local disabled_if="${12}"
87
88    if [ "${CONFIG_EFI}" == "y" ]; then
89        kernel=${kernel/%.flat/.efi}
90    fi
91
92    if [ -z "$testname" ]; then
93        return
94    fi
95
96    if [ -n "$only_tests" ] && ! find_word "$testname" "$only_tests"; then
97        return
98    fi
99
100    if [ -n "$only_group" ] && ! find_word "$only_group" "$groups"; then
101        return
102    fi
103
104    if [ -z "$GEN_SE_HEADER" ] && find_word "pv-host" "$groups"; then
105        print_result "SKIP" $testname "" "no gen-se-header available for pv-host test"
106        return
107    fi
108
109    if [ -z "$only_group" ] && find_word nodefault "$groups" &&
110            skip_nodefault; then
111        print_result "SKIP" $testname "" "test marked as manual run only"
112        return;
113    fi
114
115    if [ -n "$arch" ] && [ "$arch" != "$ARCH" ]; then
116        print_result "SKIP" $testname "" "$arch only"
117        return 2
118    fi
119
120    if [ -n "$machine" ] && [ -n "$MACHINE" ] && [ "$machine" != "$MACHINE" ]; then
121        print_result "SKIP" $testname "" "$machine only"
122        return 2
123    elif [ -n "$MACHINE" ]; then
124        machine="$MACHINE"
125    fi
126
127    if [ -n "$accel" ] && [ -n "$ACCEL" ] && [[ ! "$ACCEL" =~ ^$accel(,|$) ]]; then
128        print_result "SKIP" $testname "" "$accel only, but ACCEL=$ACCEL"
129        return 2
130    elif [ -n "$ACCEL" ]; then
131        accel="$ACCEL"
132    fi
133
134    if [[ "$disabled_if" ]] && (eval $disabled_if); then
135        print_result "SKIP" $testname "" "disabled because: $disabled_if"
136	return 2
137    fi
138
139    # check a file for a particular value before running a test
140    # the check line can contain multiple files to check separated by a space
141    # but each check parameter needs to be of the form <path>=<value>
142    if [ "$check" ]; then
143        # There is no globbing or whitespace allowed in check parameters.
144        # shellcheck disable=SC2206
145        check=($check)
146        for check_param in "${check[@]}"; do
147            path=${check_param%%=*}
148            value=${check_param#*=}
149            if ! [ -f "$path" ] || [ "$(cat $path)" != "$value" ]; then
150                print_result "SKIP" $testname "" "$path not equal to $value"
151                return 2
152            fi
153        done
154    fi
155
156    if [ ! -f "$kernel" ]; then
157        print_result "SKIP" $testname "" "Test file '$kernel' not found";
158        return 2;
159    fi
160
161    log=$(premature_failure) && {
162        skip=true
163        if [ "${CONFIG_EFI}" == "y" ]; then
164            if [ "$ARCH" == "x86_64" ] &&
165               [[ "$(tail -1 <<<"$log")" =~ "Dummy Hello World!" ]]; then
166                   skip=false
167            elif [ "$ARCH" == "arm64" ] &&
168               [[ "$(tail -2 <<<"$log" | head -1)" =~ "Dummy Hello World!" ]]; then
169                   skip=false
170            fi
171        fi
172
173        if [ ${skip} == true ]; then
174            print_result "SKIP" $testname "" "$(tail -1 <<<"$log")"
175            return 77
176        fi
177    }
178
179    cmdline=$(get_cmdline $kernel)
180    if find_word "migration" "$groups"; then
181        cmdline="MIGRATION=yes $cmdline"
182    fi
183    if find_word "panic" "$groups"; then
184        cmdline="PANIC=yes $cmdline"
185    fi
186    if [ "$verbose" = "yes" ]; then
187        echo $cmdline
188    fi
189
190    # qemu_params/extra_params in the config file may contain backticks that
191    # need to be expanded, so use eval to start qemu.  Use "> >(foo)" instead of
192    # a pipe to preserve the exit status.
193    summary=$(eval "$cmdline" 2> >(RUNTIME_log_stderr $testname) \
194                             > >(tee >(RUNTIME_log_stdout $testname $kernel) | extract_summary))
195    ret=$?
196    [ "$KUT_STANDALONE" != "yes" ] && echo > >(RUNTIME_log_stdout $testname $kernel)
197
198    if [ $ret -eq 0 ]; then
199        print_result "PASS" $testname "$summary"
200    elif [ $ret -eq 77 ]; then
201        print_result "SKIP" $testname "$summary"
202    elif [ $ret -eq 124 ]; then
203        print_result "FAIL" $testname "" "timeout; duration=$timeout"
204        if [ "$tap_output" = "yes" ]; then
205            echo "not ok TEST_NUMBER - ${testname}: timeout; duration=$timeout" >&3
206        fi
207    elif [ $ret -gt 127 ]; then
208        signame="SIG"$(kill -l $(($ret - 128)))
209        print_result "FAIL" $testname "" "terminated on $signame"
210        if [ "$tap_output" = "yes" ]; then
211            echo "not ok TEST_NUMBER - ${testname}: terminated on $signame" >&3
212        fi
213    elif [ $ret -eq 127 ] && [ "$tap_output" = "yes" ]; then
214        echo "not ok TEST_NUMBER - ${testname}: aborted" >&3
215    else
216        print_result "FAIL" $testname "$summary"
217    fi
218
219    return $ret
220}
221