1# $NetBSD: t_syntax.sh,v 1.8 2017/08/19 21:18:47 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 "test \$'\\u0123' = \$'\\304\\243'" 328 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 329 "test \$'\\u0123' = \$'\\xC4\\xA3'" 330 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 331 "test \$'\\c\\\\' = \$'\\x1C'" 332 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 333 "test \$'\\c[\\c]\\c^\\c_\\c?' = \$'\\x1B\\x1D\\x1E\\x1F\\x7F'" 334 335 # all the \X sequences for a single char X (ie: not hex/octal/unicode) 336 atf_check -s exit:0 -e empty -o inline:'\n\r\t\n' \ 337 ${TEST_SH} -c "printf '%s\\n' \$'\\a\\b\\e\\f\\n\\r\\t\\v'" 338 atf_check -s exit:0 -e empty -o inline:'\n\r\t\n' \ 339 ${TEST_SH} -c "printf '%s\\n' \$'\\cG\\cH\\x1b\\cl\\cJ\\cm\\cI\\ck'" 340 atf_check -s exit:0 -e empty -o inline:"'"'"\\\n' \ 341 ${TEST_SH} -c "printf '%s\\n' \$'\\'\\\"\\\\'" 342 343 # various invalid $'...' sequences 344 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 345 ": \$'\\q'" 346 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 347 ": \$'\\c\\q'" 348 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 349 ": \$'\\uDEFF'" 350 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 351 ": \$'\\u00'" 352 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 353 ": \$'\\u8'" 354 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 355 ": \$'abcd" 356 atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \ 357 ": \$'abcd\\" 358 359 # anything that generates \0 ends the $'...' immediately (\u cannot) 360 atf_check -s exit:0 -e empty -o inline:'aAa' ${TEST_SH} -c \ 361 "printf '%s' \$'a\\0x'\$'A\\x00X'\$'a\\c@x'" 362 363 # \newline in a $'...' is dropped (just like in "" strings) 364 atf_check -s exit:0 -e empty -o inline:'abcdef' ${TEST_SH} -c \ 365"printf '%s' \$'abc\\ 366def'" 367 # but a normal newline in a $'...' is just a newline 368 atf_check -s exit:0 -e empty -o inline:'abc\ndef' ${TEST_SH} -c \ 369"printf '%s' \$'abc 370def'" 371 # and should work when elided line wrap occurs between $ and ' 372 atf_check -s exit:0 -e empty -o inline:'abc\ndef' ${TEST_SH} -c \ 373"printf '%s' \$\\ 374'abc\\ndef'" 375 376 # $'...' only works when the $ is unquoted. 377 atf_check -s exit:0 -e empty -o inline:"abc\$'def'g" ${TEST_SH} -c \ 378 "printf '%s' \"abc\$'def'g\"" 379 atf_check -s exit:0 -e empty -o inline:'abc$defg' ${TEST_SH} -c \ 380 "printf '%s' abc\\\$'def'g" 381 atf_check -s exit:0 -e empty -o inline:'abc$def' ${TEST_SH} -c \ 382 "printf '%s' abc'\$'def" 383} 384 385atf_test_case f_redirects 386f_redirects_head() { 387 atf_set "descr" "Check parsing of redirect operators" 388} 389f_redirects_body() { 390 391 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 392 '>/dev/null' 393 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 394 '</dev/null' 395 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 396 '>>/dev/null' 397 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 398 '<>/dev/null' 399 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 400 '</dev/null>/dev/null' 401 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 402 '>|/dev/null' 403 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 404 '>/dev/null>/dev/null>/dev/null' 405 406 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 407 'echo hello >/dev/null' 408 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 409 'echo >/dev/null hello' 410 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 411 '>/dev/null echo hello' 412 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 413 'echo hello >/dev/null world' 414 atf_check -s exit:0 -o 'inline:hello world\n' -e empty ${TEST_SH} -c \ 415 'echo hello </dev/null world' 416 417 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 418 'echo hello </dev/null' 419 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 420 'echo hello 3</dev/null' 421 atf_check -s exit:0 -o 'inline:hello 3\n' -e empty ${TEST_SH} -c \ 422 'echo hello 3 </dev/null' 423 atf_check -s exit:0 -o 'inline:hello 3\n' -e empty ${TEST_SH} -c \ 424 'echo hello \3</dev/null' 425 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 426 'echo hello</dev/null' 427 atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \ 428 'hello=3; echo ${hello}</dev/null' 429 430 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 431 '2>&1' 432 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 433 '2>& 1' 434 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 435 'FD=1; 2>&"${FD}"' 436 atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \ 437 'FD=1; echo hello 2>&"${FD}" >&2' 438 439 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 440 '2>&- 3<&- 4>&-' 441 442 return 0 443} 444 445atf_test_case g_variable_syntax 446g_variable_syntax_head() { 447 atf_set "descr" "Check that var names of all legal forms work" 448} 449g_variable_syntax_body() { 450 # don't test _ as a variable, it can be "unusual" 451 for vname in a ab _a _9 a123 a_1_2_3 __ ___ ____ __1__ _0 \ 452 A AA AAA AaBb _A_a A_a_ a1_ abc_123 ab_12_cd_ef_34_99 \ 453 abcdefghijklmnopqrstuvwzyz ABCDEFGHIJKLMNOPQRSTUVWXYZ_ \ 454 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 \ 455 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 \ 456 xyzzy __0123454321__ _0_1_2_3_4_5_6_7_8_9_ ABBA X_ Y__ Z___ \ 457 _____________________________________________________________ 458 do 459 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 460 "unset ${vname}" 461 atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -c \ 462 "unset ${vname}; printf %s \${${vname}-OK}" 463 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 464 "${vname}=GOOD; printf %s \${${vname}-OK}" 465 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 466 "${vname}=GOOD; printf %s \$${vname}" 467 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 468 "unset ${vname};${vname}=GOOD;printf %s \${${vname}-OK}" 469 atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -c \ 470 "${vname}=GOOD;unset ${vname};printf %s \${${vname}-OK}" 471 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 472 "${vname}=GOOD; unset ${vname}x; printf %s \$${vname}" 473 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 474 "unset ${vname}x; ${vname}=GOOD; printf %s \$${vname}x" 475 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 476 "${vname}=GOOD; ${vname}_=BAD; printf %s \$${vname}" 477 478 case "${vname}" in 479 ?) continue;; 480 esac 481 482 # The following tests do not work for 1 char var names. 483 # hence the check and "continue" above to skip the remaining 484 # tests for that case 485 486 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 487 "${vname}=GOOD; unset ${vname%?}; printf %s \$${vname}" 488 489 # (this next would work, but becomes just a duplicate of 490 # an earlier test, so is pointless for 1 ch names) 491 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 492 "${vname}=GOOD; unset ${vname}x ${vname%?}; printf %s \$${vname}" 493 494 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 495 "unset ${vname%?};${vname}=GOOD; printf %s \$${vname%?}" 496 497 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 498 "${vname}=GOOD; ${vname%?}=BAD; printf %s \$${vname}" 499 500 # all the remaining tests require the 2nd char of the 501 # variable name to be a legal first character. That 502 # is, not a digit, so skip the rest if we have a digit 503 # second... 504 case "${vname}" in 505 ?[0-9]*) continue;; 506 esac 507 508 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 509 "${vname}=GOOD; unset ${vname#?}; printf %s \$${vname}" 510 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 511 "unset ${vname#?};${vname}=GOOD; printf %s \$${vname#?}" 512 513 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 514 "${vname}=GOOD; ${vname#?}=BAD; printf %s \$${vname}" 515 516 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 517 "unset ${vname%?} ${vname#?} ${vname}x; ${vname}=GOOD; 518 printf %s \$${vname%?}\$${vname#?}\$${vname}x" 519 520 atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \ 521 "${vname}=GOOD; ${vname%?}=BAD; ${vname}_=BAD; 522 ${vname#?}=BAD; printf %s \$${vname}" 523 done 524 525 # don't test '.' in var names, some shells permit that (in ${} anyway) 526 # this test also cannot check for embedded - + ? = : % or # 527 for vname in ,x -p +h :def 0_1 'x*x' '()' '"' "'" 'a b c' '?!' ';' 528 do 529 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 530 "echo \${${vname}}" 531 done 532 533 for vname in ,x -p +h :def 0_1 'x*x' '()' '"' "'" 'a b c' x,y,z '?!' \ 534 ';' a-b a+b 'a?b' 'a:b' 'a%b' 'a#b' 0 1 99 @ '*' '!' '?' 535 do 536 # failure modes will differ, but they should all fail somehow 537 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 538 "${vname}=" 539 done 540 541} 542 543atf_test_case h_var_assign 544h_var_assign_head() { 545 atf_set "descr" "Check var assignments " 546} 547h_var_assign_body() { 548 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 549 'a=b' 550 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 551 '\a=b' 552 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 553 'a=b c=d' 554 atf_check -s exit:0 -e empty -o 'inline:e=f\n' ${TEST_SH} -c \ 555 'a=b c=d echo e=f' 556 atf_check -s exit:0 -e empty -o 'inline:e=f\n' ${TEST_SH} -c \ 557 'a=b 2>/dev/null c=d </dev/null echo e=f' 558 559 # We need to make sure that we do not accidentally 560 # find a command called 'a=b' ... 561 562 for d in /foo /foo/bar /not-dir /no/such/directory '/!!!' \ 563 '/-/--/#' '/"/""/"""' - 564 do 565 test -d "${d}" || break 566 done 567 test "${#d}" -gt 1 || atf-skip 'Wacky directories seem to exist!' 568 569 atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \ 570 "PATH='${d}';"'a=\b' 571 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 572 "PATH='${d}';"'a\=b' 573 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 574 "PATH='${d}';"'\a=b' 575 atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \ 576 "PATH='${d}';"'X=; c=d ${X} a=b' 577} 578 579atf_test_case i_pipelines 580i_pipelines_head() { 581 atf_set "descr" "Check pipelines" 582} 583i_pipelines_body() { 584 585 cmd='printf "%s\n" foo' 586 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 587 do 588 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 589 "${cmd}" 590 cmd="${cmd} | cat" 591 done 592 593 cmd='printf "%s\n" foo' 594 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 595 do 596 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 597 "${cmd}" 598 cmd="${cmd} | 599 cat" 600 done 601 602 cmd='printf "%s\n" foo' 603 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 604 do 605 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 606 "${cmd}" 607 cmd="${cmd} | 608 609 610 611 612 cat" 613 done 614 615 cmd='! printf "%s\n" foo' 616 for n in 1 2 3 4 5 6 7 8 9 10 617 do 618 atf_check -s exit:1 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 619 "${cmd}" 620 cmd="${cmd} | cat" 621 done 622 623 cmd='exec 4>&2 3<&0; printf "%s\n" foo' 624 for n in 1 2 3 625 do 626 pfx= 627 for xtra in 'x=y' 'a=b' '6>&1' '5<&3' 628 do 629 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 630 "${cmd} | ${xtra} cat" 631 632 atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \ 633 "${cmd} | ${pfx} cat" 634 635 pfx="${pfx} ${xtra}" 636 done 637 cmd="${cmd} | ${pfx} cat" 638 done 639 640 # pipelines are not required to contain commands ... 641 # they don't do anything useful (at all) but the syntax is legal 642 base='4>&2'; cmd="${base}" 643 for pipe in 'a=b' '3<&0' '>>/dev/null' 'a= b= c=' '${x}' 'cat' 644 do 645 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 646 "${base} | ${pipe}" 647 648 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 649 "${cmd} | ${pipe}" 650 651 cmd="${cmd} | ${pipe}" 652 done 653 654 # but the command cannot be empty, or a reserved word used improperly 655 base='printf "%s\n" foo'; cmd="${base}" 656 for pipe in '' do done then else fi esac 657 do 658 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 659 "${base} | ${pipe}" 660 661 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 662 "${pipe} | ${base}" 663 664 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 665 "${cmd} | ${pipe}" 666 667 cmd="${cmd} | ${pipe}" 668 done 669} 670 671atf_test_case j_and_or_lists 672j_and_or_lists_head() { 673 atf_set "descr" "Check && and || command lists" 674} 675j_and_or_lists_body() { 676 and=true 677 or=false 678 and_or=false 679 for i in 1 2 3 4 5 6 7 8 9 10 680 do 681 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 682 "${and}" 683 684 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 685 "${or}" 686 687 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 688 "${and_or}" 689 690 and="${and} && true" 691 or="${or} || false" 692 and_or="${and_or} || true && false" 693 done 694 695 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 696 'true &&' 697 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 698 '&& true' 699 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 700 '|| true' 701 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 702 'true ||' 703 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 704 'true || && false' 705 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 706 'false || && true' 707 708 cmd='printf "%s" foo | cat | cat>/dev/null' 709 line="${cmd}" 710 for i in 1 2 3 4 711 do 712 line="${line} && ! ${cmd} || ${cmd}" 713 714 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 715 "${line}" 716 done 717 718} 719 720atf_test_case k_lists 721k_lists_head() { 722 atf_set "descr" "Check ; command lists" 723} 724k_lists_body() { 725 line= 726 for N in 1 2 3 4 727 do 728 for cmd in \ 729 true false : 'cat</dev/null>/dev/null' x=3 'exec 4>&-' 730 do 731 line="${line}${line:+;}${cmd}" 732 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 733 -e empty ${TEST_SH} -c \ 734 "echo hello; ${line}; echo world" 735 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 736 -e empty ${TEST_SH} -c \ 737 "echo hello; ${line}; echo world;" 738 done 739 done 740 741 for cmd in ';' ';;' 'false ;; true' 'false; ;true' '; true' 742 do 743 atf_check -s not-exit:0 -o ignore -e not-empty \ 744 ${TEST_SH} -c "${cmd}" 745 done 746} 747 748atf_test_case l_async_lists 749l_async_lists_head() { 750 atf_set "descr" "Check & command lists" 751} 752l_async_lists_body() { 753 line= 754 for N in 1 2 3 4 755 do 756 for cmd in \ 757 true false : 'cat</dev/null>/dev/null' x=3 'exec 4>&-' 758 do 759 line="${line:+${line}&}${cmd}" 760 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 761 -e empty ${TEST_SH} -c \ 762 "echo hello; ${line}& echo world" 763 atf_check -s exit:0 -o 'inline:hello\nworld\n' \ 764 -e empty ${TEST_SH} -c \ 765 "echo hello; ${line}& echo world" 766 done 767 done 768 769 for cmd in '&' ';&' '&;' '& true' 'false& &true' 770 do 771 atf_check -s not-exit:0 -o ignore -e not-empty \ 772 ${TEST_SH} -c "${cmd}" 773 done 774} 775 776atf_test_case m_compound_lists 777m_compound_lists_head() { 778 atf_set "descr" "Check subshells () and { ;} command grouping" 779} 780m_compound_lists_body() { 781 # Note: (( is an unspecified (reserved) operator, don't use it... 782 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 783 '( true )' 784 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 785 '( false )' 786 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 787 '( (:) )' 788 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 789 '( ( true ))' 790 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 791 '( ( ( ( ( true )))))' 792 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 793 '( ( ( ( (true);:));true))' 794 795 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 796 '()' 797 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 798 '( )' 799 800 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 801 '{ true; }' 802 atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \ 803 '{ false; }' 804 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 805 '{ { :; };}' 806 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 807 '{ { { { { :;};};};};}' 808 809 atf_check -s exit:0 -o 'inline:}\n' -e empty ${TEST_SH} -c \ 810 '{ echo } ; }' 811 atf_check -s exit:0 -o 'inline:{\n' -e empty ${TEST_SH} -c \ 812 '{ echo { ; }' 813} 814 815atf_test_case q_for_loop 816q_for_loop_head() { 817 atf_set "descr" "Check for loop parsing" 818} 819q_for_loop_body() { 820 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 821 'for x; do : ; done' 822 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 823 'for x in ; do : ; done' 824 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 825 'for x in a b c ; do : ; done' 826 827 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 828 'for x in in;do : ; done' 829 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 830 'for x in for;do : ; done' 831 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 832 'for x in do;do : ; done' 833 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 834 'for for in in;do :;done' 835 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 836 'for for in for;do :; done' 837 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 838 'for for in do;do : ;done' 839 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 840 'for in in in;do : ; done' 841 atf_check -s exit:0 -o 'inline:do\nin\ndo\n' -e empty ${TEST_SH} -c \ 842 'for in in in do in;do case $in in in)echo do;;do)echo in;;esac; done' 843 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 844 'for in in for;do : ; done' 845 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 846 'for in in do;do : ; done' 847 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 848 'for do in in;do : ; done' 849 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 850 'for do in for;do : ; done' 851 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 852 'for do in do;do : ; done' 853 atf_check -s exit:0 -o 'inline:dodo\n' -e empty ${TEST_SH} -c \ 854 'for do in do;do echo ${do}do ; done' 855} 856 857atf_test_case r_case 858r_case_head() { 859 atf_set "descr" "Check case statement parsing" 860} 861r_case_body() { 862 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 863 'case x in esac' 864 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 865 'case x in x) esac' 866 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 867 'case x in (x) esac' 868 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 869 'case x in x) ;; esac' 870 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 871 'case x in (x) ;; esac' 872 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 873 'case x in x|y) ;; esac' 874 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 875 'case x in (x|y) ;; esac' 876 877 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 878 'case x in x|esac) ;; esac' 879 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 880 'case x in x|esac|y) ;; esac' 881 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 882 'case x in (x|esac) ;; esac' 883 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 884 'case x in (x|esac|y) ;; esac' 885 886 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 887 'case x in in) esac' 888 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 889 'case x in in) ;; esac' 890 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 891 'case x in x|in) ;; esac' 892 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 893 'case x in x|in|y) ;; esac' 894 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 895 'case x in (x|in) ;; esac' 896 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 897 'case x in (in|x) ;; esac' 898 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 899 'case x in (x|in|y) ;; esac' 900 901 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 902 'case case in case) esac' 903 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 904 'case in in in) esac' 905 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 906 'case esac in (in) esac' 907 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 908 'case in in esac|cat' 909 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 910 'case esac in esac|cat' 911 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 912 'case in in esac|case x in u) echo foo;; esac' 913 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 914 'case esac in esac|case x in u) echo foo;; esac' 915 atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \ 916 'case in in esac|case x in x) echo foo;; esac' 917 918 atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ 919 'case in in (esac|cat' 920 921 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 922 'case x in x );;esac' 923 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 924 'case x in ( x );;esac' 925 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 926 'case x in x | y );;esac' 927 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 928 'case x in ( x | y );;esac' 929 930 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 931 'case x 932 in 933 ( x | y ) 934 935 ;; 936 937 938 esac 939 ' 940} 941 942atf_test_case s_if 943s_if_head() { 944 atf_set "descr" "Check if statement parsing" 945} 946s_if_body() { 947 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 948 'if :; then :; fi' 949 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 950 'if :; then :; else :; fi' 951 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 952 'if :; then :; elif :; then :; else :; fi' 953 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 954 'if :; then :; elif :; then :; elif :; then :; else :; fi' 955 956 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 957 'if :; then : else :; fi' 958 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 959 'if : then :; then :; fi' 960 961 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 962 'if if :;then :;fi then :;fi' 963 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 964 'if if :;then if :;then :;fi fi;then :;fi' 965 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 966 'if if :;then :;fi;then :;else if :;then :;fi fi' 967 968 for a in true false; do 969 for b in true false; do 970 for c in true false; do 971 972 $a && out=a || { 973 $b && out=b || { 974 $c && out=c || { 975 out=d; };};} 976 977 atf_check -s exit:0 -e empty \ 978 -o "inline:${out}"'\n' \ 979 ${TEST_SH} -c \ 980 "if $a; then echo a 981 elif $b; then echo b 982 elif $c; then echo c 983 else echo d 984 fi" 985 done 986 done 987 done 988} 989 990atf_test_case t_loops 991t_loops_head() { 992 atf_set "descr" "Check while/until loop parsing" 993} 994t_loops_body() { 995 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 996 'while false; do :; done' 997 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 998 'while false; do \done; done' 999 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1000 'until :; do :; done' 1001 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1002 'until :; do \done; done' 1003 1004 atf_check -s exit:0 -o 'inline:x\n1\n' -e empty ${TEST_SH} -c \ 1005 ':; while (exit) do echo x; false; done; echo $?' 1006 atf_check -s exit:0 -o 'inline:x\n0\n' -e empty ${TEST_SH} -c \ 1007 'false; until (exit) do echo x; done; echo $?' 1008} 1009 1010atf_test_case u_case_cont 1011u_case_cont_head() { 1012 atf_set "descr" "Check case stmt parsing using ;& [optional]" 1013} 1014u_case_cont_body() { 1015 1016 ${TEST_SH} -c 'case x in (x) false ;& (y) : ;; esac' 2>/dev/null || 1017 atf_skip ";& case list terminator unsupported in ${TEST_SH}" 1018 1019 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1020 'case x in x) ;& esac' 1021 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1022 'case x in (x) ;& esac' 1023 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1024 'case x in x|y) ;& esac' 1025 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1026 'case x in (x|y) ;& esac' 1027 1028 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1029 'case x in x );&esac' 1030 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1031 'case x in ( x );&esac' 1032 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1033 'case x in x | y );&esac' 1034 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1035 'case x in ( x | y );&esac' 1036 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) ;& esac' 1041 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1042 'case x in x|y) ;& esac' 1043 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1044 'case x in (x|y) ;& esac' 1045} 1046 1047atf_test_case x_functions 1048x_functions_head() { 1049 atf_set "descr" "Check function definition parsing" 1050} 1051x_functions_body() { 1052 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1053 'func() { :; }' 1054 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1055 'func() { :; }; func' 1056 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1057 'func()(:)' 1058 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1059 'func()if :; then false; else true; fi' 1060 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1061 'func()while false; do :;done' 1062 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1063 'func () for a in b c; do :; done' 1064 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1065 'func() case x in (y) esac' 1066 1067 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1068 'f1() { f2() { :; }; }; f1; f2' 1069 1070 # f2 should be not found, but f1 clears $? 1071 atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} -c \ 1072 'f1() { f2() { :; }; }; f2; f1' 1073 1074 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1075 'f1() { eval "$1() { :; }"; }; f1 f2; f2' 1076} 1077 1078atf_test_case z_PR_48498 1079z_PR_48498_head() { 1080 atf_set "descr" "Check for detecting the syntax error from PR bin/48498" 1081} 1082z_PR_48498_body() { 1083 1084 # reserved words/operators that end things, 1085 # were completely ignored after a ';' or '&' 1086 # many of these tests lifted directly from the PR 1087 1088 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1089 'true; fi' 1090 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1091 'false; fi' 1092 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1093 'false; then echo wut' 1094 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1095 'true; then echo wut' 1096 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1097 'true; do echo wut' 1098 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1099 'true; then' 1100 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1101 'true; else' 1102 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1103 'true; do' 1104 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1105 'true; done' 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 ':;)' 1112 1113 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1114 'true& fi' 1115 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1116 'false& fi' 1117 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1118 'false& then echo wut' 1119 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1120 'true& then echo wut' 1121 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1122 'true& do echo wut' 1123 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1124 'true& then' 1125 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1126 'true& else' 1127 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1128 'true& do' 1129 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1130 'true&done' 1131 # { 1132 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1133 ':&}' 1134 # ( 1135 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1136 ':&)' 1137} 1138 1139atf_test_case z_PR_52426 1140z_PR_52426_head() { 1141 atf_set "descr" "Check for detecting the syntax error from PR bin/52426" 1142} 1143z_PR_52426_body() { 1144 # Absoluely anything was permitted as a pattern of a case 1145 # statement, any token (except 'esac') would serve 1146 # What follows are a few "pretty" examples that were accepted. 1147 # The first is the example from the PR 1148 1149 # Note we use only ;; type case lists, ;& should do the same, but 1150 # only for shells that support it, we do not want the shell to 1151 # object to any of these just because it does not support ;& 1152 1153 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1154 'case x in <|() ;; esac' 1155 1156 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1157 'case x in ((|)) ;; esac' 1158 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1159 'case x in _|() ;; esac' 1160 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1161 'case x in ()|() ;; esac' 1162 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1163 'case x in -|;) ;; esac' 1164 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1165 'case x in (;|-) ;; esac' 1166 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1167 'case x in ;;|;) ;; esac' 1168 atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \ 1169 'case x in (|| | ||) ;; esac' 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 <> | 1182 ) ;; esac' 1183 1184 # now check some similar looking cases that are supposed to work 1185 # That is, make sure the fix for the PR does not break valid cases. 1186 1187 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1188 'case fi in ({|}) ;; (!) ;; esac' 1189 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1190 'case esac in ([|]);; (][);; !!!|!!!|!!!|!!!);; esac' 1191 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1192 'case then in ({[]]}) ;; (^^);; (^|^);; ([!]);; (-);; esac' 1193 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1194 'case while in while );;(if|then|elif|fi);;(do|done);; esac' 1195 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1196 'case until in($);;($$);;($4.50);;(1/2);;0.3333);;esac' 1197 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1198 'case return in !);; !$);; $!);; !#);; (@);; esac' 1199 atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \ 1200 'case break in (/);; (\/);; (/\|/\));; (\\//);; esac' 1201} 1202 1203atf_init_test_cases() { 1204 atf_add_test_case a_basic_tokenisation 1205 atf_add_test_case b_comments 1206 atf_add_test_case c_line_wrapping 1207 atf_add_test_case d_cstrings 1208 atf_add_test_case f_redirects 1209 atf_add_test_case g_variable_syntax 1210 atf_add_test_case h_var_assign 1211 atf_add_test_case i_pipelines 1212 atf_add_test_case j_and_or_lists 1213 atf_add_test_case k_lists 1214 atf_add_test_case l_async_lists 1215 atf_add_test_case m_compound_lists 1216 atf_add_test_case q_for_loop 1217 atf_add_test_case r_case 1218 atf_add_test_case s_if 1219 atf_add_test_case t_loops 1220 atf_add_test_case u_case_cont 1221 atf_add_test_case x_functions 1222 1223 atf_add_test_case z_PR_48498 1224 atf_add_test_case z_PR_52426 1225} 1226