1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0 3# 4# Runs a set of tests in a given subdirectory. 5export skip_rc=4 6export timeout_rc=124 7export logfile=/dev/stdout 8export per_test_logging= 9 10# Defaults for "settings" file fields: 11# "timeout" how many seconds to let each test run before running 12# over our soft timeout limit. 13export kselftest_default_timeout=45 14 15# There isn't a shell-agnostic way to find the path of a sourced file, 16# so we must rely on BASE_DIR being set to find other tools. 17if [ -z "$BASE_DIR" ]; then 18 echo "Error: BASE_DIR must be set before sourcing." >&2 19 exit 1 20fi 21 22TR_CMD=$(command -v tr) 23 24# If Perl is unavailable, we must fall back to line-at-a-time prefixing 25# with sed instead of unbuffered output. 26tap_prefix() 27{ 28 if [ ! -x /usr/bin/perl ]; then 29 sed -e 's/^/# /' 30 else 31 "$BASE_DIR"/kselftest/prefix.pl 32 fi 33} 34 35tap_timeout() 36{ 37 # Make sure tests will time out if utility is available. 38 if [ -x /usr/bin/timeout ] ; then 39 /usr/bin/timeout --foreground "$kselftest_timeout" \ 40 /usr/bin/timeout "$kselftest_timeout" $1 41 else 42 $1 43 fi 44} 45 46run_one() 47{ 48 DIR="$1" 49 TEST="$2" 50 NUM="$3" 51 52 BASENAME_TEST=$(basename $TEST) 53 54 # Reset any "settings"-file variables. 55 export kselftest_timeout="$kselftest_default_timeout" 56 57 # Safe default if tr not available 58 kselftest_cmd_args_ref="KSELFTEST_ARGS" 59 60 # Optional arguments for this command, possibly defined as an 61 # environment variable built using the test executable in all 62 # uppercase and sanitized substituting non acceptable shell 63 # variable name characters with "_" as in: 64 # 65 # KSELFTEST_<UPPERCASE_SANITIZED_TESTNAME>_ARGS="<options>" 66 # 67 # e.g. 68 # 69 # rtctest --> KSELFTEST_RTCTEST_ARGS="/dev/rtc1" 70 # 71 # cpu-on-off-test.sh --> KSELFTEST_CPU_ON_OFF_TEST_SH_ARGS="-a -p 10" 72 # 73 if [ -n "$TR_CMD" ]; then 74 BASENAME_SANITIZED=$(echo "$BASENAME_TEST" | \ 75 $TR_CMD -d "[:blank:][:cntrl:]" | \ 76 $TR_CMD -c "[:alnum:]_" "_" | \ 77 $TR_CMD [:lower:] [:upper:]) 78 kselftest_cmd_args_ref="KSELFTEST_${BASENAME_SANITIZED}_ARGS" 79 fi 80 81 # Load per-test-directory kselftest "settings" file. 82 settings="$BASE_DIR/$DIR/settings" 83 if [ -r "$settings" ] ; then 84 while read line ; do 85 # Skip comments. 86 if echo "$line" | grep -q '^#'; then 87 continue 88 fi 89 field=$(echo "$line" | cut -d= -f1) 90 value=$(echo "$line" | cut -d= -f2-) 91 eval "kselftest_$field"="$value" 92 done < "$settings" 93 fi 94 95 # Command line timeout overrides the settings file 96 if [ -n "$kselftest_override_timeout" ]; then 97 kselftest_timeout="$kselftest_override_timeout" 98 echo "# overriding timeout to $kselftest_timeout" >> "$logfile" 99 else 100 echo "# timeout set to $kselftest_timeout" >> "$logfile" 101 fi 102 103 TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST" 104 echo "# $TEST_HDR_MSG" 105 if [ ! -e "$TEST" ]; then 106 echo "# Warning: file $TEST is missing!" 107 echo "not ok $test_num $TEST_HDR_MSG" 108 else 109 if [ -x /usr/bin/stdbuf ]; then 110 stdbuf="/usr/bin/stdbuf --output=L " 111 fi 112 eval kselftest_cmd_args="\$${kselftest_cmd_args_ref:-}" 113 cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args" 114 if [ ! -x "$TEST" ]; then 115 echo "# Warning: file $TEST is not executable" 116 117 if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ] 118 then 119 interpreter=$(head -n 1 "$TEST" | cut -c 3-) 120 cmd="$stdbuf $interpreter ./$BASENAME_TEST" 121 else 122 echo "not ok $test_num $TEST_HDR_MSG" 123 return 124 fi 125 fi 126 cd `dirname $TEST` > /dev/null 127 ((((( tap_timeout "$cmd" 2>&1; echo $? >&3) | 128 tap_prefix >&4) 3>&1) | 129 (read xs; exit $xs)) 4>>"$logfile" && 130 echo "ok $test_num $TEST_HDR_MSG") || 131 (rc=$?; \ 132 if [ $rc -eq $skip_rc ]; then \ 133 echo "ok $test_num $TEST_HDR_MSG # SKIP" 134 elif [ $rc -eq $timeout_rc ]; then \ 135 echo "#" 136 echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds" 137 else 138 echo "not ok $test_num $TEST_HDR_MSG # exit=$rc" 139 fi) 140 cd - >/dev/null 141 fi 142} 143 144run_many() 145{ 146 echo "TAP version 13" 147 DIR="${PWD#${BASE_DIR}/}" 148 test_num=0 149 total=$(echo "$@" | wc -w) 150 echo "1..$total" 151 for TEST in "$@"; do 152 BASENAME_TEST=$(basename $TEST) 153 test_num=$(( test_num + 1 )) 154 if [ -n "$per_test_logging" ]; then 155 logfile="/tmp/$BASENAME_TEST" 156 cat /dev/null > "$logfile" 157 fi 158 run_one "$DIR" "$TEST" "$test_num" 159 done 160} 161