1#!/usr/bin/env bash 2 3TESTS=("$@") 4TIMEOUT=60 5DMESG_FILTER="cat" 6TEST_DIR=$(dirname "$0") 7FAILED=() 8SKIPPED=() 9TIMED_OUT=() 10TEST_FILES="" 11declare -A TEST_MAP 12 13# Only use /dev/kmsg if running as root 14DO_KMSG="1" 15[ "$(id -u)" != "0" ] && DO_KMSG="0" 16 17# Include config.local if exists and check TEST_FILES for valid devices 18if [ -f "$TEST_DIR/config.local" ]; then 19 # shellcheck source=/dev/null disable=SC1091 20 . "$TEST_DIR/config.local" 21 for dev in $TEST_FILES; do 22 if [ ! -e "$dev" ]; then 23 echo "Test file $dev not valid" 24 exit 1 25 fi 26 done 27 for dev in "${TEST_MAP[@]}"; do 28 if [ ! -e "$dev" ]; then 29 echo "Test file in map $dev not valid" 30 exit 1 31 fi 32 done 33fi 34 35_check_dmesg() 36{ 37 local dmesg_marker="$1" 38 local seqres="$2.seqres" 39 40 if [ "$DO_KMSG" -eq 0 ]; then 41 return 0 42 fi 43 44 dmesg | bash -c "$DMESG_FILTER" | grep -A 9999 "$dmesg_marker" >"${seqres}.dmesg" 45 grep -q -e "kernel BUG at" \ 46 -e "WARNING:" \ 47 -e "BUG:" \ 48 -e "Oops:" \ 49 -e "possible recursive locking detected" \ 50 -e "Internal error" \ 51 -e "INFO: suspicious RCU usage" \ 52 -e "INFO: possible circular locking dependency detected" \ 53 -e "general protection fault:" \ 54 -e "blktests failure" \ 55 "${seqres}.dmesg" 56 # shellcheck disable=SC2181 57 if [[ $? -eq 0 ]]; then 58 return 1 59 else 60 rm -f "${seqres}.dmesg" 61 return 0 62 fi 63} 64 65run_test() 66{ 67 local test_name="$1" 68 local dev="$2" 69 local test_exec=("./$test_name") 70 local test_string="$test_name" 71 local out_name="$test_name" 72 73 # Specify test string to print 74 if [ -n "$dev" ]; then 75 test_exec+=("$dev") 76 test_string="$test_name $dev" 77 local suffix 78 suffix=$(basename "$dev") 79 out_name="$out_name.$suffix" 80 fi 81 82 # Log start of the test 83 if [ "$DO_KMSG" -eq 1 ]; then 84 local dmesg_marker="Running test $test_string:" 85 echo "$dmesg_marker" > /dev/kmsg 86 else 87 local dmesg_marker="" 88 fi 89 printf "Running test %-55s" "$test_string" 90 91 # Do we have to exclude the test ? 92 echo "$TEST_EXCLUDE" | grep -w "$test_name" > /dev/null 2>&1 93 # shellcheck disable=SC2181 94 if [ $? -eq 0 ]; then 95 echo "Test skipped" 96 SKIPPED+=("<$test_string>") 97 return 98 fi 99 100 # Run the test 101 T_START=$(date +%s) 102 timeout -s INT -k $TIMEOUT $TIMEOUT "${test_exec[@]}" 103 local status=$? 104 T_END=$(date +%s) 105 106 if [ -e ./core ]; then 107 mv core "core-$test_name" 108 fi 109 110 # Check test status 111 if [ "$status" -eq 124 ]; then 112 echo "Test $test_name timed out (may not be a failure)" 113 TIMED_OUT+=("<$test_string>") 114 elif [ "$status" -eq 77 ]; then 115 echo "Skipped" 116 SKIPPED+=("<$test_string>") 117 elif [[ $test_string != xfail* ]] && [ "$status" -ne 0 ]; then 118 echo "Test $test_name failed with ret $status" 119 FAILED+=("<$test_string>") 120 elif [[ $test_string == xfail* ]] && [ "$status" -ne 1 ]; then 121 echo "Test $test_name expected fail status 1 but returned $status" 122 FAILED+=("<$test_string>") 123 elif ! _check_dmesg "$dmesg_marker" "$test_name"; then 124 echo "Test $test_name failed dmesg check" 125 FAILED+=("<$test_string>") 126 else 127 if [ -f "output/$out_name" ]; then 128 T_PREV=$(cat "output/$out_name") 129 else 130 T_PREV="" 131 fi 132 T_DIFF=$((T_END-T_START)) 133 if [ -n "$T_PREV" ]; then 134 echo "$T_DIFF sec [$T_PREV]" 135 else 136 echo "$T_DIFF sec" 137 fi 138 echo $T_DIFF > "output/$out_name" 139 fi 140} 141 142# Run all specified tests 143for tst in "${TESTS[@]}"; do 144 if [ ! -d output ]; then 145 mkdir -p output 146 fi 147 if [ -z "${TEST_MAP[$tst]}" ]; then 148 run_test "$tst" 149 if [ -n "$TEST_FILES" ]; then 150 for dev in $TEST_FILES; do 151 run_test "$tst" "$dev" 152 done 153 fi 154 else 155 run_test "$tst" "${TEST_MAP[$tst]}" 156 fi 157done 158 159if [ "$DO_KMSG" -eq "1" ]; then 160 for dmesg_file in *.dmesg; do 161 if [ -f "$dmesg_file" ]; then 162 echo "Found dmesg file $dmesg_file, outputting:" 163 cat "$dmesg_file" 164 fi 165 done 166fi 167 168if [ "${#TIMED_OUT[*]}" -ne 0 ]; then 169 echo "Tests timed out (${#TIMED_OUT[*]}): ${TIMED_OUT[*]}" 170fi 171 172KVER=$(uname -rv) 173echo "Test run complete, kernel: $KVER" 174 175if [ "${#FAILED[*]}" -ne 0 ]; then 176 echo "Tests failed (${#FAILED[*]}): ${FAILED[*]}" 177 exit 1 178elif [ "${#SKIPPED[*]}" -ne 0 ] && [ -n "$TEST_GNU_EXITCODE" ]; then 179 exit 77 180else 181 echo "All tests passed" 182 exit 0 183fi 184