shelltest.od: add more "set -e" tests and add a 'skip' return code.

Based on the earlier t/000-set-minus-e bug in minimal/do on some
shells, let's add some extra tests that reveal the weirdness on those
shells.  Unfortunately because they are so popular (including bash and
zsh), we can't reject them outright for failing this one.

While we're here, add a new return code, "skip", which notes that a
test has failed but is not important enough to be considered a warning
or failure.  Previously we just had these commented out, which is not
quite obvious enough.

...and I updated a few comments while reviewing some of the older
tests.
This commit is contained in:
Avery Pennarun 2018-12-17 12:35:32 +00:00
commit 1f64cc4525
5 changed files with 79 additions and 18 deletions

View file

@ -36,9 +36,11 @@ for sh in dash /usr/xpg4/bin/sh ash posh \
#echo "line: '$line'" >&2 #echo "line: '$line'" >&2
stripw=${line#warning: } stripw=${line#warning: }
stripf=${line#failed: } stripf=${line#failed: }
strips=${line#skip: }
crash=$line crash=$line
[ "$line" = "$stripw" ] || msgs="$msgs W$stripw" [ "$line" = "$stripw" ] || msgs="$msgs W$stripw"
[ "$line" = "$stripf" ] || msgs="$msgs F$stripf" [ "$line" = "$stripf" ] || msgs="$msgs F$stripf"
[ "$line" = "$strips" ] || msgs="$msgs s$strips"
done <shelltest.tmp done <shelltest.tmp
rm -f shelltest.tmp rm -f shelltest.tmp
msgs=${msgs# } msgs=${msgs# }

1
t/.gitignore vendored
View file

@ -1,5 +1,6 @@
/broken /broken
/shellfile /shellfile
/shellfail
/shelltest.warned /shelltest.warned
/shelltest.failed /shelltest.failed
/stress.log /stress.log

View file

@ -1,3 +1,4 @@
redo-ifchange ../../redo/sh
rm -f log rm -f log
redo fatal >/dev/null 2>&1 || true redo fatal >/dev/null 2>&1 || true

View file

@ -2,6 +2,6 @@
sed 's/\.do$//' | sed 's/\.do$//' |
xargs redo xargs redo
rm -f broken shellfile shelltest.warned shelltest.failed \ rm -f broken shellfile shellfail shelltest.warned shelltest.failed \
*~ .*~ stress.log flush-cache *~ .*~ stress.log flush-cache
rm -rf 'space home dir' rm -rf 'space home dir'

View file

@ -29,6 +29,12 @@ warn()
: >shelltest.warned : >shelltest.warned
} }
# For things that should be a warning, but which are just too common
skip()
{
echo " skip: $1"
}
quiet_stderr() quiet_stderr()
{ {
if [ -n "$SHELLTEST_QUIET" ]; then if [ -n "$SHELLTEST_QUIET" ]; then
@ -185,17 +191,20 @@ c"
[ "$t2" = "$WANT" ] || fail 45 [ "$t2" = "$WANT" ] || fail 45
# Arguably, 'export' and 'local' shouldn't change variable assignment quoting # Arguably, 'export' and 'local' shouldn't change variable assignment
# rules, but in almost all shells (except bash), they do, and POSIX doesn't say # quoting rules, but in many shells they do, and POSIX doesn't say anything
# anything about it. So let's not bother testing this, other than just letting # about it. This leads to really confusing whitespace bugs in some shells,
# it check our syntax. # where
# # local x; x=$a
# and
# local x=$a
# mean two different things when $a contains whitespace.
bob="a b *" bob="a b *"
bob=$(quiet_stderr eval 'export bob=$bob:hello'; echo "$bob") bob=$(quiet_stderr eval 'export bob=$bob:hello'; echo "$bob")
#[ "$bob" = "a b *:hello" ] || warn 46 [ "$bob" = "a b *:hello" ] || skip 46
bob="a b *" bob="a b *"
nob=$(eval 'f() { local nob=$bob:hello; echo "$nob"; }'; quiet_stderr f) nob=$(eval 'f() { local nob=$bob:hello; echo "$nob"; }'; quiet_stderr f)
#[ "$nob" = "a b *:hello" ] || warn 47 [ "$nob" = "a b *:hello" ] || skip 47
# Someone pointed out that temporary variable assignments aren't # Someone pointed out that temporary variable assignments aren't
@ -247,14 +256,14 @@ echo "`printf 'foo\r\n'`"" bar" | diff -q - broken || fail 59
# #
# This one is too obnoxious. dash and ash pass the test, but most shells don't, # This one is too obnoxious. dash and ash pass the test, but most shells
# and this case is just too dumb to care about. Just don't do that! # don't, and this case is just too dumb to care about. Just don't do that!
# #
#t=`echo $(case x in x) echo hello;; esac)` t=`echo $(case x in x) echo hello;; esac)`
#[ "$t" = "hello" ] || fail 60 [ "$t" = "hello" ] || skip 60
# #
# Note that with the little-known optional left-paren, this *does* work. Let's # Note that with the little-known optional left-paren, this *does* work.
# try it to make sure that remains true. # Let's try it to make sure that remains true.
t=`echo $(case x in (x) echo hello;; esac)` t=`echo $(case x in (x) echo hello;; esac)`
[ "$t" = "hello" ] || fail 60 [ "$t" = "hello" ] || fail 60
@ -328,6 +337,53 @@ rv=$?
[ "$rv" = 0 ] || fail 89 [ "$rv" = 0 ] || fail 89
rm -f shellfail
echo "false; true" >shellfail
# 'false' should *not* abort because outer context has "||".
# Then 'true' gives success.
set +e
(
set -e
false
true
) || fail 89a
# 'false' still should not abort even in a subshell.
set +e
(
set -e
( false; true )
[ "$?" = 0 ] || fail 89b1
true
) || fail 89b
# Check whether "." scripts inherit "set -e" setting *and* the outer "||"
# context.
set +e
(
set -e
( . ./shellfail )
# There seems to be widespread disagreement on what should happen
# here. All shells seem to inherit "set -e" into a "." script, but
# they disagree about whether the outer "||" context (which
# effectively disables "set -e") should be inherited. ksh93, bash,
# and zsh inherit it, while ash, dash, and mksh (among others) throw
# it away, causing "set -e" to abort.
#
# Honestly, the latter behaviour seems a lot more like what I'd
# expect (a separate script doesn't want its "set -e" behaviour
# to depend on whether it's deep in a context with an "||" somewhere
# outside it), so let's warn on the former. But I'm willing to hear
# arguments either way. -- apenwarr
[ "$?" = 0 ] && warn 89c
# even if "." aborted and returned nonzero, our own context should
# not have aborted, so we expect to get here and avoid the outer
# fail below.
true
) || fail 89c1
# http://www.gnu.org/software/hello/manual/autoconf/Limitations-of-Builtins.html # http://www.gnu.org/software/hello/manual/autoconf/Limitations-of-Builtins.html
. /dev/null || fail 90 . /dev/null || fail 90
(! : | :) && fail 91 || true (! : | :) && fail 91 || true
@ -338,7 +394,7 @@ case frog.c in
(*) t3=all ;; (*) t3=all ;;
esac esac
[ "$t3" = "c" ] || fail 93 [ "$t3" = "c" ] || fail 93
t4=$(echo '\n' | wc -l) t4=$(echo '\n' | wc -l) # echo should *not* be parsing backslash-escapes
[ "$t4" -eq 1 ] || warn 94 [ "$t4" -eq 1 ] || warn 94
f5() { f5() {
for arg; do for arg; do
@ -400,9 +456,10 @@ false
# this is actually a bash/kshism, but is allowed by POSIX: the parameters to # this is actually a bash/kshism, but is allowed by POSIX: the parameters to
# '.' should be passed to the sub-script. # '.' should be passed to the sub-script.
# #
# We used to require this, because it's so useful despite being optional in POSIX. # We used to require this, because it's so useful despite being optional in
# But unfortunately, too many shells (including dash) can't do it, so we ended up # POSIX. But unfortunately, too many shells (including dash) can't do it,
# always using bash, which leads people to write .do scripts with bashisms. # so we ended up always using bash, which leads people to write .do scripts
# with bashisms.
set x y z set x y z
# dotparams.od might warn 115 # dotparams.od might warn 115
. ./dotparams.od a b || fail 117 . ./dotparams.od a b || fail 117