Home | History | Annotate | Line # | Download | only in sh
t_redir.sh revision 1.4
      1 # $NetBSD: t_redir.sh,v 1.4 2016/03/08 14:26:54 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 		i=0
    126 		while [ "$i" -lt 3 ]; do
    127 			i=$((i + 1))
    128 			read line < File
    129 			echo "$line"
    130 		done
    131 	EOF
    132 	atf_check -s exit:0 -e empty \
    133 		-o inline:'First Line\nFirst Line\nFirst Line\n' \
    134 		${TEST_SH}
    135 
    136 	cat <<- 'EOF' |
    137 		i=0
    138 		while [ "$i" -lt 3 ]; do
    139 			i=$((i + 1))
    140 			read line
    141 			echo "$line"
    142 		done <File
    143 	EOF
    144 	atf_check -s exit:0 -e empty \
    145 		-o inline:'First Line\nSecond Line\nLine 3\n' \
    146 		${TEST_SH}
    147 
    148 	cat <<- 'EOF' |
    149 		i=0
    150 		while [ "$i" -lt 3 ]; do
    151 			i=$((i + 1))
    152 			read line < File
    153 			echo "$line"
    154 		done <File
    155 	EOF
    156 	atf_check -s exit:0 -e empty \
    157 		-o inline:'First Line\nFirst Line\nFirst Line\n' \
    158 		${TEST_SH}
    159 
    160 	cat <<- 'EOF' |
    161 		line=
    162 		while [ "$line" != END ]; do
    163 			read line || exit 1
    164 			echo "$line"
    165 		done <File
    166 	EOF
    167 	atf_check -s exit:0 -e empty \
    168 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    169 		${TEST_SH}
    170 
    171 	cat <<- 'EOF' |
    172 		while :; do
    173 			read line || exit 0
    174 			echo "$line"
    175 		done <File
    176 	EOF
    177 	atf_check -s exit:0 -e empty \
    178 		-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
    179 		${TEST_SH}
    180 
    181 	cat <<- 'EOF' |
    182 		i=0
    183 		while read line < File
    184 		do
    185 			echo "$line"
    186 			i=$((i + 1))
    187 			[ ${i} -ge 3 ] && break
    188 		done
    189 		echo DONE
    190 	EOF
    191 	atf_check -s exit:0 -e empty \
    192 		-o inline:'First Line\nFirst Line\nFirst Line\nDONE\n' \
    193 		${TEST_SH}
    194 
    195 	cat <<- 'EOF' |
    196 		i=0
    197 		while read line
    198 		do
    199 			echo "$line"
    200 		done <File
    201 		echo DONE
    202 	EOF
    203 	atf_check -s exit:0 -e empty \
    204 		-o inline:'First Line\nSecond Line\nLine 3\nEND\nDONE\n' \
    205 		${TEST_SH}
    206 
    207 	cat <<- 'EOF' |
    208 		i=0
    209 		while read line
    210 		do
    211 			echo "$line"
    212 			i=$((i + 1))
    213 			[ ${i} -ge 3 ] && break
    214 		done <File
    215 		echo DONE
    216 	EOF
    217 	atf_check -s exit:0 -e empty \
    218 		-o inline:'First Line\nSecond Line\nLine 3\nDONE\n' ${TEST_SH}
    219 
    220 	cat <<- 'EOF' |
    221 		i=0
    222 		while read line1 <File
    223 		do
    224 			read line2
    225 			echo "$line1":"$line2"
    226 			i=$((i + 1))
    227 			[ ${i} -ge 2 ] && break
    228 		done <File
    229 		echo DONE
    230 	EOF
    231 	atf_check -s exit:0 -e empty \
    232 	    -o inline:'First Line:First Line\nFirst Line:Second Line\nDONE\n' \
    233 		${TEST_SH}
    234 }
    235 
    236 atf_test_case do_output_redirections
    237 do_output_redirections_head()
    238 {
    239 	atf_set "descr" "Test Output redirections"
    240 }
    241 do_output_redirections_body()
    242 {
    243 nl='
    244 '
    245 	T=0
    246 	i() { T=$(($T + 1)); }
    247 
    248 	rm -f Output 2>/dev/null || :
    249 	test -f Output && atf_fail "Unable to remove Output file"
    250 #1
    251 	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '> Output'
    252 	test -f Output || atf_fail "#$T: Did not make Output file"
    253 #2
    254 	rm -f Output 2>/dev/null || :
    255 	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>> Output'
    256 	test -f Output || atf_fail "#$T: Did not make Output file"
    257 #3
    258 	rm -f Output 2>/dev/null || :
    259 	i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>| Output'
    260 	test -f Output || atf_fail "#$T: Did not make Output file"
    261 
    262 #4
    263 	rm -f Output 2>/dev/null || :
    264 	i
    265 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello >Output'
    266 	test -s Output || atf_fail "#$T: Did not make non-empty Output file"
    267 	test "$(cat Output)" = "Hello" ||
    268 	  atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
    269 #5
    270 	i
    271 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello>!Output'
    272 	test -s Output || atf_fail "#$T: Did not make non-empty Output file"
    273 	test "$(cat Output)" = "Hello" ||
    274 	  atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
    275 #6
    276 	i
    277 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Bye >>Output'
    278 	test -s Output || atf_fail "#$T: Removed Output file"
    279 	test "$(cat Output)" = "Hello${nl}Bye" || atf_fail \
    280 	  "#$T: Incorrect Output: Should be 'Hello\\nBye' is '$(cat Output)'"
    281 #7
    282 	i; atf_check -s exit:0 -o inline:'line 1\nline 2\n' -e empty \
    283 		${TEST_SH} -c \
    284 		'echo line 1 > Output; echo line 2 >> Output; cat Output'
    285 	test "$(cat Output)" = "line 1${nl}line 2" || atf_fail \
    286 	 "#$T: Incorrect Output: Should be 'line 1\\nline 2' is '$(cat Output)'"
    287 #8
    288 	i; atf_check -s exit:0 -o inline:'line 2\n' -e empty \
    289 		${TEST_SH} -c 'echo line 1 > Output; echo line 2'
    290 	test "$(cat Output)" = "line 1" || atf_fail \
    291 	    "#$T: Incorrect Output: Should be 'line 1' is '$(cat Output)'"
    292 #9
    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 #10
    300 	i; atf_check -s exit:0 -o empty -e empty \
    301 		${TEST_SH} -c '{ echo line 1; echo line 2 > Out2;} > Out1'
    302 	test "$(cat Out1)" = "line 1" || atf_fail \
    303 	    "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
    304 	test "$(cat Out2)" = "line 2" || atf_fail \
    305 	    "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
    306 #11
    307 	i; rm -f Out1 Out2 2>/dev/null || :
    308 	cat <<- 'EOF' |
    309 		for arg in 'line 1' 'line 2' 'line 3'
    310 		do
    311 			echo "$arg"
    312 			echo "$arg" > Out1
    313 		done > Out2
    314 	EOF
    315 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} 
    316 	test "$(cat Out1)" = "line 3" || atf_fail \
    317 		"#$T:  Incorrect Out1: Should be 'line 3' is '$(cat Out1)'"
    318 	test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
    319     "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
    320 #12
    321 	i; rm -f Out1 Out2 2>/dev/null || :
    322 	cat <<- 'EOF' |
    323 		for arg in 'line 1' 'line 2' 'line 3'
    324 		do
    325 			echo "$arg"
    326 			echo "$arg" >> Out1
    327 		done > Out2
    328 	EOF
    329 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} 
    330 	test "$(cat Out1)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
    331     "#$T: Incorrect Out1: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out1)'"
    332 	test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
    333     "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
    334 }
    335 
    336 atf_test_case fd_redirections
    337 fd_redirections_head()
    338 {
    339 	atf_set "descr" "Tests redirections to/from specific descriptors"
    340 }
    341 fd_redirections_body()
    342 {
    343 	# Or it will one day...
    344 } 
    345 
    346 atf_test_case local_redirections
    347 local_redirections_head()
    348 {
    349 	atf_set "descr" \
    350 	    "Tests that exec can reassign file descriptors in the shell itself"
    351 }
    352 local_redirections_body()
    353 {
    354 	# Or it will one day...
    355 }
    356 
    357 atf_test_case redir_in_case
    358 redir_in_case_head()
    359 {
    360 	atf_set "descr" "Tests that sh(1) allows just redirections " \
    361 	                "in case statements. (PR bin/48631)"
    362 }
    363 redir_in_case_body()
    364 {
    365 	atf_check -s exit:0 -o empty -e empty \
    366 	    ${TEST_SH} -c 'case x in (whatever) >foo;; esac'
    367 
    368 	atf_check -s exit:0 -o empty -e empty \
    369 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac'
    370 
    371 	atf_check -s exit:0 -o empty -e empty \
    372 	    ${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac'
    373 
    374 	atf_check -s exit:0 -o empty -e empty \
    375 	    ${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac'
    376 }
    377 
    378 atf_test_case incorrect_redirections
    379 incorrect_redirections_head()
    380 {
    381 	atf_set "descr" "Tests that sh(1) correctly ignores non-redirections"
    382 }
    383 incorrect_redirections_body() {
    384 
    385 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo>'
    386 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'read foo<'
    387 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>'
    388 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    389 		'echo x > '"$nl"
    390 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    391 		'read x < '"$nl"
    392 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    393 		'echo x <> '"$nl"
    394 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    395 		'echo x >< anything'
    396 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    397 		'echo x >>< anything'
    398 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    399 		'echo x >|< anything'
    400 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    401 		'echo x > ; read x < /dev/null || echo bad'
    402 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
    403 		'read x < & echo y > /dev/null; wait && echo bad'
    404 
    405 	rm -f Output 2>/dev/null || :
    406 	atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \
    407 		${TEST_SH} -c 'echo A Line \> Output'
    408 	test -f Output && atf_file "File 'Output' appeared and should not have"
    409 
    410 	rm -f Output 2>/dev/null || :
    411 	atf_check -s exit:0 -e empty -o empty \
    412 		${TEST_SH} -c 'echo A Line \>> Output'
    413 	test -f Output || atf_file "File 'Output' not created when it should"
    414 	test "$(cat Output)" = 'A Line >' || atf_fail \
    415 		"Output file contains '$(cat Output)' instead of '"'A Line >'\'
    416 
    417 	rm -f Output \> 2>/dev/null || :
    418 	atf_check -s exit:0 -e empty -o empty \
    419 		${TEST_SH} -c 'echo A Line >\> Output'
    420 	test -f Output && atf_file "File 'Output' appeared and should not have"
    421 	test -f '>' || atf_file "File '>' not created when it should"
    422 	test "$(cat '>')" = 'A Line Output' || atf_fail \
    423 	    "Output file ('>') contains '$(cat '>')' instead of 'A Line Output'"
    424 }
    425 
    426 # Many more tests in t_here, so here we have just rudimentary checks
    427 atf_test_case redir_here_doc
    428 redir_here_doc_head()
    429 {
    430 	atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \
    431 	                "input redirections"
    432 }
    433 redir_here_doc_body()
    434 {
    435 	# nb: the printf is not executed, it is data
    436 	cat <<- 'DONE' |
    437 		cat <<EOF
    438 			printf '%s\n' 'hello\n'
    439 		EOF
    440 	DONE
    441 	atf_check -s exit:0 -o match:printf -o match:'hello\\n' \
    442 		-e empty ${TEST_SH} 
    443 }
    444 
    445 atf_test_case subshell_redirections
    446 subshell_redirections_head()
    447 {
    448 	atf_set "descr" "Tests redirection interactions between shell and " \
    449 			"its sub-shell(s)"
    450 }
    451 subshell_redirections_body()
    452 {
    453 	# Or will, one day
    454 }
    455 
    456 atf_init_test_cases() {
    457 	atf_add_test_case basic_test_method_test
    458 	atf_add_test_case do_input_redirections
    459 	atf_add_test_case do_output_redirections
    460 	atf_add_test_case fd_redirections
    461 	atf_add_test_case local_redirections
    462 	atf_add_test_case incorrect_redirections
    463 	atf_add_test_case redir_here_doc
    464 	atf_add_test_case redir_in_case
    465 	atf_add_test_case subshell_redirections
    466 }
    467