1*b30d1939SAndy Fiddaman######################################################################## 2*b30d1939SAndy Fiddaman# # 3*b30d1939SAndy Fiddaman# This software is part of the ast package # 4*b30d1939SAndy Fiddaman# Copyright (c) 1982-2012 AT&T Intellectual Property # 5*b30d1939SAndy Fiddaman# and is licensed under the # 6*b30d1939SAndy Fiddaman# Eclipse Public License, Version 1.0 # 7*b30d1939SAndy Fiddaman# by AT&T Intellectual Property # 8*b30d1939SAndy Fiddaman# # 9*b30d1939SAndy Fiddaman# A copy of the License is available at # 10*b30d1939SAndy Fiddaman# http://www.eclipse.org/org/documents/epl-v10.html # 11*b30d1939SAndy Fiddaman# (with md5 checksum b35adb5213ca9657e911e9befb180842) # 12*b30d1939SAndy Fiddaman# # 13*b30d1939SAndy Fiddaman# Information and Software Systems Research # 14*b30d1939SAndy Fiddaman# AT&T Research # 15*b30d1939SAndy Fiddaman# Florham Park NJ # 16*b30d1939SAndy Fiddaman# # 17*b30d1939SAndy Fiddaman# David Korn <dgk@research.att.com> # 18*b30d1939SAndy Fiddaman# # 19*b30d1939SAndy Fiddaman######################################################################## 20*b30d1939SAndy Fiddamanfunction err_exit 21*b30d1939SAndy Fiddaman{ 22*b30d1939SAndy Fiddaman print -u$Error_fd -n "\t" 23*b30d1939SAndy Fiddaman print -u$Error_fd -r ${Command}[$1]: "${@:2}" 24*b30d1939SAndy Fiddaman (( Errors+=1 )) 25*b30d1939SAndy Fiddaman} 26*b30d1939SAndy Fiddamanalias err_exit='err_exit $LINENO' 27*b30d1939SAndy Fiddaman 28*b30d1939SAndy FiddamanCommand=${0##*/} 29*b30d1939SAndy Fiddamaninteger Errors=0 Error_fd=2 30*b30d1939SAndy Fiddaman 31*b30d1939SAndy Fiddamantmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 32*b30d1939SAndy Fiddamantrap "cd /; rm -rf $tmp" EXIT 33*b30d1939SAndy Fiddaman 34*b30d1939SAndy Fiddamanbuiltin getconf 35*b30d1939SAndy Fiddamanbincat=$(PATH=$(getconf PATH) whence -p cat) 36*b30d1939SAndy Fiddaman 37*b30d1939SAndy Fiddamanz=() 38*b30d1939SAndy Fiddamanz.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi) 39*b30d1939SAndy Fiddamanz.bar[0]=hello 40*b30d1939SAndy Fiddamanz.bar[2]=world 41*b30d1939SAndy Fiddamanz.bar[1]=(x=4 y=5) 42*b30d1939SAndy Fiddamanval='( 43*b30d1939SAndy Fiddaman typeset -a bar=( 44*b30d1939SAndy Fiddaman [0]=hello 45*b30d1939SAndy Fiddaman [2]=world 46*b30d1939SAndy Fiddaman [1]=( 47*b30d1939SAndy Fiddaman x=4 48*b30d1939SAndy Fiddaman y=5 49*b30d1939SAndy Fiddaman ) 50*b30d1939SAndy Fiddaman ) 51*b30d1939SAndy Fiddaman typeset -A foo=( 52*b30d1939SAndy Fiddaman [one]=hello 53*b30d1939SAndy Fiddaman [three]=hi 54*b30d1939SAndy Fiddaman [two]=( 55*b30d1939SAndy Fiddaman x=3 56*b30d1939SAndy Fiddaman y=4 57*b30d1939SAndy Fiddaman ) 58*b30d1939SAndy Fiddaman ) 59*b30d1939SAndy Fiddaman)' 60*b30d1939SAndy Fiddaman[[ $z == "$val" ]] || err_exit 'compound variable with mixed arrays not working' 61*b30d1939SAndy Fiddamanz.bar[1]=yesyes 62*b30d1939SAndy Fiddaman[[ ${z.bar[1]} == yesyes ]] || err_exit 'reassign of index array compound variable fails' 63*b30d1939SAndy Fiddamanz.bar[1]=(x=12 y=5) 64*b30d1939SAndy Fiddaman[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails' 65*b30d1939SAndy Fiddamaneval val="$z" 66*b30d1939SAndy Fiddaman( 67*b30d1939SAndy Fiddaman z.foo[three]=good 68*b30d1939SAndy Fiddaman [[ ${z.foo[three]} == good ]] || err_exit 'associative array assignment in subshell not working' 69*b30d1939SAndy Fiddaman) 70*b30d1939SAndy Fiddaman[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment' 71*b30d1939SAndy Fiddamaneval val="$z" 72*b30d1939SAndy Fiddaman( 73*b30d1939SAndy Fiddaman z.foo[two]=ok 74*b30d1939SAndy Fiddaman [[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working' 75*b30d1939SAndy Fiddaman z.bar[1]=yes 76*b30d1939SAndy Fiddaman [[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working' 77*b30d1939SAndy Fiddaman) 78*b30d1939SAndy Fiddaman[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment' 79*b30d1939SAndy Fiddaman 80*b30d1939SAndy Fiddamanx=( 81*b30d1939SAndy Fiddaman foo=( qqq=abc rrr=def) 82*b30d1939SAndy Fiddaman bar=( zzz=no rst=fed) 83*b30d1939SAndy Fiddaman) 84*b30d1939SAndy Fiddamaneval val="$x" 85*b30d1939SAndy Fiddaman( 86*b30d1939SAndy Fiddaman unset x.foo 87*b30d1939SAndy Fiddaman [[ ${x.foo.qqq} ]] && err_exit 'x.foo.qqq should be unset' 88*b30d1939SAndy Fiddaman x.foo=good 89*b30d1939SAndy Fiddaman [[ ${x.foo} == good ]] || err_exit 'x.foo should be good' 90*b30d1939SAndy Fiddaman) 91*b30d1939SAndy Fiddaman[[ $x == "$val" ]] || err_exit 'compound variable changes after unset leaves' 92*b30d1939SAndy Fiddamanunset l 93*b30d1939SAndy Fiddaman( 94*b30d1939SAndy Fiddaman l=( a=1 b="BE" ) 95*b30d1939SAndy Fiddaman) 96*b30d1939SAndy Fiddaman[[ ${l+foo} != foo ]] || err_exit 'l should be unset' 97*b30d1939SAndy Fiddaman 98*b30d1939SAndy FiddamanError_fd=9 99*b30d1939SAndy Fiddamaneval "exec $Error_fd>&2 2>/dev/null" 100*b30d1939SAndy Fiddaman 101*b30d1939SAndy FiddamanTEST_notfound=notfound 102*b30d1939SAndy Fiddamanwhile whence $TEST_notfound >/dev/null 2>&1 103*b30d1939SAndy Fiddamando TEST_notfound=notfound-$RANDOM 104*b30d1939SAndy Fiddamandone 105*b30d1939SAndy Fiddaman 106*b30d1939SAndy Fiddaman 107*b30d1939SAndy Fiddamaninteger BS=1024 nb=64 ss=60 bs no 108*b30d1939SAndy Fiddamanfor bs in $BS 1 109*b30d1939SAndy Fiddamando $SHELL -c ' 110*b30d1939SAndy Fiddaman { 111*b30d1939SAndy Fiddaman sleep '$ss' 112*b30d1939SAndy Fiddaman kill -KILL $$ 113*b30d1939SAndy Fiddaman } & 114*b30d1939SAndy Fiddaman set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs') 115*b30d1939SAndy Fiddaman print ${#1} 116*b30d1939SAndy Fiddaman kill $! 117*b30d1939SAndy Fiddaman ' > $tmp/sub 2>/dev/null 118*b30d1939SAndy Fiddaman no=$(<$tmp/sub) 119*b30d1939SAndy Fiddaman (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}" 120*b30d1939SAndy Fiddamandone 121*b30d1939SAndy Fiddaman# this time with redirection on the trailing command 122*b30d1939SAndy Fiddamanfor bs in $BS 1 123*b30d1939SAndy Fiddamando $SHELL -c ' 124*b30d1939SAndy Fiddaman { 125*b30d1939SAndy Fiddaman sleep 2 126*b30d1939SAndy Fiddaman sleep '$ss' 127*b30d1939SAndy Fiddaman kill -KILL $$ 128*b30d1939SAndy Fiddaman } & 129*b30d1939SAndy Fiddaman set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null) 130*b30d1939SAndy Fiddaman print ${#1} 131*b30d1939SAndy Fiddaman kill $! 132*b30d1939SAndy Fiddaman ' > $tmp/sub 2>/dev/null 133*b30d1939SAndy Fiddaman no=$(<$tmp/sub) 134*b30d1939SAndy Fiddaman (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs and trailing redirection -- expected $((BS*nb)), got ${no:-0}" 135*b30d1939SAndy Fiddamandone 136*b30d1939SAndy Fiddaman 137*b30d1939SAndy Fiddaman# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io 138*b30d1939SAndy Fiddaman 139*b30d1939SAndy Fiddamanset -- \ 140*b30d1939SAndy Fiddaman 'post-line print' \ 141*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; print 1); print' \ 142*b30d1939SAndy Fiddaman 1 \ 143*b30d1939SAndy Fiddaman 'pre-line print' \ 144*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; print); print 1' \ 145*b30d1939SAndy Fiddaman $'\n1' \ 146*b30d1939SAndy Fiddaman 'multiple pre-line print' \ 147*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print' \ 148*b30d1939SAndy Fiddaman $'\n\n1' \ 149*b30d1939SAndy Fiddaman 'multiple post-line print' \ 150*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print' \ 151*b30d1939SAndy Fiddaman 1 \ 152*b30d1939SAndy Fiddaman 'intermediate print' \ 153*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print' \ 154*b30d1939SAndy Fiddaman $'1\n\n2' \ 155*b30d1939SAndy Fiddaman 'simple variable' \ 156*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l' \ 157*b30d1939SAndy Fiddaman 2 \ 158*b30d1939SAndy Fiddaman 'compound variable' \ 159*b30d1939SAndy Fiddaman '$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l' \ 160*b30d1939SAndy Fiddaman $'(\n\ta=2\n\tb=BE\n)' \ 161*b30d1939SAndy Fiddaman 162*b30d1939SAndy Fiddamanexport TEST_fork TEST_unset 163*b30d1939SAndy Fiddaman 164*b30d1939SAndy Fiddamanwhile (( $# >= 3 )) 165*b30d1939SAndy Fiddamando txt=$1 166*b30d1939SAndy Fiddaman cmd=$2 167*b30d1939SAndy Fiddaman exp=$3 168*b30d1939SAndy Fiddaman shift 3 169*b30d1939SAndy Fiddaman for TEST_unset in '' 'unset var' 170*b30d1939SAndy Fiddaman do for TEST_fork in '' 'ulimit -c 0' 171*b30d1939SAndy Fiddaman do for TEST_shell in "eval" "$SHELL -c" 172*b30d1939SAndy Fiddaman do if ! got=$($TEST_shell "$cmd") 173*b30d1939SAndy Fiddaman then err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed" 174*b30d1939SAndy Fiddaman elif [[ "$got" != "$exp" ]] 175*b30d1939SAndy Fiddaman then EXP=$(printf %q "$exp") 176*b30d1939SAndy Fiddaman GOT=$(printf %q "$got") 177*b30d1939SAndy Fiddaman err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT" 178*b30d1939SAndy Fiddaman fi 179*b30d1939SAndy Fiddaman done 180*b30d1939SAndy Fiddaman done 181*b30d1939SAndy Fiddaman done 182*b30d1939SAndy Fiddamandone 183*b30d1939SAndy Fiddaman 184*b30d1939SAndy Fiddamanr=$( ($SHELL -c ' 185*b30d1939SAndy Fiddaman { 186*b30d1939SAndy Fiddaman sleep 32 187*b30d1939SAndy Fiddaman kill -KILL $$ 188*b30d1939SAndy Fiddaman } & 189*b30d1939SAndy Fiddaman for v in $(set | sed "s/=.*//") 190*b30d1939SAndy Fiddaman do command unset $v 191*b30d1939SAndy Fiddaman done 192*b30d1939SAndy Fiddaman typeset -Z5 I 193*b30d1939SAndy Fiddaman for ((I = 0; I < 1024; I++)) 194*b30d1939SAndy Fiddaman do eval A$I=1234567890 195*b30d1939SAndy Fiddaman done 196*b30d1939SAndy Fiddaman a=$(set 2>&1) 197*b30d1939SAndy Fiddaman print ok 198*b30d1939SAndy Fiddaman kill -KILL $! 199*b30d1939SAndy Fiddaman') 2>/dev/null) 200*b30d1939SAndy Fiddaman[[ $r == ok ]] || err_exit "large subshell command substitution hangs" 201*b30d1939SAndy Fiddaman 202*b30d1939SAndy Fiddamanfor TEST_command in '' $TEST_notfound 203*b30d1939SAndy Fiddamando for TEST_exec in '' 'exec' 204*b30d1939SAndy Fiddaman do for TEST_fork in '' 'ulimit -c 0;' 205*b30d1939SAndy Fiddaman do for TEST_redirect in '' '>/dev/null' 206*b30d1939SAndy Fiddaman do for TEST_substitute in '' ': $' 207*b30d1939SAndy Fiddaman do 208*b30d1939SAndy Fiddaman 209*b30d1939SAndy Fiddaman TEST_test="$TEST_substitute($TEST_fork $TEST_exec $TEST_command $TEST_redirect)" 210*b30d1939SAndy Fiddaman [[ $TEST_test == '('*([[:space:]])')' ]] && continue 211*b30d1939SAndy Fiddaman r=$($SHELL -c ' 212*b30d1939SAndy Fiddaman { 213*b30d1939SAndy Fiddaman sleep 2 214*b30d1939SAndy Fiddaman kill -KILL $$ 215*b30d1939SAndy Fiddaman } & 216*b30d1939SAndy Fiddaman '"$TEST_test"' 217*b30d1939SAndy Fiddaman kill $! 218*b30d1939SAndy Fiddaman print ok 219*b30d1939SAndy Fiddaman ') 220*b30d1939SAndy Fiddaman [[ $r == ok ]] || err_exit "shell hangs on $TEST_test" 221*b30d1939SAndy Fiddaman 222*b30d1939SAndy Fiddaman done 223*b30d1939SAndy Fiddaman done 224*b30d1939SAndy Fiddaman done 225*b30d1939SAndy Fiddaman done 226*b30d1939SAndy Fiddamandone 227*b30d1939SAndy Fiddaman 228*b30d1939SAndy Fiddaman$SHELL -c '( autoload xxxxx);print -n' || err_exit 'autoloaded functions in subshells can cause failure' 229*b30d1939SAndy Fiddamanfoo=$($SHELL <<- ++EOF++ 230*b30d1939SAndy Fiddaman (trap 'print bar' EXIT;print -n foo) 231*b30d1939SAndy Fiddaman ++EOF++ 232*b30d1939SAndy Fiddaman) 233*b30d1939SAndy Fiddaman[[ $foo == foobar ]] || err_exit 'trap on exit when last commands is subshell is not triggered' 234*b30d1939SAndy Fiddaman 235*b30d1939SAndy Fiddamanerr=$( 236*b30d1939SAndy Fiddaman $SHELL 2>&1 <<- \EOF 237*b30d1939SAndy Fiddaman date=$(whence -p date) 238*b30d1939SAndy Fiddaman function foo 239*b30d1939SAndy Fiddaman { 240*b30d1939SAndy Fiddaman x=$( $date > /dev/null 2>&1 ;:) 241*b30d1939SAndy Fiddaman } 242*b30d1939SAndy Fiddaman # consume almost all fds to push the test to the fd limit # 243*b30d1939SAndy Fiddaman integer max=$(ulimit --nofile) 244*b30d1939SAndy Fiddaman (( max -= 6 )) 245*b30d1939SAndy Fiddaman for ((i=20; i < max; i++)) 246*b30d1939SAndy Fiddaman do exec {i}>&1 247*b30d1939SAndy Fiddaman done 248*b30d1939SAndy Fiddaman for ((i=0; i < 20; i++)) 249*b30d1939SAndy Fiddaman do y=$(foo) 250*b30d1939SAndy Fiddaman done 251*b30d1939SAndy Fiddaman EOF 252*b30d1939SAndy Fiddaman) || { 253*b30d1939SAndy Fiddaman err=${err%%$'\n'*} 254*b30d1939SAndy Fiddaman err=${err#*:} 255*b30d1939SAndy Fiddaman err=${err##[[:space:]]} 256*b30d1939SAndy Fiddaman err_exit "nested command substitution with redirections failed -- $err" 257*b30d1939SAndy Fiddaman} 258*b30d1939SAndy Fiddaman 259*b30d1939SAndy Fiddamanexp=0 260*b30d1939SAndy Fiddaman$SHELL -c $' 261*b30d1939SAndy Fiddaman function foobar 262*b30d1939SAndy Fiddaman { 263*b30d1939SAndy Fiddaman print "hello world" 264*b30d1939SAndy Fiddaman } 265*b30d1939SAndy Fiddaman [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]] 266*b30d1939SAndy Fiddaman exit '$exp$' 267*b30d1939SAndy Fiddaman' 268*b30d1939SAndy Fiddamangot=$? 269*b30d1939SAndy Fiddaman[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'" 270*b30d1939SAndy Fiddamanexp=ok 271*b30d1939SAndy Fiddamangot=$($SHELL -c $' 272*b30d1939SAndy Fiddaman function foobar 273*b30d1939SAndy Fiddaman { 274*b30d1939SAndy Fiddaman print "hello world" 275*b30d1939SAndy Fiddaman } 276*b30d1939SAndy Fiddaman [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]] 277*b30d1939SAndy Fiddaman print '$exp$' 278*b30d1939SAndy Fiddaman') 279*b30d1939SAndy Fiddaman[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'" 280*b30d1939SAndy Fiddaman 281*b30d1939SAndy Fiddaman# command substitution variations # 282*b30d1939SAndy Fiddamanset -- \ 283*b30d1939SAndy Fiddaman '$(' ')' \ 284*b30d1939SAndy Fiddaman '${ ' '; }' \ 285*b30d1939SAndy Fiddaman '$(ulimit -c 0; ' ')' \ 286*b30d1939SAndy Fiddaman '$( (' ') )' \ 287*b30d1939SAndy Fiddaman '${ (' '); }' \ 288*b30d1939SAndy Fiddaman '`' '`' \ 289*b30d1939SAndy Fiddaman '`(' ')`' \ 290*b30d1939SAndy Fiddaman '`ulimit -c 0; ' '`' \ 291*b30d1939SAndy Fiddaman # end of table # 292*b30d1939SAndy Fiddamanexp=ok 293*b30d1939SAndy Fiddamantestcase[1]=' 294*b30d1939SAndy Fiddaman if %sexpr "NOMATCH" : ".*Z" >/dev/null%s 295*b30d1939SAndy Fiddaman then print error 296*b30d1939SAndy Fiddaman else print ok 297*b30d1939SAndy Fiddaman fi 298*b30d1939SAndy Fiddaman exit %s 299*b30d1939SAndy Fiddaman' 300*b30d1939SAndy Fiddamantestcase[2]=' 301*b30d1939SAndy Fiddaman function bar 302*b30d1939SAndy Fiddaman { 303*b30d1939SAndy Fiddaman pipeout=%1$sprintf Ok | tr O o%2$s 304*b30d1939SAndy Fiddaman print $pipeout 305*b30d1939SAndy Fiddaman return 0 306*b30d1939SAndy Fiddaman } 307*b30d1939SAndy Fiddaman foo=%1$sbar%2$s || foo="exit status $?" 308*b30d1939SAndy Fiddaman print $foo 309*b30d1939SAndy Fiddaman exit %3$s 310*b30d1939SAndy Fiddaman' 311*b30d1939SAndy Fiddamanwhile (( $# >= 2 )) 312*b30d1939SAndy Fiddamando for ((TEST=1; TEST<=${#testcase[@]}; TEST++)) 313*b30d1939SAndy Fiddaman do body=${testcase[TEST]} 314*b30d1939SAndy Fiddaman for code in 0 2 315*b30d1939SAndy Fiddaman do got=${ printf "$body" "$1" "$2" "$code" | $SHELL 2>&1 } 316*b30d1939SAndy Fiddaman status=$? 317*b30d1939SAndy Fiddaman if (( status != code )) 318*b30d1939SAndy Fiddaman then err_exit "test $TEST '$1...$2 exit $code' failed -- exit status $status, expected $code" 319*b30d1939SAndy Fiddaman elif [[ $got != $exp ]] 320*b30d1939SAndy Fiddaman then err_exit "test $TEST '$1...$2 exit $code' failed -- got '$got', expected '$exp'" 321*b30d1939SAndy Fiddaman fi 322*b30d1939SAndy Fiddaman done 323*b30d1939SAndy Fiddaman done 324*b30d1939SAndy Fiddaman shift 2 325*b30d1939SAndy Fiddamandone 326*b30d1939SAndy Fiddaman 327*b30d1939SAndy Fiddaman# the next tests loop on all combinations of 328*b30d1939SAndy Fiddaman# { SUB CAT INS TST APP } X { file-sizes } 329*b30d1939SAndy Fiddaman# where the file size starts at 1Ki and doubles up to and including 1Mi 330*b30d1939SAndy Fiddaman# 331*b30d1939SAndy Fiddaman# the tests and timeouts are done in async subshells to prevent 332*b30d1939SAndy Fiddaman# the test harness from hanging 333*b30d1939SAndy Fiddaman 334*b30d1939SAndy FiddamanSUB=( 335*b30d1939SAndy Fiddaman ( BEG='$( ' END=' )' ) 336*b30d1939SAndy Fiddaman ( BEG='${ ' END='; }' ) 337*b30d1939SAndy Fiddaman) 338*b30d1939SAndy FiddamanCAT=( cat $bincat ) 339*b30d1939SAndy FiddamanINS=( "" "builtin cat; " "builtin -d cat $bincat; " ": > /dev/null; " ) 340*b30d1939SAndy FiddamanAPP=( "" "; :" ) 341*b30d1939SAndy FiddamanTST=( 342*b30d1939SAndy Fiddaman ( CMD='print foo | $cat' EXP=3 ) 343*b30d1939SAndy Fiddaman ( CMD='$cat < $tmp/lin' ) 344*b30d1939SAndy Fiddaman ( CMD='cat $tmp/lin | $cat' ) 345*b30d1939SAndy Fiddaman ( CMD='read v < $tmp/buf; print $v' LIM=4*1024 ) 346*b30d1939SAndy Fiddaman ( CMD='cat $tmp/buf | read v; print $v' LIM=4*1024 ) 347*b30d1939SAndy Fiddaman) 348*b30d1939SAndy Fiddaman 349*b30d1939SAndy Fiddamanif cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null 350*b30d1939SAndy Fiddamanthen T=${#TST[@]} 351*b30d1939SAndy Fiddaman TST[T].CMD='$cat <(print foo)' 352*b30d1939SAndy Fiddaman TST[T].EXP=3 353*b30d1939SAndy Fiddamanfi 354*b30d1939SAndy Fiddaman 355*b30d1939SAndy Fiddaman# prime the two data files to 512 bytes each 356*b30d1939SAndy Fiddaman# $tmp/lin has newlines every 16 bytes and $tmp/buf has no newlines 357*b30d1939SAndy Fiddaman# the outer loop doubles the file size at top 358*b30d1939SAndy Fiddaman 359*b30d1939SAndy Fiddamanbuf=$'1234567890abcdef' 360*b30d1939SAndy Fiddamanlin=$'\n1234567890abcde' 361*b30d1939SAndy Fiddamanfor ((i=0; i<5; i++)) 362*b30d1939SAndy Fiddamando buf=$buf$buf 363*b30d1939SAndy Fiddaman lin=$lin$lin 364*b30d1939SAndy Fiddamandone 365*b30d1939SAndy Fiddamanprint -n "$buf" > $tmp/buf 366*b30d1939SAndy Fiddamanprint -n "$lin" > $tmp/lin 367*b30d1939SAndy Fiddaman 368*b30d1939SAndy Fiddamanunset SKIP 369*b30d1939SAndy Fiddamanfor ((n=1024; n<=1024*1024; n*=2)) 370*b30d1939SAndy Fiddamando cat $tmp/buf $tmp/buf > $tmp/tmp 371*b30d1939SAndy Fiddaman mv $tmp/tmp $tmp/buf 372*b30d1939SAndy Fiddaman cat $tmp/lin $tmp/lin > $tmp/tmp 373*b30d1939SAndy Fiddaman mv $tmp/tmp $tmp/lin 374*b30d1939SAndy Fiddaman for ((S=0; S<${#SUB[@]}; S++)) 375*b30d1939SAndy Fiddaman do for ((C=0; C<${#CAT[@]}; C++)) 376*b30d1939SAndy Fiddaman do cat=${CAT[C]} 377*b30d1939SAndy Fiddaman for ((I=0; I<${#INS[@]}; I++)) 378*b30d1939SAndy Fiddaman do for ((A=0; A<${#APP[@]}; A++)) 379*b30d1939SAndy Fiddaman do for ((T=0; T<${#TST[@]}; T++)) 380*b30d1939SAndy Fiddaman do #undent...# 381*b30d1939SAndy Fiddaman 382*b30d1939SAndy Fiddaman if [[ ! ${SKIP[S][C][I][A][T]} ]] 383*b30d1939SAndy Fiddaman then eval "{ x=${SUB[S].BEG}${INS[I]}${TST[T].CMD}${APP[A]}${SUB[S].END}; print \${#x}; } >\$tmp/out &" 384*b30d1939SAndy Fiddaman m=$! 385*b30d1939SAndy Fiddaman { sleep 4; kill -9 $m; } & 386*b30d1939SAndy Fiddaman k=$! 387*b30d1939SAndy Fiddaman wait $m 388*b30d1939SAndy Fiddaman h=$? 389*b30d1939SAndy Fiddaman kill -9 $k 390*b30d1939SAndy Fiddaman wait $k 391*b30d1939SAndy Fiddaman got=$(<$tmp/out) 392*b30d1939SAndy Fiddaman if [[ ! $got ]] && (( h )) 393*b30d1939SAndy Fiddaman then got=HUNG 394*b30d1939SAndy Fiddaman fi 395*b30d1939SAndy Fiddaman if [[ ${TST[T].EXP} ]] 396*b30d1939SAndy Fiddaman then exp=${TST[T].EXP} 397*b30d1939SAndy Fiddaman else exp=$n 398*b30d1939SAndy Fiddaman fi 399*b30d1939SAndy Fiddaman if [[ $got != $exp ]] 400*b30d1939SAndy Fiddaman then # on failure skip similar tests on larger files sizes # 401*b30d1939SAndy Fiddaman SKIP[S][C][I][A][T]=1 402*b30d1939SAndy Fiddaman siz=$(printf $'%#i' $exp) 403*b30d1939SAndy Fiddaman cmd=${TST[T].CMD//\$cat/$cat} 404*b30d1939SAndy Fiddaman cmd=${cmd//\$tmp\/buf/$siz.buf} 405*b30d1939SAndy Fiddaman cmd=${cmd//\$tmp\/lin/$siz.lin} 406*b30d1939SAndy Fiddaman err_exit "'x=${SUB[S].BEG}${INS[I]}${cmd}${APP[A]}${SUB[S].END} && print \${#x}' failed -- expected '$exp', got '$got'" 407*b30d1939SAndy Fiddaman elif [[ ${TST[T].EXP} ]] || (( TST[T].LIM >= n )) 408*b30d1939SAndy Fiddaman then SKIP[S][C][I][A][T]=1 409*b30d1939SAndy Fiddaman fi 410*b30d1939SAndy Fiddaman fi 411*b30d1939SAndy Fiddaman 412*b30d1939SAndy Fiddaman #...indent# 413*b30d1939SAndy Fiddaman done 414*b30d1939SAndy Fiddaman done 415*b30d1939SAndy Fiddaman done 416*b30d1939SAndy Fiddaman done 417*b30d1939SAndy Fiddaman done 418*b30d1939SAndy Fiddamandone 419*b30d1939SAndy Fiddaman 420*b30d1939SAndy Fiddaman# specifics -- there's more? 421*b30d1939SAndy Fiddaman 422*b30d1939SAndy Fiddaman{ 423*b30d1939SAndy Fiddaman cmd='{ exec 5>/dev/null; print "$(eval ls -d . 2>&1 1>&5)"; } >$tmp/out &' 424*b30d1939SAndy Fiddaman eval $cmd 425*b30d1939SAndy Fiddaman m=$! 426*b30d1939SAndy Fiddaman { sleep 4; kill -9 $m; } & 427*b30d1939SAndy Fiddaman k=$! 428*b30d1939SAndy Fiddaman wait $m 429*b30d1939SAndy Fiddaman h=$? 430*b30d1939SAndy Fiddaman kill -9 $k 431*b30d1939SAndy Fiddaman wait $k 432*b30d1939SAndy Fiddaman got=$(<$tmp/out) 433*b30d1939SAndy Fiddaman} 2>/dev/null 434*b30d1939SAndy Fiddamanexp='' 435*b30d1939SAndy Fiddamanif [[ ! $got ]] && (( h )) 436*b30d1939SAndy Fiddamanthen got=HUNG 437*b30d1939SAndy Fiddamanfi 438*b30d1939SAndy Fiddamanif [[ $got != $exp ]] 439*b30d1939SAndy Fiddamanthen err_exit "eval '$cmd' failed -- expected '$exp', got '$got'" 440*b30d1939SAndy Fiddamanfi 441*b30d1939SAndy Fiddaman 442*b30d1939SAndy Fiddamanfloat t1=$SECONDS 443*b30d1939SAndy Fiddamansleep=$(whence -p sleep) 444*b30d1939SAndy Fiddamanif [[ $sleep ]] 445*b30d1939SAndy Fiddamanthen 446*b30d1939SAndy Fiddaman $SHELL -c "( $sleep 5 </dev/null >/dev/null 2>&1 & );exit 0" | cat 447*b30d1939SAndy Fiddaman (( (SECONDS-t1) > 4 )) && err_exit '/bin/sleep& in subshell hanging' 448*b30d1939SAndy Fiddaman ((t1=SECONDS)) 449*b30d1939SAndy Fiddamanfi 450*b30d1939SAndy Fiddaman$SHELL -c '( sleep 5 </dev/null >/dev/null 2>&1 & );exit 0' | cat 451*b30d1939SAndy Fiddaman(( (SECONDS-t1) > 4 )) && err_exit 'sleep& in subshell hanging' 452*b30d1939SAndy Fiddaman 453*b30d1939SAndy Fiddamanexp=HOME=$HOME 454*b30d1939SAndy Fiddaman( HOME=/bin/sh ) 455*b30d1939SAndy Fiddamangot=$(env | grep ^HOME=) 456*b30d1939SAndy Fiddaman[[ $got == "$exp" ]] || err_exit "( HOME=/bin/sh ) cleanup failed -- expected '$exp', got '$got'" 457*b30d1939SAndy Fiddaman 458*b30d1939SAndy Fiddamancmd='echo $((case x in x)echo ok;esac);:)' 459*b30d1939SAndy Fiddamanexp=ok 460*b30d1939SAndy Fiddamangot=$($SHELL -c "$cmd" 2>&1) 461*b30d1939SAndy Fiddaman[[ $got == "$exp" ]] || err_exit "'$cmd' failed -- expected '$exp', got '$got'" 462*b30d1939SAndy Fiddaman 463*b30d1939SAndy Fiddamancmd='eval "for i in 1 2; do eval /bin/echo x; done"' 464*b30d1939SAndy Fiddamanexp=$'x\nx' 465*b30d1939SAndy Fiddamangot=$($SHELL -c "$cmd") 466*b30d1939SAndy Fiddamanif [[ $got != "$exp" ]] 467*b30d1939SAndy Fiddamanthen EXP=$(printf %q "$exp") 468*b30d1939SAndy Fiddaman GOT=$(printf %q "$got") 469*b30d1939SAndy Fiddaman err_exit "'$cmd' failed -- expected $EXP, got $GOT" 470*b30d1939SAndy Fiddamanfi 471*b30d1939SAndy Fiddaman 472*b30d1939SAndy Fiddaman( 473*b30d1939SAndy Fiddaman$SHELL -c 'sleep 20 & pid=$!; { x=$( ( seq 60000 ) );kill -9 $pid;}&;wait $pid' 474*b30d1939SAndy Fiddaman) 2> /dev/null 475*b30d1939SAndy Fiddaman(( $? )) || err_exit 'nested command substitution with large output hangs' 476*b30d1939SAndy Fiddaman 477*b30d1939SAndy Fiddaman(.sh.foo=foobar) 478*b30d1939SAndy Fiddaman[[ ${.sh.foo} == foobar ]] && err_exit '.sh subvariables in subshells remain set' 479*b30d1939SAndy Fiddaman[[ $($SHELL -c 'print 1 | : "$(/bin/cat <(/bin/cat))"') ]] && err_exit 'process substitution not working correctly in subshells' 480*b30d1939SAndy Fiddaman 481*b30d1939SAndy Fiddaman# config hang bug 482*b30d1939SAndy Fiddamaninteger i 483*b30d1939SAndy Fiddamanfor ((i=1; i < 1000; i++)) 484*b30d1939SAndy Fiddamando typeset foo$i=$i 485*b30d1939SAndy Fiddamandone 486*b30d1939SAndy Fiddaman{ 487*b30d1939SAndy Fiddaman : $( (ac_space=' '; set | grep ac_space) 2>&1) 488*b30d1939SAndy Fiddaman} < /dev/null | cat > /dev/null & 489*b30d1939SAndy Fiddamansleep 1.5 490*b30d1939SAndy Fiddamanif kill -KILL $! 2> /dev/null 491*b30d1939SAndy Fiddamanthen err_exit 'process timed out with hung comsub' 492*b30d1939SAndy Fiddamanfi 493*b30d1939SAndy Fiddamanwait $! 2> /dev/null 494*b30d1939SAndy Fiddaman(( $? > 128 )) && err_exit 'incorrect exit status with comsub' 495*b30d1939SAndy Fiddaman 496*b30d1939SAndy Fiddaman$SHELL 2> /dev/null -c '[[ ${ print foo },${ print bar } == foo,bar ]]' || err_exit '${ print foo },${ print bar } not working' 497*b30d1939SAndy Fiddaman$SHELL 2> /dev/null -c '[[ ${ print foo; },${ print bar } == foo,bar ]]' || err_exit '${ print foo; },${ print bar } not working' 498*b30d1939SAndy Fiddaman 499*b30d1939SAndy Fiddamansrc=$'true 2>&1\n: $(true | true)\n: $(true | true)\n: $(true | true)\n'$(whence -p true) 500*b30d1939SAndy Fiddamanexp=ok 501*b30d1939SAndy Fiddamangot=$( $SHELL -c "(eval '$src'); echo $exp" ) 502*b30d1939SAndy Fiddaman[[ $got == "$exp" ]] || err_exit 'subshell eval of pipeline clobbers stdout' 503*b30d1939SAndy Fiddaman 504*b30d1939SAndy Fiddamanx=$( { time $SHELL -c date >| /dev/null;} 2>&1) 505*b30d1939SAndy Fiddaman[[ $x == *real*user*sys* ]] || err_exit 'time { ...;} 2>&1 in $(...) fails' 506*b30d1939SAndy Fiddaman 507*b30d1939SAndy Fiddamanx=$($SHELL -c '( function fx { export X=123; } ; fx; ); echo $X') 508*b30d1939SAndy Fiddaman[[ $x == 123 ]] && err_exit 'global variables set from with functions inside a 509*b30d1939SAndy Fiddamansubshell can leave side effects in parent shell' 510*b30d1939SAndy Fiddaman 511*b30d1939SAndy Fiddamandate=$(whence -p date) 512*b30d1939SAndy Fiddamanerr() { return $1; } 513*b30d1939SAndy Fiddaman( err 12 ) & pid=$! 514*b30d1939SAndy Fiddaman: $( $date) 515*b30d1939SAndy Fiddamanwait $pid 516*b30d1939SAndy Fiddaman[[ $? == 12 ]] || err_exit 'exit status from subshells not being preserved' 517*b30d1939SAndy Fiddaman 518*b30d1939SAndy Fiddamanif cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null 519*b30d1939SAndy Fiddamanthen x="$(sed 's/^/Hello /' <(print "Fred" | sort))" 520*b30d1939SAndy Fiddaman [[ $x == 'Hello Fred' ]] || err_exit "process substitution of pipeline in command substitution not working" 521*b30d1939SAndy Fiddamanfi 522*b30d1939SAndy Fiddaman 523*b30d1939SAndy Fiddaman{ 524*b30d1939SAndy Fiddaman$SHELL <<- \EOF 525*b30d1939SAndy Fiddaman function foo 526*b30d1939SAndy Fiddaman { 527*b30d1939SAndy Fiddaman integer i 528*b30d1939SAndy Fiddaman print -u2 foobar 529*b30d1939SAndy Fiddaman for ((i=0; i < 8000; i++)) 530*b30d1939SAndy Fiddaman do print abcdefghijk 531*b30d1939SAndy Fiddaman done 532*b30d1939SAndy Fiddaman print -u2 done 533*b30d1939SAndy Fiddaman } 534*b30d1939SAndy Fiddaman out=$(eval "foo | cat" 2>&1) 535*b30d1939SAndy Fiddaman (( ${#out} == 96011 )) || err_exit "\${#out} is ${#out} should be 96011" 536*b30d1939SAndy FiddamanEOF 537*b30d1939SAndy Fiddaman} & pid=$! 538*b30d1939SAndy Fiddaman$SHELL -c "{ sleep 4 && kill $pid ;}" 2> /dev/null 539*b30d1939SAndy Fiddaman(( $? == 0 )) && err_exit 'process has hung' 540*b30d1939SAndy Fiddaman 541*b30d1939SAndy Fiddaman{ 542*b30d1939SAndy Fiddamanx=$( $SHELL <<- \EOF 543*b30d1939SAndy Fiddaman function func1 { typeset IFS; : $(func2); print END ;} 544*b30d1939SAndy Fiddaman function func2 { IFS="BAR"; } 545*b30d1939SAndy Fiddaman func1 546*b30d1939SAndy Fiddaman func1 547*b30d1939SAndy FiddamanEOF 548*b30d1939SAndy Fiddaman) 549*b30d1939SAndy Fiddaman} 2> /dev/null 550*b30d1939SAndy Fiddaman[[ $x == $'END\nEND' ]] || err_exit 'bug in save/restore of IFS in subshell' 551*b30d1939SAndy Fiddaman 552*b30d1939SAndy Fiddamantrue=$(whence -p true) 553*b30d1939SAndy Fiddamandate=$(whence -p date) 554*b30d1939SAndy Fiddamantmpf=$tmp/foo 555*b30d1939SAndy Fiddamanfunction fun1 556*b30d1939SAndy Fiddaman{ 557*b30d1939SAndy Fiddaman $true 558*b30d1939SAndy Fiddaman cd - >/dev/null 2>&1 559*b30d1939SAndy Fiddaman print -u2 -- "$($date) SUCCESS" 560*b30d1939SAndy Fiddaman} 561*b30d1939SAndy Fiddaman 562*b30d1939SAndy Fiddamanprint -n $(fun1 2> $tmpf) 563*b30d1939SAndy Fiddaman[[ $(< $tmpf) == *SUCCESS ]] || err_exit 'standard error output lost with command substitution' 564*b30d1939SAndy Fiddaman 565*b30d1939SAndy Fiddaman 566*b30d1939SAndy Fiddamantmpfile=$tmp/foo 567*b30d1939SAndy Fiddamancat > $tmpfile <<-\EOF 568*b30d1939SAndy Fiddaman $SHELL -c 'function g { IFS= ;};function f { typeset IFS;(g);: $V;};f;f' 569*b30d1939SAndy Fiddaman EOF 570*b30d1939SAndy Fiddaman$SHELL 2> /dev/null "$tmpfile" || err_exit 'IFS in subshell causes core dump' 571*b30d1939SAndy Fiddaman 572*b30d1939SAndy Fiddamanunset i 573*b30d1939SAndy Fiddamanif [[ -d /dev/fd ]] 574*b30d1939SAndy Fiddamanthen integer i 575*b30d1939SAndy Fiddaman for ((i=11; i < 29; i++)) 576*b30d1939SAndy Fiddaman do if ! [[ -r /dev/fd/$i || -w /dev/fd/$i ]] 577*b30d1939SAndy Fiddaman then a=$($SHELL -c "[[ -r /dev/fd/$i || -w /dev/fd/$i ]]") 578*b30d1939SAndy Fiddaman (( $? )) || err_exit "file descriptor $i not close on exec" 579*b30d1939SAndy Fiddaman fi 580*b30d1939SAndy Fiddaman done 581*b30d1939SAndy Fiddamanfi 582*b30d1939SAndy Fiddaman 583*b30d1939SAndy Fiddamantrap USR1 USR1 584*b30d1939SAndy Fiddamantrap ERR ERR 585*b30d1939SAndy Fiddaman[[ $(trap -p USR1) == USR1 ]] || err_exit 'trap -p USR1 in subshell not working' 586*b30d1939SAndy Fiddaman[[ $(trap -p ERR) == ERR ]] || err_exit 'trap -p ERR in subshell not working' 587*b30d1939SAndy Fiddaman[[ $(trap -p) == *USR* ]] || err_exit 'trap -p in subshell does not contain USR' 588*b30d1939SAndy Fiddaman[[ $(trap -p) == *ERR* ]] || err_exit 'trap -p in subshell does not contain ERR' 589*b30d1939SAndy Fiddamantrap - USR1 ERR 590*b30d1939SAndy Fiddaman 591*b30d1939SAndy Fiddaman( PATH=/bin:/usr/bin 592*b30d1939SAndy Fiddamandot=$(cat <<-EOF 593*b30d1939SAndy Fiddaman $(ls -d .) 594*b30d1939SAndy Fiddaman EOF 595*b30d1939SAndy Fiddaman) ) & sleep 1 596*b30d1939SAndy Fiddamanif kill -0 $! 2> /dev/null 597*b30d1939SAndy Fiddamanthen err_exit 'command substitution containg here-doc with command substitution fails' 598*b30d1939SAndy Fiddamanfi 599*b30d1939SAndy Fiddaman 600*b30d1939SAndy Fiddamanprintf=$(whence -p printf) 601*b30d1939SAndy Fiddaman[[ $( { trap "echo foobar" EXIT; ( $printf ""); } & wait) == foobar ]] || err_exit 'exit trap not being invoked' 602*b30d1939SAndy Fiddaman 603*b30d1939SAndy Fiddaman$SHELL 2> /dev/null -c '( PATH=/bin; set -o restricted) ; exit 0' || err_exit 'restoring PATH when a subshell enables restricted exits not working' 604*b30d1939SAndy Fiddaman 605*b30d1939SAndy Fiddaman$SHELL <<- \EOF 606*b30d1939SAndy Fiddaman wc=$(whence wc) head=$(whence head) 607*b30d1939SAndy Fiddaman print > /dev/null $( ( $head -c 1 /dev/zero | ( $wc -c) 3>&1 ) 3>&1) & 608*b30d1939SAndy Fiddaman pid=$! 609*b30d1939SAndy Fiddaman sleep 2 610*b30d1939SAndy Fiddaman kill -9 $! 2> /dev/null && err_exit '/dev/zero in command substitution hangs' 611*b30d1939SAndy Fiddaman wait $! 612*b30d1939SAndy FiddamanEOF 613*b30d1939SAndy Fiddaman 614*b30d1939SAndy Fiddamanfor f in /dev/stdout /dev/fd/1 615*b30d1939SAndy Fiddamando if [[ -e $f ]] 616*b30d1939SAndy Fiddaman then $SHELL -c "x=\$(command -p tee $f </dev/null 2>/dev/null)" || err_exit "$f in command substitution fails" 617*b30d1939SAndy Fiddaman fi 618*b30d1939SAndy Fiddamandone 619*b30d1939SAndy Fiddaman 620*b30d1939SAndy Fiddaman# ======================================== 621*b30d1939SAndy Fiddaman# Test that closing file descriptors don't affect capturing the output of a 622*b30d1939SAndy Fiddaman# subshell. Regression test for issue #198. 623*b30d1939SAndy Fiddamantmpfile=$(mktemp) 624*b30d1939SAndy Fiddamanexpected='return value' 625*b30d1939SAndy Fiddaman 626*b30d1939SAndy Fiddamanfunction get_value { 627*b30d1939SAndy Fiddaman case=$1 628*b30d1939SAndy Fiddaman (( case >= 1 )) && exec 3< $tmpfile 629*b30d1939SAndy Fiddaman (( case >= 2 )) && exec 4< $tmpfile 630*b30d1939SAndy Fiddaman (( case >= 3 )) && exec 6< $tmpfile 631*b30d1939SAndy Fiddaman 632*b30d1939SAndy Fiddaman # To trigger the bug we have to spawn an external command. Why is a 633*b30d1939SAndy Fiddaman # mystery but not really relevant. 634*b30d1939SAndy Fiddaman $(whence -p true) 635*b30d1939SAndy Fiddaman 636*b30d1939SAndy Fiddaman (( case >= 1 )) && exec 3<&- 637*b30d1939SAndy Fiddaman (( case >= 2 )) && exec 4<&- 638*b30d1939SAndy Fiddaman (( case >= 3 )) && exec 6<&- 639*b30d1939SAndy Fiddaman 640*b30d1939SAndy Fiddaman print $expected 641*b30d1939SAndy Fiddaman} 642*b30d1939SAndy Fiddaman 643*b30d1939SAndy Fiddamanactual=$(get_value 0) 644*b30d1939SAndy Fiddamanif [[ $actual != $expected ]] 645*b30d1939SAndy Fiddamanthen 646*b30d1939SAndy Fiddaman err_exit -u2 "failed to capture subshell output when closing fd: case 0" 647*b30d1939SAndy Fiddamanfi 648*b30d1939SAndy Fiddaman 649*b30d1939SAndy Fiddamanactual=$(get_value 1) 650*b30d1939SAndy Fiddamanif [[ $actual != $expected ]] 651*b30d1939SAndy Fiddamanthen 652*b30d1939SAndy Fiddaman err_exit -u2 "failed to capture subshell output when closing fd: case 1" 653*b30d1939SAndy Fiddamanfi 654*b30d1939SAndy Fiddaman 655*b30d1939SAndy Fiddamanactual=$(get_value 2) 656*b30d1939SAndy Fiddamanif [[ $actual != $expected ]] 657*b30d1939SAndy Fiddamanthen 658*b30d1939SAndy Fiddaman err_exit -u2 "failed to capture subshell output when closing fd: case 2" 659*b30d1939SAndy Fiddamanfi 660*b30d1939SAndy Fiddaman 661*b30d1939SAndy Fiddamanactual=$(get_value 3) 662*b30d1939SAndy Fiddamanif [[ $actual != $expected ]] 663*b30d1939SAndy Fiddamanthen 664*b30d1939SAndy Fiddaman err_exit -u2 "failed to capture subshell output when closing fd: case 3" 665*b30d1939SAndy Fiddamanfi 666*b30d1939SAndy Fiddaman 667*b30d1939SAndy Fiddamanrm $tmpfile 668*b30d1939SAndy Fiddaman 669*b30d1939SAndy Fiddamanexit $((Errors<125?Errors:125)) 670