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