# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
#
# A suite of tests for bash word expansions
#
# This tests parameter and variable expansion, with an empahsis on
# proper quoting behavior.
#
# Chet Ramey
#
# If you comment out the body of this function, you can do a diff against
# `expansion-tests.right' to see if the shell is behaving correctly
#
expect()
{
echo expect "$@"
}
# Test the substitution quoting characters (CTLESC and CTLNUL) in different
# combinations
expect "<^A>"
recho `echo ''`
expect "<^A>"
recho `echo ""`
expect "<^?>"
recho `echo ''`
expect "<^?>"
recho `echo ""`
expect "<^A>"
recho `echo `
expect "<^?>"
recho `echo `
expect "bar"
recho ${foo:-"`echo bar`"}
expect "<^A>"
recho ${foo:-"`echo `"}
expect "<^?>"
recho ${foo:-"`echo `"}
expect "<^A>"
recho "`echo `"
expect "<^?>"
recho "`echo `"
# Test null strings without variable expansion
expect ""
recho abcd""efgh
expect ""
recho abcd''efgh
expect ""
recho ""abcdefgh
expect ""
recho ''abcdefgh
expect ""
recho abcd""
expect ""
recho abcd''
# Test the quirky behavior of $@ in ""
expect nothing
recho "$@"
expect "< >"
recho " $@"
expect "<-->"
recho "-${@}-"
# Test null strings with variable expansion that fails
expect '<>'
recho $xxx""
expect '<>'
recho ""$xxx
expect '<>'
recho $xxx''
expect '<>'
recho ''$xxx
expect '<>'
recho $xxx""$yyy
expect '<>'
recho $xxx''$yyy
# Test null strings with variable expansion that succeeds
xxx=abc
yyy=def
expect ''
recho $xxx""
expect ''
recho ""$xxx
expect ''
recho $xxx''
expect ''
recho ''$xxx
expect ''
recho $xxx""$yyy
expect ''
recho $xxx''$yyy
unset xxx yyy
# Test the unquoted special quoting characters
expect "<^A>"
recho
expect "<^?>"
recho
expect "<^A>"
recho ""
expect "<^?>"
recho ""
expect "<^A>"
recho ''
expect "<^?>"
recho ''
# Test expansion of a variable that is unset
expect nothing
recho $xxx
expect '<>'
recho "$xxx"
expect nothing
recho "$xxx${@}"
# Test empty string expansion
expect '<>'
recho ""
expect '<>'
recho ''
# Test command substitution with (disabled) history substitution
expect ''
# set +H
recho "`echo \"Hello world!\"`"
# Test some shell special characters
expect '<`>'
recho "\`"
expect '<">'
recho "\""
expect '<\^A>'
recho "\"
expect '<\$>'
recho "\\$"
expect '<\\>'
recho "\\\\"
# This should give argv[1] = a argv[2] = b
expect ' '
FOO=`echo 'a b' | tr ' ' '\012'`
recho $FOO
# This should give argv[1] = ^A argv[2] = ^?
expect '<^A> <^?>'
FOO=`echo ' ' | tr ' ' '\012'`
recho $FOO
# Test quoted and unquoted globbing characters
expect '<**>'
recho "*"*
expect '<\.\./*/>'
recho "\.\./*/"
# Test patterns that come up when the shell quotes funny character
# combinations
expect '<^A^?^A^?>'
recho ''
expect '<^A^A>'
recho ''
expect '<^A^?>'
recho ''
expect '<^A^A^?>'
recho ''
# More tests of "$@"
set abc def ghi jkl
expect '< abc> '
recho " $@ "
expect '< abc> '
recho "${1+ $@ }"
set abc def ghi jkl
expect '<--abc> '
recho "--$@--"
set "a b" cd ef gh
expect ' '
recho ${1+"$@"}
expect ' '
recho ${foo:-"$@"}
expect ' '
recho "${@}"
expect '< >'
recho " "
expect '< - >'
recho " - "
# Test combinations of different types of quoting in a fully-quoted string
# (so the WHOLLY_QUOTED tests fail and it doesn't get set)
expect '^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>'
recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/"
# Test the various Posix parameter expansions
expect ''
recho "${x:-$(echo "foo bar")}"
expect ' '
recho ${x:-$(echo "foo bar")}
unset X
expect ''
recho ${X:=abc}
expect ''
recho $X
set a b c
expect ''
recho ${3:+posix}
POSIX=/usr/posix
expect '<10>'
recho ${#POSIX}
# remove shortest trailing match
x=file.c
expect ''
recho ${x%.c}.o
# remove longest trailing match
x=posix/src/std
expect ''
recho ${x%%/*}
# remove shortest leading pattern
x=$HOME/src/cmd
expect ''
recho ${x#$HOME}
# remove longest leading pattern
x=/one/two/three
expect ''
recho ${x##*/}
# pattern removal of patterns that don't match
z=abcdef
expect ''
recho ${z#xyz}
expect ''
recho ${z##xyz}
expect ''
recho ${z%xyz}
expect ''
recho ${z%%xyz}
# Command substitution and the quirky differences between `` and $()
expect '<\$x>'
recho '\$x'
expect '<$x>'
recho `echo '\$x'`
expect '<\$x>'
recho $(echo '\$x')
# The difference between $* "$*" and "$@"
set "abc" "def ghi" "jkl"
expect ' '
recho $*
expect ''
recho "$*"
OIFS="$IFS"
IFS=":$IFS"
# The special behavior of "$*", using the first character of $IFS as separator
expect ''
recho "$*"
IFS="$OIFS"
expect ' '
recho "$@"
expect ' '
recho "xx$@yy"
expect ' '
recho "$@$@"
foo=abc
bar=def
expect ''
recho "$foo""$bar"
unset foo
set $foo bar '' xyz "$foo" abc
expect ' <> <> '
recho "$@"
# More tests of quoting and deferred evaluation
foo=10 x=foo
y='$'$x
expect '<$foo>'
recho $y
eval y='$'$x
expect '<10>'
recho $y
# case statements
NL='
'
x='ab
cd'
expect ''
case "$x" in
*$NL*) recho "newline expected" ;;
esac
expect ''
case \? in
*"?"*) recho "got it" ;;
esac
expect ''
case \? in
*\?*) recho "got it" ;;
esac
set one two three four five
expect ' '
recho $1 $3 ${5} $8 ${9}
# length tests on positional parameters and some special parameters
expect '<5> <5>'
recho $# ${#}
expect '<3>'
recho ${#1}
expect '<1>'
recho ${##}
expect '<1>'
recho ${#?}
expect '<5>'
recho ${#@}
expect '<5>'
recho ${#*}
expect '<5>'
recho "${#@}"
expect '<5>'
recho "${#*}"
expect '<42>'
recho $((28 + 14))
expect '<26>'
recho $[ 13 * 2 ]
expect '<\>'
recho `echo \\\\`
expect '<~>'
recho '~'
expect nothing
recho $!
expect nothing
recho ${!}
# test word splitting of assignment statements not preceding a command
a="a b c d e"
declare b=$a
expect ' '
recho $b
a="a?b?c"
echo ${a//\\?/ }
echo ${a//\?/ }
${THIS_SH} -c 'var=a:b: ; IFS=" :" ; recho $var""' bash
${THIS_SH} ./exp1.sub
${THIS_SH} ./exp2.sub
${THIS_SH} ./exp3.sub
${THIS_SH} ./exp4.sub
${THIS_SH} ./exp5.sub
${THIS_SH} ./exp6.sub
${THIS_SH} ./exp7.sub
${THIS_SH} ./exp8.sub
${THIS_SH} ./exp9.sub
${THIS_SH} ./exp10.sub
${THIS_SH} ./exp11.sub
${THIS_SH} ./exp12.sub