From 8c7af93bde1798da7d59182201b3599158bf926d Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 16 Mar 2021 02:29:15 -0500 Subject: Add more shell tests, and teach txpect to do regex matches (RO and RE). --- scripts/runtest.sh | 13 +++++++++---- tests/sh.test | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/scripts/runtest.sh b/scripts/runtest.sh index 6aad9ff1..158ed7fa 100644 --- a/scripts/runtest.sh +++ b/scripts/runtest.sh @@ -61,7 +61,7 @@ optional() # Not set? if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ] then - SKIP="" + unset SKIP return fi SKIP=1 @@ -183,6 +183,8 @@ do_fail() # X means close stdin/stdout/stderr and match return code (blank means nonzero) txpect() { + local NAME CASE VERBOSITY LEN A B + # Run command with redirection through fifos NAME="$CMDNAME $1" CASE= @@ -206,16 +208,18 @@ txpect() LEN=$((${#1}-1)) CASE="$1" A= + B= case ${1::1} in # send input to child I) printf %s "${1:1}" >&$IN || { do_fail;break;} ;; + R) LEN=0; B=1; ;& # check output from child [OE]) [ $LEN == 0 ] && LARG="" || LARG="-rN $LEN" O=$OUT - [ ${1::1} == 'E' ] && O=$ERR + [ "${1:$B:1}" == 'E' ] && O=$ERR A= read -t2 $LARG A <&$O VERBOSITY="$VERBOSITY"$'\n'"$A" @@ -223,8 +227,9 @@ txpect() then [ -z "$A" ] && { do_fail;break;} else - if [ "$A" != "${1:1}" ] - then + if [ ${1::1} == 'R' ] && [[ "$A" =~ "${1:2}" ]]; then true + elif [ ${1::1} != 'R' ] && [ "$A" == "${1:1}" ]; then true + else # Append the rest of the output if there is any. read -t.1 B <&$O A="$A$B" diff --git a/tests/sh.test b/tests/sh.test index 0fed3d06..abbb1c6e 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -85,6 +85,21 @@ ln -s $(which $SH) bash testing 'non-absolute $_' "./bash -c 'echo \$_'" './bash\n' '' '' rm bash +shxpect '$_ preserved on assignment error' I$'true hello; a=1 b=2 c=${}\n' \ + E E"$P" I$'echo $_\n' O$'hello\n' +shxpect '$_ preserved on prefix error' I$'true hello; a=1 b=2 c=${} true\n' \ + E E"$P" I$'echo $_\n' O$'hello\n' +shxpect '$_ preserved on exec error' I$'true hello; ${}\n' \ + E E"$P" I$'echo $_\n' O$'hello\n' +shxpect '$_ abspath on exec' I$'env | grep ^_=\n' O$'_=/usr/bin/env\n' +testing '$_ literal after exec' 'env >/dev/null; echo $_' 'env\n' '' '' +shxpect '$_ no path for builtin' I$'true; echo $_\n' O$'true\n' +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${}' + testing 'exec exitval' "$SH -c 'exec echo hello' && echo \$?" "hello\n0\n" "" "" testing 'simple script' '$SH input' 'input\n' 'echo $0' '' testing 'simple script2' '$SH ./input two;echo $?' './input+two\n42\n' \ @@ -515,11 +530,26 @@ testing 'source is live in functions' \ testing 'subshell inheritance' \ 'func() { source input; cat <(echo $xx; xx=456; echo $xx); echo $xx;}; echo local xx=123 > input; func; echo $xx' \ '123\n456\n123\n\n' 'x' '' +testing 'semicolon vs newline' \ + 'source input 2>/dev/null || echo yes' 'one\nyes\n' \ + 'echo one\necho two; echo |' '' +testing 'syntax err pops to source but encapsulating function continues' \ + 'func() { echo one; source <(echo -e "echo hello\necho |") 2>/dev/null; echo three;}; func; echo four' \ + 'one\nhello\nthree\nfour\n' '' '' +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' '' '' testing 'functions() {} in same PID' \ '{ echo $BASHPID; chicken() { echo $BASHPID;}; chicken;} | sort -u | wc -l' '1\n' '' '' testing 'functions() () different PID' \ '{ echo $BASHPID; chicken() ( echo $BASHPID;); chicken;} | sort -u | wc -l' '2\n' '' '' +testing 'function() just wants any block span' \ + 'func() if true; then echo hello; fi; echo one; func; echo two' \ + 'one\nhello\ntwo\n' '' '' +shxpect 'local creates a whiteout' \ + I$'func() { local potato; echo ${potato?bang}; }; potato=123; func\n' \ + E E"$P" I$'echo $?\n' O$'1\n' # TODO finish variable list from shell init -- cgit v1.2.3