162306a36Sopenharmony_ci#!/bin/sh
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci# Runs a set of tests in a given subdirectory.
562306a36Sopenharmony_ciexport skip_rc=4
662306a36Sopenharmony_ciexport timeout_rc=124
762306a36Sopenharmony_ciexport logfile=/dev/stdout
862306a36Sopenharmony_ciexport per_test_logging=
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci# Defaults for "settings" file fields:
1162306a36Sopenharmony_ci# "timeout" how many seconds to let each test run before running
1262306a36Sopenharmony_ci# over our soft timeout limit.
1362306a36Sopenharmony_ciexport kselftest_default_timeout=45
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci# There isn't a shell-agnostic way to find the path of a sourced file,
1662306a36Sopenharmony_ci# so we must rely on BASE_DIR being set to find other tools.
1762306a36Sopenharmony_ciif [ -z "$BASE_DIR" ]; then
1862306a36Sopenharmony_ci	echo "Error: BASE_DIR must be set before sourcing." >&2
1962306a36Sopenharmony_ci	exit 1
2062306a36Sopenharmony_cifi
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciTR_CMD=$(command -v tr)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci# If Perl is unavailable, we must fall back to line-at-a-time prefixing
2562306a36Sopenharmony_ci# with sed instead of unbuffered output.
2662306a36Sopenharmony_citap_prefix()
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	if [ ! -x /usr/bin/perl ]; then
2962306a36Sopenharmony_ci		sed -e 's/^/# /'
3062306a36Sopenharmony_ci	else
3162306a36Sopenharmony_ci		"$BASE_DIR"/kselftest/prefix.pl
3262306a36Sopenharmony_ci	fi
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_citap_timeout()
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	# Make sure tests will time out if utility is available.
3862306a36Sopenharmony_ci	if [ -x /usr/bin/timeout ] ; then
3962306a36Sopenharmony_ci		/usr/bin/timeout --foreground "$kselftest_timeout" \
4062306a36Sopenharmony_ci			/usr/bin/timeout "$kselftest_timeout" $1
4162306a36Sopenharmony_ci	else
4262306a36Sopenharmony_ci		$1
4362306a36Sopenharmony_ci	fi
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cirun_one()
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	DIR="$1"
4962306a36Sopenharmony_ci	TEST="$2"
5062306a36Sopenharmony_ci	NUM="$3"
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	BASENAME_TEST=$(basename $TEST)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	# Reset any "settings"-file variables.
5562306a36Sopenharmony_ci	export kselftest_timeout="$kselftest_default_timeout"
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	# Safe default if tr not available
5862306a36Sopenharmony_ci	kselftest_cmd_args_ref="KSELFTEST_ARGS"
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	# Optional arguments for this command, possibly defined as an
6162306a36Sopenharmony_ci	# environment variable built using the test executable in all
6262306a36Sopenharmony_ci	# uppercase and sanitized substituting non acceptable shell
6362306a36Sopenharmony_ci	# variable name characters with "_" as in:
6462306a36Sopenharmony_ci	#
6562306a36Sopenharmony_ci	# 	KSELFTEST_<UPPERCASE_SANITIZED_TESTNAME>_ARGS="<options>"
6662306a36Sopenharmony_ci	#
6762306a36Sopenharmony_ci	# e.g.
6862306a36Sopenharmony_ci	#
6962306a36Sopenharmony_ci	# 	rtctest --> KSELFTEST_RTCTEST_ARGS="/dev/rtc1"
7062306a36Sopenharmony_ci	#
7162306a36Sopenharmony_ci	# 	cpu-on-off-test.sh --> KSELFTEST_CPU_ON_OFF_TEST_SH_ARGS="-a -p 10"
7262306a36Sopenharmony_ci	#
7362306a36Sopenharmony_ci	if [ -n "$TR_CMD" ]; then
7462306a36Sopenharmony_ci		BASENAME_SANITIZED=$(echo "$BASENAME_TEST" | \
7562306a36Sopenharmony_ci					$TR_CMD -d "[:blank:][:cntrl:]" | \
7662306a36Sopenharmony_ci					$TR_CMD -c "[:alnum:]_" "_" | \
7762306a36Sopenharmony_ci					$TR_CMD [:lower:] [:upper:])
7862306a36Sopenharmony_ci		kselftest_cmd_args_ref="KSELFTEST_${BASENAME_SANITIZED}_ARGS"
7962306a36Sopenharmony_ci	fi
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	# Load per-test-directory kselftest "settings" file.
8262306a36Sopenharmony_ci	settings="$BASE_DIR/$DIR/settings"
8362306a36Sopenharmony_ci	if [ -r "$settings" ] ; then
8462306a36Sopenharmony_ci		while read line ; do
8562306a36Sopenharmony_ci			# Skip comments.
8662306a36Sopenharmony_ci			if echo "$line" | grep -q '^#'; then
8762306a36Sopenharmony_ci				continue
8862306a36Sopenharmony_ci			fi
8962306a36Sopenharmony_ci			field=$(echo "$line" | cut -d= -f1)
9062306a36Sopenharmony_ci			value=$(echo "$line" | cut -d= -f2-)
9162306a36Sopenharmony_ci			eval "kselftest_$field"="$value"
9262306a36Sopenharmony_ci		done < "$settings"
9362306a36Sopenharmony_ci	fi
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	# Command line timeout overrides the settings file
9662306a36Sopenharmony_ci	if [ -n "$kselftest_override_timeout" ]; then
9762306a36Sopenharmony_ci		kselftest_timeout="$kselftest_override_timeout"
9862306a36Sopenharmony_ci		echo "# overriding timeout to $kselftest_timeout" >> "$logfile"
9962306a36Sopenharmony_ci	else
10062306a36Sopenharmony_ci		echo "# timeout set to $kselftest_timeout" >> "$logfile"
10162306a36Sopenharmony_ci	fi
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST"
10462306a36Sopenharmony_ci	echo "# $TEST_HDR_MSG"
10562306a36Sopenharmony_ci	if [ ! -e "$TEST" ]; then
10662306a36Sopenharmony_ci		echo "# Warning: file $TEST is missing!"
10762306a36Sopenharmony_ci		echo "not ok $test_num $TEST_HDR_MSG"
10862306a36Sopenharmony_ci	else
10962306a36Sopenharmony_ci		if [ -x /usr/bin/stdbuf ]; then
11062306a36Sopenharmony_ci			stdbuf="/usr/bin/stdbuf --output=L "
11162306a36Sopenharmony_ci		fi
11262306a36Sopenharmony_ci		eval kselftest_cmd_args="\$${kselftest_cmd_args_ref:-}"
11362306a36Sopenharmony_ci		cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args"
11462306a36Sopenharmony_ci		if [ ! -x "$TEST" ]; then
11562306a36Sopenharmony_ci			echo "# Warning: file $TEST is not executable"
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci			if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ]
11862306a36Sopenharmony_ci			then
11962306a36Sopenharmony_ci				interpreter=$(head -n 1 "$TEST" | cut -c 3-)
12062306a36Sopenharmony_ci				cmd="$stdbuf $interpreter ./$BASENAME_TEST"
12162306a36Sopenharmony_ci			else
12262306a36Sopenharmony_ci				echo "not ok $test_num $TEST_HDR_MSG"
12362306a36Sopenharmony_ci				return
12462306a36Sopenharmony_ci			fi
12562306a36Sopenharmony_ci		fi
12662306a36Sopenharmony_ci		cd `dirname $TEST` > /dev/null
12762306a36Sopenharmony_ci		((((( tap_timeout "$cmd" 2>&1; echo $? >&3) |
12862306a36Sopenharmony_ci			tap_prefix >&4) 3>&1) |
12962306a36Sopenharmony_ci			(read xs; exit $xs)) 4>>"$logfile" &&
13062306a36Sopenharmony_ci		echo "ok $test_num $TEST_HDR_MSG") ||
13162306a36Sopenharmony_ci		(rc=$?;	\
13262306a36Sopenharmony_ci		if [ $rc -eq $skip_rc ]; then	\
13362306a36Sopenharmony_ci			echo "ok $test_num $TEST_HDR_MSG # SKIP"
13462306a36Sopenharmony_ci		elif [ $rc -eq $timeout_rc ]; then \
13562306a36Sopenharmony_ci			echo "#"
13662306a36Sopenharmony_ci			echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT $kselftest_timeout seconds"
13762306a36Sopenharmony_ci		else
13862306a36Sopenharmony_ci			echo "not ok $test_num $TEST_HDR_MSG # exit=$rc"
13962306a36Sopenharmony_ci		fi)
14062306a36Sopenharmony_ci		cd - >/dev/null
14162306a36Sopenharmony_ci	fi
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cirun_many()
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	echo "TAP version 13"
14762306a36Sopenharmony_ci	DIR="${PWD#${BASE_DIR}/}"
14862306a36Sopenharmony_ci	test_num=0
14962306a36Sopenharmony_ci	total=$(echo "$@" | wc -w)
15062306a36Sopenharmony_ci	echo "1..$total"
15162306a36Sopenharmony_ci	for TEST in "$@"; do
15262306a36Sopenharmony_ci		BASENAME_TEST=$(basename $TEST)
15362306a36Sopenharmony_ci		test_num=$(( test_num + 1 ))
15462306a36Sopenharmony_ci		if [ -n "$per_test_logging" ]; then
15562306a36Sopenharmony_ci			logfile="/tmp/$BASENAME_TEST"
15662306a36Sopenharmony_ci			cat /dev/null > "$logfile"
15762306a36Sopenharmony_ci		fi
15862306a36Sopenharmony_ci		run_one "$DIR" "$TEST" "$test_num"
15962306a36Sopenharmony_ci	done
16062306a36Sopenharmony_ci}
161