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 47report_failure() 48{ 49 echo "not ok $*" 50 echo "$*" >> "$kselftest_failures_file" 51} 52 53run_one() 54{ 55 DIR="$1" 56 TEST="$2" 57 local test_num="$3" 58 59 BASENAME_TEST=$(basename $TEST) 60 61 # Reset any "settings"-file variables. 62 export kselftest_timeout="$kselftest_default_timeout" 63 64 # Safe default if tr not available 65 kselftest_cmd_args_ref="KSELFTEST_ARGS" 66 67 # Optional arguments for this command, possibly defined as an 68 # environment variable built using the test executable in all 69 # uppercase and sanitized substituting non acceptable shell 70 # variable name characters with "_" as in: 71 # 72 # KSELFTEST_<UPPERCASE_SANITIZED_TESTNAME>_ARGS="<options>" 73 # 74 # e.g. 75 # 76 # rtctest --> KSELFTEST_RTCTEST_ARGS="/dev/rtc1" 77 # 78 # cpu-on-off-test.sh --> KSELFTEST_CPU_ON_OFF_TEST_SH_ARGS="-a -p 10" 79 # 80 if [ -n "$TR_CMD" ]; then 81 BASENAME_SANITIZED=$(echo "$BASENAME_TEST" | \ 82 $TR_CMD -d "[:blank:][:cntrl:]" | \ 83 $TR_CMD -c "[:alnum:]_" "_" | \ 84 $TR_CMD [:lower:] [:upper:]) 85 kselftest_cmd_args_ref="KSELFTEST_${BASENAME_SANITIZED}_ARGS" 86 fi 87 88 # Load per-test-directory kselftest "settings" file. 89 settings="$BASE_DIR/$DIR/settings" 90 if [ -r "$settings" ] ; then 91 while read line ; do 92 # Skip comments. 93 if echo "$line" | grep -q '^#'; then 94 continue 95 fi 96 field=$(echo "$line" | cut -d= -f1) 97 value=$(echo "$line" | cut -d= -f2-) 98 eval "kselftest_$field"="$value" 99 done < "$settings" 100 fi 101 102 # Command line timeout overrides the settings file 103 if [ -n "$kselftest_override_timeout" ]; then 104 kselftest_timeout="$kselftest_override_timeout" 105 echo "# overriding timeout to $kselftest_timeout" >> "$logfile" 106 else 107 echo "# timeout set to $kselftest_timeout" >> "$logfile" 108 fi 109 110 TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST" 111 echo "# $TEST_HDR_MSG" 112 if [ ! -e "$TEST" ]; then 113 echo "# Warning: file $TEST is missing!" 114 report_failure "$test_num $TEST_HDR_MSG" 115 else 116 if [ -x /usr/bin/stdbuf ]; then 117 stdbuf="/usr/bin/stdbuf --output=L " 118 fi 119 eval kselftest_cmd_args="\$${kselftest_cmd_args_ref:-}" 120 if [ -x "$TEST" ]; then 121 cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args" 122 elif [ -x "./ksft_runner.sh" ]; then 123 cmd="$stdbuf ./ksft_runner.sh ./$BASENAME_TEST" 124 else 125 echo "# Warning: file $TEST is not executable" 126 127 if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ] 128 then 129 interpreter=$(head -n 1 "$TEST" | cut -c 3-) 130 cmd="$stdbuf $interpreter ./$BASENAME_TEST" 131 else 132 report_failure "$test_num $TEST_HDR_MSG" 133 return 134 fi 135 fi 136 cd `dirname $TEST` > /dev/null 137 ((((( tap_timeout "$cmd" 2>&1; echo $? >&3) | 138 tap_prefix >&4) 3>&1) | 139 (read xs; exit $xs)) 4>>"$logfile" && 140 echo "ok $test_num $TEST_HDR_MSG") || 141 (rc=$?; \ 142 if [ $rc -eq $skip_rc ]; then \ 143 echo "ok $test_num $TEST_HDR_MSG # SKIP" 144 elif [ $rc -eq $timeout_rc ]; then \ 145 echo "#" 146 report_failure "$test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds" 147 else 148 report_failure "$test_num $TEST_HDR_MSG # exit=$rc" 149 fi) 150 cd - >/dev/null 151 fi 152} 153 154in_netns() 155{ 156 local name=$1 157 ip netns exec $name bash <<-EOF 158 BASE_DIR=$BASE_DIR 159 source $BASE_DIR/kselftest/runner.sh 160 logfile=$logfile 161 run_one $DIR $TEST $test_num 162 EOF 163} 164 165run_in_netns() 166{ 167 local netns=$(mktemp -u ${BASENAME_TEST}-XXXXXX) 168 local tmplog="/tmp/$(mktemp -u ${BASENAME_TEST}-XXXXXX)" 169 ip netns add $netns 170 if [ $? -ne 0 ]; then 171 echo "# Warning: Create namespace failed for $BASENAME_TEST" 172 echo "not ok $test_num selftests: $DIR: $BASENAME_TEST # Create NS failed" 173 fi 174 ip -n $netns link set lo up 175 in_netns $netns &> $tmplog 176 ip netns del $netns &> /dev/null 177 cat $tmplog 178 rm -f $tmplog 179} 180 181run_many() 182{ 183 echo "TAP version 13" 184 DIR="${PWD#${BASE_DIR}/}" 185 test_num=0 186 total=$(echo "$@" | wc -w) 187 echo "1..$total" 188 for TEST in "$@"; do 189 BASENAME_TEST=$(basename $TEST) 190 test_num=$(( test_num + 1 )) 191 if [ -n "$per_test_logging" ]; then 192 logfile="/tmp/$BASENAME_TEST" 193 cat /dev/null > "$logfile" 194 fi 195 if [ -n "$RUN_IN_NETNS" ]; then 196 run_in_netns & 197 else 198 run_one "$DIR" "$TEST" "$test_num" 199 fi 200 done 201 202 wait 203} 204