1 # $NetBSD: t_syntax.sh,v 1.13 2023/12/28 20:04:10 andvar Exp $ 2 # 3 # Copyright (c) 2017 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 : ${TEST_SH:=/bin/sh} 28 29 # This set of tests verifies various requirementgs relating to correct 30 # (and incorrect) syntax of shell input 31 # 32 # There is no intent in these tests to verify correct operation 33 # (though that sometimes cannot be separated from correct parsing.) 34 # That is (or should be) verified elsewhere. 35 # 36 # Also, some very basic syntax is tested in almost every test 37 # (they cannot work without basic parsing of elementary commands) 38 # so that is also not explicitly tested here. 39 # 40 # Similarly word expansion, field splitting, redirection, all have 41 # tests of their own (though we do test parsing of redirect ops). 42 # 43 # Note that in order to test the basic facilities, other shell operations 44 # are used - a test failure here does not necessarily mean that the 45 # operation intended to be tested is faulty, just that something is. 46 47 atf_test_case a_basic_tokenisation 48 a_basic_tokenisation_head() { 49 atf_set "descr" "Test the shell correctly finds various tokens" 50 } 51 a_basic_tokenisation_body() { 52 atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \ 53 'set -- a b c; echo $#' 54 atf_check -s exit:0 -o 'inline:2\n' -e empty ${TEST_SH} -c \ 55 'set -- a""b c; echo $#' 56 atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \ 57 'set -- a"" b c; echo $#' 58 atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \ 59 'set -- ""a b c\;; echo $#' 60 61 atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \ 62 'set -- set -- c; echo $#' 63 atf_check -s exit:0 -o 'inline:1\n' -e empty ${TEST_SH} -c \ 64 'set --;set -- c; echo $#' 65 atf_check -s exit:0 -o 'inline:1\n' -e empty ${TEST_SH} -c \ 66 'set --&set -- c; echo $#' 67 atf_check -s exit:0 -o 'inline:1\n' -e empty ${TEST_SH} -c \ 68 'set -- a b&&set -- c; echo $#' 69 atf_check -s exit:0 -o 'inline:2\n' -e empty ${TEST_SH} -c \ 70 'set -- a b||set -- c; echo $#' 71 } 72 73 atf_test_case b_comments 74 b_comments_head() { 75 atf_set "descr" "Test the shell correctly handles comments" 76 } 77 b_comments_body() { 78 79 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '#' 80 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '# exit 1' 81 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'true # exit 1' 82 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c 'false # exit 0' 83 84 atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \ 85 'echo foo # bar' 86 atf_check -s exit:0 -o 'inline:foo # bar\n' -e empty ${TEST_SH} -c \ 87 'echo foo \# bar' 88 atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \ 89 'echo foo; # echo bar' 90 atf_check -s exit:0 -o 'inline:foo#bar\n' -e empty ${TEST_SH} -c \ 91 'echo foo#bar' 92 atf_check -s exit:0 -o 'inline:foo# bar\n' -e empty ${TEST_SH} -c \ 93 'echo foo# bar' 94 atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \ 95 'x=foo; echo ${x#bar}' 96 97 atf_check -s exit:0 -o 'inline:#\n' -e empty ${TEST_SH} -c \ 98 'echo "#"' 99 atf_check -s exit:0 -o 'inline:#\n' -e empty ${TEST_SH} -c \ 100 "echo '#'" 101 atf_check -s exit:0 -o 'inline:#\n' -e empty ${TEST_SH} -c \ 102 'echo \#' 103 atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \ 104 'echo "#"#' 105 atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \ 106 "echo '#'#" 107 atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \ 108 'echo \##' 109 atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \ 110 'echo "#"# #"#"' 111 atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \ 112 "echo '#'# #'#'" 113 atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \ 114 'echo \## #\#' 115 116 cat <<-'DONE' | 117 # test comments do not provoke syntax errors !\ 118 echo foo # ( { " hello 119 while : # that's forever 120 do # the following command list 121 # starting with nothing ${unset?error} 122 break # done loop terminate $( echo bar; exit 1 ) 123 done ##################################################### 124 # "hello 125 exit 0 126 DONE 127 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} || 128 atf_fail "ignoring comments" 129 } 130 131 atf_test_case c_line_wrapping 132 c_line_wrapping_head() { 133 atf_set "descr" "check aspects of command line wrapping" 134 } 135 c_line_wrapping_body() { 136 atf_require_prog ls 137 atf_require_prog printf 138 139 cat <<- 'DONE' | atf_check -s exit:0 -o ignore -e empty ${TEST_SH} -e || 140 l\ 141 s 142 DONE 143 atf_fail "#1: ls wrapped fails" 144 145 cat <<- 'DONE' | atf_check -s exit:7 -o empty -e empty ${TEST_SH} || 146 e\ 147 x\ 148 it \ 149 7 150 DONE 151 atf_fail "#2: exit7 wrapped fails" 152 153 # Have to do this twice as cannot say "any exit code but 0 or 7" ... 154 cat <<- 'DONE' | atf_check -s not-exit:0 -o empty -e not-empty \ 155 ${TEST_SH} || 156 e\ 157 x\ 158 it\ 159 7 160 DONE 161 atf_fail "#3a: !exit(0||7) badly wrapped fails (0)" 162 cat <<- 'DONE' | atf_check -s not-exit:7 -o empty -e not-empty \ 163 ${TEST_SH} || 164 e\ 165 x\ 166 it\ 167 7 168 DONE 169 atf_fail "#3b: !exit(0||7) badly wrapped fails (7)" 170 171 cat <<- 'DONE' | atf_check -s exit:0 -o empty -e empty ${TEST_SH} || 172 wh\ 173 il\ 174 e \ 175 f\a\ 176 \l\s\e 177 do 178 :\ 179 ; 180 done 181 DONE 182 atf_fail "#4: wrapped while fails" 183 184 cat <<- 'DONE' | atf_check -s exit:0 -o inline:'hellohellohellohello' \ 185 -e empty ${TEST_SH} || 186 V\ 187 AR=hel\ 188 lo 189 unset U V1 190 pri\ 191 ntf '%s' ${\ 192 VAR\ 193 } 194 p\ 195 r\ 196 i\ 197 n\ 198 t\ 199 f\ 200 \ 201 '%s' \ 202 $\ 203 {\ 204 V\ 205 A\ 206 R} 207 printf '%s' ${U\ 208 -\ 209 "$\ 210 {V\ 211 1:\ 212 =$\ 213 {V\ 214 AR+\ 215 ${V\ 216 AR}\ 217 }\ 218 }"} 219 printf '%s' ${V\ 220 1?V1\ 221 \ 222 FAIL} 223 DONE 224 atf_fail "#5: wrapped var expansions fails" 225 226 cat <<- 'DONE' | atf_check -s exit:0 -o inline:'2\n' ${TEST_SH} || 227 l\ 228 s=7 bi\ 229 n\ 230 =\ 231 3 232 echo $(\ 233 ( ls /bin )\ 234 ) 235 DONE 236 atf_fail "#6: wrapped command substitution fails" 237 238 # Inspired by src/etc/MAKEDEV.tmpl failure with (broken) 239 # sh LINENO code... avoid it happening again... 240 for VARS in 1:0:0:0 0:1:0:0 0:0:1:0 0:0:0:1 \ 241 1:0:0:1 1:0:1:0 1:1:0:0 0:1:1:0 \ 242 0:0:0:0 1:1:0:1 0:1:1:1 1:1:1:1 243 do 244 eval $( 245 IFS=: 246 set -- $VARS 247 test $(( $1 + $2 + $3 + $4 )) -eq 1 && 248 R=OK || R=BAD 249 printf "R=%s;" $R 250 for v in a b c d 251 do 252 case $1 in 253 (0) printf "export %s=false;" $v;; 254 (1) printf "export %s=true;" $v;; 255 esac 256 shift 257 done 258 ) 259 260 cat <<- 'DONE' | 261 case $(( $($a && echo 1 || echo 0) + \ 262 $($b && echo 1 || echo 0) + \ 263 $($c && echo 1 || echo 0) + \ 264 $($d && echo 1 || echo 0) )) 265 in 266 (1) printf OK ;; 267 (*) printf BAD ;; 268 esac 269 DONE 270 atf_check -s exit:0 -o inline:"${R}" ${TEST_SH} || 271 atf_fail "#7 (${VARS}): wrapped arith fails" 272 done 273 274 # inspired by pkgsrc/pkgtools/cwrappers :: libnbcompat/configure 275 # failure with (broken) sh LINENO code .. avoid recurrence 276 # This test would have failed. 277 cat <<- 'DONE' | atf_check -s exit:0 -o inline:'/tmp\n' ${TEST_SH} || 278 dn=/tmp/foo 279 280 D=`dirname -- "${dn}" || 281 expr X"${dn}" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 282 X"${dn}" : 'X\(//\)[^/]' \| \ 283 X"${dn}" : 'X\(//\)$' \| \ 284 X"${dn}" : 'X\(/\)' \| . 2>/dev/null || 285 echo X"${dn}" | 286 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 287 s//\1/ 288 q 289 } 290 /^X\(\/\/\)[^/].*/{ 291 s//\1/ 292 q 293 } 294 /^X\(\/\/\)$/{ 295 s//\1/ 296 q 297 } 298 /^X\(\/\).*/{ 299 s//\1/ 300 q 301 } 302 s/.*/./; q'` 303 304 echo "${D}" 305 DONE 306 atf_fail "#8: cwrappers/LINENO bug test failed" 307 308 return 0 309 } 310 311 atf_test_case d_cstrings 312 d_cstrings_head() { 313 atf_set "descr" "Check processing of $' ' quoting (C style strings)" 314 } 315 d_cstrings_body() { 316 unset ENV 317 318 if ! ${TEST_SH} -c ": \$'abc'" || 319 test $( ${TEST_SH} -c "printf %s \$'abc'" ) != abc 320 then 321 atf_skip "\$'...' (C style quoted strings) not supported" 322 fi 323 324 # simple stuff 325 atf_check -s exit:0 -e empty -o inline:'abc\tdef\n' ${TEST_SH} -c \ 326 "printf '%s\\n' \$'abc\tdef'" 327 atf_check -s exit:0 -e empty -o inline:'abc\tdef\n' ${TEST_SH} -c \ 328 "printf '%s\\n' \$'abc\011def'" 329 atf_check -s exit:0 -e empty -o inline:'abc\tdef\n' ${TEST_SH} -c \ 330 "printf '%s\\n' \$'abc\x09'def" 331 atf_check -s exit:0 -e empty -o inline:'abc$def\n' ${TEST_SH} -c \ 332 "def=xyz; printf '%s\\n' \$'abc\$def'" 333 334 # control chars (\c) and unicode \u 335 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 336 "test \$'\\1-\\2-\\3' = \$'\\ca-\\cb-\\cc'" 337 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 338 "test \$'\\r-\\n-\\f' = \$'\\cm-\\cj-\\cl'" 339 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 340 "unset LC_ALL; export LC_CTYPE=en_AU.UTF-8; 341 test \$'\\u0123' = \$'\\304\\243'" 342 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 343 "test \$'\\u0123' = \$'\\xC4\\xA3'" 344 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 345 "test \$'\\c\\\\' = \$'\\x1C'" 346 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 347 "test \$'\\c[\\c]\\c^\\c_\\c?' = \$'\\x1B\\x1D\\x1E\\x1F\\x7F'" 348 349 # all the \X sequences for a single char X (ie: not hex/octal/unicode) 350 atf_check -s exit:0 -e empty -o inline:'\n\r\t\n' \ 353 ${TEST_SH} -c "printf '%s\\n' \$'\\a\\b\\e\\f\\n\\r\\t\\v'" 354 atf_check -s exit:0 -e empty -o inline:'\n\r\t\n' \ 357 ${TEST_SH} -c "printf '%s\\n' \$'\\cG\\cH\\x1b\\cl\\cJ\\cm\\cI\\ck'" 358 atf_check -s exit:0 -e empty -o inline:"'"'"\\\n' \ 359 ${TEST_SH} -c "printf '%s\\n' \$'\\'\\\"\\\\'" 360 361 # various invalid $'...' sequences 362 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 363 ": \$'\\q'" 364 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 365 ": \$'\\c\\q'" 366 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 367 ": \$'\\uDEFF'" 368 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 369 ": \$'abcd" 370 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 371 ": \$'abcd\\" 372 373 # anything that generates \0 ends the $'...' immediately 374 atf_check -s exit:0 -e empty -o inline:'aAaA' ${TEST_SH} -c \ 375 "printf '%s' \$'a\\0x'\$'A\\x00X'\$'a\\c@x'\$'A\\u0000X'" 376 377 # \newline in a $'...' is dropped (just like in "" strings) 378 atf_check -s exit:0 -e empty -o inline:'abcdef' ${TEST_SH} -c \ 379 "printf '%s' \$'abc\\ 380 def'" 381 # but a normal newline in a $'...' is just a newline 382 atf_check -s exit:0 -e empty -o inline:'abc\ndef' ${TEST_SH} -c \ 383 "printf '%s' \$'abc 384 def'" 385 # and should work when elided line wrap occurs between $ and ' 386 atf_check -s exit:0 -e empty -o inline:'abc\ndef' ${TEST_SH} -c \ 387 "printf '%s' \$\\ 388 'abc\\ndef'" 389 390 # $'...' only works when the $ is unquoted. 391 atf_check -s exit:0 -e empty -o inline:"abc\$'def'g" ${TEST_SH} -c \ 392 "printf '%s' \"abc\$'def'g\"" 393 atf_check -s exit:0 -e empty -o inline:'abc$defg' ${TEST_SH} -c \ 394 "printf '%s' abc\\\$'def'g" 395 atf_check -s exit:0 -e empty -o inline:'abc$def' ${TEST_SH} -c \ 396 "printf '%s' abc'\$'def" 397 } 398 399 atf_test_case f_redirects 400 f_redirects_head() { 401 atf_set "descr" "Check parsing of redirect operators" 402 } 403 f_redirects_body() { 404 405 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 406 '>/dev/null' 407 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 408 '</dev/null' 409 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 410 '>>/dev/null' 411 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 412 '<>/dev/null' 413 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 414 '</dev/null>/dev/null' 415 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 416 '>|/dev/null' 417 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 418 '>/dev/null>/dev/null>/dev/null' 419 420 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 421 'echo hello >/dev/null' 422 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 423 'echo >/dev/null hello' 424 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 425 '>/dev/null echo hello' 426 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 427 'echo hello >/dev/null world' 428 atf_check -s exit:0 -o 'inline:hello world\n' -e empty ${TEST_SH} -c \ 429 'echo hello </dev/null world' 430 431 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 432 'echo hello </dev/null' 433 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 434 'echo hello 3</dev/null' 435 atf_check -s exit:0 -o 'inline:hello 3\n' -e empty ${TEST_SH} -c \ 436 'echo hello 3 </dev/null' 437 atf_check -s exit:0 -o 'inline:hello 3\n' -e empty ${TEST_SH} -c \ 438 'echo hello \3</dev/null' 439 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 440 'echo hello</dev/null' 441 atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \ 442 'hello=3; echo ${hello}</dev/null' 443 444 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 445 '2>&1' 446 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 447 '2>& 1' 448 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 449 'FD=1; 2>&"${FD}"' 450 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 451 'FD=1; echo hello 2>&"${FD}" >&2' 452 453 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 454 '2>&- 3<&- 4>&-' 455 456 return 0 457 } 458 459 atf_test_case g_variable_syntax 460 g_variable_syntax_head() { 461 atf_set "descr" "Check that var names of all legal forms work" 462 } 463 g_variable_syntax_body() { 464 # don't test _ as a variable, it can be "unusual" 465 for vname in a ab _a _9 a123 a_1_2_3 __ ___ ____ __1__ _0 \ 466 A AA AAA AaBb _A_a A_a_ a1_ abc_123 ab_12_cd_ef_34_99 \ 467 abcdefghijklmnopqrstuvwzyz ABCDEFGHIJKLMNOPQRSTUVWXYZ_ \ 468 A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all \ 469 Then_Make_it_Even_Longer_by_Multiplying_it___A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all__A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all__A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all__A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all \ 470 xyzzy __0123454321__ _0_1_2_3_4_5_6_7_8_9_ ABBA X_ Y__ Z___ \ 471 _____________________________________________________________ 472 do 473 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 474 "unset ${vname}" 475 atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -c \ 476 "unset ${vname}; printf %s \${${vname}-OK}" 477 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 478 "${vname}=GOOD; printf %s \${${vname}-OK}" 479 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 480 "${vname}=GOOD; printf %s \$${vname}" 481 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 482 "unset ${vname};${vname}=GOOD;printf %s \${${vname}-OK}" 483 atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -c \ 484 "${vname}=GOOD;unset ${vname};printf %s \${${vname}-OK}" 485 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 486 "${vname}=GOOD; unset ${vname}x; printf %s \$${vname}" 487 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 488 "unset ${vname}x; ${vname}=GOOD; printf %s \$${vname}x" 489 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 490 "${vname}=GOOD; ${vname}_=BAD; printf %s \$${vname}" 491 492 case "${vname}" in 493 ?) continue;; 494 esac 495 496 # The following tests do not work for 1 char var names. 497 # hence the check and "continue" above to skip the remaining 498 # tests for that case 499 500 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 501 "${vname}=GOOD; unset ${vname%?}; printf %s \$${vname}" 502 503 # (this next would work, but becomes just a duplicate of 504 # an earlier test, so is pointless for 1 ch names) 505 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 506 "${vname}=GOOD; unset ${vname}x ${vname%?}; printf %s \$${vname}" 507 508 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 509 "unset ${vname%?};${vname}=GOOD; printf %s \$${vname%?}" 510 511 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 512 "${vname}=GOOD; ${vname%?}=BAD; printf %s \$${vname}" 513 514 # all the remaining tests require the 2nd char of the 515 # variable name to be a legal first character. That 516 # is, not a digit, so skip the rest if we have a digit 517 # second... 518 case "${vname}" in 519 ?[0-9]*) continue;; 520 esac 521 522 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 523 "${vname}=GOOD; unset ${vname#?}; printf %s \$${vname}" 524 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 525 "unset ${vname#?};${vname}=GOOD; printf %s \$${vname#?}" 526 527 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 528 "${vname}=GOOD; ${vname#?}=BAD; printf %s \$${vname}" 529 530 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 531 "unset ${vname%?} ${vname#?} ${vname}x; ${vname}=GOOD; 532 printf %s \$${vname%?}\$${vname#?}\$${vname}x" 533 534 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 535 "${vname}=GOOD; ${vname%?}=BAD; ${vname}_=BAD; 536 ${vname#?}=BAD; printf %s \$${vname}" 537 done 538 539 # don't test '.' in var names, some shells permit that (in ${} anyway) 540 # this test also cannot check for embedded - + ? = : % or # 541 for vname in ,x -p +h :def 0_1 'x*x' '()' '"' "'" 'a b c' '?!' ';' 542 do 543 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 544 "echo \${${vname}}" 545 done 546 547 for vname in ,x -p +h :def 0_1 'x*x' '()' '"' "'" 'a b c' x,y,z '?!' \ 548 ';' a-b a+b 'a?b' 'a:b' 'a%b' 'a#b' 0 1 99 @ '*' '!' '?' 549 do 550 # failure modes will differ, but they should all fail somehow 551 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 552 "${vname}=" 553 done 554 555 } 556 557 atf_test_case h_var_assign 558 h_var_assign_head() { 559 atf_set "descr" "Check var assignments " 560 } 561 h_var_assign_body() { 562 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 563 'a=b' 564 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 565 '\a=b' 566 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 567 'a=b c=d' 568 atf_check -s exit:0 -e empty -o 'inline:e=f\n' ${TEST_SH} -c \ 569 'a=b c=d echo e=f' 570 atf_check -s exit:0 -e empty -o 'inline:e=f\n' ${TEST_SH} -c \ 571 'a=b 2>/dev/null c=d </dev/null echo e=f' 572 573 # We need to make sure that we do not accidentally 574 # find a command called 'a=b' ... 575 576 for d in /foo /foo/bar /not-dir /no/such/directory '/!!!' \ 577 '/-/--/#' '/"/""/"""' - 578 do 579 test -d "${d}" || break 580 done 581 test "${#d}" -gt 1 || atf-skip 'Wacky directories seem to exist!' 582 583 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 584 "PATH='${d}';"'a=\b' 585 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 586 "PATH='${d}';"'a\=b' 587 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 588 "PATH='${d}';"'\a=b' 589 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 590 "PATH='${d}';"'X=; c=d ${X} a=b' 591 } 592 593 atf_test_case i_pipelines 594 i_pipelines_head() { 595 atf_set "descr" "Check pipelines" 596 } 597 i_pipelines_body() { 598 599 cmd='printf "%s\n" foo' 600 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 601 do 602 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 603 "${cmd}" 604 cmd="${cmd} | cat" 605 done 606 607 cmd='printf "%s\n" foo' 608 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 609 do 610 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 611 "${cmd}" 612 cmd="${cmd} | 613 cat" 614 done 615 616 cmd='printf "%s\n" foo' 617 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 618 do 619 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 620 "${cmd}" 621 cmd="${cmd} | 622 623 624 625 626 cat" 627 done 628 629 cmd='! printf "%s\n" foo' 630 for n in 1 2 3 4 5 6 7 8 9 10 631 do 632 atf_check -s exit:1 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 633 "${cmd}" 634 cmd="${cmd} | cat" 635 done 636 637 cmd='exec 4>&2 3<&0; printf "%s\n" foo' 638 for n in 1 2 3 639 do 640 pfx= 641 for xtra in 'x=y' 'a=b' '6>&1' '5<&3' 642 do 643 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 644 "${cmd} | ${xtra} cat" 645 646 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 647 "${cmd} | ${pfx} cat" 648 649 pfx="${pfx} ${xtra}" 650 done 651 cmd="${cmd} | ${pfx} cat" 652 done 653 654 # pipelines are not required to contain commands ... 655 # they don't do anything useful (at all) but the syntax is legal 656 base='4>&2'; cmd="${base}" 657 for pipe in 'a=b' '3<&0' '>>/dev/null' 'a= b= c=' '${x}' 'cat' 658 do 659 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 660 "${base} | ${pipe}" 661 662 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 663 "${cmd} | ${pipe}" 664 665 cmd="${cmd} | ${pipe}" 666 done 667 668 # but the command cannot be empty, or a reserved word used improperly 669 base='printf "%s\n" foo'; cmd="${base}" 670 for pipe in '' do done then else fi esac 671 do 672 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 673 "${base} | ${pipe}" 674 675 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 676 "${pipe} | ${base}" 677 678 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 679 "${cmd} | ${pipe}" 680 681 cmd="${cmd} | ${pipe}" 682 done 683 } 684 685 atf_test_case j_and_or_lists 686 j_and_or_lists_head() { 687 atf_set "descr" "Check && and || command lists" 688 } 689 j_and_or_lists_body() { 690 and=true 691 or=false 692 and_or=false 693 for i in 1 2 3 4 5 6 7 8 9 10 694 do 695 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 696 "${and}" 697 698 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 699 "${or}" 700 701 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 702 "${and_or}" 703 704 and="${and} && true" 705 or="${or} || false" 706 and_or="${and_or} || true && false" 707 done 708 709 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 710 'true &&' 711 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 712 '&& true' 713 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 714 '|| true' 715 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 716 'true ||' 717 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 718 'true || && false' 719 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 720 'false || && true' 721 722 cmd='printf "%s" foo | cat | cat>/dev/null' 723 line="${cmd}" 724 for i in 1 2 3 4 725 do 726 line="${line} && ! ${cmd} || ${cmd}" 727 728 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 729 "${line}" 730 done 731 732 } 733 734 atf_test_case k_lists 735 k_lists_head() { 736 atf_set "descr" "Check ; command lists" 737 } 738 k_lists_body() { 739 line= 740 for N in 1 2 3 4 741 do 742 for cmd in \ 743 true false : 'cat</dev/null>/dev/null' x=3 'exec 4>&-' 744 do 745 line="${line}${line:+;}${cmd}" 746 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 747 -e empty ${TEST_SH} -c \ 748 "echo hello; ${line}; echo world" 749 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 750 -e empty ${TEST_SH} -c \ 751 "echo hello; ${line}; echo world;" 752 done 753 done 754 755 for cmd in ';' ';;' 'false ;; true' 'false; ;true' '; true' 756 do 757 atf_check -s not-exit:0 -o ignore -e not-empty \ 758 ${TEST_SH} -c "${cmd}" 759 done 760 } 761 762 atf_test_case l_async_lists 763 l_async_lists_head() { 764 atf_set "descr" "Check & command lists" 765 } 766 l_async_lists_body() { 767 line= 768 for N in 1 2 3 4 769 do 770 for cmd in \ 771 true false : 'cat</dev/null>/dev/null' x=3 'exec 4>&-' 772 do 773 line="${line:+${line}&}${cmd}" 774 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 775 -e empty ${TEST_SH} -c \ 776 "echo hello; ${line}& echo world" 777 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 778 -e empty ${TEST_SH} -c \ 779 "echo hello; ${line}& echo world" 780 done 781 done 782 783 for cmd in '&' ';&' '&;' '& true' 'false& &true' 784 do 785 atf_check -s not-exit:0 -o ignore -e not-empty \ 786 ${TEST_SH} -c "${cmd}" 787 done 788 } 789 790 atf_test_case m_compound_lists 791 m_compound_lists_head() { 792 atf_set "descr" "Check subshells () and { ;} command grouping" 793 } 794 m_compound_lists_body() { 795 # Note: (( is an unspecified (reserved) operator, don't use it... 796 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 797 '( true )' 798 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 799 '( false )' 800 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 801 '( (:) )' 802 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 803 '( ( true ))' 804 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 805 '( ( ( ( ( true )))))' 806 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 807 '( ( ( ( (true);:));true))' 808 809 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 810 '()' 811 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 812 '( )' 813 814 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 815 '{ true; }' 816 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 817 '{ false; }' 818 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 819 '{ { :; };}' 820 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 821 '{ { { { { :;};};};};}' 822 823 atf_check -s exit:0 -o 'inline:}\n' -e empty ${TEST_SH} -c \ 824 '{ echo } ; }' 825 atf_check -s exit:0 -o 'inline:{\n' -e empty ${TEST_SH} -c \ 826 '{ echo { ; }' 827 } 828 829 atf_test_case q_for_loop 830 q_for_loop_head() { 831 atf_set "descr" "Check for loop parsing" 832 } 833 q_for_loop_body() { 834 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 835 'for x; do : ; done' 836 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 837 'for x in ; do : ; done' 838 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 839 'for x in a b c ; do : ; done' 840 841 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 842 'for x in in;do : ; done' 843 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 844 'for x in for;do : ; done' 845 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 846 'for x in do;do : ; done' 847 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 848 'for for in in;do :;done' 849 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 850 'for for in for;do :; done' 851 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 852 'for for in do;do : ;done' 853 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 854 'for in in in;do : ; done' 855 atf_check -s exit:0 -o 'inline:do\nin\ndo\n' -e empty ${TEST_SH} -c \ 856 'for in in in do in;do case $in in in)echo do;;do)echo in;;esac; done' 857 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 858 'for in in for;do : ; done' 859 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 860 'for in in do;do : ; done' 861 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 862 'for do in in;do : ; done' 863 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 864 'for do in for;do : ; done' 865 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 866 'for do in do;do : ; done' 867 atf_check -s exit:0 -o 'inline:dodo\n' -e empty ${TEST_SH} -c \ 868 'for do in do;do echo ${do}do ; done' 869 } 870 871 atf_test_case r_case 872 r_case_head() { 873 atf_set "descr" "Check case statement parsing" 874 } 875 r_case_body() { 876 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 877 'case x in esac' 878 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 879 'case x in x) esac' 880 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 881 'case x in (x) esac' 882 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 883 'case x in x) ;; esac' 884 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 885 'case x in (x) ;; esac' 886 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 887 'case x in x|y) ;; esac' 888 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 889 'case x in (x|y) ;; esac' 890 891 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 892 'case x in x|esac) ;; esac' 893 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 894 'case x in x|esac|y) ;; esac' 895 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 896 'case x in (x|esac) ;; esac' 897 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 898 'case x in (x|esac|y) ;; esac' 899 900 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 901 'case x in in) esac' 902 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 903 'case x in in) ;; esac' 904 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 905 'case x in x|in) ;; esac' 906 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 907 'case x in x|in|y) ;; esac' 908 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 909 'case x in (x|in) ;; esac' 910 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 911 'case x in (in|x) ;; esac' 912 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 913 'case x in (x|in|y) ;; esac' 914 915 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 916 'case case in case) esac' 917 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 918 'case in in in) esac' 919 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 920 'case esac in (in) esac' 921 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 922 'case in in esac|cat' 923 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 924 'case esac in esac|cat' 925 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 926 'case in in esac|case x in u) echo foo;; esac' 927 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 928 'case esac in esac|case x in u) echo foo;; esac' 929 atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \ 930 'case in in esac|case x in x) echo foo;; esac' 931 932 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 933 'case in in (esac|cat' 934 935 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 936 'case x in x );;esac' 937 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 938 'case x in ( x );;esac' 939 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 940 'case x in x | y );;esac' 941 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 942 'case x in ( x | y );;esac' 943 944 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 945 'case x 946 in 947 ( x | y ) 948 949 ;; 950 951 952 esac 953 ' 954 } 955 956 atf_test_case s_if 957 s_if_head() { 958 atf_set "descr" "Check if statement parsing" 959 } 960 s_if_body() { 961 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 962 'if :; then :; fi' 963 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 964 'if :; then :; else :; fi' 965 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 966 'if :; then :; elif :; then :; else :; fi' 967 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 968 'if :; then :; elif :; then :; elif :; then :; else :; fi' 969 970 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 971 'if :; then : else :; fi' 972 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 973 'if : then :; then :; fi' 974 975 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 976 'if if :;then :;fi then :;fi' 977 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 978 'if if :;then if :;then :;fi fi;then :;fi' 979 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 980 'if if :;then :;fi;then :;else if :;then :;fi fi' 981 982 for a in true false; do 983 for b in true false; do 984 for c in true false; do 985 986 $a && out=a || { 987 $b && out=b || { 988 $c && out=c || { 989 out=d; };};} 990 991 atf_check -s exit:0 -e empty \ 992 -o "inline:${out}"'\n' \ 993 ${TEST_SH} -c \ 994 "if $a; then echo a 995 elif $b; then echo b 996 elif $c; then echo c 997 else echo d 998 fi" 999 done 1000 done 1001 done 1002 } 1003 1004 atf_test_case t_loops 1005 t_loops_head() { 1006 atf_set "descr" "Check while/until loop parsing" 1007 } 1008 t_loops_body() { 1009 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1010 'while false; do :; done' 1011 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1012 'while false; do \done; done' 1013 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1014 'until :; do :; done' 1015 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1016 'until :; do \done; done' 1017 1018 atf_check -s exit:0 -o 'inline:x\n1\n' -e empty ${TEST_SH} -c \ 1019 ':; while (exit) do echo x; false; done; echo $?' 1020 atf_check -s exit:0 -o 'inline:x\n0\n' -e empty ${TEST_SH} -c \ 1021 'false; until (exit) do echo x; done; echo $?' 1022 } 1023 1024 atf_test_case u_case_cont 1025 u_case_cont_head() { 1026 atf_set "descr" "Check case stmt parsing using ;& [optional]" 1027 } 1028 u_case_cont_body() { 1029 1030 ${TEST_SH} -c 'case x in (x) false ;& (y) : ;; esac' 2>/dev/null || 1031 atf_skip ";& case list terminator unsupported in ${TEST_SH}" 1032 1033 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1034 'case x in x) ;& esac' 1035 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1036 'case x in (x) ;& esac' 1037 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1038 'case x in x|y) ;& esac' 1039 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1040 'case x in (x|y) ;& esac' 1041 1042 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1043 'case x in x );&esac' 1044 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1045 'case x in ( x );&esac' 1046 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1047 'case x in x | y );&esac' 1048 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1049 'case x in ( x | y );&esac' 1050 1051 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1052 'case x in x) ;& (y) esac' 1053 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1054 'case x in (x) ;& esac' 1055 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1056 'case x in x|y) ;& esac' 1057 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1058 'case x in (x|y) ;& esac' 1059 } 1060 1061 atf_test_case x_functions 1062 x_functions_head() { 1063 atf_set "descr" "Check function definition parsing" 1064 } 1065 x_functions_body() { 1066 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1067 'func() { :; }' 1068 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1069 'func() { :; }; func' 1070 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1071 'func()(:)' 1072 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1073 'func()if :; then false; else true; fi' 1074 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1075 'func()while false; do :;done' 1076 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1077 'func () for a in b c; do :; done' 1078 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1079 'func() case x in (y) esac' 1080 1081 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1082 'f1() { f2() { :; }; }; f1; f2' 1083 1084 # f2 should be not found, but f1 clears $? 1085 atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} -c \ 1086 'f1() { f2() { :; }; }; f2; f1' 1087 1088 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1089 'f1() { eval "$1() { :; }"; }; f1 f2; f2' 1090 } 1091 1092 atf_test_case z_PR_48498 1093 z_PR_48498_head() { 1094 atf_set "descr" "Check for detecting the syntax error from PR bin/48498" 1095 } 1096 z_PR_48498_body() { 1097 1098 # reserved words/operators that end things, 1099 # were completely ignored after a ';' or '&' 1100 # many of these tests lifted directly from the PR 1101 1102 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1103 'true; fi' 1104 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1105 'false; fi' 1106 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1107 'false; then echo wut' 1108 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1109 'true; then echo wut' 1110 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1111 'true; do echo wut' 1112 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1113 'true; then' 1114 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1115 'true; else' 1116 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1117 'true; do' 1118 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1119 'true; done' 1120 # { 1121 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1122 ': ; }' 1123 # ( 1124 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1125 ':;)' 1126 1127 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1128 'true& fi' 1129 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1130 'false& fi' 1131 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1132 'false& then echo wut' 1133 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1134 'true& then echo wut' 1135 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1136 'true& do echo wut' 1137 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1138 'true& then' 1139 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1140 'true& else' 1141 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1142 'true& do' 1143 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1144 'true&done' 1145 # { 1146 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1147 ':&}' 1148 # ( 1149 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1150 ':&)' 1151 } 1152 1153 atf_test_case z_PR_52426 1154 z_PR_52426_head() { 1155 atf_set "descr" "Check for detecting the syntax error from PR bin/52426" 1156 } 1157 z_PR_52426_body() { 1158 # Absoluely anything was permitted as a pattern of a case 1159 # statement, any token (except 'esac') would serve 1160 # What follows are a few "pretty" examples that were accepted. 1161 # The first is the example from the PR 1162 1163 # Note we use only ;; type case lists, ;& should do the same, but 1164 # only for shells that support it, we do not want the shell to 1165 # object to any of these just because it does not support ;& 1166 1167 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1168 'case x in <|() ;; esac' 1169 1170 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1171 'case x in ((|)) ;; esac' 1172 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1173 'case x in _|() ;; esac' 1174 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1175 'case x in ()|() ;; esac' 1176 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1177 'case x in -|;) ;; esac' 1178 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1179 'case x in (;|-) ;; esac' 1180 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1181 'case x in ;;|;) ;; esac' 1182 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1183 'case x in (|| | ||) ;; esac' 1184 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1185 'case x in (<<|>>) ;; esac' 1186 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1187 'case x in (&&|&) ;; (|||>&) ;; &) esac' 1188 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1189 'case x in (>||<) ;; esac' 1190 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1191 'case x in( || | || | || | || | || );; esac' 1192 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1193 'case x in (||| ||| ||| ||| ||) ;; esac' 1194 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1195 'case x in <> | 1196 ) ;; esac' 1197 1198 # now check some similar looking cases that are supposed to work 1199 # That is, make sure the fix for the PR does not break valid cases. 1200 1201 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1202 'case fi in ({|}) ;; (!) ;; esac' 1203 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1204 'case esac in ([|]);; (][);; !!!|!!!|!!!|!!!);; esac' 1205 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1206 'case then in ({[]]}) ;; (^^);; (^|^);; ([!]);; (-);; esac' 1207 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1208 'case while in while );;(if|then|elif|fi);;(do|done);; esac' 1209 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1210 'case until in($);;($$);;($4.50);;(1/2);;0.3333);;esac' 1211 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1212 'case return in !);; !$);; $!);; !#);; (@);; esac' 1213 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1214 'case break in (/);; (\/);; (/\|/\));; (\\//);; esac' 1215 } 1216 1217 atf_test_case z_PR_53712 1218 z_PR_53712_head() { 1219 atf_set "descr" "Check for avoiding the core dump from PR bin/53712" 1220 } 1221 z_PR_53712_body() { 1222 atf_require_prog sysctl 1223 atf_require_prog rm 1224 1225 # Don't want to have to deal with all the possible ways 1226 # that the systcm might be configured to drop core files... 1227 sysctl -w proc.$$.corename=core || 1228 atf_skip "Unable to set file name for core dump file" 1229 rm -f core 1230 1231 ${TEST_SH} -c '{ } > out'; S=$? 1232 test -f core && 1233 atf_fail "PR bin/53712: ${TEST_SH} dumps core: status=$S" 1234 test "$S" -lt 128 || 1235 atf_fail "PR bin/53712: ${TEST_SH} reported status $S (core?)" 1236 1237 # It doesn't matter here whether or not there was an error 1238 # from the empty compound, or whether "out" was created 1239 # just that no core dump appeared, and the shell did not 1240 # exit because of a signal. 1241 1242 return 0 1243 } 1244 1245 atf_init_test_cases() { 1246 atf_add_test_case a_basic_tokenisation 1247 atf_add_test_case b_comments 1248 atf_add_test_case c_line_wrapping 1249 atf_add_test_case d_cstrings 1250 atf_add_test_case f_redirects 1251 atf_add_test_case g_variable_syntax 1252 atf_add_test_case h_var_assign 1253 atf_add_test_case i_pipelines 1254 atf_add_test_case j_and_or_lists 1255 atf_add_test_case k_lists 1256 atf_add_test_case l_async_lists 1257 atf_add_test_case m_compound_lists 1258 atf_add_test_case q_for_loop 1259 atf_add_test_case r_case 1260 atf_add_test_case s_if 1261 atf_add_test_case t_loops 1262 atf_add_test_case u_case_cont 1263 atf_add_test_case x_functions 1264 1265 atf_add_test_case z_PR_48498 1266 atf_add_test_case z_PR_52426 1267 atf_add_test_case z_PR_53712 1268 } 1269