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