From 959bf3461909c09bdaaaf854f24a7fdc0bfee16c Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 3 Sep 2022 06:55:09 -0500 Subject: [PATCH] Test suite update. Reorder functions to group helpers and API, eliminate SKIPNEXT and make SKIP a count (with optional setting it to 99999), fix txpect to actually listen to exit codes (wait needs PID else rc always 0), allow multiple X from txpect (since shxpect adds an X0 at end which could be duplicate), simplify some stuff, adjust tests for new SKIP + txpect X semantics --- scripts/runtest.sh | 123 ++++++++++++++++++++++----------------------- scripts/test.sh | 4 +- tests/chmod.test | 4 +- tests/sh.test | 6 +-- 4 files changed, 66 insertions(+), 71 deletions(-) diff --git a/scripts/runtest.sh b/scripts/runtest.sh index 9390bd59..467f8b82 100644 --- a/scripts/runtest.sh +++ b/scripts/runtest.sh @@ -2,9 +2,7 @@ # # Copyright 2005 by Rob Landley -# This file defines two main functions, "testcmd" and "optional". The -# first performs a test, the second enables/disables tests based on -# configuration options. +# This file defines three main functions: "testing", "testcmd", and "txpect". # The following environment variables enable optional behavior in "testing": # DEBUG - Show every command run by test script. @@ -30,26 +28,13 @@ # The environment variable "FAILCOUNT" contains a cumulative total of the # number of failed tests. # -# The "optional" function is used to skip certain tests (by setting the -# environment variable SKIP), ala: -# optional CFG_THINGY +# The environment variable "SKIP" says how many upcoming tests to skip, +# defaulting to 0 and counting down when set to a higher number. # -# The "optional" function checks the environment variable "OPTIONFLAGS", -# which is either empty (in which case it always clears SKIP) or -# else contains a colon-separated list of features (in which case the function -# clears SKIP if the flag was found, or sets it to 1 if the flag was not found). - -export FAILCOUNT=0 -export SKIP= - -# Helper functions - -# Check config to see if option is enabled, set SKIP if not. - -SHOWPASS=PASS -SHOWFAIL=FAIL -SHOWSKIP=SKIP +# Function "optional" enables/disables tests based on configuration options. +export FAILCOUNT=0 SKIP=0 +: ${SHOWPASS:=PASS} ${SHOWFAIL:=FAIL} ${SHOWSKIP:=SKIP} if tty -s <&1 then SHOWPASS="$(echo -e "\033[1;32m${SHOWPASS}\033[0m")" @@ -57,48 +42,14 @@ then SHOWSKIP="$(echo -e "\033[1;33m${SHOWSKIP}\033[0m")" fi -optional() -{ - option=`printf %s "$OPTIONFLAGS" | egrep "(^|:)$1(:|\$)"` - # Not set? - if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ] - then - unset SKIP - return - fi - SKIP=1 -} +# Helper functions +# Check if VERBOSE= contains a given string. (This allows combining.) verbose_has() { [ "${VERBOSE/$1/}" != "$VERBOSE" ] } -skipnot() -{ - if verbose_has quiet - then - eval "$@" 2>/dev/null - else - eval "$@" - fi - [ $? -eq 0 ] || SKIPNEXT=1 -} - -toyonly() -{ - IS_TOYBOX="$("$C" --version 2>/dev/null)" - # Ideally we'd just check for "toybox", but toybox sed lies to make autoconf - # happy, so we have at least two things to check for. - case "$IS_TOYBOX" in - toybox*) ;; - This\ is\ not\ GNU*) ;; - *) SKIPNEXT=1 ;; - esac - - "$@" -} - wrong_args() { if [ $# -ne 5 ] @@ -127,8 +78,43 @@ do_fail() ! verbose_has all && exit 1 } -# The testing function +# Functions test files call directly + +# Set SKIP high if option not enabled in $OPTIONFLAGS (unless OPTIONFLAGS blank) +optional() +{ + [ -n "$OPTIONFLAGS" ] && [ "$OPTIONFLAGS" == "${OPTIONFLAGS/:$1:/}" ] && + SKIP=99999 || SKIP=0 +} + +# Evalute command line and skip next test when false +skipnot() +{ + if verbose_has quiet + then + eval "$@" 2>/dev/null + else + eval "$@" + fi + [ $? -eq 0 ] || ((++SKIP)) +} + +# Skip this test (rest of command line) when not running toybox. +toyonly() +{ + IS_TOYBOX="$("$C" --version 2>/dev/null)" + # Ideally we'd just check for "toybox", but toybox sed lies to make autoconf + # happy, so we have at least two things to check for. + case "$IS_TOYBOX" in + toybox*) ;; + This\ is\ not\ GNU*) ;; + *) ((++SKIP)) ;; + esac + + "$@" +} +# Takes five arguments: "name" "command" "result" "infile" "stdin" testing() { NAME="$CMDNAME $1" @@ -138,10 +124,11 @@ testing() [ -n "$DEBUG" ] && set -x - if [ -n "$SKIP" -o -n "$SKIP_HOST" -a -n "$TEST_HOST" -o -n "$SKIPNEXT" ] + if [ "$SKIP" -gt 0 ] then verbose_has quiet && printf "%s\n" "$SHOWSKIP: $NAME" - unset SKIPNEXT + ((--SKIP)) + return 0 fi @@ -170,6 +157,7 @@ testing() return 0 } +# Wrapper for "testing", adds command name being tested to start of command line testcmd() { wrong_args "$@" @@ -179,13 +167,15 @@ testcmd() testing "$X" "\"$C\" $2" "$3" "$4" "$5" } +# Simple implementation of "expect" written in shell. + # txpect NAME COMMAND [I/O/E/Xstring]... # Run COMMAND and interact with it: send I strings to input, read O or E # strings from stdout or stderr (empty string is "read line of input here"), # X means close stdin/stdout/stderr and match return code (blank means nonzero) txpect() { - local NAME CASE VERBOSITY LEN A B X O + local NAME CASE VERBOSITY LEN PID A B X O # Run command with redirection through fifos NAME="$CMDNAME $1" @@ -198,13 +188,14 @@ txpect() return fi eval "$2" out-$$ 2>err-$$ & + PID=$! shift 2 : {IN}>in-$$ {OUT}&2 + do_fail fi } diff --git a/scripts/test.sh b/scripts/test.sh index 7e80ccbf..66ea56e1 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -27,7 +27,7 @@ TESTDIR="$PWD" export LC_COLLATE=C [ -f "$TOPDIR/generated/config.h" ] && - export OPTIONFLAGS=:$(echo $($SED -nr 's/^#define CFG_(.*) 1/\1/p' "$TOPDIR/generated/config.h") | $SED 's/ /:/g') + export OPTIONFLAGS=:$($SED -nr 's/^#define CFG_(.*) 1$/\1/p' "$TOPDIR/generated/config.h" | tr '\n' :) do_test() { @@ -38,7 +38,7 @@ do_test() if [ -z "$TEST_HOST" ] then C="$TESTDIR/$CMDNAME" - [ ! -e "$C" ] && echo "$CMDNAME disabled" && return + [ ! -e "$C" ] && echo "$SHOWSKIP: $CMDNAME disabled" && return C="$(dirname $(realpath "$C"))/$CMDNAME" else C="$(which $CMDNAME 2>/dev/null)" diff --git a/tests/chmod.test b/tests/chmod.test index 6c4de0c0..99c4dd16 100755 --- a/tests/chmod.test +++ b/tests/chmod.test @@ -104,13 +104,13 @@ chtest a-w,a+x "dr-xr-xr-x\n-r-xr-xr-x\n" # macOS doesn't allow +s in /tmp touch s-supported -chmod +s s-supported 2>/dev/null || SKIP=1 +skipnot chmod +s s-supported 2>/dev/null rm s-supported chtest g+s "drwxr-sr-x\n-rw-r-Sr--\n" chtest u+s "drwsr-xr-x\n-rwSr--r--\n" chtest +s "drwsr-sr-x\n-rwSr-Sr--\n" chtest o+s "drwxr-xr-x\n-rw-r--r--\n" -unset SKIP +SKIP=0 chtest +t "drwxr-xr-t\n-rw-r--r-T\n" chtest a=r+w+x "drwxrwxrwx\n-rwxrwxrwx\n" diff --git a/tests/sh.test b/tests/sh.test index dae0bf88..7dd7b00e 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -57,7 +57,7 @@ shxpect() { shxpect "prompt and exit" I$'exit\n' shxpect "prompt and echo" I$'echo hello\n' O$'hello\n' E"$P" -shxpect "redirect err" I$'echo > /dev/full\n' E E"$P" +shxpect "redirect err" I$'echo > /dev/full\n' E E"$P" X1 shxpect "wait for <(exit)" I$'cat <(echo hello 1>&2)\n' E$'hello\n' E"$P" # Test the sh -c stuff before changing EVAL @@ -100,7 +100,7 @@ testing 'prefix is local for builtins' 'abc=123; abc=def unset abc; echo $abc' \ '123\n' '' '' testing 'prefix localizes magic vars' \ 'SECONDS=123; SECONDS=345 true; echo $SECONDS' '123\n' '' '' -shxpect 'body evaluated before variable exports' I$'a=x${} y${}\n' RE'y${}' +shxpect 'body evaluated before variable exports' I$'a=x${} y${}\n' RE'y${}' X1 testing '$NOTHING clears $_' 'true; $NOTHING; echo $_' '\n' '' '' testing 'assignment with redirect is persistent, not prefix' \ 'ABC=DEF > potato && rm potato && echo $ABC' 'DEF\n' '' '' @@ -597,7 +597,7 @@ testing '"exit shell" means exit eval but encapsulating function continues' \ 'func() { eval "echo one; echo \${?potato}; echo and" 2>/dev/null; echo plus;}; func; echo then' \ 'one\nplus\nthen\n' '' '' -shxpect "functions need block" I$'x() echo;\n' RE'[Ss]yntax [Ee]rror' +shxpect "functions need block" I$'x() echo;\n' RE'[Ss]yntax [Ee]rror' X2 testing 'functions() {} in same PID' \ '{ echo $BASHPID; chicken() { echo $BASHPID;}; chicken;} | sort -u | wc -l' '1\n' '' '' testing 'functions() () different PID' \ -- 2.39.2