1*8462SApril.Chin@Sun.COM########################################################################
2*8462SApril.Chin@Sun.COM#                                                                      #
3*8462SApril.Chin@Sun.COM#               This software is part of the ast package               #
4*8462SApril.Chin@Sun.COM#          Copyright (c) 1982-2008 AT&T Intellectual Property          #
5*8462SApril.Chin@Sun.COM#                      and is licensed under the                       #
6*8462SApril.Chin@Sun.COM#                  Common Public License, Version 1.0                  #
7*8462SApril.Chin@Sun.COM#                    by AT&T Intellectual Property                     #
8*8462SApril.Chin@Sun.COM#                                                                      #
9*8462SApril.Chin@Sun.COM#                A copy of the License is available at                 #
10*8462SApril.Chin@Sun.COM#            http://www.opensource.org/licenses/cpl1.0.txt             #
11*8462SApril.Chin@Sun.COM#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12*8462SApril.Chin@Sun.COM#                                                                      #
13*8462SApril.Chin@Sun.COM#              Information and Software Systems Research               #
14*8462SApril.Chin@Sun.COM#                            AT&T Research                             #
15*8462SApril.Chin@Sun.COM#                           Florham Park NJ                            #
16*8462SApril.Chin@Sun.COM#                                                                      #
17*8462SApril.Chin@Sun.COM#                  David Korn <dgk@research.att.com>                   #
18*8462SApril.Chin@Sun.COM#                                                                      #
19*8462SApril.Chin@Sun.COM########################################################################
20*8462SApril.Chin@Sun.COMfunction err_exit
21*8462SApril.Chin@Sun.COM{
22*8462SApril.Chin@Sun.COM	print -u$Error_fd -n "\t"
23*8462SApril.Chin@Sun.COM	print -u$Error_fd -r ${Command}[$1]: "${@:2}"
24*8462SApril.Chin@Sun.COM	(( Errors+=1 ))
25*8462SApril.Chin@Sun.COM}
26*8462SApril.Chin@Sun.COMalias err_exit='err_exit $LINENO'
27*8462SApril.Chin@Sun.COMCommand=${0##*/}
28*8462SApril.Chin@Sun.COMinteger Errors=0 Error_fd=2
29*8462SApril.Chin@Sun.COM
30*8462SApril.Chin@Sun.COMz=()
31*8462SApril.Chin@Sun.COMz.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
32*8462SApril.Chin@Sun.COMz.bar[0]=hello
33*8462SApril.Chin@Sun.COMz.bar[2]=world
34*8462SApril.Chin@Sun.COMz.bar[1]=(x=4 y=5)
35*8462SApril.Chin@Sun.COMval='(
36*8462SApril.Chin@Sun.COM	typeset -a bar=(
37*8462SApril.Chin@Sun.COM		[0]=hello
38*8462SApril.Chin@Sun.COM		[2]=world
39*8462SApril.Chin@Sun.COM		[1]=(
40*8462SApril.Chin@Sun.COM			x=4
41*8462SApril.Chin@Sun.COM			y=5
42*8462SApril.Chin@Sun.COM		)
43*8462SApril.Chin@Sun.COM	)
44*8462SApril.Chin@Sun.COM	typeset -A foo=(
45*8462SApril.Chin@Sun.COM		[one]=hello
46*8462SApril.Chin@Sun.COM		[three]=hi
47*8462SApril.Chin@Sun.COM		[two]=(
48*8462SApril.Chin@Sun.COM			x=3
49*8462SApril.Chin@Sun.COM			y=4
50*8462SApril.Chin@Sun.COM		)
51*8462SApril.Chin@Sun.COM	)
52*8462SApril.Chin@Sun.COM)'
53*8462SApril.Chin@Sun.COM[[ $z == "$val" ]] || err_exit 'compound variable with mixed arrays not working'
54*8462SApril.Chin@Sun.COMz.bar[1]=yesyes
55*8462SApril.Chin@Sun.COM[[ ${z.bar[1]} == yesyes ]] || err_exit 'reassign of index array compound variable fails'
56*8462SApril.Chin@Sun.COMz.bar[1]=(x=12 y=5)
57*8462SApril.Chin@Sun.COM[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails'
58*8462SApril.Chin@Sun.COMeval val="$z"
59*8462SApril.Chin@Sun.COM(
60*8462SApril.Chin@Sun.COM	z.foo[three]=good
61*8462SApril.Chin@Sun.COM	[[ ${z.foo[three]} == good ]] || err_exit 'associative array assignment in subshell not working'
62*8462SApril.Chin@Sun.COM)
63*8462SApril.Chin@Sun.COM[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
64*8462SApril.Chin@Sun.COMeval val="$z"
65*8462SApril.Chin@Sun.COM(
66*8462SApril.Chin@Sun.COMfalse
67*8462SApril.Chin@Sun.COM	z.foo[two]=ok
68*8462SApril.Chin@Sun.COM	[[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working'
69*8462SApril.Chin@Sun.COM	z.bar[1]=yes
70*8462SApril.Chin@Sun.COM	[[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working'
71*8462SApril.Chin@Sun.COM)
72*8462SApril.Chin@Sun.COM[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
73*8462SApril.Chin@Sun.COM
74*8462SApril.Chin@Sun.COMx=(
75*8462SApril.Chin@Sun.COM	foo=( qqq=abc rrr=def)
76*8462SApril.Chin@Sun.COM	bar=( zzz=no rst=fed)
77*8462SApril.Chin@Sun.COM)
78*8462SApril.Chin@Sun.COMeval val="$x"
79*8462SApril.Chin@Sun.COM(
80*8462SApril.Chin@Sun.COM	unset x.foo
81*8462SApril.Chin@Sun.COM	[[ ${x.foo.qqq} ]] && err_exit 'x.foo.qqq should be unset'
82*8462SApril.Chin@Sun.COM	x.foo=good
83*8462SApril.Chin@Sun.COM	[[ ${x.foo} == good ]] || err_exit 'x.foo should be good'
84*8462SApril.Chin@Sun.COM)
85*8462SApril.Chin@Sun.COM[[ $x == "$val" ]] || err_exit 'compound variable changes after unset leaves'
86*8462SApril.Chin@Sun.COMunset l
87*8462SApril.Chin@Sun.COM(
88*8462SApril.Chin@Sun.COM	l=( a=1 b="BE" )
89*8462SApril.Chin@Sun.COM)
90*8462SApril.Chin@Sun.COM[[ ${l+foo} != foo ]] || err_exit 'l should be unset'
91*8462SApril.Chin@Sun.COM
92*8462SApril.Chin@Sun.COMError_fd=9
93*8462SApril.Chin@Sun.COMeval "exec $Error_fd>&2 2>/dev/null"
94*8462SApril.Chin@Sun.COM
95*8462SApril.Chin@Sun.COMTEST_notfound=notfound
96*8462SApril.Chin@Sun.COMwhile	whence $TEST_notfound >/dev/null 2>&1
97*8462SApril.Chin@Sun.COMdo	TEST_notfound=notfound-$RANDOM
98*8462SApril.Chin@Sun.COMdone
99*8462SApril.Chin@Sun.COM
100*8462SApril.Chin@Sun.COMtmp=/tmp/kshsubsh$$
101*8462SApril.Chin@Sun.COMtrap "rm -f $tmp" EXIT
102*8462SApril.Chin@Sun.COMinteger BS=1024 nb=64 ss=60 bs no
103*8462SApril.Chin@Sun.COMfor bs in $BS 1
104*8462SApril.Chin@Sun.COMdo	$SHELL -c '
105*8462SApril.Chin@Sun.COM		{
106*8462SApril.Chin@Sun.COM			sleep '$ss'
107*8462SApril.Chin@Sun.COM			kill -KILL $$
108*8462SApril.Chin@Sun.COM		} &
109*8462SApril.Chin@Sun.COM		set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs')
110*8462SApril.Chin@Sun.COM		print ${#1}
111*8462SApril.Chin@Sun.COM		kill $!
112*8462SApril.Chin@Sun.COM	' > $tmp 2>/dev/null
113*8462SApril.Chin@Sun.COM	no=$(<$tmp)
114*8462SApril.Chin@Sun.COM	(( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}"
115*8462SApril.Chin@Sun.COMdone
116*8462SApril.Chin@Sun.COM# this time with redirection on the trailing command
117*8462SApril.Chin@Sun.COMfor bs in $BS 1
118*8462SApril.Chin@Sun.COMdo	$SHELL -c '
119*8462SApril.Chin@Sun.COM		{
120*8462SApril.Chin@Sun.COM			sleep 2
121*8462SApril.Chin@Sun.COM			sleep '$ss'
122*8462SApril.Chin@Sun.COM			kill -KILL $$
123*8462SApril.Chin@Sun.COM		} &
124*8462SApril.Chin@Sun.COM		set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null)
125*8462SApril.Chin@Sun.COM		print ${#1}
126*8462SApril.Chin@Sun.COM		kill $!
127*8462SApril.Chin@Sun.COM	' > $tmp 2>/dev/null
128*8462SApril.Chin@Sun.COM	no=$(<$tmp)
129*8462SApril.Chin@Sun.COM	(( 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}"
130*8462SApril.Chin@Sun.COMdone
131*8462SApril.Chin@Sun.COM
132*8462SApril.Chin@Sun.COM# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io
133*8462SApril.Chin@Sun.COM
134*8462SApril.Chin@Sun.COMset -- \
135*8462SApril.Chin@Sun.COM	'post-line print'								\
136*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; print 1); print'					\
137*8462SApril.Chin@Sun.COM	1										\
138*8462SApril.Chin@Sun.COM	'pre-line print'								\
139*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; print); print 1'					\
140*8462SApril.Chin@Sun.COM	$'\n1'										\
141*8462SApril.Chin@Sun.COM	'multiple pre-line print'							\
142*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print'		\
143*8462SApril.Chin@Sun.COM	$'\n\n1'									\
144*8462SApril.Chin@Sun.COM	'multiple post-line print'							\
145*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print'		\
146*8462SApril.Chin@Sun.COM	1										\
147*8462SApril.Chin@Sun.COM	'intermediate print'								\
148*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print'	\
149*8462SApril.Chin@Sun.COM	$'1\n\n2'									\
150*8462SApril.Chin@Sun.COM	'simple variable'								\
151*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l'				\
152*8462SApril.Chin@Sun.COM	2										\
153*8462SApril.Chin@Sun.COM	'compound variable'								\
154*8462SApril.Chin@Sun.COM	'$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l'		\
155*8462SApril.Chin@Sun.COM	$'(\n\ta=2\n\tb=BE\n)'								\
156*8462SApril.Chin@Sun.COM
157*8462SApril.Chin@Sun.COMexport TEST_fork TEST_unset
158*8462SApril.Chin@Sun.COM
159*8462SApril.Chin@Sun.COMwhile	(( $# >= 3 ))
160*8462SApril.Chin@Sun.COMdo	txt=$1
161*8462SApril.Chin@Sun.COM	cmd=$2
162*8462SApril.Chin@Sun.COM	exp=$3
163*8462SApril.Chin@Sun.COM	shift 3
164*8462SApril.Chin@Sun.COM	for TEST_unset in '' 'unset var'
165*8462SApril.Chin@Sun.COM	do	for TEST_fork in '' 'ulimit -c 0'
166*8462SApril.Chin@Sun.COM		do	for TEST_shell in "eval" "$SHELL -c"
167*8462SApril.Chin@Sun.COM			do	if	! got=$($TEST_shell "$cmd")
168*8462SApril.Chin@Sun.COM				then	err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed"
169*8462SApril.Chin@Sun.COM				elif	[[ "$got" != "$exp" ]]
170*8462SApril.Chin@Sun.COM				then	EXP=$(printf %q "$exp")
171*8462SApril.Chin@Sun.COM					GOT=$(printf %q "$got")
172*8462SApril.Chin@Sun.COM					err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT"
173*8462SApril.Chin@Sun.COM				fi
174*8462SApril.Chin@Sun.COM			done
175*8462SApril.Chin@Sun.COM		done
176*8462SApril.Chin@Sun.COM	done
177*8462SApril.Chin@Sun.COMdone
178*8462SApril.Chin@Sun.COM
179*8462SApril.Chin@Sun.COMr=$( ($SHELL -c '
180*8462SApril.Chin@Sun.COM	{
181*8462SApril.Chin@Sun.COM		sleep 32
182*8462SApril.Chin@Sun.COM		kill -KILL $$
183*8462SApril.Chin@Sun.COM	} &
184*8462SApril.Chin@Sun.COM	for v in $(set | sed "s/=.*//")
185*8462SApril.Chin@Sun.COM	do	command unset $v
186*8462SApril.Chin@Sun.COM	done
187*8462SApril.Chin@Sun.COM	typeset -Z5 I
188*8462SApril.Chin@Sun.COM	for ((I = 0; I < 1024; I++))
189*8462SApril.Chin@Sun.COM	do	eval A$I=1234567890
190*8462SApril.Chin@Sun.COM	done
191*8462SApril.Chin@Sun.COM	a=$(set 2>&1)
192*8462SApril.Chin@Sun.COM	print ok
193*8462SApril.Chin@Sun.COM	kill -KILL $!
194*8462SApril.Chin@Sun.COM') 2>/dev/null)
195*8462SApril.Chin@Sun.COM[[ $r == ok ]] || err_exit "large subshell command substitution hangs"
196*8462SApril.Chin@Sun.COM
197*8462SApril.Chin@Sun.COMfor TEST_command in '' $TEST_notfound
198*8462SApril.Chin@Sun.COMdo	for TEST_exec in '' 'exec'
199*8462SApril.Chin@Sun.COM	do	for TEST_fork in '' 'ulimit -c 0;'
200*8462SApril.Chin@Sun.COM		do	for TEST_redirect in '' '>/dev/null'
201*8462SApril.Chin@Sun.COM			do	for TEST_substitute in '' ': $'
202*8462SApril.Chin@Sun.COM				do
203*8462SApril.Chin@Sun.COM
204*8462SApril.Chin@Sun.COM	TEST_test="$TEST_substitute($TEST_fork $TEST_exec $TEST_command $TEST_redirect)"
205*8462SApril.Chin@Sun.COM	[[ $TEST_test == '('*([[:space:]])')' ]] && continue
206*8462SApril.Chin@Sun.COM	r=$($SHELL -c '
207*8462SApril.Chin@Sun.COM		{
208*8462SApril.Chin@Sun.COM			sleep 2
209*8462SApril.Chin@Sun.COM			kill -KILL $$
210*8462SApril.Chin@Sun.COM		} &
211*8462SApril.Chin@Sun.COM		'"$TEST_test"'
212*8462SApril.Chin@Sun.COM		kill $!
213*8462SApril.Chin@Sun.COM		print ok
214*8462SApril.Chin@Sun.COM		')
215*8462SApril.Chin@Sun.COM	[[ $r == ok ]] || err_exit "shell hangs on $TEST_test"
216*8462SApril.Chin@Sun.COM
217*8462SApril.Chin@Sun.COM				done
218*8462SApril.Chin@Sun.COM			done
219*8462SApril.Chin@Sun.COM		done
220*8462SApril.Chin@Sun.COM	done
221*8462SApril.Chin@Sun.COMdone
222*8462SApril.Chin@Sun.COM
223*8462SApril.Chin@Sun.COMexit $Errors
224