xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/tests/subshell.sh (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
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