diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-15 03:46:12 +0300 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-15 03:46:12 +0300 |
| commit | e997ac58ad0b47141c62c79cde8356fe5633287a (patch) | |
| tree | e90b14828d52d0eb8131bac7b54fb7b3775fbffc /tools | |
| parent | 6198c86a975f7bec992459fe4506846caae4e41a (diff) | |
| parent | f8e0a5a174d7d3bc3547c15bc1647c35427f5c34 (diff) | |
| download | linux-e997ac58ad0b47141c62c79cde8356fe5633287a.tar.xz | |
Merge tag 'linux_kselftest-next-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull kselftest updates from Shuah Khan:
- cpu-hotplug: fix to check if cpu hotplug is supported to avoid
test failures when cpu hotplug isn't supported.
- frace: fix to relevant comparisons and path checks in the helper so
it handles those patterns without spurious shell warnings.
- runner.sh: add ktrap support
- tracing: fix to make --logdir option work again
- tracing: fix to check awk supports non POSIX strtonum()
- mqueue: fix incorrectly named settings file to make sure the test
used the correct timeout value
- kselftest:
- fix to treat xpass as successful result
- add ksft_reset_state()
- kselftest_harness:
- validate kselftest exit codes are handled explicitly
- add detection of invalid mixing of kselftest and harness
functionality
- add validation of intermixing of kselftest and harness
functionality
- run_kselftest.sh:
- remove unused $ROOT
- resolve BASE_DIR with pwd -P to avoid dependency on realpath
or readlink commands to generate a physical absolute path for
BASE_DIR
- allow choosing per-test log directory
- preserve subtarget failures in all/install
* tag 'linux_kselftest-next-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
selftests/ftrace: Quote check_requires comparisons
selftests: Preserve subtarget failures in all/install
selftests/run_kselftest.sh: Allow choosing per-test log directory
selftests/run_kselftest.sh: Resolve BASE_DIR with pwd -P
selftests/run_kselftest.sh: Remove unused $ROOT
selftests/cpu-hotplug: Fix check for cpu hotplug not supported
selftests/mqueue: Fix incorrectly named file
selftests: Use ktap helpers for runner.sh
selftests: harness: Validate intermixing of kselftest and harness functionality
selftests: harness: Detect illegal mixing of kselftest and harness functionality
selftests: kselftest: Add ksft_reset_state()
selftests: harness: Validate that explicit kselftest exitcodes are handled
selftests: kselftest: Treat xpass as successful result
selftests/tracing: Fix to check awk supports non POSIX strtonum()
selftests/tracing: Fix to make --logdir option work again
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/testing/selftests/Makefile | 8 | ||||
| -rwxr-xr-x | tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh | 2 | ||||
| -rwxr-xr-x | tools/testing/selftests/ftrace/ftracetest | 18 | ||||
| -rw-r--r-- | tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc | 2 | ||||
| -rw-r--r-- | tools/testing/selftests/ftrace/test.d/functions | 18 | ||||
| -rw-r--r-- | tools/testing/selftests/kselftest.h | 12 | ||||
| -rw-r--r-- | tools/testing/selftests/kselftest/runner.sh | 98 | ||||
| -rw-r--r-- | tools/testing/selftests/kselftest_harness.h | 9 | ||||
| -rw-r--r-- | tools/testing/selftests/kselftest_harness/harness-selftest.c | 40 | ||||
| -rw-r--r-- | tools/testing/selftests/kselftest_harness/harness-selftest.expected | 52 | ||||
| -rw-r--r-- | tools/testing/selftests/mqueue/settings (renamed from tools/testing/selftests/mqueue/setting) | 0 | ||||
| -rwxr-xr-x | tools/testing/selftests/run_kselftest.sh | 59 |
12 files changed, 238 insertions, 80 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 450f13ba4cca..0949f370ad78 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -209,14 +209,14 @@ export KHDR_INCLUDES .DEFAULT_GOAL := all all: - @ret=1; \ + @ret=0; \ for TARGET in $(TARGETS) $(INSTALL_DEP_TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ mkdir $$BUILD_TARGET -p; \ $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET \ O=$(abs_objtree) \ $(if $(FORCE_TARGETS),|| exit); \ - ret=$$((ret * $$?)); \ + [ $$? -eq 0 ] || ret=1; \ done; exit $$ret; run_tests: all @@ -274,7 +274,7 @@ ifdef INSTALL_PATH install -m 744 kselftest/ksft.py $(INSTALL_PATH)/kselftest/ install -m 744 run_kselftest.sh $(INSTALL_PATH)/ rm -f $(TEST_LIST) - @ret=1; \ + @ret=0; \ for TARGET in $(TARGETS) $(INSTALL_DEP_TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install \ @@ -283,7 +283,7 @@ ifdef INSTALL_PATH OBJ_PATH=$(INSTALL_PATH) \ O=$(abs_objtree) \ $(if $(FORCE_TARGETS),|| exit); \ - ret=$$((ret * $$?)); \ + [ $$? -eq 0 ] || ret=1; \ done; exit $$ret; diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh index 6232a46ca6e1..287cfd5809f6 100755 --- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh @@ -24,7 +24,7 @@ prerequisite() exit $ksft_skip fi - if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then + if ! ls $SYSFS/devices/system/cpu/cpu*/online > /dev/null 2>&1; then echo $msg cpu hotplug is not supported >&2 exit $ksft_skip fi diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest index 3230bd54dba8..0a56bf209f6c 100755 --- a/tools/testing/selftests/ftrace/ftracetest +++ b/tools/testing/selftests/ftrace/ftracetest @@ -130,8 +130,7 @@ parse_opts() { # opts shift 1 ;; --logdir|-l) - LOG_DIR=$2 - LINK_PTR= + USER_LOG_DIR=$2 shift 2 ;; --rv) @@ -199,6 +198,7 @@ fi TOP_DIR=`absdir $0` TEST_DIR=$TOP_DIR/test.d TEST_CASES=`find_testcases $TEST_DIR` +USER_LOG_DIR= KEEP_LOG=0 KTAP=0 DEBUG=0 @@ -210,12 +210,18 @@ RV_TEST=0 # Parse command-line options parse_opts $* +[ $DEBUG -ne 0 ] && set -x + +# TOP_DIR can be changed for rv. Setting log directory. LOG_TOP_DIR=$TOP_DIR/logs LOG_DATE=`date +%Y%m%d-%H%M%S` -LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/ -LINK_PTR=$LOG_TOP_DIR/latest - -[ $DEBUG -ne 0 ] && set -x +if [ -n "$USER_LOG_DIR" ]; then + LOG_DIR=$USER_LOG_DIR + LINK_PTR= +else + LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/ + LINK_PTR=$LOG_TOP_DIR/latest +fi if [ $RV_TEST -ne 0 ]; then TRACING_DIR=$TRACING_DIR/rv diff --git a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc index a2c42e13f614..8e905d4fe6dd 100644 --- a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc +++ b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc @@ -4,6 +4,8 @@ # requires: trace_marker_raw # flags: instance +check_awk_strtonum || exit_unresolved + is_little_endian() { if lscpu | grep -q 'Little Endian'; then echo 1; diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions index e8e718139294..826141e299e5 100644 --- a/tools/testing/selftests/ftrace/test.d/functions +++ b/tools/testing/selftests/ftrace/test.d/functions @@ -145,13 +145,13 @@ check_requires() { # Check required files and tracers p=${i%:program} r=${i%:README} t=${i%:tracer} - if [ $p != $i ]; then - if ! which $p ; then + if [ "$p" != "$i" ]; then + if ! which "$p" ; then echo "Required program $p is not found." exit_unresolved fi - elif [ $t != $i ]; then - if ! grep -wq $t available_tracers ; then + elif [ "$t" != "$i" ]; then + if ! grep -wq "$t" available_tracers ; then echo "Required tracer $t is not configured." exit_unsupported fi @@ -162,17 +162,21 @@ check_requires() { # Check required files and tracers else test=$TRACING_DIR fi - if ! grep -Fq "$r" $test/README ; then + if ! grep -Fq "$r" "$test"/README ; then echo "Required feature pattern \"$r\" is not in README." exit_unsupported fi - elif [ ! -e $i ]; then + elif [ ! -e "$i" ]; then echo "Required feature interface $i doesn't exist." exit_unsupported fi done } +check_awk_strtonum() { # strtonum is GNU awk extension + awk 'BEGIN{strtonum("0x1")}' +} + LOCALHOST=127.0.0.1 yield() { @@ -223,4 +227,4 @@ get_mnt_options() { local opts=$(mount | grep -m1 "$mnt_point" | sed -e 's/.*(\(.*\)).*/\1/') echo "$opts" -}
\ No newline at end of file +} diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h index afbcf8412ae5..6d809f08ab7b 100644 --- a/tools/testing/selftests/kselftest.h +++ b/tools/testing/selftests/kselftest.h @@ -399,6 +399,7 @@ static inline __noreturn void ksft_exit_fail(void) #define ksft_finished() \ ksft_exit(ksft_plan == \ ksft_cnt.ksft_pass + \ + ksft_cnt.ksft_xpass + \ ksft_cnt.ksft_xfail + \ ksft_cnt.ksft_xskip) @@ -475,4 +476,15 @@ static inline int ksft_min_kernel_version(unsigned int min_major, return major > min_major || (major == min_major && minor >= min_minor); } +static inline void ksft_reset_state(void) +{ + ksft_cnt.ksft_pass = 0; + ksft_cnt.ksft_fail = 0; + ksft_cnt.ksft_xfail = 0; + ksft_cnt.ksft_xpass = 0; + ksft_cnt.ksft_xskip = 0; + ksft_cnt.ksft_error = 0; + ksft_plan = 0; +} + #endif /* __KSELFTEST_H */ diff --git a/tools/testing/selftests/kselftest/runner.sh b/tools/testing/selftests/kselftest/runner.sh index 3a62039fa621..6da3390825fe 100644 --- a/tools/testing/selftests/kselftest/runner.sh +++ b/tools/testing/selftests/kselftest/runner.sh @@ -1,11 +1,12 @@ -#!/bin/sh +#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # # Runs a set of tests in a given subdirectory. -export skip_rc=4 +. $(dirname "$(readlink -e "${BASH_SOURCE[0]}")")/ktap_helpers.sh export timeout_rc=124 export logfile=/dev/stdout export per_test_logging= +export per_test_log_dir=/tmp export RUN_IN_NETNS= # Defaults for "settings" file fields: @@ -44,17 +45,11 @@ tap_timeout() fi } -report_failure() -{ - echo "not ok $*" - echo "$*" >> "$kselftest_failures_file" -} - run_one() { DIR="$1" TEST="$2" - local test_num="$3" + local rc test_num="$3" BASENAME_TEST=$(basename $TEST) @@ -102,16 +97,17 @@ run_one() # Command line timeout overrides the settings file if [ -n "$kselftest_override_timeout" ]; then kselftest_timeout="$kselftest_override_timeout" - echo "# overriding timeout to $kselftest_timeout" >> "$logfile" + ktap_print_msg "overriding timeout to $kselftest_timeout" >> "$logfile" else - echo "# timeout set to $kselftest_timeout" >> "$logfile" + ktap_print_msg "timeout set to $kselftest_timeout" >> "$logfile" fi TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST" echo "# $TEST_HDR_MSG" if [ ! -e "$TEST" ]; then - echo "# Warning: file $TEST is missing!" - report_failure "$test_num $TEST_HDR_MSG" + ktap_print_msg "Warning: file $TEST is missing!" + ktap_test_fail "$test_num $TEST_HDR_MSG" + rc=$KSFT_FAIL else if [ -x /usr/bin/stdbuf ]; then stdbuf="/usr/bin/stdbuf --output=L " @@ -122,33 +118,38 @@ run_one() elif [ -x "./ksft_runner.sh" ]; then cmd="$stdbuf ./ksft_runner.sh ./$BASENAME_TEST" else - echo "# Warning: file $TEST is not executable" + ktap_print_msg "Warning: file $TEST is not executable" if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ] then interpreter=$(head -n 1 "$TEST" | cut -c 3-) cmd="$stdbuf $interpreter ./$BASENAME_TEST" else - report_failure "$test_num $TEST_HDR_MSG" - return + ktap_test_fail "$test_num $TEST_HDR_MSG" + return $KSFT_FAIL fi fi cd `dirname $TEST` > /dev/null - ((((( tap_timeout "$cmd" 2>&1; echo $? >&3) | + (((( tap_timeout "$cmd" 2>&1; echo $? >&3) | tap_prefix >&4) 3>&1) | - (read xs; exit $xs)) 4>>"$logfile" && - echo "ok $test_num $TEST_HDR_MSG") || - (rc=$?; \ - if [ $rc -eq $skip_rc ]; then \ - echo "ok $test_num $TEST_HDR_MSG # SKIP" - elif [ $rc -eq $timeout_rc ]; then \ - echo "#" - report_failure "$test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds" - else - report_failure "$test_num $TEST_HDR_MSG # exit=$rc" - fi) + (read xs; exit $xs)) 4>>"$logfile" + rc=$? + case "$rc" in + "$KSFT_PASS") + ktap_test_pass "$test_num $TEST_HDR_MSG";; + "$KSFT_SKIP") + ktap_test_skip "$test_num $TEST_HDR_MSG";; + "$KSFT_XFAIL") + ktap_test_xfail "$test_num $TEST_HDR_MSG";; + "$timeout_rc") + ktap_test_fail "$test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds";; + *) + ktap_test_fail "$test_num $TEST_HDR_MSG # exit=$rc";; + esac cd - >/dev/null fi + + return $rc } in_netns() @@ -164,40 +165,65 @@ in_netns() run_in_netns() { - local netns=$(mktemp -u ${BASENAME_TEST}-XXXXXX) local tmplog="/tmp/$(mktemp -u ${BASENAME_TEST}-XXXXXX)" + local netns=$(mktemp -u ${BASENAME_TEST}-XXXXXX) + local rc + ip netns add $netns if [ $? -ne 0 ]; then - echo "# Warning: Create namespace failed for $BASENAME_TEST" - echo "not ok $test_num selftests: $DIR: $BASENAME_TEST # Create NS failed" + ktap_print_msg "Warning: Create namespace failed for $BASENAME_TEST" + ktap_test_fail "$test_num selftests: $DIR: $BASENAME_TEST # Create NS failed" fi ip -n $netns link set lo up + in_netns $netns &> $tmplog + rc=$? + ip netns del $netns &> /dev/null + # Cat the log at once to avoid parallel netns logs. cat $tmplog rm -f $tmplog + return $rc } run_many() { - echo "TAP version 13" DIR="${PWD#${BASE_DIR}/}" test_num=0 - total=$(echo "$@" | wc -w) - echo "1..$total" + local rc + pids=() + for TEST in "$@"; do BASENAME_TEST=$(basename $TEST) test_num=$(( test_num + 1 )) if [ -n "$per_test_logging" ]; then - logfile="/tmp/$BASENAME_TEST" + logfile="$per_test_log_dir/$BASENAME_TEST" cat /dev/null > "$logfile" fi if [ -n "$RUN_IN_NETNS" ]; then run_in_netns & + pids+=($!) else run_one "$DIR" "$TEST" "$test_num" fi done - wait + # These variables are outputs of ktap_helpers.sh but since we've + # run the test in a subprocess we need to update them manually + for pid in "${pids[@]}"; do + wait "$pid" + rc=$? + case "$rc" in + "$KSFT_PASS") + KTAP_CNT_PASS=$((KTAP_CNT_PASS + 1));; + "$KSFT_FAIL") + KTAP_CNT_FAIL=$((KTAP_CNT_FAIL + 1));; + "$KSFT_SKIP") + KTAP_CNT_SKIP=$((KTAP_CNT_SKIP + 1));; + "$KSFT_XFAIL") + KTAP_CNT_XFAIL=$((KTAP_CNT_XFAIL + 1));; + *) + KTAP_CNT_FAIL=$((KTAP_CNT_FAIL + 1));; + esac + done } diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h index 4afaef01c22e..75fb016cd190 100644 --- a/tools/testing/selftests/kselftest_harness.h +++ b/tools/testing/selftests/kselftest_harness.h @@ -1225,7 +1225,16 @@ static void __run_test(struct __fixture_metadata *f, t->exit_code = KSFT_FAIL; } else if (child == 0) { setpgrp(); + + /* Reset state inherited from the harness */ + ksft_reset_state(); + t->fn(t, variant); + + if (__test_passed(t) && (ksft_get_fail_cnt() || ksft_get_error_cnt())) { + ksft_print_msg("Illegal usage of low-level ksft APIs in harness test\n"); + t->exit_code = KSFT_FAIL; + } _exit(t->exit_code); } else { t->pid = child; diff --git a/tools/testing/selftests/kselftest_harness/harness-selftest.c b/tools/testing/selftests/kselftest_harness/harness-selftest.c index 7820bb5d0e6d..3e3033d2745a 100644 --- a/tools/testing/selftests/kselftest_harness/harness-selftest.c +++ b/tools/testing/selftests/kselftest_harness/harness-selftest.c @@ -118,6 +118,46 @@ TEST_F(fixture_setup_failure, pass) { TH_LOG("after"); } +TEST(exit_pass) { + exit(KSFT_PASS); +} + +TEST(exit_xpass) { + exit(KSFT_XPASS); +} + +TEST(exit_fail) { + exit(KSFT_FAIL); +} + +TEST(exit_xfail) { + exit(KSFT_XFAIL); +} + +TEST(exit_skip) { + exit(KSFT_SKIP); +} + +TEST(test_result_pass) { + ksft_test_result_pass(""); +} + +TEST(test_result_xpass) { + ksft_test_result_xpass(""); +} + +TEST(test_result_fail) { + ksft_test_result_fail(""); +} + +TEST(test_result_xfail) { + ksft_test_result_xfail(""); +} + +TEST(test_result_skip) { + ksft_test_result_skip(""); +} + int main(int argc, char **argv) { /* diff --git a/tools/testing/selftests/kselftest_harness/harness-selftest.expected b/tools/testing/selftests/kselftest_harness/harness-selftest.expected index 97e1418c1c7e..c0a68ec124f8 100644 --- a/tools/testing/selftests/kselftest_harness/harness-selftest.expected +++ b/tools/testing/selftests/kselftest_harness/harness-selftest.expected @@ -1,6 +1,6 @@ TAP version 13 -1..9 -# Starting 9 tests from 4 test cases. +1..19 +# Starting 19 tests from 4 test cases. # RUN global.standalone_pass ... # harness-selftest.c:19:standalone_pass:before # harness-selftest.c:23:standalone_pass:after @@ -24,6 +24,39 @@ ok 3 global.signal_pass # signal_fail: Test terminated by assertion # FAIL global.signal_fail not ok 4 global.signal_fail +# RUN global.exit_pass ... +# OK global.exit_pass +ok 5 global.exit_pass +# RUN global.exit_xpass ... +# OK global.exit_xpass +ok 6 global.exit_xpass # XPASS unknown +# RUN global.exit_fail ... +# exit_fail: Test failed +# FAIL global.exit_fail +not ok 7 global.exit_fail +# RUN global.exit_xfail ... +# OK global.exit_xfail +ok 8 global.exit_xfail # XFAIL unknown +# RUN global.exit_skip ... +# OK global.exit_skip +ok 9 global.exit_skip # SKIP unknown +# RUN global.test_result_pass ... +# OK global.test_result_pass +ok 10 global.test_result_pass +# RUN global.test_result_xpass ... +# OK global.test_result_xpass +ok 11 global.test_result_xpass +# RUN global.test_result_fail ... +not ok 1 # Illegal usage of low-level ksft APIs in harness test +# test_result_fail: Test failed +# FAIL global.test_result_fail +not ok 12 global.test_result_fail +# RUN global.test_result_xfail ... +# OK global.test_result_xfail +ok 13 global.test_result_xfail +# RUN global.test_result_skip ... +# OK global.test_result_skip +ok 14 global.test_result_skip # RUN fixture.pass ... # harness-selftest.c:53:pass:setup # harness-selftest.c:62:pass:before @@ -32,7 +65,7 @@ not ok 4 global.signal_fail # harness-selftest.c:66:pass:after # harness-selftest.c:58:pass:teardown same-process=1 # OK fixture.pass -ok 5 fixture.pass +ok 15 fixture.pass # RUN fixture.fail ... # harness-selftest.c:53:fail:setup # harness-selftest.c:70:fail:before @@ -40,25 +73,26 @@ ok 5 fixture.pass # harness-selftest.c:58:fail:teardown same-process=1 # fail: Test terminated by assertion # FAIL fixture.fail -not ok 6 fixture.fail +not ok 16 fixture.fail # RUN fixture.timeout ... # harness-selftest.c:53:timeout:setup # harness-selftest.c:77:timeout:before # timeout: Test terminated by timeout # FAIL fixture.timeout -not ok 7 fixture.timeout +not ok 17 fixture.timeout # RUN fixture_parent.pass ... # harness-selftest.c:87:pass:setup # harness-selftest.c:96:pass:before # harness-selftest.c:98:pass:after # harness-selftest.c:92:pass:teardown same-process=0 # OK fixture_parent.pass -ok 8 fixture_parent.pass +ok 18 fixture_parent.pass # RUN fixture_setup_failure.pass ... # harness-selftest.c:106:pass:setup # harness-selftest.c:108:pass:Expected 0 (0) == 1 (1) # pass: Test terminated by assertion # FAIL fixture_setup_failure.pass -not ok 9 fixture_setup_failure.pass -# FAILED: 4 / 9 tests passed. -# Totals: pass:4 fail:5 xfail:0 xpass:0 skip:0 error:0 +not ok 19 fixture_setup_failure.pass +# FAILED: 12 / 19 tests passed. +# 1 skipped test(s) detected. Consider enabling relevant config options to improve coverage. +# Totals: pass:9 fail:7 xfail:1 xpass:1 skip:1 error:0 diff --git a/tools/testing/selftests/mqueue/setting b/tools/testing/selftests/mqueue/settings index a953c96aa16e..a953c96aa16e 100644 --- a/tools/testing/selftests/mqueue/setting +++ b/tools/testing/selftests/mqueue/settings diff --git a/tools/testing/selftests/run_kselftest.sh b/tools/testing/selftests/run_kselftest.sh index 84d45254675c..e11b0e93ba41 100755 --- a/tools/testing/selftests/run_kselftest.sh +++ b/tools/testing/selftests/run_kselftest.sh @@ -4,12 +4,7 @@ # Run installed kselftest tests. # -# Fallback to readlink if realpath is not available -if which realpath > /dev/null; then - BASE_DIR=$(realpath $(dirname $0)) -else - BASE_DIR=$(readlink -f $(dirname $0)) -fi +BASE_DIR=$(cd "$(dirname "$0")" && pwd -P) cd $BASE_DIR TESTS="$BASE_DIR"/kselftest-list.txt @@ -21,14 +16,13 @@ else fi . ./kselftest/runner.sh -ROOT=$PWD usage() { cat <<EOF Usage: $0 [OPTIONS] -s | --summary Print summary with detailed log in output.log (conflict with -p) - -p | --per-test-log Print test log in /tmp with each test name (conflict with -s) + -p | --per-test-log [DIR] Print test log in /tmp or DIR with each test name (conflict with -s) -t | --test COLLECTION:TEST Run TEST from COLLECTION -S | --skip COLLECTION:TEST Skip TEST from COLLECTION -c | --collection COLLECTION Run all tests from COLLECTION @@ -56,7 +50,33 @@ while true; do shift ;; -p | --per-test-log) per_test_logging=1 - shift ;; + if [ -n "$2" ] && [ "${2#-}" = "$2" ]; then + per_test_log_dir="$2" + if [ -e "$per_test_log_dir" ] && [ ! -d "$per_test_log_dir" ]; then + echo "Per-test log path is not a dir:" \ + "$per_test_log_dir" >&2 + exit 1 + fi + if [ ! -d "$per_test_log_dir" ] && \ + ! mkdir -p "$per_test_log_dir"; then + echo "Could not create log dir:" \ + "$per_test_log_dir" >&2 + exit 1 + fi + per_test_log_dir=$(cd "$per_test_log_dir" && pwd -P) + if [ -z "$per_test_log_dir" ]; then + echo "Could not resolve per-test log directory" >&2 + exit 1 + fi + if [ ! -w "$per_test_log_dir" ]; then + echo "Per-test log dir is not writable:" \ + "$per_test_log_dir" >&2 + exit 1 + fi + shift 2 + else + shift + fi ;; -t | --test) TESTS="$TESTS $2" shift 2 ;; @@ -121,18 +141,23 @@ if [ -n "$SKIP" ]; then done fi -kselftest_failures_file="$(mktemp --tmpdir kselftest-failures-XXXXXX)" -export kselftest_failures_file - +curdir=$(pwd) +total=$(echo "$available" | wc -w) collections=$(echo "$available" | cut -d: -f1 | sort | uniq) + +ktap_print_header +ktap_set_plan "$total" + for collection in $collections ; do [ -w /dev/kmsg ] && echo "kselftest: Running tests in $collection" >> /dev/kmsg tests=$(echo "$available" | grep "^$collection:" | cut -d: -f2) - ($dryrun cd "$collection" && $dryrun run_many $tests) + $dryrun cd "$collection" && $dryrun run_many $tests + $dryrun cd "$curdir" done -failures="$(cat "$kselftest_failures_file")" -rm "$kselftest_failures_file" -if "$ERROR_ON_FAIL" && [ "$failures" ]; then - exit 1 +ktap_print_totals +if "$ERROR_ON_FAIL" && [ "$KTAP_CNT_FAIL" -ne 0 ]; then + exit "$KSFT_FAIL" +else + exit "$KSFT_PASS" fi |
