]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
tests/shell: export NFT_TEST_RANDOM_SEED variable for tests
authorThomas Haller <thaller@redhat.com>
Wed, 13 Sep 2023 08:20:23 +0000 (10:20 +0200)
committerFlorian Westphal <fw@strlen.de>
Fri, 15 Sep 2023 13:52:06 +0000 (15:52 +0200)
Let "run-tests.sh" export a NFT_TEST_RANDOM_SEED variable, set to
a decimal, random integer (in the range of 0 to 0x7FFFFFFF).

The purpose is to provide a seed to tests for randomization.
Randomizing tests is very useful to increase the coverage while not
testing all combinations (which might not be practical).

The point of NFT_TEST_RANDOM_SEED is that the user can set the
environment variable so that the same series of random events is used.
That is useful for reproducing an issue, that is known to happen with a
certain seed.

- by default, if the user leaves NFT_TEST_RANDOM_SEED unset or empty,
  the script generates a number using $SRANDOM.
- if the user sets NFT_TEST_RANDOM_SEED to an integer it is taken
  as is (modulo 0x80000000).
- otherwise, calculate a number by hashing the value of
  $NFT_TEST_RANDOM_SEED.

Signed-off-by: Thomas Haller <thaller@redhat.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
tests/shell/run-tests.sh

index 7ac6202ca43c884e8022e15f4c18338fb09470e1..c77284acd555d4d5f01d6f4304a31b1826203e57 100755 (executable)
@@ -21,6 +21,31 @@ array_contains() {
        return 1
 }
 
+strtonum() {
+       local s="$1"
+       local n
+       local n2
+
+       re='^[[:space:]]*([0-9]+)[[:space:]]*$'
+       if [[ "$s" =~ $re ]] ; then
+               n="${BASH_REMATCH[1]}"
+               if [ "$(( n + 0 ))" = "$n" ] ; then
+                       echo "$n"
+                       return 0
+               fi
+       fi
+       re='^[[:space:]]*0x([0-9a-fA-F]+)[[:space:]]*$'
+       if [[ "$s" =~ $re ]] ; then
+               n="${BASH_REMATCH[1]}"
+               n2="$(( 16#$n + 0 ))"
+               if [ "$n2" = "$(printf '%d' "0x$n" 2>/dev/null)" ] ; then
+                       echo "$n2"
+                       return 0
+               fi
+       fi
+       return 1
+}
+
 _msg() {
        local level="$1"
        shift
@@ -170,6 +195,9 @@ usage() {
        echo "                 Setting this to \"0\" means also to perform global cleanups between tests (remove"
        echo "                 kernel modules)."
        echo "                 Parallel jobs requires unshare and are disabled with NFT_TEST_UNSHARE_CMD=\"\"."
+       echo " NFT_TEST_RANDOM_SEED=<SEED>: The test runner will export the environment variable NFT_TEST_RANDOM_SEED"
+       echo "                 set to a random number. This can be used as a stable seed for tests to randomize behavior."
+       echo "                 Set this to a fixed value to get reproducible behavior."
        echo " TMPDIR=<PATH> : select a different base directory for the result data."
        echo
        echo " NFT_TEST_HAVE_<FEATURE>=*|y: Some tests requires certain features or will be skipped."
@@ -209,9 +237,26 @@ KMEMLEAK="$(bool_y "$KMEMLEAK")"
 NFT_TEST_KEEP_LOGS="$(bool_y "$NFT_TEST_KEEP_LOGS")"
 NFT_TEST_HAS_REALROOT="$NFT_TEST_HAS_REALROOT"
 NFT_TEST_JOBS="${NFT_TEST_JOBS:-$_NFT_TEST_JOBS_DEFAULT}"
+NFT_TEST_RANDOM_SEED="$NFT_TEST_RANDOM_SEED"
 NFT_TEST_SKIP_slow="$(bool_y "$NFT_TEST_SKIP_slow")"
 DO_LIST_TESTS=
 
+if [ -z "$NFT_TEST_RANDOM_SEED" ] ; then
+       # Choose a random value.
+       n="$SRANDOM"
+else
+       # Parse as number.
+       n="$(strtonum "$NFT_TEST_RANDOM_SEED")"
+       if [ -z "$n" ] ; then
+               # If not a number, pick a hash based on the SHA-sum of the seed.
+               n="$(printf "%d" "0x$(sha256sum <<<"NFT_TEST_RANDOM_SEED:$NFT_TEST_RANDOM_SEED" | sed -n '1 { s/^\(........\).*/\1/p }')")"
+       fi
+fi
+# Limit a 31 bit decimal so tests can rely on this being in a certain
+# restricted form.
+NFT_TEST_RANDOM_SEED="$(( $n % 0x80000000 ))"
+export NFT_TEST_RANDOM_SEED
+
 TESTS=()
 
 while [ $# -gt 0 ] ; do
@@ -473,6 +518,7 @@ msg_info "conf: NFT_TEST_HAS_UNSHARED=$(printf '%q' "$NFT_TEST_HAS_UNSHARED")"
 msg_info "conf: NFT_TEST_HAS_UNSHARED_MOUNT=$(printf '%q' "$NFT_TEST_HAS_UNSHARED_MOUNT")"
 msg_info "conf: NFT_TEST_KEEP_LOGS=$(printf '%q' "$NFT_TEST_KEEP_LOGS")"
 msg_info "conf: NFT_TEST_JOBS=$NFT_TEST_JOBS"
+msg_info "conf: NFT_TEST_RANDOM_SEED=$NFT_TEST_RANDOM_SEED"
 msg_info "conf: TMPDIR=$(printf '%q' "$_TMPDIR")"
 echo
 for KEY in $(compgen -v | grep '^NFT_TEST_SKIP_' | sort) ; do