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 [ "$status" -ne 0 ]; then 118 echo "Test $test_name failed with ret $status" 119 FAILED+=("<$test_string>") 120 elif ! _check_dmesg "$dmesg_marker" "$test_name"; then 121 echo "Test $test_name failed dmesg check" 122 FAILED+=("<$test_string>") 123 else 124 if [ -f "output/$out_name" ]; then 125 T_PREV=$(cat "output/$out_name") 126 else 127 T_PREV="" 128 fi 129 T_DIFF=$((T_END-T_START)) 130 if [ -n "$T_PREV" ]; then 131 echo "$T_DIFF sec [$T_PREV]" 132 else 133 echo "$T_DIFF sec" 134 fi 135 echo $T_DIFF > "output/$out_name" 136 fi 137} 138 139# Run all specified tests 140for tst in "${TESTS[@]}"; do 141 if [ ! -d output ]; then 142 mkdir -p output 143 fi 144 if [ -z "${TEST_MAP[$tst]}" ]; then 145 run_test "$tst" 146 if [ -n "$TEST_FILES" ]; then 147 for dev in $TEST_FILES; do 148 run_test "$tst" "$dev" 149 done 150 fi 151 else 152 run_test "$tst" "${TEST_MAP[$tst]}" 153 fi 154done 155 156if [ "${#TIMED_OUT[*]}" -ne 0 ]; then 157 echo "Tests timed out (${#TIMED_OUT[*]}): ${TIMED_OUT[*]}" 158fi 159 160if [ "${#FAILED[*]}" -ne 0 ]; then 161 echo "Tests failed (${#FAILED[*]}): ${FAILED[*]}" 162 exit 1 163elif [ "${#SKIPPED[*]}" -ne 0 ] && [ -n "$TEST_GNU_EXITCODE" ]; then 164 exit 77 165else 166 echo "All tests passed" 167 exit 0 168fi 169