diff --git a/src/cmd/ksh93/tests/arrays.sh b/src/cmd/ksh93/tests/arrays.sh index 2130aac1c..d8d55c294 100755 --- a/src/cmd/ksh93/tests/arrays.sh +++ b/src/cmd/ksh93/tests/arrays.sh @@ -729,5 +729,12 @@ do "(expected $(printf %q "$exp"), got $(printf %q "$got"))" done +# ====== +# https://github.com/att/ast/issues/23 +unset foo bar +typeset -a foo=([1]=w [2]=x) bar=(a b c) +foo+=("${bar[@]}") +[[ $(typeset -p foo) == 'typeset -a foo=([1]=w [2]=x [3]=a [4]=b [5]=c)' ]] || err_exit 'Appending does not work if array contains empty indexes' + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh index f0cdfb072..7aa1fea59 100755 --- a/src/cmd/ksh93/tests/basic.sh +++ b/src/cmd/ksh93/tests/basic.sh @@ -795,7 +795,7 @@ trap - DEBUG # bug compat # In ksh93v- and ksh2020 EXIT traps don't work in forked subshells # https://github.com/att/ast/issues/1452 exp="forked subshell EXIT trap okay" -got="$(ulimit -t unlimited; trap 'echo forked subshell EXIT trap okay' EXIT)" +got="$(ulimit -t unlimited 2> /dev/null; trap 'echo forked subshell EXIT trap okay' EXIT)" [[ $got == $exp ]] || err_exit "EXIT trap did not trigger in forked subshell" \ "(expected $(printf %q "$exp"), got $(printf %q "$got"))" diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh index d66f90f68..392405c2c 100755 --- a/src/cmd/ksh93/tests/builtins.sh +++ b/src/cmd/ksh93/tests/builtins.sh @@ -40,14 +40,14 @@ got=$(getconf -l | awk '{ gsub(/=.*/, "") } /[[:upper:]]/ { print }') exp="GETCONF=\"$bingetconf\"" got=$(getconf -q | grep 'GETCONF=') [[ $exp == "$got" ]] || err_exit "'getconf -q' fails to quote string values" \ - "(expected $exp, got $got)" + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" # The -n option should only return matching names. # https://github.com/ksh93/ksh/issues/279 exp="GETCONF=$bingetconf" got=$(getconf -n GETCONF) [[ $exp == "$got" ]] || err_exit "'getconf -n' doesn't match names correctly" \ - "(expected $exp, got $got)" + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" # ====== # Test shell builtin commands @@ -1201,12 +1201,12 @@ exp=$(uname -o) # Test for a possible crash (to avoid crashing the script, fork the subshell) ( - ulimit -t unlimited + ulimit -t unlimited 2> /dev/null uname -d > /dev/null ) || err_exit "'uname -d' crashes" # 'uname -d' shouldn't change the output of 'uname -o' -got=$(ulimit -t unlimited; uname -d > /dev/null; uname -o) +got=$(ulimit -t unlimited 2> /dev/null; uname -d > /dev/null; uname -o) [[ $exp == $got ]] || err_exit "'uname -d' changes the output of 'uname -o'" \ "(expected $(printf %q "$exp"), got $(printf %q "$got"))" diff --git a/src/cmd/ksh93/tests/functions.sh b/src/cmd/ksh93/tests/functions.sh index 3df8813c1..731c1a6e0 100755 --- a/src/cmd/ksh93/tests/functions.sh +++ b/src/cmd/ksh93/tests/functions.sh @@ -31,9 +31,25 @@ bin_echo=$(whence -p echo) bin_sleep=$(whence -p sleep) bin_kill=$(whence -p kill) +# ====== +# In ksh93v- and ksh2020 eval'ing a function definition may dump the function body to stdout. +# https://github.com/att/ast/issues/1160 +got="$($SHELL -c ' + for ((i=0; i<1025; i++)) + do str="${str}12345678" + done + eval "foo() { $str; }" + + baz() { eval "bar() { FAILURE; }"; } + ( baz >&3 ) 3>&1 +')" +[[ -n "$got" ]] && err_exit "eval'ing function dumps function body to stdout" \ + "(got $(printf %q "$got"))" + +# ====== +# Check for global variables and $0 integer foo=33 bar=bye -# check for global variables and $0 function foobar { case $1 in diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh index 0ad2f71fa..77d1171ab 100755 --- a/src/cmd/ksh93/tests/io.sh +++ b/src/cmd/ksh93/tests/io.sh @@ -283,12 +283,22 @@ EOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin' $SHELL -c 'exec 3>; /dev/null' 2> /dev/null && err_exit '>; with exec should be an error' $SHELL -c ': 3>; /dev/null' 2> /dev/null || err_exit '>; not working with at all' print hello > $tmp/1 -if ! $SHELL -c "false >; $tmp/1" 2> /dev/null -then let 1;[[ $(<$tmp/1) == hello ]] || err_exit '>; not preserving file on failure' -fi -if ! $SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1 2> /dev/null -then [[ $(<$tmp/1) == 'hello world' ]] || err_exit '>; not updating file on success' -fi +$SHELL -c "false >; $tmp/1" +status=$? +(( status == 1 )) || err_exit "unexpected exit status" \ + "(expected 1, got $status)" +exp='hello' +got=$(<$tmp/1) +[[ $got == "$exp" ]] || err_exit '>; not preserving file on failure' \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +$SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1 +status=$? +(( status == 0 )) || err_exit "unexpected exit status" \ + "(expected 0, got $status)" +exp='hello world' +got="$(<$tmp/1)" +[[ $got == "$exp" ]] || err_exit '>; not updating file on success' \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" $SHELL -c 'exec 3<>; /dev/null' 2> /dev/null && err_exit '<>; with exec should be an error' $SHELL -c ': 3<>; /dev/null' 2> /dev/null || err_exit '<>; not working with at all' @@ -474,13 +484,6 @@ do out=$("$binfalse" 2>/dev/null) fi done -rm -f $tmp/file1 $tmp/file2 -print foo > $tmp/file3 -ln -s $tmp/file3 $tmp/file2 -ln -s $tmp/file2 $tmp/file1 -print bar >; $tmp/file1 -[[ $(<$tmp/file3) == bar ]] || err_exit '>; not following symlinks' - for i in 1 do : done {n}< /dev/null @@ -639,8 +642,8 @@ fi # ====== # "&>file" redirection operator, shorthand for ">file 2>&1" (new as of 93u+m; inherited from old SHOPT_BASH) -if [[ -o ?posix ]] -then set -o posix +if [[ -o ?posix ]] && command set -o posix +then # This should print in a background job, then create an empty file, as '>aha1.txt' is a separate command. eval ' print -u1 bad1 &>aha1.txt print -u2 bad2 &>aha2.txt @@ -654,11 +657,8 @@ then set -o posix ' >/dev/null 2>&1 [[ $(< aha1.txt) == ok1 ]] || err_exit '&> does not redirect stdout' [[ $(< aha2.txt) == ok2 ]] || err_exit '&> does not redirect stderr' -fi - -# In POSIX mode, file descriptors > 2 should remain open when invoking another program -if [[ -o ?posix ]] -then (set -o posix; exec 7>ok.txt; "$SHELL" -c 'print ok >&7' 2>/dev/null) + # In POSIX mode, file descriptors > 2 should remain open when invoking another program + (set -o posix; exec 7>ok.txt; "$SHELL" -c 'print ok >&7' 2>/dev/null) [[ $( 2 not inherited in POSIX mode' fi (exec 7>bad.txt; "$SHELL" -c 'print bad >&7' 2>/dev/null) @@ -853,5 +853,30 @@ cat >out2 < <(case x in x) cat out1;; esac) [[ $($TMPF +export TMPF +[[ -n "$($SHELL -c 'echo $(<$TMPF)' <&-)" ]] || err_exit "Closing stdin causes failure when reading file through \$(<)" +[[ -n "$($SHELL -c "$SHELL -c 'echo \$(<$TMPF) >&2' >&-" 2>&1)" ]] || err_exit "Closing stdout causes failure when reading file through \$(<)" +[[ -n "$($SHELL -c 'echo $(<$TMPF)' 2>&-)" ]] || err_exit "Closing stderr causes failure when reading file through \$(<)" + +# ====== +# Verify that symlinks are correctly canonicalized as part of a conditional redirection. +# https://github.com/att/ast/issues/492 +mkdir -p dir1/dir2 +ln -s dir1 s1 +cd dir1 +ln -s dir2 s2 +cd .. +exp=symlinks-resolved +print wrong-answer > dir1/dir2/x +print $exp >; s1/s2/x +got=$(< dir1/dir2/x) +[[ $got == "$exp" ]] || err_exit "symlink in conditional redirect wrong" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh index 02771ab7f..7d5f0c317 100755 --- a/src/cmd/ksh93/tests/pty.sh +++ b/src/cmd/ksh93/tests/pty.sh @@ -577,6 +577,10 @@ actual=$(echo begin; exec >/dev/tty; [ -t ] && test -t) \ && echo OK7 || echo 'test -t in comsub with exec >/dev/tty fails' actual=$(echo begin; exec >/dev/tty; [ -n X -a -t ] && test -n X -a -t) \ && echo OK8 || echo 'test -t in comsub with exec >/dev/tty fails (compound expression)' +# The broken ksh2020 fix for [ -t 1 ] (https://github.com/att/ast/pull/1083) caused +# [ -t 1 ] to fail in non-comsub virtual subshells. +( test -t 1 ) && echo OK9 || echo 'test -t 1 in virtual subshell fails' +( test -t ) && echo OK10 || echo 'test -t in virtual subshell fails' EOF tst $LINENO <<"!" L test -t 1 inside command substitution @@ -593,6 +597,8 @@ r ^OK5\r\n$ r ^OK6\r\n$ r ^OK7\r\n$ r ^OK8\r\n$ +r ^OK9\r\n$ +r ^OK10\r\n$ r ^:test-2: ! @@ -841,5 +847,16 @@ r \t#foo\r\n$ r \thist -lnN 1\r\n$ ! +# err_exit # +((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!" +L tab completion while expanding ${.sh.*} variables +# https://github.com/att/ast/issues/1461 + +d 15 +p :test-1: +w test \$\{.sh.level\t +r ^:test-1: test \$\{.sh.level\}\r\n$ +! + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/shtests b/src/cmd/ksh93/tests/shtests index e3f6748d9..53c3ef266 100755 --- a/src/cmd/ksh93/tests/shtests +++ b/src/cmd/ksh93/tests/shtests @@ -446,7 +446,7 @@ print "Total errors: $total_e" # if we have the 'times' builtin and can use process substitution with output redirection. # See: https://github.com/ksh93/ksh/commit/65d363fd # https://github.com/ksh93/ksh/issues/2 -if ( ulimit -t unlimited # fork to circumvent old ksh bugs +if ( ulimit -t unlimited 2> /dev/null # fork to circumvent old ksh bugs unalias times PATH=/dev/null whence -q times || exit cd "$tmp" || exit diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index 4c94e1eeb..937c85066 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -1344,5 +1344,14 @@ exp=5 got=$($SHELL "$lineno_subshell") [[ $exp == $got ]] || err_exit "LINENO corrupted after leaving virtual subshell (expected $exp, got $got)" +# ====== +# Check if ${.sh.file} is set to correct value after sourcing a file +# https://github.com/att/ast/issues/472 +cat > $tmp/foo.sh < /dev/null +[[ ${.sh.file} == $0 ]] || err_exit "\${.sh.file} is not set to the correct value after sourcing a file" + # ====== exit $((Errors<125?Errors:125))