This script is used to compare the running kernel version (`ulimit -r`) against a list of versions, to find out whether a test should be skipped or not. If kernel has a bug, a test might not pass. In that case, the test should exit with error code 77 as we also want to pass the test suite on distro kernels. However, if we know that the bug was fixed in a certain kernel version, then we the failure to be fatal and noticeable. Example usage: if ! _check_some_condition ; then echo "The condition to check for kernel bug https://git.kernel.org/XYZ failed" "$NFT_TEST_BASEDIR/helpers/eval-exit-code" kernel 6.5.6 6.6 exit $? fi Note that "eval-exit-code" will always exit with a non-zero exit code. It will also print a message about the comparison, which ends up in the test output. Signed-off-by: Thomas Haller <thaller@xxxxxxxxxx> --- tests/shell/helpers/eval-exit-code | 116 +++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100755 tests/shell/helpers/eval-exit-code diff --git a/tests/shell/helpers/eval-exit-code b/tests/shell/helpers/eval-exit-code new file mode 100755 index 000000000000..d007c0fc0fd6 --- /dev/null +++ b/tests/shell/helpers/eval-exit-code @@ -0,0 +1,116 @@ +#!/bin/bash -e + +die() { + printf "%s\n" "$*" + exit 2 +} + +usage() { + echo "usage: $0 [MODE] [ARGS...]" + echo "" + echo "Evaluates whether to exit a test with skip or failure reason." + echo "" + echo "The use case is for example a kernel bug, which prevents a test from passing. We" + echo "know that certain newer kernel versions have the fix, and we require the test to" + echo "pass there. When an assertion fails, The script will determine that the test should" + echo "have passed and exit with code \"1\". When running against an older kernel, the failure" + echo "is expected and the script exits with \"77\" to indicate a skip." + echo "" + echo "The script always either exits with:" + echo " 1: the check determined that we have a hard failure (a message is printed)" + echo " 77: the check determined that we skip (a message is printed)" + echo " 2: an error in the script happend (invalid arguments?)" + echo "" + echo "MODE can be one of:" + echo " \"kernel\": compares \`ulimit -r\` against the arguments. The arguments are" + echo " kernel versions for which we expect to support the feature and when called" + echo " on such a kernel, the script returns \"1\" to indicate a hard failure. Against" + echo " older kernels, \"77\" is returned. Multiple kernel version can be provided for" + echo " example \`$0 kernel 6.5.6 6.6\`." + echo "" + echo "USAGE:" + echo " if ! _check_some_condition ; then" + echo " echo \"The condition to check for kernel bug https://git.kernel.org/XYZ failed\"" + echo " \"\$NFT_TEST_BASEDIR/helpers/eval-exit-code\" kernel 6.5.6 6.6" + echo " exit \$?" + echo " fi" + exit 2 +} + +[ "$#" -eq 0 ] && usage + +_kernel_check_skip() { + local kversion="$1" + local compare="$2" + + if [ "$kversion" = "$compare" ] ; then + return 1 + fi + if [[ "$kversion" == "$compare"[.-]* ]] ; then + return 1 + fi + + local a1="$(printf '%s\n' 0 "$kversion" "$compare" 100000)" + local a2="$(printf '%s' "$a1" | sort -V)" + + if [ "$a1" != "$a2" ] ; then + return 1 + fi + return 0 +} + +_PRINT_ARG="???" + +eval_kernel() { + local compare + local kversion + + if [ -n "$_EVAL_EXIT_CODE_UNAME" ] ; then + # Only for testing. + kversion="$_EVAL_EXIT_CODE_UNAME" + else + kversion="$(uname -r)" || die "uname -r failed" + fi + + [ $# -ge 1 ] || die "Operation kernel expects one or more kernel versions to be compared with >= against $kversion" + + _PRINT_ARG="$kversion" + + local all_skip=1 + for compare; do + _kernel_check_skip "$kversion" "$compare" || all_skip=0 + done + if [ "$all_skip" -eq 1 ] ; then + return 77 + fi + return 1 +} + +run_op() { + local mode="$1" + shift + + rc=2 + "eval_$mode" "$@" || rc=$? + if [ "$rc" -eq 77 ] ; then + echo "Checking \"$mode\" ($@) against $_PRINT_ARG indicates to skip the test" + else + echo "Checking \"$mode\" ($@) against $_PRINT_ARG indicates a hard failure" + fi + exit "$rc" +} + +mode="$1" +shift + +case "$mode" in + kernel) + run_op "$mode" "$@" + ;; + -h|--help) + usage + ;; + *) + die "Invalid mode \"$mode\". Try $0 --help" + ;; +esac -- 2.41.0