Home | History | Annotate | Line # | Download | only in sh
t_redir.sh revision 1.8
      1  1.8       kre # $NetBSD: t_redir.sh,v 1.8 2016/05/11 17:43:17 kre 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.4  christos atf_test_case fd_redirections
    330  1.4  christos fd_redirections_head()
    331  1.4  christos {
    332  1.4  christos 	atf_set "descr" "Tests redirections to/from specific descriptors"
    333  1.4  christos }
    334  1.4  christos fd_redirections_body()
    335  1.4  christos {
    336  1.6  christos 	atf_require_prog /bin/echo
    337  1.6  christos 
    338  1.6  christos 	cat <<- 'DONE' > helper.sh
    339  1.6  christos 		f() {
    340  1.6  christos 			/bin/echo nothing "$1" >& "$1"
    341  1.6  christos 		}
    342  1.6  christos 		for n
    343  1.6  christos 		do
    344  1.6  christos 			eval "f $n $n"'> file-$n'
    345  1.6  christos 		done
    346  1.6  christos 	DONE
    347  1.6  christos 	cat <<- 'DONE' > reread.sh
    348  1.6  christos 		f() {
    349  1.6  christos 			(read -r var; echo "${var}") <&"$1"
    350  1.6  christos 		}
    351  1.6  christos 		for n
    352  1.6  christos 		do
    353  1.6  christos 			x=$( eval "f $n $n"'< file-$n' )
    354  1.6  christos 			test "${x}" = "nothing $n" || echo "$n"
    355  1.6  christos 		done
    356  1.6  christos 	DONE
    357  1.6  christos 
    358  1.6  christos 	validate()
    359  1.6  christos 	{
    360  1.6  christos 	    for n
    361  1.6  christos 	    do
    362  1.6  christos 		test -e "file-$n" || atf_fail "file-$n not created"
    363  1.6  christos 		C=$(cat file-"$n")
    364  1.6  christos 		test "$C" = "nothing $n" ||
    365  1.6  christos 			atf_fail "file-$n contains '$C' not 'nothing $n'"
    366  1.6  christos 	    done
    367  1.6  christos 	}
    368  1.6  christos 
    369  1.6  christos 	atf_check -s exit:0 -e empty -o empty \
    370  1.6  christos 		${TEST_SH} helper.sh 1 2 3 4 5 6 7 8 9
    371  1.6  christos 	validate 1 2 3 4 5 6 7 8 9
    372  1.6  christos 	atf_check -s exit:0 -e empty -o empty \
    373  1.6  christos 		${TEST_SH} reread.sh 3 4 5 6 7 8 9
    374  1.6  christos 
    375  1.6  christos 	L=$(ulimit -n)
    376  1.6  christos 	if [ "$L" -ge 30 ]
    377  1.6  christos 	then
    378  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    379  1.6  christos 			${TEST_SH} helper.sh 10 15 19 20 25 29
    380  1.6  christos 		validate 10 15 19 20 25 29
    381  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    382  1.6  christos 			${TEST_SH} reread.sh 10 15 19 20 25 29
    383  1.6  christos 	fi
    384  1.6  christos 	if [ "$L" -ge 100 ]
    385  1.6  christos 	then
    386  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    387  1.6  christos 			${TEST_SH} helper.sh 32 33 49 50 51 63 64 65 77 88 99
    388  1.6  christos 		validate 32 33 49 50 51 63 64 65 77 88 99
    389  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    390  1.6  christos 			${TEST_SH} reread.sh 32 33 49 50 51 63 64 65 77 88 99
    391  1.6  christos 	fi
    392  1.6  christos 	if [ "$L" -ge 500 ]
    393  1.6  christos 	then
    394  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    395  1.6  christos 			${TEST_SH} helper.sh 100 101 199 200 222 333 444 499
    396  1.6  christos 		validate 100 101 199 200 222 333 444 499
    397  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    398  1.6  christos 			${TEST_SH} reread.sh 100 101 199 200 222 333 444 499
    399  1.6  christos 	fi
    400  1.6  christos 	if [ "$L" -gt 1005 ]
    401  1.6  christos 	then
    402  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    403  1.6  christos 			${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
    404  1.6  christos 		validate 1000 1001 1002 1003 1004 1005
    405  1.6  christos 		atf_check -s exit:0 -e empty -o empty \
    406  1.6  christos 			${TEST_SH} reread.sh 1000 1001 1002 1003 1004 1005
    407  1.6  christos 	fi
    408  1.4  christos } 
    409  1.4  christos 
    410  1.4  christos atf_test_case local_redirections
    411  1.4  christos local_redirections_head()
    412  1.4  christos {
    413  1.4  christos 	atf_set "descr" \
    414  1.4  christos 	    "Tests that exec can reassign file descriptors in the shell itself"
    415  1.4  christos }
    416  1.4  christos local_redirections_body()
    417  1.4  christos {
    418  1.6  christos 	cat <<- 'DONE' > helper.sh
    419  1.6  christos 		for f
    420  1.6  christos 		do
    421  1.6  christos 			eval "exec $f"'> file-$f'
    422  1.6  christos 		done
    423  1.6  christos 
    424  1.6  christos 		for f
    425  1.6  christos 		do
    426  1.6  christos 			printf '%s\n' "Hello $f" >&"$f"
    427  1.6  christos 		done
    428  1.6  christos 
    429  1.6  christos 		for f
    430  1.6  christos 		do
    431  1.6  christos 			eval "exec $f"'>&-'
    432  1.6  christos 		done
    433  1.6  christos 
    434  1.6  christos 		for f
    435  1.6  christos 		do
    436  1.6  christos 			eval "exec $f"'< file-$f'
    437  1.6  christos 		done
    438  1.6  christos 
    439  1.6  christos 		for f
    440  1.6  christos 		do
    441  1.6  christos 			exec <& "$f"
    442  1.6  christos 			read -r var || echo >&2 "No data in file-$f"
    443  1.6  christos 			read -r x && echo >&2 "Too much data in file-${f}: $x"
    444  1.6  christos 			test "${var}" = "Hello $f" ||
    445  1.6  christos 			    echo >&2 "file-$f contains '${var}' not 'Hello $f'"
    446  1.6  christos 		done
    447  1.6  christos 	DONE
    448  1.6  christos 
    449  1.6  christos 	atf_check -s exit:0 -o empty -e empty \
    450  1.6  christos 		${TEST_SH} helper.sh 3 4 5 6 7 8 9
    451  1.6  christos 
    452  1.6  christos 	L=$(ulimit -n)
    453  1.6  christos 	if [ "$L" -ge 30 ]
    454  1.6  christos 	then
    455  1.6  christos 		atf_check -s exit:0 -o empty -e empty \
    456  1.6  christos 			${TEST_SH} helper.sh 10 11 13 15 16 19 20 28 29
    457  1.6  christos 	fi
    458  1.6  christos 	if [ "$L" -ge 100 ]
    459  1.6  christos 	then
    460  1.6  christos 		atf_check -s exit:0 -o empty -e empty \
    461  1.6  christos 			${TEST_SH} helper.sh 30 31 32 63 64 65 77 88 99
    462  1.6  christos 	fi
    463  1.6  christos 	if [ "$L" -ge 500 ]
    464  1.6  christos 	then
    465  1.6  christos 		atf_check -s exit:0 -o empty -e empty \
    466  1.6  christos 			${TEST_SH} helper.sh 100 101 111 199 200 201 222 333 499
    467  1.6  christos 	fi
    468  1.6  christos 	if [ "$L" -ge 1005 ]
    469  1.6  christos 	then
    470  1.6  christos 		atf_check -s exit:0 -o empty -e empty \
    471  1.6  christos 			${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
    472  1.6  christos 	fi
    473  1.4  christos }
    474  1.4  christos 
    475  1.7       kre atf_test_case named_fd_redirections
    476  1.7       kre named_fd_redirections_head()
    477  1.7       kre {
    478  1.7       kre 	atf_set "descr" "Tests redirections to /dev/stdout (etc)"
    479  1.7       kre 
    480  1.7       kre }
    481  1.7       kre named_fd_redirections_body()
    482  1.7       kre {
    483  1.7       kre 	if test -c /dev/stdout
    484  1.7       kre 	then
    485  1.7       kre 		atf_check -s exit:0 -o inline:'OK\n' -e empty \
    486  1.7       kre 			${TEST_SH} -c 'echo OK >/dev/stdout'
    487  1.7       kre 		atf_check -s exit:0 -o inline:'OK\n' -e empty \
    488  1.7       kre 			${TEST_SH} -c '/bin/echo OK >/dev/stdout'
    489  1.7       kre 	fi
    490  1.7       kre 
    491  1.7       kre 	if test -c /dev/stdin
    492  1.7       kre 	then
    493  1.7       kre 		atf_require_prog cat
    494  1.7       kre 
    495  1.7       kre 		echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
    496  1.7       kre 			${TEST_SH} -c 'read var </dev/stdin; echo $var'
    497  1.7       kre 		echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
    498  1.7       kre 			${TEST_SH} -c 'cat </dev/stdin'
    499  1.7       kre 	fi
    500  1.7       kre 
    501  1.7       kre 	if test -c /dev/stderr
    502  1.7       kre 	then
    503  1.7       kre 		atf_check -s exit:0 -e inline:'OK\n' -o empty \
    504  1.7       kre 			${TEST_SH} -c 'echo OK 2>/dev/stderr >&2'
    505  1.7       kre 		atf_check -s exit:0 -e inline:'OK\n' -o empty \
    506  1.7       kre 			${TEST_SH} -c '/bin/echo OK 2>/dev/stderr >&2'
    507  1.7       kre 	fi
    508  1.7       kre 
    509  1.7       kre 	if test -c /dev/fd/8 && test -c /dev/fd/9
    510  1.7       kre 	then
    511  1.7       kre 		atf_check -s exit:0 -o inline:'EIGHT\n' -e empty \
    512  1.7       kre 			${TEST_SH} -c 'printf "%s\n" EIGHT 8>&1 >/dev/fd/8 |
    513  1.7       kre 					cat 9<&0 </dev/fd/9'
    514  1.7       kre 	fi
    515  1.7       kre 
    516  1.7       kre 	return 0
    517  1.7       kre }
    518  1.7       kre 
    519  1.1  christos atf_test_case redir_in_case
    520  1.4  christos redir_in_case_head()
    521  1.4  christos {
    522  1.4  christos 	atf_set "descr" "Tests that sh(1) allows just redirections " \
    523  1.1  christos 	                "in case statements. (PR bin/48631)"
    524  1.1  christos }
    525  1.4  christos redir_in_case_body()
    526  1.4  christos {
    527  1.2  christos 	atf_check -s exit:0 -o empty -e empty \
    528  1.2  christos 	    ${TEST_SH} -c 'case x in (whatever) >foo;; esac'
    529  1.4  christos 
    530  1.4  christos 	atf_check -s exit:0 -o empty -e empty \
    531  1.4  christos 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac'
    532  1.4  christos 
    533  1.4  christos 	atf_check -s exit:0 -o empty -e empty \
    534  1.4  christos 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac'
    535  1.4  christos 
    536  1.4  christos 	atf_check -s exit:0 -o empty -e empty \
    537  1.4  christos 	    ${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac'
    538  1.2  christos }
    539  1.2  christos 
    540  1.4  christos atf_test_case incorrect_redirections
    541  1.4  christos incorrect_redirections_head()
    542  1.4  christos {
    543  1.4  christos 	atf_set "descr" "Tests that sh(1) correctly ignores non-redirections"
    544  1.4  christos }
    545  1.4  christos incorrect_redirections_body() {
    546  1.4  christos 
    547  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo>'
    548  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'read foo<'
    549  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>'
    550  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    551  1.4  christos 		'echo x > '"$nl"
    552  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    553  1.4  christos 		'read x < '"$nl"
    554  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    555  1.4  christos 		'echo x <> '"$nl"
    556  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    557  1.4  christos 		'echo x >< anything'
    558  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    559  1.4  christos 		'echo x >>< anything'
    560  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    561  1.4  christos 		'echo x >|< anything'
    562  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    563  1.4  christos 		'echo x > ; read x < /dev/null || echo bad'
    564  1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    565  1.4  christos 		'read x < & echo y > /dev/null; wait && echo bad'
    566  1.4  christos 
    567  1.4  christos 	rm -f Output 2>/dev/null || :
    568  1.4  christos 	atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \
    569  1.4  christos 		${TEST_SH} -c 'echo A Line \> Output'
    570  1.4  christos 	test -f Output && atf_file "File 'Output' appeared and should not have"
    571  1.4  christos 
    572  1.4  christos 	rm -f Output 2>/dev/null || :
    573  1.4  christos 	atf_check -s exit:0 -e empty -o empty \
    574  1.4  christos 		${TEST_SH} -c 'echo A Line \>> Output'
    575  1.4  christos 	test -f Output || atf_file "File 'Output' not created when it should"
    576  1.4  christos 	test "$(cat Output)" = 'A Line >' || atf_fail \
    577  1.4  christos 		"Output file contains '$(cat Output)' instead of '"'A Line >'\'
    578  1.4  christos 
    579  1.4  christos 	rm -f Output \> 2>/dev/null || :
    580  1.4  christos 	atf_check -s exit:0 -e empty -o empty \
    581  1.4  christos 		${TEST_SH} -c 'echo A Line >\> Output'
    582  1.4  christos 	test -f Output && atf_file "File 'Output' appeared and should not have"
    583  1.4  christos 	test -f '>' || atf_file "File '>' not created when it should"
    584  1.4  christos 	test "$(cat '>')" = 'A Line Output' || atf_fail \
    585  1.4  christos 	    "Output file ('>') contains '$(cat '>')' instead of 'A Line Output'"
    586  1.4  christos }
    587  1.4  christos 
    588  1.4  christos # Many more tests in t_here, so here we have just rudimentary checks
    589  1.2  christos atf_test_case redir_here_doc
    590  1.4  christos redir_here_doc_head()
    591  1.4  christos {
    592  1.2  christos 	atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \
    593  1.2  christos 	                "input redirections"
    594  1.2  christos }
    595  1.4  christos redir_here_doc_body()
    596  1.4  christos {
    597  1.4  christos 	# nb: the printf is not executed, it is data
    598  1.3  christos 	cat <<- 'DONE' |
    599  1.3  christos 		cat <<EOF
    600  1.3  christos 			printf '%s\n' 'hello\n'
    601  1.3  christos 		EOF
    602  1.3  christos 	DONE
    603  1.4  christos 	atf_check -s exit:0 -o match:printf -o match:'hello\\n' \
    604  1.4  christos 		-e empty ${TEST_SH} 
    605  1.4  christos }
    606  1.4  christos 
    607  1.4  christos atf_test_case subshell_redirections
    608  1.4  christos subshell_redirections_head()
    609  1.4  christos {
    610  1.4  christos 	atf_set "descr" "Tests redirection interactions between shell and " \
    611  1.4  christos 			"its sub-shell(s)"
    612  1.4  christos }
    613  1.4  christos subshell_redirections_body()
    614  1.4  christos {
    615  1.6  christos 	atf_require_prog cat
    616  1.6  christos 
    617  1.6  christos 	LIM=$(ulimit -n)
    618  1.6  christos 
    619  1.6  christos 	cat <<- 'DONE' |
    620  1.6  christos 		exec 6>output-file
    621  1.6  christos 
    622  1.6  christos 		( printf "hello\n" >&6 )
    623  1.6  christos 
    624  1.6  christos 		exec 8<output-file
    625  1.6  christos 
    626  1.6  christos 		( read hello <&8 ; test hello = "$hello" || echo >&2 Hello )
    627  1.6  christos 
    628  1.6  christos 		( printf "bye-bye\n" >&6 )
    629  1.6  christos 
    630  1.6  christos 		( exec 8<&- )
    631  1.6  christos 		read bye <&8 || echo >&2 "Closed?"
    632  1.6  christos 		echo Bye="$bye"
    633  1.6  christos 	DONE
    634  1.6  christos 	atf_check -s exit:0 -o match:Bye=bye-bye -e empty \
    635  1.6  christos 		${TEST_SH}
    636  1.6  christos 
    637  1.6  christos 	cat <<- 'DONE' |
    638  1.6  christos 		for arg in one-4 two-24 three-14
    639  1.6  christos 		do
    640  1.6  christos 			fd=${arg#*-}
    641  1.6  christos 			file=${arg%-*}
    642  1.6  christos 			eval "exec ${fd}>${file}"
    643  1.6  christos 		done
    644  1.6  christos 
    645  1.6  christos 		for arg in one-5 two-7 three-19
    646  1.6  christos 		do
    647  1.6  christos 			fd=${arg#*-}
    648  1.6  christos 			file=${arg%-*}
    649  1.6  christos 			eval "exec ${fd}<${file}"
    650  1.6  christos 		done
    651  1.6  christos 
    652  1.6  christos 		(
    653  1.6  christos 			echo line-1 >&4
    654  1.6  christos 			echo line-2 >&24
    655  1.6  christos 			echo line-3 >&14
    656  1.6  christos 			echo go
    657  1.6  christos 		) | (
    658  1.6  christos 			read go
    659  1.6  christos 			read x <&5
    660  1.6  christos 			read y <&7
    661  1.6  christos 			read z <&19
    662  1.6  christos 
    663  1.6  christos 			printf "%s\n" "${x}" "${y}" "${z}"
    664  1.6  christos 		)
    665  1.6  christos 	DONE
    666  1.6  christos 	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
    667  1.6  christos 		-e empty ${TEST_SH}
    668  1.6  christos 
    669  1.6  christos 	cat <<- 'DONE' |
    670  1.6  christos 		for arg in one-4-5 two-6-7 three-8-9 four-11-10 five-3-12
    671  1.6  christos 		do
    672  1.6  christos 			ofd=${arg##*-}
    673  1.6  christos 			file=${arg%-*}
    674  1.6  christos 			ifd=${file#*-}
    675  1.6  christos 			file=${file%-*}
    676  1.6  christos 			eval "exec ${ofd}>${file}"
    677  1.6  christos 			eval "exec ${ifd}<${file}"
    678  1.6  christos 		done
    679  1.6  christos 
    680  1.6  christos 		( ( ( echo line-1 >& 13 ) 13>&12 ) 12>&5 ) >stdout 2>errout
    681  1.6  christos 		( ( ( echo line-2 >& 4) 13>&12 ) 4>&7 ) >>stdout 2>>errout
    682  1.6  christos 		( ( ( echo line-3 >& 6) 8>&1 6>&11 >&12) 11>&9 >&7 ) >>stdout
    683  1.6  christos 
    684  1.6  christos 		( ( ( cat <&13 >&12 ) 13<&8 12>&10 ) 10>&1 8<&6 ) 6<&4
    685  1.6  christos 		( ( ( cat <&4 ) <&4 6<&8 8<&11  )
    686  1.6  christos 			<&4 4<&6 6<&8 8<&11 ) <&4 4<&6 6<&8 8<&11 11<&3
    687  1.6  christos 		( ( ( cat <&7 >&1 ) 7<&6 >&10 ) 10>&2 6<&8 ) 2>&1
    688  1.6  christos 	DONE
    689  1.6  christos 	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
    690  1.6  christos 		-e empty ${TEST_SH}
    691  1.6  christos }
    692  1.6  christos 
    693  1.6  christos atf_test_case ulimit_redirection_interaction
    694  1.6  christos ulimit_redirection_interaction_head()
    695  1.6  christos {
    696  1.6  christos 	atf_set "descr" "Tests interactions between redirect and ulimit -n "
    697  1.6  christos }
    698  1.6  christos ulimit_redirection_interaction_body()
    699  1.6  christos {
    700  1.6  christos 	atf_require_prog ls
    701  1.6  christos 
    702  1.6  christos 	cat <<- 'DONE' > helper.sh
    703  1.6  christos 		oLIM=$(ulimit -n)
    704  1.6  christos 		HRD=$(ulimit -H -n)
    705  1.6  christos 		test "${oLIM}" -lt "${HRD}"  && ulimit -n "${HRD}"
    706  1.6  christos 		LIM=$(ulimit -n)
    707  1.6  christos 
    708  1.6  christos 		FDs=
    709  1.6  christos 		LFD=-1
    710  1.6  christos 		while [ ${LIM} -gt 16 ]
    711  1.6  christos 		do
    712  1.6  christos 			FD=$(( ${LIM} - 1 ))
    713  1.6  christos 			if [ "${FD}" -eq "${LFD}" ]; then
    714  1.6  christos 				echo >&2 "Infinite loop... (busted $(( )) ??)"
    715  1.6  christos 				exit 1
    716  1.6  christos 			fi
    717  1.6  christos 			LFD="${FD}"
    718  1.6  christos 
    719  1.6  christos 			eval "exec ${FD}"'> /dev/null'
    720  1.6  christos 			FDs="${FD}${FDs:+ }${FDs}"
    721  1.6  christos 
    722  1.6  christos 			(
    723  1.6  christos 				FD=$(( ${LIM} + 1 ))
    724  1.6  christos 				eval "exec ${FD}"'> /dev/null'
    725  1.6  christos 				echo "Reached unreachable command"
    726  1.6  christos 			) 2>/dev/null && echo >&2 "Opened beyond limit!"
    727  1.6  christos 
    728  1.6  christos 			(eval 'ls 2>&1 3>&1 4>&1 5>&1 '"${FD}"'>&1') >&"${FD}"
    729  1.6  christos 
    730  1.6  christos 			LIM=$(( ${LIM} / 2 ))
    731  1.6  christos 			ulimit -S -n "${LIM}"
    732  1.6  christos 		done
    733  1.6  christos 
    734  1.6  christos 		# Even though ulimit has been reduced, open fds should work
    735  1.6  christos 		for FD in ${FDs}
    736  1.6  christos 		do
    737  1.6  christos 			echo ${FD} in ${FDs} >&"${FD}" || exit 1
    738  1.6  christos 		done
    739  1.6  christos 
    740  1.6  christos 		ulimit -S -n "${oLIM}"
    741  1.6  christos 
    742  1.6  christos 		# maybe more later...
    743  1.6  christos 
    744  1.6  christos 	DONE
    745  1.6  christos 
    746  1.6  christos 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} helper.sh
    747  1.1  christos }
    748  1.1  christos 
    749  1.7       kre atf_test_case validate_fn_redirects
    750  1.7       kre validate_fn_redirects_head()
    751  1.7       kre {
    752  1.7       kre 	# These test cases inspired by PR bin/48875 and the sh
    753  1.7       kre 	# changes that were required to fix it.
    754  1.7       kre 
    755  1.7       kre 	atf_set "descr" "Tests various redirections applied to functions " \
    756  1.7       kre 		"See PR bin/48875"
    757  1.7       kre }
    758  1.7       kre validate_fn_redirects_body()
    759  1.7       kre {
    760  1.7       kre 	cat <<- 'DONE' > f-def
    761  1.7       kre 		f() {
    762  1.7       kre 			printf '%s\n' In-Func
    763  1.7       kre 		}
    764  1.7       kre 	DONE
    765  1.7       kre 
    766  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess1\n' -e empty \
    767  1.7       kre 		${TEST_SH} -c ". ./f-def; f ; printf '%s\n' success1"
    768  1.7       kre 	atf_check -s exit:0 -o inline:'success2\n' -e empty \
    769  1.7       kre 		${TEST_SH} -c ". ./f-def; f >/dev/null; printf '%s\n' success2"
    770  1.7       kre 	atf_check -s exit:0 -o inline:'success3\n' -e empty \
    771  1.7       kre 		${TEST_SH} -c ". ./f-def; f >&- ; printf '%s\n' success3"
    772  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess4\n' -e empty \
    773  1.7       kre 		${TEST_SH} -c ". ./f-def; f & wait; printf '%s\n' success4"
    774  1.7       kre 	atf_check -s exit:0 -o inline:'success5\n' -e empty \
    775  1.7       kre 		${TEST_SH} -c ". ./f-def; f >&- & wait; printf '%s\n' success5"
    776  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess6\n' -e empty \
    777  1.7       kre 		${TEST_SH} -c ". ./f-def; f;f; printf '%s\n' success6"
    778  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess7\n' -e empty \
    779  1.7       kre 		${TEST_SH} -c ". ./f-def; { f;f;}; printf '%s\n' success7"
    780  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess8\n' -e empty \
    781  1.7       kre 		${TEST_SH} -c ". ./f-def; { f;f;}& wait; printf '%s\n' success8"
    782  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess9\n' -e empty \
    783  1.7       kre 		${TEST_SH} -c \
    784  1.7       kre 		   ". ./f-def; { f>/dev/null;f;}& wait; printf '%s\n' success9"
    785  1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess10\n' -e empty \
    786  1.7       kre 		${TEST_SH} -c \
    787  1.7       kre 		   ". ./f-def; { f;f>/dev/null;}& wait; printf '%s\n' success10"
    788  1.7       kre 
    789  1.8       kre 	# This one tests the issue etcupdate had with the original 48875 fix
    790  1.8       kre 	atf_check -s exit:0 -o inline:'Func a\nFunc b\nFunc c\n' -e empty \
    791  1.8       kre 		${TEST_SH} -c '
    792  1.8       kre 			f() {
    793  1.8       kre 				echo Func "$1"
    794  1.8       kre 			}
    795  1.8       kre 			exec 3<&0 4>&1
    796  1.8       kre 			( echo x-a; echo y-b; echo z-c ) |
    797  1.8       kre 			while read A
    798  1.8       kre 			do
    799  1.8       kre 				B=${A#?-}
    800  1.8       kre 				f "$B" <&3 >&4
    801  1.8       kre 			done >&2'
    802  1.8       kre 
    803  1.7       kre 	# Tests with sh reading stdin, which is not quite the same internal
    804  1.7       kre 	# mechanism.
    805  1.7       kre 	echo ". ./f-def || echo >&2 FAIL
    806  1.7       kre 		f
    807  1.7       kre 		printf '%s\n' stdin1
    808  1.7       kre 	"| atf_check -s exit:0 -o inline:'In-Func\nstdin1\n' -e empty ${TEST_SH}
    809  1.7       kre 
    810  1.7       kre 	echo '
    811  1.7       kre 		. ./f-def || echo >&2 FAIL
    812  1.7       kre 		f >&-
    813  1.8       kre 		printf "%s\n" stdin2
    814  1.7       kre 	' | atf_check -s exit:0 -o inline:'stdin2\n' -e empty ${TEST_SH}
    815  1.7       kre 
    816  1.7       kre 	cat <<- 'DONE' > fgh.def
    817  1.7       kre 		f() {
    818  1.7       kre 			echo -n f >&3
    819  1.7       kre 			sleep 4
    820  1.7       kre 			echo -n F >&3
    821  1.7       kre 		}
    822  1.7       kre 		g() {
    823  1.7       kre 			echo -n g >&3
    824  1.7       kre 			sleep 2
    825  1.7       kre 			echo -n G >&3
    826  1.7       kre 		}
    827  1.7       kre 		h() {
    828  1.7       kre 			echo -n h >&3
    829  1.7       kre 		}
    830  1.7       kre 	DONE
    831  1.7       kre 
    832  1.7       kre 	atf_check -s exit:0 -o inline:'fFgGh' -e empty \
    833  1.7       kre 		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
    834  1.7       kre 			exec 3>&1
    835  1.7       kre 			f; g; h'
    836  1.7       kre 
    837  1.7       kre 	atf_check -s exit:0 -o inline:'fghGF' -e empty \
    838  1.7       kre 		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
    839  1.7       kre 			exec 3>&1
    840  1.7       kre 			f & sleep 1; g & sleep 1; h; wait'
    841  1.7       kre 
    842  1.7       kre 	atf_check -s exit:0 -o inline:'fFgGhX Y\n' -e empty \
    843  1.7       kre 		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
    844  1.7       kre 			exec 3>&1
    845  1.7       kre 			echo X $( f ; g ; h ) Y'
    846  1.7       kre 
    847  1.7       kre 	# This one is the real test for PR bin/48875.  If the
    848  1.7       kre 	# cmdsub does not complete before f g (and h) exit,
    849  1.7       kre 	# then the 'F' & 'G' will precede 'X Y' in the output.
    850  1.7       kre 	# If the cmdsub finishes while f & g are still running,
    851  1.7       kre 	# then the X Y will appear before the F and G.
    852  1.7       kre 	# The trailing "sleep 3" is just so we catch all the
    853  1.7       kre 	# output (otherwise atf_check will be finished while
    854  1.7       kre 	# f & g are still sleeping).
    855  1.7       kre 
    856  1.7       kre 	atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty \
    857  1.7       kre 		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
    858  1.7       kre 			exec 3>&1
    859  1.7       kre 			echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
    860  1.7       kre 			sleep 3
    861  1.7       kre 			exec 4>&1 || echo FD_FAIL
    862  1.7       kre 			'
    863  1.7       kre 
    864  1.7       kre 	# Do the test again to verify it also all works reading stdin
    865  1.7       kre 	# (which is a slightly different path through the shell)
    866  1.7       kre 	echo '
    867  1.7       kre 		. ./fgh.def || echo >&2 FAIL
    868  1.7       kre 		exec 3>&1
    869  1.7       kre 		echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
    870  1.7       kre 		sleep 3
    871  1.7       kre 		exec 4>&1 || echo FD_FAIL
    872  1.7       kre 	' | atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty ${TEST_SH}
    873  1.7       kre }
    874  1.7       kre 
    875  1.1  christos atf_init_test_cases() {
    876  1.4  christos 	atf_add_test_case basic_test_method_test
    877  1.4  christos 	atf_add_test_case do_input_redirections
    878  1.4  christos 	atf_add_test_case do_output_redirections
    879  1.4  christos 	atf_add_test_case fd_redirections
    880  1.4  christos 	atf_add_test_case local_redirections
    881  1.4  christos 	atf_add_test_case incorrect_redirections
    882  1.7       kre 	atf_add_test_case named_fd_redirections
    883  1.4  christos 	atf_add_test_case redir_here_doc
    884  1.1  christos 	atf_add_test_case redir_in_case
    885  1.4  christos 	atf_add_test_case subshell_redirections
    886  1.6  christos 	atf_add_test_case ulimit_redirection_interaction
    887  1.7       kre 	atf_add_test_case validate_fn_redirects
    888  1.1  christos }
    889