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 cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args" 115 if [ ! -x "$TEST" ]; then 116 echo "# Warning: file $TEST is not executable" 117 118 if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ] 119 then 120 interpreter=$(head -n 1 "$TEST" | cut -c 3-) 121 cmd="$stdbuf $interpreter ./$BASENAME_TEST" 122 else 123 echo "not ok $test_num $TEST_HDR_MSG" 124 return 125 fi 126 fi 127 cd `dirname $TEST` > /dev/null 128 ((((( tap_timeout "$cmd" 2>&1; echo $? >&3) | 129 tap_prefix >&4) 3>&1) | 130 (read xs; exit $xs)) 4>>"$logfile" && 131 echo "ok $test_num $TEST_HDR_MSG") || 132 (rc=$?; \ 133 if [ $rc -eq $skip_rc ]; then \ 134 echo "ok $test_num $TEST_HDR_MSG # SKIP" 135 elif [ $rc -eq $timeout_rc ]; then \ 136 echo "#" 137 echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds" 138 else 139 echo "not ok $test_num $TEST_HDR_MSG # exit=$rc" 140 fi) 141 cd - >/dev/null 142 fi 143} 144 145in_netns() 146{ 147 local name=$1 148 ip netns exec $name bash <<-EOF 149 BASE_DIR=$BASE_DIR 150 source $BASE_DIR/kselftest/runner.sh 151 logfile=$logfile 152 run_one $DIR $TEST $test_num 153 EOF 154} 155 156run_in_netns() 157{ 158 local netns=$(mktemp -u ${BASENAME_TEST}-XXXXXX) 159 local tmplog="/tmp/$(mktemp -u ${BASENAME_TEST}-XXXXXX)" 160 ip netns add $netns 161 if [ $? -ne 0 ]; then 162 echo "# Warning: Create namespace failed for $BASENAME_TEST" 163 echo "not ok $test_num selftests: $DIR: $BASENAME_TEST # Create NS failed" 164 fi 165 ip -n $netns link set lo up 166 in_netns $netns &> $tmplog 167 ip netns del $netns &> /dev/null 168 cat $tmplog 169 rm -f $tmplog 170} 171 172run_many() 173{ 174 echo "TAP version 13" 175 DIR="${PWD#${BASE_DIR}/}" 176 test_num=0 177 total=$(echo "$@" | wc -w) 178 echo "1..$total" 179 for TEST in "$@"; do 180 BASENAME_TEST=$(basename $TEST) 181 test_num=$(( test_num + 1 )) 182 if [ -n "$per_test_logging" ]; then 183 logfile="/tmp/$BASENAME_TEST" 184 cat /dev/null > "$logfile" 185 fi 186 if [ -n "$RUN_IN_NETNS" ]; then 187 run_in_netns & 188 else 189 run_one "$DIR" "$TEST" "$test_num" 190 fi 191 done 192 193 wait 194} 195