diff --git a/src/cmd/ksh93/tests/arrays.sh b/src/cmd/ksh93/tests/arrays.sh index f24b5578bc2f..4e27367f2089 100755 --- a/src/cmd/ksh93/tests/arrays.sh +++ b/src/cmd/ksh93/tests/arrays.sh @@ -524,6 +524,7 @@ typeset -m 'a[0]=a[1]' typeset -m 'a[1]=j' [[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving index array elements not working' unset a j +[[ $(typeset -p a) ]] && err_exit 'unset associative array after typeset -m not working' typeset -A a=( [0]="aa" [1]="bb" [2]="cc" ) typeset -m 'j=a[0]' diff --git a/src/cmd/ksh93/tests/arrays2.sh b/src/cmd/ksh93/tests/arrays2.sh index 23e1d8247479..4701565fdb9b 100755 --- a/src/cmd/ksh93/tests/arrays2.sh +++ b/src/cmd/ksh93/tests/arrays2.sh @@ -224,6 +224,15 @@ print -v cx > /dev/null print -v cx | read -C l 2> /dev/null || err_exit 'read -C fails from output of print -v' ((SHOPT_FIXEDARRAY)) && [[ ${cx%cx=} != "${l%l=}" ]] && err_exit 'print -v for compound variable with fixed 2d array not working' +unset foo +typeset -A foo +typeset -A foo[bar] +foo[bar][x]=2 +(( foo[bar][x]++ )) +exp=3 +[[ ${foo[bar][x]} == $exp ]] || err_ext "subscript gets added incorrectly to an associative array when ++ operator is called" \ + "(expected '$exp', got '${foo[bar][x]}')" + # ====== # Multidimensional arrays with an unset method shouldn't cause a crash. # The test itself must be run inside of a function. diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh index 18fd83dc1576..7d8f52a5319f 100755 --- a/src/cmd/ksh93/tests/basic.sh +++ b/src/cmd/ksh93/tests/basic.sh @@ -419,8 +419,16 @@ unset foo unset foo foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false' expected=foreback +got=`print -n fore; (sleep 2;print back)&` +[[ $got == $expected ]] || err_exit "\`\` command substitution background process output error (expected '$expected', got '$got')" got=$(print -n fore; (sleep .2;print back)&) -[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'" +[[ $got == $expected ]] || err_exit "\$() command substitution background process output error (expected '$expected', got '$got')" +got=${ print -n fore; (sleep 2;print back)& } +[[ $got == $expected ]] || err_exit "\${} shared-state command substitution background process output error (expected '$expected', got '$got')" +function abc { sleep 2; print back; } +function abcd { abc & } +got=$(print -n fore;abcd) +[[ $got == $expected ]] || err_exit "\$() command substitution background with function process output error (expected '$expected', got '$got')" for false in false $binfalse do x=$($false) && err_exit "x=\$($false) should fail" @@ -790,5 +798,46 @@ trap - DEBUG # bug compat [[ $got == "$exp" ]] || err_exit "DEBUG trap did not trigger return from POSIX function on status 255" \ "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +# ====== +# 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 == $exp ]] || err_exit "EXIT trap did not trigger in forked subshell" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + +exp="virtual subshell EXIT trap okay" +got="$(trap 'echo virtual subshell EXIT trap okay' EXIT)" +[[ $got == $exp ]] || err_exit "EXIT trap did not trigger in virtual subshell" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + +# ====== +# Regression test for https://github.com/att/ast/issues/1403 +for t in {A..Z}; do + $SHELL -c "trap - $t 2> /dev/null" + [[ $? == 1 ]] || err_exit "'trap' throws segfault when given invalid signal name '$t'" +done + +# ====== +# Is an invalid flag handled correctly? +# ksh2020 regression: https://github.com/att/ast/issues/1284 +actual=$($SHELL --verson 2>&1) +actual_status=$? +expect='ksh: verson: bad option(s)' +expect_status=2 +[[ "$actual" == ${expect}* ]] || err_exit "failed to get version string" \ + "(expected $(printf %q ${expect}*), got $(printf %q "$actual"))" +[[ $actual_status == $expect_status ]] || + err_exit "wrong exit status (expected '$expect_status', got '$actual_status')" + +# ====== +# Test for illegal seek error (ksh93v- regression) +# https://www.mail-archive.com/ast-users@lists.research.att.com/msg00816.html +exp='1 +2' +got="$(join <(printf '%d\n' 1 2) <(printf '%d\n' 1 2))" +[[ $exp == $got ]] || err_exit "pipeline fails with illegal seek error" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/bracket.sh b/src/cmd/ksh93/tests/bracket.sh index 4d7d6b00631d..95771aee70d9 100755 --- a/src/cmd/ksh93/tests/bracket.sh +++ b/src/cmd/ksh93/tests/bracket.sh @@ -408,5 +408,13 @@ do unset var [[ -n ${var+s} ]] || err_exit "[[ -n \${var+s} ]] should be true for empty var with attribute -$flag" done +# ====== +# Tests from ksh93v- for the -eq operator +[[ 010 -eq 10 ]] || err_exit '010 is not 10 in [[...]]' + +unset foo +foo=10 +([[ foo -eq 10 ]]) || err_exit 'foo -eq 10 fails in [[...]] with foo=10' + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh index 76630e31f7e9..5e7330f2b628 100755 --- a/src/cmd/ksh93/tests/builtins.sh +++ b/src/cmd/ksh93/tests/builtins.sh @@ -686,11 +686,6 @@ then ( fi cd "$tmp" -$SHELL +E -i 2>/dev/null <<- \! && err_exit 'interactive shell should not exit 0 after false' - false - exit -! - if kill -L > /dev/null 2>&1 then [[ $(kill -l HUP) == "$(kill -L HUP)" ]] || err_exit 'kill -l and kill -L are not the same when given a signal name' [[ $(kill -l 9) == "$(kill -L 9)" ]] || err_exit 'kill -l and kill -L are not the same when given a signal number' @@ -974,7 +969,7 @@ fi EOF "$SHELL" -i "$sleepsig" 2> /dev/null || err_exit "'sleep -s' doesn't work with intervals of more than 30 seconds" -# ========== +# ====== # Builtins should handle unrecognized options correctly while IFS= read -r bltin <&3 do case $bltin in @@ -1013,5 +1008,42 @@ then got=$( { "$SHELL" -c ' "(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))" fi +# ====== +# Regression test for https://github.com/att/ast/issues/1402 +# +# We throw away stderr because we only want the value of '$t', not the error text from running +# 'command' with an invalid flag. +exp='good' +got=$($SHELL -c 't=good; t=bad command -@; print $t' 2>/dev/null) +[[ $exp == $got ]] || err_exit "temp var assignment with 'command'" \ + "(expected $(printf %q "$expect"), got $(printf %q "$actual"))" + +# ====== +# Regression test for https://github.com/att/ast/issues/949 +foo_script='#!/bin/sh +exit 0' +echo "$foo_script" > "$tmp/foo1.sh" +echo "$foo_script" > "$tmp/foo2.sh" +builtin chmod +chmod +x "$tmp/foo1.sh" "$tmp/foo2.sh" +$SHELL "$tmp/foo1.sh" || err_exit "builtin 'chmod +x' doesn't work on first script" +$SHELL "$tmp/foo2.sh" || err_exit "builtin 'chmod +x' doesn't work on second script" + +# ====== +# In ksh93v- 2013-10-10 alpha cd doesn't fail on directories without execute permission. +# Additionally, ksh93v- added a regression test for attempting to use cd on a file. +mkdir "$tmp/noexecute" +chmod -x "$tmp/noexecute" +$SHELL -c "cd $tmp/noexecute" 2> /dev/null && err_exit "'cd' on directories without an execute bit doesn't fail" +touch "$tmp/notadir" +$SHELL -c "cd $tmp/notadir" 2> /dev/null && err_exit "'cd' on a normal file doesn't fail" + +# ====== +# 'kill %' should fail with exit status 1 +{ $SHELL -c 'kill %' ;} 2> /dev/null +got=$? +exp=1 +[[ $got == $exp ]] || err_exit "'kill %' has the wrong exit status (expected '$exp'; got '$got')" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/case.sh b/src/cmd/ksh93/tests/case.sh index 84c6b42b66be..f28d56e18c29 100755 --- a/src/cmd/ksh93/tests/case.sh +++ b/src/cmd/ksh93/tests/case.sh @@ -102,5 +102,11 @@ got=$(eval 'case x in (if);; esac' 2>&1) || err_exit "'(' + 'if' as first patter got=$(eval 'case x in foo);; if);; esac' 2>&1) || err_exit "'if' as nth pattern fails: got $(printf %q "$got")" got=$(eval 'case x in (foo);; (if);; esac' 2>&1) || err_exit "'(' + 'if' as nth pattern fails: got $(printf %q "$got")" +# ====== +# Verify an invalid character class name is handled without a SIGSEGV or similar failure +# https://github.com/att/ast/issues/1409 +got="$($SHELL -c 'case x in [x[:bogus:]]) echo x ;; esac')" +[[ -z $got ]] || err_exit "invalid char class name (got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/exit.sh b/src/cmd/ksh93/tests/exit.sh index a6ca0647e97e..1940e7f4213c 100755 --- a/src/cmd/ksh93/tests/exit.sh +++ b/src/cmd/ksh93/tests/exit.sh @@ -76,4 +76,64 @@ cd / cd ~- || err_exit "cd back failed" $SHELL -c 'builtin -f cmd getconf; getconf --"?-version"; exit 0' >/dev/null 2>&1 || err_exit 'ksh plugin exit failed -- was ksh built with CCFLAGS+=$(CC.EXPORT.DYNAMIC)?' +# ====== +# Verify the 'exit' command behaves as expected + +got=$($SHELL -c 'exit' 2>&1) +status=$? +exp=0 +[[ -z $got ]] || err_exit 'bare exit' \ + "(got $(printf %q "$got"))" +[[ $exp == $status ]] || err_exit 'bare exit' \ + "(expected '$exp', got '$status')" + +got=$($SHELL -c 'exit 0' 2>&1) +status=$? +exp=0 +[[ -z $got ]] || err_exit 'exit 0' \ + "(got $(printf %q "$got"))" +[[ $exp == $status ]] || err_exit 'exit 0' \ + "(expected '$exp', got '$status')" + +got=$($SHELL -c 'exit 1' 2>&1) +status=$? +exp=1 +[[ -z $got ]] || err_exit 'exit 1' \ + "(got $(printf %q "$got"))" +[[ $exp == $status ]] || err_exit 'exit 1' \ + "(expected '$exp', got '$status')" + +got=$($SHELL -c 'function e37 { return 37; } ; e37' 2>&1) +status=$? +exp=37 +[[ -z $got ]] || err_exit 'exit 37' \ + "(got $(printf %q "$got"))" +[[ $exp == $status ]] || err_exit 'exit 37' \ + "(expected '$exp', got '$status')" + +got=$($SHELL -c 'exit -1' 2>&1) +status=$? +exp=255 +[[ -z $got ]] || err_exit 'exit -1' \ + "(got $(printf %q "$got"))" +[[ $exp == $status ]] || err_exit 'exit -1' \ + "(expected '$exp', got '$status')" + +got=$($SHELL -c 'exit -2' 2>&1) +status=$? +exp=254 +[[ -z $got ]] || err_exit 'exit -2' \ + "(got $(printf %q "$got"))" +[[ $exp == $status ]] || err_exit 'exit -2' \ + "(expected '$exp', got '$status')" + +$SHELL +E -i 2>/dev/null <<- \! && err_exit 'interactive shell should not exit 0 after false' + false + exit +! +status=$? +exp=1 +[[ $exp == $status ]] || err_exit 'bare exit after false' \ + "(expected '$exp', got '$status')" + exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh index ace60fe040a7..3a73d7be46df 100755 --- a/src/cmd/ksh93/tests/io.sh +++ b/src/cmd/ksh93/tests/io.sh @@ -715,5 +715,23 @@ got=$(export tmp; "$SHELL" -ec \ (redirect {v}>$tmp/v.out; echo ok2 >&$v) 2>/dev/null [[ -r $tmp/v.out && $(<$tmp/v.out) == ok2 ]] || err_exit 'redirect {varname}>file not working in a subshell' +# ====== +# Regression test for a process substitution hang in ksh93v- 2013-10-10 alpha +{ + producer() { + for ((i = 0; i < 20000; i++ )) do + print xxxxx${i}xxxxx + done + } + consumer() { + while read var; do + print ${var} + done < ${1} + } + consumer <(producer) > /dev/null +} & pid=$! +(sleep 5; kill -HUP $pid) 2> /dev/null & +wait $pid 2> /dev/null || err_exit "process substitution hangs" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/math.sh b/src/cmd/ksh93/tests/math.sh index 2e4c948b97ab..b13e6c35f2ee 100755 --- a/src/cmd/ksh93/tests/math.sh +++ b/src/cmd/ksh93/tests/math.sh @@ -260,5 +260,12 @@ unset x [[ $(typeset -lE 0 x=5.67; typeset -p x) == 'typeset -l -E 0 x=6' ]] || err_exit 'typeset -lE 0 with assignment failed to round.' [[ $(typeset -lX 0 x=5.67; typeset -p x) == 'typeset -l -X 0 x=0x1p+2' ]] || err_exit 'typeset -lX 0 with assignment failed to round.' +# ====== +# typeset -s used without -i shouldn't set foo to garbage +exp=30000 +got="$(typeset -s foo=30000; echo $foo)" +[[ $exp == $got ]] || err_exit "unexpected output from typeset -s without -i" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index 727160c81ef8..bdb40b8e308f 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -1258,5 +1258,13 @@ exp='foo/foobar/fool' got=$(IFS=/; foo=bar foobar=fbar fool=pity; print -r -- "${!foo*}") [[ $got == "$exp" ]] || err_exit "\${!foo*}: expected $(printf %q "$exp"), got $(printf %q "$got")" +# ====== +# In ksh93v- ${.sh.subshell} is unset by the $PS4 prompt +# https://github.com/att/ast/issues/1092 +exp='0' +got="$($SHELL -c 'PS4="${.sh.subshell}"; echo ${.sh.subshell}')" +[[ "$exp" == "$got" ]] || err_exit "\${.sh.subshell} is wrongly unset in the \$PS4 prompt" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))