diff options
Diffstat (limited to 'tests')
154 files changed, 3359 insertions, 254 deletions
diff --git a/tests/alias.right b/tests/alias.right index cab07a98..3ab9a717 100644 --- a/tests/alias.right +++ b/tests/alias.right @@ -18,3 +18,15 @@ one two three four +Error: bar +ok 1 +ok 2 +text +whoops: nullalias +foo +a +a b +a b +a a b +ok 3 +ok 4 diff --git a/tests/alias.tests b/tests/alias.tests index d1ba97b3..6aa1218b 100644 --- a/tests/alias.tests +++ b/tests/alias.tests @@ -38,3 +38,5 @@ unalias foo bar baz ${THIS_SH} ./alias1.sub ${THIS_SH} ./alias2.sub +${THIS_SH} ./alias3.sub +${THIS_SH} ./alias4.sub diff --git a/tests/alias3.sub b/tests/alias3.sub new file mode 100644 index 00000000..bb94268a --- /dev/null +++ b/tests/alias3.sub @@ -0,0 +1,12 @@ +#!/bin/bash +shopt -s expand_aliases +alias foo='oneword' +foo_word='foo' +# +# Fails silently to match 'foo': +# +case "$foo_word" +in + foo) ;; + *) echo bad 1;; +esac diff --git a/tests/alias4.sub b/tests/alias4.sub new file mode 100644 index 00000000..966b93d1 --- /dev/null +++ b/tests/alias4.sub @@ -0,0 +1,61 @@ +shopt -s expand_aliases + +# from an austin-group report +alias foo="echo 'Error:" +foo bar' + +# from some FreeBSD sh tests + +v=1 +alias a='unalias -a +v=2' +eval a +[ "$v" = 2 ] && echo ok 1 +v=1 +alias a='unalias a +v=2' +eval a +[ "$v" = 2 ] && echo ok 2 + +# make sure command doesn't ever reset anything even if it's made a keyword +unalias -a +alias command=command +alias true='echo bad' +eval 'command true' + +unalias -a +alias alias0=command +alias true='echo bad' +eval 'alias0 true' + +# make sure null aliases are ok +unalias -a +alias nullalias='' +alias foo='echo ' +foo nullalias text +unalias foo + +# aliases shouldn't be expanded in quoted strings even when the previous word +# is an alias whose expansion ends in a space +alias foo="echo 'whoops: " +foo nullalias' + +unalias -a + +# recursive alias definitions +alias echo=echo +eval echo foo + +alias echo='echo a' + +echo +echo b +eval echo b +echo $(eval echo b) + +unalias -a + +# alias expansion when in a command position after redirections +alias e=echo +eval '</dev/null e ok 3' +eval 'a=true e ok 4' diff --git a/tests/arith-for.right b/tests/arith-for.right index 5b25c5eb..5c09070b 100644 --- a/tests/arith-for.right +++ b/tests/arith-for.right @@ -64,11 +64,11 @@ fx () 0 1 2 -./arith-for.tests: line 77: syntax error: arithmetic expression required -./arith-for.tests: line 77: syntax error: `(( i=0; "i < 3" ))' +bash: -c: line 0: syntax error: arithmetic expression required +bash: -c: line 0: syntax error: `(( i=0; "i < 3" ))' 2 -./arith-for.tests: line 83: syntax error: `;' unexpected -./arith-for.tests: line 83: syntax error: `(( i=0; i < 3; i++; 7 ))' +bash: -c: line 0: syntax error: `;' unexpected +bash: -c: line 0: syntax error: `(( i=0; i < 3; i++; 7 ))' 2 20 20 diff --git a/tests/arith-for.tests b/tests/arith-for.tests index 00e2d4ae..33f4bd66 100644 --- a/tests/arith-for.tests +++ b/tests/arith-for.tests @@ -74,17 +74,19 @@ type fx fx # errors -for (( i=0; "i < 3" )) +{ +${THIS_SH} -c 'for (( i=0; "i < 3" )) do echo $i -done -echo $? +done' ; echo $? ; } 2>&1 | sed 's|^.*/||' +#echo $? -for (( i=0; i < 3; i++; 7 )) +{ +${THIS_SH} -c 'for (( i=0; i < 3; i++; 7 )) do echo $i -done -echo $? +done' ; echo $?; } 2>&1 | sed 's|^.*/||' +#echo $? # one-liners added in post-bash-2.04 for ((i=0; i < 20; i++)) do : ; done diff --git a/tests/arith.right b/tests/arith.right index 13c8c710..2c3d172a 100644 --- a/tests/arith.right +++ b/tests/arith.right @@ -242,14 +242,22 @@ efg e abcdefg efg +0 +0 +0 +0 +0 +0 +0 8 12 -./arith.tests: line 294: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ") -./arith.tests: line 298: a b: syntax error in expression (error token is "b") -./arith.tests: line 299: ((: a b: syntax error in expression (error token is "b") +./arith.tests: line 297: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ") +./arith.tests: line 301: a b: syntax error in expression (error token is "b") +./arith.tests: line 302: ((: a b: syntax error in expression (error token is "b") 42 42 42 42 42 42 -./arith.tests: line 310: b[c]d: syntax error in expression (error token is "d") +./arith.tests: line 314: 'foo' : syntax error: operand expected (error token is "'foo' ") +./arith.tests: line 318: b[c]d: syntax error in expression (error token is "d") diff --git a/tests/arith.tests b/tests/arith.tests index 79ce016d..bc9490e9 100644 --- a/tests/arith.tests +++ b/tests/arith.tests @@ -283,6 +283,9 @@ ${THIS_SH} ./arith6.sub # part of word expansions such as substring extraction ${THIS_SH} ./arith7.sub +# problems with evaluation of conditional expressions +${THIS_SH} ./arith8.sub + x=4 y=7 @@ -306,5 +309,10 @@ printf "%u\n" $n echo $(( 16#$(printf "%x\n" $n) )) echo $(( 16#$(printf "%X\n" $n) )) +# these are errors +foo=1 +echo $(( 'foo' )) + + # causes longjmp botches through bash-2.05b a[b[c]d]=e diff --git a/tests/arith8.sub b/tests/arith8.sub new file mode 100644 index 00000000..1ab0895e --- /dev/null +++ b/tests/arith8.sub @@ -0,0 +1,37 @@ +# problems with evaluation of wrong terms in conditional expressions through +# bash-4.4 + +a=0 x="a=1" +((0?x:0)) +echo $a +unset a x + +a=0 x="a=1" +((1?0:x)) +echo $a +unset a x + +a=0 x="a=1" +((0?(x):0)) +echo $a +unset a x + +a=0 x="a=1" +((0?$x:0)) +echo $a +unset a x + +a=0 x="a=1" +((0&&x)) +echo $a +unset a x + +a=0 x="a=1" +((1||x)) +echo $a +unset a x + +a=0 +((0?arr[a=1]:0)) +echo $a +unset a diff --git a/tests/array.right b/tests/array.right index 031a0b7e..aab4153d 100644 --- a/tests/array.right +++ b/tests/array.right @@ -26,7 +26,7 @@ hello world 11 3 bdef hello world test expression test 2 -./array.tests: line 76: readonly: `a[5]': not a valid identifier +./array.tests: line 79: readonly: `a[5]': not a valid identifier declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") declare -ar c declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") @@ -46,17 +46,17 @@ declare -ar c declare -a d=([1]="" [2]="bdef" [5]="hello world" [6]="test" [9]="ninth element") declare -a e=([0]="test") declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") -./array.tests: line 100: a: readonly variable -./array.tests: line 102: b[]: bad array subscript -./array.tests: line 103: b[*]: bad array subscript -./array.tests: line 104: ${b[ ]}: bad substitution -./array.tests: line 106: c[-2]: bad array subscript -./array.tests: line 107: c: bad array subscript +./array.tests: line 103: a: readonly variable +./array.tests: line 105: b[]: bad array subscript +./array.tests: line 106: b[*]: bad array subscript +./array.tests: line 107: ${b[ ]}: bad substitution +./array.tests: line 109: c[-2]: bad array subscript +./array.tests: line 110: c: bad array subscript -./array.tests: line 109: d[7]: cannot assign list to array member -./array.tests: line 111: []=abcde: bad array subscript -./array.tests: line 111: [*]=last: cannot assign to non-numeric index -./array.tests: line 111: [-65]=negative: bad array subscript +./array.tests: line 112: d[7]: cannot assign list to array member +./array.tests: line 114: []=abcde: bad array subscript +./array.tests: line 114: [*]=last: cannot assign to non-numeric index +./array.tests: line 114: [-65]=negative: bad array subscript declare -a BASH_ARGC=() declare -a BASH_ARGV=() declare -a BASH_LINENO=([0]="0") @@ -68,8 +68,8 @@ declare -a b=([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd") declare -ar c declare -a d=([1]="test test") declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") -./array.tests: line 119: unset: ps1: not an array variable -./array.tests: line 123: declare: c: cannot destroy array variables in this way +./array.tests: line 122: unset: ps1: not an array variable +./array.tests: line 126: declare: c: cannot destroy array variables in this way this of this is a test of read using arrays this test @@ -127,7 +127,7 @@ grep [ 123 ] * 6 7 9 5 length = 3 value = new1 new2 new3 -./array.tests: line 239: narray: unbound variable +./array.tests: line 242: narray: unbound variable ./array1.sub: line 1: syntax error near unexpected token `(' ./array1.sub: line 1: `printf "%s\n" -a a=(a 'b c')' ./array2.sub: line 1: declare: `[]=asdf': not a valid identifier @@ -154,10 +154,10 @@ for case if then else 12 14 16 18 20 4414758999202 aaa bbb -./array.tests: line 289: syntax error near unexpected token `<>' -./array.tests: line 289: `metas=( <> < > ! )' -./array.tests: line 290: syntax error near unexpected token `<>' -./array.tests: line 290: `metas=( [1]=<> [2]=< [3]=> [4]=! )' +./array.tests: line 292: syntax error near unexpected token `<>' +./array.tests: line 292: `metas=( <> < > ! )' +./array.tests: line 293: syntax error near unexpected token `<>' +./array.tests: line 293: `metas=( [1]=<> [2]=< [3]=> [4]=! )' abc 3 case 4 abc case if then else 5 @@ -502,3 +502,122 @@ unset declare -a a=() declare -A A=() declare -a foo=([0]="1" [1]="(4 5 6)" [2]="3") +a1 +argv[1] = <> +argv[2] = <> +a2 +argv[1] = <> +a3 +argv[1] = <> +argv[2] = <x> +a4 +argv[1] = <y> +p1 +argv[1] = <> +argv[2] = <> +p2 +argv[1] = <> +argv[2] = <x> +p3 +argv[1] = <y> +./array23.sub: line 9: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +./array23.sub: line 10: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +foo +0 +foo +foo +foo +6 +./array23.sub: line 21: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )") +./array23.sub: line 22: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )") +IFS=: ${var-$*} +abc +def ghi +jkl +abc +def ghi +jkl +---- +IFS=: ${var=$*} +abc +def ghi +jkl +var=abc:def ghi:jkl +abc +def ghi +jkl +var=abc:def ghi:jkl +---- +IFS=: ${var+$*} +abc +def ghi +jkl +abc +def ghi +jkl +---- +IFS= ${var-$*} +abc +def ghi +jkl +abc +def ghi +jkl +---- +IFS= ${var=$*} +abcdef ghijkl +var=abcdef ghijkl +abcdef ghijkl +var=abcdef ghijkl +---- +IFS= ${var+$*} +abc +def ghi +jkl +abc +def ghi +jkl +1. indexed: +reference: +./array25.sub: line 10: ${a[ ]}: bad substitution +./array25.sub: line 11: ' ': syntax error: operand expected (error token is "' '") +./array25.sub: line 12: ${a[ ]}: bad substitution +4. 0 +5. 0 +6. 0 +assignment: +1.declare -a a=([0]="10" [1]="1") +2.declare -a a=([0]="11" [1]="1") +3.declare -a a=([0]="12" [1]="1") +4.declare -a a=([0]="13" [1]="1") +arithmetic: +1.declare -a a=([0]="0" [1]="1") +2.declare -a a=([0]="0" [1]="1") +3.declare -a a=([0]="0" [1]="1") +4.declare -a a=([0]="0" [1]="1") +5.declare -a a=([0]="0" [1]="1") +6.declare -a a=([0]="11" [1]="1") +7.declare -a a=([0]="0" [1]="1") +8.declare -a a=([0]="13" [1]="1") +2. associative: +reference: +./array25.sub: line 47: ${a[ ]}: bad substitution +2. +./array25.sub: line 49: ${a[ ]}: bad substitution +4. +5. +6. +assignment: +1.declare -A a=([" "]="10" [0]="0" [1]="1" ) +2.declare -A a=([" "]="11" [0]="0" [1]="1" ) +3.declare -A a=([" "]="12" [0]="0" [1]="1" ) +4.declare -A a=([" "]="13" [0]="0" [1]="1" ) +arithmetic: +1.declare -A a=([" "]="13" [0]="0" [1]="1" ) +2.declare -A a=([" "]="13" [0]="0" [1]="1" ) +3.declare -A a=([" "]="13" [0]="0" [1]="1" ) +4.declare -A a=([" "]="13" [0]="0" [1]="1" ) +5.declare -A a=([" "]="13" [0]="0" [1]="1" ) +6.declare -A a=([" "]="13" [0]="0" [1]="1" ["\" \""]="11" ) +7.declare -A a=([" "]="13" [0]="0" [1]="1" ["\" \""]="11" ) +8.declare -A a=([" "]="13" [0]="0" [1]="1" ["\" \""]="13" ) diff --git a/tests/array.tests b/tests/array.tests index b1053937..e045d5c4 100644 --- a/tests/array.tests +++ b/tests/array.tests @@ -21,6 +21,9 @@ unset a a=abcde declare -a a echo ${a[0]} +if [ "$a" != "${a[0]}" ]; then + echo 'array.tests: $a and $a[0] array mismatch' +fi unset a a=abcde @@ -248,7 +251,7 @@ ${THIS_SH} ./array3.sub ${THIS_SH} ./array4.sub set +u -cd /tmp +cd ${TMPDIR:=/tmp} touch 1=bar foo=([10]="bar") @@ -397,3 +400,7 @@ ${THIS_SH} ./array18.sub ${THIS_SH} ./array19.sub ${THIS_SH} ./array20.sub ${THIS_SH} ./array21.sub +${THIS_SH} ./array22.sub +${THIS_SH} ./array23.sub +${THIS_SH} ./array24.sub +${THIS_SH} ./array25.sub diff --git a/tests/array22.sub b/tests/array22.sub new file mode 100644 index 00000000..e0463c34 --- /dev/null +++ b/tests/array22.sub @@ -0,0 +1,34 @@ +# This isn't perfect behavior, but it establishes a baseline and will provide +# a way to detect behavior changes + +echo a1 +a[0]= a[1]=; recho "${a[@]:-y}" +unset a + +echo a2 +a[1]=; recho "${a[@]:-y}" +unset a + +echo a3 +a[0]= a[1]=x; recho "${a[@]:-y}" +unset a + +echo a4 +a[0]= a[1]=x; recho ${a[@]:+y} +unset a + +echo p1 +set '' '' +recho "${@:-y}" + +shift $# + +echo p2 +set '' x +recho "${@:-y}" + +shift $# + +echo p3 +set '' x +recho ${@:+y} diff --git a/tests/array23.sub b/tests/array23.sub new file mode 100644 index 00000000..a762aadb --- /dev/null +++ b/tests/array23.sub @@ -0,0 +1,22 @@ +# this captures how bash and ksh93 expand indexed array subscripts in +# various contexts. if changes are ever made, or an option added to do +# this differently, the diffs will show up here + +typeset -a array + +index='$( echo >&2 foo )' # Literal shell code should never be evaluated unless an 'eval' is involved. + +echo ${array[ $index ]} # [] expands $index, results in a literal that [] does not re-evaluate. +echo $(( $index )) # (( )) expands $index, results in a literal that (( )) does not re-evaluate. +echo $(( array[ $index ] )) # (( )) expands $index, results in a literal that [] DOES re-evaluate. + +(( array[ $index ] )) + +typeset -a a + +: $(( a[$index]=5 )) + +#shopt -s assoc_expand_once +echo $((1+a[$index])) +echo $((1+a[\$index])) +echo "1+${a[$index]}" diff --git a/tests/array24.sub b/tests/array24.sub new file mode 100644 index 00000000..108f761b --- /dev/null +++ b/tests/array24.sub @@ -0,0 +1,47 @@ +set -- "abc" "def ghi" "jkl" +A=("$@") + +IFS=':' + +echo 'IFS=: ${var-$*}' +unset var; printf '%s\n' ${var-$*} +printf '%s\n' ${var-${A[*]}} + +echo "----" +echo 'IFS=: ${var=$*}' + +unset var; printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" + +unset var; printf '%s\n' ${var=${A[*]}} +printf 'var=%s\n' "$var" + +echo "----" +echo 'IFS=: ${var+$*}' + +printf '%s\n' ${var+$*} +printf '%s\n' ${var+${A[*]}} + +echo "----" +echo 'IFS= ${var-$*}' + +IFS='' +unset var; printf '%s\n' ${var-$*} +unset var; printf '%s\n' ${var-${A[*]}} + +echo "----" +echo 'IFS= ${var=$*}' + +unset var +printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" + +unset var +printf '%s\n' ${var=${A[*]}} +printf 'var=%s\n' "$var" + +echo "----" +echo 'IFS= ${var+$*}' + +printf '%s\n' ${var+$*} +printf '%s\n' ${var+${A[*]}} diff --git a/tests/array25.sub b/tests/array25.sub new file mode 100644 index 00000000..b550d9d5 --- /dev/null +++ b/tests/array25.sub @@ -0,0 +1,70 @@ +# tests with blank subscripts, indexed and associative + +echo 1. indexed: +a[0]=0 a[1]=1 + +v=" " + +echo reference: + +echo 1. ${a[ ]} +echo 2. ${a[' ']} +echo 3. "${a[ ]}" +echo 4. ${a[$v]} +echo 5. ${a["$v"]} +echo 6. "${a[$v]}" + +echo assignment: + +echo -n 1. ; a[ ]=10 ; typeset -p a ; a[0]=0 +echo -n 2. ; a[" "]=11 ; typeset -p a ; a[0]=0 +echo -n 3. ; a[$v]=12 ; typeset -p a ; a[0]=0 +echo -n 4. ; a["$v"]=13 ; typeset -p a ; a[0]=0 + +echo arithmetic: + +echo -n 1. ; (( a[ ]=10 )); typeset -p a ; a[0]=0 +echo -n 2. ; (( a[" "]=11 )); typeset -p a ; a[0]=0 +echo -n 3. ; (( a[$v]=12 )); typeset -p a ; a[0]=0 +echo -n 4. ; (( a["$v"]=13 )); typeset -p a ; a[0]=0 +echo -n 5. ; let "a[ ]=10" ; typeset -p a ; a[0]=0 +echo -n 6. ; let "a[\" \"]=11" ; typeset -p a ; a[0]=0 +echo -n 7. ; let "a[$v]=12" ; typeset -p a ; a[0]=0 +echo -n 8. ; let "a[\"$v\"]=13" ; typeset -p a ; a[0]=0 + +unset -v a v + +echo 2. associative: +shopt -s assoc_expand_once + +typeset -A a +a[0]=0 a[1]=1 + +v=" " + +echo reference: + +echo 1. ${a[ ]} +echo 2. ${a[' ']} +echo 3. "${a[ ]}" +echo 4. ${a[$v]} +echo 5. ${a["$v"]} +echo 6. "${a[$v]}" + +echo assignment: + +echo -n 1. ; a[ ]=10 ; typeset -p a ; a[0]=0 +echo -n 2. ; a[" "]=11 ; typeset -p a ; a[0]=0 +echo -n 3. ; a[$v]=12 ; typeset -p a ; a[0]=0 +echo -n 4. ; a["$v"]=13 ; typeset -p a ; a[0]=0 + +echo arithmetic: + +echo -n 1. ; (( a[ ]=10 )); typeset -p a ; a[0]=0 +echo -n 2. ; (( a[" "]=11 )); typeset -p a ; a[0]=0 +echo -n 3. ; (( a[$v]=12 )); typeset -p a ; a[0]=0 +echo -n 4. ; (( a["$v"]=13 )); typeset -p a ; a[0]=0 +echo -n 5. ; let "a[ ]=10" ; typeset -p a ; a[0]=0 +echo -n 6. ; let "a[\" \"]=11" ; typeset -p a ; a[0]=0 +echo -n 7. ; let "a[$v]=12" ; typeset -p a ; a[0]=0 +echo -n 8. ; let "a[\"$v\"]=13" ; typeset -p a ; a[0]=0 diff --git a/tests/array5.sub b/tests/array5.sub index 778a28df..00953c4a 100644 --- a/tests/array5.sub +++ b/tests/array5.sub @@ -4,7 +4,7 @@ mkdir $TMPDIR/bash-test-$$ cd $TMPDIR/bash-test-$$ -trap "cd / ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15 +trap "cd $OLDPWD ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15 touch '[3]=abcde' diff --git a/tests/assoc.right b/tests/assoc.right index 0a6951d4..e10636b2 100644 --- a/tests/assoc.right +++ b/tests/assoc.right @@ -195,3 +195,28 @@ declare -A assoc=([0]="assoc" ) assoc declare -A assoc=([two]="twoless" [three]="three" [one]="onemore" ) declare -Ar assoc=([two]="twoless" [three]="three" [one]="onemore" ) +declare -A b=(["\""]="" [")"]="" ["\\"]="" ["]"]="" ["\`"]="" ) +declare -A b=(["]"]="" ["\`"]="" ) +declare -A dict=(["\""]="1" ["'"]="3" ["\\"]="4" ["\`"]="2" ) +./assoc9.sub: line 23: unset: `dict["]': not a valid identifier +./assoc9.sub: line 23: unset: `dict[']': not a valid identifier +./assoc9.sub: line 23: unset: `dict[\]': not a valid identifier +./assoc9.sub: line 23: unset: `dict[`]': not a valid identifier +declare -A dict=(["\""]="1" ["'"]="3" ["\\"]="4" ["\`"]="2" ) +declare -A dict=(["\""]="1" ["'"]="3" ["\\"]="4" ["\`"]="2" ) +declare -A dict=() +4 +4 +a[$b]= 5 +declare -A a=(["80's"]="Depeche Mode" ) +./assoc9.sub: line 71: read: `a[80's]': not a valid identifier +declare -A a +declare -A a=(["80's"]="Depeche Mode" ) +./assoc9.sub: line 83: printf: `a[80's]': not a valid identifier +declare -A a +declare -A a=(["80's"]="Depeche Mode" ) +6 +1 +1+5 +declare -A a=(["\$(date >&2)"]="5" ) +declare -A myarray=([foo]="bleh" ["foo[bar"]="bleh" ) diff --git a/tests/assoc.tests b/tests/assoc.tests index 32536b8d..24ab08c0 100644 --- a/tests/assoc.tests +++ b/tests/assoc.tests @@ -107,7 +107,7 @@ unset flix wheat # TEST - index expansion: no word splitting or globbing typeset -A wheat -cd /tmp +cd ${TMPDIR:=/tmp} touch '[sfiri]' wheat=([s*]=6 [foo bar]=flix ) @@ -174,6 +174,13 @@ T='([a]=1)' echo "${T[@]}" unset T +# peculiar ksh93 semantics for unsubscripted assoc variable reference +declare -A T +T[0]='zero' +if [ "$T" != "${T[0]}" ]; then + echo 'assoc.tests: $T and ${T[0]} mismatch' +fi + ${THIS_SH} ./assoc1.sub ${THIS_SH} ./assoc2.sub @@ -207,3 +214,6 @@ readonly -A assoc declare -p assoc ${THIS_SH} ./assoc8.sub + +# new shopt option to prevent multiple expansion of assoc array subscripts +${THIS_SH} ./assoc9.sub diff --git a/tests/assoc9.sub b/tests/assoc9.sub new file mode 100644 index 00000000..c5fbe45b --- /dev/null +++ b/tests/assoc9.sub @@ -0,0 +1,110 @@ +typeset -A a=( [\\]= [\"]= [\)]= ) b +for x in "${!a[@]}"; do b[$x]=; done +b+=([\`]= [\]]=) +typeset -p b +for x in "${!a[@]}"; do + unset -v 'b[$x]' +done +typeset -p b + +unset -v a b + +loaddict() +{ + dict['"']=1 + dict['`']=2 + dict["'"]=3 + dict['\']=4 + declare -p dict +} + +del() +{ + unset -v dict["$1"]; +} + +declare -A dict +loaddict +for k in "${!dict[@]}"; do del "$k"; done +declare -p dict + +unset 'dict[@]' + +shopt -s assoc_expand_once +declare -A dict +loaddict +for k in "${!dict[@]}"; do del "$k"; done +declare -p dict + +unset a b dict + +typeset -A a +b="80's" + +((++a[$b])) + +((++a["$b"])) +[[ $((++a[$b])) ]] +[[ $((++a["$b"])) ]] +echo ${a["$b"]} +echo ${a[$b]} + +let "++a[$b]" + +echo 'a[$b]=' "${a[$b]}" + +unset a b + +declare -A a +b="80's" + +: ${a[$b]:='Depeche Mode'} + +declare -p a + +unset a b +shopt -u assoc_expand_once + +typeset -A a +b="80's" + +read a[$b] <<<"Depeche Mode" +typeset -p a + +shopt -s assoc_expand_once +read a[$b] <<<"Depeche Mode" +typeset -p a + +unset a +shopt -u assoc_expand_once + +typeset -A a + +printf -v a[$b] "%s" "Depeche Mode" +typeset -p a + +shopt -s assoc_expand_once + +printf -v a[$b] "%s" "Depeche Mode" +typeset -p a + +unset a + +declare -A a +x='$(date >&2)' +a[$x]=5 + +shopt -s assoc_expand_once +echo $((1+a[$x])) +echo $((1+a[\$x])) +echo "1+${a[$x]}" + +declare -p a + +shopt -s assoc_expand_once +declare -A myarray + +declare myarray["foo[bar"]=bleh +myarray["foo"]=bleh + +declare -p myarray diff --git a/tests/case.right b/tests/case.right index a17234b9..d2055c9d 100644 --- a/tests/case.right +++ b/tests/case.right @@ -25,3 +25,38 @@ ok 8 ok 9 mysterious 1 mysterious 2 +argv[1] = <\a\b\c\^A\d\e\f> +argv[1] = <\a\b\c\^A\d\e\f> +argv[1] = <abc^Adef> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +--- testing: soh +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +--- testing: stx +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +--- testing: del +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 diff --git a/tests/case.tests b/tests/case.tests index 7ab316a7..cc73d8e1 100644 --- a/tests/case.tests +++ b/tests/case.tests @@ -51,3 +51,5 @@ case " " in ( [" "] ) echo ok;; ( * ) echo no;; esac # tests of quote removal and pattern matching ${THIS_SH} ./case1.sub +${THIS_SH} ./case2.sub +${THIS_SH} ./case3.sub diff --git a/tests/case2.sub b/tests/case2.sub new file mode 100644 index 00000000..085f888c --- /dev/null +++ b/tests/case2.sub @@ -0,0 +1,52 @@ +x=$'\\a\\b\\c\\\001\\d\\e\\f' +y='\a\b\c\\d\e\f' +z=$'abc\001def' + +recho "$x" +recho "$y" +recho "$z" + +case $'abc\001def' in +$x) echo ok 1 ;; +*) echo oops 1;; +esac + +case $z in +$x) echo ok 2 ;; +*) echo oops 2;; +esac + +case $'abc\001def' in +$y) echo ok 3 ;; +*) echo oops 3;; +esac + +case $z in +$y) echo ok 4 ;; +*) echo oops 4;; +esac + +# no backslash before \001 +x=$'\\a\\b\\c\001\\d\\e\\f' +y='\a\b\c\d\e\f' + +case $'abc\001def' in +$x) echo ok 5 ;; +*) echo oops 5;; +esac + +case $z in +$x) echo ok 6 ;; +*) echo oops 6;; +esac + +case $'abc\001def' in +$y) echo ok 7 ;; +*) echo oops 7;; +esac + +case $z in +$y) echo ok 8 ;; +*) echo oops 8;; +esac + diff --git a/tests/case3.sub b/tests/case3.sub new file mode 100644 index 00000000..77526c32 --- /dev/null +++ b/tests/case3.sub @@ -0,0 +1,40 @@ +#!/bin/sh + +testmatch() { + case $1 in + ( $2 ) printf ok1 ;; + ( * ) printf fail1 ;; + esac + case $1,$2 in + ( $2,"$2" ) printf ok2 ;; + ( * ) printf fail2 ;; + esac + case $1, in + ( $2, ) printf ok3 ;; + ( * ) printf fail3 ;; + esac + case ,$2 in + ( ,"$2" ) printf ok4 ;; + ( * ) printf fail4 ;; + esac + case "$1,$2" in + ( $2,"$2" ) printf ok5 ;; + ( * ) printf fail5 ;; + esac + echo +} + +for c in $'\1' $'\2' $'\177'; do + echo -n "--- testing: " + echo "$c" | od -t a | awk 'NR==1 { print $2 } ' + testmatch "${c}" "\\${c}" + testmatch "${c}x" "\\${c}\\x" # bash-git fails case 2 and 5 for $'\1' + testmatch "${c}x" "${c}\\x" + testmatch "${c}x" "${c}x" + testmatch "${c}x" "\\${c}x" + testmatch "x${c}" "\\x\\${c}" + testmatch "x${c}" "x\\${c}" +done + +match() { case $1 in ( $2 ) ;; ( * ) return 1 ;; esac; } +match $'? *x\1y\177z' $'??\\*\\x\\\1\\y\\\177\\z' || echo bad 6 diff --git a/tests/comsub-posix.tests b/tests/comsub-posix.tests index 0650ca98..d53e6ebc 100644 --- a/tests/comsub-posix.tests +++ b/tests/comsub-posix.tests @@ -1,3 +1,4 @@ +: ${HOME:=/} # works right echo ab$(echo mnop)yz diff --git a/tests/comsub.right b/tests/comsub.right index 09518aae..71bb205a 100644 --- a/tests/comsub.right +++ b/tests/comsub.right @@ -28,6 +28,7 @@ ok 4 ok 5 ok 6 xyz +ok 7 \/tmp\/foo\/bar /tmp/foo/bar /tmp/foo/bar @@ -48,3 +49,9 @@ b c 1 2 +d \ +g +d \ +g +d \ +g diff --git a/tests/comsub.tests b/tests/comsub.tests index 4defc31e..ed56007c 100644 --- a/tests/comsub.tests +++ b/tests/comsub.tests @@ -44,6 +44,19 @@ bar') # long-standing parse error in all versions up through bash-4.3 echo ${foo:-$(echo a{b,c})} >/dev/null +# parsing problem based on recursively calling bison parser through bash-4.4 +for (( INDEX=0; INDEX<$((10-$(echo length $V_NAME))); INDEX++ )) +do + : +done + +# problem with four-character words followed by a metachar through bash-4.4 +comsub_foo_1() +{ + echo $(while true; do case $HOME in /*) echo abs ;; esac; done) +} + ${THIS_SH} ./comsub1.sub ${THIS_SH} ./comsub2.sub ${THIS_SH} ./comsub3.sub +${THIS_SH} ./comsub4.sub diff --git a/tests/comsub1.sub b/tests/comsub1.sub index 216e03f1..b1af263b 100644 --- a/tests/comsub1.sub +++ b/tests/comsub1.sub @@ -52,3 +52,9 @@ echo $( # we just took and pasted in some # command substitution echo xyz ) + +# problem with parse_comsub through bash-4.4 +case $(echo $$'x\nx') in +x*) echo bad 7;; +*) echo ok 7;; +esac diff --git a/tests/comsub2.sub b/tests/comsub2.sub index a2d58ad0..d60ae6a0 100644 --- a/tests/comsub2.sub +++ b/tests/comsub2.sub @@ -3,6 +3,6 @@ qpath='\/tmp\/foo\/bar' echo "$qpath" # it's crazy that all three of these produce the same result -echo ${qpath//\\/} -echo ${qpath//"`echo \\`"/} -echo ${qpath//`echo "\\\\\\\\"`/} +printf "%s\n" ${qpath//\\/} +printf "%s\n" ${qpath//"`printf '%s' \\`"/} +printf "%s\n" ${qpath//`printf '%s' "\\\\\\\\"`/} diff --git a/tests/comsub4.sub b/tests/comsub4.sub new file mode 100644 index 00000000..461a9ad1 --- /dev/null +++ b/tests/comsub4.sub @@ -0,0 +1,27 @@ +x=$(cat <<'EOT' +d \ +g +EOT +) + +echo "$x" +unset x + +x=$( cat <<\EOT\ +4 +d \ +g +EOT4 +) + +echo "$x" +unset x + +x=$( cat <<\EOT +d \ +g +EOT +) + +echo "$x" + diff --git a/tests/cond-regexp.sub b/tests/cond-regexp.sub deleted file mode 100644 index 724957dd..00000000 --- a/tests/cond-regexp.sub +++ /dev/null @@ -1,42 +0,0 @@ -VAR='[[:alpha:]]' - -[[ $VAR =~ '[[:alpha:]]' ]] && echo match 1 - -[[ a =~ '[[:alpha:]]' ]] || echo match 2 - -[[ a =~ [[:alpha:]] ]] && echo match 3 - -[[ a =~ $VAR ]] && echo match 4 - -[[ a =~ "$VAR" ]] || echo match 5 - -line=aab -[[ $line =~ [[:space:]]*(a)?b ]] && echo match 6 - -V="alphabet" -[[ $V == alphabet ]] && echo yes 1 -[[ $V == "alphabet" ]] && echo yes 2 -[[ $V == 'alphabet' ]] && echo yes 3 -[[ $V =~ alphabet ]] && echo yes 4 -[[ $V =~ "alphabet" ]] && echo yes 5 -[[ $V =~ 'alphabet' ]] && echo yes 6 - -DOG="Dog name - 01 - Wiggles" -REPAT='([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$' -if [[ $DOG =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]] -then - echo Dog ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]} -fi -if [[ $DOG =~ $REPAT ]] -then - echo Dog ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]} -fi - -[[ $REPAT =~ "$REPAT" ]] && echo rematch 1 - -v="one two buckle my shoe" -[[ ${v} =~ "one two" ]] && echo matches 7 - -[[ ${v} =~ (one two) ]] && echo matches 8 - -[[ ${v} =~ one\ two ]] && echo matches 9 diff --git a/tests/cond-regexp2.sub b/tests/cond-regexp2.sub index 71abfb70..2bea6384 100644 --- a/tests/cond-regexp2.sub +++ b/tests/cond-regexp2.sub @@ -28,3 +28,5 @@ [[ ']' =~ [']'] ]] && echo ok 11 [[ a =~ ['a]'] ]] || echo ok 12 + +[[ "\\" =~ [^]"."] ]] || echo unexpected diff --git a/tests/cond.tests b/tests/cond.tests index 8e4548ac..2cef9293 100755 --- a/tests/cond.tests +++ b/tests/cond.tests @@ -180,6 +180,9 @@ echo ${BASH_REMATCH[@]} if [[ "123abc" == *?(a)bc ]]; then echo ok 42; else echo bad 42; fi if [[ "123abc" == *?(a)bc ]]; then echo ok 43; else echo bad 43; fi +match() { [[ $1 == $2 ]]; } +match $'? *x\1y\177z' $'??\\*\\x\\\1\\y\\\177\\z' || echo bad 44 + foo="" [[ bar == *"${foo,,}"* ]] && echo ok 1 [[ bar == *${foo,,}* ]] && echo ok 2 diff --git a/tests/coproc.tests b/tests/coproc.tests index d347eb74..5066f7c5 100644 --- a/tests/coproc.tests +++ b/tests/coproc.tests @@ -30,8 +30,8 @@ read LINE <&${REFLECT[0]} echo $LINE { sleep 1; kill $REFLECT_PID; } & -wait $REFLECT_PID >$TMPOUT 2>&1 || echo "coproc.tests: REFLECT: status $?" -grep 'Terminated.*coproc.*REFLECT' < $TMPOUT >/dev/null 2>&1 || { +wait $REFLECT_PID >$TMPOUT 2>&1 || { status=$? ; echo "coproc.tests: REFLECT: status $status" ; } +[[ $status < 128 || $status == 143 ]] || { echo "coproc.tests: wait for REFLECT failed" >&2 } rm -f $TMPOUT diff --git a/tests/dollar-at-star b/tests/dollar-at-star index 2d2a1b66..0f713dc3 100755 --- a/tests/dollar-at-star +++ b/tests/dollar-at-star @@ -6,6 +6,23 @@ recho "$*" recho $@ recho $* +foo=$* +foo=$@ + +foo="$*" +foo="$@" + +unset -v bar + +foo=${bar:-$*} +foo=${bar:-$@} + +foo=${bar:-"$*"} +foo=${bar:-"$@"} + +foo=${!*} +foo=${!@} + set a b recho "$*" @@ -271,4 +288,18 @@ ${THIS_SH} ./dollar-star6.sub # problem through bash-4.2 ${THIS_SH} ./dollar-star7.sub +# tests for expansions of $* (unquoted) when IFS is null and word splitting is +# not going to be performed. +# problem through bash-4.4 in some parameter expansion contexts +${THIS_SH} ./dollar-star8.sub + +# tests for expansions of "$@" when there are no positional parameter or when +# $1 == '' and the expansion is preceded by something that results in a quoted +# null string +${THIS_SH} ./dollar-at7.sub + +# tests for expansions of $* when in an assignment context (no splitting) and +# IFS is null +${THIS_SH} ./dollar-star9.sub + exit 0 diff --git a/tests/dollar-at-star4.sub b/tests/dollar-at-star4.sub index 690eb677..be2892dd 100644 --- a/tests/dollar-at-star4.sub +++ b/tests/dollar-at-star4.sub @@ -33,10 +33,12 @@ unset a unset IFS set a b "c d" printf '<%s>' $* ; echo +printf '<%s>' ${q-$*} ; echo IFS= set a b "c d" printf '<%s>' $* ; echo +printf '<%s>' ${q-$*} ; echo IFS=: set a b diff --git a/tests/dollar-at7.sub b/tests/dollar-at7.sub new file mode 100644 index 00000000..311a6fef --- /dev/null +++ b/tests/dollar-at7.sub @@ -0,0 +1,46 @@ +set -- '' + +recho 1 ''"$@" +recho 2 """$@" + +recho 3 "$@""$@" +recho 4 "$x""$@" + +set -- + +echo ----- +recho 1 ''"$@" +recho 2 """$@" + +recho 3 "$@""$@" +recho 4 "$x""$@" + +set -- X + +echo ------ +recho 1 ''"${@/*}" +recho 2 """${@/*}" + +recho 3 "$x""${@/*}" + +recho 4 ''"${@#X}" +recho 5 """${@#X}" + +recho 6 "$x""${@#X}" + +set -- + +echo ----- +recho 1 ''"${@/*}" +recho 2 """${@/*}" + +recho 3 "$x""${@/*}" + +recho 4 ''"${@#X}" +recho 5 """${@#X}" + +recho 6 "$x""${@#X}" + +echo ----- +recho 1 "$novar${*}$(echo)" +recho 2 ''"$novar${@}$(echo)" diff --git a/tests/dollar-star8.sub b/tests/dollar-star8.sub new file mode 100644 index 00000000..72ba1080 --- /dev/null +++ b/tests/dollar-star8.sub @@ -0,0 +1,21 @@ +IFS= +set "abc" "def ghi" "jkl" + +set ${1+$*} +printf '<%s>\n' "$#" "$@" + +set "abc" "def ghi" "jkl" +set $* +printf '<%s>\n' "$#" "$@" + +printf '<%s>\n' $* ; +printf '<%s>\n' ${q:-$*} +printf '<%s>\n' "${q:-$*}" + +IFS=: +printf '<%s>\n' $* ; +printf '<%s>\n' ${q:-$*} +printf '<%s>\n' "${q:-$*}" + +unset -v IFS +printf '<%s>\n' $* $@ diff --git a/tests/dollar-star9.sub b/tests/dollar-star9.sub new file mode 100644 index 00000000..26d0ed21 --- /dev/null +++ b/tests/dollar-star9.sub @@ -0,0 +1,46 @@ +set -- 1 2 + +IFS= + +a=$* b=${*} +c=${*/} d=${*#} e=${*%} f=${*:1} +printf '<%s>' "$a" "$b" "$c" "$d" "$e" "$f"; echo + +unset a b c d e f +: ${a=$*} ${b=${*}} ${c=${*/}} +: ${d=${*#}} ${e=${*%}} ${f=${*:1}} +printf '<%s>' "$a" "$b" "$c" "$d" "$e" "$f" ; echo + +unset f g +f=${*,,} g=${*@Q} +printf '<%s>' "$f" "$g" ; echo + +unset -v a b c d e f g +unset var + +# resetting IFS here + +IFS=$' \t\n' + +printf '%s\n' "${*:1}" +var=${*:1}; printf '%s\n' "$var" +var="${*:1}"; printf '%s\n' "$var" + +unset var +recho ${var-${*}} +recho ${var-${*:1}} +recho "${var-${*:1}}" +recho ${var-"${*:1}"} + +unset var +recho ${var=${*}} +printf 'var=%s\n' "$var" +unset var +recho ${var=${*:1}} +printf 'var=%s\n' "$var" + +a=${*:1} +recho "$a" + +: ${b=${*:1}} +recho "$b" diff --git a/tests/dollar.right b/tests/dollar.right index 1e48c24e..d72361f9 100644 --- a/tests/dollar.right +++ b/tests/dollar.right @@ -177,6 +177,8 @@ ab a b a b <a><b><c><d> +<a><b><c><d> +<a><b><c d> <a><b><c d> <a><b> <a:b> @@ -478,3 +480,100 @@ argv[2] = <b> argv[3] = <c> argv[4] = <d> argv[1] = <a b c d> +<3> +<abc> +<def ghi> +<jkl> +<3> +<abc> +<def ghi> +<jkl> +<abc> +<def ghi> +<jkl> +<abc> +<def ghi> +<jkl> +<abcdef ghijkl> +<abc> +<def ghi> +<jkl> +<abc> +<def ghi> +<jkl> +<abc:def ghi:jkl> +<abc> +<def> +<ghi> +<jkl> +<abc> +<def> +<ghi> +<jkl> +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[2] = <> +argv[1] = <4> +argv[2] = <> +----- +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[1] = <4> +argv[2] = <> +------ +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[2] = <> +argv[1] = <4> +argv[2] = <> +argv[1] = <5> +argv[2] = <> +argv[1] = <6> +argv[2] = <> +----- +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[2] = <> +argv[1] = <4> +argv[2] = <> +argv[1] = <5> +argv[2] = <> +argv[1] = <6> +argv[2] = <> +----- +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +<12><12><12><12><12><12> +<12><12><12><12><12><12> +<12><'1''2'> +1 2 +1 2 +1 2 +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +var=1 2 +argv[1] = <1> +argv[2] = <2> +var=1 2 +argv[1] = <1 2> +argv[1] = <1 2> diff --git a/tests/dstack2.tests b/tests/dstack2.tests index d902bffb..3aa105b3 100644 --- a/tests/dstack2.tests +++ b/tests/dstack2.tests @@ -1,3 +1,4 @@ +wdir=$PWD cd / echo expect '~1' @@ -31,3 +32,5 @@ dirs -v -1 echo these lines should be the same dirs -0 echo ~-0 ${DIRSTACK[NDIRS]} + +cd "$wdir" diff --git a/tests/dynvar.right b/tests/dynvar.right new file mode 100644 index 00000000..e1344c60 --- /dev/null +++ b/tests/dynvar.right @@ -0,0 +1,7 @@ +BASHPID ok +BASH_ARGV0 ok +BASH_ARGV0 ok +SECONDS ok +EPOCHSECONDS ok +EPOCHREALTIME ok +echo $BASH_COMMAND diff --git a/tests/dynvar.tests b/tests/dynvar.tests new file mode 100644 index 00000000..a01f5ed2 --- /dev/null +++ b/tests/dynvar.tests @@ -0,0 +1,77 @@ +# specvar -- test some of the dynamic variables + +# BASHPID +pid=$$ +bpid=$BASHPID +subpid=$( (echo $BASHPID) ) + +if [ "$bpid" -ne "$subpid" ]; then echo BASHPID ok; fi + +# BASH_ARGV0 + +BASH_ARGV0=hello +case $0 in +hello) echo BASH_ARGV0 ok ;; +*) echo "BASH_ARGV0 mismatch: $BASH_ARGV0 ($0)" >&2 ;; +esac + +setarg0() +{ + BASH_ARGV0="$1" +} + +setarg0 arg0 +case $0 in +arg0) echo BASH_ARGV0 ok ;; +*) echo "BASH_ARGV0 mismatch: $BASH_ARGV0 ($0)" >&2 ;; +esac + +# SECONDS +before=$SECONDS +sleep 2 +after=$SECONDS + +if (( $after > $before )); then echo SECONDS ok; fi +unset before after + +# EPOCHSECONDS + +# not exact, but should work + +now1=$(perl -e 'print time') +now2=$EPOCHSECONDS + +case $now1 in +$now2) echo EPOCHSECONDS ok ;; +*) echo "current time via perl and EPOCHSECONDS possible mismatch|$now1|$now2" >&2 ;; +esac +unset now1 now2 + +LC_ALL=C # force decimal point to `.' +now1=$EPOCHREALTIME +now2=$EPOCHREALTIME +sec1=${now1%%.*} +sec2=${now2%%.*} + +msec1=${now1##*.} +msec2=${now2##*.} +# cut off leading zeros +shopt -s extglob +msec1=${msec1##*(0)} +msec2=${msec2##*(0)} + +dsec=$(( $sec2 - $sec1 )) +dmsec=$(( $msec2 - $msec1 )) +if (( $dmsec < 0 )); then + dmsec=$(( dmsec + 1000000 )) + dsec=$(( desc - 1 )) +fi + +# not a real test, but ok for a start +if (( $dmsec < 1000000 )); then echo EPOCHREALTIME ok; fi + +${THIS_SH} -c 'echo $BASH_COMMAND' + +# FUNCNAME tested in func.tests +# RANDOM tested in varenv.sh +# LINENO tested in dbg-support diff --git a/tests/errors.right b/tests/errors.right index 362855e3..4bf478b0 100644 --- a/tests/errors.right +++ b/tests/errors.right @@ -120,17 +120,61 @@ after readonly assignment ./errors4.sub: line 7: var: readonly variable ./errors5.sub: line 6: array: unbound variable ./errors5.sub: line 7: array: unbound variable -./errors5.sub: line 10: 7: unbound variable +./errors5.sub: line 8: array[7]: unbound variable ./errors5.sub: line 11: 7: unbound variable +./errors5.sub: line 12: 7: unbound variable after 1: 1 after 2: 1 after 3: 1 array after 1: 1 array after 2: 1 -./errors6.sub: line 18: ${-3}: bad substitution -./errors6.sub: line 19: -3: bad substitution +./errors6.sub: uvar: parameter not set +./errors6.sub: uvar: parameter null or not set + +./errors6.sub: uvar: parameter null or not set +./errors6.sub: line 25: ${-3:-${-3}}: bad substitution +./errors6.sub: line 26: ${-3}: bad substitution +./errors6.sub: line 27: -3: invalid variable name after indir: 1 -./errors6.sub: line 18: ${-3}: bad substitution -./errors6.sub: line 19: -3: bad substitution +./errors6.sub: line 30: -3: invalid variable name + +unset +./errors6.sub: line 37: var: invalid indirect expansion +./errors6.sub: line 38: var: invalid indirect expansion +./errors6.sub: line 41: invalid-ident: invalid variable name +./errors6.sub: line 42: invalid-ident: invalid variable name +./errors6.sub: line 43: invalid-ident: invalid variable name +./errors6.sub: uvar: parameter not set +./errors6.sub: uvar: parameter null or not set + +./errors6.sub: uvar: parameter null or not set +./errors6.sub: line 25: ${-3:-${-3}}: bad substitution +./errors6.sub: line 26: ${-3}: bad substitution +./errors6.sub: line 27: -3: invalid variable name after indir: 1 -./errors.tests: line 278: `!!': not a valid identifier +./errors6.sub: line 30: -3: invalid variable name + +unset +./errors6.sub: line 37: var: invalid indirect expansion +./errors6.sub: line 38: var: invalid indirect expansion +./errors6.sub: line 41: invalid-ident: invalid variable name +./errors6.sub: line 42: invalid-ident: invalid variable name +./errors6.sub: line 43: invalid-ident: invalid variable name +./errors7.sub: line 8: x: readonly variable +./errors7.sub: line 8: notthere: command not found +after no such command: 127 +./errors7.sub: line 10: x: readonly variable +echo builtin +after non-special builtin: 0 +./errors7.sub: line 12: x: readonly variable +after special builtin: 0 +./errors7.sub: line 14: x: readonly variable +./errors7.sub: line 8: x: readonly variable +./errors7.sub: line 8: notthere: command not found +after no such command: 127 +./errors7.sub: line 10: x: readonly variable +echo builtin +after non-special builtin: 0 +./errors7.sub: line 12: x: readonly variable +./errors7.sub: line 14: x: readonly variable +./errors.tests: line 281: `!!': not a valid identifier diff --git a/tests/errors.tests b/tests/errors.tests index ff542f78..4183d024 100644 --- a/tests/errors.tests +++ b/tests/errors.tests @@ -270,6 +270,9 @@ ${THIS_SH} ./errors5.sub ${THIS_SH} ./errors6.sub THIS_SH="${THIS_SH} -o posix" ${THIS_SH} ./errors6.sub +${THIS_SH} ./errors7.sub +${THIS_SH} -o posix ./errors7.sub + # this must be last! # in posix mode, a function name must be a valid identifier # this can't go in posix2.tests, since it causes the shell to exit diff --git a/tests/errors5.sub b/tests/errors5.sub index 7d9068b7..112b2a11 100644 --- a/tests/errors5.sub +++ b/tests/errors5.sub @@ -5,6 +5,7 @@ set -u ( echo ${#array} ) ( echo ${array} ) +( echo ${array[7]} ) set -- 1 2 3 ( echo ${#7} ) diff --git a/tests/errors6.sub b/tests/errors6.sub index 3c05625a..b80580e7 100644 --- a/tests/errors6.sub +++ b/tests/errors6.sub @@ -15,6 +15,29 @@ echo array after 1: $?' 2>/dev/null ${THIS_SH} -c 'typeset -A v ; v["0"]=one ; echo ${v[ ]} echo array after 2: $?' 2>/dev/null +${THIS_SH} -c 'echo ${uvar?}' ./errors6.sub +${THIS_SH} -c 'echo ${uvar:?}' ./errors6.sub +export uvar= +${THIS_SH} -c 'echo ${uvar?}' ./errors6.sub +${THIS_SH} -c 'echo ${uvar:?}' ./errors6.sub +unset uvar + +echo "${-3:-${-3}}" echo ${-3} x=-3; echo ${!x} echo after indir: $? + +function ivar() { echo -n "${!1:-${1}}"; } +ivar -3 + +foo=bar +echo ${!foo} +echo ${!foo:-unset} + +echo ${!var:-unset} +echo ${!var+unset} + +foo=invalid-ident +echo ${!foo} +echo ${!foo:-unset} +echo ${!foo+unset} diff --git a/tests/errors7.sub b/tests/errors7.sub new file mode 100644 index 00000000..067867a1 --- /dev/null +++ b/tests/errors7.sub @@ -0,0 +1,15 @@ +: ${THIS_SH:=./bash} +readonly x=4 + +# in posix mode, these are all variable assignment errors, so strict conformance +# implies that we exit after any of them. ksh93 doesn't do that. we more-or-less +# emulate the ksh93 behavior + +x=8 notthere +echo after no such command: $? +x=8 echo echo builtin +echo after non-special builtin: $? +( x=8 : nosuchdir +echo after special builtin: $? ) +( x=8 $nocmd +echo after assignment error: $? ) diff --git a/tests/exec12.sub b/tests/exec12.sub index 4bd6121b..bc627d2d 100644 --- a/tests/exec12.sub +++ b/tests/exec12.sub @@ -1,5 +1,6 @@ : ${TMPDIR:=/var/tmp} TMPFILE=$TMPDIR/exitcode +trap 'rm -f $TMPFILE' 0 rm -f $TMPFILE set -e diff --git a/tests/exec7.sub b/tests/exec7.sub index ea2fd066..0267505c 100644 --- a/tests/exec7.sub +++ b/tests/exec7.sub @@ -18,3 +18,6 @@ chmod 755 testb/foo PATH=$TMPDIR/testa:$TMPDIR/testb $THIS_SH -c foo rm -rf testa testb + +cd $OLDPWD +exit 0 diff --git a/tests/execscript b/tests/execscript index 3415ae3c..c1819de7 100644 --- a/tests/execscript +++ b/tests/execscript @@ -59,10 +59,10 @@ echo $? echo $? # kill two birds with one test -- test out the BASH_ENV code -echo echo this is bashenv > /tmp/bashenv -export BASH_ENV=/tmp/bashenv +echo echo this is bashenv > $TMPDIR/bashenv +export BASH_ENV=$TMPDIR/bashenv ${THIS_SH} ./exec3.sub -rm -f /tmp/bashenv +rm -f $TMPDIR/bashenv unset BASH_ENV # we're resetting the $PATH to empty, so this should be last @@ -108,7 +108,7 @@ ${THIS_SH} ./exec6.sub # checks for properly deciding what constitutes an executable file ${THIS_SH} ./exec7.sub -${THIS_SH} -i ./exec8.sub +${THIS_SH} -i ${PWD}/exec8.sub ${THIS_SH} ./exec9.sub diff --git a/tests/exp.right b/tests/exp.right index 96617397..599482a7 100644 --- a/tests/exp.right +++ b/tests/exp.right @@ -210,11 +210,13 @@ argv[1] = <correct> argv[2] = <a> argv[1] = <correct> argv[2] = <a> +./exp7.sub: line 5: INFORM: dequote_string: string with bare CTLESC argv[1] = <^A> argv[1] = <3> argv[2] = <^C> argv[3] = <^C> argv[4] = <^C> +./exp7.sub: line 10: INFORM: dequote_string: string with bare CTLESC argv[1] = <^A> argv[1] = <x^Ay^?z> argv[1] = <x^Ay^?z> @@ -291,7 +293,9 @@ var=abc:def ghi:jkl abcdef ghijkl abcdef ghijkl abcdef ghijkl -abcdef ghijkl +abc +def ghi +jkl abcdef ghijkl abcdef ghijkl abcdef ghijkl @@ -332,3 +336,68 @@ jkl [] [foo] [] +< A >< B >< A >< B > +< A >< B >< A >< B > +< A >< B >< a >< b > +< A >< B >< A >< B > +< A >< B ><' A '><' B '> +----- +< A >< B >< A >< B > +< A >< B >< A >< B > +< A >< B >< a >< b > +< A >< B >< A >< B > +< A >< B ><' A '><' B '> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a b> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <12> +argv[1] = <12> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = < > +argv[1] = < > +argv[1] = < > +argv[1] = < > +argv[1] = < > +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +argv[1] = <file.o> +argv[1] = <posix> +argv[1] = </src/cmd> +argv[1] = <three> +argv[1] = </one/two/three> +abcdefg +abcdefg +abcdefg +abcdefg +cdefg +abcdefg +abcde +abcdefg diff --git a/tests/exp.tests b/tests/exp.tests index b446d637..6e364f9c 100644 --- a/tests/exp.tests +++ b/tests/exp.tests @@ -405,3 +405,6 @@ ${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 diff --git a/tests/exp10.sub b/tests/exp10.sub new file mode 100644 index 00000000..6592bab9 --- /dev/null +++ b/tests/exp10.sub @@ -0,0 +1,26 @@ +set -- ' A ' ' B ' +IFS= + +printf '<%s>' ${*} ${*##} +echo +printf '<%s>' ${*} ${*/} +echo +printf '<%s>' ${*} ${*,,} +echo +printf '<%s>' ${*} ${*:1:2} +echo +printf '<%s>' ${*} ${*@Q} +echo + +echo ----- + +printf '<%s>' ${@} ${@##} +echo +printf '<%s>' ${@} ${@/} +echo +printf '<%s>' ${@} ${@,,} +echo +printf '<%s>' ${@} ${@:1:2} +echo +printf '<%s>' ${@} ${@@Q} +echo diff --git a/tests/exp11.sub b/tests/exp11.sub new file mode 100644 index 00000000..cae7b19c --- /dev/null +++ b/tests/exp11.sub @@ -0,0 +1,92 @@ +set -- '1 2' + +unset var +recho ${var-${*:1}} + +unset var +recho ${var=$*} + +unset var +recho ${var=${*:1}} +recho "$var" + +# posix interp 221 +unset var +recho ${var:-a\ b} + +recho ${var:=a\ b} +recho "$var" + +set -- 1 2 +IFS= + +unset a b c +recho $* +recho ${a-$*} +recho ${b-${*/}} +recho ${c=${*/}} +recho "$c" +recho ${b-${*,,}} +recho ${d-${*,,}} + +unset -v a b c +IFS=$' \t\n' + +set -- ' ' +A=(' ') + +IFS= +unset var +var=${*@E} +recho "$var" + +unset var +var=${A[*]@E} +recho "$var" + +unset var +var=${@@E} +recho "$var" + +unset var +var=${A[@]@E} +recho "$var" + +unset novar +recho ${novar-${A[*]@E}} + +unset -v var novar +IFS=$' \t\n' + +set -- 1 2 +A=( 1 2 ) +IFS= + +a=$* +recho "$a" +b=${*@E} +recho "$b" + +unset a b +a=${A[*]} +recho "$a" +b=${A[*]@E} +recho "$b" + +set -- $'\t' +A=$1 + +IFS=$1 +[[ ${A[@]} ]] && echo ok 1 +[[ ${A[*]} ]] && echo ok 2 +[[ ${A[0]} ]] && echo ok 3 + +IFS=$' \t\n' +[[ ${A[@]} ]] && echo ok 4 +[[ ${A[*]} ]] && echo ok 5 +[[ ${A[0]} ]] && echo ok 6 + +IFS= +[[ ${A[@]} ]] && echo ok 7 +[[ ${A[*]} ]] && echo ok 8 +[[ ${A[0]} ]] && echo ok 9 diff --git a/tests/exp12.sub b/tests/exp12.sub new file mode 100644 index 00000000..0aaa2f44 --- /dev/null +++ b/tests/exp12.sub @@ -0,0 +1,38 @@ +# force single-byte versions of these functions + +export LANG=C + +# remove shortest trailing match +x=file.c +recho ${x%.c}.o + +# remove longest trailing match +x=posix/src/std +recho ${x%%/*} + +# remove shortest leading pattern +x=$HOME/src/cmd +recho ${x#$HOME} + +# remove longest leading pattern +x=/one/two/three +recho ${x##*/} + +# and no match thrown in for good measure +recho ${x#nomatch} + +foo=abcdefg + +# fail +echo ${foo%ab} +echo ${foo%def} + +echo ${foo#fg} +echo ${foo#def} + +# succeed +echo ${foo#ab} +echo ${foo#def} + +echo ${foo%fg} +echo ${foo%def} diff --git a/tests/exp5.sub b/tests/exp5.sub index 9346b579..52dd4a15 100644 --- a/tests/exp5.sub +++ b/tests/exp5.sub @@ -1,15 +1,14 @@ # expansions involving patterns - var='[hello' echo "${var//[/}" red='\[\e[0;31m\]' -echo "${red//\\[\\e/}" +printf "%s\n" "${red//\\[\\e/}" foo="${red//\\[\\e/}" # foo == [0;31m\] -echo "${foo//[0;31m\\/}" +printf "%s\n" "${foo//[0;31m\\/}" echo "${var//[]/}" echo "${red//[]/}" diff --git a/tests/exp8.sub b/tests/exp8.sub index 99340838..ff44febc 100644 --- a/tests/exp8.sub +++ b/tests/exp8.sub @@ -10,11 +10,11 @@ declare -p var | sed -n l recho ${var@Q} recho ${var@P} -echo ${var@A} +echo -E ${var@A} unset array array=( [$'x\001y\177z']=foo ) # should be error -echo ${array[@]@A} +echo -E ${array[@]@A} unset array declare -a array=([0]=$'x\001y\177z') @@ -23,9 +23,9 @@ declare -p array unset array array=( "$var" ) recho ${array[@]} -echo ${array[@]@A} +echo -E ${array[@]@A} unset array declare -A array array=( [$'x\001y\177z']=$'a\242b\002c' ) -echo ${array[@]@A} +echo -E ${array[@]@A} diff --git a/tests/extglob.right b/tests/extglob.right index efb7e5fb..691f6879 100644 --- a/tests/extglob.right +++ b/tests/extglob.right @@ -94,14 +94,23 @@ a ab a . .. . .. a.log +*(foo) +*(foo|bar) a.log ?(foo) a.log a.log . .. +. .. +a.log a.log .x .y .z a b c .x .y .z a b c a b c a b c +a b c +a b c +.x .y .z a b c +.x .y .z a b c +* diff --git a/tests/extglob.tests b/tests/extglob.tests index a51c4db1..32a6569f 100644 --- a/tests/extglob.tests +++ b/tests/extglob.tests @@ -374,4 +374,6 @@ ${THIS_SH} ./extglob3.sub ${THIS_SH} ./extglob4.sub +${THIS_SH} ./extglob5.sub + exit 0 diff --git a/tests/extglob1a.sub b/tests/extglob1a.sub index e029ea49..686dab74 100644 --- a/tests/extglob1a.sub +++ b/tests/extglob1a.sub @@ -12,5 +12,5 @@ echo a!(x) echo a*?(x) echo a?(x) -builtin cd / +builtin cd $OLDPWD rm -rf $TESTDIR diff --git a/tests/extglob3.sub b/tests/extglob3.sub index 94567ee9..3f51c40c 100644 --- a/tests/extglob3.sub +++ b/tests/extglob3.sub @@ -1,5 +1,5 @@ shopt -s extglob -DIR=/tmp/extglob-$$ +DIR=$TMPDIR/extglob-$$ mkdir $DIR cd $DIR @@ -7,15 +7,18 @@ touch a.log echo *(.) echo *(.)* +echo *(foo) +echo *(foo|bar) echo ?(foo)* echo ?(foo) echo *(foo)* echo @(|foo)* echo *(foo).* +echo *(foo|bar).* echo !(foo)* +echo !(foo|bar)* cd $OLDPWD rm -rf $DIR - diff --git a/tests/extglob4.sub b/tests/extglob4.sub index 2ec8f319..2b4c53c9 100644 --- a/tests/extglob4.sub +++ b/tests/extglob4.sub @@ -19,7 +19,14 @@ echo @(*|.!(|.)) # wrong, adds . and .. echo @(*|@(f)) # ?? echo @(*|@(ff)) -cd / +echo !(f) +echo !(f)!(f) + +shopt -s dotglob +echo @(*|@(f)) +echo @(*|@(ff)) + +cd $OLDPWD rm -rf $GTDIR [[ a = a*?(/)b ]] && echo bad match 1 diff --git a/tests/extglob5.sub b/tests/extglob5.sub new file mode 100644 index 00000000..d400f839 --- /dev/null +++ b/tests/extglob5.sub @@ -0,0 +1,18 @@ +# globignore extglob patterns containing colons -- problem until bash-4.2 + +: ${TMPDIR:=/tmp} +TESTDIR=$TMPDIR/bash-globignore-$$ +[ -d "$TESTDIR" ] || mkdir "$TESTDIR" + +cd "$TESTDIR" || exit 2 + +shopt -s extglob +GLOBIGNORE='+([^[:alnum:]]):@([-.,:; _]):[![:alnum:]]' + +touch ';' '++' +echo * + +rm ';' '++' + +cd $OLDPWD +rmdir $TESTDIR diff --git a/tests/getopts5.sub b/tests/getopts5.sub index 30614ef9..874b2810 100644 --- a/tests/getopts5.sub +++ b/tests/getopts5.sub @@ -2,7 +2,7 @@ getop () { - local OPTIND + local OPTIND=1 local OPTERR=1 echo getop: OPTERR=$OPTERR diff --git a/tests/glob.right b/tests/glob.right index 04a0fd5f..83b7bc7a 100644 --- a/tests/glob.right +++ b/tests/glob.right @@ -1,4 +1,61 @@ foo/bar foobar/bar +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +b +argv[1] = <A£\B> +argv[1] = <A> +argv[1] = <B> +argv[1] = <a£\b> +0000000 141 243 134 142 +0000004 +ok 6 +ok 7 +invalid bracket expression +== LANG=C == +[[:alpha:] +ok 1 +[a +[[:alpha:] +ok 2 +ok 3 +== LANG=en_US.UTF-8 == +[[:alpha:] +ok 1 +[a +[[:alpha:] +ok 2 +ok 3 +invalid character class +== LANG=C == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +== LANG=en_US.UTF-8 == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +invalid collating symbols +== LANG=C == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +== LANG=en_US.UTF-8 == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 argv[1] = <a> argv[2] = <abc> argv[3] = <abd> @@ -13,7 +70,7 @@ argv[2] = <abc> argv[3] = <abd> argv[4] = <abe> tmp/l1 tmp/l2 tmp/*4 tmp/l3 -./glob.tests: line 44: no match: tmp/*4 +./glob.tests: line 46: no match: tmp/*4 argv[1] = <bdir/> argv[1] = <*> argv[1] = <a*> diff --git a/tests/glob.tests b/tests/glob.tests index d32988bc..7ae51723 100644 --- a/tests/glob.tests +++ b/tests/glob.tests @@ -9,10 +9,12 @@ expect() # First, a test that bash-2.01.1 fails ${THIS_SH} ./glob1.sub +${THIS_SH} ./glob2.sub +${THIS_SH} ./glob3.sub MYDIR=$PWD # save where we are -TESTDIR=/tmp/glob-test +TESTDIR=$TMPDIR/glob-test-$$ mkdir $TESTDIR builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } rm -rf * diff --git a/tests/glob1.sub b/tests/glob1.sub index 8745cd99..6b3b8ad1 100644 --- a/tests/glob1.sub +++ b/tests/glob1.sub @@ -1,7 +1,10 @@ # bash-2.01.1 failed this test -FN=/tmp/bash-glob.$$ +: ${TMPDIR:=/var/tmp} + +FN=$TMPDIR/bash-glob.$$ mkdir $FN cd $FN + mkdir foo mkdir foobar touch foo/bar @@ -10,5 +13,5 @@ chmod 311 foo foobar echo f*/bar chmod 777 foo foobar -cd / +cd $OLDPWD rm -rf $FN diff --git a/tests/glob2.sub b/tests/glob2.sub new file mode 100644 index 00000000..d33013b6 --- /dev/null +++ b/tests/glob2.sub @@ -0,0 +1,44 @@ +. ./test-glue-functions + +var='ab\' + +case $var in +ab\\) echo ok 1;; +*) echo bad 1;; +esac + +case $var in +$var) echo ok 2;; +*) echo bad 2;; +esac + +case $var in +'ab\') echo ok 3;; +*) echo bad 3;; +esac + +[[ $var = $var ]] && echo ok 4 +[[ $var = $'ab\134' ]] && echo ok 5 + +LC_ALL=zh_HK.big5hkscs + +read a b c <<< $'\u3b1 b c\n' +echo $b +unset a b c + +export alpha=$'\u3b1' + +printf -v v 'A%sB' "$alpha" +recho "$v" +IFS=$alpha read a b c <<<"$v" +recho "$a" +recho "$b" +unset a b v + +recho "a${alpha}b" +printf "%s" "a${alpha}b" | LC_ALL=C od -b | _intl_normalize_spaces + +a=$'\u3b1' +[[ $a = $a ]] && echo ok 6 + +LC_ALL=zh_HK.big5hkscs ${THIS_SH} -c $'[[ \u3b1 = \u3b1 ]]' && echo ok 7 diff --git a/tests/glob3.sub b/tests/glob3.sub new file mode 100644 index 00000000..378234db --- /dev/null +++ b/tests/glob3.sub @@ -0,0 +1,123 @@ +: ${TMPDIR:=/var/tmp} +cd $TMPDIR + +matchfunc() +{ + echo == LANG=$LANG == + + touch a p + echo [[:alpha:] + rm a p + + case l in + [[:alpha:]) echo bad 1;; + *) echo ok 1;; + esac + + touch '[a' '[x' + echo [[:alpha:] + rm '[a' + echo [[:alpha:] + rm '[x' + + case [a in + [[:alpha:]) echo ok 2;; + *) echo bad 2;; + esac + + case [x in + [[:alpha:]) echo bad 3;; + *) echo ok 3;; + esac +} + +echo invalid bracket expression +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc + +unset -f matchfunc + +matchfunc() +{ + echo == LANG=$LANG == + + case a] in + [[:aleph:]]) echo bad 1;; + *) echo ok 1;; + esac + + case a in + [[:aleph:]]) echo bad 2;; + *) echo ok 2;; + esac + + case a] in + [[:"alpha":]]) echo bad 3;; + *) echo ok 3;; + esac + + case a in + [[:"alpha":]]) echo bad 4;; + *) echo ok 4;; + esac + + case a in + [abc[:foo:]]) echo ok 5;; + *) echo bad 5 ;; + esac + + case a in + [[:foo:]abc]) echo ok 6;; + *) echo bad 6 ;; + esac +} + +echo invalid character class +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc + +unset -f matchfunc + +matchfunc() +{ + echo == LANG=$LANG == + + case h in + [[.hyphen.]) echo bad 1;; + *) echo ok 1;; + esac + + case - in + [[.hyphen.]]) echo ok 2;; + *) echo bad 2;; + esac + + case slash in + [[.slash.]]) echo bad 3;; + *) echo ok 3;; + esac + + case a in + [abc[.nonsense.]]) echo ok 4;; + *) echo bad 4 ;; + esac + + case a in + [[.nonsense.]abc]) echo ok 5;; + *) echo bad 5 ;; + esac +} + +echo invalid collating symbols + +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc diff --git a/tests/globstar2.sub b/tests/globstar2.sub index f4bb1b1c..4e1a0245 100644 --- a/tests/globstar2.sub +++ b/tests/globstar2.sub @@ -1,5 +1,6 @@ olddir=$PWD -EMPTY=/tmp/empty +: ${TMPDIR:=/var/tmp} +EMPTY=$TMPDIR/empty shopt -s globstar s() diff --git a/tests/heredoc.right b/tests/heredoc.right index 137a2956..f6541dca 100644 --- a/tests/heredoc.right +++ b/tests/heredoc.right @@ -20,7 +20,7 @@ jkl mno fff is a function fff () { - ed /tmp/foo > /dev/null <<ENDOFINPUT + ed ${TMPDIR}/foo <<ENDOFINPUT > /dev/null /^name/d w q @@ -31,7 +31,7 @@ ENDOFINPUT fff is a function fff () { - ed /tmp/foo > /dev/null <<ENDOFINPUT + ed ${TMPDIR}/foo <<ENDOFINPUT > /dev/null /^name/d w q @@ -43,11 +43,11 @@ foo is a function foo () { echo; - cat <<END + cat <<END bar END - cat <<EOF + cat <<EOF qux EOF @@ -59,13 +59,13 @@ qux bar qux abc def geh -./heredoc3.sub: line 9: warning: here-document at line 7 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 10: warning: here-document at line 8 delimited by end-of-file (wanted `EOF') = here is the text = -./heredoc3.sub: line 15: warning: here-document at line 13 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 16: warning: here-document at line 14 delimited by end-of-file (wanted `EOF') this paren ) is not a problem -./heredoc3.sub: line 21: warning: here-document at line 19 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 22: warning: here-document at line 20 delimited by end-of-file (wanted `EOF') these balanced parens ( ) are not a problem -./heredoc3.sub: line 27: warning: here-document at line 25 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 28: warning: here-document at line 26 delimited by end-of-file (wanted `EOF') quoted balanced parens \( ) are not a problem either more text in a subshell some more text in a different subshell @@ -82,8 +82,16 @@ end helloEND hello \END end hello<NL>\END -./heredoc3.sub: line 78: warning: here-document at line 76 delimited by end-of-file (wanted `EOF') -./heredoc3.sub: line 79: syntax error: unexpected end of file +./heredoc3.sub: line 85: warning: here-document at line 83 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 86: syntax error: unexpected end of file +heredoc1 +EOF +Ok:0 +argv[1] = <onetwo> +argv[2] = <threefour> +argv[1] = <two> +argv[2] = <threefi> +argv[3] = <ve> comsub here-string ./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF') hi diff --git a/tests/heredoc.tests b/tests/heredoc.tests index ebc770ac..303949f4 100644 --- a/tests/heredoc.tests +++ b/tests/heredoc.tests @@ -59,22 +59,22 @@ cat <<- EOF EOF # check appending of text to file from here document -rm -f /tmp/bash-zzz -cat > /tmp/bash-zzz << EOF +rm -f ${TMPDIR}/bash-zzz +cat > ${TMPDIR}/bash-zzz << EOF abc EOF -cat >> /tmp/bash-zzz << EOF +cat >> ${TMPDIR}/bash-zzz << EOF def ghi jkl mno EOF -cat /tmp/bash-zzz -rm -f /tmp/bash-zzz +cat ${TMPDIR}/bash-zzz +rm -f ${TMPDIR}/bash-zzz # make sure command printing puts the here-document as the last redirection # on the line, and the function export code preserves syntactic correctness fff() { - ed /tmp/foo <<ENDOFINPUT >/dev/null + ed ${TMPDIR}/foo <<ENDOFINPUT >/dev/null /^name/d w q @@ -90,8 +90,8 @@ ${THIS_SH} ./heredoc1.sub # test heredocs in command substitutions ${THIS_SH} ./heredoc2.sub - ${THIS_SH} ./heredoc3.sub +${THIS_SH} ./heredoc4.sub echo $( cat <<< "comsub here-string" diff --git a/tests/heredoc3.sub b/tests/heredoc3.sub index baf91c14..a5a2fbc0 100644 --- a/tests/heredoc3.sub +++ b/tests/heredoc3.sub @@ -1,4 +1,5 @@ SAVEPWD=$PWD +: ${TMPDIR:=/tmp} cd $TMPDIR || echo "heredoc3.sub: cannot cd to $TMPDIR" >&2 text=$(cat <<EOF @@ -69,7 +70,13 @@ cat <<END hello \END END -echo end 'hello<NL>\END' +echo -E end 'hello<NL>\END' + +# gprof +if [ -n "$GMON_OUT_PREFIX" ]; then + mv ${GMON_OUT_PREFIX}.[0-9]* "$SAVEPWD" >/dev/null 2>&1 +fi +cd "$SAVEPWD" # this has to be last -- results in a syntax error # doesn't currently parse because EOF is not on a line by itself -- should it? diff --git a/tests/heredoc4.sub b/tests/heredoc4.sub new file mode 100644 index 00000000..381b64a9 --- /dev/null +++ b/tests/heredoc4.sub @@ -0,0 +1,12 @@ +cat <<EO`true`F +heredoc1 +EO`false`F +EO`true`F +echo Ok:$? + +one=one +four=four +five='fi ve' + +recho $one`echo two three`$four +recho `echo two three`$five diff --git a/tests/histexp.right b/tests/histexp.right index ed6e0894..bcf5dea6 100644 --- a/tests/histexp.right +++ b/tests/histexp.right @@ -8,7 +8,7 @@ echo $BASH_VERSION 2 /bin/sh -c 'echo this is $0' 3 ls 4 echo $BASH_VERSION - 5 HISTFILE=/tmp/newhistory + 5 HISTFILE=$TMPDIR/newhistory 6 echo line 2 for history echo line 2 for history echo line 2 for history @@ -19,7 +19,7 @@ line 2 for history 2 /bin/sh -c 'echo this is $0' 3 ls 4 echo $BASH_VERSION - 5 HISTFILE=/tmp/newhistory + 5 HISTFILE=$TMPDIR/newhistory 6 echo line 2 for history 7 set -H 8 echo line 2 for history @@ -181,6 +181,15 @@ echo g g eval echo "echo g" echo g +h +echo \!\! `echo echo h` +!! echo h +i +echo echo i `echo echo i` +echo i echo i +j +echo `echo j` echo j +j echo j a cat < <(echo echo a) echo a diff --git a/tests/histexp.tests b/tests/histexp.tests index 99c7520d..2901064f 100644 --- a/tests/histexp.tests +++ b/tests/histexp.tests @@ -1,6 +1,6 @@ LC_ALL=C LANG=C -trap 'rm /tmp/newhistory' 0 +trap 'rm $TMPDIR/newhistory' 0 file=bax histchars='!^#' # make sure history comment char is set correctly @@ -25,7 +25,7 @@ history -p '!!:z' history -HISTFILE=/tmp/newhistory +HISTFILE=$TMPDIR/newhistory history -a history -w diff --git a/tests/histexp3.sub b/tests/histexp3.sub index ae2b4986..495f0952 100644 --- a/tests/histexp3.sub +++ b/tests/histexp3.sub @@ -31,5 +31,14 @@ echo "!!" echo g eval echo "!!" +echo h +echo \!\! `echo !!` + +echo i +echo !! `echo !!` + +echo j +echo `echo j` !! + set +o history rm -f $HISTFILE # just in case diff --git a/tests/history.right b/tests/history.right index de8e22b4..d83fc718 100644 --- a/tests/history.right +++ b/tests/history.right @@ -36,13 +36,13 @@ echo line for history echo line for history displaying $HISTFILE after history -a echo line for history -HISTFILE=/tmp/newhistory +HISTFILE=$TMPDIR/newhistory 1 for i in one two three; do echo $i; done 2 /bin/sh -c 'echo this is $0' 3 ls 4 echo $BASH_VERSION 5 echo line for history - 6 HISTFILE=/tmp/newhistory + 6 HISTFILE=$TMPDIR/newhistory 7 echo displaying \$HISTFILE after history -a 8 cat $HISTFILE for i in one two three; do echo $i; done @@ -50,7 +50,7 @@ for i in one two three; do echo $i; done ls echo $BASH_VERSION echo line for history -HISTFILE=/tmp/newhistory +HISTFILE=$TMPDIR/newhistory echo displaying \$HISTFILE after history -a cat $HISTFILE 1 for i in one two three; do echo $i; done @@ -58,7 +58,7 @@ cat $HISTFILE 3 ls 4 echo $BASH_VERSION 5 echo line for history - 6 HISTFILE=/tmp/newhistory + 6 HISTFILE=$TMPDIR/newhistory 7 echo displaying \$HISTFILE after history -a 8 cat $HISTFILE 9 echo line 2 for history @@ -69,7 +69,7 @@ echo line 2 for history 3 ls 4 echo $BASH_VERSION 5 echo line for history - 6 HISTFILE=/tmp/newhistory + 6 HISTFILE=$TMPDIR/newhistory 7 echo displaying \$HISTFILE after history -a 8 cat $HISTFILE 9 echo line 2 for history @@ -80,7 +80,7 @@ echo line 2 for history line 2 for history 4 echo $BASH_VERSION 5 echo line for history -6 HISTFILE=/tmp/newhistory +6 HISTFILE=$TMPDIR/newhistory 7 echo displaying \$HISTFILE after history -a 8 cat $HISTFILE 9 echo line 2 for history @@ -94,10 +94,10 @@ line 2 for history 17 unset HISTFILE 4 echo $BASH_VERSION 5 echo line for history -6 HISTFILE=/tmp/newhistory +6 HISTFILE=$TMPDIR/newhistory 7 echo displaying \$HISTFILE after history -a 8 cat $HISTFILE -./history.tests: line 75: fc: history specification out of range +./history.tests: line 76: fc: history specification out of range 14 set -H 15 echo line 2 for history 16 unset HISTSIZE @@ -107,7 +107,7 @@ echo xx xb xc xx xb xc echo 44 48 4c 44 48 4c -./history.tests: line 90: fc: no command found +./history.tests: line 91: fc: no command found aa bb cc @@ -140,7 +140,41 @@ three one two three -4.4 +5.0 echo ${BASH_VERSION%\.*} -4.4 +5.0 echo ${BASH_VERSION%\.*} +a +b +c +d +e + 1 echo a + 2 echo b + 3 echo c + 4 echo d + 5 echo e + + 1 echo a + 2 echo e +f +g +h +i + 1 echo a + 2 echo e + 3 echo f + 4 echo g + 5 echo h + +./history3.sub: line 27: history: 16: history position out of range +./history3.sub: line 28: history: 200: history position out of range +./history3.sub: line 29: history: -20: history position out of range +./history3.sub: line 30: history: -50: history position out of range +./history3.sub: line 31: history: 5-0xaf: history position out of range + 1 echo a + 2 echo e + 3 echo f + 4 echo g + 5 echo h + diff --git a/tests/history.tests b/tests/history.tests index f976fbdf..4001bd6c 100644 --- a/tests/history.tests +++ b/tests/history.tests @@ -1,4 +1,4 @@ -trap 'rm /tmp/newhistory' 0 +trap 'rm $TMPDIR/newhistory' 0 # bad options history -x @@ -20,6 +20,7 @@ HISTFILE=history.list HISTCONTROL=ignoreboth HISTIGNORE='&:history*:fc*' HISTSIZE=32 +export HISTIGNORE shopt -s cmdhist set -o history @@ -39,7 +40,7 @@ history -p '!!' fc -nl -HISTFILE=/tmp/newhistory +HISTFILE=$TMPDIR/newhistory history -a echo displaying \$HISTFILE after history -a cat $HISTFILE @@ -112,3 +113,4 @@ ${THIS_SH} ./history1.sub rm -f $TMPDIR/foohist-* ${THIS_SH} ./history2.sub +${THIS_SH} ./history3.sub diff --git a/tests/history3.sub b/tests/history3.sub new file mode 100644 index 00000000..8722666c --- /dev/null +++ b/tests/history3.sub @@ -0,0 +1,36 @@ +: ${TMPDIR:=/tmp} + +set -o history +HISTFILE=$TMPDIR/history-$$ + +history -c + +echo a +echo b +echo c +echo d +echo e + +history ; echo + +history -d 2-4 + +history + +echo f +echo g +echo h +echo i +history -d 6--1 +history ; echo + +history -d 16-40 +history -d 1-200 +history -d -20-50 +history -d 1--50 +history -d 5-0xaf + +history ; echo + +unset HISTFILE +exit 0 diff --git a/tests/ifs.right b/tests/ifs.right index 512f6ee5..465efcf0 100644 --- a/tests/ifs.right +++ b/tests/ifs.right @@ -8,3 +8,5 @@ a:b:c:d:e a:b:c:d:e a b c d e a b c d e +argv[1] = <file> +argv[1] = <*> diff --git a/tests/ifs.tests b/tests/ifs.tests index 763e2a00..71769005 100644 --- a/tests/ifs.tests +++ b/tests/ifs.tests @@ -59,3 +59,5 @@ IFS=: export x echo $x IFS="$DEFIFS" + +${THIS_SH} ./ifs1.sub diff --git a/tests/ifs1.sub b/tests/ifs1.sub new file mode 100644 index 00000000..6ea489af --- /dev/null +++ b/tests/ifs1.sub @@ -0,0 +1,14 @@ +: ${TMPDIR:=/tmp} +dir=bashtest-$$ + +mkdir $TMPDIR/$dir || exit 1 +touch $TMPDIR/$dir/file || exit 2 +cd $TMPDIR/$dir || exit 3 + +IFS='?*[]' +recho * + +recho "*" + +cd $OLDPWD +rm -rf $TMPDIR/$dir diff --git a/tests/jobs.right b/tests/jobs.right index c3ee9443..0e9d1d19 100644 --- a/tests/jobs.right +++ b/tests/jobs.right @@ -16,31 +16,32 @@ Waiting for job 6 job 6 returns 0 Waiting for job 7 job 7 returns 0 -[1] Running sleep 5 & -[2] Running sleep 5 & -[3] Running sleep 5 & -[4]- Running sleep 5 & -[5]+ Running ( sleep 5; exit 4 ) & +[1] Running sleep 2 & +[2] Running sleep 2 & +[3] Running sleep 2 & +[4]- Running sleep 2 & +[5]+ Running ( sleep 2; exit 4 ) & 4 0 i killed it 12 [1]- Running sleep 20 & [3]+ Running sleep 20 & +child1 exit status 0 0 -./jobs.tests: line 22: wait: %1: no such job -./jobs.tests: line 27: fg: no job control +./jobs.tests: line 25: wait: %1: no such job +./jobs.tests: line 30: fg: no job control wait-for-pid wait-errors -./jobs.tests: line 40: wait: `1-1': not a pid or valid job spec -./jobs.tests: line 41: wait: `-4': not a pid or valid job spec +./jobs.tests: line 43: wait: `1-1': not a pid or valid job spec +./jobs.tests: line 44: wait: `-4': not a pid or valid job spec wait-for-background-pids async list wait-for-background-pids async list wait for child forked wait-when-no-children wait-for-job -./jobs.tests: line 63: wait: %2: no such job +./jobs.tests: line 66: wait: %2: no such job 127 async list wait-for-job forked @@ -53,19 +54,19 @@ sleep 5 fg-bg 4 sleep 5 fg-bg 5 -./jobs.tests: line 90: fg: %2: no such job -./jobs.tests: line 91: bg: job 1 already in background +./jobs.tests: line 93: fg: %2: no such job +./jobs.tests: line 94: bg: job 1 already in background fg-bg 6 -./jobs.tests: line 98: fg: -s: invalid option +./jobs.tests: line 101: fg: -s: invalid option fg: usage: fg [job_spec] -./jobs.tests: line 99: bg: -s: invalid option +./jobs.tests: line 102: bg: -s: invalid option bg: usage: bg [job_spec ...] -./jobs.tests: line 104: disown: -s: invalid option +./jobs.tests: line 107: disown: -s: invalid option disown: usage: disown [-h] [-ar] [jobspec ... | pid ...] -./jobs.tests: line 108: disown: %1: no such job -./jobs.tests: line 111: disown: %2: no such job +./jobs.tests: line 111: disown: %1: no such job +./jobs.tests: line 114: disown: %2: no such job wait-for-non-child -./jobs.tests: line 114: wait: pid 1 is not a child of this shell +./jobs.tests: line 117: wait: pid 1 is not a child of this shell 127 3 -- 1 2 3 -- 1 - 2 - 3 [1] Running sleep 300 & @@ -75,8 +76,8 @@ running jobs: [1] Running sleep 300 & [2]- Running sleep 350 & [3]+ Running sleep 400 & -./jobs.tests: line 131: kill: %4: no such job -./jobs.tests: line 133: jobs: %4: no such job +./jobs.tests: line 134: kill: %4: no such job +./jobs.tests: line 136: jobs: %4: no such job current job: [3]+ Running sleep 400 & previous job: diff --git a/tests/jobs.tests b/tests/jobs.tests index c99f4f71..3c2eef31 100644 --- a/tests/jobs.tests +++ b/tests/jobs.tests @@ -15,6 +15,9 @@ ${THIS_SH} ./jobs4.sub # test out wait -n framework ${THIS_SH} ./jobs5.sub +# test out wait -f framework +${THIS_SH} ./jobs6.sub + jobs echo $? diff --git a/tests/jobs1.sub b/tests/jobs1.sub index aa9a3726..53f66cc6 100644 --- a/tests/jobs1.sub +++ b/tests/jobs1.sub @@ -2,7 +2,7 @@ set -m sleep 60 & -FN=/tmp/jobs-pid.$$ +FN=$TMPDIR/jobs-pid.$$ pid1=$! jobs -p %+ > $FN diff --git a/tests/jobs4.sub b/tests/jobs4.sub index 2eb4197a..898b449b 100644 --- a/tests/jobs4.sub +++ b/tests/jobs4.sub @@ -1,12 +1,12 @@ # test being able to use job control notation in jobs/kill/wait without # job control active, as the SUS requires -sleep 5 & +sleep 2 & -sleep 5 & -sleep 5 & -sleep 5 & -(sleep 5 ; exit 4) & +sleep 2 & +sleep 2 & +sleep 2 & +(sleep 2 ; exit 4) & jobs diff --git a/tests/jobs6.sub b/tests/jobs6.sub new file mode 100644 index 00000000..9ed59ee5 --- /dev/null +++ b/tests/jobs6.sub @@ -0,0 +1,14 @@ +# framework to test `wait -f' which forces wait until a job exits +set -o monitor +sleep 5 & +child1=$! + +( sleep 1; kill -STOP $child1 ; sleep 1 ; kill -CONT $child1 )& + +child2=$! + +wait -f %1 +echo child1 exit status $? + +wait $child2 +exit 0 diff --git a/tests/more-exp.tests b/tests/more-exp.tests index 4a3cb7f5..10b3a47e 100644 --- a/tests/more-exp.tests +++ b/tests/more-exp.tests @@ -152,7 +152,7 @@ b1() b2() { recho $* - recho $# + recho ${#} } expect '<1>' @@ -414,7 +414,7 @@ recho ${#} expect '<5>' recho ${#?:-xyz} -shift $# +shift ${#} expect '<0>' recho ${#:-foo} diff --git a/tests/nameref.right b/tests/nameref.right index 53002595..2ab62b09 100644 --- a/tests/nameref.right +++ b/tests/nameref.right @@ -48,7 +48,7 @@ argv[1] = <unset> expect <bar> argv[1] = <bar> expect <unset> -argv[1] = <unset> +./nameref3.sub: line 16: foo: invalid indirect expansion ./nameref3.sub: line 21: unset: bar: cannot unset: readonly variable expect <two> two @@ -226,6 +226,13 @@ declare -r RO="x" ./nameref11.sub: line 39: declare: RO_PID: not found ./nameref11.sub: line 41: RO2: readonly variable declare -r RO2="a" +2 +./nameref11.sub: line 52: typeset: `2': invalid variable name for name reference +2 +./nameref11.sub: line 57: typeset: `2': invalid variable name for name reference +2 +./nameref11.sub: line 62: foo[2]: invalid indirect expansion +./nameref11.sub: line 63: bar: invalid indirect expansion ./nameref12.sub: line 6: declare: `/': invalid variable name for name reference ./nameref12.sub: line 9: declare: `%': invalid variable name for name reference ./nameref12.sub: line 13: `^': not a valid identifier @@ -306,30 +313,38 @@ declare -a b=([0]="0") ./nameref15.sub: line 19: warning: ref: circular name reference ./nameref15.sub: line 20: warning: ref: circular name reference ./nameref15.sub: line 21: warning: ref: circular name reference -inside +inside X outside X -./nameref15.sub: line 29: typeset: ref: nameref variable self references not allowed -./nameref15.sub: line 31: ref: nameref variable self references not allowed +before: 7 +./nameref15.sub: line 32: typeset: warning: xxx: circular name reference +./nameref15.sub: line 32: warning: xxx: circular name reference +./nameref15.sub: line 33: warning: xxx: circular name reference +declare -n xxx="xxx" +./nameref15.sub: line 35: warning: xxx: circular name reference +xxx_func: inside: xxx = foo +after: foo +./nameref15.sub: line 46: typeset: ref: nameref variable self references not allowed +./nameref15.sub: line 48: ref: nameref variable self references not allowed declare -n ref="re" declare -n ref="re" declare -- re="4" 4 declare -n foo="var[@]" declare -n ref="var[@]" -./nameref15.sub: line 48: var[@]: bad array subscript +./nameref15.sub: line 65: var[@]: bad array subscript declare -n bar="var[@]" -./nameref15.sub: line 53: var[@]: bad array subscript +./nameref15.sub: line 70: var[@]: bad array subscript declare -n a="b" declare -n b="a[1]" -./nameref15.sub: line 61: warning: a: removing nameref attribute +./nameref15.sub: line 78: warning: a: removing nameref attribute declare -a a=([1]="foo") declare -n b="a[1]" -./nameref15.sub: line 66: warning: a: removing nameref attribute +./nameref15.sub: line 83: warning: a: removing nameref attribute declare -a a=([1]="foo") declare -n b="a[1]" declare -n n="v" declare -a v=([1]="1") -./nameref15.sub: line 82: typeset: n: not found +./nameref15.sub: line 99: typeset: n: not found declare -a v=([0]="0" [1]="1") declare -n n="v[1]" declare -a v=([0]="0") @@ -409,3 +424,19 @@ declare -a var=([123]="") declare -n ref="var[123]" ./nameref18.sub: line 54: declare: var[123]: not found declare -a var=([123]="X") +declare -n foo="bar" +declare -- foo="bar" +./nameref19.sub: line 9: declare: bar: not found +declare -n foo="bar" +declare -- foo="bar" +declare -i bar="11" +declare -inx foo6 +declare -ix foo6 +declare -n foo="bar" +declare -- bar="Hello World!" +declare -- foo="bar" +declare -- bar="Hello World!" +declare -n foo="bar" +declare -- bar +declare -- foo="bar" +declare -- bar diff --git a/tests/nameref11.sub b/tests/nameref11.sub index 85feedfa..402e5015 100644 --- a/tests/nameref11.sub +++ b/tests/nameref11.sub @@ -39,3 +39,25 @@ unset -n ref ; unset ref declare -r RO RO_PID; coproc RO { :; }; declare -p RO_PID; wait; declare -p RO RO_PID declare -r RO2=a; declare -n ref_PID=RO2; coproc ref { :; }; wait; declare -p RO2 + +unset x y +set -- one two three + +y=2 +typeset -n x=y +echo ${x} + +unset -n x + +typeset -n y +echo $y + +unset -n y + +typeset -n y +y=2 +echo ${y} + +declare -n foo=bar +echo ${!foo[2]} +echo ${!bar} diff --git a/tests/nameref15.sub b/tests/nameref15.sub index 6c9ace5e..9fbacd4f 100644 --- a/tests/nameref15.sub +++ b/tests/nameref15.sub @@ -26,6 +26,23 @@ add_X_echo ref echo outside "$ref" unset ref +# same test, but assigning nameref variable circular reference directly +xxx_func() +{ + typeset -n xxx=xxx + xxx=foo + declare -p xxx + echo $FUNCNAME: inside: xxx = $xxx +} + +xxx=7 +echo before: $xxx +xxx_func +echo after: $xxx + +unset xxx +unset -f xxx_func + typeset -n ref=ref typeset -n ref=re ref+=f @@ -85,4 +102,3 @@ v=(0 1) declare -n n=v[1] unset n declare -p n v - diff --git a/tests/nameref19.sub b/tests/nameref19.sub new file mode 100644 index 00000000..d46c003f --- /dev/null +++ b/tests/nameref19.sub @@ -0,0 +1,51 @@ +# can we unset the nameref attribute on variables with values that reference +# unset variables? + +unset bar +declare -n foo="bar" +declare -p foo + +declare +n foo +declare -p foo bar + +declare -n foo +declare -p foo + +# let's try removing the nameref attribute -- other attributes and assignments +# apply to the nameref target + +declare +n -i foo=7+4 +declare -p foo bar + +unset foo bar + +# but if the nameref variable doesn't have a value, the attributes apply to +# the nameref variable itself. thanks ksh93 + +declare -n foo6 +declare -xi foo6 +declare -p foo6 + +# and when we remove the nameref attribute, the other attributes remain + +declare +n foo6 +declare -p foo6 + +unset foo6 + +# make sure these cases continue to work + +# nameref referencing an existing, set variable +declare -n foo=bar +bar='Hello World!' +declare -p foo bar +declare +n foo +declare -p foo bar +unset foo bar + +# nameref referencing an existing, unset variable +declare -n foo=bar +declare bar +declare -p foo bar +declare +n foo +declare -p foo bar diff --git a/tests/new-exp.right b/tests/new-exp.right index 9913fbd6..12fc18dd 100644 --- a/tests/new-exp.right +++ b/tests/new-exp.right @@ -169,11 +169,11 @@ lines. This-string-has-multiple-lines. this is a test of proc subst this is test 2 -./new-exp2.sub: line 31: /tmp/bashtmp.x*: No such file or directory -./new-exp2.sub: line 35: /tmp/redir-notthere: No such file or directory +a +./new-exp2.sub: line 42: /tmp/redir-notthere: No such file or directory 1 -./new-exp2.sub: line 42: 1111111111111111111111: command not found +./new-exp2.sub: line 49: 1111111111111111111111: command not found argv[1] = <6> ./new-exp.tests: line 285: ${#:}: bad substitution @@ -624,7 +624,7 @@ c Sub = 0 2 4 8 <'ab cd'> <'4'> <'ab cd'> <> -argv[1] = <host(2)[4.4]$ > +argv[1] = <host(2)[5.0]$ > < > <' \t\n'> @@ -643,6 +643,26 @@ ir a b c d e 5 a5b +abcxxxdef +abcÃ¥def +ḅć +Ã¥ +prependḅć +Ã¥append +prependÃ¥ +ḅćappend +Ã¥ +ḅć +ḅć +ḅć +Ã¥ +Ã¥ +Ã¥ +ḅć +Ã¥ +Ã¥ +ḅć +ḅć argv[1] = </> argv[1] = </> -./new-exp.tests: line 608: ABXD: parameter unset +./new-exp.tests: line 611: ABXD: parameter unset diff --git a/tests/new-exp.tests b/tests/new-exp.tests index c4aa9d16..31e15468 100644 --- a/tests/new-exp.tests +++ b/tests/new-exp.tests @@ -340,7 +340,7 @@ recho "${foo:-$@}" expect '<ab> <cd> <ef> <gh>' recho "${foo:-"$@"}" -shift $# +shift ${#} expect nothing recho $xxx"$@" expect nothing @@ -498,7 +498,7 @@ recho ${*%?} recho ${@#?} recho ${*#?} -shift $# +shift ${#} set -u ( recho $9 ; echo after 1) ( recho ${9} ; echo after 2) @@ -597,6 +597,9 @@ ${THIS_SH} ./new-exp9.sub # new parameter transformation `@' expansion operator ${THIS_SH} ./new-exp10.sub +# parameter substring replacement and removal operators with multibyte chars +${THIS_SH} ./new-exp11.sub + # problems with stray CTLNUL in bash-4.0-alpha unset a a=/a diff --git a/tests/new-exp1.sub b/tests/new-exp1.sub index c015c223..2b621fca 100644 --- a/tests/new-exp1.sub +++ b/tests/new-exp1.sub @@ -1,3 +1,4 @@ +FN=${TMPDIR}/bashtest-$$ expect() { echo expect "$@" @@ -5,7 +6,11 @@ expect() expect this is a test of proc subst cat <(echo this is a test of proc subst) -echo this is test 2 > /tmp/x +echo this is test 2 > $FN expect this is test 2 -cat <(cat /tmp/x) -rm -f /tmp/x +cat <(cat $FN) +rm -f $FN + +foo= +expect a +cat ${foo:-<(echo a)} diff --git a/tests/new-exp11.sub b/tests/new-exp11.sub new file mode 100644 index 00000000..da6b4e1f --- /dev/null +++ b/tests/new-exp11.sub @@ -0,0 +1,46 @@ +# pattern matching and replacement operators with multibyte characters + +LANG=en_US.UTF-8 + +s1='abcÃ¥def' +s2='Ã¥' +s3='ḅć' + +s23=${s2}${s3} + +echo ${s1/$s2/xxx} +echo ${s1/$s3/xxx} + +echo ${s23/#$s2/} +echo ${s23/%$s3/} + +echo ${s23/#$s2/prepend} +echo ${s23/%$s3/append} + +echo ${s2/#/prepend} +echo ${s3/%/append} + +echo ${s2/#/} +echo ${s3/%/} + +recho ${s2/$s2/} +recho ${s3/$s3/} + +# posix pattern replacements + +echo ${s23##$s2} +echo ${s23#$s2} + +echo ${s23%%$s3} +echo ${s23%$s3} + +# fail + +echo ${s2/#ab/xx} +echo ${s3/%ab/xx} + +echo ${s2#ab} +echo ${s2##ab} + +echo ${s3%ab} +echo ${s3%%ab} diff --git a/tests/new-exp2.sub b/tests/new-exp2.sub index e8377799..ea52b3ce 100644 --- a/tests/new-exp2.sub +++ b/tests/new-exp2.sub @@ -4,7 +4,7 @@ export LANG=C # test out the new $(< filename) code # it should be exactly equivalent to $(cat filename) -FILENAME=/tmp/bashtmp.x$$ +FILENAME=$TMPDIR/bashtmp.x$$ trap 'rm -f $FILENAME' 0 @@ -21,17 +21,24 @@ if [[ $LINES1 != $LINES2 ]]; then echo 'whoops: $(< filename) failed' fi -LINES2=$(< /tmp/bashtmp.x*) +LINES2=$(< $TMPDIR/bashtmp.x*) if [[ $LINES1 != $LINES2 ]]; then echo 'whoops: $(< filename) with glob expansion failed' fi # but the glob expansion in the redirection should fail in posix mode set -o posix -LINES2=$(< /tmp/bashtmp.x*) +exec 3>&2 +exec 2>/dev/null +LINES2=$(< $TMPDIR/bashtmp.x*) +exec 2>&3 +if [[ $LINES2 -gt 0 ]]; then + echo "whoops: redirection glob expansion should be disabled in posix mode" >&2 +fi set +o posix # now see what happens when we try it with a non-existant file +rm -f /tmp/redir-notthere LINES3=$(< /tmp/redir-notthere) echo $? diff --git a/tests/parser.right b/tests/parser.right index 43d5a8ed..cecbb222 100644 --- a/tests/parser.right +++ b/tests/parser.right @@ -1 +1,16 @@ AAA +bash5: `invalid-name': not a valid identifier +in +in +in +in +bash5: -c: line 0: syntax error near unexpected token `)' +bash5: -c: line 0: `case x in esac) echo done; esac' +in +bash5: -c: line 0: syntax error near unexpected token `do' +bash5: -c: line 0: `case in do do) echo in; esac' +bash5: -c: line 0: syntax error near unexpected token `(' +bash5: -c: line 0: `for()' +in +done +ok 1 diff --git a/tests/parser.tests b/tests/parser.tests index 12ff88c2..6e020a4b 100644 --- a/tests/parser.tests +++ b/tests/parser.tests @@ -2,3 +2,5 @@ # this has to be in a separate file to get desired EOF behavior ${THIS_SH} ./parser1.sub + +${THIS_SH} ./posix2syntax.sub diff --git a/tests/posix2syntax.sub b/tests/posix2syntax.sub new file mode 100644 index 00000000..e7dda58f --- /dev/null +++ b/tests/posix2syntax.sub @@ -0,0 +1,53 @@ +: ${THIS_SH:=./bash} +bashname=bash${BASH_VERSION%%.*} + +# tests for Posix grammar special cases + +# Posix grammar rule 5 +${THIS_SH} -c 'for invalid-name in a b c; do echo error; done' $bashname + +# Posix grammar rule 6: third word in FOR or SELECT +for i; do echo; done; echo in +for i; do echo in; done +for i do echo in; done + +select i; do echo; done; echo in +select i; do echo in; done; echo in +select i do echo in; done; echo in + +# Posix grammar rule 4: when PATTERN == ESAC, return ESAC +${THIS_SH} -c 'case x in esac) echo done; esac' $bashname + +# Posix grammar rule 6: third word in CASE +${THIS_SH} -c 'case in in in) echo in; esac;' $bashname +${THIS_SH} -c 'case in do do) echo in; esac' $bashname + +# Posix grammar rule 8: function NAME +${THIS_SH} -o posix -c 'for() +{ +echo function for; +}' $bashname + +for for in for; do echo in; echo done; done + +${THIS_SH} -c 'for (( i = 0; i < 5; i++ )) do : ; done' $bashname +${THIS_SH} -c 'for (( i = 0; i < 5; i++ )) { : ; }' $bashname + +# bug report: IN turning on unwanted alias expansion +${THIS_SH} -o posix -c ' +alias foo='two words' +foo_word='foo' +case "$foo_word" +in + foo) echo "bad 1";; +esac' $bashname + +${THIS_SH} -o posix -c ' +alias foo='oneword' +foo_word='foo' +case "$foo_word" +in + foo) echo "ok 1";; +esac' $bashname + + diff --git a/tests/posixexp.right b/tests/posixexp.right index 0ba6555a..1e81eadb 100644 --- a/tests/posixexp.right +++ b/tests/posixexp.right @@ -37,5 +37,243 @@ argv[1] = <'bar> argv[1] = <foo 'bar baz> argv[1] = <}z> argv[1] = <''z}> -./posixexp.tests: line 77: unexpected EOF while looking for matching `}' -./posixexp.tests: line 78: syntax error: unexpected end of file +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <12> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <12> +argv[1] = <12> +normal IFS +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +null IFS +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +argv[1] = < abc def ghi jkl > +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +non-standard IFS +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +argv[1] = < abc def ghi jkl > +argv[1] = < abc def ghi jkl > +unset IFS +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +argv[1] = < abc def ghi jkl > +argv[1] = < abc def ghi jkl > + +001: IFS = (unset): unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +002: IFS = (unset): unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +003: IFS = (unset): unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +004: IFS = (unset): foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +005: IFS = (unset): foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +006: IFS = (unset): foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +007: IFS = (unset): unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +008: IFS = (unset): unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +009: IFS = (unset): unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +010: IFS = (unset): foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +011: IFS = (unset): foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +012: IFS = (unset): foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del + +013: IFS = (null): unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +014: IFS = (null): unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +015: IFS = (null): unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +016: IFS = (null): foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +017: IFS = (null): foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +018: IFS = (null): foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +019: IFS = (null): unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +020: IFS = (null): unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +021: IFS = (null): unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +022: IFS = (null): foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +023: IFS = (null): foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +024: IFS = (null): foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del + +025: IFS = x: unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +026: IFS = x: unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +027: IFS = x: unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +028: IFS = x: foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +029: IFS = x: foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +030: IFS = x: foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +031: IFS = x: unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +032: IFS = x: unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +033: IFS = x: unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +034: IFS = x: foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +035: IFS = x: foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +036: IFS = x: foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del + +037: IFS = sp ht nl: unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +038: IFS = sp ht nl: unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +039: IFS = sp ht nl: unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +040: IFS = sp ht nl: foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +041: IFS = sp ht nl: foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +042: IFS = sp ht nl: foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +043: IFS = sp ht nl: unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +044: IFS = sp ht nl: unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +045: IFS = sp ht nl: unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +046: IFS = sp ht nl: foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +047: IFS = sp ht nl: foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +048: IFS = sp ht nl: foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +[ abc def ghi jkl / abc def ghi jkl ] +[ abc def ghi jkl ] +[ abc def ghi jkl / abc def ghi jkl / abc def ghi jkl ] +./posixexp.tests: line 82: unexpected EOF while looking for matching `}' +./posixexp.tests: line 83: syntax error: unexpected end of file diff --git a/tests/posixexp.tests b/tests/posixexp.tests index 60be1c74..76dfede9 100644 --- a/tests/posixexp.tests +++ b/tests/posixexp.tests @@ -72,6 +72,11 @@ ${THIS_SH} ./posixexp1.sub || echo "bash posixexp1.sub: test $? failed" THIS_SH=$TMPDIR/sh ${THIS_SH} ./posixexp2.sub || echo "sh posixexp2.sub: test $? failed" rm -f $TMPDIR/sh +${THIS_SH} ./posixexp3.sub +${THIS_SH} ./posixexp4.sub +${THIS_SH} ./posixexp5.sub +${THIS_SH} ./posixexp6.sub + # this will be an error foo=bar echo "${foo:-"a}" diff --git a/tests/posixexp2.sub b/tests/posixexp2.sub index f48d0887..397769da 100644 --- a/tests/posixexp2.sub +++ b/tests/posixexp2.sub @@ -18,4 +18,7 @@ ${THIS_SH} -c 'echo ${1?}' 2>/dev/null && exit 11 ${THIS_SH} -c 'echo ${1?}' ${THIS_SH} x >/dev/null || exit 12 ${THIS_SH} -c 'echo ${2?}' ${THIS_SH} x 2>/dev/null && exit 13 ${THIS_SH} -c 'echo ${2?}' ${THIS_SH} x y >/dev/null || exit 14 + +${THIS_SH} -c $'echo $(( x+ )) \n exit 0' ${THIS_SH} 2>/dev/null && exit 15 + exit 0 diff --git a/tests/posixexp2.tests b/tests/posixexp2.tests index 57dd767d..2bec58e0 100644 --- a/tests/posixexp2.tests +++ b/tests/posixexp2.tests @@ -1,6 +1,6 @@ # From mksh -set -o posix +set -o posix ; shopt -u xpg_echo (echo 1 ${IFS+'}'z}) 2>&- || echo failed in 1 (echo 2 "${IFS+'}'z}") 2>&- || echo failed in 2 diff --git a/tests/posixexp3.sub b/tests/posixexp3.sub new file mode 100644 index 00000000..c40afa94 --- /dev/null +++ b/tests/posixexp3.sub @@ -0,0 +1,52 @@ +set -- 1 2 + +unset var +recho ${var-$@} +recho ${var-"$@"} +recho ${var-$*} +recho ${var-"$*"} + +unset -v a b c d +recho ${a=$@} +recho "$a" +recho ${b="$@"} +recho "$b" +recho ${c=$*} +recho "$c" +recho ${d="$*"} +recho "$d" + +IFS= +unset var +recho ${var-$@} +recho ${var-"$@"} +recho ${var-$*} +recho ${var-"$*"} + +unset -v a b c d +# Posix interp 221 +# there should never be any word splitting because IFS is null +recho ${a=$@} +recho "$a" +recho $a +recho ${b="$@"} +recho "$b" +recho $b +recho ${c=$*} +recho "$c" +recho $c +recho ${d="$*"} +recho "$d" +recho $d + +unset -v a b c d +a=$@ +recho $a +b="$@" +recho $b +c=$* +recho $c +d="$*" +recho $d + +unset -v parameter a b c d diff --git a/tests/posixexp4.sub b/tests/posixexp4.sub new file mode 100644 index 00000000..22bfeca8 --- /dev/null +++ b/tests/posixexp4.sub @@ -0,0 +1,31 @@ +set -- ' abc' 'def ghi' 'jkl ' + +echo normal IFS +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} + +echo null IFS +IFS= +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} + +echo non-standard IFS +IFS=: +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} # this is inconsistent + +echo unset IFS +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} diff --git a/tests/posixexp5.sub b/tests/posixexp5.sub new file mode 100644 index 00000000..cceeb00c --- /dev/null +++ b/tests/posixexp5.sub @@ -0,0 +1,51 @@ +# test suite contribution from Martijn Dekker + +defaultIFS=$IFS +set -o errexit -o noglob +(set -o pipefail) 2>/dev/null && set -o pipefail +teststring=$(printf '\1\2\3\177') +n=0 + +trim_od() { + od -a | sed -n '1 { s/^0*[[:blank:]]*//; s/[[:blank:]]*$//; p; }' +} + +doTest() { + set -- "$teststring" + eval "$testcmd" + case ${IFS+s}${IFS:+n} in + ( sn ) i=$(printf %s "$IFS" | trim_od) ;; + ( s ) i='(null)' ;; + ( '' ) i='(unset)' ;; + ( * ) echo 'internal error!' >&2; exit 125 ;; + esac + printf '\n%03d: IFS = %s: %s\n' "$((n+=1))" "$i" "$testcmd" + printf %s "$*${foo+/}${foo-}" | trim_od +} + +doAllTests() { + for testcmd in \ + 'unset -v foo; set -- ${foo=$*}' \ + 'unset -v foo; set -- ${foo="$*"}' \ + 'unset -v foo; set -- "${foo=$*}"' \ + \ + 'foo=; set -- ${foo:=$*}' \ + 'foo=; set -- ${foo:="$*"}' \ + 'foo=; set -- "${foo:=$*}"' \ + \ + 'unset -v foo; set -- ${foo=$@}' \ + 'unset -v foo; set -- ${foo="$@"}' \ + 'unset -v foo; set -- "${foo=$@}"' \ + \ + 'foo=; set -- ${foo:=$@}' \ + 'foo=; set -- ${foo:="$@"}' \ + 'foo=; set -- "${foo:=$@}"' + do + doTest "$testcmd" + done +} + +unset -v IFS; doAllTests +IFS=''; doAllTests +IFS='x'; doAllTests +IFS=$defaultIFS; doAllTests diff --git a/tests/posixexp6.sub b/tests/posixexp6.sub new file mode 100644 index 00000000..ed38d535 --- /dev/null +++ b/tests/posixexp6.sub @@ -0,0 +1,57 @@ +var=$'\01\02\03\177' + +bar=${unset:-$var} +recho "$bar" +unset -v bar +bar=${unset:-"$var"} +recho "$bar" + +foo=${parameter:=$var} + +recho "$foo" +recho "$parameter" + +unset -v foo parameter + +foo=${parameter:="$var"} + +recho "$foo" +recho "$parameter" + +unset -v foo parameter + +foo="${parameter:=$var}" + +recho "$foo" +recho "$parameter" + +unset -v foo parameter + +recho ${parameter:=a\ b} +unset -v parameter + +recho ${parameter:="a b"} +unset -v parameter + +v='a b' + +recho ${parameter:=$v} +unset -v parameter + +recho ${parameter:="$v"} +unset -v parameter + +# unsetting IFS here + +set " abc " " def ghi " "jkl " +unset -v IFS var +var=${var-$*}/${var-$*} +printf '[%s]\n' "$var" + +unset -v var +: ${var=$*} +printf '[%s]\n' "$var" + +unset -v var +: ${var:=$*/$*/${var-$*}} +printf '[%s]\n' "$var" diff --git a/tests/posixpat.tests b/tests/posixpat.tests index 91fac3b8..65c557a3 100644 --- a/tests/posixpat.tests +++ b/tests/posixpat.tests @@ -20,13 +20,15 @@ case 9 in [![:alpha:]]) echo ok 4;; esac -# invalid character class expressions are just characters to be matched case a in [:al:]) echo ok 5;; esac +# invalid character class expressions are no longer just characters to be +# matched case a in -[[:al:]) echo ok 6;; +[[:al:]) echo bad 6;; +*) echo ok 6;; esac case '!' in @@ -230,4 +232,3 @@ case a in [[=b=]) echo oops;; # an incomplete equiv class is just a string *) echo ok 3;; esac - diff --git a/tests/printf.right b/tests/printf.right index ae34a890..593f084b 100644 --- a/tests/printf.right +++ b/tests/printf.right @@ -148,6 +148,7 @@ b xx xx +< >< > one one\ctwo 4\.2 diff --git a/tests/printf.tests b/tests/printf.tests index e72f5c8b..9dbac6f0 100644 --- a/tests/printf.tests +++ b/tests/printf.tests @@ -308,6 +308,9 @@ shopt -s nullglob extglob echo "x$(printf "%b" @(hugo))x" printf -v var "%b" @(hugo); echo "x${var}x" +# make sure that missing arguments are always handled like the empty string +printf "<%3s><%3b>\n" + # tests variable assignment with -v ${THIS_SH} ./printf1.sub @@ -316,4 +319,3 @@ ${THIS_SH} ./printf2.sub ${THIS_SH} ./printf3.sub ${THIS_SH} ./printf4.sub - diff --git a/tests/printf3.sub b/tests/printf3.sub index ec14fa34..d45e101c 100644 --- a/tests/printf3.sub +++ b/tests/printf3.sub @@ -6,7 +6,7 @@ SECS=1275250155 export TZ=EST5EDT case $SHELLSTART in -*s*) SHELLSTART=$(perl -e 'print time') ; DATESECS=false ;; # take a shot +*s*) SHELLSTART=$EPOCHSECONDS ; DATESECS=false ;; # take a shot *) DATESECS=true ;; esac @@ -15,7 +15,7 @@ printf "%(abde)Z\n" -1 printf "%(%e-%b-%Y %T)T\n" $SECS -printf -v v1 "%(%e-%b-%Y %T)T\n" $( $DATESECS && date +%s || perl -e 'print time') +printf -v v1 "%(%e-%b-%Y %T)T\n" $( $DATESECS && date +%s || echo $EPOCHSECONDS ) printf -v v2 "%(%e-%b-%Y %T)T\n" -1 case $v1 in diff --git a/tests/procsub.right b/tests/procsub.right new file mode 100644 index 00000000..cf1dbb10 --- /dev/null +++ b/tests/procsub.right @@ -0,0 +1,29 @@ +test1 +foo +test2 +test3 +test4 +8 +test5 +test6 +test7 +test8 +test8a +test9 +hi +bye +l8r +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +intern +1 +0 +0 +0 +0 +extern +1 +0 +0 +0 +0 +123 diff --git a/tests/procsub.tests b/tests/procsub.tests new file mode 100644 index 00000000..4678ac69 --- /dev/null +++ b/tests/procsub.tests @@ -0,0 +1,99 @@ +# process substitution constructs that have caused problems in the past +. ./test-glue-functions + +eval cat <(echo test1) +eval "echo foo;cat" <(echo test2) + +unset f +f=<(echo test3); cat "$f" + +unset f +eval f=<(echo test4) "; cat \$f" + +unset f + +FN=$TMPDIR/bashtest-procsub-$$ +cat >"$FN" <<EOF +echo "test 12" | wc -c | _cut_leading_spaces +cat "\$1" +EOF + +source "$FN" <(echo test5) +rm -f "$FN" +unset FN + +cat <( echo test6 ) <( echo test7 ) +cat <( echo test8 ; sleep 2; echo test8a ) <( echo test9 ) + +# Zev Weiss 11/7/2012 +fn() { cat | cat "$1"; } +fn <(:) < /dev/null + +unset -f fn + +f1(){ + cat $1 + date >/dev/null +} +f2(){ + date >/dev/null + cat $1 +} +cat <(echo hi) +f1 <(echo bye) +f2 <(echo l8r) + +unset -f f1 f2 + +# set up conditions for test +ulimit -n 256 + +bug() +{ +c=$(ulimit -n) +let c+=100 +while let c-- +do + while read -ru3 x + do + echo -n : + done 3< <(echo x) +done +echo +} + +bug +unset -f bug + +count_lines() +{ + wc -l < $1 + wc -l < $1 + wc -l < $1 + true | wc -l < $1 + wc -l < $1 +} + +echo intern +count_lines <(date) | _cut_leading_spaces +unset -f count_lines + +echo extern +FN=$TMPDIR/bashtest-$$ +cat >$FN <<EOF +wc -l < \$1 +wc -l < \$1 +wc -l < \$1 +true | wc -l < \$1 +wc -l < \$1 +EOF + +${THIS_SH} -c "source $FN <(date)" | _cut_leading_spaces +rm -f $FN + +moo() { ls -l "$1" >/dev/null; ls -l "$1" >/dev/null; }; moo >(true) +moo() { ls -al "$1" >/dev/null; (true); ls -al "$1" >/dev/null; }; moo >(true) + +unset -f moo + +${THIS_SH} ./procsub1.sub diff --git a/tests/redir12.sub b/tests/procsub1.sub index 0e68f3b2..0e68f3b2 100644 --- a/tests/redir12.sub +++ b/tests/procsub1.sub diff --git a/tests/quote.right b/tests/quote.right index 00b55c62..e4c25741 100644 --- a/tests/quote.right +++ b/tests/quote.right @@ -66,6 +66,12 @@ argv[2] = <ab> ${ argv[1] = <(")> argv[1] = <(")> +string \ +string \ +string \ +string \ +string \ +string \} 'weferfds'\''dsfsdf' 'weferfdsdsfsdf' 'weferfds'\''dsfsdf' diff --git a/tests/quote.tests b/tests/quote.tests index 0c55293b..57ee7e58 100644 --- a/tests/quote.tests +++ b/tests/quote.tests @@ -109,4 +109,15 @@ recho `echo "(\\")"` # ultimate workaround recho `echo "(\")"` +# various strings ending in backslashes + +echo 'string \' +echo "string \\" + +echo string\ \\ + +echo ${foo:-'string \'} +echo "${foo:-string \\}" +echo ${foo:-string \\\}} + ${THIS_SH} ./quote1.sub diff --git a/tests/quote1.sub b/tests/quote1.sub index c83e64ac..a9a1ef15 100644 --- a/tests/quote1.sub +++ b/tests/quote1.sub @@ -14,7 +14,7 @@ echo "'${test//"'"/}'" echo "'${test//"'"/"'\\''"}'" -echo "'${test//"'"/\'\\'\'}'" +printf "%s\n" "'${test//"'"/\'\\'\'}'" #echo "'${test//'/}'" # hangs waiting for ' #echo "'${test//"'"/'\\''}'" # hangs waiting for ' diff --git a/tests/read.tests b/tests/read.tests index fe27dae3..f67cd00e 100644 --- a/tests/read.tests +++ b/tests/read.tests @@ -25,43 +25,43 @@ echo $'\177' | ( read ; recho "$REPLY" ) # the input stream echo $'ab\\\ncd' | ( read ; recho "$REPLY" ) -echo "A B " > /tmp/IN +echo "A B " > $TMPDIR/IN unset x y z -read x y z < /tmp/IN +read x y z < $TMPDIR/IN echo 1: "x[$x] y[$y] z[$z]" echo 1a: ${z-z not set} -read x < /tmp/IN +read x < $TMPDIR/IN echo 2: "x[$x]" -rm /tmp/IN +rm $TMPDIR/IN # this is where the bash `read' behavior with respect to $REPLY differs # from ksh93 -echo "A B " > /tmp/IN +echo "A B " > $TMPDIR/IN -read < /tmp/IN +read < $TMPDIR/IN echo "[$REPLY]" -rm /tmp/IN +rm $TMPDIR/IN -echo " A B " > /tmp/IN +echo " A B " > $TMPDIR/IN -read < /tmp/IN +read < $TMPDIR/IN echo "[$REPLY]" -rm /tmp/IN +rm $TMPDIR/IN # make sure that read with more variables than words sets the extra # variables to the empty string bvar=bvar cvar=cvar -echo aa > /tmp/IN -read avar bvar cvar < /tmp/IN +echo aa > $TMPDIR/IN +read avar bvar cvar < $TMPDIR/IN echo =="$avar"== echo =="$bvar"== echo =="$cvar"== -rm /tmp/IN +rm $TMPDIR/IN # test behavior of read with various settings of IFS diff --git a/tests/redir.right b/tests/redir.right index c158e251..ab737d49 100644 --- a/tests/redir.right +++ b/tests/redir.right @@ -26,10 +26,10 @@ from stdin: aa to stdout ./redir4.sub: line 32: $fd: ambiguous redirect ./redir4.sub: line 33: $fd: ambiguous redirect -/tmp/err-and-out: +err-and-out: to stdout to stderr -/tmp/err-and-out: +err-and-out: to stdout to stderr 0 -- 3 0 @@ -157,4 +157,3 @@ a+=3 foo foo ./redir11.sub: line 53: $(echo $a): Bad file descriptor -123 diff --git a/tests/redir.tests b/tests/redir.tests index 24e3cd1a..7b74ac53 100644 --- a/tests/redir.tests +++ b/tests/redir.tests @@ -191,4 +191,3 @@ ${THIS_SH} ./redir9.sub ${THIS_SH} ./redir10.sub ${THIS_SH} ./redir11.sub -${THIS_SH} ./redir12.sub diff --git a/tests/redir4.sub b/tests/redir4.sub index 47344554..14406d01 100644 --- a/tests/redir4.sub +++ b/tests/redir4.sub @@ -34,23 +34,23 @@ exec 4>&$fd exec 3>&1 4>&2 -exec >&/tmp/err-and-out +exec >&${TMPDIR}/err-and-out echo to stdout echo to stderr >&2 exec 1>&3 2>&4 -echo /tmp/err-and-out: -cat /tmp/err-and-out +echo err-and-out: +cat ${TMPDIR}/err-and-out -rm /tmp/err-and-out +rm ${TMPDIR}/err-and-out -fd=/tmp/err-and-out +fd=${TMPDIR}/err-and-out exec >&$fd echo to stdout echo to stderr >&2 exec 1>&3 2>&4 -echo /tmp/err-and-out: -cat /tmp/err-and-out +echo err-and-out: +cat ${TMPDIR}/err-and-out -rm /tmp/err-and-out +rm ${TMPDIR}/err-and-out diff --git a/tests/redir6.sub b/tests/redir6.sub index 60cc68b0..c735e523 100644 --- a/tests/redir6.sub +++ b/tests/redir6.sub @@ -6,3 +6,5 @@ pwd echo $? echo $? echo $? + +cd $OLDPWD diff --git a/tests/redir8.sub b/tests/redir8.sub index 5f972a14..88753f2f 100644 --- a/tests/redir8.sub +++ b/tests/redir8.sub @@ -56,4 +56,6 @@ exec 0<&7 exec 7<&- rm -f infile + +cd $OLDPWD exit 0 diff --git a/tests/rsh.right b/tests/rsh.right index 022b2ca1..a728f137 100644 --- a/tests/rsh.right +++ b/tests/rsh.right @@ -1,13 +1,19 @@ -./rsh.tests: line 9: cd: restricted -./rsh.tests: line 10: PATH: readonly variable -./rsh.tests: line 11: SHELL: readonly variable -./rsh.tests: line 12: /bin/sh: restricted: cannot specify `/' in command names -./rsh.tests: line 14: .: ./source.sub3: restricted -./rsh.tests: line 17: /tmp/restricted: restricted: cannot redirect output -./rsh.tests: line 21: /tmp/restricted: restricted: cannot redirect output -./rsh.tests: line 26: command: -p: restricted -./rsh.tests: line 28: set: +r: invalid option +./rsh1.sub: line 9: /bin/sh: restricted +./rsh1.sub: line 11: sh: not found +./rsh1.sub: line 12: a: command not found +./rsh2.sub: line 10: hash: /bin/sh: restricted +./rsh2.sub: line 12: hash: sh: not found +./rsh2.sub: line 13: a: command not found +./rsh.tests: line 12: cd: restricted +./rsh.tests: line 13: PATH: readonly variable +./rsh.tests: line 14: SHELL: readonly variable +./rsh.tests: line 15: /bin/sh: restricted: cannot specify `/' in command names +./rsh.tests: line 17: .: ./source.sub3: restricted +./rsh.tests: line 20: /tmp/restricted: restricted: cannot redirect output +./rsh.tests: line 24: /tmp/restricted: restricted: cannot redirect output +./rsh.tests: line 29: command: -p: restricted +./rsh.tests: line 31: set: +r: invalid option set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...] -./rsh.tests: line 29: set: restricted: invalid option name -./rsh.tests: line 31: exec: restricted +./rsh.tests: line 32: set: restricted: invalid option name +./rsh.tests: line 34: exec: restricted ./rsh.tests: after exec diff --git a/tests/rsh.tests b/tests/rsh.tests index ffdf6e55..d1d77784 100644 --- a/tests/rsh.tests +++ b/tests/rsh.tests @@ -4,6 +4,9 @@ # adding builtins dynamically with enable -f # importing function definitions from environment +${THIS_SH} ./rsh1.sub +${THIS_SH} ./rsh2.sub + set -r cd / diff --git a/tests/rsh1.sub b/tests/rsh1.sub new file mode 100644 index 00000000..fdd4ddd9 --- /dev/null +++ b/tests/rsh1.sub @@ -0,0 +1,16 @@ +cd ${TMPDIR:-/tmp} +cp /bin/sh . + +PATH=/rbin:/usr/local/rbin +hash -p /bin/rm rm + +set -r + +BASH_CMDS[x]=/bin/sh + +BASH_CMDS[a]="sh" +a -c 'echo hello' + +rm -f sh a + +exit 0 diff --git a/tests/rsh2.sub b/tests/rsh2.sub new file mode 100644 index 00000000..8c82c68b --- /dev/null +++ b/tests/rsh2.sub @@ -0,0 +1,17 @@ +cd ${TMPDIR:-/tmp} +cp /bin/sh . +ln sh a + +PATH=/rbin:/usr/local/rbin +hash -p /bin/rm rm + +set -r + +hash -p /bin/sh sh + +hash -p sh a +a -c 'echo hello' + +rm -f sh a + +exit 0 diff --git a/tests/run-all b/tests/run-all index 2882fe07..34d3e4c8 100644 --- a/tests/run-all +++ b/tests/run-all @@ -9,15 +9,21 @@ SUFFIX=`${THIS_SH} -c 'echo $(( $RANDOM + $BASHPID ))'` BASH_TSTOUT=${TMPDIR}/bashtst-$SUFFIX # for now export BASH_TSTOUT -trap 'rm -f $BASH_TSTOUT' 0 +trap 'rm -f $BASH_TSTOUT' 0 1 2 3 15 PATH=.:$PATH # just to get recho/zecho/printenv if not run via `make tests' export PATH # unset BASH_ENV only if it is set [ "${BASH_ENV+set}" = "set" ] && unset BASH_ENV -# ditto for SHELLOPTS -#[ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS +# can't reliably do it for SHELLOPTS; SHELLOPTS is readonly in bash +if [ "${BASH_VERSION+set}" = "set" ]; then + export -n SHELLOPTS # just make sure its not exported + set +o posix + typeset -p SHELLOPTS +else + [ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS 2>/dev/null +fi : ${THIS_SH:=../bash} export THIS_SH diff --git a/tests/run-dynvar b/tests/run-dynvar new file mode 100644 index 00000000..26c5434b --- /dev/null +++ b/tests/run-dynvar @@ -0,0 +1,2 @@ +${THIS_SH} ./dynvar.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} dynvar.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-minimal b/tests/run-minimal index c7fba73e..bbb9da18 100644 --- a/tests/run-minimal +++ b/tests/run-minimal @@ -41,6 +41,8 @@ do run-ifs-tests|run-input-test|run-invert|run-more-exp|run-nquote) echo $x ; sh $x ;; run-ifs-posix|run-posix2|run-posixpat|run-posixpipe) echo $x ; sh $x ;; run-precedence|run-quote|run-read|run-rhs-exp|run-strip|run-tilde) echo $x ; sh $x ;; + run-dynvar) echo $x ; sh $x ;; + ;; *) ;; esac rm -f "$BASH_TSTOUT" diff --git a/tests/run-procsub b/tests/run-procsub new file mode 100644 index 00000000..796faaa8 --- /dev/null +++ b/tests/run-procsub @@ -0,0 +1,7 @@ +echo "warning: all of these tests will fail if process substitution has not" >&2 +echo "warning: been compiled into the shell or if the OS does not provide" >&2 +echo "warning: FIFOs or /dev/fd. Some tests may fail if the OS does not" >&2 +echo "warning: provide FIFOs." >&2 + +${THIS_SH} ./procsub.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} procsub.right && rm -f ${BASH_TSTOUT} diff --git a/tests/set-x.right b/tests/set-x.right index a41a382a..259602e5 100644 --- a/tests/set-x.right +++ b/tests/set-x.right @@ -26,6 +26,10 @@ + x=i + case x in + x=i ++ foo=one ++ foo+=two ++ echo onetwo +onetwo + set +x 1 2 diff --git a/tests/set-x.tests b/tests/set-x.tests index 648f0a9e..531c53f6 100755 --- a/tests/set-x.tests +++ b/tests/set-x.tests @@ -14,6 +14,11 @@ case x in 0) x=i ;; *) x=i ;; esac + +foo=one +foo+=two +echo $foo + set +x # test BASH_XTRACEFD diff --git a/tests/shopt.right b/tests/shopt.right index 86d9ed6b..bb0ac696 100644 --- a/tests/shopt.right +++ b/tests/shopt.right @@ -2,6 +2,7 @@ shopt: usage: shopt [-pqsu] [-o] [optname ...] -- shopt -u autocd +shopt -u assoc_expand_once shopt -u cdable_vars shopt -s cdspell shopt -u checkhash @@ -14,6 +15,7 @@ shopt -u compat40 shopt -u compat41 shopt -u compat42 shopt -u compat43 +shopt -u compat44 shopt -s complete_fullquote shopt -u direxpand shopt -u dirspell @@ -37,6 +39,7 @@ shopt -u inherit_errexit shopt -s interactive_comments shopt -u lastpipe shopt -u lithist +shopt -u localvar_inherit shopt -u login_shell shopt -u mailwarn shopt -u no_empty_cmd_completion @@ -67,6 +70,7 @@ shopt -s promptvars shopt -s sourcepath -- shopt -u autocd +shopt -u assoc_expand_once shopt -u cdable_vars shopt -u checkhash shopt -u checkjobs @@ -77,6 +81,7 @@ shopt -u compat40 shopt -u compat41 shopt -u compat42 shopt -u compat43 +shopt -u compat44 shopt -u direxpand shopt -u dirspell shopt -u dotglob @@ -94,6 +99,7 @@ shopt -u huponexit shopt -u inherit_errexit shopt -u lastpipe shopt -u lithist +shopt -u localvar_inherit shopt -u login_shell shopt -u mailwarn shopt -u no_empty_cmd_completion @@ -105,6 +111,7 @@ shopt -u shift_verbose shopt -u xpg_echo -- autocd off +assoc_expand_once off cdable_vars off checkhash off checkjobs off @@ -115,6 +122,7 @@ compat40 off compat41 off compat42 off compat43 off +compat44 off direxpand off dirspell off dotglob off @@ -132,6 +140,7 @@ huponexit off inherit_errexit off lastpipe off lithist off +localvar_inherit off login_shell off mailwarn off no_empty_cmd_completion off diff --git a/tests/test-glue-functions b/tests/test-glue-functions index 2b2f61d0..b958ab71 100644 --- a/tests/test-glue-functions +++ b/tests/test-glue-functions @@ -6,4 +6,8 @@ _intl_normalize_spaces() sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/[[:space:]]*$//' } - +# avoid whitespace differences in wc implementations +_cut_leading_spaces() +{ + sed -e 's/^[[:space:]]*//g' +} diff --git a/tests/test.right b/tests/test.right index 7fcd9964..9832bd6d 100644 --- a/tests/test.right +++ b/tests/test.right @@ -289,3 +289,7 @@ t -t /dev/tty4 t -t /dev/tty4444444... 1 1 +t -p /dev/fd/6 +1 +t -p /dev/fd/6 +0 diff --git a/tests/test.tests b/tests/test.tests index 47eef354..07a87a0b 100644 --- a/tests/test.tests +++ b/tests/test.tests @@ -436,3 +436,5 @@ t -t /dev/tty4444444... # fixed in bash-4.0-beta t -t ' ' + +${THIS_SH} ./test1.sub diff --git a/tests/test1.sub b/tests/test1.sub new file mode 100644 index 00000000..a1c58170 --- /dev/null +++ b/tests/test1.sub @@ -0,0 +1,21 @@ +# some systems, like old SunOS, have stat on /dev/fd/N and fstat(N, ...) +# return different results +: ${TMPDIR:=/tmp} + +trap 'rm -f ${TMPDIR}/pipe' 0 1 2 3 6 15 + +exec 6>&- +echo "t -p /dev/fd/6" +test -p /dev/fd/6 +echo $? + +rm -f ${TMPDIR}/pipe 2>/dev/null +mkfifo ${TMPDIR}/pipe +cat < ${TMPDIR}/pipe & +exec 6>&- +exec 6>${TMPDIR}/pipe +echo "t -p /dev/fd/6" +test -p /dev/fd/6 +echo $? +exec 2>/dev/null # disable process termination message +kill $! 2>/dev/null diff --git a/tests/tilde.tests b/tests/tilde.tests index 50f19e98..8a9f1369 100644 --- a/tests/tilde.tests +++ b/tests/tilde.tests @@ -1,3 +1,4 @@ +wdir=$PWD # this is needed because posix mode restricts tilde expansion to assignment # statements preceding a command, instead of the default of expanding all # assignment statements on the line (e.g., after `export'). Without this, @@ -69,3 +70,6 @@ esac USER=root # should exist just about everywhere echo ~$USER + +cd "$wdir" +exit 0 diff --git a/tests/trap.right b/tests/trap.right index 1f68d331..41658293 100644 --- a/tests/trap.right +++ b/tests/trap.right @@ -64,6 +64,14 @@ after while before false in trap2a.sub after false in trap2a.sub command substitution +ERRTRAP +ERRTRAP +bar +ERRTRAP +ERRTRAP +ERRTRAP +ERRTRAP +ERRTRAP +[6] echo 1 1 +[7] echo 2 @@ -93,6 +101,10 @@ sleep 2 wait $! exit in trap EXIT +fn +after 1 +fn +after 2 caught a child death caught a child death caught a child death diff --git a/tests/trap.tests b/tests/trap.tests index 4176df08..637bfd28 100644 --- a/tests/trap.tests +++ b/tests/trap.tests @@ -74,6 +74,9 @@ ${THIS_SH} ./trap4.sub # This doesn't work right on all Unix versions #${THIS_SH} ./trap5.sub +# Return trap issues +${THIS_SH} ./trap6.sub + # # show that setting a trap on SIGCHLD is not disastrous. # diff --git a/tests/trap2.sub b/tests/trap2.sub index 73357df2..0f1f2d96 100755 --- a/tests/trap2.sub +++ b/tests/trap2.sub @@ -23,3 +23,27 @@ echo after while ./trap2a.sub echo $(false ; echo command substitution) + +# test behavior of failed commands following `command' builtin +command false + +(command false) +command false | echo bar + +(false) + +exit 42 | command false + +command command command false + +unset FALSE +if [ -x /bin/false ]; then + FALSE=/bin/false +elif [ -x /usr/bin/false ]; then + FALSE=/usr/bin/false +else + FALSE='command false' +fi + +command $FALSE +command command command $FALSE diff --git a/tests/trap6.sub b/tests/trap6.sub new file mode 100644 index 00000000..332a1773 --- /dev/null +++ b/tests/trap6.sub @@ -0,0 +1,15 @@ +set -o functrace +fn() { return; } + +trap "echo fn ; fn" RETURN + +fn +echo after 1 + +unset -f fn + +fn() { eval return; } +fn +echo after 2 + +unset -f fn diff --git a/tests/type.right b/tests/type.right index 3f7d26e2..7ec6bfba 100644 --- a/tests/type.right +++ b/tests/type.right @@ -65,11 +65,11 @@ foo is a function foo () { echo; - cat <<END + cat <<END bar END - cat <<EOF + cat <<EOF qux EOF @@ -86,7 +86,7 @@ foo () rm -f a b c; for f in a b c; do - cat >> ${f} <<-EOF + cat <<-EOF >> ${f} file EOF @@ -99,7 +99,7 @@ c:file bb is a function bb () { - ( cat <<EOF + ( cat <<EOF foo bar EOF @@ -110,13 +110,13 @@ mkcoprocs is a function mkcoprocs () { coproc a { - cat <<EOF1 + cat <<EOF1 producer 1 EOF1 } coproc b { - cat <<EOF2 + cat <<EOF2 producer 2 EOF2 @@ -126,7 +126,7 @@ EOF2 mkcoprocs is a function mkcoprocs () { - coproc COPROC ( b cat <<EOF + coproc COPROC ( b cat <<EOF heredoc body EOF diff --git a/tests/type3.sub b/tests/type3.sub index a90afef0..442f22e4 100644 --- a/tests/type3.sub +++ b/tests/type3.sub @@ -16,3 +16,6 @@ eval "$(type foo | sed 1d)" foo rm -f a b c + +cd $OLDPWD +exit 0 diff --git a/tests/varenv.right b/tests/varenv.right index 38d1ce7d..7ca5f661 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -91,6 +91,62 @@ global:2 after: --global-- after: ---- x = :1:2 +in o1 (readonly modifying local scalars): +declare -r i1="a b c" +declare -r j1="1 2 3" +after o1: +./varenv9.sub: line 15: declare: i1: not found +./varenv9.sub: line 15: declare: j1: not found +in o2 (readonly setting global scalars): +declare -r i2="a b c" +declare -r j2="1 2 3" +after o2: +declare -r i2="a b c" +declare -r j2="1 2 3" +./varenv9.sub: line 33: unset: i2: cannot unset: readonly variable +./varenv9.sub: line 33: unset: j2: cannot unset: readonly variable +in o3 (readonly modifying locals, converting to arrays): +declare -ar i3=([0]="a" [1]="b" [2]="c") +declare -ar j3=([0]="1" [1]="2" [2]="3") +after o3: +./varenv9.sub: line 48: declare: i3: not found +./varenv9.sub: line 48: declare: j3: not found +in o4 (readonly setting global array variables): +declare -ar i4=([0]="a" [1]="b" [2]="c") +declare -ar j4=([0]="1" [1]="2" [2]="3") +after o4: +declare -ar i4=([0]="a" [1]="b" [2]="c") +declare -ar j4=([0]="1" [1]="2" [2]="3") +./varenv9.sub: line 66: unset: i4: cannot unset: readonly variable +./varenv9.sub: line 66: unset: j4: cannot unset: readonly variable +main: unset +inner: res unset +outer: res: X Y +main: after first call: X +inner: X +outer: res: X Y +main: after second call: X +func: null or unset +after func: x = outside +./varenv11.sub: line 4: local: qux: readonly variable +./varenv11.sub: line 5: qux: readonly variable +declare -A foo=([one]="one" [zero]="zero" ) +declare -a bar=([0]="zero" [1]="one") +declare -A foo=([one]="one" [zero]="zero" ) +declare -a bar=([0]="zero" [1]="one") +./varenv11.sub: line 29: a: readonly variable +foo=abc +func1: var = + +func1: var = + +inside: declare -- foo +outside: +declare -x foo="abc" +inside: declare -x var="value" +outside: declare -- var="one" +inside: declare -- var="local" +outside: declare -x var="global" a=z a=b a=z diff --git a/tests/varenv.sh b/tests/varenv.sh index a0d31690..f2299b43 100644 --- a/tests/varenv.sh +++ b/tests/varenv.sh @@ -221,5 +221,18 @@ ${THIS_SH} ./varenv7.sub # redirections ${THIS_SH} ./varenv8.sub +# make sure that builtins like readonly and export modify local array variables +# if executed in shell functions, like they modify local scalar variables +${THIS_SH} ./varenv9.sub + +# more tests of unset and local variables with dynamic scoping +${THIS_SH} ./varenv10.sub + +# tests of compound assignments in function scope +${THIS_SH} ./varenv11.sub + +# temporary environment variable propagation and scoping in posix mode +${THIS_SH} ./varenv12.sub + # make sure variable scoping is done right tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a diff --git a/tests/varenv10.sub b/tests/varenv10.sub new file mode 100644 index 00000000..887cfd2c --- /dev/null +++ b/tests/varenv10.sub @@ -0,0 +1,47 @@ +#!/bin/bash +# +# various tests of unset when applied to variables at different local scopes + +# function unsetting variable at previous local scope, uncovering global + +inner() +{ + unset res + echo ${FUNCNAME}: ${res-res unset} + if [[ $1 == "set" ]]; then + res[0]="X" + res[1]="Y" + fi +} + +outer() +{ + local res= + inner "$1" + echo ${FUNCNAME}: "res: ${res[@]}" +} + +echo main: ${res-unset} +outer set +echo main: after first call: ${res-unset} +outer dontset +echo main: after second call: ${res-unset} + +unset -f outer inner +unset res + +# local scope, unset variable at the same scope as local declaration +func() +{ + typeset x=4 + + unset x + echo ${FUNCNAME}: ${x:-null or unset} +} + +x=outside +func +echo after func: x = $x + +unset -f func +unset x diff --git a/tests/varenv11.sub b/tests/varenv11.sub new file mode 100644 index 00000000..d4384983 --- /dev/null +++ b/tests/varenv11.sub @@ -0,0 +1,30 @@ +# couple of errors here +func() +{ + local qux=7 + local qux=(one two) + local what=(zero one two) +} + +readonly qux=42 +func + +func2() +{ + declare -gA foo=([zero]=zero [one]=one) + declare -ga bar=(zero one) +} + +foo=help +bar=me + +func2 + +declare -p foo bar +unset foo bar +func2 +declare -p foo bar + +readonly a=7 +a=(1 2 3) + diff --git a/tests/varenv12.sub b/tests/varenv12.sub new file mode 100644 index 00000000..6aaf512b --- /dev/null +++ b/tests/varenv12.sub @@ -0,0 +1,62 @@ +set -o posix + +fn() { foo=abc : ; typeset +x foo; printenv|grep ^foo=; } + +fn +unset -v foo +unset -f fn + +func1() { + var=1 + var=2 : # or 'var=2 return', or another special builtin + unset -v var + echo $FUNCNAME: var = $var +} +func2() { + func1 + unset -v var # bug: fails silently +} +func1 +echo ${var+"BUG: still set 1"} + +unset var +func2 +echo ${var+"BUG: still set 2"} + +unset -v var +unset -f func1 func2 + +fn() { foo=abc : ; typeset +x foo; echo -n 'inside: ' ; declare -p foo; } +fn +echo outside: +declare -p foo + +unset -v foo +unset -f fn + +func() +{ + var=value declare -x var + echo -n 'inside: ' ; declare -p var +} + +var=one +func +echo -n 'outside: ' ; declare -p var + +unset -v var +unset -f func + +func() +{ + local var=local + var=global : + echo -n 'inside: ' ; declare -p var +} + +var=outside +func +echo -n 'outside: ' ; declare -p var + +unset -v var +unset -f func diff --git a/tests/varenv9.sub b/tests/varenv9.sub new file mode 100644 index 00000000..eda1be3f --- /dev/null +++ b/tests/varenv9.sub @@ -0,0 +1,66 @@ +# case 1: readonly modifying local scalar variables +o1() { + local i1 j1 + readonly i1=$1 + readonly j1="1 2 3" + + echo "in o1 (readonly modifying local scalars):" + declare -p i1 + declare -p j1 +} + +o1 "a b c" + +echo after o1: +declare -p i1 j1 + +unset i1 j1 + +# case 2: readonly setting global scalar variables +o2() { + readonly i2=$1 + readonly j2="1 2 3" + + echo "in o2 (readonly setting global scalars):" + declare -p i2 + declare -p j2 +} + +o2 "a b c" +echo after o2: +declare -p i2 j2 + +unset i2 j2 + +# case 3: readonly modifying local variables, converting to arrays +o3() { + local i3 j3 + readonly i3=($1) + readonly j3=(1 2 3) + + echo "in o3 (readonly modifying locals, converting to arrays):" + declare -p i3 + declare -p j3 +} + +o3 "a b c" +echo after o3: +declare -p i3 j3 + +unset i3 j3 + +# case 4: readonly setting global array variables +o4() { + readonly i4=($1) + readonly j4=(1 2 3) + + echo "in o4 (readonly setting global array variables):" + declare -p i4 + declare -p j4 +} + +o4 "a b c" +echo after o4: +declare -p i4 j4 + +unset i4 j4 diff --git a/tests/vredir.right b/tests/vredir.right index 3985f22d..f449ae6f 100644 --- a/tests/vredir.right +++ b/tests/vredir.right @@ -27,7 +27,7 @@ line 3 bar is a function bar () { - exec {v}<<EOF + exec {v}<<EOF line 1 line 2 line 3 |
