Home | History | Annotate | Line # | Download | only in sh
t_fsplit.sh revision 1.7
      1 # $NetBSD: t_fsplit.sh,v 1.7 2017/06/24 11:06:17 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; $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_init_test_cases() {
    443 	atf_add_test_case for
    444 	atf_add_test_case default_val
    445 	atf_add_test_case replacement_val
    446 	atf_add_test_case ifs_alpha
    447 	atf_add_test_case quote
    448 	atf_add_test_case dollar_at
    449 	atf_add_test_case ifs
    450 	atf_add_test_case var_length
    451 	atf_add_test_case split_arith
    452 }
    453