Home | History | Annotate | Line # | Download | only in sh
t_redir.sh revision 1.6
      1 # $NetBSD: t_redir.sh,v 1.6 2016/05/02 01:47:14 christos Exp $
      2 #
      3 # Copyright (c) 2016 The NetBSD Foundation, Inc.
      4 # All rights reserved.
      5 #
      6 # Redistribution and use in source and binary forms, with or without
      7 # modification, are permitted provided that the following conditions
      8 # are met:
      9 # 1. Redistributions of source code must retain the above copyright
     10 #    notice, this list of conditions and the following disclaimer.
     11 # 2. Redistributions in binary form must reproduce the above copyright
     12 #    notice, this list of conditions and the following disclaimer in the
     13 #    documentation and/or other materials provided with the distribution.
     14 #
     15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25 # POSSIBILITY OF SUCH DAMAGE.
     26 #
     27 # the implementation of "sh" to test
     28 : ${TEST_SH:="/bin/sh"}
     29 
     30 # Any failures in this first test means it is not worth bothering looking
     31 # for causes of failures in any other tests, make this one work first.
     32 
     33 # Problems with this test usually mean inadequate ATF_SHELL used for testing.
     34 # (though if all pass but the last, it might be a TEST_SH problem.)
     35 
     36 atf_test_case basic_test_method_test
     37 basic_test_method_test_head()
     38 {
     39 	atf_set "descr" "Tests that test method works as expected"
     40 }
     41 basic_test_method_test_body()
     42 {
     43 	cat <<- 'DONE' |
     44 	DONE
     45 	atf_check -s exit:0 -o empty -e empty ${TEST_SH}
     46 	cat <<- 'DONE' |
     47 	DONE
     48 	atf_check -s exit:0 -o match:0 -e empty ${TEST_SH} -c 'wc -l'
     49 
     50 	cat <<- 'DONE' |
     51 		echo hello
     52 	DONE
     53 	atf_check -s exit:0 -o match:hello -e empty ${TEST_SH} 
     54 	cat <<- 'DONE' |
     55 		echo hello
     56 	DONE
     57 	atf_check -s exit:0 -o match:1 -e empty ${TEST_SH} -c 'wc -l'
     58 
     59 	cat <<- 'DONE' |
     60 		echo hello\
     61 					world
     62 	DONE
     63 	atf_check -s exit:0 -o match:helloworld -e empty ${TEST_SH} 
     64 	cat <<- 'DONE' |
     65 		echo hello\
     66 					world
     67 	DONE
     68 	atf_check -s exit:0 -o match:2 -e empty ${TEST_SH} -c 'wc -l'
     69 
     70 	printf '%s\n%s\n%s\n' Line1 Line2 Line3 > File
     71 	atf_check -s exit:0 -o inline:'Line1\nLine2\nLine3\n' -e empty \
     72 		${TEST_SH} -c 'cat File'
     73 
     74 	cat <<- 'DONE' |
     75 		set -- X "" '' Y
     76 		echo ARGS="${#}"
     77 		echo '' -$1- -$2- -$3- -$4-
     78 		cat <<EOF
     79 			X=$1
     80 		EOF
     81 		cat <<\EOF
     82 			Y=$4
     83 		EOF
     84 	DONE
     85 	atf_check -s exit:0 -o match:ARGS=4 -o match:'-X- -- -- -Y-' \
     86 		-o match:X=X -o match:'Y=\$4' -e empty ${TEST_SH} 
     87 }
     88 
     89 atf_test_case do_input_redirections
     90 do_input_redirections_head()
     91 {
     92 	atf_set "descr" "Tests that simple input redirection works"
     93 }
     94 do_input_redirections_body()
     95 {
     96 	printf '%s\n%s\n%s\nEND\n' 'First Line' 'Second Line' 'Line 3' >File
     97 
     98 	atf_check -s exit:0 -e empty \
     99 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    100 		${TEST_SH} -c 'cat < File'
    101 	atf_check -s exit:0 -e empty \
    102 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    103 		${TEST_SH} -c 'cat <File'
    104 	atf_check -s exit:0 -e empty \
    105 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    106 		${TEST_SH} -c 'cat< File'
    107 	atf_check -s exit:0 -e empty \
    108 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    109 		${TEST_SH} -c 'cat < "File"'
    110 	atf_check -s exit:0 -e empty \
    111 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    112 		${TEST_SH} -c '< File cat'
    113 
    114 	ln File wc
    115 	atf_check -s exit:0 -e empty \
    116 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    117 		${TEST_SH} -c '< wc cat'
    118 
    119 	mv wc cat
    120 	atf_check -s exit:0 -e empty -o match:4 \
    121 		${TEST_SH} -c '< cat wc'
    122 
    123 
    124 	cat <<- 'EOF' |
    125 		for l in 1 2 3; do
    126 			read line < File
    127 			echo "$line"
    128 		done
    129 	EOF
    130 	atf_check -s exit:0 -e empty \
    131 		-o inline:'First Line\nFirst Line\nFirst Line\n' \
    132 		${TEST_SH}
    133 
    134 	cat <<- 'EOF' |
    135 		for l in 1 2 3; do
    136 			read line
    137 			echo "$line"
    138 		done <File
    139 	EOF
    140 	atf_check -s exit:0 -e empty \
    141 		-o inline:'First Line\nSecond Line\nLine 3\n' \
    142 		${TEST_SH}
    143 
    144 	cat <<- 'EOF' |
    145 		for l in 1 2 3; do
    146 			read line < File
    147 			echo "$line"
    148 		done <File
    149 	EOF
    150 	atf_check -s exit:0 -e empty \
    151 		-o inline:'First Line\nFirst Line\nFirst Line\n' \
    152 		${TEST_SH}
    153 
    154 	cat <<- 'EOF' |
    155 		line=
    156 		while [ "$line" != END ]; do
    157 			read line || exit 1
    158 			echo "$line"
    159 		done <File
    160 	EOF
    161 	atf_check -s exit:0 -e empty \
    162 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    163 		${TEST_SH}
    164 
    165 	cat <<- 'EOF' |
    166 		while :; do
    167 			read line || exit 0
    168 			echo "$line"
    169 		done <File
    170 	EOF
    171 	atf_check -s exit:0 -e empty \
    172 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    173 		${TEST_SH}
    174 
    175 	cat <<- 'EOF' |
    176 		l=''
    177 		while read line < File
    178 		do
    179 			echo "$line"
    180 			l="${l}x"
    181 			[ ${#l} -ge 3 ] && break
    182 		done
    183 		echo DONE
    184 	EOF
    185 	atf_check -s exit:0 -e empty \
    186 		-o inline:'First Line\nFirst Line\nFirst Line\nDONE\n' \
    187 		${TEST_SH}
    188 
    189 	cat <<- 'EOF' |
    190 		while read line
    191 		do
    192 			echo "$line"
    193 		done <File
    194 		echo DONE
    195 	EOF
    196 	atf_check -s exit:0 -e empty \
    197 		-o inline:'First Line\nSecond Line\nLine 3\nEND\nDONE\n' \
    198 		${TEST_SH}
    199 
    200 	cat <<- 'EOF' |
    201 		l=''
    202 		while read line
    203 		do
    204 			echo "$line"
    205 			l="${l}x"
    206 			[ ${#l} -ge 3 ] && break
    207 		done <File
    208 		echo DONE
    209 	EOF
    210 	atf_check -s exit:0 -e empty \
    211 		-o inline:'First Line\nSecond Line\nLine 3\nDONE\n' ${TEST_SH}
    212 
    213 	cat <<- 'EOF' |
    214 		l=''
    215 		while read line1 <File
    216 		do
    217 			read line2
    218 			echo "$line1":"$line2"
    219 			l="${l}x"
    220 			[ ${#l} -ge 2 ] && break
    221 		done <File
    222 		echo DONE
    223 	EOF
    224 	atf_check -s exit:0 -e empty \
    225 	    -o inline:'First Line:First Line\nFirst Line:Second Line\nDONE\n' \
    226 		${TEST_SH}
    227 }
    228 
    229 atf_test_case do_output_redirections
    230 do_output_redirections_head()
    231 {
    232 	atf_set "descr" "Test Output redirections"
    233 }
    234 do_output_redirections_body()
    235 {
    236 nl='
    237 '
    238 	T=0
    239 	i() { T=$(expr "$T" + 1); }
    240 
    241 	rm -f Output 2>/dev/null || :
    242 	test -f Output && atf_fail "Unable to remove Output file"
    243 #1
    244 	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '> Output'
    245 	test -f Output || atf_fail "#$T: Did not make Output file"
    246 #2
    247 	rm -f Output 2>/dev/null || :
    248 	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>> Output'
    249 	test -f Output || atf_fail "#$T: Did not make Output file"
    250 #3
    251 	rm -f Output 2>/dev/null || :
    252 	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>| Output'
    253 	test -f Output || atf_fail "#$T: Did not make Output file"
    254 
    255 #4
    256 	rm -f Output 2>/dev/null || :
    257 	i
    258 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello >Output'
    259 	test -s Output || atf_fail "#$T: Did not make non-empty Output file"
    260 	test "$(cat Output)" = "Hello" ||
    261 	  atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
    262 #5
    263 	i
    264 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello>!Output'
    265 	test -s Output || atf_fail "#$T: Did not make non-empty Output file"
    266 	test "$(cat Output)" = "Hello" ||
    267 	  atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
    268 #6
    269 	i
    270 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Bye >>Output'
    271 	test -s Output || atf_fail "#$T: Removed Output file"
    272 	test "$(cat Output)" = "Hello${nl}Bye" || atf_fail \
    273 	  "#$T: Incorrect Output: Should be 'Hello\\nBye' is '$(cat Output)'"
    274 #7
    275 	i; atf_check -s exit:0 -o inline:'line 1\nline 2\n' -e empty \
    276 		${TEST_SH} -c \
    277 		'echo line 1 > Output; echo line 2 >> Output; cat Output'
    278 	test "$(cat Output)" = "line 1${nl}line 2" || atf_fail \
    279 	 "#$T: Incorrect Output: Should be 'line 1\\nline 2' is '$(cat Output)'"
    280 #8
    281 	i; atf_check -s exit:0 -o inline:'line 2\n' -e empty \
    282 		${TEST_SH} -c 'echo line 1 > Output; echo line 2'
    283 	test "$(cat Output)" = "line 1" || atf_fail \
    284 	    "#$T: Incorrect Output: Should be 'line 1' is '$(cat Output)'"
    285 #9
    286 	i; atf_check -s exit:0 -o empty -e empty \
    287 		${TEST_SH} -c '(echo line 1; echo line 2 > Out2) > Out1'
    288 	test "$(cat Out1)" = "line 1" || atf_fail \
    289 	    "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
    290 	test "$(cat Out2)" = "line 2" || atf_fail \
    291 	    "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
    292 #10
    293 	i; atf_check -s exit:0 -o empty -e empty \
    294 		${TEST_SH} -c '{ echo line 1; echo line 2 > Out2;} > Out1'
    295 	test "$(cat Out1)" = "line 1" || atf_fail \
    296 	    "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
    297 	test "$(cat Out2)" = "line 2" || atf_fail \
    298 	    "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
    299 #11
    300 	i; rm -f Out1 Out2 2>/dev/null || :
    301 	cat <<- 'EOF' |
    302 		for arg in 'line 1' 'line 2' 'line 3'
    303 		do
    304 			echo "$arg"
    305 			echo "$arg" > Out1
    306 		done > Out2
    307 	EOF
    308 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} 
    309 	test "$(cat Out1)" = "line 3" || atf_fail \
    310 		"#$T:  Incorrect Out1: Should be 'line 3' is '$(cat Out1)'"
    311 	test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
    312     "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
    313 #12
    314 	i; rm -f Out1 Out2 2>/dev/null || :
    315 	cat <<- 'EOF' |
    316 		for arg in 'line 1' 'line 2' 'line 3'
    317 		do
    318 			echo "$arg"
    319 			echo "$arg" >> Out1
    320 		done > Out2
    321 	EOF
    322 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} 
    323 	test "$(cat Out1)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
    324     "#$T: Incorrect Out1: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out1)'"
    325 	test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
    326     "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
    327 }
    328 
    329 atf_test_case fd_redirections
    330 fd_redirections_head()
    331 {
    332 	atf_set "descr" "Tests redirections to/from specific descriptors"
    333 }
    334 fd_redirections_body()
    335 {
    336 	atf_require_prog /bin/echo
    337 
    338 	cat <<- 'DONE' > helper.sh
    339 		f() {
    340 			/bin/echo nothing "$1" >& "$1"
    341 		}
    342 		for n
    343 		do
    344 			eval "f $n $n"'> file-$n'
    345 		done
    346 	DONE
    347 	cat <<- 'DONE' > reread.sh
    348 		f() {
    349 			(read -r var; echo "${var}") <&"$1"
    350 		}
    351 		for n
    352 		do
    353 			x=$( eval "f $n $n"'< file-$n' )
    354 			test "${x}" = "nothing $n" || echo "$n"
    355 		done
    356 	DONE
    357 
    358 	validate()
    359 	{
    360 	    for n
    361 	    do
    362 		test -e "file-$n" || atf_fail "file-$n not created"
    363 		C=$(cat file-"$n")
    364 		test "$C" = "nothing $n" ||
    365 			atf_fail "file-$n contains '$C' not 'nothing $n'"
    366 	    done
    367 	}
    368 
    369 	atf_check -s exit:0 -e empty -o empty \
    370 		${TEST_SH} helper.sh 1 2 3 4 5 6 7 8 9
    371 	validate 1 2 3 4 5 6 7 8 9
    372 	atf_check -s exit:0 -e empty -o empty \
    373 		${TEST_SH} reread.sh 3 4 5 6 7 8 9
    374 
    375 	L=$(ulimit -n)
    376 	if [ "$L" -ge 30 ]
    377 	then
    378 		atf_check -s exit:0 -e empty -o empty \
    379 			${TEST_SH} helper.sh 10 15 19 20 25 29
    380 		validate 10 15 19 20 25 29
    381 		atf_check -s exit:0 -e empty -o empty \
    382 			${TEST_SH} reread.sh 10 15 19 20 25 29
    383 	fi
    384 	if [ "$L" -ge 100 ]
    385 	then
    386 		atf_check -s exit:0 -e empty -o empty \
    387 			${TEST_SH} helper.sh 32 33 49 50 51 63 64 65 77 88 99
    388 		validate 32 33 49 50 51 63 64 65 77 88 99
    389 		atf_check -s exit:0 -e empty -o empty \
    390 			${TEST_SH} reread.sh 32 33 49 50 51 63 64 65 77 88 99
    391 	fi
    392 	if [ "$L" -ge 500 ]
    393 	then
    394 		atf_check -s exit:0 -e empty -o empty \
    395 			${TEST_SH} helper.sh 100 101 199 200 222 333 444 499
    396 		validate 100 101 199 200 222 333 444 499
    397 		atf_check -s exit:0 -e empty -o empty \
    398 			${TEST_SH} reread.sh 100 101 199 200 222 333 444 499
    399 	fi
    400 	if [ "$L" -gt 1005 ]
    401 	then
    402 		atf_check -s exit:0 -e empty -o empty \
    403 			${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
    404 		validate 1000 1001 1002 1003 1004 1005
    405 		atf_check -s exit:0 -e empty -o empty \
    406 			${TEST_SH} reread.sh 1000 1001 1002 1003 1004 1005
    407 	fi
    408 } 
    409 
    410 atf_test_case local_redirections
    411 local_redirections_head()
    412 {
    413 	atf_set "descr" \
    414 	    "Tests that exec can reassign file descriptors in the shell itself"
    415 }
    416 local_redirections_body()
    417 {
    418 	cat <<- 'DONE' > helper.sh
    419 		for f
    420 		do
    421 			eval "exec $f"'> file-$f'
    422 		done
    423 
    424 		for f
    425 		do
    426 			printf '%s\n' "Hello $f" >&"$f"
    427 		done
    428 
    429 		for f
    430 		do
    431 			eval "exec $f"'>&-'
    432 		done
    433 
    434 		for f
    435 		do
    436 			eval "exec $f"'< file-$f'
    437 		done
    438 
    439 		for f
    440 		do
    441 			exec <& "$f"
    442 			read -r var || echo >&2 "No data in file-$f"
    443 			read -r x && echo >&2 "Too much data in file-${f}: $x"
    444 			test "${var}" = "Hello $f" ||
    445 			    echo >&2 "file-$f contains '${var}' not 'Hello $f'"
    446 		done
    447 	DONE
    448 
    449 	atf_check -s exit:0 -o empty -e empty \
    450 		${TEST_SH} helper.sh 3 4 5 6 7 8 9
    451 
    452 	L=$(ulimit -n)
    453 	if [ "$L" -ge 30 ]
    454 	then
    455 		atf_check -s exit:0 -o empty -e empty \
    456 			${TEST_SH} helper.sh 10 11 13 15 16 19 20 28 29
    457 	fi
    458 	if [ "$L" -ge 100 ]
    459 	then
    460 		atf_check -s exit:0 -o empty -e empty \
    461 			${TEST_SH} helper.sh 30 31 32 63 64 65 77 88 99
    462 	fi
    463 	if [ "$L" -ge 500 ]
    464 	then
    465 		atf_check -s exit:0 -o empty -e empty \
    466 			${TEST_SH} helper.sh 100 101 111 199 200 201 222 333 499
    467 	fi
    468 	if [ "$L" -ge 1005 ]
    469 	then
    470 		atf_check -s exit:0 -o empty -e empty \
    471 			${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
    472 	fi
    473 }
    474 
    475 atf_test_case redir_in_case
    476 redir_in_case_head()
    477 {
    478 	atf_set "descr" "Tests that sh(1) allows just redirections " \
    479 	                "in case statements. (PR bin/48631)"
    480 }
    481 redir_in_case_body()
    482 {
    483 	atf_check -s exit:0 -o empty -e empty \
    484 	    ${TEST_SH} -c 'case x in (whatever) >foo;; esac'
    485 
    486 	atf_check -s exit:0 -o empty -e empty \
    487 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac'
    488 
    489 	atf_check -s exit:0 -o empty -e empty \
    490 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac'
    491 
    492 	atf_check -s exit:0 -o empty -e empty \
    493 	    ${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac'
    494 }
    495 
    496 atf_test_case incorrect_redirections
    497 incorrect_redirections_head()
    498 {
    499 	atf_set "descr" "Tests that sh(1) correctly ignores non-redirections"
    500 }
    501 incorrect_redirections_body() {
    502 
    503 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo>'
    504 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'read foo<'
    505 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>'
    506 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    507 		'echo x > '"$nl"
    508 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    509 		'read x < '"$nl"
    510 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    511 		'echo x <> '"$nl"
    512 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    513 		'echo x >< anything'
    514 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    515 		'echo x >>< anything'
    516 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    517 		'echo x >|< anything'
    518 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    519 		'echo x > ; read x < /dev/null || echo bad'
    520 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    521 		'read x < & echo y > /dev/null; wait && echo bad'
    522 
    523 	rm -f Output 2>/dev/null || :
    524 	atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \
    525 		${TEST_SH} -c 'echo A Line \> Output'
    526 	test -f Output && atf_file "File 'Output' appeared and should not have"
    527 
    528 	rm -f Output 2>/dev/null || :
    529 	atf_check -s exit:0 -e empty -o empty \
    530 		${TEST_SH} -c 'echo A Line \>> Output'
    531 	test -f Output || atf_file "File 'Output' not created when it should"
    532 	test "$(cat Output)" = 'A Line >' || atf_fail \
    533 		"Output file contains '$(cat Output)' instead of '"'A Line >'\'
    534 
    535 	rm -f Output \> 2>/dev/null || :
    536 	atf_check -s exit:0 -e empty -o empty \
    537 		${TEST_SH} -c 'echo A Line >\> Output'
    538 	test -f Output && atf_file "File 'Output' appeared and should not have"
    539 	test -f '>' || atf_file "File '>' not created when it should"
    540 	test "$(cat '>')" = 'A Line Output' || atf_fail \
    541 	    "Output file ('>') contains '$(cat '>')' instead of 'A Line Output'"
    542 }
    543 
    544 # Many more tests in t_here, so here we have just rudimentary checks
    545 atf_test_case redir_here_doc
    546 redir_here_doc_head()
    547 {
    548 	atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \
    549 	                "input redirections"
    550 }
    551 redir_here_doc_body()
    552 {
    553 	# nb: the printf is not executed, it is data
    554 	cat <<- 'DONE' |
    555 		cat <<EOF
    556 			printf '%s\n' 'hello\n'
    557 		EOF
    558 	DONE
    559 	atf_check -s exit:0 -o match:printf -o match:'hello\\n' \
    560 		-e empty ${TEST_SH} 
    561 }
    562 
    563 atf_test_case subshell_redirections
    564 subshell_redirections_head()
    565 {
    566 	atf_set "descr" "Tests redirection interactions between shell and " \
    567 			"its sub-shell(s)"
    568 }
    569 subshell_redirections_body()
    570 {
    571 	atf_require_prog cat
    572 
    573 	LIM=$(ulimit -n)
    574 
    575 	cat <<- 'DONE' |
    576 		exec 6>output-file
    577 
    578 		( printf "hello\n" >&6 )
    579 
    580 		exec 8<output-file
    581 
    582 		( read hello <&8 ; test hello = "$hello" || echo >&2 Hello )
    583 
    584 		( printf "bye-bye\n" >&6 )
    585 
    586 		( exec 8<&- )
    587 		read bye <&8 || echo >&2 "Closed?"
    588 		echo Bye="$bye"
    589 	DONE
    590 	atf_check -s exit:0 -o match:Bye=bye-bye -e empty \
    591 		${TEST_SH}
    592 
    593 	cat <<- 'DONE' |
    594 		for arg in one-4 two-24 three-14
    595 		do
    596 			fd=${arg#*-}
    597 			file=${arg%-*}
    598 			eval "exec ${fd}>${file}"
    599 		done
    600 
    601 		for arg in one-5 two-7 three-19
    602 		do
    603 			fd=${arg#*-}
    604 			file=${arg%-*}
    605 			eval "exec ${fd}<${file}"
    606 		done
    607 
    608 		(
    609 			echo line-1 >&4
    610 			echo line-2 >&24
    611 			echo line-3 >&14
    612 			echo go
    613 		) | (
    614 			read go
    615 			read x <&5
    616 			read y <&7
    617 			read z <&19
    618 
    619 			printf "%s\n" "${x}" "${y}" "${z}"
    620 		)
    621 	DONE
    622 	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
    623 		-e empty ${TEST_SH}
    624 
    625 	cat <<- 'DONE' |
    626 		for arg in one-4-5 two-6-7 three-8-9 four-11-10 five-3-12
    627 		do
    628 			ofd=${arg##*-}
    629 			file=${arg%-*}
    630 			ifd=${file#*-}
    631 			file=${file%-*}
    632 			eval "exec ${ofd}>${file}"
    633 			eval "exec ${ifd}<${file}"
    634 		done
    635 
    636 		( ( ( echo line-1 >& 13 ) 13>&12 ) 12>&5 ) >stdout 2>errout
    637 		( ( ( echo line-2 >& 4) 13>&12 ) 4>&7 ) >>stdout 2>>errout
    638 		( ( ( echo line-3 >& 6) 8>&1 6>&11 >&12) 11>&9 >&7 ) >>stdout
    639 
    640 		( ( ( cat <&13 >&12 ) 13<&8 12>&10 ) 10>&1 8<&6 ) 6<&4
    641 		( ( ( cat <&4 ) <&4 6<&8 8<&11  )
    642 			<&4 4<&6 6<&8 8<&11 ) <&4 4<&6 6<&8 8<&11 11<&3
    643 		( ( ( cat <&7 >&1 ) 7<&6 >&10 ) 10>&2 6<&8 ) 2>&1
    644 	DONE
    645 	atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
    646 		-e empty ${TEST_SH}
    647 }
    648 
    649 atf_test_case ulimit_redirection_interaction
    650 ulimit_redirection_interaction_head()
    651 {
    652 	atf_set "descr" "Tests interactions between redirect and ulimit -n "
    653 }
    654 ulimit_redirection_interaction_body()
    655 {
    656 	atf_require_prog ls
    657 
    658 	cat <<- 'DONE' > helper.sh
    659 		oLIM=$(ulimit -n)
    660 		HRD=$(ulimit -H -n)
    661 		test "${oLIM}" -lt "${HRD}"  && ulimit -n "${HRD}"
    662 		LIM=$(ulimit -n)
    663 
    664 		FDs=
    665 		LFD=-1
    666 		while [ ${LIM} -gt 16 ]
    667 		do
    668 			FD=$(( ${LIM} - 1 ))
    669 			if [ "${FD}" -eq "${LFD}" ]; then
    670 				echo >&2 "Infinite loop... (busted $(( )) ??)"
    671 				exit 1
    672 			fi
    673 			LFD="${FD}"
    674 
    675 			eval "exec ${FD}"'> /dev/null'
    676 			FDs="${FD}${FDs:+ }${FDs}"
    677 
    678 			(
    679 				FD=$(( ${LIM} + 1 ))
    680 				eval "exec ${FD}"'> /dev/null'
    681 				echo "Reached unreachable command"
    682 			) 2>/dev/null && echo >&2 "Opened beyond limit!"
    683 
    684 			(eval 'ls 2>&1 3>&1 4>&1 5>&1 '"${FD}"'>&1') >&"${FD}"
    685 
    686 			LIM=$(( ${LIM} / 2 ))
    687 			ulimit -S -n "${LIM}"
    688 		done
    689 
    690 		# Even though ulimit has been reduced, open fds should work
    691 		for FD in ${FDs}
    692 		do
    693 			echo ${FD} in ${FDs} >&"${FD}" || exit 1
    694 		done
    695 
    696 		ulimit -S -n "${oLIM}"
    697 
    698 		# maybe more later...
    699 
    700 	DONE
    701 
    702 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} helper.sh
    703 }
    704 
    705 atf_init_test_cases() {
    706 	atf_add_test_case basic_test_method_test
    707 	atf_add_test_case do_input_redirections
    708 	atf_add_test_case do_output_redirections
    709 	atf_add_test_case fd_redirections
    710 	atf_add_test_case local_redirections
    711 	atf_add_test_case incorrect_redirections
    712 	atf_add_test_case redir_here_doc
    713 	atf_add_test_case redir_in_case
    714 	atf_add_test_case subshell_redirections
    715 	atf_add_test_case ulimit_redirection_interaction
    716 }
    717