########################################################################
# #
# This software is part of the ast package #
# Copyright (c) 1982-2012 AT&T Intellectual Property #
# and is licensed under the #
# Eclipse Public License, Version 1.0 #
# by AT&T Intellectual Property #
# #
# A copy of the License is available at #
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
# #
# Information and Software Systems Research #
# AT&T Research #
# Florham Park NJ #
# #
# David Korn <dgk@research.att.com> #
# #
########################################################################
function err_exit
{
print -u$Error_fd -n "\t"
}
alias err_exit='err_exit $LINENO'
builtin getconf
z=()
val='(
typeset -a bar=(
[0]=hello
[2]=world
[1]=(
x=4
y=5
)
)
typeset -A foo=(
[one]=hello
[three]=hi
[two]=(
x=3
y=4
)
)
)'
[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails'
eval val="$z"
(
)
eval val="$z"
(
[[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working'
[[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working'
)
x=(
)
eval val="$x"
(
unset x.foo
)
unset l
(
l=( a=1 b="BE" )
)
Error_fd=9
done
do $SHELL -c '
{
kill -KILL $$
} &
print ${#1}
kill $!
(( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}"
done
# this time with redirection on the trailing command
do $SHELL -c '
{
sleep 2
kill -KILL $$
} &
print ${#1}
kill $!
(( 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}"
done
# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io
set -- \
'post-line print' \
'$TEST_unset; ($TEST_fork; print 1); print' \
1 \
'pre-line print' \
'$TEST_unset; ($TEST_fork; print); print 1' \
$'\n1' \
'multiple pre-line print' \
'$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print' \
$'\n\n1' \
'multiple post-line print' \
'$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print' \
1 \
'intermediate print' \
'$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print' \
$'1\n\n2' \
'simple variable' \
'$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l' \
2 \
'compound variable' \
'$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l' \
$'(\n\ta=2\n\tb=BE\n)' \
export TEST_fork TEST_unset
while (( $# >= 3 ))
do txt=$1
cmd=$2
exp=$3
shift 3
then err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed"
err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT"
fi
done
done
done
done
{
sleep 32
kill -KILL $$
} &
for v in $(set | sed "s/=.*//")
do command unset $v
done
typeset -Z5 I
for ((I = 0; I < 1024; I++))
do eval A$I=1234567890
done
a=$(set 2>&1)
print ok
kill -KILL $!
do
r=$($SHELL -c '
{
sleep 2
kill -KILL $$
} &
kill $!
print ok
')
done
done
done
done
done
$SHELL -c '( autoload xxxxx);print -n' || err_exit 'autoloaded functions in subshells can cause failure'
++EOF++
)
err=$(
function foo
{
}
# consume almost all fds to push the test to the fd limit #
do exec {i}>&1
done
for ((i=0; i < 20; i++))
do y=$(foo)
done
) || {
}
exp=0
$SHELL -c $'
function foobar
{
print "hello world"
}
[[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
'
got=$?
[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
function foobar
{
print "hello world"
}
[[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
')
[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
# command substitution variations #
set -- \
'$(' ')' \
'${ ' '; }' \
'$(ulimit -c 0; ' ')' \
'$( (' ') )' \
'${ (' '); }' \
'`' '`' \
'`(' ')`' \
'`ulimit -c 0; ' '`' \
# end of table #
then print error
else print ok
fi
exit %s
'
function bar
{
pipeout=%1$sprintf Ok | tr O o%2$s
print $pipeout
return 0
}
foo=%1$sbar%2$s || foo="exit status $?"
print $foo
exit %3$s
'
while (( $# >= 2 ))
status=$?
fi
done
done
shift 2
done
# the next tests loop on all combinations of
# { SUB CAT INS TST APP } X { file-sizes }
# where the file size starts at 1Ki and doubles up to and including 1Mi
#
# the tests and timeouts are done in async subshells to prevent
# the test harness from hanging
SUB=(
)
TST=(
)
then T=${#TST[@]}
fi
# prime the two data files to 512 bytes each
# the outer loop doubles the file size at top
buf=$'1234567890abcdef'
lin=$'\n1234567890abcde'
for ((i=0; i<5; i++))
done
unset SKIP
for ((n=1024; n<=1024*1024; n*=2))
for ((S=0; S<${#SUB[@]}; S++))
do for ((C=0; C<${#CAT[@]}; C++))
for ((I=0; I<${#INS[@]}; I++))
do for ((A=0; A<${#APP[@]}; A++))
do for ((T=0; T<${#TST[@]}; T++))
do #undent...#
if [[ ! ${SKIP[S][C][I][A][T]} ]]
then eval "{ x=${SUB[S].BEG}${INS[I]}${TST[T].CMD}${APP[A]}${SUB[S].END}; print \${#x}; } >\$tmp/out &"
m=$!
k=$!
wait $m
h=$?
kill -9 $k
wait $k
fi
else exp=$n
fi
then # on failure skip similar tests on larger files sizes #
SKIP[S][C][I][A][T]=1
err_exit "'x=${SUB[S].BEG}${INS[I]}${cmd}${APP[A]}${SUB[S].END} && print \${#x}' failed -- expected '$exp', got '$got'"
then SKIP[S][C][I][A][T]=1
fi
fi
done
done
done
done
done
done
# specifics -- there's more?
{
eval $cmd
m=$!
k=$!
wait $m
h=$?
kill -9 $k
wait $k
exp=''
fi
fi
if [[ $sleep ]]
then
fi
cmd='echo $((case x in x)echo ok;esac);:)'
exp=$'x\nx'
fi
(
$SHELL -c 'sleep 20 & pid=$!; { x=$( ( seq 60000 ) );kill -9 $pid;}&;wait $pid'
[[ $($SHELL -c 'print 1 | : "$(/bin/cat <(/bin/cat))"') ]] && err_exit 'process substitution not working correctly in subshells'
# config hang bug
integer i
for ((i=1; i < 1000; i++))
do typeset foo$i=$i
done
{
sleep 1.5
then err_exit 'process timed out with hung comsub'
fi
$SHELL 2> /dev/null -c '[[ ${ print foo },${ print bar } == foo,bar ]]' || err_exit '${ print foo },${ print bar } not working'
$SHELL 2> /dev/null -c '[[ ${ print foo; },${ print bar } == foo,bar ]]' || err_exit '${ print foo; },${ print bar } not working'
[[ $x == 123 ]] && err_exit 'global variables set from with functions inside a
subshell can leave side effects in parent shell'
: $( $date)
wait $pid
[[ $? == 12 ]] || err_exit 'exit status from subshells not being preserved'
[[ $x == 'Hello Fred' ]] || err_exit "process substitution of pipeline in command substitution not working"
fi
{
function foo
{
integer i
for ((i=0; i < 8000; i++))
do print abcdefghijk
done
print -u2 done
}
(( ${#out} == 96011 )) || err_exit "\${#out} is ${#out} should be 96011"
} & pid=$!
{
)
true=$(whence -p true)
function fun1
{
}
$SHELL -c 'function g { IFS= ;};function f { typeset IFS;(g);: $V;};f;f'
unset i
then integer i
for ((i=11; i < 29; i++))
fi
done
fi
$(ls -d .)
EOF
) ) & sleep 1
if kill -0 $! 2> /dev/null
then err_exit 'command substitution containg here-doc with command substitution fails'
fi
printf=$(whence -p printf)
[[ $( { trap "echo foobar" EXIT; ( $printf ""); } & wait) == foobar ]] || err_exit 'exit trap not being invoked'
$SHELL 2> /dev/null -c '( PATH=/bin; set -o restricted) ; exit 0' || err_exit 'restoring PATH when a subshell enables restricted exits not working'
$SHELL <<- \EOF
wc=$(whence wc) head=$(whence head)
print > /dev/null $( ( $head -c 1 /dev/zero | ( $wc -c) 3>&1 ) 3>&1) &
pid=$!
sleep 2
kill -9 $! 2> /dev/null && err_exit '/dev/zero in command substitution hangs'
wait $!
EOF
do if [[ -e $f ]]
then $SHELL -c "x=\$(command -p tee $f </dev/null 2>/dev/null)" || err_exit "$f in command substitution fails"
fi
done