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