######################################################################## # # # 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 # # http://www.eclipse.org/org/documents/epl-v10.html # # (with md5 checksum b35adb5213ca9657e911e9befb180842) # # # # Information and Software Systems Research # # AT&T Research # # Florham Park NJ # # # # David Korn # # # ######################################################################## # test the behavior of co-processes function err_exit { print -u2 -n "\t" print -u2 -r ${Command}[$1]: "${@:2}" let Errors+=1 } alias err_exit='err_exit $LINENO' Command=${0##*/} integer Errors=0 tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } trap "cd /; rm -rf $tmp" EXIT if [[ -d /cygdrive ]] then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system exit $((Errors)) fi bintrue=$(whence -p true) function ping # id { integer x=0 while ((x++ < 5)) do read -r print -r "$1 $REPLY" done } bincat=$(whence -p cat) builtin cat for cat in cat $bincat do $cat |& print -p "hello" read -p line [[ $line == hello ]] || err_exit "$cat coprocessing fails" exec 5>&p 6<&p print -u5 'hello again' || err_exit "write on $cat coprocess u5 fails" read -u6 line [[ $line == 'hello again' ]] || err_exit "$cat coprocess after moving fds fails" exec 5<&- 6<&- wait $! ping three |& exec 3>&p ping four |& exec 4>&p ping pipe |& integer count for i in three four pipe four pipe four three pipe pipe three pipe do case $i in three) to=-u3;; four) to=-u4;; pipe) to=-p;; esac (( count++ )) print $to $i $count done while ((count > 0)) do (( count-- )) read -p set -- $REPLY if [[ $1 != $2 ]] then err_exit "$cat coprocess $1 does not match $2" fi case $1 in three) ;; four) ;; pipe) ;; *) err_exit "$cat coprocess unknown message +|$REPLY|+" ;; esac done kill $(jobs -p) 2>/dev/null file=$tmp/regress $cat > $file <<-! $cat |& ! chmod +x $file sleep 10 |& $file 2> /dev/null || err_exit "parent $cat coprocess prevents script coprocess" exec 5<&p 6>&p exec 5<&- 6>&- kill $(jobs -p) 2>/dev/null ${SHELL-ksh} |& cop=$! exp=Done print -p $'print hello | '$cat$'\nprint '$exp read -t 5 -p read -t 5 -p got=$REPLY if [[ $got != $exp ]] then err_exit "${SHELL-ksh} $cat coprocess io failed -- got '$got', expected '$exp'" fi exec 5<&p 6>&p exec 5<&- 6>&- { sleep 4; kill $cop; } 2>/dev/null & spy=$! if wait $cop 2>/dev/null then kill $spy 2>/dev/null else err_exit "$cat coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'" fi wait { echo line1 | grep 'line2' echo line2 | grep 'line1' } |& SECONDS=0 count=0 while read -p -t 10 line do ((count++)) done if (( SECONDS > 8 )) then err_exit "$cat coprocess read -p hanging (SECONDS=$SECONDS count=$count)" fi wait $! ( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) || err_exit "$cat coprocess cleanup not working correctly" { : |& } 2>/dev/null || err_exit "subshell $cat coprocess lingers in parent" wait $! unset N r e integer N=5 e=12345 ( integer i for ((i = 1; i <= N; i++)) do print $i |& read -p r print -n $r wait $! done print ) 2>/dev/null | read -t 10 r [[ $r == $e ]] || err_exit "$cat coprocess timing bug -- expected $e, got '$r'" r= ( integer i for ((i = 1; i <= N; i++)) do print $i |& sleep 0.01 r=$r$($cat <&p) wait $! done print $r ) 2>/dev/null | read -t 10 r [[ $r == $e ]] || err_exit "$cat coprocess command substitution bug -- expected $e, got '$r'" ( $cat |& sleep 0.01 exec 6>&p print -u6 ok exec 6>&- sleep 2 kill $! 2> /dev/null ) && err_exit "$cat coprocess with subshell would hang" for sig in IOT ABRT do if ( trap - $sig ) 2> /dev/null then if [[ $( { sig=$sig $SHELL 2> /dev/null <<- ++EOF++ $cat |& pid=\$! trap "print TRAP" \$sig ( sleep 2 kill -\$sig \$\$ sleep 2 kill -\$sig \$\$ kill \$pid sleep 2 kill \$\$ ) & while read -p || ((\$? > 256)) do : done ++EOF++ } ) != $'TRAP\nTRAP' ]] 2> /dev/null then err_exit "traps when reading from $cat coprocess not working" fi break fi done trap 'sleep_pid=; kill $pid; err_exit "$cat coprocess 1 hung"' TERM { sleep 5; kill $$; } & sleep_pid=$! $cat |& pid=$! exec 5<&p 6>&p exp=hi print -u6 $exp; read -u5 [[ $REPLY == "$exp" ]] || err_exit "REPLY from $cat coprocess failed -- expected '$exp', got '$REPLY'" exec 6>&- wait $pid trap - TERM [[ $sleep_pid ]] && kill $sleep_pid trap 'sleep_pid=; kill $pid; err_exit "$cat coprocess 2 hung"' TERM { sleep 5; kill $$; } & sleep_pid=$! $cat |& pid=$! print foo >&p 2> /dev/null || err_exit "first write of foo to $cat coprocess failed" print foo >&p 2> /dev/null || err_exit "second write of foo to coprocess failed" kill $pid wait $pid 2> /dev/null trap - TERM [[ $sleep_pid ]] && kill $sleep_pid trap 'sleep_pid=; kill $pid; err_exit "$cat coprocess 3 hung"' TERM { sleep 5; kill $$; } & sleep_pid=$! $cat |& pid=$! print -p foo print -p bar read <&p || err_exit "first read from $cat coprocess failed" [[ $REPLY == foo ]] || err_exit "first REPLY from $cat coprocess is $REPLY not foo" read <&p || err_exit "second read from $cat coprocess failed" [[ $REPLY == bar ]] || err_exit "second REPLY from $cat coprocess is $REPLY not bar" kill $pid wait $pid 2> /dev/null trap - TERM [[ $sleep_pid ]] && kill $sleep_pid done exp=ksh got=$(print -r $'#00315 COATTRIBUTES=\'label=make \' # @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $ _COSHELL_msgfd=5 { { (eval \'function fun { trap \":\" 0; return 1; }; trap \"exit 0\" 0; fun; exit 1\') && PATH= print -u$_COSHELL_msgfd ksh; } || { times && echo bsh >&$_COSHELL_msgfd; } || { echo osh >&$_COSHELL_msgfd; }; } >/dev/null 2>&1' | $SHELL 5>&1) [[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'" function cop { read print ok } exp=ok cop |& pid=$! if print -p yo 2>/dev/null then read -p got else got='no coprocess' fi [[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'" kill $pid 2>/dev/null wait cop |& pid=$! ( if print -p yo 2>/dev/null then read -p got else got='no coprocess' fi [[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'" ) kill $pid 2>/dev/null wait exp='no coprocess' ( cop |& print $! > $tmp/pid ) pid=$(<$tmp/pid) if print -p yo 2>/dev/null then read -p got else got=$exp fi [[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'" kill $pid 2>/dev/null wait ( cop |& print $! > $tmp/pid ) pid=$(<$tmp/pid) ( if print -p yo 2>/dev/null then read -p got else got=$exp fi [[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'" kill $pid 2>/dev/null wait ) function mypipe { read; read print -r -- "$REPLY" } mypipe |& print -p "hello" z="$( $bintrue $($bintrue) )" { print -p "world";} 2> /dev/null read -p [[ $REPLY == world ]] || err_exit "expected 'world' got '$REPLY'" kill $pid 2>/dev/null wait function cop { read print ok } exp=ok cop |& pid=$! ( if print -p yo 2>/dev/null then read -p got else got='no coprocess' fi [[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'" ) kill $pid 2>/dev/null wait tee=$(whence -p tee) ls -l |& pid=$! $tee -a /dev/null <&p > /dev/null wait $pid x=$? [[ $x == 0 ]] || err_exit "coprocess exitval should be 0, not $x" exit $((Errors<125?Errors:125))