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