Home | History | Annotate | Line # | Download | only in sh
t_redir.sh revision 1.13
      1  1.13       kre # $NetBSD: t_redir.sh,v 1.13 2021/11/16 11:15:26 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.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.12       kre 			${TEST_SH} -c 'read var </dev/stdin; echo $var' ||
    565  1.12       kre 				atf_fail "/dev/stdin test 1"
    566   1.7       kre 		echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
    567  1.12       kre 			${TEST_SH} -c 'cat </dev/stdin' ||
    568  1.12       kre 				atf_fail "/dev/stdin test 2"
    569   1.7       kre 	fi
    570   1.7       kre 
    571   1.7       kre 	if test -c /dev/stderr
    572   1.7       kre 	then
    573   1.7       kre 		atf_check -s exit:0 -e inline:'OK\n' -o empty \
    574   1.7       kre 			${TEST_SH} -c 'echo OK 2>/dev/stderr >&2'
    575   1.7       kre 		atf_check -s exit:0 -e inline:'OK\n' -o empty \
    576   1.7       kre 			${TEST_SH} -c '/bin/echo OK 2>/dev/stderr >&2'
    577   1.7       kre 	fi
    578   1.7       kre 
    579   1.7       kre 	if test -c /dev/fd/8 && test -c /dev/fd/9
    580   1.7       kre 	then
    581   1.7       kre 		atf_check -s exit:0 -o inline:'EIGHT\n' -e empty \
    582   1.7       kre 			${TEST_SH} -c 'printf "%s\n" EIGHT 8>&1 >/dev/fd/8 |
    583   1.7       kre 					cat 9<&0 </dev/fd/9'
    584   1.7       kre 	fi
    585   1.7       kre 
    586   1.7       kre 	return 0
    587   1.7       kre }
    588   1.7       kre 
    589   1.1  christos atf_test_case redir_in_case
    590   1.4  christos redir_in_case_head()
    591   1.4  christos {
    592   1.4  christos 	atf_set "descr" "Tests that sh(1) allows just redirections " \
    593   1.1  christos 	                "in case statements. (PR bin/48631)"
    594   1.1  christos }
    595   1.4  christos redir_in_case_body()
    596   1.4  christos {
    597   1.2  christos 	atf_check -s exit:0 -o empty -e empty \
    598   1.2  christos 	    ${TEST_SH} -c 'case x in (whatever) >foo;; esac'
    599   1.4  christos 
    600   1.4  christos 	atf_check -s exit:0 -o empty -e empty \
    601   1.4  christos 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac'
    602   1.4  christos 
    603   1.4  christos 	atf_check -s exit:0 -o empty -e empty \
    604   1.4  christos 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac'
    605   1.4  christos 
    606   1.4  christos 	atf_check -s exit:0 -o empty -e empty \
    607   1.4  christos 	    ${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac'
    608   1.2  christos }
    609   1.2  christos 
    610   1.4  christos atf_test_case incorrect_redirections
    611   1.4  christos incorrect_redirections_head()
    612   1.4  christos {
    613   1.4  christos 	atf_set "descr" "Tests that sh(1) correctly ignores non-redirections"
    614   1.4  christos }
    615   1.4  christos incorrect_redirections_body() {
    616   1.4  christos 
    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 'read foo<'
    619   1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>'
    620   1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    621   1.4  christos 		'echo x > '"$nl"
    622   1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    623   1.4  christos 		'read 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 <> '"$nl"
    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 >|< anything'
    632   1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    633   1.4  christos 		'echo x > ; read x < /dev/null || echo bad'
    634   1.4  christos 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    635   1.4  christos 		'read x < & echo y > /dev/null; wait && echo bad'
    636   1.4  christos 
    637   1.4  christos 	rm -f Output 2>/dev/null || :
    638   1.4  christos 	atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \
    639   1.4  christos 		${TEST_SH} -c 'echo A Line \> Output'
    640   1.4  christos 	test -f Output && atf_file "File 'Output' appeared and should not have"
    641   1.4  christos 
    642   1.4  christos 	rm -f Output 2>/dev/null || :
    643   1.4  christos 	atf_check -s exit:0 -e empty -o empty \
    644   1.4  christos 		${TEST_SH} -c 'echo A Line \>> Output'
    645   1.4  christos 	test -f Output || atf_file "File 'Output' not created when it should"
    646   1.4  christos 	test "$(cat Output)" = 'A Line >' || atf_fail \
    647   1.4  christos 		"Output file contains '$(cat Output)' instead of '"'A Line >'\'
    648   1.4  christos 
    649   1.4  christos 	rm -f Output \> 2>/dev/null || :
    650   1.4  christos 	atf_check -s exit:0 -e empty -o empty \
    651   1.4  christos 		${TEST_SH} -c 'echo A Line >\> Output'
    652   1.4  christos 	test -f Output && atf_file "File 'Output' appeared and should not have"
    653   1.4  christos 	test -f '>' || atf_file "File '>' not created when it should"
    654   1.4  christos 	test "$(cat '>')" = 'A Line Output' || atf_fail \
    655   1.4  christos 	    "Output file ('>') contains '$(cat '>')' instead of 'A Line Output'"
    656  1.10       kre 
    657  1.10       kre 	rm -fr OutDir
    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'
    660  1.10       kre 	atf-check -s not-exit:0 -o empty -e not-empty \
    661  1.10       kre 		${TEST_SH} -c ': > OutDir/stdout || printf foo; printf bar'
    662  1.10       kre 	atf-check -s exit:0 -o inline:bar -e not-empty \
    663  1.10       kre 		${TEST_SH} -c '> OutDir/stdout; printf bar'
    664  1.10       kre 	atf-check -s exit:0 -o inline:foobar -e not-empty \
    665  1.10       kre 		${TEST_SH} -c '> OutDir/stdout || printf foo; printf bar'
    666  1.10       kre 	atf-check -s exit:0 -o inline:bar -e not-empty \
    667  1.10       kre 		${TEST_SH} -c 'command : > OutDir/stdout; printf bar'
    668  1.10       kre 	atf-check -s exit:0 -o inline:foobar -e not-empty ${TEST_SH} -c \
    669  1.10       kre 		'command : > OutDir/stdout || printf foo; printf bar'
    670  1.10       kre 	atf-check -s not-exit:0 -o empty -e not-empty \
    671  1.10       kre 		${TEST_SH} -c ': <> OutDir/stdout; printf foo'
    672  1.10       kre 
    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'
    675  1.10       kre 	atf-check -s not-exit:0 -o empty -e not-empty \
    676  1.10       kre 		${TEST_SH} -c ': >&8 || printf foo; printf bar'
    677  1.10       kre 	atf-check -s exit:0 -o inline:bar -e not-empty \
    678  1.10       kre 		${TEST_SH} -c '>&8 ; printf bar'
    679  1.10       kre 	atf-check -s exit:0 -o inline:foobar -e not-empty \
    680  1.10       kre 		${TEST_SH} -c '>&8 || printf foo; printf bar'
    681  1.10       kre 	atf-check -s exit:0 -o inline:bar -e not-empty \
    682  1.10       kre 		${TEST_SH} -c 'command : >&7; printf bar'
    683  1.10       kre 	atf-check -s exit:0 -o inline:foobar -e not-empty ${TEST_SH} -c \
    684  1.10       kre 		'command : >&7 || printf foo; printf bar'
    685  1.10       kre 
    686  1.10       kre 	return 0
    687   1.4  christos }
    688   1.4  christos 
    689   1.4  christos # Many more tests in t_here, so here we have just rudimentary checks
    690   1.2  christos atf_test_case redir_here_doc
    691   1.4  christos redir_here_doc_head()
    692   1.4  christos {
    693   1.2  christos 	atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \
    694   1.2  christos 	                "input redirections"
    695   1.2  christos }
    696   1.4  christos redir_here_doc_body()
    697   1.4  christos {
    698   1.4  christos 	# nb: the printf is not executed, it is data
    699   1.3  christos 	cat <<- 'DONE' |
    700   1.3  christos 		cat <<EOF
    701   1.3  christos 			printf '%s\n' 'hello\n'
    702   1.3  christos 		EOF
    703   1.3  christos 	DONE
    704   1.4  christos 	atf_check -s exit:0 -o match:printf -o match:'hello\\n' \
    705   1.4  christos 		-e empty ${TEST_SH} 
    706   1.4  christos }
    707   1.4  christos 
    708   1.4  christos atf_test_case subshell_redirections
    709   1.4  christos subshell_redirections_head()
    710   1.4  christos {
    711   1.4  christos 	atf_set "descr" "Tests redirection interactions between shell and " \
    712   1.4  christos 			"its sub-shell(s)"
    713   1.4  christos }
    714   1.4  christos subshell_redirections_body()
    715   1.4  christos {
    716   1.6  christos 	atf_require_prog cat
    717   1.6  christos 
    718   1.6  christos 	LIM=$(ulimit -n)
    719   1.6  christos 
    720   1.6  christos 	cat <<- 'DONE' |
    721   1.6  christos 		exec 6>output-file
    722   1.6  christos 
    723   1.6  christos 		( printf "hello\n" >&6 )
    724   1.6  christos 
    725   1.6  christos 		exec 8<output-file
    726   1.6  christos 
    727   1.6  christos 		( read hello <&8 ; test hello = "$hello" || echo >&2 Hello )
    728   1.6  christos 
    729   1.6  christos 		( printf "bye-bye\n" >&6 )
    730   1.6  christos 
    731   1.6  christos 		( exec 8<&- )
    732   1.6  christos 		read bye <&8 || echo >&2 "Closed?"
    733   1.6  christos 		echo Bye="$bye"
    734   1.6  christos 	DONE
    735   1.6  christos 	atf_check -s exit:0 -o match:Bye=bye-bye -e empty \
    736   1.6  christos 		${TEST_SH}
    737   1.6  christos 
    738   1.6  christos 	cat <<- 'DONE' |
    739   1.6  christos 		for arg in one-4 two-24 three-14
    740   1.6  christos 		do
    741   1.6  christos 			fd=${arg#*-}
    742   1.6  christos 			file=${arg%-*}
    743   1.6  christos 			eval "exec ${fd}>${file}"
    744   1.6  christos 		done
    745   1.6  christos 
    746   1.6  christos 		for arg in one-5 two-7 three-19
    747   1.6  christos 		do
    748   1.6  christos 			fd=${arg#*-}
    749   1.6  christos 			file=${arg%-*}
    750   1.6  christos 			eval "exec ${fd}<${file}"
    751   1.6  christos 		done
    752   1.6  christos 
    753   1.6  christos 		(
    754   1.6  christos 			echo line-1 >&4
    755   1.6  christos 			echo line-2 >&24
    756   1.6  christos 			echo line-3 >&14
    757   1.6  christos 			echo go
    758   1.6  christos 		) | (
    759   1.6  christos 			read go
    760   1.6  christos 			read x <&5
    761   1.6  christos 			read y <&7
    762   1.6  christos 			read z <&19
    763   1.6  christos 
    764   1.6  christos 			printf "%s\n" "${x}" "${y}" "${z}"
    765   1.6  christos 		)
    766   1.6  christos 	DONE
    767   1.6  christos 	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
    768   1.6  christos 		-e empty ${TEST_SH}
    769   1.6  christos 
    770   1.6  christos 	cat <<- 'DONE' |
    771   1.6  christos 		for arg in one-4-5 two-6-7 three-8-9 four-11-10 five-3-12
    772   1.6  christos 		do
    773   1.6  christos 			ofd=${arg##*-}
    774   1.6  christos 			file=${arg%-*}
    775   1.6  christos 			ifd=${file#*-}
    776   1.6  christos 			file=${file%-*}
    777   1.6  christos 			eval "exec ${ofd}>${file}"
    778   1.6  christos 			eval "exec ${ifd}<${file}"
    779   1.6  christos 		done
    780   1.6  christos 
    781   1.6  christos 		( ( ( echo line-1 >& 13 ) 13>&12 ) 12>&5 ) >stdout 2>errout
    782   1.6  christos 		( ( ( echo line-2 >& 4) 13>&12 ) 4>&7 ) >>stdout 2>>errout
    783   1.6  christos 		( ( ( echo line-3 >& 6) 8>&1 6>&11 >&12) 11>&9 >&7 ) >>stdout
    784   1.6  christos 
    785   1.6  christos 		( ( ( cat <&13 >&12 ) 13<&8 12>&10 ) 10>&1 8<&6 ) 6<&4
    786   1.6  christos 		( ( ( cat <&4 ) <&4 6<&8 8<&11  )
    787   1.6  christos 			<&4 4<&6 6<&8 8<&11 ) <&4 4<&6 6<&8 8<&11 11<&3
    788   1.6  christos 		( ( ( cat <&7 >&1 ) 7<&6 >&10 ) 10>&2 6<&8 ) 2>&1
    789   1.6  christos 	DONE
    790   1.6  christos 	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
    791   1.6  christos 		-e empty ${TEST_SH}
    792   1.6  christos }
    793   1.6  christos 
    794   1.6  christos atf_test_case ulimit_redirection_interaction
    795   1.6  christos ulimit_redirection_interaction_head()
    796   1.6  christos {
    797   1.6  christos 	atf_set "descr" "Tests interactions between redirect and ulimit -n "
    798   1.6  christos }
    799   1.6  christos ulimit_redirection_interaction_body()
    800   1.6  christos {
    801   1.6  christos 	atf_require_prog ls
    802   1.6  christos 
    803   1.6  christos 	cat <<- 'DONE' > helper.sh
    804   1.6  christos 		oLIM=$(ulimit -n)
    805   1.6  christos 		HRD=$(ulimit -H -n)
    806   1.6  christos 		test "${oLIM}" -lt "${HRD}"  && ulimit -n "${HRD}"
    807   1.6  christos 		LIM=$(ulimit -n)
    808   1.6  christos 
    809   1.6  christos 		FDs=
    810   1.6  christos 		LFD=-1
    811   1.6  christos 		while [ ${LIM} -gt 16 ]
    812   1.6  christos 		do
    813   1.6  christos 			FD=$(( ${LIM} - 1 ))
    814   1.6  christos 			if [ "${FD}" -eq "${LFD}" ]; then
    815   1.6  christos 				echo >&2 "Infinite loop... (busted $(( )) ??)"
    816   1.6  christos 				exit 1
    817   1.6  christos 			fi
    818   1.6  christos 			LFD="${FD}"
    819   1.6  christos 
    820   1.6  christos 			eval "exec ${FD}"'> /dev/null'
    821   1.6  christos 			FDs="${FD}${FDs:+ }${FDs}"
    822   1.6  christos 
    823   1.6  christos 			(
    824   1.6  christos 				FD=$(( ${LIM} + 1 ))
    825   1.6  christos 				eval "exec ${FD}"'> /dev/null'
    826   1.6  christos 				echo "Reached unreachable command"
    827   1.6  christos 			) 2>/dev/null && echo >&2 "Opened beyond limit!"
    828   1.6  christos 
    829   1.6  christos 			(eval 'ls 2>&1 3>&1 4>&1 5>&1 '"${FD}"'>&1') >&"${FD}"
    830   1.6  christos 
    831   1.6  christos 			LIM=$(( ${LIM} / 2 ))
    832   1.6  christos 			ulimit -S -n "${LIM}"
    833   1.6  christos 		done
    834   1.6  christos 
    835   1.6  christos 		# Even though ulimit has been reduced, open fds should work
    836   1.6  christos 		for FD in ${FDs}
    837   1.6  christos 		do
    838   1.6  christos 			echo ${FD} in ${FDs} >&"${FD}" || exit 1
    839   1.6  christos 		done
    840   1.6  christos 
    841   1.6  christos 		ulimit -S -n "${oLIM}"
    842   1.6  christos 
    843   1.6  christos 		# maybe more later...
    844   1.6  christos 
    845   1.6  christos 	DONE
    846   1.6  christos 
    847   1.6  christos 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} helper.sh
    848   1.1  christos }
    849   1.1  christos 
    850   1.7       kre atf_test_case validate_fn_redirects
    851   1.7       kre validate_fn_redirects_head()
    852   1.7       kre {
    853   1.7       kre 	# These test cases inspired by PR bin/48875 and the sh
    854   1.7       kre 	# changes that were required to fix it.
    855   1.7       kre 
    856   1.7       kre 	atf_set "descr" "Tests various redirections applied to functions " \
    857   1.7       kre 		"See PR bin/48875"
    858   1.7       kre }
    859   1.7       kre validate_fn_redirects_body()
    860   1.7       kre {
    861   1.7       kre 	cat <<- 'DONE' > f-def
    862   1.7       kre 		f() {
    863   1.7       kre 			printf '%s\n' In-Func
    864   1.7       kre 		}
    865   1.7       kre 	DONE
    866   1.7       kre 
    867   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess1\n' -e empty \
    868   1.7       kre 		${TEST_SH} -c ". ./f-def; f ; printf '%s\n' success1"
    869   1.7       kre 	atf_check -s exit:0 -o inline:'success2\n' -e empty \
    870   1.7       kre 		${TEST_SH} -c ". ./f-def; f >/dev/null; printf '%s\n' success2"
    871  1.11       kre 	atf_check -s exit:0 -o inline:'success3\n' -e not-empty \
    872   1.7       kre 		${TEST_SH} -c ". ./f-def; f >&- ; printf '%s\n' success3"
    873   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess4\n' -e empty \
    874   1.7       kre 		${TEST_SH} -c ". ./f-def; f & wait; printf '%s\n' success4"
    875  1.11       kre 	atf_check -s exit:0 -o inline:'success5\n' -e not-empty \
    876   1.7       kre 		${TEST_SH} -c ". ./f-def; f >&- & wait; printf '%s\n' success5"
    877   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess6\n' -e empty \
    878   1.7       kre 		${TEST_SH} -c ". ./f-def; f;f; printf '%s\n' success6"
    879   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess7\n' -e empty \
    880   1.7       kre 		${TEST_SH} -c ". ./f-def; { f;f;}; printf '%s\n' success7"
    881   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess8\n' -e empty \
    882   1.7       kre 		${TEST_SH} -c ". ./f-def; { f;f;}& wait; printf '%s\n' success8"
    883   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess9\n' -e empty \
    884   1.7       kre 		${TEST_SH} -c \
    885   1.7       kre 		   ". ./f-def; { f>/dev/null;f;}& wait; printf '%s\n' success9"
    886   1.7       kre 	atf_check -s exit:0 -o inline:'In-Func\nsuccess10\n' -e empty \
    887   1.7       kre 		${TEST_SH} -c \
    888   1.7       kre 		   ". ./f-def; { f;f>/dev/null;}& wait; printf '%s\n' success10"
    889   1.7       kre 
    890   1.8       kre 	# This one tests the issue etcupdate had with the original 48875 fix
    891   1.8       kre 	atf_check -s exit:0 -o inline:'Func a\nFunc b\nFunc c\n' -e empty \
    892   1.8       kre 		${TEST_SH} -c '
    893   1.8       kre 			f() {
    894   1.8       kre 				echo Func "$1"
    895   1.8       kre 			}
    896   1.8       kre 			exec 3<&0 4>&1
    897   1.8       kre 			( echo x-a; echo y-b; echo z-c ) |
    898   1.8       kre 			while read A
    899   1.8       kre 			do
    900   1.8       kre 				B=${A#?-}
    901   1.8       kre 				f "$B" <&3 >&4
    902   1.8       kre 			done >&2'
    903   1.8       kre 
    904   1.9       kre 	# And this tests a similar condition with that same fix
    905   1.9       kre 	cat  <<- 'DONE' >Script
    906   1.9       kre 		f() {
    907   1.9       kre 			printf '%s' " hello $1"
    908   1.9       kre 		}
    909   1.9       kre 		exec 3>&1
    910   1.9       kre 		echo $( for i in a b c
    911   1.9       kre 			do printf '%s' @$i; f $i >&3; done >foo
    912   1.9       kre 		)
    913   1.9       kre 		printf '%s\n' foo=$(cat foo)
    914   1.9       kre 	DONE
    915   1.9       kre 	atf_check -s exit:0 -e empty \
    916   1.9       kre 	    -o inline:' hello a hello b hello c\nfoo=@a@b@c\n' \
    917   1.9       kre 	    ${TEST_SH} Script
    918   1.9       kre 
    919   1.7       kre 	# Tests with sh reading stdin, which is not quite the same internal
    920   1.7       kre 	# mechanism.
    921   1.7       kre 	echo ". ./f-def || echo >&2 FAIL
    922   1.7       kre 		f
    923   1.7       kre 		printf '%s\n' stdin1
    924  1.12       kre 	" | atf_check -s exit:0 -o inline:'In-Func\nstdin1\n' -e empty \
    925  1.12       kre 	      ${TEST_SH} ||
    926  1.12       kre 		atf_fail "stdin1 test failure"
    927   1.7       kre 
    928   1.7       kre 	echo '
    929   1.7       kre 		. ./f-def || echo >&2 FAIL
    930  1.13       kre 		f >&- 2>/dev/null
    931   1.8       kre 		printf "%s\n" stdin2
    932  1.12       kre 	' | atf_check -s exit:0 -o inline:'stdin2\n' -e empty ${TEST_SH} ||
    933  1.12       kre 		atf_fail "stdin2 test failure"
    934   1.7       kre 
    935   1.7       kre 	cat <<- 'DONE' > fgh.def
    936   1.7       kre 		f() {
    937   1.7       kre 			echo -n f >&3
    938   1.7       kre 			sleep 4
    939   1.7       kre 			echo -n F >&3
    940   1.7       kre 		}
    941   1.7       kre 		g() {
    942   1.7       kre 			echo -n g >&3
    943   1.7       kre 			sleep 2
    944   1.7       kre 			echo -n G >&3
    945   1.7       kre 		}
    946   1.7       kre 		h() {
    947   1.7       kre 			echo -n h >&3
    948   1.7       kre 		}
    949   1.7       kre 	DONE
    950   1.7       kre 
    951   1.7       kre 	atf_check -s exit:0 -o inline:'fFgGh' -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; g; h'
    955   1.7       kre 
    956   1.7       kre 	atf_check -s exit:0 -o inline:'fghGF' -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 			f & sleep 1; g & sleep 1; h; wait'
    960   1.7       kre 
    961   1.7       kre 	atf_check -s exit:0 -o inline:'fFgGhX Y\n' -e empty \
    962   1.7       kre 		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
    963   1.7       kre 			exec 3>&1
    964   1.7       kre 			echo X $( f ; g ; h ) Y'
    965   1.7       kre 
    966   1.7       kre 	# This one is the real test for PR bin/48875.  If the
    967   1.7       kre 	# cmdsub does not complete before f g (and h) exit,
    968   1.7       kre 	# then the 'F' & 'G' will precede 'X Y' in the output.
    969   1.7       kre 	# If the cmdsub finishes while f & g are still running,
    970   1.7       kre 	# then the X Y will appear before the F and G.
    971   1.7       kre 	# The trailing "sleep 3" is just so we catch all the
    972   1.7       kre 	# output (otherwise atf_check will be finished while
    973   1.7       kre 	# f & g are still sleeping).
    974   1.7       kre 
    975   1.7       kre 	atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty \
    976   1.7       kre 		${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
    977   1.7       kre 			exec 3>&1
    978   1.7       kre 			echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
    979   1.7       kre 			sleep 3
    980   1.7       kre 			exec 4>&1 || echo FD_FAIL
    981   1.7       kre 			'
    982   1.7       kre 
    983   1.7       kre 	# Do the test again to verify it also all works reading stdin
    984   1.7       kre 	# (which is a slightly different path through the shell)
    985   1.7       kre 	echo '
    986   1.7       kre 		. ./fgh.def || echo >&2 FAIL
    987   1.7       kre 		exec 3>&1
    988   1.7       kre 		echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
    989   1.7       kre 		sleep 3
    990   1.7       kre 		exec 4>&1 || echo FD_FAIL
    991  1.12       kre 	' | atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty ${TEST_SH} ||
    992  1.12       kre 		atf_fail "48875 stdin variant failure"
    993   1.7       kre }
    994   1.7       kre 
    995   1.1  christos atf_init_test_cases() {
    996   1.4  christos 	atf_add_test_case basic_test_method_test
    997   1.4  christos 	atf_add_test_case do_input_redirections
    998   1.4  christos 	atf_add_test_case do_output_redirections
    999  1.10       kre 	atf_add_test_case do_redirect_input_output
   1000   1.4  christos 	atf_add_test_case fd_redirections
   1001   1.4  christos 	atf_add_test_case local_redirections
   1002   1.4  christos 	atf_add_test_case incorrect_redirections
   1003   1.7       kre 	atf_add_test_case named_fd_redirections
   1004   1.4  christos 	atf_add_test_case redir_here_doc
   1005   1.1  christos 	atf_add_test_case redir_in_case
   1006   1.4  christos 	atf_add_test_case subshell_redirections
   1007   1.6  christos 	atf_add_test_case ulimit_redirection_interaction
   1008   1.7       kre 	atf_add_test_case validate_fn_redirects
   1009   1.1  christos }
   1010