diff --git a/src/cmd/ksh93/tests/_common b/src/cmd/ksh93/tests/_common index 7b7dc76cb..719be9151 100644 --- a/src/cmd/ksh93/tests/_common +++ b/src/cmd/ksh93/tests/_common @@ -21,7 +21,7 @@ _message() } function err_exit { - _message "$@" + _message "$1" "FAIL:" "${@:2}" let Errors+=1 } alias err_exit='err_exit $LINENO' # inaccurate err_exit name kept for historical integrity :) diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh index 1ce70622f..815493461 100755 --- a/src/cmd/ksh93/tests/leaks.sh +++ b/src/cmd/ksh93/tests/leaks.sh @@ -16,6 +16,7 @@ # Florham Park NJ # # # # David Korn # +# Martijn Dekker # # # ######################################################################## @@ -27,31 +28,22 @@ if builtin vmstate 2>/dev/null && n=$(vmstate --format='%(busy_size)u') && let "($n) == ($n) && n > 0" # non-zero number? -then N=512 # number of iterations for each test - unit=bytes - tolerance=$((4*N)) # tolerate 4 bytes per iteration to account for vmalloc artefacts - vmalloc=enabled - function getmem +then vmalloc=enabled + getmem() { - vmstate --format='%(busy_size)u' + print $(( $(vmstate --format='%(busy_size)u') / 1024 )) } # On Linux, we can use /proc to get byte granularity for vsize (field 23). elif [[ -f /proc/$$/stat && $(uname) == Linux ]] -then N=4096 # number of iterations for each test - unit=bytes - tolerance=$((16*N)) # tolerate 16 bytes per iteration to account for malloc artefacts - function getmem +then getmem() { - cut -f 23 -d ' ' /dev/null) && let "($n) == ($n) && n > 0" -then N=16384 - unit=KiB - tolerance=$((4*N/1024)) # tolerate 4 bytes per iteration to account for malloc artefacts - function getmem +then getmem() { ps -o vsz= -p "$$" } @@ -59,10 +51,7 @@ then N=16384 # of the 'ps' command (the standard 'vsz', virtual size, is not usable). elif n=$(ps -o rss= -p "$$" 2>/dev/null) && let "($n) == ($n) && n > 0" -then N=16384 - unit=KiB - tolerance=$((12*N/1024)) # tolerate 12 bytes per iteration to account for malloc/ps artefacts - function getmem +then getmem() { ps -o rss= -p "$$" } @@ -70,79 +59,104 @@ else warning 'cannot find method to measure memory usage; skipping tests' exit 0 fi -# test for variable reset leak # +# Parameters for test blocks. +# Intended to cope with all non-deterministic OS memory management artefacts. +# +# Theory: if we can get a sequence of $min_good_blocks blocks of $block_iter iterations without the memory state changing, +# then we can safely assume it's not a memory leak, break the loop, and consider the test succeeded. To allow for +# unpredictable OS memory management artefacts, that sequence is allowed to occur anywhere within $max_iter iterations. +# This speeds up the tests, as successful tests can bow out at $((min_good_blocks * block_iter)) iterations if they're +# lucky. If the OS decides to randomly grow the memory heap, it may take more tries, but hopefully not more than +# $max_iter iterations. If the loop counter reaches $max_iter, then we assume a memory leak and throw a test failure. -function test_reset -{ - integer i N=$1 +typeset -ir max_iter=16384 block_iter=128 min_good_blocks=16 - for ((i = 0; i < N; i++)) - do u=$i - done -} +# Set up test block construct. +# Known leaks can be marked known=y to turn them into non-fail warnings. +# +# Usage: +# TEST title='description' [ known=y [ url= ] ] +# +# DO +# +# DONE +# +# To avoid messing up $LINENO, aliases should not contain newline characters. +# To keep things readable, backslash line continuation is used instead. -# Initialise variables used below to avoid false leaks -before=0 after=0 i=0 u=0 +typeset .lt # create lt (leak test) namespace for internal variables +typeset -i .lt.before=0 .lt.after=0 .lt.total=0 .lt.good=0 .lt.i=0 .lt.j=0 +alias TEST=\ +'for .lt.i in 1; do '\ +' unset -v known url; ' + # optional preparatory commands go here +alias DO=\ +' if [[ -v known && ! -v DEBUG ]]; '\ +' then warning "skipping test for known leak \"$title\";" '\ +' "export DEBUG=y to test" ${url:+"and help us fix it at: $url"}; '\ +' break; '\ +' fi; '\ +' .lt.before=$(getmem) .lt.good=0 .lt.total=0; '\ +' for ((.lt.i = 0; .lt.i < max_iter; .lt.i += block_iter)); '\ +' do for ((.lt.j = 0; .lt.j < block_iter; .lt.j++)); '\ +' do ' + # test payload commands go here +alias DONE=\ +' done; '\ +' .lt.after=$(getmem); '\ +' if ((.lt.after <= .lt.before)); '\ +' then ((.lt.good++ == min_good_blocks)) && break; '\ +' else ((.lt.good = 0)); '\ +' ((.lt.total += (.lt.after - .lt.before))); '\ +' .lt.before=$(getmem); '\ +' fi; '\ +' done; '\ +' if ((.lt.i >= max_iter)); '\ +' then if [[ -v known ]]; '\ +' then err_exit "known leak: $title: leaked approx ${.lt.total} KiB after ${.lt.i} iterations" '\ +' ${url:+"-- help us fix it at: $url"}; '\ +' else err_exit "$title: leaked approx ${.lt.total} KiB after ${.lt.i} iterations"; '\ +' fi; '\ +' elif [[ -v known ]]; '\ +' then warning "did not detect known leak \"$title\": succeeded after ${.lt.i} iterations)" ${url:+"-- see: $url"}; '\ +' elif [[ -v DEBUG ]]; '\ +' then _message "$LINENO" "[DEBUG] test \"$title\" succeeded after ${.lt.i} iterations"; '\ +' fi; '\ +'done' +# ____ Begin memory leak tests ____ -# Check results. -# The function has 'err_exit' in the name so that shtests counts each call as a test. -function err_exit_if_leak -{ - if ((after > before + tolerance)) - then err\_exit "$1" "$2 (leaked approx $((after - before)) $unit after $N iterations)" - fi -} -alias err_exit_if_leak='err_exit_if_leak "$LINENO"' - -# one round to get to steady state -- sensitive to -x - -test_reset $N -test_reset $N -before=$(getmem) -test_reset $N -after=$(getmem) -err_exit_if_leak "variable value reset memory leak" - -# buffer boundary tests - -for exp in 65535 65536 -do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1) - [[ $got == $exp ]] || err_exit "large command substitution failed -- expected $exp, got $got" -done +TEST title='variable value reset' + integer i=0 + u=foo +DO + u=$((++i)) +DONE +# data for the next two tests... data="(v=;sid=;di=;hi=;ti='1328244300';lv='o';id='172.3.161.178';var=(k='conn_num._total';u=;fr=;l='Number of Connections';n='22';t='number';))" read -C stat <<< "$data" -for ((i=0; i < 8; i++)) # steady state first -do print -r -- "$data" | while read -u$n -C stat; do :; done {n}<&0- -done -before=$(getmem) -for ((i=0; i < N; i++)) -do print -r -- "$data" -done | while read -u$n -C stat - do : - done {n}<&0- -after=$(getmem) -err_exit_if_leak "memory leak with read -C when deleting compound variable" -# extra 'read's to get to steady state -for ((i=0; i < 10; i++)) -do read -C stat <<< "$data" -done -before=$(getmem) -for ((i=0; i < N; i++)) -do read -C stat <<< "$data" -done -after=$(getmem) -err_exit_if_leak "memory leak with read -C when using <<<" +while : +do print -r -- "$data" +done | \ +TEST title='read -C when deleting compound variable' +DO read -u$n -C stat +DONE {n}<&0- + +TEST title='read -C when using <<<' +DO + read -C stat <<< "$data" +DONE + +unset data stat # ====== # Unsetting an associative array shouldn't cause a memory leak # See https://www.mail-archive.com/ast-users@lists.research.att.com/msg01016.html -typeset -A stuff -before=$(getmem) -for (( i=0; i < N; i++ )) -do +TEST title='unset of associative array' + typeset -A stuff +DO unset stuff[xyz] typeset -A stuff[xyz] stuff[xyz][elem0]="data0" @@ -150,106 +164,82 @@ do stuff[xyz][elem2]="data2" stuff[xyz][elem3]="data3" stuff[xyz][elem4]="data4" -done -unset stuff -after=$(getmem) -err_exit_if_leak 'unset of associative array causes memory leak' +DONE + +# https://github.com/ksh93/ksh/issues/94 +TEST title='defining associative array in subshell' known=y url=https://github.com/ksh93/ksh/issues/94 +DO + (typeset -A foo=([a]=1 [b]=2 [c]=3)) +DONE # ====== # Memory leak when resetting PATH and clearing hash table -# ...steady memory state: -command -v ls >/dev/null # add something to hash table -PATH=/dev/null true # set/restore PATH & clear hash table # ...test for leak: -before=$(getmem) -for ((i=0; i < N; i++)) -do PATH=/dev/null true # set/restore PATH & clear hash table +TEST title='PATH reset before PATH search' +DO + PATH=/dev/null true # set/restore PATH & clear hash table command -v ls # do PATH search, add to hash table -done >/dev/null -after=$(getmem) -err_exit_if_leak 'memory leak on PATH reset before PATH search' +DONE >/dev/null # ...test for another leak that only shows up when building with nmake: -before=$(getmem) -for ((i=0; i < N; i++)) -do PATH=/dev/null true # set/restore PATH & clear hash table -done >/dev/null -after=$(getmem) -err_exit_if_leak 'memory leak on PATH reset' +TEST title='PATH reset' +DO + PATH=/dev/null true # set/restore PATH & clear hash table +DONE >/dev/null # ====== # Defining a function in a virtual subshell # https://github.com/ksh93/ksh/issues/114 -unset -f foo -before=$(getmem) -for ((i=0; i < N; i++)) -do (function foo { :; }; foo) -done -after=$(getmem) -err_exit_if_leak 'ksh function defined in virtual subshell' -typeset -f foo >/dev/null && err_exit 'ksh function leaks out of subshell' +TEST title='ksh function defined in virtual subshell' + unset -f foo +DO + (function foo { :; }; foo) +DONE -unset -f foo -before=$(getmem) -for ((i=0; i < N; i++)) -do (foo() { :; }; foo) -done -after=$(getmem) -err_exit_if_leak 'POSIX function defined in virtual subshell' -typeset -f foo >/dev/null && err_exit 'POSIX function leaks out of subshell' +TEST title='POSIX function defined in virtual subshell' + unset -f foo +DO + (foo() { :; }; foo) +DONE # Unsetting a function in a virtual subshell -function foo { echo bar; } -before=$(getmem) -for ((i=0; i < N; i++)) -do (unset -f foo) -done -after=$(getmem) -err_exit_if_leak 'ksh function unset in virtual subshell' -typeset -f foo >/dev/null || err_exit 'ksh function unset in subshell was unset in main shell' +TEST title='ksh function unset in virtual subshell' + function foo { echo bar; } +DO + (unset -f foo) +DONE -foo() { echo bar; } -before=$(getmem) -for ((i=0; i < N; i++)) -do (unset -f foo) -done -after=$(getmem) -err_exit_if_leak 'POSIX function unset in virtual subshell' -typeset -f foo >/dev/null || err_exit 'POSIX function unset in subshell was unset in main shell' +TEST title='POSIX function unset in virtual subshell' + foo() { echo bar; } +DO + (unset -f foo) +DONE -before=$(getmem) -for ((i=0; i < N; i++)) -do (function foo { echo baz; }; unset -f foo) -done -after=$(getmem) -err_exit_if_leak 'ksh function defined and unset in virtual subshell' +TEST title='ksh function defined and unset in virtual subshell' +DO + (function foo { echo baz; }; unset -f foo) +DONE -before=$(getmem) -for ((i=0; i < N; i++)) -do (foo() { echo baz; }; unset -f foo) -done -after=$(getmem) -err_exit_if_leak 'POSIX function defined and unset in virtual subshell' +TEST title='POSIX function defined and unset in virtual subshell' +DO + (foo() { echo baz; }; unset -f foo) +DONE # ====== # Sourcing a dot script in a virtual subshell -echo 'echo "$@"' > $tmp/dot.sh -before=$(getmem) -for ((i=0; i < N; i++)) -do (. "$tmp/dot.sh" dot one two three >/dev/null) -done -after=$(getmem) -err_exit_if_leak 'script dotted in virtual subshell' +TEST title='script dotted in virtual subshell' + echo 'echo "$@"' > $tmp/dot.sh +DO + (. "$tmp/dot.sh" dot one two three >/dev/null) +DONE -echo 'echo "$@"' > $tmp/dot.sh -before=$(getmem) -for ((i=0; i < N; i++)) -do (source "$tmp/dot.sh" source four five six >/dev/null) -done -after=$(getmem) -err_exit_if_leak 'script sourced in virtual subshell' +TEST title='script sourced in virtual subshell' + echo 'echo "$@"' > $tmp/dot.sh +DO + (source "$tmp/dot.sh" source four five six >/dev/null) +DONE # ====== # Multiple leaks when using arrays in functions (Red Hat #921455) @@ -259,31 +249,27 @@ err_exit_if_leak 'script sourced in virtual subshell' # after the patch) when run in a non-C locale. [[ $vmalloc == enabled ]] && saveLANG=$LANG && LANG=C # comment out to test remaining leak (1/2) -function _hash -{ - typeset w=([abc]=1 [def]=31534 [xyz]=42) - print -u2 $w 2>&- - # accessing the var will leak -} -before=$(getmem) -for ((i=0; i < N; i++)) -do _hash -done -after=$(getmem) -err_exit_if_leak 'associative array in function' +TEST title='associative array in function' + function _hash + { + typeset w=([abc]=1 [def]=31534 [xyz]=42) + print -u2 $w 2>&- + # accessing the var will leak + } +DO + _hash +DONE -function _array -{ - typeset w=(1 31534 42) - print -u2 $w 2>&- - # unset w will prevent leak -} -before=$(getmem) -for ((i=0; i < N; i++)) -do _array -done -after=$(getmem) -err_exit_if_leak 'indexed array in function' +TEST title='indexed array in function' + function _array + { + typeset w=(1 31534 42) + print -u2 $w 2>&- + # unset w will prevent leak + } +DO + _array +DONE [[ $vmalloc == enabled ]] && LANG=$saveLANG # comment out to test remaining leak (2/2) @@ -292,175 +278,126 @@ err_exit_if_leak 'indexed array in function' # Fix based on: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-memlik3.patch # The fix was backported from ksh 93v- beta. -function myFunction -{ - typeset toPrint="something" - echo "${toPrint}" -} -state=$(myFunction) -before=$(getmem) -for ((i=0; i < N; i++)) -do state=$(myFunction) -done -after=$(getmem) -err_exit_if_leak 'typeset in function called by command substitution' +TEST title='typeset in function called by command substitution' + function myFunction + { + typeset toPrint="something" + echo "${toPrint}" + } +DO + state=$(myFunction) +DONE # ====== # Check that unsetting an alias frees both the node and its value -before=$(getmem) -for ((i=0; i < N; i++)) -do alias "test$i=command$i" +TEST title='unalias' +DO + alias "test$i=command$i" unalias "test$i" -done -after=$(getmem) -err_exit_if_leak 'unalias' +DONE # ====== # Red Hat bug rhbz#982142: command substitution leaks # case1: Nested command substitutions # (reportedly already fixed in 93u+, but let's keep the test) -before=$(getmem) -for ((i=0; i < N; i++)) -do a=`true 1 + \`true 1 + 1\`` # was: a=`expr 1 + \`expr 1 + 1\`` -done -after=$(getmem) -err_exit_if_leak 'nested command substitutions' +TEST title='nested command substitutions' +DO + a=`true 1 + \`true 1 + 1\`` # was: a=`expr 1 + \`expr 1 + 1\`` +DONE # case2: Command alias -alias ls='true -ltr' # was: alias ls='ls -ltr' -before=$(getmem) -for ((i=0; i < N; i++)) -do eval 'a=`ls`' -done -after=$(getmem) -unalias ls -err_exit_if_leak 'alias in command substitution' +TEST title='alias in command substitution' + alias ls='true -ltr' # was: alias ls='ls -ltr' +DO + eval 'a=`ls`' +DONE # case3: Function call via autoload -cat >$tmp/func1 <<\EOF -function func1 -{ - echo "func1 call"; -} -EOF -FPATH=$tmp -autoload func1 -a=`func1` # steady memory state -before=$(getmem) -for ((i=0; i < N; i++)) -do a=`func1` -done -after=$(getmem) -unset -f func1 -unset -v FPATH -err_exit_if_leak 'function call via autoload in command substitution' +TEST title='function call via autoload in command substitution' + cat >$tmp/func1 <<-\EOF + function func1 + { + echo "func1 call"; + } + EOF + FPATH=$tmp + autoload func1 +DO + a=`func1` +DONE # ====== # add some random utilities to the hash table to detect memory leak on hash table reset when changing PATH random_utils=(chmod cp mv awk sed diff comm cut sort uniq date env find mkdir rmdir pr sleep) - save_PATH=$PATH -hash "${random_utils[@]}" -before=$(getmem) -for ((i=0; i < N; i++)) -do hash -r - hash "${random_utils[@]}" -done -after=$(getmem) -err_exit_if_leak 'clear hash table (hash -r) in main shell' -before=$(getmem) -for ((i=0; i < N; i++)) -do PATH=/dev/null +TEST title='clear hash table (hash -r) in main shell' +DO + hash -r + hash "${random_utils[@]}" +DONE + +TEST title='set PATH value in main shell' +DO + PATH=/dev/null PATH=$save_PATH hash "${random_utils[@]}" -done -after=$(getmem) -err_exit_if_leak 'set PATH value in main shell' +DONE -before=$(getmem) -for ((i=0; i < N; i++)) -do PATH=/dev/null command true -done -after=$(getmem) -err_exit_if_leak 'run command with preceding PATH assignment in main shell' +TEST title='run command with preceding PATH assignment in main shell' +DO + PATH=/dev/null command true +DONE -: <<'disabled' # TODO: known leak (approx 73552 bytes after 512 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do typeset -A PATH +TEST title='set PATH attribute in main shell' known=y url=https://github.com/ksh93/ksh/issues/405 +DO + typeset -A PATH unset PATH PATH=$save_PATH hash "${random_utils[@]}" -done -after=$(getmem) -err_exit_if_leak 'set PATH attribute in main shell' -disabled +DONE -: <<'disabled' # TODO: known leak (approx 99568 bytes after 512 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do unset PATH +TEST title='unset PATH in main shell' known=y url=https://github.com/ksh93/ksh/issues/405 +DO + unset PATH PATH=$save_PATH hash "${random_utils[@]}" -done -after=$(getmem) -err_exit_if_leak 'unset PATH in main shell' -disabled +DONE -hash "${random_utils[@]}" -before=$(getmem) -for ((i=0; i < N; i++)) -do (hash -r) -done -after=$(getmem) -err_exit_if_leak 'clear hash table (hash -r) in subshell' +TEST title='clear hash table (hash -r) in subshell' + hash "${random_utils[@]}" +DO + (hash -r) +DONE -: <<'disabled' # TODO: known leak (approx 123520 bytes after 512 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do (PATH=/dev/null) -done -after=$(getmem) -err_exit_if_leak 'set PATH value in subshell' -disabled +TEST title='set PATH value in subshell' known=y url=https://github.com/ksh93/ksh/issues/405 +DO + (PATH=/dev/null) +DONE -: <<'disabled' # TODO: known leak (approx 24544 bytes after 512 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do (PATH=/dev/null command true) -done -after=$(getmem) -err_exit_if_leak 'run command with preceding PATH assignment in subshell' -disabled +TEST title='run command with preceding PATH assignment in subshell' known=y url=https://github.com/ksh93/ksh/issues/405 +DO + (PATH=/dev/null command true) +DONE -: <<'disabled' # TODO: known leak (approx 131200 bytes after 512 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do (readonly PATH) -done -after=$(getmem) -err_exit_if_leak 'set PATH attribute in subshell' -disabled +TEST title='set PATH attribute in subshell' known=y url=https://github.com/ksh93/ksh/issues/405 +DO + (readonly PATH) +DONE -: <<'disabled' # TODO: known leak (approx 229440 bytes after 512 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do (unset PATH) -done -after=$(getmem) -err_exit_if_leak 'unset PATH in subshell' -disabled +TEST title='unset PATH in subshell' known=y url=https://github.com/ksh93/ksh/issues/405 +DO + (unset PATH) +DONE # ====== # Test for a memory leak after 'cd' (in relation to $PWD and $OLDPWD) -original_pwd=$PWD -before=$(getmem) -for ((i=0; i < N; i++)) -do cd /tmp +TEST title='PWD and/or OLDPWD changed by cd' +DO + cd /tmp cd - > /dev/null PWD=/foo OLDPWD=/bar @@ -471,23 +408,14 @@ do cd /tmp cd - > /dev/null unset OLDPWD PWD cd /bin - cd /tmp -done -after=$(getmem) -err_exit_if_leak 'PWD and/or OLDPWD changed by cd' -cd $original_pwd + cd "$tmp" +DONE # ====== -# https://github.com/ksh93/ksh/issues/253#issuecomment-815308466 -: <<'disabled' # TODO: known leak(s) (approx 1008 KiB after 16384 iterations) -before=$(getmem) -for ((i=0; i < N; i++)) -do +TEST title='variable with discipline function in subshell' known=y url=https://github.com/ksh93/ksh/issues/404 +DO (SECONDS=1; LANG=C) -done -after=$(getmem) -err_exit_if_leak 'Variable with discipline function in subshell causes memory leak' -disabled +DONE # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh index 0f07073d8..a42076f9c 100755 --- a/src/cmd/ksh93/tests/pty.sh +++ b/src/cmd/ksh93/tests/pty.sh @@ -27,8 +27,6 @@ # read the pty manual by running: arch/*/bin/pty --man # # Do not globally set the locale; these tests must pass for all locales. -# -# The # err_exit # comments are to enable shtests to count the tests. # the trickiest part of the tests is avoiding typeahead # in the pty dialogue @@ -101,7 +99,6 @@ then warning "pty command hangs on $bintrue -- tests skipped" exit 0 fi -# err_exit # tst $LINENO <<"!" L POSIX sh 026(C) @@ -125,7 +122,6 @@ w wait u (Killed|Done) ! -# err_exit # tst $LINENO <<"!" L POSIX sh 028(C) @@ -148,7 +144,6 @@ w wait u (Killed|Done) ! -# err_exit # tst $LINENO <<"!" L POSIX sh 029(C) @@ -171,7 +166,6 @@ w wait u (Killed|Done) ! -# err_exit # tst $LINENO <<"!" L POSIX sh 091(C) @@ -188,7 +182,6 @@ w o u ^hello\r?\n$ ! -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L POSIX sh 093(C) @@ -204,7 +197,6 @@ w e u ^goodbye\r?\n$ ! -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L POSIX sh 094(C) @@ -221,7 +213,6 @@ u ^hello\r?\n$ if [[ $(id -u) == 0 ]] then warning "running as root: skipping test POSIX sh 096(C)" else -# err_exit # tst $LINENO <<"!" L POSIX sh 096(C) @@ -251,7 +242,6 @@ r history ! fi -# err_exit # tst $LINENO <<"!" L POSIX sh 097(C) @@ -267,7 +257,6 @@ u ^ok\r?\n$ if [[ $(id -u) == 0 ]] then warning "running as root: skipping test POSIX sh 099(C)" else -# err_exit # tst $LINENO <<"!" L POSIX sh 099(C) @@ -297,7 +286,6 @@ r history ! fi -# err_exit # tst $LINENO <<"!" L POSIX sh 100(C) @@ -313,7 +301,6 @@ w echo ok u ^ok\r?\n$ ! -# err_exit # ((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!" L POSIX sh 101(C) @@ -358,7 +345,6 @@ w echo interrupt=:\cV\cC: u ^interrupt=:\cC:\r?\n$ ! -# err_exit # tst $LINENO <<"!" L POSIX sh 104(C) @@ -378,7 +364,6 @@ u ^done\r?\n$ if [[ $(id -u) == 0 ]] then warning "running as root: skipping test POSIX sh 111(C)" else -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L POSIX sh 111(C) @@ -402,7 +387,6 @@ fi if [[ $(id -u) == 0 ]] then warning "running as root: skipping test POSIX sh 251(C)" else -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L POSIX sh 251(C) @@ -461,7 +445,6 @@ u yes-yes ! disabled -# err_exit # # Test file name completion in vi mode if((SHOPT_VSH)); then mkdir "/tmp/fakehome_$$" && tst $LINENO <test_t.sh <<"EOF" integer n @@ -604,7 +581,6 @@ r ^OK11\r\n$ r ^:test-2: ! -# err_exit # tst $LINENO <<"!" L race condition while launching external commands @@ -623,7 +599,6 @@ r ^/dev/null\r\n$ r ^:test-2: ! -# err_exit # ((SHOPT_ESH)) && [[ -o ?backslashctrl ]] && tst $LINENO <<"!" L nobackslashctrl in emacs @@ -637,7 +612,6 @@ w \cR\\\cH\cH r ^:test-2: \r\n$ ! -# err_exit # ((SHOPT_ESH)) && tst $LINENO <<"!" L emacs backslash escaping @@ -655,7 +629,6 @@ w true \\\cC r true \^C ! -# err_exit # ((SHOPT_VSH)) && touch vi_completion_A_file vi_completion_B_file && tst $LINENO <<"!" L vi filename completion menu @@ -690,7 +663,6 @@ r ^:test-3: ls vi_completion_A_file\r\n$ r ^vi_completion_A_file\r\n$ ! -# err_exit # tst $LINENO <<"!" L syntax error added to history file @@ -706,7 +678,6 @@ r ^:test-2: fc -lN1\r\n$ r \tdo something\r\n$ ! -# err_exit # tst $LINENO <<"!" L value of $? after the shell uses a variable with a discipline function @@ -730,7 +701,6 @@ w echo "Exit status is: $?" u Exit status is: 1 ! -# err_exit # ((SHOPT_ESH)) && ((SHOPT_VSH)) && tst $LINENO <<"!" L crash after switching from emacs to vi mode @@ -751,7 +721,6 @@ r ^:test-2: echo Success\r\n$ r ^Success\r\n$ ! -# err_exit # ((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!" L value of $? after tilde expansion in tab completion @@ -769,7 +738,6 @@ w echo $? ~\t u 42 /tmp ! -# err_exit # ((SHOPT_MULTIBYTE && (SHOPT_VSH || SHOPT_ESH))) && [[ ${LC_ALL:-${LC_CTYPE:-${LANG:-}}} =~ [Uu][Tt][Ff]-?8 ]] && touch $'XXX\xc3\xa1' $'XXX\xc3\xab' && @@ -783,7 +751,6 @@ w : XX\t r ^:test-1: : XXX\r\n$ ! -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L Using b, B, w and W commands in vi mode # https://github.com/att/ast/issues/1467 @@ -797,7 +764,6 @@ r ^:test-2: echo asdf\r\n$ r ^asdf\r\n$ ! -# err_exit # ((SHOPT_ESH)) && mkdir -p emacstest/123abc && VISUAL=emacs tst $LINENO <<"!" L autocomplete stops numeric input # https://github.com/ksh93/ksh/issues/198 @@ -808,7 +774,6 @@ w cd emacste\t123abc r ^:test-1: cd emacstest/123abc\r\n$ ! -# err_exit # echo '((' >$tmp/synerror ENV=$tmp/synerror tst $LINENO <<"!" L syntax error in profile causes exit on startup @@ -822,7 +787,6 @@ r ^:test-1: echo ok\r\n$ r ^ok\r\n$ ! -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L split on quoted whitespace when extracting words from command history # https://github.com/ksh93/ksh/pull/291 @@ -836,7 +800,6 @@ w :\E_ r ^:test-2: : One\\ "Two Three"\$'Four Five'\.mp3\r\n$ ! -# err_exit # ((SHOPT_VSH)) && tst $LINENO <<"!" L crash when entering comment into history file (vi mode) # https://github.com/att/ast/issues/798 @@ -851,7 +814,6 @@ 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 @@ -862,7 +824,6 @@ w test \$\{.sh.level\t r ^:test-1: test \$\{.sh.level\}\r\n$ ! -# err_exit # ((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!" L tab completion executes command substitutions # https://github.com/ksh93/ksh/issues/268 @@ -876,7 +837,6 @@ w `echo true`\t r ^:test-2: `echo true`\r\n$ ! -# err_exit # ((SHOPT_ESH)) && VISUAL=emacs tst $LINENO <<"!" L emacs: keys with repeat parameters repeat extra steps # https://github.com/ksh93/ksh/issues/292 @@ -896,7 +856,6 @@ w : test_string\1\E6\E[C\4 r ^:test-4: : teststring\r\n$ ! -# err_exit # tst $LINENO <<"!" L crash with KEYBD trap after entering multi-line command substitution # https://www.mail-archive.com/ast-users@lists.research.att.com/msg00313.html @@ -907,7 +866,6 @@ w true); echo "Exit status is $?" u Exit status is 0 ! -# err_exit # tst $LINENO <<"!" L interrupted PS2 discipline function # https://github.com/ksh93/ksh/issues/347 @@ -929,7 +887,6 @@ r > \) r one two three end ! -# err_exit # ((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!" L tab completion of '.' and '..' # https://github.com/ksh93/ksh/issues/372 @@ -948,7 +905,6 @@ w : ..\t r : \.\./\r\n$ ! -# err_exit # tst $LINENO <<"!" L Ctrl+C with SIGINT ignored # https://github.com/ksh93/ksh/issues/343 diff --git a/src/cmd/ksh93/tests/shtests b/src/cmd/ksh93/tests/shtests index ee479316d..593281cdf 100755 --- a/src/cmd/ksh93/tests/shtests +++ b/src/cmd/ksh93/tests/shtests @@ -8,7 +8,7 @@ valgrindflags='--xml=yes --log-file=/dev/null --track-origins=yes --read-var-inf USAGE=$' [-s8? -@(#)$Id: shtests (ksh 93u+m) 2021-12-20 $ +@(#)$Id: shtests (ksh 93u+m) 2021-12-28 $ ] [-author?David Korn ] [-author?Glenn Fowler ] @@ -344,6 +344,8 @@ do [[ $i == *.sh ]] || i+='.sh' fi t=$( case $i in glob.sh) grep -c '^[[:blank:]]*test_[a-z]\{3,\}' $i ;; + leaks.sh) grep -c ^TEST $i ;; + pty.sh) grep -c 'tst ' $i ;; *) grep -c err_exit $i ;; esac ) tests[$i]=$t diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index ad90f6667..177c0fdba 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -100,6 +100,10 @@ while whence $TEST_notfound >/dev/null 2>&1 do TEST_notfound=notfound-$RANDOM done +for exp in 65535 65536 +do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1) + [[ $got == $exp ]] || err_exit "large command substitution failed -- expected $exp, got $got" +done integer BS=1024 nb=64 ss=60 bs no for bs in $BS 1