aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/runtest.sh94
-rwxr-xr-xtests/sh.test81
2 files changed, 100 insertions, 75 deletions
diff --git a/scripts/runtest.sh b/scripts/runtest.sh
index 25c8e104..9c19811c 100644
--- a/scripts/runtest.sh
+++ b/scripts/runtest.sh
@@ -95,6 +95,26 @@ wrong_args()
fi
}
+# Announce failure and handle fallout
+do_fail()
+{
+ FAILCOUNT=$(($FAILCOUNT+1))
+ printf "%s\n" "$SHOWFAIL: $NAME"
+ if [ -n "$VERBOSE" ]
+ then
+ [ ! -z "$4" ] && printf "%s\n" "echo -ne \"$4\" > input"
+ printf "%s\n" "echo -ne '$5' |$EVAL $2"
+ printf "%s\n" "$DIFF"
+ [ "$VERBOSE" == fail ] && exit 1
+ fi
+}
+
+# Announce success
+do_pass()
+{
+ [ "$VERBOSE" != "nopass" ] && printf "%s\n" "$SHOWPASS: $NAME"
+}
+
# The testing function
testing()
@@ -124,15 +144,7 @@ testing()
DIFF="$(diff -au${NOSPACE:+w} expected actual)"
if [ ! -z "$DIFF" ]
then
- FAILCOUNT=$(($FAILCOUNT+1))
- printf "%s\n" "$SHOWFAIL: $NAME"
- if [ -n "$VERBOSE" ]
- then
- [ ! -z "$4" ] && printf "%s\n" "echo -ne \"$4\" > input"
- printf "%s\n" "echo -ne '$5' |$EVAL $2"
- printf "%s\n" "$DIFF"
- [ "$VERBOSE" == fail ] && exit 1
- fi
+ do_fail
else
[ "$VERBOSE" != "nopass" ] && printf "%s\n" "$SHOWPASS: $NAME"
fi
@@ -152,6 +164,70 @@ testcmd()
testing "$X" "\"$C\" $2" "$3" "$4" "$5"
}
+# 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 "any nonzero string here"),
+# X means close stdin/stdout/stderr and match return code (blank means nonzero)
+txpect()
+{
+ # Run command with redirection through fifos
+ NAME="$1"
+
+ if [ $# -lt 2 ] || ! mkfifo in-$$ out-$$ err-$$
+ then
+ do_fail
+ return
+ fi
+ $2 <in-$$ >out-$$ 2>err-$$ &
+ shift 2
+ : {IN}>in-$$ {OUT}<out-$$ {ERR}<err-$$ && rm in-$$ out-$$ err-$$
+
+ [ $? -ne 0 ] && { do_fail;return;}
+
+ # Loop through challenge/response pairs, with 2 second timeout
+ while [ $# -gt 0 ]
+ do
+ LEN=$((${#1}-1))
+ case ${1::1} in
+
+ # send input to child
+ I) echo -en "${1:1}" >&$IN || { do_fail;return;} ;;
+
+ # check output from child
+ [OE])
+ [ $LEN == 0 ] && LARG="" || LARG="-rN $LEN"
+ O=$OUT
+ [ ${1::1} == 'E' ] && O=$ERR
+ read -t2 $LARG A <&$O
+ if [ $LEN -eq 0 ]
+ then
+ [ -z "$A" ] && { do_fail;return;}
+ else
+ [ "$A" != "${1:1}" ] && { do_fail;return;}
+ fi
+ ;;
+
+ # close I/O and wait for exit
+ X)
+ exec {IN}<&- {OUT}<&- {ERR}<&-
+ wait
+ X=$?
+ if [ -z "$LEN" ]
+ then
+ [ $X -eq 0 ] && { do_fail;return;} # any error
+ else
+ [ $X != "${1:1}" ] && { do_fail;return;} # specific value
+ fi
+ ;;
+ esac
+ shift
+ done
+ # In case we already closed it
+ exec {IN}<&- {OUT}<&- {ERR}<&-
+
+ do_pass
+}
+
# Recursively grab an executable and all the libraries needed to run it.
# Source paths beginning with / will be copied into destpath, otherwise
# the file is assumed to already be there and only its library dependencies
diff --git a/tests/sh.test b/tests/sh.test
index 875a0df8..ac7b6e45 100755
--- a/tests/sh.test
+++ b/tests/sh.test
@@ -1,76 +1,25 @@
#!/bin/bash
+# Testing shell corner cases _within_ a shell script is kind of hard.
+
[ -f testing.sh ] && . testing.sh
#testing "name" "command" "result" "infile" "stdin"
-if [ -z "$(which bash)" ]
-then
- echo "$SHOWSKIP: no bash alias"
- return 2>/dev/null
- exit
-fi
-
-shellit()
-{
- EVAL="bash -c" testing "$2" "$1 printf %s $2" "$3" "$4" "$5"
-}
-
-# $'' expands special chars but doesn't do so inside double quotes.
+[ -z "$SH" ] && { [ -z "$TEST_HOST" ] && SH="sh" || export SH="bash" ; }
+export EVAL="$SH -c"
-shellit "" "\$'a\\tb'" "a\tb" "" ""
-shellit "" "\"\$'a\\tb'\"" '$'"'"'a\\tb'"'" "" ""
+testing "leading assignments don't affect current line" \
+ 'VAR=12345 echo ${VAR}a' "a\n" "" ""
+testing "can't have space before first : but yes around arguments" \
+ 'BLAH=abcdefghi; echo ${BLAH: 1 : 3 }' "bcd\n" "" ""
-# $(( )) tests
+# Prompt changes for root/normal user
+[ $(id -u) -eq 0 ] && P='#' || P='$'
+# run sufficiently isolated shell child process to get predictable results
+SH="env -i PATH=${PATH@Q} PS1=\\$ $SH --noediting --noprofile --norc -is"
-shellit 'x=1;' '$((-x))' '-1' '' ''
-shellit 'x=0;' '$((x++)); echo $x' '01\n' '' ''
-shellit 'x=0;' '$((++x))' '1' '' ''
-shellit 'x=0;' '$((~x))' '-1' '' ''
-shellit 'x=1;' '$((!x))' '0' '' ''
-shellit 'x=0;' '$((!x))' '1' '' ''
-shellit 'x=2;' '$((2*x))' '4' '' ''
-shellit 'x=9;' '$((x/4))' '2' '' ''
-shellit 'x=9;' '$((x%4))' '1' '' ''
-shellit 'x=4;' '$((x+2))' '6' '' ''
-shellit 'x=4;' '$((x-2))' '2' '' ''
-shellit 'x=4;' '$((1<<x))' '16' '' ''
-shellit 'x=4;' '$((x>>1))' '2' '' ''
-shellit '' '$((3**4))' '81' '' ''
-shellit '' '$((3<=4))' '1' '' ''
-shellit '' '$((3>=4))' '0' '' ''
-shellit '' '$((3<4))' '1' '' ''
-shellit '' '$((3>4))' '0' '' ''
-shellit '' '$((3==4))' '0' '' ''
-shellit '' '$((3!=4))' '1' '' ''
-shellit '' '$((6&4))' '4' '' ''
-shellit '' '$((4|2))' '6' '' ''
-shellit '' '$((6&&2))' '1' '' ''
-shellit '' '$((6||4))' '1' '' ''
-shellit '' '$((1?2:3))' '2' '' ''
-shellit 'x=2;' '$((x=3)); echo $x' '33\n' '' ''
-shellit 'x=2;' '$((x*=3)); echo $x' '66\n' '' ''
-shellit 'x=5;' '$((x/=2)); echo $x' '22\n' '' ''
-shellit 'x=9;' '$((x%=5)); echo $x' '44\n' '' ''
-shellit 'x=9;' '$((x-=3)); echo $x' '66\n' '' ''
-shellit 'x=3;' '$((x+=2)); echo $x' '55\n' '' ''
-shellit 'x=7;' '$((x&=13)); echo $x' '55\n' '' ''
-shellit 'x=5;' '$((x|=12)); echo $x' '1313\n' '' ''
-shellit 'x=5;' '$((x^=12)); echo $x' '99\n' '' ''
-shellit 'x=2;' '$((x<<=2)); echo $x' '88\n' '' ''
-shellit 'x=12;' '$((x>>=2)); echo $x' '33\n' '' ''
-shellit 'x=2;' '$((x++,5)); echo $x' '53\n' '' ''
+# texpect "name" "command" E/O/I"string"
-# echo $(ls -l #comment)
-# cat -</dev/null
-# cat -|xargs echo
-# cat -(ls)
-# echo -!
-# echo -{
-# echo -(
-# (echo -)
-# echo $
-# "echo \$(echo \"hello\nworld\")"
-# "echo \"one ;\ntwo\""
-# echo $(ls -l &)
-# echo one < /dev/null two
+txpect "prompt and exit" "$SH" "E$P" "Iexit\n" X0
+txpect "prompt and echo" "$SH" "E$P" "Iecho hello\n" "Ohello"$'\n' "E$P" X0