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