# 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 '' 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 ${THIS_SH} ./exp13.sub