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