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