1 1.10 kre # $NetBSD: t_fsplit.sh,v 1.10 2024/10/19 11:59:51 kre Exp $ 2 1.1 jruoho # 3 1.2 christos # Copyright (c) 2007-2016 The NetBSD Foundation, Inc. 4 1.1 jruoho # All rights reserved. 5 1.1 jruoho # 6 1.1 jruoho # Redistribution and use in source and binary forms, with or without 7 1.1 jruoho # modification, are permitted provided that the following conditions 8 1.1 jruoho # are met: 9 1.1 jruoho # 1. Redistributions of source code must retain the above copyright 10 1.1 jruoho # notice, this list of conditions and the following disclaimer. 11 1.1 jruoho # 2. Redistributions in binary form must reproduce the above copyright 12 1.1 jruoho # notice, this list of conditions and the following disclaimer in the 13 1.1 jruoho # documentation and/or other materials provided with the distribution. 14 1.1 jruoho # 15 1.1 jruoho # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 1.1 jruoho # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 1.1 jruoho # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 1.1 jruoho # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 1.1 jruoho # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 1.1 jruoho # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 1.1 jruoho # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 1.1 jruoho # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 1.1 jruoho # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 1.1 jruoho # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 1.1 jruoho # POSSIBILITY OF SUCH DAMAGE. 26 1.1 jruoho # 27 1.1 jruoho 28 1.1 jruoho # The standard 29 1.1 jruoho # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html 30 1.1 jruoho # explains (section 2.6) that Field splitting should be performed on the 31 1.1 jruoho # result of variable expansions. 32 1.1 jruoho # In particular this means that in ${x-word}, 'word' must be expanded as if 33 1.1 jruoho # the "${x-" and "}" were absent from the input line. 34 1.1 jruoho # 35 1.1 jruoho # So: sh -c 'set ${x-a b c}; echo $#' should give 3. 36 1.6 kre # and: sh -c 'set -- ${x-}' echo $#' should give 0 37 1.1 jruoho # 38 1.1 jruoho 39 1.3 christos # the implementation of "sh" to test 40 1.3 christos : ${TEST_SH:="/bin/sh"} 41 1.3 christos 42 1.1 jruoho nl=' 43 1.1 jruoho ' 44 1.1 jruoho 45 1.1 jruoho check() 46 1.1 jruoho { 47 1.9 kre if [ "${TEST}" -eq 0 ] 48 1.9 kre then 49 1.9 kre FAILURES= 50 1.9 kre fi 51 1.9 kre 52 1.2 christos TEST=$((${TEST} + 1)) 53 1.2 christos 54 1.2 christos case "$#" in 55 1.2 christos (2) ;; 56 1.9 kre (*) atf_fail "Internal test error, $# args to check, test ${TEST}";; 57 1.2 christos esac 58 1.2 christos 59 1.8 kre result=$( ${TEST_SH} -c "unset x a b d c e f g h; $1" ) 60 1.2 christos STATUS="$?" 61 1.2 christos 62 1.1 jruoho # Remove newlines 63 1.1 jruoho oifs="$IFS" 64 1.1 jruoho IFS="$nl" 65 1.1 jruoho result="$(echo $result)" 66 1.1 jruoho IFS="$oifs" 67 1.2 christos 68 1.9 kre # # trim the test text in case we use it in a message below 69 1.9 kre # case "$1" in 70 1.9 kre # ????????????????*) 71 1.9 kre # set -- "$(expr "$1" : '\(............\).*')..." "$2" ;; 72 1.9 kre # esac 73 1.2 christos 74 1.9 kre if [ "$2" != "${result}" ] 75 1.1 jruoho then 76 1.9 kre FAILURES="${FAILURES}${FAILURES:+ }${TEST}" 77 1.9 kre printf >&2 'Sub-test %d failed:\n %s\n' \ 78 1.9 kre "${TEST}" "$1" 79 1.9 kre printf >&2 ' Expected: [%s]\n' "$2" 80 1.9 kre printf >&2 ' Received: [%s]\n' "${result}" 81 1.9 kre 82 1.9 kre if [ "${STATUS}" != 0 ] 83 1.2 christos then 84 1.9 kre printf >&2 ' Sub-test exit status: %d\n' "${STATUS}" 85 1.2 christos fi 86 1.2 christos elif [ "${STATUS}" != 0 ] 87 1.2 christos then 88 1.9 kre FAILURES="${FAILURES}${FAILURES:+ }${TEST}" 89 1.9 kre printf >&2 'Sub-test %d failed:\n\t%s\n' \ 90 1.9 kre "${TEST}" "$1" 91 1.9 kre printf >&2 ' Sub-test exit status: %d (with correct output)\n' \ 92 1.9 kre "${STATUS}" 93 1.9 kre fi 94 1.9 kre 95 1.9 kre return 0 96 1.9 kre } 97 1.9 kre 98 1.9 kre check_results() 99 1.9 kre { 100 1.9 kre NAME=$1 101 1.9 kre 102 1.9 kre set -- ${FAILURES} 103 1.9 kre 104 1.9 kre if [ $# -eq 0 ] 105 1.9 kre then 106 1.9 kre return 0 107 1.1 jruoho fi 108 1.6 kre 109 1.9 kre unset IFS 110 1.9 kre printf >&2 'Subtest %s: %d sub-tests (of %d) [%s] failed.\n' \ 111 1.9 kre "${NAME}" "$#" "${TEST}" "$*" 112 1.9 kre 113 1.9 kre atf_fail "$# of ${TEST} sub-tests (${FAILURES}), see stderr" 114 1.6 kre return 0 115 1.1 jruoho } 116 1.1 jruoho 117 1.1 jruoho atf_test_case for 118 1.9 kre for_head() 119 1.9 kre { 120 1.1 jruoho atf_set "descr" "Checks field splitting in for loops" 121 1.1 jruoho } 122 1.9 kre for_body() 123 1.9 kre { 124 1.1 jruoho unset x 125 1.1 jruoho 126 1.2 christos TEST=0 127 1.1 jruoho # Since I managed to break this, leave the test in 128 1.1 jruoho check 'for f in $x; do echo x${f}y; done' '' 129 1.9 kre 130 1.9 kre check_results for 131 1.1 jruoho } 132 1.1 jruoho 133 1.1 jruoho atf_test_case default_val 134 1.9 kre default_val_head() 135 1.9 kre { 136 1.1 jruoho atf_set "descr" "Checks field splitting in variable default values" 137 1.1 jruoho } 138 1.9 kre default_val_body() 139 1.9 kre { 140 1.2 christos TEST=0 141 1.1 jruoho # Check that IFS is applied to text from ${x-...} unless it is inside 142 1.1 jruoho # any set of "..." 143 1.2 christos check 'set -- ${x-a b c}; echo $#' 3 144 1.2 christos 145 1.2 christos check 'set -- ${x-"a b" c}; echo $#' 2 146 1.2 christos check 'set -- ${x-a "b c"}; echo $#' 2 147 1.2 christos check 'set -- ${x-"a b c"}; echo $#' 1 148 1.2 christos 149 1.2 christos check "set -- \${x-'a b' c}; echo \$#" 2 150 1.2 christos check "set -- \${x-a 'b c'}; echo \$#" 2 151 1.2 christos check "set -- \${x-'a b c'}; echo \$#" 1 152 1.2 christos 153 1.2 christos check 'set -- ${x-a\ b c}; echo $#' 2 154 1.2 christos check 'set -- ${x-a b\ c}; echo $#' 2 155 1.2 christos check 'set -- ${x-a\ b\ c}; echo $#' 1 156 1.2 christos 157 1.2 christos check 'set -- ${x}; echo $#' 0 158 1.2 christos check 'set -- ${x-}; echo $#' 0 159 1.2 christos check 'set -- ${x-""}; echo $#' 1 160 1.2 christos check 'set -- ""${x}; echo $#' 1 161 1.2 christos check 'set -- ""${x-}; echo $#' 1 162 1.2 christos check 'set -- ""${x-""}; echo $#' 1 163 1.2 christos check 'set -- ${x}""; echo $#' 1 164 1.2 christos check 'set -- ${x-}""; echo $#' 1 165 1.2 christos check 'set -- ${x-""}""; echo $#' 1 166 1.2 christos check 'set -- ""${x}""; echo $#' 1 167 1.2 christos check 'set -- ""${x-}""; echo $#' 1 168 1.2 christos check 'set -- ""${x-""}""; echo $#' 1 169 1.2 christos 170 1.2 christos check 'for i in ${x-a b c}; do echo "z${i}z"; done' \ 171 1.2 christos 'zaz zbz zcz' 172 1.2 christos check 'for i in ${x-"a b" c}; do echo "z${i}z"; done' \ 173 1.2 christos 'za bz zcz' 174 1.2 christos check 'for i in ${x-"a ${x-b c}" d}; do echo "z${i}z"; done' \ 175 1.2 christos 'za b cz zdz' 176 1.2 christos check 'for i in ${x-a ${x-b c} d}; do echo "z${i}z"; done' \ 177 1.2 christos 'zaz zbz zcz zdz' 178 1.2 christos 179 1.5 kre # I am not sure the first of these two is correct, the rules on 180 1.5 kre # quoting word in ${var-word} are peculiar, and hard to fathom... 181 1.5 kre # It is what the NetBSD shell does, and bash, not the freebsd shell 182 1.5 kre # and not ksh93 (as of Mar 1, 2016, and still in June 2017) 183 1.5 kre # The likely correct interp of the next one is 'za bz zcz zdz' 184 1.2 christos 185 1.7 kre # That and the "should be" below are correct as of POSIX 7 TC2 186 1.7 kre # But this is going to change to "unspecified" in POSIX 8 187 1.7 kre # (resolution of bug 221) so instead of being incorrect (as now) 188 1.7 kre # the NetBSD shell will simply be implementing is version 189 1.7 kre # of unspecified behaviour. Just beware that shells differ, 190 1.7 kre # a shell that fails this test is not incorrect because of it. 191 1.7 kre 192 1.5 kre # should be: uuuu qqqqqq uuu q uuu (unquoted/quoted) no nesting. 193 1.2 christos check 'for i in ${x-"a ${x-"b c"}" d}; do echo "z${i}z"; done' \ 194 1.2 christos 'za b cz zdz' 195 1.2 christos check 'for i in ${x-a ${x-"b c"} d}; do echo "z${i}z"; done' \ 196 1.2 christos 'zaz zb cz zdz' 197 1.9 kre 198 1.9 kre check_results default_val 199 1.2 christos } 200 1.2 christos 201 1.2 christos atf_test_case replacement_val 202 1.9 kre replacement_val_head() 203 1.9 kre { 204 1.2 christos atf_set "descr" "Checks field splitting in variable replacement values" 205 1.2 christos } 206 1.9 kre replacement_val_body() 207 1.9 kre { 208 1.2 christos TEST=0 209 1.2 christos 210 1.2 christos # Check that IFS is applied to text from ${x+...} unless it is inside 211 1.2 christos # any set of "...", or whole expansion is quoted, or both... 212 1.2 christos 213 1.2 christos check 'x=BOGUS; set -- ${x+a b c}; echo $#' 3 214 1.2 christos 215 1.2 christos check 'x=BOGUS; set -- ${x+"a b" c}; echo $#' 2 216 1.2 christos check 'x=BOGUS; set -- ${x+a "b c"}; echo $#' 2 217 1.2 christos check 'x=BOGUS; set -- ${x+"a b c"}; echo $#' 1 218 1.2 christos 219 1.2 christos check "x=BOGUS; set -- \${x+'a b' c}; echo \$#" 2 220 1.2 christos check "x=BOGUS; set -- \${x+a 'b c'}; echo \$#" 2 221 1.2 christos check "x=BOGUS; set -- \${x+'a b c'}; echo \$#" 1 222 1.2 christos 223 1.2 christos check 'x=BOGUS; set -- ${x+a\ b c}; echo $#' 2 224 1.2 christos check 'x=BOGUS; set -- ${x+a b\ c}; echo $#' 2 225 1.2 christos check 'x=BOGUS; set -- ${x+a\ b\ c}; echo $#' 1 226 1.2 christos 227 1.2 christos check 'x=BOGUS; set -- ${x+}; echo $#' 0 228 1.2 christos check 'x=BOGUS; set -- ${x+""}; echo $#' 1 229 1.2 christos check 'x=BOGUS; set -- ""${x+}; echo $#' 1 230 1.2 christos check 'x=BOGUS; set -- ""${x+""}; echo $#' 1 231 1.2 christos check 'x=BOGUS; set -- ${x+}""; echo $#' 1 232 1.2 christos check 'x=BOGUS; set -- ${x+""}""; echo $#' 1 233 1.2 christos check 'x=BOGUS; set -- ""${x+}""; echo $#' 1 234 1.2 christos check 'x=BOGUS; set -- ""${x+""}""; echo $#' 1 235 1.2 christos 236 1.2 christos # verify that the value of $x does not affecty the value of ${x+...} 237 1.2 christos check 'x=BOGUS; set -- ${x+}; echo X$1' X 238 1.2 christos check 'x=BOGUS; set -- ${x+""}; echo X$1' X 239 1.2 christos check 'x=BOGUS; set -- ""${x+}; echo X$1' X 240 1.2 christos check 'x=BOGUS; set -- ""${x+""}; echo X$1' X 241 1.2 christos check 'x=BOGUS; set -- ${x+}""; echo X$1' X 242 1.2 christos check 'x=BOGUS; set -- ${x+""}""; echo X$1' X 243 1.2 christos check 'x=BOGUS; set -- ""${x+}""; echo X$1' X 244 1.2 christos check 'x=BOGUS; set -- ""${x+""}""; echo X$1' X 245 1.2 christos 246 1.2 christos check 'x=BOGUS; set -- ${x+}; echo X${1-:}X' X:X 247 1.2 christos check 'x=BOGUS; set -- ${x+""}; echo X${1-:}X' XX 248 1.2 christos check 'x=BOGUS; set -- ""${x+}; echo X${1-:}X' XX 249 1.2 christos check 'x=BOGUS; set -- ""${x+""}; echo X${1-:}X' XX 250 1.2 christos check 'x=BOGUS; set -- ${x+}""; echo X${1-:}X' XX 251 1.2 christos check 'x=BOGUS; set -- ${x+""}""; echo X${1-:}X' XX 252 1.2 christos check 'x=BOGUS; set -- ""${x+}""; echo X${1-:}X' XX 253 1.2 christos check 'x=BOGUS; set -- ""${x+""}""; echo X${1-:}X' XX 254 1.2 christos 255 1.2 christos # and validate that the replacement can be used as expected 256 1.2 christos check 'x=BOGUS; for i in ${x+a b c}; do echo "z${i}z"; done'\ 257 1.2 christos 'zaz zbz zcz' 258 1.2 christos check 'x=BOGUS; for i in ${x+"a b" c}; do echo "z${i}z"; done'\ 259 1.2 christos 'za bz zcz' 260 1.2 christos check 'x=BOGUS; for i in ${x+"a ${x+b c}" d}; do echo "z${i}z"; done'\ 261 1.2 christos 'za b cz zdz' 262 1.6 kre 263 1.7 kre # see the (extended) comment in the default_val test. This will be 264 1.7 kre # unspecified, hence we are OK (will be) but expect differences. 265 1.6 kre # also incorrect: uuuu qqqqqq uuu q uuu 266 1.2 christos check 'x=BOGUS; for i in ${x+"a ${x+"b c"}" d}; do echo "z${i}z"; done'\ 267 1.2 christos 'za b cz zdz' 268 1.6 kre 269 1.2 christos check 'x=BOGUS; for i in ${x+a ${x+"b c"} d}; do echo "z${i}z"; done'\ 270 1.2 christos 'zaz zb cz zdz' 271 1.2 christos check 'x=BOGUS; for i in ${x+a ${x+b c} d}; do echo "z${i}z"; done'\ 272 1.2 christos 'zaz zbz zcz zdz' 273 1.9 kre 274 1.9 kre check_results replacement_val 275 1.1 jruoho } 276 1.1 jruoho 277 1.1 jruoho atf_test_case ifs_alpha 278 1.9 kre ifs_alpha_head() 279 1.9 kre { 280 1.1 jruoho atf_set "descr" "Checks that field splitting works with alphabetic" \ 281 1.1 jruoho "characters" 282 1.1 jruoho } 283 1.9 kre ifs_alpha_body() 284 1.9 kre { 285 1.1 jruoho unset x 286 1.1 jruoho 287 1.2 christos TEST=0 288 1.1 jruoho # repeat with an alphabetic in IFS 289 1.1 jruoho check 'IFS=q; set ${x-aqbqc}; echo $#' 3 290 1.2 christos check 'IFS=q; for i in ${x-aqbqc}; do echo "z${i}z"; done' \ 291 1.2 christos 'zaz zbz zcz' 292 1.2 christos check 'IFS=q; for i in ${x-"aqb"qc}; do echo "z${i}z"; done' \ 293 1.2 christos 'zaqbz zcz' 294 1.2 christos check 'IFS=q; for i in ${x-"aq${x-bqc}"qd}; do echo "z${i}z"; done' \ 295 1.2 christos 'zaqbqcz zdz' 296 1.6 kre 297 1.6 kre # this is another almost certainly incorrect expectation 298 1.7 kre # (but again, see comment in default_val test - becoming unspecified.) 299 1.6 kre # uu qqqqqq uuu q uu (quoted/unquoted) 300 1.2 christos check 'IFS=q; for i in ${x-"aq${x-"bqc"}"qd}; do echo "z${i}z"; done' \ 301 1.2 christos 'zaqbqcz zdz' 302 1.6 kre 303 1.2 christos check 'IFS=q; for i in ${x-aq${x-"bqc"}qd}; do echo "z${i}z"; done' \ 304 1.2 christos 'zaz zbqcz zdz' 305 1.9 kre 306 1.9 kre check_results ifs_alpha 307 1.1 jruoho } 308 1.1 jruoho 309 1.1 jruoho atf_test_case quote 310 1.9 kre quote_head() 311 1.9 kre { 312 1.1 jruoho atf_set "descr" "Checks that field splitting works with multi-word" \ 313 1.1 jruoho "fields" 314 1.1 jruoho } 315 1.9 kre quote_body() 316 1.9 kre { 317 1.1 jruoho unset x 318 1.1 jruoho 319 1.2 christos TEST=0 320 1.1 jruoho # Some quote propagation checks 321 1.1 jruoho check 'set "${x-a b c}"; echo $#' 1 322 1.6 kre 323 1.6 kre # this is another almost certainly incorrect expectation 324 1.7 kre # (but again, see comment in default_val test - becoming unspecified.) 325 1.6 kre # qqqq uuu qqq (quoted/unquoted) $1 is a $# is 2 326 1.1 jruoho check 'set "${x-"a b" c}"; echo $1' 'a b c' 327 1.6 kre 328 1.1 jruoho check 'for i in "${x-a b c}"; do echo "z${i}z"; done' 'za b cz' 329 1.9 kre 330 1.9 kre check_results quote 331 1.1 jruoho } 332 1.1 jruoho 333 1.1 jruoho atf_test_case dollar_at 334 1.9 kre dollar_at_head() 335 1.9 kre { 336 1.1 jruoho atf_set "descr" "Checks that field splitting works when expanding" \ 337 1.1 jruoho "\$@" 338 1.1 jruoho } 339 1.9 kre dollar_at_body() 340 1.9 kre { 341 1.1 jruoho unset x 342 1.1 jruoho 343 1.2 christos TEST=0 344 1.1 jruoho # Check we get "$@" right 345 1.2 christos 346 1.2 christos check 'set --; for i in x"$@"x; do echo "z${i}z"; done' 'zxxz' 347 1.2 christos check 'set a; for i in x"$@"x; do echo "z${i}z"; done' 'zxaxz' 348 1.9 kre check 'set a b; for i in x"$@"x; do echo "z${i}z"; done' \ 349 1.9 kre 'zxaz zbxz' 350 1.2 christos 351 1.2 christos check 'set --; for i; do echo "z${i}z"; done' '' 352 1.2 christos check 'set --; for i in $@; do echo "z${i}z"; done' '' 353 1.2 christos check 'set --; for i in "$@"; do echo "z${i}z"; done' '' 354 1.2 christos # atf_expect_fail "PR bin/50834" 355 1.2 christos check 'set --; for i in ""$@; do echo "z${i}z"; done' 'zz' 356 1.2 christos # atf_expect_pass 357 1.2 christos check 'set --; for i in $@""; do echo "z${i}z"; done' 'zz' 358 1.2 christos check 'set --; for i in ""$@""; do echo "z${i}z"; done' 'zz' 359 1.2 christos check 'set --; for i in """$@"; do echo "z${i}z"; done' 'zz' 360 1.2 christos check 'set --; for i in "$@"""; do echo "z${i}z"; done' 'zz' 361 1.2 christos check 'set --; for i in """$@""";do echo "z${i}z"; done' 'zz' 362 1.2 christos 363 1.2 christos check 'set ""; for i; do echo "z${i}z"; done' 'zz' 364 1.2 christos check 'set ""; for i in "$@"; do echo "z${i}z"; done' 'zz' 365 1.2 christos check 'set "" ""; for i; do echo "z${i}z"; done' 'zz zz' 366 1.2 christos check 'set "" ""; for i in "$@"; do echo "z${i}z"; done' 'zz zz' 367 1.2 christos check 'set "" ""; for i in $@; do echo "z${i}z"; done' '' 368 1.2 christos 369 1.2 christos check 'set "a b" c; for i; do echo "z${i}z"; done' \ 370 1.2 christos 'za bz zcz' 371 1.2 christos check 'set "a b" c; for i in "$@"; do echo "z${i}z"; done' \ 372 1.2 christos 'za bz zcz' 373 1.2 christos check 'set "a b" c; for i in $@; do echo "z${i}z"; done' \ 374 1.2 christos 'zaz zbz zcz' 375 1.2 christos check 'set " a b " c; for i in "$@"; do echo "z${i}z"; done' \ 376 1.2 christos 'z a b z zcz' 377 1.4 christos 378 1.4 christos check 'set a b c; for i in "$@$@"; do echo "z${i}z"; done' \ 379 1.4 christos 'zaz zbz zcaz zbz zcz' 380 1.4 christos check 'set a b c; for i in "$@""$@";do echo "z${i}z"; done' \ 381 1.4 christos 'zaz zbz zcaz zbz zcz' 382 1.9 kre 383 1.9 kre check_results dollar_at 384 1.1 jruoho } 385 1.1 jruoho 386 1.1 jruoho atf_test_case ifs 387 1.9 kre ifs_head() 388 1.9 kre { 389 1.1 jruoho atf_set "descr" "Checks that IFS correctly configures field" \ 390 1.1 jruoho "splitting behavior" 391 1.1 jruoho } 392 1.9 kre ifs_body() 393 1.9 kre { 394 1.1 jruoho unset x 395 1.1 jruoho 396 1.2 christos TEST=0 397 1.1 jruoho # Some IFS tests 398 1.9 kre check 't="-- "; IFS=" "; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '0' 399 1.9 kre check 't=" x"; IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1' 400 1.9 kre check 't=" x "; IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1' 401 1.9 kre check 't=axb; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' \ 402 1.9 kre '2 a:b' 403 1.9 kre check 't="a x b"; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' \ 404 1.9 kre '2 a : b' 405 1.9 kre check 't="a xx b"; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' \ 406 1.9 kre '3 a :: b' 407 1.9 kre check 't="a xx b"; IFS="x ";set $t; IFS=":"; r="$*"; IFS=; echo $# $r' \ 408 1.9 kre '3 a::b' 409 1.9 kre # A recent 'clarification' means that a single trailing IFS 410 1.9 kre # non-whitespace doesn't generate an empty parameter 411 1.9 kre check 't="xax"; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' \ 412 1.9 kre '2 :a' 413 1.9 kre check 't="xax "; IFS="x "; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' \ 414 1.9 kre '2 :a' 415 1.1 jruoho # Verify that IFS isn't being applied where it shouldn't be. 416 1.9 kre check 'IFS="x"; set axb; IFS=":"; r="$*"; IFS=; echo $# $r' '1 axb' 417 1.9 kre check 'IFS=x; set axb; IFS=:; r=$*; IFS=; echo $# $r' '1 axb' 418 1.9 kre check 'IFS=x; set axb; set -- "$*"; IFS=:; r=$*; IFS=; echo $# $r' \ 419 1.9 kre '1 axb' 420 1.9 kre check 'IFS=x; set axb; set -- $* ; IFS=:; r=$*; IFS=; echo $# $r' \ 421 1.9 kre '2 a:b' 422 1.9 kre 423 1.9 kre check_results ifs 424 1.1 jruoho } 425 1.1 jruoho 426 1.1 jruoho atf_test_case var_length 427 1.9 kre var_length_head() 428 1.9 kre { 429 1.1 jruoho atf_set "descr" "Checks that field splitting works when expanding" \ 430 1.1 jruoho "a variable's length" 431 1.1 jruoho } 432 1.9 kre var_length_body() 433 1.9 kre { 434 1.2 christos TEST=0 435 1.1 jruoho 436 1.1 jruoho long=12345678123456781234567812345678 437 1.1 jruoho long=$long$long$long$long 438 1.2 christos export long 439 1.5 kre unset x 440 1.2 christos 441 1.2 christos # first test that the test method works... 442 1.2 christos check 'set -u; : ${long}; echo ${#long}' '128' 443 1.2 christos 444 1.2 christos # Check that we apply IFS to ${#var} 445 1.2 christos check 'echo ${#long}; IFS=2; echo ${#long}; set 1 ${#long};echo $#' \ 446 1.2 christos '128 1 8 3' 447 1.5 kre check 'IFS=2; set ${x-${#long}}; IFS=" "; echo $* $#' '1 8 2' 448 1.5 kre check 'IFS=2; set ${x-"${#long}"}; IFS=" "; echo $* $#' '128 1' 449 1.5 kre check 'IFS=2; set "${x-${#long}}"; IFS=" "; echo $* $#' '128 1' 450 1.5 kre check 'IFS=2; set ${x-${#long}}; : ; echo $* $#' '1 8 ' 451 1.5 kre check 'IFS=2; set ${x-${#long}}; : ; echo $* "$#"' '1 8 2' 452 1.5 kre check 'IFS=2; set ${x-${#long}}; : ; echo "$*" "$#"' '128 2' 453 1.5 kre check 'IFS=2; set ${x-${#long}}; : ; echo "$@" "$#"' '1 8 2' 454 1.9 kre 455 1.9 kre check_results var_length 456 1.1 jruoho } 457 1.1 jruoho 458 1.6 kre atf_test_case split_arith 459 1.9 kre split_arith_head() 460 1.9 kre { 461 1.6 kre atf_set "descr" "Checks that field splitting works when expanding" \ 462 1.6 kre "the results from arithmetic" 463 1.6 kre } 464 1.9 kre split_arith_body() 465 1.9 kre { 466 1.6 kre TEST=0 467 1.6 kre 468 1.6 kre # Check that we apply IFS to $(( expr )) 469 1.6 kre 470 1.6 kre # Note: we do not check the actual arithmetic operations here 471 1.6 kre # (there is a separate test just for that) so we just enter 472 1.6 kre # the "answer" inside $(( )) ... also makes it easier to visualise 473 1.6 kre 474 1.6 kre check 'IFS=5; echo $(( 123456789 ))' '1234 6789' 475 1.6 kre check 'IFS=5; echo "$(( 123456789 ))"' '123456789' 476 1.6 kre check 'IFS=37; echo $(( 123456789 ))' '12 456 89' 477 1.6 kre check 'IFS=37; echo "$(( 123456789 ))"' '123456789' 478 1.6 kre check 'IFS=159; echo $(( 123456789 ))' ' 234 678' 479 1.6 kre 480 1.6 kre check 'IFS=5; set -- $(( 123456789 )); echo $#: $1 $2 $3 $4' \ 481 1.6 kre '2: 1234 6789' 482 1.6 kre check 'IFS=5; set -- "$(( 123456789 ))"; echo $#: $1 $2 $3 $4' \ 483 1.6 kre '1: 1234 6789' # go ahead: explain it! 484 1.6 kre check 'IFS=5; set -- "$(( 123456789 ))"; echo "$#: $1 $2 $3 $4"' \ 485 1.6 kre '1: 123456789 ' # ah! 486 1.6 kre 487 1.6 kre check 'IFS=37; set -- $(( 123456789 )); echo $#: $1 $2 $3 $4' \ 488 1.6 kre ' : 12 456 89' # Tricky! 489 1.6 kre check 'IFS=5; set -- $(( 123456789 )); echo $#: $*' \ 490 1.6 kre '2: 1234 6789' 491 1.6 kre check 'IFS=47; set -- $(( 123456789 )); echo $#: $*' \ 492 1.6 kre '3: 123 56 89' 493 1.6 kre check 'IFS=5; set -- $(( 123456789 )); echo "$#: $*"' \ 494 1.6 kre '2: 123456789' 495 1.6 kre check 'IFS=37; set -- $(( 123456789 )); echo "$#: $*"' \ 496 1.6 kre '3: 123456389' # [sic] 497 1.6 kre check 'IFS=5; set -- $(( 123456789 )); echo $#: $@' \ 498 1.6 kre '2: 1234 6789' 499 1.6 kre check 'IFS=47; set -- $(( 123456789 )); echo $#: $@' \ 500 1.6 kre '3: 123 56 89' 501 1.6 kre check 'IFS=5; set -- $(( 123456789 )); echo "$#: $@"' \ 502 1.6 kre '2: 1234 6789' 503 1.6 kre check 'IFS=37; set -- $(( 123456789 )); echo "$#: $*"' \ 504 1.6 kre '3: 123456389' # [sic] 505 1.6 kre 506 1.6 kre check 'IFS=1; set -- $(( 1111 )); echo "$#:" $*' '4: ' 507 1.6 kre check 'IFS=" 1"; set -- $(( 1231231231 )); echo "$#: $*"' \ 508 1.6 kre '4: 23 23 23' 509 1.6 kre check 'IFS="1 "; set -- $(( 1231231231 )); echo "$#: $*"' \ 510 1.6 kre '4: 123123123' 511 1.6 kre 512 1.6 kre check 'IFS=5; echo 5$(( 123456789 ))5' '51234 67895' 513 1.6 kre check 'IFS=37; echo 73$(( 123456789 ))37' '7312 456 8937' 514 1.6 kre check 'IFS=159; echo 11$(( 123456789 ))95' '11 234 678 95' 515 1.6 kre check 'IFS="159 "; echo 11$(( 123456789 ))95' '11 234 678 95' 516 1.6 kre check 'IFS="159 "; echo 11$(( 11234567899 ))95' '11 234 678 95' 517 1.9 kre 518 1.9 kre check_results split_arith 519 1.6 kre } 520 1.6 kre 521 1.8 kre atf_test_case read_split 522 1.9 kre read_split_head() 523 1.9 kre { 524 1.8 kre atf_set "descr" "Checks that field splitting works for the read" \ 525 1.8 kre "built-in utility" 526 1.8 kre } 527 1.8 kre # 528 1.8 kre # CAUTION: There are literal <tab> chars in the following test. 529 1.8 kre # It is important that they be retained as is (the ones in the data 530 1.8 kre # and results - those used for test formatting are immaterial). 531 1.8 kre # 532 1.9 kre read_split_body() 533 1.9 kre { 534 1.8 kre DATA=" aaa bbb:ccc ddd+eee fff:ggg+hhh " # CAUTION: tabs! 535 1.8 kre 536 1.8 kre TEST=0 537 1.8 kre 538 1.8 kre check "unset IFS; printf '%s\n' '${DATA}' | { 539 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 540 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 541 1.8 kre '<aaa><bbb:ccc><ddd+eee><fff:ggg+hhh><><><><>' 542 1.8 kre 543 1.8 kre check "unset IFS; printf '%s\n' '${DATA}' | { 544 1.8 kre read x || printf 'FAIL:%d' \"\$?\" && 545 1.8 kre printf '<%s>' "'"$x"; }' \ 546 1.8 kre '<aaa bbb:ccc ddd+eee fff:ggg+hhh>' 547 1.8 kre 548 1.8 kre check "IFS=; printf '%s\n' '${DATA}' | { 549 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 550 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 551 1.8 kre "<${DATA}><><><><><><><>" 552 1.8 kre 553 1.8 kre check "IFS=' '; printf '%s\n' '${DATA}' | { 554 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 555 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 556 1.8 kre '<aaa><bbb:ccc><ddd+eee><fff:ggg+hhh><><><><>' 557 1.8 kre 558 1.8 kre check "IFS=':'; printf '%s\n' '${DATA}' | { 559 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 560 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 561 1.8 kre '< aaa bbb><ccc ddd+eee fff><ggg+hhh ><><><><><>' 562 1.8 kre 563 1.8 kre check "IFS=': '; printf '%s\n' '${DATA}' | { 564 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 565 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 566 1.8 kre '<aaa><bbb><ccc><ddd+eee fff><ggg+hhh ><><><>' 567 1.8 kre 568 1.8 kre check "IFS=': '; printf '%s\n' '${DATA}' | { 569 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 570 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 571 1.8 kre '< aaa bbb><ccc ddd+eee><fff><ggg+hhh>< ><><><>' 572 1.8 kre 573 1.8 kre check "IFS='+'; printf '%s\n' '${DATA}' | { 574 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 575 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 576 1.8 kre '< aaa bbb:ccc ddd><eee fff:ggg><hhh ><><><><><>' 577 1.8 kre 578 1.8 kre check "IFS=' +'; printf '%s\n' '${DATA}' | { 579 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 580 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 581 1.8 kre '<aaa><bbb:ccc><ddd><eee fff:ggg><hhh ><><><>' 582 1.8 kre 583 1.8 kre check "IFS='+ '; printf '%s\n' '${DATA}' | { 584 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 585 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 586 1.8 kre '< aaa bbb:ccc ddd><eee><fff:ggg><hhh>< ><><><>' 587 1.8 kre 588 1.8 kre # This tests the bug from PR bin/57849 (which existed about 2 days) 589 1.8 kre # It also tests that a var-assign before read does not corrupt the 590 1.8 kre # value of the var in the executing shell environment 591 1.8 kre check "IFS='+'; printf '%s\n' '${DATA}' | { 592 1.8 kre IFS=: read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 593 1.8 kre printf '<%s>' "'"$IFS" "$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 594 1.8 kre '<+>< aaa bbb><ccc ddd+eee fff><ggg+hhh ><><><><><>' 595 1.8 kre 596 1.8 kre check "IFS='+'; printf '%s\n' '${DATA}' | { 597 1.8 kre IFS= read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 598 1.8 kre printf '<%s>' "'"$IFS" "$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 599 1.8 kre "<+><${DATA}><><><><><><><>" 600 1.8 kre 601 1.8 kre # This doesn't really belong here, just tests that EOF works... 602 1.8 kre # (and that read sets unused vars to '', doesn't leave them unset) 603 1.8 kre check "unset IFS; set -u; 604 1.8 kre read a b c d e f g h </dev/null || printf 'FAIL:%d' \"\$?\" && 605 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"' \ 606 1.8 kre "FAIL:1<><><><><><><><>" 607 1.8 kre 608 1.8 kre # And a similar one where EOF follows some data (which is read) 609 1.8 kre check "unset IFS; set -u; printf 'a b c' | { 610 1.8 kre read a b c d e f g h || printf 'FAIL:%d' \"\$?\" && 611 1.8 kre printf '<%s>' "'"$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h"; }' \ 612 1.8 kre "FAIL:1<a><b><c><><><><><>" 613 1.9 kre 614 1.9 kre check_results read_split 615 1.8 kre } 616 1.8 kre 617 1.9 kre atf_init_test_cases() 618 1.9 kre { 619 1.1 jruoho atf_add_test_case for 620 1.1 jruoho atf_add_test_case default_val 621 1.2 christos atf_add_test_case replacement_val 622 1.1 jruoho atf_add_test_case ifs_alpha 623 1.1 jruoho atf_add_test_case quote 624 1.1 jruoho atf_add_test_case dollar_at 625 1.1 jruoho atf_add_test_case ifs 626 1.1 jruoho atf_add_test_case var_length 627 1.6 kre atf_add_test_case split_arith 628 1.8 kre atf_add_test_case read_split 629 1.1 jruoho } 630