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