xref: /freebsd/contrib/netbsd-tests/bin/sh/t_redir.sh (revision c22165b4f1f5d38b681921797a44b3ba8c13b7e0)
1*640235e2SEnji Cooper# $NetBSD: t_redir.sh,v 1.9 2016/05/14 00:33:02 kre Exp $
2*640235e2SEnji Cooper#
3*640235e2SEnji Cooper# Copyright (c) 2016 The NetBSD Foundation, Inc.
4*640235e2SEnji Cooper# All rights reserved.
5*640235e2SEnji Cooper#
6*640235e2SEnji Cooper# Redistribution and use in source and binary forms, with or without
7*640235e2SEnji Cooper# modification, are permitted provided that the following conditions
8*640235e2SEnji Cooper# are met:
9*640235e2SEnji Cooper# 1. Redistributions of source code must retain the above copyright
10*640235e2SEnji Cooper#    notice, this list of conditions and the following disclaimer.
11*640235e2SEnji Cooper# 2. Redistributions in binary form must reproduce the above copyright
12*640235e2SEnji Cooper#    notice, this list of conditions and the following disclaimer in the
13*640235e2SEnji Cooper#    documentation and/or other materials provided with the distribution.
14*640235e2SEnji Cooper#
15*640235e2SEnji Cooper# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16*640235e2SEnji Cooper# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17*640235e2SEnji Cooper# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18*640235e2SEnji Cooper# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19*640235e2SEnji Cooper# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*640235e2SEnji Cooper# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*640235e2SEnji Cooper# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*640235e2SEnji Cooper# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*640235e2SEnji Cooper# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*640235e2SEnji Cooper# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*640235e2SEnji Cooper# POSSIBILITY OF SUCH DAMAGE.
26*640235e2SEnji Cooper#
27*640235e2SEnji Cooper# the implementation of "sh" to test
28*640235e2SEnji Cooper: ${TEST_SH:="/bin/sh"}
29*640235e2SEnji Cooper
30*640235e2SEnji Cooper# Any failures in this first test means it is not worth bothering looking
31*640235e2SEnji Cooper# for causes of failures in any other tests, make this one work first.
32*640235e2SEnji Cooper
33*640235e2SEnji Cooper# Problems with this test usually mean inadequate ATF_SHELL used for testing.
34*640235e2SEnji Cooper# (though if all pass but the last, it might be a TEST_SH problem.)
35*640235e2SEnji Cooper
36*640235e2SEnji Cooperatf_test_case basic_test_method_test
37*640235e2SEnji Cooperbasic_test_method_test_head()
38*640235e2SEnji Cooper{
39*640235e2SEnji Cooper	atf_set "descr" "Tests that test method works as expected"
40*640235e2SEnji Cooper}
41*640235e2SEnji Cooperbasic_test_method_test_body()
42*640235e2SEnji Cooper{
43*640235e2SEnji Cooper	cat <<- 'DONE' |
44*640235e2SEnji Cooper	DONE
45*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH}
46*640235e2SEnji Cooper	cat <<- 'DONE' |
47*640235e2SEnji Cooper	DONE
48*640235e2SEnji Cooper	atf_check -s exit:0 -o match:0 -e empty ${TEST_SH} -c 'wc -l'
49*640235e2SEnji Cooper
50*640235e2SEnji Cooper	cat <<- 'DONE' |
51*640235e2SEnji Cooper		echo hello
52*640235e2SEnji Cooper	DONE
53*640235e2SEnji Cooper	atf_check -s exit:0 -o match:hello -e empty ${TEST_SH}
54*640235e2SEnji Cooper	cat <<- 'DONE' |
55*640235e2SEnji Cooper		echo hello
56*640235e2SEnji Cooper	DONE
57*640235e2SEnji Cooper	atf_check -s exit:0 -o match:1 -e empty ${TEST_SH} -c 'wc -l'
58*640235e2SEnji Cooper
59*640235e2SEnji Cooper	cat <<- 'DONE' |
60*640235e2SEnji Cooper		echo hello\
61*640235e2SEnji Cooper					world
62*640235e2SEnji Cooper	DONE
63*640235e2SEnji Cooper	atf_check -s exit:0 -o match:helloworld -e empty ${TEST_SH}
64*640235e2SEnji Cooper	cat <<- 'DONE' |
65*640235e2SEnji Cooper		echo hello\
66*640235e2SEnji Cooper					world
67*640235e2SEnji Cooper	DONE
68*640235e2SEnji Cooper	atf_check -s exit:0 -o match:2 -e empty ${TEST_SH} -c 'wc -l'
69*640235e2SEnji Cooper
70*640235e2SEnji Cooper	printf '%s\n%s\n%s\n' Line1 Line2 Line3 > File
71*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'Line1\nLine2\nLine3\n' -e empty \
72*640235e2SEnji Cooper		${TEST_SH} -c 'cat File'
73*640235e2SEnji Cooper
74*640235e2SEnji Cooper	cat <<- 'DONE' |
75*640235e2SEnji Cooper		set -- X "" '' Y
76*640235e2SEnji Cooper		echo ARGS="${#}"
77*640235e2SEnji Cooper		echo '' -$1- -$2- -$3- -$4-
78*640235e2SEnji Cooper		cat <<EOF
79*640235e2SEnji Cooper			X=$1
80*640235e2SEnji Cooper		EOF
81*640235e2SEnji Cooper		cat <<\EOF
82*640235e2SEnji Cooper			Y=$4
83*640235e2SEnji Cooper		EOF
84*640235e2SEnji Cooper	DONE
85*640235e2SEnji Cooper	atf_check -s exit:0 -o match:ARGS=4 -o match:'-X- -- -- -Y-' \
86*640235e2SEnji Cooper		-o match:X=X -o match:'Y=\$4' -e empty ${TEST_SH}
87*640235e2SEnji Cooper}
88*640235e2SEnji Cooper
89*640235e2SEnji Cooperatf_test_case do_input_redirections
90*640235e2SEnji Cooperdo_input_redirections_head()
91*640235e2SEnji Cooper{
92*640235e2SEnji Cooper	atf_set "descr" "Tests that simple input redirection works"
93*640235e2SEnji Cooper}
94*640235e2SEnji Cooperdo_input_redirections_body()
95*640235e2SEnji Cooper{
96*640235e2SEnji Cooper	printf '%s\n%s\n%s\nEND\n' 'First Line' 'Second Line' 'Line 3' >File
97*640235e2SEnji Cooper
98*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
99*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
100*640235e2SEnji Cooper		${TEST_SH} -c 'cat < File'
101*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
102*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
103*640235e2SEnji Cooper		${TEST_SH} -c 'cat <File'
104*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
105*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
106*640235e2SEnji Cooper		${TEST_SH} -c 'cat< File'
107*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
108*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
109*640235e2SEnji Cooper		${TEST_SH} -c 'cat < "File"'
110*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
111*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
112*640235e2SEnji Cooper		${TEST_SH} -c '< File cat'
113*640235e2SEnji Cooper
114*640235e2SEnji Cooper	ln File wc
115*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
116*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
117*640235e2SEnji Cooper		${TEST_SH} -c '< wc cat'
118*640235e2SEnji Cooper
119*640235e2SEnji Cooper	mv wc cat
120*640235e2SEnji Cooper	atf_check -s exit:0 -e empty -o match:4 \
121*640235e2SEnji Cooper		${TEST_SH} -c '< cat wc'
122*640235e2SEnji Cooper
123*640235e2SEnji Cooper
124*640235e2SEnji Cooper	cat <<- 'EOF' |
125*640235e2SEnji Cooper		for l in 1 2 3; do
126*640235e2SEnji Cooper			read line < File
127*640235e2SEnji Cooper			echo "$line"
128*640235e2SEnji Cooper		done
129*640235e2SEnji Cooper	EOF
130*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
131*640235e2SEnji Cooper		-o inline:'First Line\nFirst Line\nFirst Line\n' \
132*640235e2SEnji Cooper		${TEST_SH}
133*640235e2SEnji Cooper
134*640235e2SEnji Cooper	cat <<- 'EOF' |
135*640235e2SEnji Cooper		for l in 1 2 3; do
136*640235e2SEnji Cooper			read line
137*640235e2SEnji Cooper			echo "$line"
138*640235e2SEnji Cooper		done <File
139*640235e2SEnji Cooper	EOF
140*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
141*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\n' \
142*640235e2SEnji Cooper		${TEST_SH}
143*640235e2SEnji Cooper
144*640235e2SEnji Cooper	cat <<- 'EOF' |
145*640235e2SEnji Cooper		for l in 1 2 3; do
146*640235e2SEnji Cooper			read line < File
147*640235e2SEnji Cooper			echo "$line"
148*640235e2SEnji Cooper		done <File
149*640235e2SEnji Cooper	EOF
150*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
151*640235e2SEnji Cooper		-o inline:'First Line\nFirst Line\nFirst Line\n' \
152*640235e2SEnji Cooper		${TEST_SH}
153*640235e2SEnji Cooper
154*640235e2SEnji Cooper	cat <<- 'EOF' |
155*640235e2SEnji Cooper		line=
156*640235e2SEnji Cooper		while [ "$line" != END ]; do
157*640235e2SEnji Cooper			read line || exit 1
158*640235e2SEnji Cooper			echo "$line"
159*640235e2SEnji Cooper		done <File
160*640235e2SEnji Cooper	EOF
161*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
162*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
163*640235e2SEnji Cooper		${TEST_SH}
164*640235e2SEnji Cooper
165*640235e2SEnji Cooper	cat <<- 'EOF' |
166*640235e2SEnji Cooper		while :; do
167*640235e2SEnji Cooper			read line || exit 0
168*640235e2SEnji Cooper			echo "$line"
169*640235e2SEnji Cooper		done <File
170*640235e2SEnji Cooper	EOF
171*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
172*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
173*640235e2SEnji Cooper		${TEST_SH}
174*640235e2SEnji Cooper
175*640235e2SEnji Cooper	cat <<- 'EOF' |
176*640235e2SEnji Cooper		l=''
177*640235e2SEnji Cooper		while read line < File
178*640235e2SEnji Cooper		do
179*640235e2SEnji Cooper			echo "$line"
180*640235e2SEnji Cooper			l="${l}x"
181*640235e2SEnji Cooper			[ ${#l} -ge 3 ] && break
182*640235e2SEnji Cooper		done
183*640235e2SEnji Cooper		echo DONE
184*640235e2SEnji Cooper	EOF
185*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
186*640235e2SEnji Cooper		-o inline:'First Line\nFirst Line\nFirst Line\nDONE\n' \
187*640235e2SEnji Cooper		${TEST_SH}
188*640235e2SEnji Cooper
189*640235e2SEnji Cooper	cat <<- 'EOF' |
190*640235e2SEnji Cooper		while read line
191*640235e2SEnji Cooper		do
192*640235e2SEnji Cooper			echo "$line"
193*640235e2SEnji Cooper		done <File
194*640235e2SEnji Cooper		echo DONE
195*640235e2SEnji Cooper	EOF
196*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
197*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nEND\nDONE\n' \
198*640235e2SEnji Cooper		${TEST_SH}
199*640235e2SEnji Cooper
200*640235e2SEnji Cooper	cat <<- 'EOF' |
201*640235e2SEnji Cooper		l=''
202*640235e2SEnji Cooper		while read line
203*640235e2SEnji Cooper		do
204*640235e2SEnji Cooper			echo "$line"
205*640235e2SEnji Cooper			l="${l}x"
206*640235e2SEnji Cooper			[ ${#l} -ge 3 ] && break
207*640235e2SEnji Cooper		done <File
208*640235e2SEnji Cooper		echo DONE
209*640235e2SEnji Cooper	EOF
210*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
211*640235e2SEnji Cooper		-o inline:'First Line\nSecond Line\nLine 3\nDONE\n' ${TEST_SH}
212*640235e2SEnji Cooper
213*640235e2SEnji Cooper	cat <<- 'EOF' |
214*640235e2SEnji Cooper		l=''
215*640235e2SEnji Cooper		while read line1 <File
216*640235e2SEnji Cooper		do
217*640235e2SEnji Cooper			read line2
218*640235e2SEnji Cooper			echo "$line1":"$line2"
219*640235e2SEnji Cooper			l="${l}x"
220*640235e2SEnji Cooper			[ ${#l} -ge 2 ] && break
221*640235e2SEnji Cooper		done <File
222*640235e2SEnji Cooper		echo DONE
223*640235e2SEnji Cooper	EOF
224*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
225*640235e2SEnji Cooper	    -o inline:'First Line:First Line\nFirst Line:Second Line\nDONE\n' \
226*640235e2SEnji Cooper		${TEST_SH}
227*640235e2SEnji Cooper}
228*640235e2SEnji Cooper
229*640235e2SEnji Cooperatf_test_case do_output_redirections
230*640235e2SEnji Cooperdo_output_redirections_head()
231*640235e2SEnji Cooper{
232*640235e2SEnji Cooper	atf_set "descr" "Test Output redirections"
233*640235e2SEnji Cooper}
234*640235e2SEnji Cooperdo_output_redirections_body()
235*640235e2SEnji Cooper{
236*640235e2SEnji Coopernl='
237*640235e2SEnji Cooper'
238*640235e2SEnji Cooper	T=0
239*640235e2SEnji Cooper	i() { T=$(expr "$T" + 1); }
240*640235e2SEnji Cooper
241*640235e2SEnji Cooper	rm -f Output 2>/dev/null || :
242*640235e2SEnji Cooper	test -f Output && atf_fail "Unable to remove Output file"
243*640235e2SEnji Cooper#1
244*640235e2SEnji Cooper	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '> Output'
245*640235e2SEnji Cooper	test -f Output || atf_fail "#$T: Did not make Output file"
246*640235e2SEnji Cooper#2
247*640235e2SEnji Cooper	rm -f Output 2>/dev/null || :
248*640235e2SEnji Cooper	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>> Output'
249*640235e2SEnji Cooper	test -f Output || atf_fail "#$T: Did not make Output file"
250*640235e2SEnji Cooper#3
251*640235e2SEnji Cooper	rm -f Output 2>/dev/null || :
252*640235e2SEnji Cooper	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>| Output'
253*640235e2SEnji Cooper	test -f Output || atf_fail "#$T: Did not make Output file"
254*640235e2SEnji Cooper
255*640235e2SEnji Cooper#4
256*640235e2SEnji Cooper	rm -f Output 2>/dev/null || :
257*640235e2SEnji Cooper	i
258*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello >Output'
259*640235e2SEnji Cooper	test -s Output || atf_fail "#$T: Did not make non-empty Output file"
260*640235e2SEnji Cooper	test "$(cat Output)" = "Hello" ||
261*640235e2SEnji Cooper	  atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
262*640235e2SEnji Cooper#5
263*640235e2SEnji Cooper	i
264*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello>!Output'
265*640235e2SEnji Cooper	test -s Output || atf_fail "#$T: Did not make non-empty Output file"
266*640235e2SEnji Cooper	test "$(cat Output)" = "Hello" ||
267*640235e2SEnji Cooper	  atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
268*640235e2SEnji Cooper#6
269*640235e2SEnji Cooper	i
270*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Bye >>Output'
271*640235e2SEnji Cooper	test -s Output || atf_fail "#$T: Removed Output file"
272*640235e2SEnji Cooper	test "$(cat Output)" = "Hello${nl}Bye" || atf_fail \
273*640235e2SEnji Cooper	  "#$T: Incorrect Output: Should be 'Hello\\nBye' is '$(cat Output)'"
274*640235e2SEnji Cooper#7
275*640235e2SEnji Cooper	i; atf_check -s exit:0 -o inline:'line 1\nline 2\n' -e empty \
276*640235e2SEnji Cooper		${TEST_SH} -c \
277*640235e2SEnji Cooper		'echo line 1 > Output; echo line 2 >> Output; cat Output'
278*640235e2SEnji Cooper	test "$(cat Output)" = "line 1${nl}line 2" || atf_fail \
279*640235e2SEnji Cooper	 "#$T: Incorrect Output: Should be 'line 1\\nline 2' is '$(cat Output)'"
280*640235e2SEnji Cooper#8
281*640235e2SEnji Cooper	i; atf_check -s exit:0 -o inline:'line 2\n' -e empty \
282*640235e2SEnji Cooper		${TEST_SH} -c 'echo line 1 > Output; echo line 2'
283*640235e2SEnji Cooper	test "$(cat Output)" = "line 1" || atf_fail \
284*640235e2SEnji Cooper	    "#$T: Incorrect Output: Should be 'line 1' is '$(cat Output)'"
285*640235e2SEnji Cooper#9
286*640235e2SEnji Cooper	i; atf_check -s exit:0 -o empty -e empty \
287*640235e2SEnji Cooper		${TEST_SH} -c '(echo line 1; echo line 2 > Out2) > Out1'
288*640235e2SEnji Cooper	test "$(cat Out1)" = "line 1" || atf_fail \
289*640235e2SEnji Cooper	    "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
290*640235e2SEnji Cooper	test "$(cat Out2)" = "line 2" || atf_fail \
291*640235e2SEnji Cooper	    "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
292*640235e2SEnji Cooper#10
293*640235e2SEnji Cooper	i; atf_check -s exit:0 -o empty -e empty \
294*640235e2SEnji Cooper		${TEST_SH} -c '{ echo line 1; echo line 2 > Out2;} > Out1'
295*640235e2SEnji Cooper	test "$(cat Out1)" = "line 1" || atf_fail \
296*640235e2SEnji Cooper	    "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
297*640235e2SEnji Cooper	test "$(cat Out2)" = "line 2" || atf_fail \
298*640235e2SEnji Cooper	    "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
299*640235e2SEnji Cooper#11
300*640235e2SEnji Cooper	i; rm -f Out1 Out2 2>/dev/null || :
301*640235e2SEnji Cooper	cat <<- 'EOF' |
302*640235e2SEnji Cooper		for arg in 'line 1' 'line 2' 'line 3'
303*640235e2SEnji Cooper		do
304*640235e2SEnji Cooper			echo "$arg"
305*640235e2SEnji Cooper			echo "$arg" > Out1
306*640235e2SEnji Cooper		done > Out2
307*640235e2SEnji Cooper	EOF
308*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH}
309*640235e2SEnji Cooper	test "$(cat Out1)" = "line 3" || atf_fail \
310*640235e2SEnji Cooper		"#$T:  Incorrect Out1: Should be 'line 3' is '$(cat Out1)'"
311*640235e2SEnji Cooper	test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
312*640235e2SEnji Cooper    "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
313*640235e2SEnji Cooper#12
314*640235e2SEnji Cooper	i; rm -f Out1 Out2 2>/dev/null || :
315*640235e2SEnji Cooper	cat <<- 'EOF' |
316*640235e2SEnji Cooper		for arg in 'line 1' 'line 2' 'line 3'
317*640235e2SEnji Cooper		do
318*640235e2SEnji Cooper			echo "$arg"
319*640235e2SEnji Cooper			echo "$arg" >> Out1
320*640235e2SEnji Cooper		done > Out2
321*640235e2SEnji Cooper	EOF
322*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH}
323*640235e2SEnji Cooper	test "$(cat Out1)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
324*640235e2SEnji Cooper    "#$T: Incorrect Out1: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out1)'"
325*640235e2SEnji Cooper	test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
326*640235e2SEnji Cooper    "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
327*640235e2SEnji Cooper}
328*640235e2SEnji Cooper
329*640235e2SEnji Cooperatf_test_case fd_redirections
330*640235e2SEnji Cooperfd_redirections_head()
331*640235e2SEnji Cooper{
332*640235e2SEnji Cooper	atf_set "descr" "Tests redirections to/from specific descriptors"
333*640235e2SEnji Cooper}
334*640235e2SEnji Cooperfd_redirections_body()
335*640235e2SEnji Cooper{
336*640235e2SEnji Cooper	atf_require_prog /bin/echo
337*640235e2SEnji Cooper
338*640235e2SEnji Cooper	cat <<- 'DONE' > helper.sh
339*640235e2SEnji Cooper		f() {
340*640235e2SEnji Cooper			/bin/echo nothing "$1" >& "$1"
341*640235e2SEnji Cooper		}
342*640235e2SEnji Cooper		for n
343*640235e2SEnji Cooper		do
344*640235e2SEnji Cooper			eval "f $n $n"'> file-$n'
345*640235e2SEnji Cooper		done
346*640235e2SEnji Cooper	DONE
347*640235e2SEnji Cooper	cat <<- 'DONE' > reread.sh
348*640235e2SEnji Cooper		f() {
349*640235e2SEnji Cooper			(read -r var; echo "${var}") <&"$1"
350*640235e2SEnji Cooper		}
351*640235e2SEnji Cooper		for n
352*640235e2SEnji Cooper		do
353*640235e2SEnji Cooper			x=$( eval "f $n $n"'< file-$n' )
354*640235e2SEnji Cooper			test "${x}" = "nothing $n" || echo "$n"
355*640235e2SEnji Cooper		done
356*640235e2SEnji Cooper	DONE
357*640235e2SEnji Cooper
358*640235e2SEnji Cooper	validate()
359*640235e2SEnji Cooper	{
360*640235e2SEnji Cooper	    for n
361*640235e2SEnji Cooper	    do
362*640235e2SEnji Cooper		test -e "file-$n" || atf_fail "file-$n not created"
363*640235e2SEnji Cooper		C=$(cat file-"$n")
364*640235e2SEnji Cooper		test "$C" = "nothing $n" ||
365*640235e2SEnji Cooper			atf_fail "file-$n contains '$C' not 'nothing $n'"
366*640235e2SEnji Cooper	    done
367*640235e2SEnji Cooper	}
368*640235e2SEnji Cooper
369*640235e2SEnji Cooper	atf_check -s exit:0 -e empty -o empty \
370*640235e2SEnji Cooper		${TEST_SH} helper.sh 1 2 3 4 5 6 7 8 9
371*640235e2SEnji Cooper	validate 1 2 3 4 5 6 7 8 9
372*640235e2SEnji Cooper	atf_check -s exit:0 -e empty -o empty \
373*640235e2SEnji Cooper		${TEST_SH} reread.sh 3 4 5 6 7 8 9
374*640235e2SEnji Cooper
375*640235e2SEnji Cooper	L=$(ulimit -n)
376*640235e2SEnji Cooper	if [ "$L" -ge 30 ]
377*640235e2SEnji Cooper	then
378*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
379*640235e2SEnji Cooper			${TEST_SH} helper.sh 10 15 19 20 25 29
380*640235e2SEnji Cooper		validate 10 15 19 20 25 29
381*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
382*640235e2SEnji Cooper			${TEST_SH} reread.sh 10 15 19 20 25 29
383*640235e2SEnji Cooper	fi
384*640235e2SEnji Cooper	if [ "$L" -ge 100 ]
385*640235e2SEnji Cooper	then
386*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
387*640235e2SEnji Cooper			${TEST_SH} helper.sh 32 33 49 50 51 63 64 65 77 88 99
388*640235e2SEnji Cooper		validate 32 33 49 50 51 63 64 65 77 88 99
389*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
390*640235e2SEnji Cooper			${TEST_SH} reread.sh 32 33 49 50 51 63 64 65 77 88 99
391*640235e2SEnji Cooper	fi
392*640235e2SEnji Cooper	if [ "$L" -ge 500 ]
393*640235e2SEnji Cooper	then
394*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
395*640235e2SEnji Cooper			${TEST_SH} helper.sh 100 101 199 200 222 333 444 499
396*640235e2SEnji Cooper		validate 100 101 199 200 222 333 444 499
397*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
398*640235e2SEnji Cooper			${TEST_SH} reread.sh 100 101 199 200 222 333 444 499
399*640235e2SEnji Cooper	fi
400*640235e2SEnji Cooper	if [ "$L" -gt 1005 ]
401*640235e2SEnji Cooper	then
402*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
403*640235e2SEnji Cooper			${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
404*640235e2SEnji Cooper		validate 1000 1001 1002 1003 1004 1005
405*640235e2SEnji Cooper		atf_check -s exit:0 -e empty -o empty \
406*640235e2SEnji Cooper			${TEST_SH} reread.sh 1000 1001 1002 1003 1004 1005
407*640235e2SEnji Cooper	fi
408*640235e2SEnji Cooper}
409*640235e2SEnji Cooper
410*640235e2SEnji Cooperatf_test_case local_redirections
411*640235e2SEnji Cooperlocal_redirections_head()
412*640235e2SEnji Cooper{
413*640235e2SEnji Cooper	atf_set "descr" \
414*640235e2SEnji Cooper	    "Tests that exec can reassign file descriptors in the shell itself"
415*640235e2SEnji Cooper}
416*640235e2SEnji Cooperlocal_redirections_body()
417*640235e2SEnji Cooper{
418*640235e2SEnji Cooper	cat <<- 'DONE' > helper.sh
419*640235e2SEnji Cooper		for f
420*640235e2SEnji Cooper		do
421*640235e2SEnji Cooper			eval "exec $f"'> file-$f'
422*640235e2SEnji Cooper		done
423*640235e2SEnji Cooper
424*640235e2SEnji Cooper		for f
425*640235e2SEnji Cooper		do
426*640235e2SEnji Cooper			printf '%s\n' "Hello $f" >&"$f"
427*640235e2SEnji Cooper		done
428*640235e2SEnji Cooper
429*640235e2SEnji Cooper		for f
430*640235e2SEnji Cooper		do
431*640235e2SEnji Cooper			eval "exec $f"'>&-'
432*640235e2SEnji Cooper		done
433*640235e2SEnji Cooper
434*640235e2SEnji Cooper		for f
435*640235e2SEnji Cooper		do
436*640235e2SEnji Cooper			eval "exec $f"'< file-$f'
437*640235e2SEnji Cooper		done
438*640235e2SEnji Cooper
439*640235e2SEnji Cooper		for f
440*640235e2SEnji Cooper		do
441*640235e2SEnji Cooper			exec <& "$f"
442*640235e2SEnji Cooper			read -r var || echo >&2 "No data in file-$f"
443*640235e2SEnji Cooper			read -r x && echo >&2 "Too much data in file-${f}: $x"
444*640235e2SEnji Cooper			test "${var}" = "Hello $f" ||
445*640235e2SEnji Cooper			    echo >&2 "file-$f contains '${var}' not 'Hello $f'"
446*640235e2SEnji Cooper		done
447*640235e2SEnji Cooper	DONE
448*640235e2SEnji Cooper
449*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty \
450*640235e2SEnji Cooper		${TEST_SH} helper.sh 3 4 5 6 7 8 9
451*640235e2SEnji Cooper
452*640235e2SEnji Cooper	L=$(ulimit -n)
453*640235e2SEnji Cooper	if [ "$L" -ge 30 ]
454*640235e2SEnji Cooper	then
455*640235e2SEnji Cooper		atf_check -s exit:0 -o empty -e empty \
456*640235e2SEnji Cooper			${TEST_SH} helper.sh 10 11 13 15 16 19 20 28 29
457*640235e2SEnji Cooper	fi
458*640235e2SEnji Cooper	if [ "$L" -ge 100 ]
459*640235e2SEnji Cooper	then
460*640235e2SEnji Cooper		atf_check -s exit:0 -o empty -e empty \
461*640235e2SEnji Cooper			${TEST_SH} helper.sh 30 31 32 63 64 65 77 88 99
462*640235e2SEnji Cooper	fi
463*640235e2SEnji Cooper	if [ "$L" -ge 500 ]
464*640235e2SEnji Cooper	then
465*640235e2SEnji Cooper		atf_check -s exit:0 -o empty -e empty \
466*640235e2SEnji Cooper			${TEST_SH} helper.sh 100 101 111 199 200 201 222 333 499
467*640235e2SEnji Cooper	fi
468*640235e2SEnji Cooper	if [ "$L" -ge 1005 ]
469*640235e2SEnji Cooper	then
470*640235e2SEnji Cooper		atf_check -s exit:0 -o empty -e empty \
471*640235e2SEnji Cooper			${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
472*640235e2SEnji Cooper	fi
473*640235e2SEnji Cooper}
474*640235e2SEnji Cooper
475*640235e2SEnji Cooperatf_test_case named_fd_redirections
476*640235e2SEnji Coopernamed_fd_redirections_head()
477*640235e2SEnji Cooper{
478*640235e2SEnji Cooper	atf_set "descr" "Tests redirections to /dev/stdout (etc)"
479*640235e2SEnji Cooper
480*640235e2SEnji Cooper}
481*640235e2SEnji Coopernamed_fd_redirections_body()
482*640235e2SEnji Cooper{
483*640235e2SEnji Cooper	if test -c /dev/stdout
484*640235e2SEnji Cooper	then
485*640235e2SEnji Cooper		atf_check -s exit:0 -o inline:'OK\n' -e empty \
486*640235e2SEnji Cooper			${TEST_SH} -c 'echo OK >/dev/stdout'
487*640235e2SEnji Cooper		atf_check -s exit:0 -o inline:'OK\n' -e empty \
488*640235e2SEnji Cooper			${TEST_SH} -c '/bin/echo OK >/dev/stdout'
489*640235e2SEnji Cooper	fi
490*640235e2SEnji Cooper
491*640235e2SEnji Cooper	if test -c /dev/stdin
492*640235e2SEnji Cooper	then
493*640235e2SEnji Cooper		atf_require_prog cat
494*640235e2SEnji Cooper
495*640235e2SEnji Cooper		echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
496*640235e2SEnji Cooper			${TEST_SH} -c 'read var </dev/stdin; echo $var'
497*640235e2SEnji Cooper		echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
498*640235e2SEnji Cooper			${TEST_SH} -c 'cat </dev/stdin'
499*640235e2SEnji Cooper	fi
500*640235e2SEnji Cooper
501*640235e2SEnji Cooper	if test -c /dev/stderr
502*640235e2SEnji Cooper	then
503*640235e2SEnji Cooper		atf_check -s exit:0 -e inline:'OK\n' -o empty \
504*640235e2SEnji Cooper			${TEST_SH} -c 'echo OK 2>/dev/stderr >&2'
505*640235e2SEnji Cooper		atf_check -s exit:0 -e inline:'OK\n' -o empty \
506*640235e2SEnji Cooper			${TEST_SH} -c '/bin/echo OK 2>/dev/stderr >&2'
507*640235e2SEnji Cooper	fi
508*640235e2SEnji Cooper
509*640235e2SEnji Cooper	if test -c /dev/fd/8 && test -c /dev/fd/9
510*640235e2SEnji Cooper	then
511*640235e2SEnji Cooper		atf_check -s exit:0 -o inline:'EIGHT\n' -e empty \
512*640235e2SEnji Cooper			${TEST_SH} -c 'printf "%s\n" EIGHT 8>&1 >/dev/fd/8 |
513*640235e2SEnji Cooper					cat 9<&0 </dev/fd/9'
514*640235e2SEnji Cooper	fi
515*640235e2SEnji Cooper
516*640235e2SEnji Cooper	return 0
517*640235e2SEnji Cooper}
518*640235e2SEnji Cooper
519*640235e2SEnji Cooperatf_test_case redir_in_case
520*640235e2SEnji Cooperredir_in_case_head()
521*640235e2SEnji Cooper{
522*640235e2SEnji Cooper	atf_set "descr" "Tests that sh(1) allows just redirections " \
523*640235e2SEnji Cooper	                "in case statements. (PR bin/48631)"
524*640235e2SEnji Cooper}
525*640235e2SEnji Cooperredir_in_case_body()
526*640235e2SEnji Cooper{
527*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty \
528*640235e2SEnji Cooper	    ${TEST_SH} -c 'case x in (whatever) >foo;; esac'
529*640235e2SEnji Cooper
530*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty \
531*640235e2SEnji Cooper	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac'
532*640235e2SEnji Cooper
533*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty \
534*640235e2SEnji Cooper	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac'
535*640235e2SEnji Cooper
536*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty \
537*640235e2SEnji Cooper	    ${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac'
538*640235e2SEnji Cooper}
539*640235e2SEnji Cooper
540*640235e2SEnji Cooperatf_test_case incorrect_redirections
541*640235e2SEnji Cooperincorrect_redirections_head()
542*640235e2SEnji Cooper{
543*640235e2SEnji Cooper	atf_set "descr" "Tests that sh(1) correctly ignores non-redirections"
544*640235e2SEnji Cooper}
545*640235e2SEnji Cooperincorrect_redirections_body() {
546*640235e2SEnji Cooper
547*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo>'
548*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'read foo<'
549*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>'
550*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
551*640235e2SEnji Cooper		'echo x > '"$nl"
552*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
553*640235e2SEnji Cooper		'read x < '"$nl"
554*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
555*640235e2SEnji Cooper		'echo x <> '"$nl"
556*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
557*640235e2SEnji Cooper		'echo x >< anything'
558*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
559*640235e2SEnji Cooper		'echo x >>< anything'
560*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
561*640235e2SEnji Cooper		'echo x >|< anything'
562*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
563*640235e2SEnji Cooper		'echo x > ; read x < /dev/null || echo bad'
564*640235e2SEnji Cooper	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
565*640235e2SEnji Cooper		'read x < & echo y > /dev/null; wait && echo bad'
566*640235e2SEnji Cooper
567*640235e2SEnji Cooper	rm -f Output 2>/dev/null || :
568*640235e2SEnji Cooper	atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \
569*640235e2SEnji Cooper		${TEST_SH} -c 'echo A Line \> Output'
570*640235e2SEnji Cooper	test -f Output && atf_file "File 'Output' appeared and should not have"
571*640235e2SEnji Cooper
572*640235e2SEnji Cooper	rm -f Output 2>/dev/null || :
573*640235e2SEnji Cooper	atf_check -s exit:0 -e empty -o empty \
574*640235e2SEnji Cooper		${TEST_SH} -c 'echo A Line \>> Output'
575*640235e2SEnji Cooper	test -f Output || atf_file "File 'Output' not created when it should"
576*640235e2SEnji Cooper	test "$(cat Output)" = 'A Line >' || atf_fail \
577*640235e2SEnji Cooper		"Output file contains '$(cat Output)' instead of '"'A Line >'\'
578*640235e2SEnji Cooper
579*640235e2SEnji Cooper	rm -f Output \> 2>/dev/null || :
580*640235e2SEnji Cooper	atf_check -s exit:0 -e empty -o empty \
581*640235e2SEnji Cooper		${TEST_SH} -c 'echo A Line >\> Output'
582*640235e2SEnji Cooper	test -f Output && atf_file "File 'Output' appeared and should not have"
583*640235e2SEnji Cooper	test -f '>' || atf_file "File '>' not created when it should"
584*640235e2SEnji Cooper	test "$(cat '>')" = 'A Line Output' || atf_fail \
585*640235e2SEnji Cooper	    "Output file ('>') contains '$(cat '>')' instead of 'A Line Output'"
586*640235e2SEnji Cooper}
587*640235e2SEnji Cooper
588*640235e2SEnji Cooper# Many more tests in t_here, so here we have just rudimentary checks
589*640235e2SEnji Cooperatf_test_case redir_here_doc
590*640235e2SEnji Cooperredir_here_doc_head()
591*640235e2SEnji Cooper{
592*640235e2SEnji Cooper	atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \
593*640235e2SEnji Cooper	                "input redirections"
594*640235e2SEnji Cooper}
595*640235e2SEnji Cooperredir_here_doc_body()
596*640235e2SEnji Cooper{
597*640235e2SEnji Cooper	# nb: the printf is not executed, it is data
598*640235e2SEnji Cooper	cat <<- 'DONE' |
599*640235e2SEnji Cooper		cat <<EOF
600*640235e2SEnji Cooper			printf '%s\n' 'hello\n'
601*640235e2SEnji Cooper		EOF
602*640235e2SEnji Cooper	DONE
603*640235e2SEnji Cooper	atf_check -s exit:0 -o match:printf -o match:'hello\\n' \
604*640235e2SEnji Cooper		-e empty ${TEST_SH}
605*640235e2SEnji Cooper}
606*640235e2SEnji Cooper
607*640235e2SEnji Cooperatf_test_case subshell_redirections
608*640235e2SEnji Coopersubshell_redirections_head()
609*640235e2SEnji Cooper{
610*640235e2SEnji Cooper	atf_set "descr" "Tests redirection interactions between shell and " \
611*640235e2SEnji Cooper			"its sub-shell(s)"
612*640235e2SEnji Cooper}
613*640235e2SEnji Coopersubshell_redirections_body()
614*640235e2SEnji Cooper{
615*640235e2SEnji Cooper	atf_require_prog cat
616*640235e2SEnji Cooper
617*640235e2SEnji Cooper	LIM=$(ulimit -n)
618*640235e2SEnji Cooper
619*640235e2SEnji Cooper	cat <<- 'DONE' |
620*640235e2SEnji Cooper		exec 6>output-file
621*640235e2SEnji Cooper
622*640235e2SEnji Cooper		( printf "hello\n" >&6 )
623*640235e2SEnji Cooper
624*640235e2SEnji Cooper		exec 8<output-file
625*640235e2SEnji Cooper
626*640235e2SEnji Cooper		( read hello <&8 ; test hello = "$hello" || echo >&2 Hello )
627*640235e2SEnji Cooper
628*640235e2SEnji Cooper		( printf "bye-bye\n" >&6 )
629*640235e2SEnji Cooper
630*640235e2SEnji Cooper		( exec 8<&- )
631*640235e2SEnji Cooper		read bye <&8 || echo >&2 "Closed?"
632*640235e2SEnji Cooper		echo Bye="$bye"
633*640235e2SEnji Cooper	DONE
634*640235e2SEnji Cooper	atf_check -s exit:0 -o match:Bye=bye-bye -e empty \
635*640235e2SEnji Cooper		${TEST_SH}
636*640235e2SEnji Cooper
637*640235e2SEnji Cooper	cat <<- 'DONE' |
638*640235e2SEnji Cooper		for arg in one-4 two-24 three-14
639*640235e2SEnji Cooper		do
640*640235e2SEnji Cooper			fd=${arg#*-}
641*640235e2SEnji Cooper			file=${arg%-*}
642*640235e2SEnji Cooper			eval "exec ${fd}>${file}"
643*640235e2SEnji Cooper		done
644*640235e2SEnji Cooper
645*640235e2SEnji Cooper		for arg in one-5 two-7 three-19
646*640235e2SEnji Cooper		do
647*640235e2SEnji Cooper			fd=${arg#*-}
648*640235e2SEnji Cooper			file=${arg%-*}
649*640235e2SEnji Cooper			eval "exec ${fd}<${file}"
650*640235e2SEnji Cooper		done
651*640235e2SEnji Cooper
652*640235e2SEnji Cooper		(
653*640235e2SEnji Cooper			echo line-1 >&4
654*640235e2SEnji Cooper			echo line-2 >&24
655*640235e2SEnji Cooper			echo line-3 >&14
656*640235e2SEnji Cooper			echo go
657*640235e2SEnji Cooper		) | (
658*640235e2SEnji Cooper			read go
659*640235e2SEnji Cooper			read x <&5
660*640235e2SEnji Cooper			read y <&7
661*640235e2SEnji Cooper			read z <&19
662*640235e2SEnji Cooper
663*640235e2SEnji Cooper			printf "%s\n" "${x}" "${y}" "${z}"
664*640235e2SEnji Cooper		)
665*640235e2SEnji Cooper	DONE
666*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
667*640235e2SEnji Cooper		-e empty ${TEST_SH}
668*640235e2SEnji Cooper
669*640235e2SEnji Cooper	cat <<- 'DONE' |
670*640235e2SEnji Cooper		for arg in one-4-5 two-6-7 three-8-9 four-11-10 five-3-12
671*640235e2SEnji Cooper		do
672*640235e2SEnji Cooper			ofd=${arg##*-}
673*640235e2SEnji Cooper			file=${arg%-*}
674*640235e2SEnji Cooper			ifd=${file#*-}
675*640235e2SEnji Cooper			file=${file%-*}
676*640235e2SEnji Cooper			eval "exec ${ofd}>${file}"
677*640235e2SEnji Cooper			eval "exec ${ifd}<${file}"
678*640235e2SEnji Cooper		done
679*640235e2SEnji Cooper
680*640235e2SEnji Cooper		( ( ( echo line-1 >& 13 ) 13>&12 ) 12>&5 ) >stdout 2>errout
681*640235e2SEnji Cooper		( ( ( echo line-2 >& 4) 13>&12 ) 4>&7 ) >>stdout 2>>errout
682*640235e2SEnji Cooper		( ( ( echo line-3 >& 6) 8>&1 6>&11 >&12) 11>&9 >&7 ) >>stdout
683*640235e2SEnji Cooper
684*640235e2SEnji Cooper		( ( ( cat <&13 >&12 ) 13<&8 12>&10 ) 10>&1 8<&6 ) 6<&4
685*640235e2SEnji Cooper		( ( ( cat <&4 ) <&4 6<&8 8<&11  )
686*640235e2SEnji Cooper			<&4 4<&6 6<&8 8<&11 ) <&4 4<&6 6<&8 8<&11 11<&3
687*640235e2SEnji Cooper		( ( ( cat <&7 >&1 ) 7<&6 >&10 ) 10>&2 6<&8 ) 2>&1
688*640235e2SEnji Cooper	DONE
689*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
690*640235e2SEnji Cooper		-e empty ${TEST_SH}
691*640235e2SEnji Cooper}
692*640235e2SEnji Cooper
693*640235e2SEnji Cooperatf_test_case ulimit_redirection_interaction
694*640235e2SEnji Cooperulimit_redirection_interaction_head()
695*640235e2SEnji Cooper{
696*640235e2SEnji Cooper	atf_set "descr" "Tests interactions between redirect and ulimit -n "
697*640235e2SEnji Cooper}
698*640235e2SEnji Cooperulimit_redirection_interaction_body()
699*640235e2SEnji Cooper{
700*640235e2SEnji Cooper	atf_require_prog ls
701*640235e2SEnji Cooper
702*640235e2SEnji Cooper	cat <<- 'DONE' > helper.sh
703*640235e2SEnji Cooper		oLIM=$(ulimit -n)
704*640235e2SEnji Cooper		HRD=$(ulimit -H -n)
705*640235e2SEnji Cooper		test "${oLIM}" -lt "${HRD}"  && ulimit -n "${HRD}"
706*640235e2SEnji Cooper		LIM=$(ulimit -n)
707*640235e2SEnji Cooper
708*640235e2SEnji Cooper		FDs=
709*640235e2SEnji Cooper		LFD=-1
710*640235e2SEnji Cooper		while [ ${LIM} -gt 16 ]
711*640235e2SEnji Cooper		do
712*640235e2SEnji Cooper			FD=$(( ${LIM} - 1 ))
713*640235e2SEnji Cooper			if [ "${FD}" -eq "${LFD}" ]; then
714*640235e2SEnji Cooper				echo >&2 "Infinite loop... (busted $(( )) ??)"
715*640235e2SEnji Cooper				exit 1
716*640235e2SEnji Cooper			fi
717*640235e2SEnji Cooper			LFD="${FD}"
718*640235e2SEnji Cooper
719*640235e2SEnji Cooper			eval "exec ${FD}"'> /dev/null'
720*640235e2SEnji Cooper			FDs="${FD}${FDs:+ }${FDs}"
721*640235e2SEnji Cooper
722*640235e2SEnji Cooper			(
723*640235e2SEnji Cooper				FD=$(( ${LIM} + 1 ))
724*640235e2SEnji Cooper				eval "exec ${FD}"'> /dev/null'
725*640235e2SEnji Cooper				echo "Reached unreachable command"
726*640235e2SEnji Cooper			) 2>/dev/null && echo >&2 "Opened beyond limit!"
727*640235e2SEnji Cooper
728*640235e2SEnji Cooper			(eval 'ls 2>&1 3>&1 4>&1 5>&1 '"${FD}"'>&1') >&"${FD}"
729*640235e2SEnji Cooper
730*640235e2SEnji Cooper			LIM=$(( ${LIM} / 2 ))
731*640235e2SEnji Cooper			ulimit -S -n "${LIM}"
732*640235e2SEnji Cooper		done
733*640235e2SEnji Cooper
734*640235e2SEnji Cooper		# Even though ulimit has been reduced, open fds should work
735*640235e2SEnji Cooper		for FD in ${FDs}
736*640235e2SEnji Cooper		do
737*640235e2SEnji Cooper			echo ${FD} in ${FDs} >&"${FD}" || exit 1
738*640235e2SEnji Cooper		done
739*640235e2SEnji Cooper
740*640235e2SEnji Cooper		ulimit -S -n "${oLIM}"
741*640235e2SEnji Cooper
742*640235e2SEnji Cooper		# maybe more later...
743*640235e2SEnji Cooper
744*640235e2SEnji Cooper	DONE
745*640235e2SEnji Cooper
746*640235e2SEnji Cooper	atf_check -s exit:0 -o empty -e empty ${TEST_SH} helper.sh
747*640235e2SEnji Cooper}
748*640235e2SEnji Cooper
749*640235e2SEnji Cooperatf_test_case validate_fn_redirects
750*640235e2SEnji Coopervalidate_fn_redirects_head()
751*640235e2SEnji Cooper{
752*640235e2SEnji Cooper	# These test cases inspired by PR bin/48875 and the sh
753*640235e2SEnji Cooper	# changes that were required to fix it.
754*640235e2SEnji Cooper
755*640235e2SEnji Cooper	atf_set "descr" "Tests various redirections applied to functions " \
756*640235e2SEnji Cooper		"See PR bin/48875"
757*640235e2SEnji Cooper}
758*640235e2SEnji Coopervalidate_fn_redirects_body()
759*640235e2SEnji Cooper{
760*640235e2SEnji Cooper	cat <<- 'DONE' > f-def
761*640235e2SEnji Cooper		f() {
762*640235e2SEnji Cooper			printf '%s\n' In-Func
763*640235e2SEnji Cooper		}
764*640235e2SEnji Cooper	DONE
765*640235e2SEnji Cooper
766*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nsuccess1\n' -e empty \
767*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; f ; printf '%s\n' success1"
768*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'success2\n' -e empty \
769*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; f >/dev/null; printf '%s\n' success2"
770*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'success3\n' -e empty \
771*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; f >&- ; printf '%s\n' success3"
772*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nsuccess4\n' -e empty \
773*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; f & wait; printf '%s\n' success4"
774*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'success5\n' -e empty \
775*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; f >&- & wait; printf '%s\n' success5"
776*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess6\n' -e empty \
777*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; f;f; printf '%s\n' success6"
778*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess7\n' -e empty \
779*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; { f;f;}; printf '%s\n' success7"
780*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess8\n' -e empty \
781*640235e2SEnji Cooper		${TEST_SH} -c ". ./f-def; { f;f;}& wait; printf '%s\n' success8"
782*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nsuccess9\n' -e empty \
783*640235e2SEnji Cooper		${TEST_SH} -c \
784*640235e2SEnji Cooper		   ". ./f-def; { f>/dev/null;f;}& wait; printf '%s\n' success9"
785*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'In-Func\nsuccess10\n' -e empty \
786*640235e2SEnji Cooper		${TEST_SH} -c \
787*640235e2SEnji Cooper		   ". ./f-def; { f;f>/dev/null;}& wait; printf '%s\n' success10"
788*640235e2SEnji Cooper
789*640235e2SEnji Cooper	# This one tests the issue etcupdate had with the original 48875 fix
790*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'Func a\nFunc b\nFunc c\n' -e empty \
791*640235e2SEnji Cooper		${TEST_SH} -c '
792*640235e2SEnji Cooper			f() {
793*640235e2SEnji Cooper				echo Func "$1"
794*640235e2SEnji Cooper			}
795*640235e2SEnji Cooper			exec 3<&0 4>&1
796*640235e2SEnji Cooper			( echo x-a; echo y-b; echo z-c ) |
797*640235e2SEnji Cooper			while read A
798*640235e2SEnji Cooper			do
799*640235e2SEnji Cooper				B=${A#?-}
800*640235e2SEnji Cooper				f "$B" <&3 >&4
801*640235e2SEnji Cooper			done >&2'
802*640235e2SEnji Cooper
803*640235e2SEnji Cooper	# And this tests a similar condition with that same fix
804*640235e2SEnji Cooper	cat  <<- 'DONE' >Script
805*640235e2SEnji Cooper		f() {
806*640235e2SEnji Cooper			printf '%s' " hello $1"
807*640235e2SEnji Cooper		}
808*640235e2SEnji Cooper		exec 3>&1
809*640235e2SEnji Cooper		echo $( for i in a b c
810*640235e2SEnji Cooper			do printf '%s' @$i; f $i >&3; done >foo
811*640235e2SEnji Cooper		)
812*640235e2SEnji Cooper		printf '%s\n' foo=$(cat foo)
813*640235e2SEnji Cooper	DONE
814*640235e2SEnji Cooper	atf_check -s exit:0 -e empty \
815*640235e2SEnji Cooper	    -o inline:' hello a hello b hello c\nfoo=@a@b@c\n' \
816*640235e2SEnji Cooper	    ${TEST_SH} Script
817*640235e2SEnji Cooper
818*640235e2SEnji Cooper	# Tests with sh reading stdin, which is not quite the same internal
819*640235e2SEnji Cooper	# mechanism.
820*640235e2SEnji Cooper	echo ". ./f-def || echo >&2 FAIL
821*640235e2SEnji Cooper		f
822*640235e2SEnji Cooper		printf '%s\n' stdin1
823*640235e2SEnji Cooper	"| atf_check -s exit:0 -o inline:'In-Func\nstdin1\n' -e empty ${TEST_SH}
824*640235e2SEnji Cooper
825*640235e2SEnji Cooper	echo '
826*640235e2SEnji Cooper		. ./f-def || echo >&2 FAIL
827*640235e2SEnji Cooper		f >&-
828*640235e2SEnji Cooper		printf "%s\n" stdin2
829*640235e2SEnji Cooper	' | atf_check -s exit:0 -o inline:'stdin2\n' -e empty ${TEST_SH}
830*640235e2SEnji Cooper
831*640235e2SEnji Cooper	cat <<- 'DONE' > fgh.def
832*640235e2SEnji Cooper		f() {
833*640235e2SEnji Cooper			echo -n f >&3
834*640235e2SEnji Cooper			sleep 4
835*640235e2SEnji Cooper			echo -n F >&3
836*640235e2SEnji Cooper		}
837*640235e2SEnji Cooper		g() {
838*640235e2SEnji Cooper			echo -n g >&3
839*640235e2SEnji Cooper			sleep 2
840*640235e2SEnji Cooper			echo -n G >&3
841*640235e2SEnji Cooper		}
842*640235e2SEnji Cooper		h() {
843*640235e2SEnji Cooper			echo -n h >&3
844*640235e2SEnji Cooper		}
845*640235e2SEnji Cooper	DONE
846*640235e2SEnji Cooper
847*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'fFgGh' -e empty \
848*640235e2SEnji Cooper		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
849*640235e2SEnji Cooper			exec 3>&1
850*640235e2SEnji Cooper			f; g; h'
851*640235e2SEnji Cooper
852*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'fghGF' -e empty \
853*640235e2SEnji Cooper		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
854*640235e2SEnji Cooper			exec 3>&1
855*640235e2SEnji Cooper			f & sleep 1; g & sleep 1; h; wait'
856*640235e2SEnji Cooper
857*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'fFgGhX Y\n' -e empty \
858*640235e2SEnji Cooper		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
859*640235e2SEnji Cooper			exec 3>&1
860*640235e2SEnji Cooper			echo X $( f ; g ; h ) Y'
861*640235e2SEnji Cooper
862*640235e2SEnji Cooper	# This one is the real test for PR bin/48875.  If the
863*640235e2SEnji Cooper	# cmdsub does not complete before f g (and h) exit,
864*640235e2SEnji Cooper	# then the 'F' & 'G' will precede 'X Y' in the output.
865*640235e2SEnji Cooper	# If the cmdsub finishes while f & g are still running,
866*640235e2SEnji Cooper	# then the X Y will appear before the F and G.
867*640235e2SEnji Cooper	# The trailing "sleep 3" is just so we catch all the
868*640235e2SEnji Cooper	# output (otherwise atf_check will be finished while
869*640235e2SEnji Cooper	# f & g are still sleeping).
870*640235e2SEnji Cooper
871*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty \
872*640235e2SEnji Cooper		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
873*640235e2SEnji Cooper			exec 3>&1
874*640235e2SEnji Cooper			echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
875*640235e2SEnji Cooper			sleep 3
876*640235e2SEnji Cooper			exec 4>&1 || echo FD_FAIL
877*640235e2SEnji Cooper			'
878*640235e2SEnji Cooper
879*640235e2SEnji Cooper	# Do the test again to verify it also all works reading stdin
880*640235e2SEnji Cooper	# (which is a slightly different path through the shell)
881*640235e2SEnji Cooper	echo '
882*640235e2SEnji Cooper		. ./fgh.def || echo >&2 FAIL
883*640235e2SEnji Cooper		exec 3>&1
884*640235e2SEnji Cooper		echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
885*640235e2SEnji Cooper		sleep 3
886*640235e2SEnji Cooper		exec 4>&1 || echo FD_FAIL
887*640235e2SEnji Cooper	' | atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty ${TEST_SH}
888*640235e2SEnji Cooper}
889*640235e2SEnji Cooper
890*640235e2SEnji Cooperatf_init_test_cases() {
891*640235e2SEnji Cooper	atf_add_test_case basic_test_method_test
892*640235e2SEnji Cooper	atf_add_test_case do_input_redirections
893*640235e2SEnji Cooper	atf_add_test_case do_output_redirections
894*640235e2SEnji Cooper	atf_add_test_case fd_redirections
895*640235e2SEnji Cooper	atf_add_test_case local_redirections
896*640235e2SEnji Cooper	atf_add_test_case incorrect_redirections
897*640235e2SEnji Cooper	atf_add_test_case named_fd_redirections
898*640235e2SEnji Cooper	atf_add_test_case redir_here_doc
899*640235e2SEnji Cooper	atf_add_test_case redir_in_case
900*640235e2SEnji Cooper	atf_add_test_case subshell_redirections
901*640235e2SEnji Cooper	atf_add_test_case ulimit_redirection_interaction
902*640235e2SEnji Cooper	atf_add_test_case validate_fn_redirects
903*640235e2SEnji Cooper}
904