142d46e57SKees Cook#!/bin/sh 242d46e57SKees Cook# SPDX-License-Identifier: GPL-2.0 342d46e57SKees Cook# 442d46e57SKees Cook# Runs a set of tests in a given subdirectory. 542d46e57SKees Cookexport skip_rc=4 6852c8cbfSKees Cookexport timeout_rc=124 742d46e57SKees Cookexport logfile=/dev/stdout 8bf660782SKees Cookexport per_test_logging= 942d46e57SKees Cook 10852c8cbfSKees Cook# Defaults for "settings" file fields: 11f6a01213SLuis Chamberlain# "timeout" how many seconds to let each test run before running 12f6a01213SLuis Chamberlain# over our soft timeout limit. 13852c8cbfSKees Cookexport kselftest_default_timeout=45 14852c8cbfSKees Cook 155c069b6dSKees Cook# There isn't a shell-agnostic way to find the path of a sourced file, 165c069b6dSKees Cook# so we must rely on BASE_DIR being set to find other tools. 175c069b6dSKees Cookif [ -z "$BASE_DIR" ]; then 185c069b6dSKees Cook echo "Error: BASE_DIR must be set before sourcing." >&2 195c069b6dSKees Cook exit 1 205c069b6dSKees Cookfi 215c069b6dSKees Cook 22e005ff01SCristian MarussiTR_CMD=$(command -v tr) 23e005ff01SCristian Marussi 245c069b6dSKees Cook# If Perl is unavailable, we must fall back to line-at-a-time prefixing 255c069b6dSKees Cook# with sed instead of unbuffered output. 265c069b6dSKees Cooktap_prefix() 275c069b6dSKees Cook{ 285c069b6dSKees Cook if [ ! -x /usr/bin/perl ]; then 295c069b6dSKees Cook sed -e 's/^/# /' 305c069b6dSKees Cook else 315c069b6dSKees Cook "$BASE_DIR"/kselftest/prefix.pl 325c069b6dSKees Cook fi 335c069b6dSKees Cook} 345c069b6dSKees Cook 35852c8cbfSKees Cooktap_timeout() 36852c8cbfSKees Cook{ 37852c8cbfSKees Cook # Make sure tests will time out if utility is available. 38852c8cbfSKees Cook if [ -x /usr/bin/timeout ] ; then 39*9616cb34SBjörn Töpel /usr/bin/timeout --foreground "$kselftest_timeout" \ 40*9616cb34SBjörn Töpel /usr/bin/timeout "$kselftest_timeout" $1 41852c8cbfSKees Cook else 42303f8e2dSSeongJae Park $1 43852c8cbfSKees Cook fi 44852c8cbfSKees Cook} 45852c8cbfSKees Cook 4642d46e57SKees Cookrun_one() 4742d46e57SKees Cook{ 48bf660782SKees Cook DIR="$1" 49bf660782SKees Cook TEST="$2" 50bf660782SKees Cook NUM="$3" 5142d46e57SKees Cook 5242d46e57SKees Cook BASENAME_TEST=$(basename $TEST) 5342d46e57SKees Cook 54852c8cbfSKees Cook # Reset any "settings"-file variables. 55852c8cbfSKees Cook export kselftest_timeout="$kselftest_default_timeout" 56e005ff01SCristian Marussi 57e005ff01SCristian Marussi # Safe default if tr not available 58e005ff01SCristian Marussi kselftest_cmd_args_ref="KSELFTEST_ARGS" 59e005ff01SCristian Marussi 60e005ff01SCristian Marussi # Optional arguments for this command, possibly defined as an 61e005ff01SCristian Marussi # environment variable built using the test executable in all 62e005ff01SCristian Marussi # uppercase and sanitized substituting non acceptable shell 63e005ff01SCristian Marussi # variable name characters with "_" as in: 64e005ff01SCristian Marussi # 65e005ff01SCristian Marussi # KSELFTEST_<UPPERCASE_SANITIZED_TESTNAME>_ARGS="<options>" 66e005ff01SCristian Marussi # 67e005ff01SCristian Marussi # e.g. 68e005ff01SCristian Marussi # 69e005ff01SCristian Marussi # rtctest --> KSELFTEST_RTCTEST_ARGS="/dev/rtc1" 70e005ff01SCristian Marussi # 71e005ff01SCristian Marussi # cpu-on-off-test.sh --> KSELFTEST_CPU_ON_OFF_TEST_SH_ARGS="-a -p 10" 72e005ff01SCristian Marussi # 73e005ff01SCristian Marussi if [ -n "$TR_CMD" ]; then 74e005ff01SCristian Marussi BASENAME_SANITIZED=$(echo "$BASENAME_TEST" | \ 75e005ff01SCristian Marussi $TR_CMD -d "[:blank:][:cntrl:]" | \ 76e005ff01SCristian Marussi $TR_CMD -c "[:alnum:]_" "_" | \ 77e005ff01SCristian Marussi $TR_CMD [:lower:] [:upper:]) 78e005ff01SCristian Marussi kselftest_cmd_args_ref="KSELFTEST_${BASENAME_SANITIZED}_ARGS" 79e005ff01SCristian Marussi fi 80e005ff01SCristian Marussi 81852c8cbfSKees Cook # Load per-test-directory kselftest "settings" file. 82852c8cbfSKees Cook settings="$BASE_DIR/$DIR/settings" 83852c8cbfSKees Cook if [ -r "$settings" ] ; then 84852c8cbfSKees Cook while read line ; do 854505e215SKees Cook # Skip comments. 864505e215SKees Cook if echo "$line" | grep -q '^#'; then 874505e215SKees Cook continue 884505e215SKees Cook fi 89852c8cbfSKees Cook field=$(echo "$line" | cut -d= -f1) 90852c8cbfSKees Cook value=$(echo "$line" | cut -d= -f2-) 91852c8cbfSKees Cook eval "kselftest_$field"="$value" 92852c8cbfSKees Cook done < "$settings" 93852c8cbfSKees Cook fi 94852c8cbfSKees Cook 95f6a01213SLuis Chamberlain # Command line timeout overrides the settings file 96f6a01213SLuis Chamberlain if [ -n "$kselftest_override_timeout" ]; then 97f6a01213SLuis Chamberlain kselftest_timeout="$kselftest_override_timeout" 98f6a01213SLuis Chamberlain echo "# overriding timeout to $kselftest_timeout" >> "$logfile" 99f6a01213SLuis Chamberlain else 100f6a01213SLuis Chamberlain echo "# timeout set to $kselftest_timeout" >> "$logfile" 101f6a01213SLuis Chamberlain fi 102f6a01213SLuis Chamberlain 103bf660782SKees Cook TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST" 1045c069b6dSKees Cook echo "# $TEST_HDR_MSG" 105fd63b2eaSKees Cook if [ ! -e "$TEST" ]; then 106303f8e2dSSeongJae Park echo "# Warning: file $TEST is missing!" 107b0df366bSKees Cook echo "not ok $test_num $TEST_HDR_MSG" 10842d46e57SKees Cook else 10958e2847aSRyan Roberts if [ -x /usr/bin/stdbuf ]; then 11058e2847aSRyan Roberts stdbuf="/usr/bin/stdbuf --output=L " 11158e2847aSRyan Roberts fi 112e005ff01SCristian Marussi eval kselftest_cmd_args="\$${kselftest_cmd_args_ref:-}" 11358e2847aSRyan Roberts cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args" 114303f8e2dSSeongJae Park if [ ! -x "$TEST" ]; then 115303f8e2dSSeongJae Park echo "# Warning: file $TEST is not executable" 116303f8e2dSSeongJae Park 117303f8e2dSSeongJae Park if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ] 118303f8e2dSSeongJae Park then 119303f8e2dSSeongJae Park interpreter=$(head -n 1 "$TEST" | cut -c 3-) 12058e2847aSRyan Roberts cmd="$stdbuf $interpreter ./$BASENAME_TEST" 121303f8e2dSSeongJae Park else 122303f8e2dSSeongJae Park echo "not ok $test_num $TEST_HDR_MSG" 123303f8e2dSSeongJae Park return 124303f8e2dSSeongJae Park fi 125303f8e2dSSeongJae Park fi 12642d46e57SKees Cook cd `dirname $TEST` > /dev/null 127303f8e2dSSeongJae Park ((((( tap_timeout "$cmd" 2>&1; echo $? >&3) | 1285c069b6dSKees Cook tap_prefix >&4) 3>&1) | 1295c069b6dSKees Cook (read xs; exit $xs)) 4>>"$logfile" && 130b0df366bSKees Cook echo "ok $test_num $TEST_HDR_MSG") || 131852c8cbfSKees Cook (rc=$?; \ 132852c8cbfSKees Cook if [ $rc -eq $skip_rc ]; then \ 133b85d387cSPaolo Bonzini echo "ok $test_num $TEST_HDR_MSG # SKIP" 134852c8cbfSKees Cook elif [ $rc -eq $timeout_rc ]; then \ 135d187801dSSeongJae Park echo "#" 1364505e215SKees Cook echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds" 13742d46e57SKees Cook else 138852c8cbfSKees Cook echo "not ok $test_num $TEST_HDR_MSG # exit=$rc" 13942d46e57SKees Cook fi) 14042d46e57SKees Cook cd - >/dev/null 14142d46e57SKees Cook fi 14242d46e57SKees Cook} 143bf660782SKees Cook 144bf660782SKees Cookrun_many() 145bf660782SKees Cook{ 146bf660782SKees Cook echo "TAP version 13" 147ac87813dSMatthieu Baerts DIR="${PWD#${BASE_DIR}/}" 148bf660782SKees Cook test_num=0 149b0df366bSKees Cook total=$(echo "$@" | wc -w) 150b0df366bSKees Cook echo "1..$total" 151bf660782SKees Cook for TEST in "$@"; do 152bf660782SKees Cook BASENAME_TEST=$(basename $TEST) 153bf660782SKees Cook test_num=$(( test_num + 1 )) 154bf660782SKees Cook if [ -n "$per_test_logging" ]; then 155bf660782SKees Cook logfile="/tmp/$BASENAME_TEST" 156bf660782SKees Cook cat /dev/null > "$logfile" 157bf660782SKees Cook fi 158bf660782SKees Cook run_one "$DIR" "$TEST" "$test_num" 159bf660782SKees Cook done 160bf660782SKees Cook} 161