1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2011 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######################################################################## 20# test the behavior of co-processes 21function err_exit 22{ 23 print -u2 -n "\t" 24 print -u2 -r ${Command}[$1]: "${@:2}" 25 let Errors+=1 26} 27alias err_exit='err_exit $LINENO' 28 29Command=${0##*/} 30integer Errors=0 31 32tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 33trap "cd /; rm -rf $tmp" EXIT 34 35if [[ -d /cygdrive ]] 36then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system 37 exit $((Errors)) 38fi 39 40bintrue=$(whence -p true) 41 42function ping # id 43{ 44 integer x=0 45 while ((x++ < 5)) 46 do read -r 47 print -r "$1 $REPLY" 48 done 49} 50 51cat |& 52print -p "hello" 53read -p line 54[[ $line == hello ]] || err_exit 'coprocessing fails' 55exec 5>&p 6<&p 56print -u5 'hello again' || err_exit 'write on u5 fails' 57read -u6 line 58[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails' 59exec 5<&- 6<&- 60wait $! 61 62ping three |& 63exec 3>&p 64ping four |& 65exec 4>&p 66ping pipe |& 67 68integer count 69for i in three four pipe four pipe four three pipe pipe three pipe 70do case $i in 71 three) to=-u3;; 72 four) to=-u4;; 73 pipe) to=-p;; 74 esac 75 (( count++ )) 76 print $to $i $count 77done 78 79while ((count > 0)) 80do (( count-- )) 81 read -p 82 set -- $REPLY 83 if [[ $1 != $2 ]] 84 then err_exit "$1 does not match $2" 85 fi 86 case $1 in 87 three) ;; 88 four) ;; 89 pipe) ;; 90 *) err_exit "unknown message +|$REPLY|+" ;; 91 esac 92done 93kill $(jobs -p) 2>/dev/null 94 95file=$tmp/regress 96cat > $file <<\! 97/bin/cat |& 98! 99chmod +x $file 100sleep 10 |& 101$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess" 102exec 5<&p 6>&p 103exec 5<&- 6>&- 104kill $(jobs -p) 2>/dev/null 105 106${SHELL-ksh} |& 107cop=$! 108exp=Done 109print -p $'print hello | cat\nprint '$exp 110read -t 5 -p 111read -t 5 -p 112got=$REPLY 113if [[ $got != $exp ]] 114then err_exit "${SHELL-ksh} coprocess io failed -- got '$got', expected '$exp'" 115fi 116exec 5<&p 6>&p 117exec 5<&- 6>&- 118{ sleep 4; kill $cop; } 2>/dev/null & 119spy=$! 120if wait $cop 2>/dev/null 121then kill $spy 2>/dev/null 122else err_exit "coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'" 123fi 124wait 125 126{ 127echo line1 | grep 'line2' 128echo line2 | grep 'line1' 129} |& 130SECONDS=0 count=0 131while read -p -t 10 line 132do ((count++)) 133done 134if (( SECONDS > 8 )) 135then err_exit "read -p hanging (SECONDS=$SECONDS count=$count)" 136fi 137wait $! 138 139( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) || 140 err_exit "coprocess cleanup not working correctly" 141{ : |& } 2>/dev/null || 142 err_exit "subshell coprocess lingers in parent" 143wait $! 144 145unset N r e 146integer N=5 147e=12345 148( 149 integer i 150 for ((i = 1; i <= N; i++)) 151 do print $i |& 152 read -p r 153 print -n $r 154 wait $! 155 done 156 print 157) 2>/dev/null | read -t 10 r 158[[ $r == $e ]] || err_exit "coprocess timing bug -- expected $e, got '$r'" 159r= 160( 161 integer i 162 for ((i = 1; i <= N; i++)) 163 do print $i |& 164 sleep 0.01 165 r=$r$(cat <&p) 166 wait $! 167 done 168 print $r 169) 2>/dev/null | read -t 10 r 170[[ $r == $e ]] || err_exit "coprocess command substitution bug -- expected $e, got '$r'" 171 172( 173 /bin/cat |& 174 sleep 0.01 175 exec 6>&p 176 print -u6 ok 177 exec 6>&- 178 sleep 1 179 kill $! 2> /dev/null 180) && err_exit 'coprocess with subshell would hang' 181for sig in IOT ABRT 182do if ( trap - $sig ) 2> /dev/null 183 then if [[ $( { sig=$sig $SHELL 2> /dev/null <<- '++EOF++' 184 cat |& 185 pid=$! 186 trap "print TRAP" $sig 187 ( 188 sleep 2 189 kill -$sig $$ 190 sleep 2 191 kill -$sig $$ 192 kill $pid 193 sleep 2 194 kill $$ 195 ) & 196 read -p 197 ++EOF++ 198 } ) != $'TRAP\nTRAP' ]] 2> /dev/null 199 then err_exit 'traps when reading from coprocess not working' 200 fi 201 break 202 fi 203done 204 205trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM 206{ sleep 5; kill $$; } & 207sleep_pid=$! 208builtin cat 209cat |& 210pid=$! 211exec 5<&p 6>&p 212exp=hi 213print -u6 $exp; read -u5 214[[ $REPLY == "$exp" ]] || err_exit "REPLY failed -- expected '$exp', got '$REPLY'" 215exec 6>&- 216wait $pid 217trap - TERM 218[[ $sleep_pid ]] && kill $sleep_pid 219 220trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM 221{ sleep 5; kill $$; } & 222sleep_pid=$! 223cat |& 224pid=$! 225print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed' 226print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed' 227kill $pid 228wait $pid 2> /dev/null 229trap - TERM 230[[ $sleep_pid ]] && kill $sleep_pid 231 232trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM 233{ sleep 5; kill $$; } & 234sleep_pid=$! 235cat |& 236pid=$! 237print -p foo 238print -p bar 239read <&p || err_exit 'first read from coprocess failed' 240[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo" 241read <&p || err_exit 'second read from coprocess failed' 242[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar" 243kill $pid 244wait $pid 2> /dev/null 245trap - TERM 246[[ $sleep_pid ]] && kill $sleep_pid 247 248exp=ksh 249got=$(print -r $'#00315 250COATTRIBUTES=\'label=make \' 251# @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $ 252_COSHELL_msgfd=5 253{ { (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) 254[[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'" 255 256function cop 257{ 258 read 259 print ok 260} 261 262exp=ok 263 264cop |& 265pid=$! 266if print -p yo 2>/dev/null 267then read -p got 268else got='no coprocess' 269fi 270[[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'" 271kill $pid 2>/dev/null 272wait 273 274cop |& 275pid=$! 276( 277if print -p yo 2>/dev/null 278then read -p got 279else got='no coprocess' 280fi 281[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'" 282) 283kill $pid 2>/dev/null 284wait 285 286exp='no coprocess' 287 288( 289cop |& 290print $! > $tmp/pid 291) 292pid=$(<$tmp/pid) 293if print -p yo 2>/dev/null 294then read -p got 295else got=$exp 296fi 297[[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'" 298kill $pid 2>/dev/null 299wait 300 301( 302cop |& 303print $! > $tmp/pid 304) 305pid=$(<$tmp/pid) 306( 307if print -p yo 2>/dev/null 308then read -p got 309else got=$exp 310fi 311[[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'" 312kill $pid 2>/dev/null 313wait 314) 315 316function mypipe 317{ 318 read; read 319 print -r -- "$REPLY" 320} 321 322mypipe |& 323print -p "hello" 324z="$( $bintrue $($bintrue) )" 325{ print -p "world";} 2> /dev/null 326read -p 327[[ $REPLY == world ]] || err_exit "expected 'world' got '$REPLY'" 328kill $pid 2>/dev/null 329wait 330 331 332function cop 333{ 334 read 335 print ok 336} 337exp=ok 338cop |& 339pid=$! 340( 341if print -p yo 2>/dev/null 342then read -p got 343else got='no coprocess' 344fi 345[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'" 346) 347kill $pid 2>/dev/null 348wait 349 350exit $((Errors<125?Errors:125)) 351