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