diff options
Diffstat (limited to 'tests')
266 files changed, 15613 insertions, 0 deletions
diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..a1a081b --- /dev/null +++ b/tests/README @@ -0,0 +1 @@ +Type `sh run-all'. diff --git a/tests/alias.right b/tests/alias.right new file mode 100644 index 0000000..53111be --- /dev/null +++ b/tests/alias.right @@ -0,0 +1,4 @@ +alias: 0 +alias: 0 +./alias.tests: line 25: qfoo: command not found +quux diff --git a/tests/alias.tests b/tests/alias.tests new file mode 100644 index 0000000..9cfec16 --- /dev/null +++ b/tests/alias.tests @@ -0,0 +1,37 @@ +# place holder for future alias testing +shopt -s expand_aliases + +# alias/unalias tests originally in builtins.tests + +unalias -a +# this should return success, according to POSIX.2 +alias +echo alias: $? +alias foo=bar +unalias foo +# this had better return success, according to POSIX.2 +alias +echo alias: $? + +# bug in all versions through bash-2.05b + +unalias qfoo qbar qbaz quux 2>/dev/null + +alias qfoo=qbar +alias qbar=qbaz +alias qbaz=quux +alias quux=qfoo + +qfoo + +unalias qfoo qbar qbaz quux + +unalias -a + +alias foo='echo ' +alias bar=baz +alias baz=quux + +foo bar + +unalias foo bar baz diff --git a/tests/appendop.right b/tests/appendop.right new file mode 100644 index 0000000..1e24333 --- /dev/null +++ b/tests/appendop.right @@ -0,0 +1,18 @@ +14 +1 2 3 4 5 6 +1 2 3 4 51 6 +5 +14 +7 +42 +1 2 3 4 12 +18 +1 2 3 4 18 +1 2 7 4 5 +1 2 7 13 5 9 +14 +9 +4 +9 +16 +./appendop.tests: line 83: x: readonly variable diff --git a/tests/appendop.tests b/tests/appendop.tests new file mode 100644 index 0000000..7b61f3f --- /dev/null +++ b/tests/appendop.tests @@ -0,0 +1,83 @@ +# basic cases +a=1 +a+=4 +echo $a + +x=(1 2 3) +x+=(4 5 6) + +echo ${x[@]} + +x[4]+=1 +echo ${x[@]} + +# trickier cases + +a+=5 printenv a +echo $a + +# if the integer flag is set, ksh93 appears to do arithmetic += and evaluate +# old value as an arithmetic expression +a= +typeset -i a +a+=7 +echo $a + +b=4+1 +typeset -i b +b+=37 + +echo $b + +unset x +x=(1 2 3 4 5) + +typeset -i x + +x[4]+=7 + +echo ${x[@]} + +unset x +typeset -i x + +x=([0]=7+11) +echo ${x[@]} + +unset x +x=(1 2 3 4 5) + +typeset -i x + +#x[4]=7+11 + +x=(1 2 3 4 [4]=7+11 ) +echo ${x[@]} + +x=( 1 2 [2]+=7 4 5 ) +echo ${x[@]} + +x+=( [3]+=9 [5]=9 ) +echo ${x[@]} + +unset a +a=1 +export a+=4 +printenv a +printenv a+ + +unset x +typeset -i x=4+5 +echo $x + +unset x +typeset x+=4 +echo $x + +typeset -i x+=5 +echo $x + +readonly x+=7 +echo $x + +x+=5 diff --git a/tests/arith-for.right b/tests/arith-for.right new file mode 100644 index 0000000..4494110 --- /dev/null +++ b/tests/arith-for.right @@ -0,0 +1,74 @@ +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +2 +4 +fx is a function +fx () +{ + i=0; + for ((1; i < 3; i++ )) + do + echo $i; + done; + for ((i=0; 1; i++ )) + do + if (( i >= 3 )); then + break; + fi; + echo $i; + done; + for ((i=0; i<3; 1)) + do + echo $i; + (( i++ )); + done; + i=0; + for ((1; 1; 1)) + do + if (( i > 2 )); then + break; + fi; + echo $i; + (( i++ )); + done; + i=0; + for ((1; 1; 1)) + do + if (( i > 2 )); then + break; + fi; + echo $i; + (( i++ )); + done +} +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +./arith-for.tests: line 77: syntax error: arithmetic expression required +./arith-for.tests: line 77: 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 ))' +2 +20 +20 diff --git a/tests/arith-for.tests b/tests/arith-for.tests new file mode 100644 index 0000000..585aa51 --- /dev/null +++ b/tests/arith-for.tests @@ -0,0 +1,94 @@ +fx() +{ +i=0 +for (( ; i < 3; i++ )) +do + echo $i +done + +for (( i=0; ; i++ )) +do + if (( i >= 3 )); then + break; + fi + echo $i +done + +for (( i=0; i<3; )) +do + echo $i + (( i++ )) +done + +i=0 +for (( ; ; )) +do + if (( i > 2 )); then + break; + fi + echo $i; + (( i++ )) +done + +i=0 +for ((;;)) +do + if (( i > 2 )); then + break; + fi + echo $i; + (( i++ )) +done +} + +for (( i=0; "i < 3" ; i++ )) +do + echo $i +done + +i=0 +for (( ; "i < 3"; i++ )) +do + echo $i +done + +for (( i=0; ; i++ )) +do + if (( i >= 3 )); then + break; + fi + echo $i +done + +for ((i = 0; ;i++ )) +do + echo $i + if (( i < 3 )); then + (( i++ )) + continue; + fi + break +done + +type fx +fx + +# errors +for (( i=0; "i < 3" )) +do + echo $i +done +echo $? + +for (( i=0; i < 3; i++; 7 )) +do + echo $i +done +echo $? + +# one-liners added in post-bash-2.04 +for ((i=0; i < 20; i++)) do : ; done +echo $i + +for ((i=0; i < 20; i++)) { : ; } +echo $i diff --git a/tests/arith.right b/tests/arith.right new file mode 100644 index 0000000..1365786 --- /dev/null +++ b/tests/arith.right @@ -0,0 +1,203 @@ +163 +166 +4 +16 +8 +2 +4 +2 +2 +1 +0 +0 +0 +1 +1 +2 +-3 +-2 +1 +0 +2 +131072 +29 +33 +49 +1 +1 +0 +0 +1 +1 +1 +2 +3 +1 +58 +2 +60 +1 +256 +16 +62 +4 +29 +5 +-4 +4 +1 +32 +32 +1 +1 +32 +20 +1,i+=2 +30 +1,j+=2 +20 +1,i+=2 +30 +1,j+=2 +./arith.tests: line 108: 1 ? 20 : x+=2: attempted assignment to non-variable (error token is "+=2") +20 +6 +6,5,3 +263 +255 +255 +127 +36 +40 +10 +10 +10 +10 +10 +10 +36 +36 +62 +63 +./arith.tests: line 143: 3425#56: invalid arithmetic base (error token is "3425#56") +0 +./arith.tests: line 149: 7 = 43 : attempted assignment to non-variable (error token is "= 43 ") +./arith.tests: line 150: 2#44: value too great for base (error token is "2#44") +./arith.tests: line 151: 44 / 0 : division by 0 (error token is " ") +./arith.tests: line 152: let: jv += $iv: syntax error: operand expected (error token is "$iv") +./arith.tests: line 153: jv += $iv : syntax error: operand expected (error token is "$iv ") +./arith.tests: line 154: let: rv = 7 + (43 * 6: missing `)' (error token is "6") +./arith.tests: line 158: 0#4: invalid number (error token is "0#4") +./arith.tests: line 159: 2#110#11: invalid number (error token is "2#110#11") +abc +def +ghi +ok +6 +1 +0 +./arith.tests: line 177: 4 + : syntax error: operand expected (error token is " ") +16 +./arith.tests: line 182: 4 ? : 3 + 5 : expression expected (error token is ": 3 + 5 ") +./arith.tests: line 183: 1 ? 20 : `:' expected for conditional expression (error token is " ") +./arith.tests: line 184: 4 ? 20 : : expression expected (error token is " ") +9 +./arith.tests: line 190: 0 && B=42 : attempted assignment to non-variable (error token is "=42 ") +9 +./arith.tests: line 193: 1 || B=88 : attempted assignment to non-variable (error token is "=88 ") +9 +0 +9 +0 +9 +1 +9 +7 +7 +4 +32767 +32768 +131072 +2147483647 +1 +4 +4 +5 +5 +4 +3 +3 +4 +4 +7 +./arith.tests: line 241: 7-- : syntax error: operand expected (error token is " ") +./arith.tests: line 243: --x=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 244: ++x=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 246: x++=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 247: x--=7 : attempted assignment to non-variable (error token is "=7 ") +4 +7 +-7 +7 +7 +./arith1.sub: line 2: 4-- : syntax error: operand expected (error token is " ") +./arith1.sub: line 3: 4++ : syntax error: operand expected (error token is " ") +./arith1.sub: line 4: 4 -- : syntax error: operand expected (error token is " ") +./arith1.sub: line 5: 4 ++ : syntax error: operand expected (error token is " ") +1 +2 +1 +2 +6 +3 +7 +4 +0 +3 +7 +2 +-2 +1 +./arith1.sub: line 35: ((: ++ : syntax error: operand expected (error token is " ") +7 +7 +./arith1.sub: line 38: ((: -- : syntax error: operand expected (error token is " ") +7 +7 +7 +7 +1 +2 +1 +2 +1 +0 +5 +1 +6 +2 +3 +1 +4 +0 +./arith2.sub: line 33: ((: -- : syntax error: operand expected (error token is " ") +-7 +-7 +./arith2.sub: line 37: ((: ++ : syntax error: operand expected (error token is " ") +7 +7 +-7 +-7 +7 +7 +8 12 +./arith.tests: line 268: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ") +./arith.tests: line 272: a b: syntax error in expression (error token is "b") +./arith.tests: line 273: ((: a b: syntax error in expression (error token is "b") +42 +42 +42 +42 +42 +42 +./arith.tests: line 284: b[c]d: syntax error in expression (error token is "d") diff --git a/tests/arith.tests b/tests/arith.tests new file mode 100644 index 0000000..33622e7 --- /dev/null +++ b/tests/arith.tests @@ -0,0 +1,284 @@ +set +o posix +declare -i iv jv + +iv=$(( 3 + 5 * 32 )) +echo $iv +iv=iv+3 +echo $iv +iv=2 +jv=iv + +let "jv *= 2" +echo $jv +jv=$(( $jv << 2 )) +echo $jv + +let jv="$jv / 2" +echo $jv +jv="jv >> 2" +echo $jv + +iv=$((iv+ $jv)) +echo $iv +echo $((iv -= jv)) +echo $iv +echo $(( iv == jv )) +echo $(( iv != $jv )) +echo $(( iv < jv )) +echo $(( $iv > $jv )) +echo $(( iv <= $jv )) +echo $(( $iv >= jv )) + +echo $jv +echo $(( ~$jv )) +echo $(( ~1 )) +echo $(( ! 0 )) + +echo $(( jv % 2 )) +echo $(( $iv % 4 )) + +echo $(( iv <<= 16 )) +echo $(( iv %= 33 )) + +echo $(( 33 & 55 )) +echo $(( 33 | 17 )) + +echo $(( iv && $jv )) +echo $(( $iv || jv )) + +echo $(( iv && 0 )) +echo $(( iv & 0 )) +echo $(( iv && 1 )) +echo $(( iv & 1 )) + +echo $(( $jv || 0 )) +echo $(( jv | 0 )) +echo $(( jv | 1 )) +echo $(( $jv || 1 )) + +let 'iv *= jv' +echo $iv +echo $jv +let "jv += $iv" +echo $jv + +echo $(( jv /= iv )) +echo $(( jv <<= 8 )) +echo $(( jv >>= 4 )) + +echo $(( iv |= 4 )) +echo $(( iv &= 4 )) + +echo $(( iv += (jv + 9))) +echo $(( (iv + 4) % 7 )) + +# unary plus, minus +echo $(( +4 - 8 )) +echo $(( -4 + 8 )) + +# conditional expressions +echo $(( 4<5 ? 1 : 32)) +echo $(( 4>5 ? 1 : 32)) +echo $(( 4>(2+3) ? 1 : 32)) +echo $(( 4<(2+3) ? 1 : 32)) +echo $(( (2+2)<(2+3) ? 1 : 32)) +echo $(( (2+2)>(2+3) ? 1 : 32)) + +# check that the unevaluated part of the ternary operator does not do +# evaluation or assignment +x=i+=2 +y=j+=2 +declare -i i=1 j=1 +echo $((1 ? 20 : (x+=2))) +echo $i,$x +echo $((0 ? (y+=2) : 30)) +echo $j,$y + +x=i+=2 +y=j+=2 +declare -i i=1 j=1 +echo $((1 ? 20 : (x+=2))) +echo $i,$x +echo $((0 ? (y+=2) : 30)) +echo $i,$y + +# check precedence of assignment vs. conditional operator +# should be an error +declare -i x=2 +y=$((1 ? 20 : x+=2)) + +# check precedence of assignment vs. conditional operator +declare -i x=2 +echo $((0 ? x+=2 : 20)) + +# associativity of assignment-operator operator +declare -i i=1 j=2 k=3 +echo $((i += j += k)) +echo $i,$j,$k + +# octal, hex +echo $(( 0x100 | 007 )) +echo $(( 0xff )) +echo $(( 16#ff )) +echo $(( 16#FF/2 )) +echo $(( 8#44 )) + +echo $(( 8 ^ 32 )) + +# other bases +echo $(( 16#a )) +echo $(( 32#a )) +echo $(( 56#a )) +echo $(( 64#a )) + +echo $(( 16#A )) +echo $(( 32#A )) +echo $(( 56#A )) +echo $(( 64#A )) + +echo $(( 64#@ )) +echo $(( 64#_ )) + +# weird bases +echo $(( 3425#56 )) + +# missing number after base +echo $(( 2# )) + +# these should generate errors +echo $(( 7 = 43 )) +echo $(( 2#44 )) +echo $(( 44 / 0 )) +let 'jv += $iv' +echo $(( jv += \$iv )) +let 'rv = 7 + (43 * 6' + +# more errors +declare -i i +i=0#4 +i=2#110#11 + +((echo abc; echo def;); echo ghi) + +if (((4+4) + (4 + 7))); then + echo ok +fi + +(()) # make sure the null expression works OK + +a=(0 2 4 6) +echo $(( a[1] + a[2] )) +echo $(( (a[1] + a[2]) == a[3] )) +(( (a[1] + a[2]) == a[3] )) ; echo $? + +# test pushing and popping the expression stack +unset A +A="4 + " +echo $(( ( 4 + A ) + 4 )) +A="3 + 5" +echo $(( ( 4 + A ) + 4 )) + +# badly-formed conditional expressions +echo $(( 4 ? : $A )) +echo $(( 1 ? 20 )) +echo $(( 4 ? 20 : )) + +# precedence and short-circuit evaluation +B=9 +echo $B + +echo $(( 0 && B=42 )) +echo $B + +echo $(( 1 || B=88 )) +echo $B + +echo $(( 0 && (B=42) )) +echo $B + +echo $(( (${$} - $$) && (B=42) )) +echo $B + +echo $(( 1 || (B=88) )) +echo $B + +# until command with (( )) command +x=7 + +echo $x +until (( x == 4 )) +do + echo $x + x=4 +done + +echo $x + +# exponentiation +echo $(( 2**15 - 1)) +echo $(( 2**(16-1))) +echo $(( 2**16*2 )) +echo $(( 2**31-1)) +echo $(( 2**0 )) + +# {pre,post}-{inc,dec}rement and associated errors + +x=4 + +echo $x +echo $(( x++ )) +echo $x +echo $(( x-- )) +echo $x + +echo $(( --x )) +echo $x + +echo $(( ++x )) +echo $x + +echo $(( ++7 )) +echo $(( 7-- )) + +echo $(( --x=7 )) +echo $(( ++x=7 )) + +echo $(( x++=7 )) +echo $(( x--=7 )) + +echo $x + +echo $(( +7 )) +echo $(( -7 )) + +echo $(( ++7 )) +echo $(( --7 )) + +${THIS_SH} ./arith1.sub +${THIS_SH} ./arith2.sub + +x=4 +y=7 + +(( x=8 , y=12 )) + +echo $x $y + +# should be an error +(( x=9 y=41 )) + +# These are errors +unset b +echo $((a b)) +((a b)) + +n=42 +printf "%d\n" $n +printf "%i\n" $n +echo $(( 8#$(printf "%o\n" $n) )) +printf "%u\n" $n +echo $(( 16#$(printf "%x\n" $n) )) +echo $(( 16#$(printf "%X\n" $n) )) + +# causes longjmp botches through bash-2.05b +a[b[c]d]=e diff --git a/tests/arith1.sub b/tests/arith1.sub new file mode 100644 index 0000000..43cae80 --- /dev/null +++ b/tests/arith1.sub @@ -0,0 +1,38 @@ +# test of redone post-increment and post-decrement code +echo $(( 4-- )) +echo $(( 4++ )) +echo $(( 4 -- )) +echo $(( 4 ++ )) + +(( array[0]++ )) +echo ${array} + +(( array[0] ++ )) +echo ${array} + +(( a++ )) +echo $a +(( a ++ )) +echo $a + +echo $(( a ++ + 4 )) +echo $a + +echo $(( a+++4 )) +echo $a + +echo $(( a---4 )) +echo $a + +echo $(( a -- + 4 )) +echo $a + +echo $(( a -- - 4 )) +echo $a + +(( ++ + 7 )) + +(( ++ )) +echo $(( +++7 )) +echo $(( ++ + 7 )) +(( -- )) diff --git a/tests/arith2.sub b/tests/arith2.sub new file mode 100644 index 0000000..7eac952 --- /dev/null +++ b/tests/arith2.sub @@ -0,0 +1,45 @@ +echo $(( --7 )) +echo $(( ++7 )) +echo $(( -- 7 )) +echo $(( ++ 7 )) + +((++array[0] )) +echo $array +(( ++ array[0] )) +echo $array + +(( ++a )) +echo $a +(( ++ a )) +echo $a + +(( --a )) +echo $a +(( -- a )) +echo $a + +echo $(( 4 + ++a )) +echo $a + +echo $(( 4+++a )) +echo $a + +echo $(( 4---a )) +echo $a + +echo $(( 4 - -- a )) +echo $a + +(( -- )) +echo $(( ---7 )) +echo $(( -- - 7 )) + +(( ++ )) +echo $(( ++7 )) +echo $(( ++ + 7 )) + +echo $(( ++-7 )) +echo $(( ++ - 7 )) + +echo $(( +--7 )) +echo $(( -- + 7 )) diff --git a/tests/array-at-star b/tests/array-at-star new file mode 100755 index 0000000..80f039d --- /dev/null +++ b/tests/array-at-star @@ -0,0 +1,120 @@ +# test the expansion of ${array[@]} and ${array[*]}, both quoted and +# unquoted. the expansions should be exactly analogous to the +# expansions of $@ and $* quoted and unquoted +A=(a b) + +recho "${A[*]}" + +# If IFS is null, the parameters are joined without separators +IFS='' +recho "${A[*]}" + +# If IFS is unset, the parameters are separated by spaces +unset IFS +recho "${A[*]}" + +recho "${A[@]}" +recho ${A[@]} + +IFS='/' +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +# according to POSIX.2, unquoted $* should expand to multiple words if +# $IFS is null, just like unquoted $@ +IFS='' +A=(bob 'tom dick harry' joe) +set "${A[*]}" +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +# if IFS is unset, the individual positional parameters are split on +# " \t\n" if $* or $@ are unquoted +unset IFS +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +# but not for "$@" or "$*" +A=(bob 'tom dick harry' joe) +set "${A[*]}" +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set "${A[@]}" +recho $# +recho $1 +recho $2 +recho $3 + +# these should both expand the value of A to multiple words +A=(a b c d e) +IFS="" +recho ${A[@]} +recho "${A[@]}" + +# this example is straight from the POSIX.2 rationale and adapted to arrays +A=(foo bar bam) + +recho "${A[@]}" +recho "${A[*]}" + +unset IFS + +recho "${A[@]}" +recho ${A[@]} +recho "${A[*]}" diff --git a/tests/array.right b/tests/array.right new file mode 100644 index 0000000..488b4e4 --- /dev/null +++ b/tests/array.right @@ -0,0 +1,199 @@ + +./array.tests: line 15: syntax error near unexpected token `&' +./array.tests: line 15: `test=(first & second)' +1 +abcde +abcde +abcde bdef +abcde bdef +declare -a BASH_ARGC='()' +declare -a BASH_ARGV='()' +declare -a BASH_LINENO='([0]="0")' +declare -a BASH_SOURCE='([0]="./array.tests")' +declare -a DIRSTACK='()' +declare -a FUNCNAME='([0]="main")' +declare -a a='([0]="abcde" [1]="" [2]="bdef")' +declare -a b='()' +declare -ar c='()' +abcde bdef +abcde bdef +abcde +abcde +abcde + +bdef +hello world +11 +3 +bdef hello world test expression +./array.tests: line 74: readonly: `a[5]': not a valid identifier +declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' +declare -ar c='()' +declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' +declare -ar c='()' +readonly -a a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' +readonly -a c='()' +a test +declare -a BASH_ARGC='()' +declare -a BASH_ARGV='()' +declare -a BASH_LINENO='([0]="0")' +declare -a BASH_SOURCE='([0]="./array.tests")' +declare -a DIRSTACK='()' +declare -a FUNCNAME='([0]="main")' +declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' +declare -a b='([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd")' +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 98: a: readonly variable +./array.tests: line 100: b[]: bad array subscript +./array.tests: line 101: b[*]: bad array subscript +./array.tests: line 102: ${b[ ]}: bad substitution +./array.tests: line 104: c[-2]: bad array subscript +./array.tests: line 105: c: bad array subscript + +./array.tests: line 107: d[7]: cannot assign list to array member +./array.tests: line 109: []=abcde: bad array subscript +./array.tests: line 109: [*]=last: cannot assign to non-numeric index +./array.tests: line 109: [-65]=negative: bad array subscript +declare -a BASH_ARGC='()' +declare -a BASH_ARGV='()' +declare -a BASH_LINENO='([0]="0")' +declare -a BASH_SOURCE='([0]="./array.tests")' +declare -a DIRSTACK='()' +declare -a FUNCNAME='([0]="main")' +declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' +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 117: unset: ps1: not an array variable +./array.tests: line 121: declare: c: cannot destroy array variables in this way +this of +this is a test of read using arrays +this test +this is a test of arrays +declare -a BASH_ARGC='()' +declare -a BASH_ARGV='()' +declare -a BASH_LINENO='([0]="0")' +declare -a BASH_SOURCE='([0]="./array.tests")' +declare -a DIRSTACK='()' +declare -a FUNCNAME='([0]="main")' +declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' +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")' +declare -a rv='([0]="this" [1]="is" [2]="a" [3]="test" [4]="of" [5]="read" [6]="using" [7]="arrays")' +abde +abde +bbb +efgh +wxyz +wxyz +./array.tests +a +b c +d +e f g +h +./array.tests +a +b c +d +e f g +h +/bin /usr/bin /usr/ucb /usr/local/bin . /sbin /usr/sbin +bin bin ucb bin . sbin sbin +bin +/ / / / / / +/ +argv[1] = <bin> +argv[1] = </> +argv[1] = <sbin> +argv[1] = </> +\bin \usr/bin \usr/ucb \usr/local/bin . \sbin \usr/sbin +\bin \usr\bin \usr\ucb \usr\local\bin . \sbin \usr\sbin +\bin \usr\bin \usr\ucb \usr\local\bin . \sbin \usr\sbin +4 -- 4 +7 -- 7 +55 +49 +6 -- 6 +42 14 44 +grep [ 123 ] * +6 7 9 +6 7 9 5 +length = 3 +value = new1 new2 new3 +./array.tests: line 237: 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: syntax error near unexpected token `(' +./array2.sub: line 1: `declare -a ''=(a 'b c')' +9 +9 + + +7 8 9 + +a b c d e f g +for case if then else +<> < > ! +12 14 16 18 20 +4414758999202 +aaa bbb +./array.tests: line 282: syntax error near unexpected token `<>' +./array.tests: line 282: `metas=( <> < > ! )' +./array.tests: line 283: syntax error near unexpected token `<>' +./array.tests: line 283: `metas=( [1]=<> [2]=< [3]=> [4]=! )' +abc 3 +case 4 +abc case if then else 5 +abc case if then else 5 +0 +case 4 +case if then else 5 +case if then else 5 +argv[1] = <0> +argv[2] = <1> +argv[3] = <4> +argv[4] = <10> +argv[1] = <0> +argv[2] = <1> +argv[3] = <4> +argv[4] = <10> +argv[1] = <0> +argv[2] = <1> +argv[3] = <4> +argv[4] = <10> +argv[1] = <0 1 4 10> +include null element -- expect one +one +include unset element -- expect three five +three five +start at unset element -- expect five seven +five seven +too many elements -- expect three five seven +three five seven +positive offset - expect five seven +five seven +negative offset to unset element - expect seven +seven +positive offset 2 - expect seven +seven +negative offset 2 - expect seven +seven +out-of-range offset + +e +4 +1 4 7 10 +'b +b c +$0 +t +[3]=abcde r s t u v +e +9 diff --git a/tests/array.tests b/tests/array.tests new file mode 100644 index 0000000..4a735d8 --- /dev/null +++ b/tests/array.tests @@ -0,0 +1,398 @@ +# this is needed so that the bad assignments (b[]=bcde, for example) do not +# cause fatal shell errors when in posix mode +set +o posix + +set +a +# The calls to egrep -v are to filter out builtin array variables that are +# automatically set and possibly contain values that vary. + +# first make sure we handle the basics +x=() +echo ${x[@]} +unset x + +# this should be an error +test=(first & second) +echo $? +unset test + +# make sure declare -a converts an existing variable to an array +unset a +a=abcde +declare -a a +echo ${a[0]} + +unset a +a=abcde +a[2]=bdef + +unset b +declare -a b[256] + +unset c[2] +unset c[*] + +a[1]= + +_ENV=/bin/true +x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} + +declare -r c[100] + +echo ${a[0]} ${a[4]} +echo ${a[@]} + +echo ${a[*]} + +# this should print out values, too +declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +unset a[7] +echo ${a[*]} + +unset a[4] +echo ${a[*]} + +echo ${a} +echo "${a}" +echo $a + +unset a[0] +echo ${a} + +echo ${a[@]} + +a[5]="hello world" +echo ${a[5]} +echo ${#a[5]} + +echo ${#a[@]} + +a[4+5/2]="test expression" +echo ${a[@]} + +readonly a[5] +readonly a +# these two lines should output `declare' commands +readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' +declare -ar | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' +# this line should output `readonly' commands, even for arrays +set -o posix +readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' +set +o posix + +declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' +d[9]="ninth element" + +declare -a e[10]=test # this works in post-bash-2.05 versions +declare -a e[10]='(test)' + +pass=/etc/passwd +declare -a f='("${d[@]}")' +b=([0]=this [1]=is [2]=a [3]=test [4]="$PS1" [5]=$pass) + +echo ${b[@]:2:3} + +declare -pa | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +a[3]="this is a test" + +b[]=bcde +b[*]=aaa +echo ${b[ ]} + +c[-2]=4 +echo ${c[-4]} + +d[7]=(abdedfegeee) + +d=([]=abcde [1]="test test" [*]=last [-65]=negative ) + +unset d[12] +unset e[*] + +declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +ps1='hello' +unset ps1[2] +unset ${ps1[2]} + +declare +a ps1 +declare +a c + +# the prompt should not print when using a here doc +read -p "array test: " -a rv <<! +this is a test of read using arrays +! + +echo ${rv[0]} ${rv[4]} +echo ${rv[@]} + +# the variable should be converted to an array when `read -a' is done +vv=1 +read -a vv <<! +this is a test of arrays +! +echo ${vv[0]} ${vv[3]} +echo ${vv[@]} +unset vv + +declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +export rv +#set + +x[4]=bbb +x=abde +echo $x +echo ${x[0]} +echo ${x[4]} +echo efgh | ( read x[1] ; echo ${x[1]} ) +echo wxyz | ( declare -a x ; read x ; echo $x ; echo ${x[0]} ) + +# Make sure that arrays can be used to save the positional paramters verbatim +set -- a 'b c' d 'e f g' h + +ARGV=( [0]=$0 "$@" ) + +for z in "${ARGV[@]}" +do + echo "$z" +done + +echo "$0" +for z in "$@" +do + echo "$z" +done + +# do various pattern removal and length tests +XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin + +xpath=( $( IFS=: ; echo $XPATH ) ) + +echo ${xpath[@]} +echo ${xpath[@]##*/} +echo ${xpath[0]##*/} +echo ${xpath[@]%%[!/]*} +echo ${xpath[0]%%[!/]*} +recho ${xpath##*/} +recho ${xpath%%[!/]*} +recho ${xpath[5]##*/} +recho ${xpath[5]%%[!/]*} + +# let's try to make it a DOS-style path + +zecho "${xpath[@]/\//\\}" +zecho "${xpath[@]//\//\\}" +zecho "${xpath[@]//[\/]/\\}" + +# length of the first element of the array, since array without subscript +# is equivalent to referencing first element +echo ${#xpath} -- ${#xpath[0]} + +# number of elements in the array +nelem=${#xpath[@]} +echo ${#xpath[@]} -- $nelem + +# total length of all elements in the array, including space separators +xx="${xpath[*]}" +echo ${#xx} + +# total length of all elements in the array +xx=$( IFS='' ; echo "${xpath[*]}" ) +echo ${#xx} + +unset xpath[nelem-1] + +nelem=${#xpath[@]} +echo ${#xpath[@]} -- $nelem + +# arrays and things that look like index assignments +array=(42 [1]=14 [2]=44) + +array2=(grep [ 123 ] \*) + +echo ${array[@]} +echo "${array2[@]}" + +# arrays and implicit arithmetic evaluation +declare -i -a iarray + +iarray=( 2+4 1+6 7+2 ) +echo ${iarray[@]} + +iarray[4]=4+1 +echo ${iarray[@]} + +# make sure assignment using the compound assignment syntax removes all +# of the old elements from the array value +barray=(old1 old2 old3 old4 old5) +barray=(new1 new2 new3) +echo "length = ${#barray[@]}" +echo "value = ${barray[*]}" + +# make sure the array code behaves correctly with respect to unset variables +set -u +( echo ${#narray[4]} ) + +${THIS_SH} ./array1.sub +${THIS_SH} ./array2.sub + +# some old bugs and ksh93 compatibility tests +${THIS_SH} ./array3.sub + +set +u +cd /tmp + +touch 1=bar +foo=([10]="bar") +echo ${foo[0]} +rm 1=bar + +foo=(a b c d e f g) +echo ${foo[@]} + +# quoted reserved words are ok +foo=(\for \case \if \then \else) +echo ${foo[@]} + +# quoted metacharacters are ok +foo=( [1]='<>' [2]='<' [3]='>' [4]='!' ) +echo ${foo[@]} + +# numbers are just words when not in a redirection context +foo=( 12 14 16 18 20 ) +echo ${foo[@]} + +foo=( 4414758999202 ) +echo ${foo[@]} + +# this was a bug in all versions of bash 2.x up to and including bash-2.04 +declare -a ddd=(aaa +bbb) +echo ${ddd[@]} + +# errors until post-bash-2.05a; now reserved words are OK +foo=(a b c for case if then else) + +foo=(for case if then else) + +# errors +metas=( <> < > ! ) +metas=( [1]=<> [2]=< [3]=> [4]=! ) + +# various expansions that didn't really work right until post-bash-2.04 +foo='abc' +echo ${foo[0]} ${#foo[0]} +echo ${foo[1]} ${#foo[1]} +echo ${foo[@]} ${#foo[@]} +echo ${foo[*]} ${#foo[*]} + +foo='' +echo ${foo[0]} ${#foo[0]} +echo ${foo[1]} ${#foo[1]} +echo ${foo[@]} ${#foo[@]} +echo ${foo[*]} ${#foo[*]} + +# new expansions added after bash-2.05b +x[0]=zero +x[1]=one +x[4]=four +x[10]=ten + +recho ${!x[@]} +recho "${!x[@]}" +recho ${!x[*]} +recho "${!x[*]}" + +# sparse array tests for code fixed in bash-3.0 +unset av +av[1]='one' +av[2]='' + +av[3]=three +av[5]=five +av[7]=seven + +echo include null element -- expect one +echo ${av[@]:1:2} # what happens when we include a null element? +echo include unset element -- expect three five +echo ${av[@]:3:2} # what happens when we include an unset element? +echo start at unset element -- expect five seven +echo ${av[@]:4:2} # what happens when we start at an unset element? + +echo too many elements -- expect three five seven +echo ${av[@]:3:5} # how about too many elements? + +echo positive offset - expect five seven +echo ${av[@]:5:2} +echo negative offset to unset element - expect seven +echo ${av[@]: -2:2} + +echo positive offset 2 - expect seven +echo ${av[@]: 6:2} +echo negative offset 2 - expect seven +echo ${av[@]: -1:2} + +echo out-of-range offset +echo ${av[@]:12} + +# parsing problems and other inconsistencies not fixed until post bash-3.0 +unset x +declare -a x=(')' $$) +[ ${x[1]} -eq $$ ] || echo bad + +unset x +declare -a x=(a b c d e) +echo ${x[4]} + +z=([1]=one [4]=four [7]=seven [10]=ten) + +echo ${#z[@]} + +echo ${!z[@]} + +unset x +declare -a x=(a \'b c\') + +echo "${x[1]}" + +unset x +declare -a x=(a 'b c') + +echo "${x[1]}" + +unset x +declare -a x=($0) +[ "${x[@]}" = $0 ] || echo double expansion of \$0 +declare -a x=(\$0) +echo "${x[@]}" + +: ${TMPDIR:=/tmp} + +mkdir $TMPDIR/bash-test-$$ +cd $TMPDIR/bash-test-$$ + +trap "cd / ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15 + +touch '[3]=abcde' + +touch r s t u v + +declare -a x=(*) + +echo ${x[3]} +echo ${x[@]} + +unset x +x=(a b c d e) + +echo ${x[*]: -1} + +unset x[4] +unset x[2] + +x[9]='9' + +echo ${x[*]: -1} diff --git a/tests/array1.sub b/tests/array1.sub new file mode 100644 index 0000000..86e9332 --- /dev/null +++ b/tests/array1.sub @@ -0,0 +1 @@ +printf "%s\n" -a a=(a 'b c') diff --git a/tests/array2.right b/tests/array2.right new file mode 100644 index 0000000..b5145c2 --- /dev/null +++ b/tests/array2.right @@ -0,0 +1,74 @@ +argv[1] = <a b> +argv[1] = <ab> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <1> +argv[1] = <bobtom dick harryjoe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <1> +argv[1] = <bob> +argv[2] = <tom> +argv[3] = <dick> +argv[4] = <harry> +argv[5] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom> +argv[2] = <dick> +argv[3] = <harry> +argv[1] = <joe> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foobarbam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo bar bam> diff --git a/tests/array2.sub b/tests/array2.sub new file mode 100644 index 0000000..0e6417d --- /dev/null +++ b/tests/array2.sub @@ -0,0 +1 @@ +declare -a ''=(a 'b c') diff --git a/tests/array3.sub b/tests/array3.sub new file mode 100644 index 0000000..579b42b --- /dev/null +++ b/tests/array3.sub @@ -0,0 +1,9 @@ +a=(0 1 2 3 4 5 6 7 8 9) + +echo ${a[@]: -1} + +echo ${a[@]:9} +echo ${a[@]:10} +echo ${a[@]:11} + +echo ${a[@]:7:3} diff --git a/tests/braces.right b/tests/braces.right new file mode 100644 index 0000000..3d7ef8e --- /dev/null +++ b/tests/braces.right @@ -0,0 +1,43 @@ +ffc ffb ffa +fdg feg ffg +lxyz nxyz mxyz +{abc,def} +{abc} +{a,b,c,d,e} +x} y} {a} b} c} +x,y {abc} trie +/usr/ucb/ex /usr/ucb/edit /usr/lib/ex /usr/lib/how_ex +XXXX{a,b,c} +XXXXa XXXXb XXXXc +{} +{ } +} +{ +abcd{efgh +foo 1 2 bar +foo 1 2 bar +foo 1 2 bar +foobar foobaz. +foobar foobaz +bazx bazy +vx vy +bazx bazy +1 2 3 4 5 6 7 8 9 10 +0..10 braces +0 1 2 3 4 5 6 7 8 9 10 braces +x0y x1y x2y x3y x4y x5y x6y x7y x8y x9y x10y xbracesy +3 +x3y +10 9 8 7 6 5 4 3 2 1 +10y 9y 8y 7y 6y 5y 4y 3y 2y 1y +x10y x9y x8y x7y x6y x5y x4y x3y x2y x1y +a b c d e f +f e d c b a +a ` _ ^ ] [ Z Y X W V U T S R Q P O N M L K J I H G F E D C B A +A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a +f +{1..f} +{f..1} +01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 +-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 +-20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 diff --git a/tests/braces.tests b/tests/braces.tests new file mode 100644 index 0000000..3f57829 --- /dev/null +++ b/tests/braces.tests @@ -0,0 +1,70 @@ +echo ff{c,b,a} +echo f{d,e,f}g +echo {l,n,m}xyz +echo {abc\,def} +echo {abc} + +echo \{a,b,c,d,e} +echo {x,y,\{a,b,c}} +echo {x\,y,\{abc\},trie} + +echo /usr/{ucb/{ex,edit},lib/{ex,how_ex}} + +echo XXXX\{`echo a b c | tr ' ' ','`\} +eval echo XXXX\{`echo a b c | tr ' ' ','`\} + +echo {} +echo { } +echo } +echo { +echo abcd{efgh + +echo foo {1,2} bar +echo `zecho foo {1,2} bar` +echo $(zecho foo {1,2} bar) + +var=baz +varx=vx +vary=vy + +echo foo{bar,${var}.} +echo foo{bar,${var}} + +echo "${var}"{x,y} +echo $var{x,y} +echo ${var}{x,y} + +unset var varx vary + +# new sequence brace operators +echo {1..10} + +# this doesn't work yet +echo {0..10,braces} +# but this does +echo {{0..10},braces} +echo x{{0..10},braces}y + +echo {3..3} +echo x{3..3}y +echo {10..1} +echo {10..1}y +echo x{10..1}y + +echo {a..f} +echo {f..a} + +echo {a..A} +echo {A..a} + +echo {f..f} + +# mixes are incorrectly-formed brace expansions +echo {1..f} +echo {f..1} + +echo 0{1..9} {10..20} + +# do negative numbers work? +echo {-1..-10} +echo {-20..0} diff --git a/tests/builtins.right b/tests/builtins.right new file mode 100644 index 0000000..9266b5a --- /dev/null +++ b/tests/builtins.right @@ -0,0 +1,132 @@ +a +end-1 +a +end-2 +a:x +end-a +b:x +end-b +c:x +end-c +end-3 +a:x +end +a +b +c +end-1 +a +b +c +end-2 +a:x +a:y +a:z +end-a +b:x +b:y +b:z +end-b +c:x +c:y +c:z +end-c +end-3 +a:x +b:x +c:x +end +$BVAR +$BVAR +$BVAR +$BVAR +foo +bar +xxx +0022 +u=rwx,g=rx,o=rx +0002 +u=rwx,g=rwx,o=rx +umask 0002 +umask -S u=rwx,g=rwx,o=rx +u=rwx,g=rwx,o=rwx +enable . +enable : +enable break +enable continue +enable eval +enable exec +enable exit +enable export +enable readonly +enable return +enable set +enable shift +enable source +enable times +enable trap +enable unset +enable . +enable : +enable break +enable continue +enable eval +enable exec +enable exit +enable export +enable readonly +enable return +enable set +enable shift +enable source +enable times +enable trap +enable unset +enable -n test worked +enable test worked +specialname +-specialname +FOO=BAR +FOO=BAR +hash: hash table empty +0 +AVAR +foo +in source.sub2, calling return +5 +a b c +a b c +x y z +a b c +a b c +m n o p +a b c +m n o p +/tmp/bash-dir-a +/tmp/bash-dir-a +/tmp/bash-dir-a +./source5.sub: line 10: /tmp/source-notthere: No such file or directory +after bad source 1 +./source5.sub: line 17: /tmp/source-notthere: No such file or directory +AVAR +foo +foo +AVAR +foo +foo +AVAR +foo +declare -x foo="" +declare -x FOO="\$\$" +./builtins.tests: line 207: declare: FOO: not found +declare -x FOO="\$\$" +ok +ok +./builtins.tests: line 239: kill: 4096: invalid signal specification +1 +a\n\n\nb +a + + +b +./builtins.tests: line 248: exit: status: numeric argument required diff --git a/tests/builtins.tests b/tests/builtins.tests new file mode 100644 index 0000000..3c28633 --- /dev/null +++ b/tests/builtins.tests @@ -0,0 +1,250 @@ +# tests for miscellaneous builtins not tested elsewhere +set +p +set +o posix + +ulimit -c 0 2>/dev/null + +# check that break breaks loops +for i in a b c; do echo $i; break; echo bad-$i; done +echo end-1 +for i in a b c; do echo $i; break 1; echo bad-$i; done +echo end-2 +for i in a b c; do + for j in x y z; do + echo $i:$j + break + echo bad-$i + done + echo end-$i +done +echo end-3 + +# check that break breaks nested loops +for i in a b c; do + for j in x y z; do + echo $i:$j + break 2 + echo bad-$i + done + echo end-$i +done +echo end + +# check that continue continues loops +for i in a b c; do echo $i; continue; echo bad-$i ; done +echo end-1 +for i in a b c; do echo $i; continue 1; echo bad-$i; done +echo end-2 +for i in a b c; do + for j in x y z; do + echo $i:$j + continue + echo bad-$i-$j + done + echo end-$i +done +echo end-3 + +# check that continue breaks out of nested loops +for i in a b c; do + for j in x y z; do + echo $i:$j + continue 2 + echo bad-$i-$j + done + echo end-$i +done +echo end + +# check that `eval' re-evaluates arguments, but `builtin' and `command' do not +AVAR='$BVAR' +BVAR=foo + +echo $AVAR +builtin echo $AVAR +command echo $AVAR +eval echo \$AVAR +eval echo $AVAR + +# test out eval with a temp environment +AVAR=bar eval echo \$AVAR +BVAR=xxx eval echo $AVAR + +unset -v AVAR BVAR + +# test umask +mask=$(umask) +umask 022 +umask +umask -S +umask -S u=rwx,g=rwx,o=rx >/dev/null # 002 +umask +umask -S +umask -p +umask -p -S +umask 0 +umask -S +umask ${mask} # restore original mask + +# builtin/command without arguments should do nothing. maybe someday they will +builtin +command + +# test enable +enable -ps + +enable -aps ; enable -nps + +enable -n test +case "$(type -t test)" in +builtin) echo oops -- enable -n test failed ;; +*) echo enable -n test worked ;; +esac + +enable test +case "$(type -t test)" in +builtin) echo enable test worked ;; +*) echo oops -- enable test failed ;; +esac + +# test options to exec +(exec -a specialname ${THIS_SH} -c 'echo $0' ) +(exec -l -a specialname ${THIS_SH} -c 'echo $0' ) +# test `clean' environment. if /bin/sh is bash, and the script version of +# printenv is run, there will be variables in the environment that bash +# sets on startup. Also test code that prefixes argv[0] with a dash. +(export FOO=BAR ; exec -c -l printenv ) | grep FOO +(FOO=BAR exec -c printenv ) | grep FOO + +(export FOO=BAR ; exec printenv ) | grep FOO +(FOO=BAR exec printenv ) | grep FOO + +# ok, forget everything about hashed commands +hash -r +hash + +# this had better succeed, since command -p guarantees we will find the +# standard utilties +command -p hash rm + +# check out source/. + +# sourcing a zero-length-file had better not be an error +rm -f /tmp/zero-length-file +cp /dev/null /tmp/zero-length-file +. /tmp/zero-length-file +echo $? +rm /tmp/zero-length-file + +AVAR=AVAR + +. ./source1.sub +AVAR=foo . ./source1.sub + +. ./source2.sub +echo $? + +set -- a b c +. ./source3.sub + +# make sure source with arguments does not change the shell's positional +# parameters, but that the sourced file sees the arguments as its +# positional parameters +echo "$@" +. ./source3.sub x y z +echo "$@" + +# but if the sourced script sets the positional parameters explicitly, they +# should be reflected in the calling shell's positional parameters. this +# also tests one of the shopt options that controls source using $PATH to +# find the script +echo "$@" +shopt -u sourcepath +. source4.sub +echo "$@" + +# this is complicated when the sourced scripts gets its own positional +# parameters from arguments to `.' +set -- a b c +echo "$@" +. source4.sub x y z +echo "$@" + +# test out cd and $CDPATH +${THIS_SH} ./builtins1.sub + +# test behavior of `.' when given a non-existant file argument +${THIS_SH} ./source5.sub + +# in posix mode, assignment statements preceding special builtins are +# reflected in the shell environment. `.' and `eval' need special-case +# code. +set -o posix +echo $AVAR +AVAR=foo . ./source1.sub +echo $AVAR + +AVAR=AVAR +echo $AVAR +AVAR=foo eval echo \$AVAR +echo $AVAR + +AVAR=AVAR +echo $AVAR +AVAR=foo : +echo $AVAR +set +o posix + +# but assignment statements preceding `export' are always reflected in +# the environment +foo="" export foo +declare -p foo +unset foo + +# assignment statements preceding `declare' should be displayed correctly, +# but not persist after the command +FOO='$$' declare -p FOO +declare -p FOO +unset FOO + +# except for `declare -x', which should be equivalent to `export' +FOO='$$' declare -x FOO +declare -p FOO +unset FOO + +# test out kill -l. bash versions prior to 2.01 did `kill -l num' wrong +sigone=$(kill -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') + +case "$(kill -l 1)" in +${sigone/SIG/}) echo ok;; +*) echo oops -- kill -l failure;; +esac + +# kill -l and trap -l should display exactly the same output +sigonea=$(trap -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') + +if [ "$sigone" != "$sigonea" ]; then + echo oops -- kill -l and trap -l differ +fi + +# POSIX.2 says that exit statuses > 128 are mapped to signal names by +# subtracting 128 so you can find out what signal killed a process +case "$(kill -l $(( 128 + 1)) )" in +${sigone/SIG/}) echo ok;; +*) echo oops -- kill -l 129 failure;; +esac + +# out-of-range signal numbers should report the argument in the error +# message, not 128 less than the argument +kill -l 4096 + +# kill -l NAME should return the signal number +kill -l ${sigone/SIG/} + +# test behavior of shopt xpg_echo +${THIS_SH} ./builtins2.sub + +# this must be last -- it is a fatal error +exit status + +echo after bad exit diff --git a/tests/builtins1.sub b/tests/builtins1.sub new file mode 100644 index 0000000..5b79711 --- /dev/null +++ b/tests/builtins1.sub @@ -0,0 +1,14 @@ +unset CDPATH + +MYDIR=$(pwd -P) +FULLDIR=/tmp/bash-dir-a +DIR=${FULLDIR##*/} + +mkdir $FULLDIR +CDPATH=.:/tmp +cd $DIR +pwd +echo $PWD + +cd $MYDIR +rmdir $FULLDIR diff --git a/tests/builtins2.sub b/tests/builtins2.sub new file mode 100644 index 0000000..e4cb32a --- /dev/null +++ b/tests/builtins2.sub @@ -0,0 +1,10 @@ +# test behavior of shopt xpg_echo + +USG_ECHO=off +shopt -q xpg_echo && USG_ECHO=on + +shopt -u xpg_echo +echo 'a\n\n\nb' + +shopt -s xpg_echo +echo 'a\n\n\nb' diff --git a/tests/cond.right b/tests/cond.right new file mode 100644 index 0000000..06f36a9 --- /dev/null +++ b/tests/cond.right @@ -0,0 +1,37 @@ +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 0 +returns: 0 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 0 +returns: 1 +returns: 1 +returns: 1 +returns: 1 +returns: 0 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 1 +returns: 0 +returns: 1 +returns: 1 +returns: 0 +./cond.tests: line 101: [[: 4+: syntax error: operand expected (error token is "+") +returns: 1 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +ok +ok 42 +ok 43 diff --git a/tests/cond.tests b/tests/cond.tests new file mode 100755 index 0000000..3abfa9d --- /dev/null +++ b/tests/cond.tests @@ -0,0 +1,159 @@ +# +# the test/[ code is tested elsewhere, and the [[...]] just uses the same +# code. this tests the special features of [[...]] +# +TDIR=/usr/homes/chet + +# this one is straight out of the ksh88 book +[[ foo > bar && $PWD -ef . ]] +echo returns: $? + +# [[ x ]] is equivalent to [[ -n x ]] +[[ x ]] +echo returns: $? + +# [[ ! x ]] is equivalent to [[ ! -n x ]] +[[ ! x ]] +echo returns: $? + +# ! binds tighter than test/[ -- it binds to a term, not an expression +[[ ! x || x ]] +echo returns: $? + +# parenthesized terms didn't work right until post-2.04 +[[ a ]] +echo returns: $? + +[[ (a) ]] +echo returns: $? + +[[ -n a ]] +echo returns: $? + +[[ (-n a) ]] +echo returns: $? + +# unset variables don't need to be quoted +[[ -n $UNSET ]] +echo returns: $? + +[[ -z $UNSET ]] +echo returns: $? + +# the ==/= and != operators do pattern matching +[[ $TDIR == /usr/homes/* ]] +echo returns: $? + +# ...but you can quote any part of the pattern to have it matched as a string +[[ $TDIR == /usr/homes/\* ]] +echo returns: $? + +[[ $TDIR == '/usr/homes/*' ]] +echo returns: $? + +# if the first part of && fails, the second is not executed +[[ -n $UNSET && $UNSET == foo ]] +echo returns: $? + +[[ -z $UNSET && $UNSET == foo ]] +echo returns: $? + +# if the first part of || succeeds, the second is not executed +[[ -z $UNSET || -d $PWD ]] +echo returns: $? + +# if the rhs were executed, it would be an error +[[ -n $TDIR || $HOME -ef ${H*} ]] +echo returns: $? + +[[ -n $TDIR && -z $UNSET || $HOME -ef ${H*} ]] +echo returns: $? + +# && has a higher parsing precedence than || +[[ -n $TDIR && -n $UNSET || $TDIR -ef . ]] +echo returns: $? + +# ...but expressions in parentheses may be used to override precedence rules +[[ -n $TDIR || -n $UNSET && $PWD -ef xyz ]] +echo returns: $? + +[[ ( -n $TDIR || -n $UNSET ) && $PWD -ef xyz ]] +echo returns: $? + +# some arithmetic tests for completeness -- see what happens with missing +# operands, bad expressions, makes sure arguments are evaluated as +# arithmetic expressions, etc. + +unset IVAR A +[[ 7 -gt $IVAR ]] +echo returns: $? + +[[ $IVAR -gt 7 ]] +echo returns: $? + +IVAR=4 +[[ $IVAR -gt 7 ]] +echo returns: $? + +[[ 7 -eq 4+3 ]] +echo returns: $? + +[[ 7 -eq 4+ ]] +echo returns: $? + +IVAR=4+3 +[[ $IVAR -eq 7 ]] +echo returns: $? + +A=7 +[[ $IVAR -eq A ]] +echo returns: $? + +unset IVAR A + +# more pattern matching tests + +[[ $filename == *.c ]] +echo returns: $? + +filename=patmatch.c + +[[ $filename == *.c ]] +echo returns: $? + +# the extended globbing features may be used when matching patterns +shopt -s extglob + +arg=-7 + +[[ $arg == -+([0-9]) ]] +echo returns: $? + +arg=-H + +[[ $arg == -+([0-9]) ]] +echo returns: $? + +arg=+4 +[[ $arg == ++([0-9]) ]] +echo returns: $? + +# make sure the null string is never matched if the string is not null +STR=file.c +PAT= + +if [[ $STR = $PAT ]]; then + echo oops +fi + +# but that if the string is null, a null pattern is matched correctly +STR= +PAT= + +if [[ $STR = $PAT ]]; then + echo ok +fi + +# bug in all versions up to and including bash-2.05b +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 diff --git a/tests/cprint.right b/tests/cprint.right new file mode 100644 index 0000000..5dd629d --- /dev/null +++ b/tests/cprint.right @@ -0,0 +1,72 @@ +tf is a function +tf () +{ + echo this is ${0##*/} >/dev/null; + echo a | cat - >/dev/null; + test -f ${0##*/} && echo ${0##*/} is a regular file; + test -d ${0##*/} || echo ${0##*/} is not a directory; + echo a; + echo b; + echo c; + echo background >/dev/null & ( exit 1 ); + echo $?; + { + echo a + }; + i=0; + while (( i < 3 )); do + test -r /dev/fd/$i; + i=$(( i + 1 )); + done; + [[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops >/dev/null; + for name in $( echo 1 2 3 ); + do + test -r /dev/fd/$name; + done; + if [[ -r /dev/fd/0 && -w /dev/fd/1 ]]; then + echo ok >/dev/null; + else + if (( 7 > 40 )); then + echo oops; + else + echo done; + fi; + fi >/dev/null; + case $PATH in + *$PWD*) + echo \$PWD in \$PATH + ;; + *) + echo \$PWD not in \$PATH + ;; + esac >/dev/null; + while false; do + echo z; + done >/dev/null; + until true; do + echo z; + done >/dev/null; + echo \&\|'()' \{ echo abcde \; \}; + eval fu\%nc'()' \{ echo abcde \; \}; + type fu\%nc +} +tf2 is a function +tf2 () +{ + ( { + time -p echo a | cat - >/dev/null + } ) 2>&1 +} +cprint.tests is a regular file +cprint.tests is not a directory +a +b +c +1 +a +&|() { echo abcde ; } +fu%nc is a function +fu%nc () +{ + echo abcde +} diff --git a/tests/cprint.tests b/tests/cprint.tests new file mode 100644 index 0000000..08ff1eb --- /dev/null +++ b/tests/cprint.tests @@ -0,0 +1,67 @@ +# +# a nonsense script and shell function to test out the command printing code +# +tf() +{ + # simple command with redir + echo this is ${0##*/} > /dev/null + + # pipeline + echo a | cat - > /dev/null + + test -f ${0##*/} && echo ${0##*/} is a regular file + test -d ${0##*/} || echo ${0##*/} is not a directory + + echo a ; echo b ; echo c + + echo background >/dev/null & + + ( exit 1 ) + echo $? + + { echo a ; } + + i=0 + while (( i < 3 )); do + test -r /dev/fd/$i + i=$(( i + 1 )) + done + + [[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops > /dev/null + + for name in $( echo 1 2 3 ); do + test -r /dev/fd/$name + done + + if [[ -r /dev/fd/0 && -w /dev/fd/1 ]] ; then + echo ok > /dev/null + elif (( 7 > 40 )) ; then + echo oops + else + echo done + fi > /dev/null + + case $PATH in + *$PWD*) echo \$PWD in \$PATH ;; + *) echo \$PWD not in \$PATH ;; + esac > /dev/null + + while false; do echo z; done > /dev/null + + until true; do echo z ; done > /dev/null + + echo \&\|'()' \{ echo abcde \; \} + # when not in POSIX mode, we can have weirdly-named functions + eval fu\%nc'()' \{ echo abcde \; \} + type fu\%nc +} + +tf2() +{ + ( { time -p echo a | cat - > /dev/null ; } ) 2>&1 +} + +type tf +type tf2 + +tf diff --git a/tests/dbg-support.right b/tests/dbg-support.right new file mode 100644 index 0000000..eb7d3c3 --- /dev/null +++ b/tests/dbg-support.right @@ -0,0 +1,353 @@ +debug lineno: 63 main +debug lineno: 66 main +FUNCNAME main +debug lineno: 70 main +debug lineno: 17 fn1 +debug lineno: 18 fn1 +LINENO 18 +debug lineno: 19 fn1 +LINENO 19 +debug lineno: 20 fn1 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 21 fn1 +FUNCNAME[0] fn1 +debug lineno: 22 fn1 +debug lineno: 22 fn1 70 ./dbg-support.tests +debug lineno: 23 fn1 +debug lineno: 23 fn1 70 main ./dbg-support.tests +debug lineno: 24 fn1 +debug lineno: 24 fn1 +debug lineno: 25 fn1 +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [EXPR] +debug lineno: 25 fn1 +debug lineno: 17 fn1 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 17 fn1 +debug lineno: 14 print_return_trap +debug lineno: 71 main +debug lineno: 28 fn2 +debug lineno: 29 fn2 +fn2 here. Calling fn1... +debug lineno: 30 fn2 +debug lineno: 17 fn1 +debug lineno: 18 fn1 +LINENO 18 +debug lineno: 19 fn1 +LINENO 19 +debug lineno: 20 fn1 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 21 fn1 +FUNCNAME[0] fn1 +debug lineno: 22 fn1 +debug lineno: 22 fn1 30 ./dbg-support.tests +debug lineno: 23 fn1 +debug lineno: 23 fn1 30 fn2 ./dbg-support.tests +debug lineno: 24 fn1 +debug lineno: 24 fn1 71 main ./dbg-support.tests +debug lineno: 25 fn1 +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [EXPR] +debug lineno: 25 fn1 +debug lineno: 17 fn1 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 17 fn1 +debug lineno: 14 print_return_trap +debug lineno: 28 fn2 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 28 fn2 +debug lineno: 14 print_return_trap +debug lineno: 72 main +debug lineno: 33 fn3 +debug lineno: 34 fn3 +LINENO 34 +debug lineno: 35 fn3 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 38 fn3 +debug lineno: 39 fn3 +debug lineno: 40 fn3 +debug lineno: 40 fn3 +debug lineno: 41 fn3 +debug lineno: 42 fn3 +debug lineno: 43 fn3 +fn3 called from file `./dbg-support.tests' at line 0 +debug lineno: 40 fn3 +debug lineno: 40 fn3 +debug lineno: 41 fn3 +debug lineno: 42 fn3 +debug lineno: 42 fn3 +debug lineno: 43 fn3 +main called from file `./dbg-support.tests' at line 0 +debug lineno: 40 fn3 +debug lineno: 40 fn3 +debug lineno: 46 fn3 +debug lineno: 18 source +SOURCED LINENO 18 +debug lineno: 19 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 20 source +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 46 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 72 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[3]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 46 fn3 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 46 fn3 +debug lineno: 14 print_return_trap +debug lineno: 33 fn3 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 33 fn3 +debug lineno: 14 print_return_trap +debug lineno: 73 main +debug lineno: 18 source +SOURCED LINENO 18 +debug lineno: 19 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 20 source +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 73 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 73 main +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 73 main +debug lineno: 14 print_return_trap +debug lineno: 76 main +debug lineno: 79 main +LINENO 18 +LINENO 19 +BASH_SOURCE[0] ./dbg-support.tests +FUNCNAME[0] fn1 +79 ./dbg-support.tests +79 main ./dbg-support.tests + +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [EXPR] + +debug lineno: 80 main +fn2 here. Calling fn1... +LINENO 18 +LINENO 19 +BASH_SOURCE[0] ./dbg-support.tests +FUNCNAME[0] fn1 +30 ./dbg-support.tests +30 fn2 ./dbg-support.tests +80 main ./dbg-support.tests +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [EXPR] + +debug lineno: 81 main +LINENO 34 +BASH_SOURCE[0] ./dbg-support.tests +fn3 called from file `./dbg-support.tests' at line 0 +main called from file `./dbg-support.tests' at line 0 +SOURCED LINENO 18 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +FUNCNAME[1]: source called from ./dbg-support.tests at line 46 +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 81 +FUNCNAME[3]: main called from ./dbg-support.tests at line 0 +debug lineno: 82 main +fn4 here. Calling fn3... +LINENO 34 +BASH_SOURCE[0] ./dbg-support.tests +fn3 called from file `./dbg-support.tests' at line 82 +fn4 called from file `./dbg-support.tests' at line 0 +main called from file `./dbg-support.tests' at line 0 +SOURCED LINENO 18 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +FUNCNAME[1]: source called from ./dbg-support.tests at line 46 +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 51 +FUNCNAME[3]: fn4 called from ./dbg-support.tests at line 82 +FUNCNAME[4]: main called from ./dbg-support.tests at line 0 +debug lineno: 83 main +SOURCED LINENO 18 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +FUNCNAME[1]: source called from ./dbg-support.tests at line 83 +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +return lineno: 83 main +debug lineno: 86 main +debug lineno: 89 main +debug lineno: 18 source +SOURCED LINENO 18 +debug lineno: 19 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 20 source +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 89 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 89 main +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 89 main +debug lineno: 14 print_return_trap +debug lineno: 90 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 94 main +debug lineno: 97 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 94 main +debug lineno: 97 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 94 main +debug lineno: 95 main +Hit 2 +debug lineno: 97 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 103 main +SOURCED FN LINENO 5 FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 103 FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 104 main +SOURCED FN LINENO 5 FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 104 FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 105 main +debug lineno: 106 main +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 106 +FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 110 main +debug lineno: 111 main +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 111 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 114 main +debug lineno: 119 main +debug lineno: 123 main +got it +debug lineno: 131 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 131 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 132 main +debug lineno: 133 main diff --git a/tests/dbg-support.sub b/tests/dbg-support.sub new file mode 100644 index 0000000..f68f8d9 --- /dev/null +++ b/tests/dbg-support.sub @@ -0,0 +1,26 @@ +# This file is intended to be sourced from one of the bashdb test programs + +sourced_fn() { + name="fn2" + echo "SOURCED FN LINENO $LINENO" + + # Print a stack trace + declare -i n + n=${#FUNCNAME[@]} + for (( i=0 ; (( i < $n )) ; i++ )) ; do + local -i j=i+1 + [ $j -eq $n ] && j=i # main()'s file is the same as the first caller + echo "FUNCNAME[$i]: ${FUNCNAME[$i]} called from ${BASH_SOURCE[$j]}" \ + "at line ${BASH_LINENO[$i]}" + done +} + +echo "SOURCED LINENO $LINENO" +echo "SOURCED BASH_SOURCE[0]" ${BASH_SOURCE[0]} +sourced_fn + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** + diff --git a/tests/dbg-support.tests b/tests/dbg-support.tests new file mode 100755 index 0000000..517591c --- /dev/null +++ b/tests/dbg-support.tests @@ -0,0 +1,139 @@ +#!../bash +# +# Test correct functioning bash debug support not via the bashdb +# debugger but merely by printing via print_trap() +# $Id: dbg-support.tests,v 1.13 2003/02/17 22:02:25 rockyb Exp $ +shopt -s extdebug +print_debug_trap() { + echo "debug lineno: $1 ${FUNCNAME[1]}" + return +} + +print_return_trap() { + echo "return lineno: $1 ${FUNCNAME[1]}" + return +} + +fn1() { + echo "LINENO $LINENO" + echo "LINENO $LINENO" + echo "BASH_SOURCE[0]" ${BASH_SOURCE[0]} + echo "FUNCNAME[0]" ${FUNCNAME[0]} + echo `caller` + echo `caller 0` + echo `caller 1` + echo `caller foo` +} + +fn2() { + echo "fn2 here. Calling fn1..." + fn1 +} + +fn3() { + echo "LINENO $LINENO" + echo "BASH_SOURCE[0]" ${BASH_SOURCE[0]} + + # Print a stack trace + declare -i n + n=${#FUNCNAME[@]} + for (( i=0 ; (( i < $n )) ; i++ )) ; do + local -i j=i+1 + [ $j -eq $n ] && j=i # main()'s file is the same as the first caller + echo "${FUNCNAME[$i]} called from file " \ + "\`${BASH_SOURCE[$j]}' at line ${BASH_LINENO[$j]}" + done + source ./dbg-support.sub +} + +fn4() { + echo "fn4 here. Calling fn3..." + fn3 +} + + +#!../bash +# +# Test of support for debugging facilities in bash +# +# Test debugger set option functrace - set on. Not in vanilla Bash 2.05 +# +set -o functrace +trap 'print_debug_trap $LINENO' DEBUG +trap 'print_return_trap $LINENO' RETURN + +# Funcname is now an array, but you still can't see it outside a function +echo "FUNCNAME" ${FUNCNAME[0]:-main} + +# We should trace into the below. +# Start easy with a simple function. +fn1 +fn2 +fn3 +source ./dbg-support.sub + +# Test debugger set option functrace - set off +set +T + +# We should not trace into this. +fn1 +fn2 +fn3 +fn4 +source ./dbg-support.sub + +# Another way to say: set -o functrace +set -T + +# We should trace into this. +source ./dbg-support.sub +set +T + +# Test that the line numbers in the presence of conditionals are correct. +for (( i=0 ; (( i <= 2 )) ; i++ )) ; do + if [ $i -eq 2 ] ; then + echo "Hit 2" + fi + j=4 +done + +# +# Check line numbers in command substitution +# +echo $(sourced_fn) +echo `sourced_fn` +x=$((sourced_fn)) +x={ sourced_fn } + +# Make sure we step into sourced_fn as a comand when we request to do so. +# Vanilla bash 2.0 doesn't do. +set -o functrace +x={ sourced_fn } + +# Should see line number of xyzzy below. Vanilla bash 2.05b doesn't do +case xyzzy in + a ) + x=5 + ;; + xyzz? ) + case 3 in + 2 ) + x=6 ;; + 3 ) + echo "got it" ;; + * ) echo "no good" ;; + esac + ;; + * ) +esac + +# Should see line numbers for initial for lines. +for i in 0 1 ; do + for j in 3 4 ; do + ((x=i+j)) + done +done +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/dbg-support2.right b/tests/dbg-support2.right new file mode 100644 index 0000000..c9d884e --- /dev/null +++ b/tests/dbg-support2.right @@ -0,0 +1,7 @@ +lineno: 17 (6) main +lineno: 18 (6) main +x is 1 +lineno: 19 (6) main +lineno: 20 (6) main +lineno: 21 (6) main +x is 1 diff --git a/tests/dbg-support2.tests b/tests/dbg-support2.tests new file mode 100755 index 0000000..fdc0f31 --- /dev/null +++ b/tests/dbg-support2.tests @@ -0,0 +1,26 @@ +#!../bash +# +# Test correct trap return codes = 2 means skip execution. +shopt -s extdebug +print_trap() { + echo "lineno: $1 ($LINENO) ${FUNCNAME[1]}" + if [[ $debug_exit == 2 ]] ; then + debug_exit=0 + return 2 + fi + return 0 +} + +debug_exit=0 +trap 'print_trap $LINENO' DEBUG + +x=1 +echo "x is $x" +debug_exit=2 +x=2 +echo "x is $x" + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/dollar-at-star b/tests/dollar-at-star new file mode 100755 index 0000000..25c2443 --- /dev/null +++ b/tests/dollar-at-star @@ -0,0 +1,226 @@ +# first, let's start with the basics + +recho "$@" +recho "$*" + +recho $@ +recho $* + +set a b + +recho "$*" + +# If IFS is null, the parameters are joined without separators +IFS='' +recho "$*" + +# If IFS is unset, the parameters are separated by spaces +unset IFS +recho "${*}" + +recho "$@" +recho $@ + +IFS='/' +set bob 'tom dick harry' joe +set $* +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set ${*} +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set $@ +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set ${@} +recho $# +recho $1 +recho $2 +recho $3 + +# according to POSIX.2, unquoted $* should expand to multiple words if +# $IFS is null, just like unquoted $@ +IFS='' +set bob 'tom dick harry' joe +set $* +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set $@ +recho $# +recho $1 +recho $2 +recho $3 + +# if IFS is unset, the individual positional parameters are split on +# " \t\n" if $* or $@ are unquoted +unset IFS +set bob 'tom dick harry' joe +set $* +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set $@ +recho $# +recho $1 +recho $2 +recho $3 + +# but not for "$@" or "$*" +set bob 'tom dick harry' joe +set "$*" +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set "$@" +recho $# +recho $1 +recho $2 +recho $3 + +# POSIX.2 says these should both expand the positional parameters +# to multiple words +set a b c d e +IFS="" +recho $@ +recho "$@" + +# this example is straight from the POSIX.2 rationale +set foo bar bam + +recho "$@" +recho "$*" + +unset IFS + +recho "$@" +recho $@ +recho "$*" + +IFS=: + +# special variables +set -- 1 2 3 4 5 6 7 8 9 10 + +bar=${*} +foo=$* +echo foo = "$foo" +echo bar = "$bar" + +foo1=$@ +bar1=${@} + +echo foo1 = "$foo1" +echo bar1 = "$bar1" + +foo2="$*" +bar2="${*}" + +echo foo2 = "$foo2" +echo bar2 = "$bar2" + +eval foo3='$*' bar3='${*}' +echo foo3 = "$foo3" +echo bar3 = "$bar3" + +case $* in +*\:*) echo ok 1;; +*) echo bad 1;; +esac + +case $@ in +*\:*) echo bad 2;; +*) echo ok 2;; +esac + +case "$*" in +*\:*) echo ok 3;; +*) echo bad 3;; +esac + +case "$@" in +*\:*) echo bad 4;; +*) echo ok 4;; +esac + +IFS=$' \t\n' + +bar=${*} +foo=$* +echo foo = "$foo" +echo bar = "$bar" + +foo1=$@ +bar1=${@} + +echo foo1 = "$foo1" +echo bar1 = "$bar1" + +foo2="$*" +bar2="${*}" + +echo foo2 = "$foo2" +echo bar2 = "$bar2" + +eval foo3='$*' bar3='${*}' +echo foo3 = "$foo3" +echo bar3 = "$bar3" + +case $* in +*\ *) echo ok 1;; +*) echo bad 1;; +esac + +case $@ in +*\ *) echo ok 2;; +*) echo bad 2;; +esac + +case "$*" in +*\ *) echo ok 3;; +*) echo bad 3;; +esac + +case "$@" in +*\ *) echo ok 4;; +*) echo bad 4;; +esac + +# tests for special expansion of "$*" and "${array[*]}" when used with other +# expansions -- bugs through bash-2.05b +${THIS_SH} ./dollar-star1.sub + +# tests for expansion of "$@" on rhs of things like ${param:+word}. Bugs +# though bash-2.05b +${THIS_SH} ./dollar-at1.sub + +# tests for expansion of other variables in double-quoted strings containing +# $@. Bugs through bash-2.05b +${THIS_SH} ./dollar-at2.sub + +# tests for various expansions of $* in different contexts -- word split, +# no splitting, etc. when $IFS is NUL +${THIS_SH} ./dollar-star2.sub + +exit 0 diff --git a/tests/dollar-at1.sub b/tests/dollar-at1.sub new file mode 100644 index 0000000..6d40786 --- /dev/null +++ b/tests/dollar-at1.sub @@ -0,0 +1,29 @@ +echo_argc() +{ + echo $# +} + +a() +{ + shift + echo_argc "$@" + echo_argc ${1:+"$@"} + echo_argc "${1:+$@}" + echo_argc 1 2 3 +} + +b() +{ + _IFS="$IFS" + IFS="$1" + shift + echo_argc "$@" + echo_argc ${1:+"$@"} + echo_argc "${1:+$@}" + echo_argc 1 2 3 + IFS="$_IFS" +} + +a "X" foo bar hoge + +b "X" foo bar hoge diff --git a/tests/dollar-at2.sub b/tests/dollar-at2.sub new file mode 100644 index 0000000..c079a29 --- /dev/null +++ b/tests/dollar-at2.sub @@ -0,0 +1,19 @@ +t1() +{ + xxx="echo $@" + + recho "$xxx ; echo $@" +} + +t2() +{ + xxx="echo $@" + + recho "${xxx} ; echo $@" +} + +t1 1 +t1 1 2 + +t2 1 +t2 1 2 diff --git a/tests/dollar-star1.sub b/tests/dollar-star1.sub new file mode 100644 index 0000000..63a9ef8 --- /dev/null +++ b/tests/dollar-star1.sub @@ -0,0 +1,31 @@ +set -- a b c +x=(a b c); IFS='|' + +echo "${*/#/x}" +echo "${x[*]/#/x}" + +echo "$*" +echo "${x[*]}" + +echo "$@" +echo "${x[@]}" + +echo "${@/#/x}" +echo "${x[@]/#/x}" + +echo "${*:1:2}" +echo "${x[*]:1:2}" + +echo "${@:1:2}" +echo "${x[@]:1:2}" + +IFS=$' \t\n' +set -- xa xb xc +x=(xa xb xc) +IFS='|' + +echo "${*#x}" +echo "${x[*]#x}" + +echo "$*" +echo "${x[*]}" diff --git a/tests/dollar-star2.sub b/tests/dollar-star2.sub new file mode 100644 index 0000000..844a297 --- /dev/null +++ b/tests/dollar-star2.sub @@ -0,0 +1,26 @@ +set A B + +IFS= + +x=$* +y="$*" + +recho "$x" +recho "$y" + +IFS=$' \t\n' + +set 'A B' 'C D' + +IFS= + +x=$* +y="$*" + +recho "$x" +recho "$y" + +recho $x +recho $* +recho $y +recho "$*" diff --git a/tests/dollar.right b/tests/dollar.right new file mode 100644 index 0000000..ff57f1c --- /dev/null +++ b/tests/dollar.right @@ -0,0 +1,136 @@ +argv[1] = <> +argv[1] = <a b> +argv[1] = <ab> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <1> +argv[1] = <bob> +argv[2] = <tom> +argv[3] = <dick> +argv[4] = <harry> +argv[5] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom> +argv[2] = <dick> +argv[3] = <harry> +argv[1] = <joe> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foobarbam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo bar bam> +foo = 1:2:3:4:5:6:7:8:9:10 +bar = 1:2:3:4:5:6:7:8:9:10 +foo1 = 1 2 3 4 5 6 7 8 9 10 +bar1 = 1 2 3 4 5 6 7 8 9 10 +foo2 = 1:2:3:4:5:6:7:8:9:10 +bar2 = 1:2:3:4:5:6:7:8:9:10 +foo3 = 1:2:3:4:5:6:7:8:9:10 +bar3 = 1:2:3:4:5:6:7:8:9:10 +ok 1 +ok 2 +ok 3 +ok 4 +foo = 1 2 3 4 5 6 7 8 9 10 +bar = 1 2 3 4 5 6 7 8 9 10 +foo1 = 1 2 3 4 5 6 7 8 9 10 +bar1 = 1 2 3 4 5 6 7 8 9 10 +foo2 = 1 2 3 4 5 6 7 8 9 10 +bar2 = 1 2 3 4 5 6 7 8 9 10 +foo3 = 1 2 3 4 5 6 7 8 9 10 +bar3 = 1 2 3 4 5 6 7 8 9 10 +ok 1 +ok 2 +ok 3 +ok 4 +xa|xb|xc +xa|xb|xc +a|b|c +a|b|c +a b c +a b c +xa xb xc +xa xb xc +a|b +b|c +a b +b c +a|b|c +a|b|c +xa|xb|xc +xa|xb|xc +3 +3 +3 +3 +3 +3 +3 +3 +argv[1] = <echo 1 ; echo 1> +argv[1] = <echo 1 2 ; echo 1> +argv[2] = <2> +argv[1] = <echo 1 ; echo 1> +argv[1] = <echo 1 2 ; echo 1> +argv[2] = <2> +argv[1] = <AB> +argv[1] = <AB> +argv[1] = <A BC D> +argv[1] = <A BC D> +argv[1] = <A BC D> +argv[1] = <A B> +argv[2] = <C D> +argv[1] = <A BC D> +argv[1] = <A BC D> diff --git a/tests/dstack.right b/tests/dstack.right new file mode 100644 index 0000000..73a006c --- /dev/null +++ b/tests/dstack.right @@ -0,0 +1,55 @@ +./dstack.tests: line 6: pushd: /tmp/xxx-notthere: No such file or directory +./dstack.tests: line 9: pushd: no other directory +./dstack.tests: line 10: popd: directory stack empty +./dstack.tests: line 13: pushd: -m: invalid number +pushd: usage: pushd [dir | +N | -N] [-n] +./dstack.tests: line 14: popd: -m: invalid number +popd: usage: popd [+N | -N] [-n] +./dstack.tests: line 15: dirs: -m: invalid number +dirs: usage: dirs [-clpv] [+N] [-N] +./dstack.tests: line 16: dirs: 7: invalid option +dirs: usage: dirs [-clpv] [+N] [-N] +/ +ok +/usr / +/usr / +/usr / +/usr / +/usr / +/ +/usr / +/etc /usr / +/etc /usr / +/etc /usr / + 0 /etc + 1 /usr + 2 / +/usr /etc / +/etc /usr / +/tmp /etc /usr / +/tmp +/tmp +/usr +/usr +./dstack.tests: line 58: dirs: 9: directory stack index out of range +./dstack.tests: line 58: dirs: 9: directory stack index out of range +./dstack.tests: line 59: pushd: +9: directory stack index out of range +./dstack.tests: line 59: pushd: -9: directory stack index out of range +./dstack.tests: line 60: popd: +9: directory stack index out of range +./dstack.tests: line 60: popd: -9: directory stack index out of range +/tmp /etc / +/tmp /etc / +/tmp /etc / +/tmp /usr /etc / +/tmp +/tmp /usr /etc / +/tmp /usr /etc / +/tmp +/tmp /bin /etc / +/tmp +/tmp /bin / +/tmp +/bin / /tmp +/bin / /tmp +/bin +/bin diff --git a/tests/dstack.tests b/tests/dstack.tests new file mode 100644 index 0000000..6c4cef1 --- /dev/null +++ b/tests/dstack.tests @@ -0,0 +1,87 @@ +export LC_ALL=C +export LANG=C + +dirs -c +# error -- nonexistant directory +pushd /tmp/xxx-notthere + +# errors -- empty stack +pushd +popd + +# errors -- bad numeric arguments -- should not cause the script to exit +pushd -m +popd -m +dirs -m +dirs 7 + +MYDIR=$PWD +unalias cd 2>/dev/null + +unalias -a + +command cd -P / +command pwd -P # better be `/' + +case "$OLDPWD" in +$MYDIR) echo ok ;; +*) echo oops -- bad \$OLDPWD ;; +esac + +pushd /usr +echo $PWD $OLDPWD +dirs +echo ${DIRSTACK[@]} + +# this should not change the directory stack at all +pushd -n +0 +dirs + +popd +pushd /usr + +pushd /etc +dirs +dirs -l +dirs -v + +# two consecutive `pushd's should swap the top two stack elements, then +# swap them back, leaving the stack intact +pushd +pushd + +pushd /tmp +echo ${DIRSTACK[0]} ; dirs +0 +echo ${DIRSTACK[2]} ; dirs +2 + +# these should be errors, but not affect the directory stack +dirs +9; dirs -9 +pushd +9 ; pushd -9 +popd +9 ; popd -9 + +popd -n +2 +dirs +echo ${DIRSTACK[@]} + +pushd -n /usr +echo $PWD +dirs +echo ${DIRSTACK[@]} + +builtin pwd + +DIRSTACK[1]=/bin +dirs + +builtin pwd +popd +2 +builtin pwd -L +pushd -1 +dirs +echo ${DIRSTACK[0]} + +dirs -c +dirs + +# this is for the benefit of pure coverage +cd $MYDIR diff --git a/tests/dstack2.right b/tests/dstack2.right new file mode 100644 index 0000000..d682a27 --- /dev/null +++ b/tests/dstack2.right @@ -0,0 +1,24 @@ +expect ~1 +~1 +/usr / +/tmp /usr / +/tmp /usr / +these lines should be the same +/tmp +/tmp /tmp +these lines should be the same +/usr +/usr /usr +these lines should be the same +/ +/ / +these lines should be the same +/tmp +/tmp /tmp +these lines should be the same +/usr +/usr /usr + 1 /usr +these lines should be the same +/ +/ / diff --git a/tests/dstack2.tests b/tests/dstack2.tests new file mode 100644 index 0000000..d902bff --- /dev/null +++ b/tests/dstack2.tests @@ -0,0 +1,33 @@ +cd / + +echo expect '~1' +echo ~1 + +pushd /usr +pushd /tmp +dirs + +echo these lines should be the same +dirs +0 +echo ~0 ${DIRSTACK[0]} +echo these lines should be the same +dirs +1 +echo ~1 ${DIRSTACK[1]} +echo these lines should be the same +dirs +2 +echo ~2 ${DIRSTACK[2]} + +NDIRS=$(( ${#DIRSTACK[@]} - 1 )) + +echo these lines should be the same +dirs -2 +echo ~-2 ${DIRSTACK[NDIRS-2]} + +echo these lines should be the same +dirs -1 +echo ~-1 ${DIRSTACK[NDIRS-1]} +dirs -v -1 + +echo these lines should be the same +dirs -0 +echo ~-0 ${DIRSTACK[NDIRS]} diff --git a/tests/errors.right b/tests/errors.right new file mode 100644 index 0000000..ac987fb --- /dev/null +++ b/tests/errors.right @@ -0,0 +1,100 @@ +./errors.tests: line 17: alias: -x: invalid option +alias: usage: alias [-p] [name[=value] ... ] +./errors.tests: line 18: unalias: -x: invalid option +unalias: usage: unalias [-a] name [name ...] +./errors.tests: line 19: alias: hoowah: not found +./errors.tests: line 20: unalias: hoowah: not found +./errors.tests: line 23: `1': not a valid identifier +declare -fr func +./errors.tests: line 36: func: readonly function +./errors.tests: line 39: unset: -x: invalid option +unset: usage: unset [-f] [-v] [name ...] +./errors.tests: line 42: unset: func: cannot unset: readonly function +./errors.tests: line 45: declare: func: readonly function +./errors.tests: line 49: unset: XPATH: cannot unset: readonly variable +./errors.tests: line 52: unset: `/bin/sh': not a valid identifier +./errors.tests: line 55: unset: cannot simultaneously unset a function and a variable +./errors.tests: line 58: declare: -z: invalid option +declare: usage: declare [-afFirtx] [-p] [name[=value] ...] +./errors.tests: line 60: declare: `-z': not a valid identifier +./errors.tests: line 61: declare: `/bin/sh': not a valid identifier +./errors.tests: line 65: declare: cannot use `-f' to make functions +./errors.tests: line 68: exec: -i: invalid option +exec: usage: exec [-cl] [-a name] file [redirection ...] +./errors.tests: line 72: export: XPATH: not a function +./errors.tests: line 75: break: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 76: continue: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 79: shift: label: numeric argument required +./errors.tests: line 84: shift: too many arguments +./errors.tests: line 90: let: expression expected +./errors.tests: line 93: local: can only be used in a function +./errors.tests: line 96: logout: not login shell: use `exit' +./errors.tests: line 99: hash: notthere: not found +./errors.tests: line 102: hash: -v: invalid option +hash: usage: hash [-lr] [-p pathname] [-dt] [name ...] +./errors.tests: line 106: hash: hashing disabled +./errors.tests: line 109: export: `AA[4]': not a valid identifier +./errors.tests: line 110: readonly: `AA[4]': not a valid identifier +./errors.tests: line 113: [-2]: bad array subscript +./errors.tests: line 117: AA: readonly variable +./errors.tests: line 121: AA: readonly variable +./errors.tests: line 129: shift: 5: shift count out of range +./errors.tests: line 130: shift: -2: shift count out of range +./errors.tests: line 133: shopt: no_such_option: invalid shell option name +./errors.tests: line 134: shopt: no_such_option: invalid shell option name +./errors.tests: line 137: umask: 09: octal number out of range +./errors.tests: line 138: umask: `:': invalid symbolic mode character +./errors.tests: line 139: umask: `:': invalid symbolic mode operator +./errors.tests: line 142: umask: -i: invalid option +umask: usage: umask [-p] [-S] [mode] +./errors.tests: line 146: umask: `u': invalid symbolic mode character +./errors.tests: line 155: VAR: readonly variable +./errors.tests: line 158: declare: VAR: readonly variable +./errors.tests: line 159: declare: VAR: readonly variable +./errors.tests: line 161: declare: unset: not found +./errors.tests: line 164: VAR: readonly variable +./errors.tests: command substitution: line 168: syntax error: unexpected end of file +./errors.tests: command substitution: line 168: syntax error near unexpected token `done' +./errors.tests: command substitution: line 168: ` for z in 1 2 3; done ' +./errors.tests: line 171: cd: HOME not set +./errors.tests: line 172: cd: /tmp/xyz.bash: No such file or directory +./errors.tests: line 174: cd: OLDPWD not set +./errors.tests: line 175: cd: /bin/sh: Not a directory +./errors.tests: line 177: cd: /tmp/cd-notthere: No such file or directory +./errors.tests: line 180: .: filename argument required +.: usage: . filename [arguments] +./errors.tests: line 181: source: filename argument required +source: usage: source filename [arguments] +./errors.tests: line 184: .: -i: invalid option +.: usage: . filename [arguments] +./errors.tests: line 187: set: -q: invalid option +set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] +./errors.tests: line 190: enable: sh: not a shell builtin +./errors.tests: line 190: enable: bash: not a shell builtin +./errors.tests: line 193: shopt: cannot set and unset shell options simultaneously +./errors.tests: line 196: read: var: invalid timeout specification +./errors.tests: line 199: read: `/bin/sh': not a valid identifier +./errors.tests: line 202: VAR: readonly variable +./errors.tests: line 205: readonly: -x: invalid option +readonly: usage: readonly [-af] [name[=value] ...] or readonly -p +./errors.tests: line 208: eval: -i: invalid option +eval: usage: eval [arg ...] +./errors.tests: line 209: command: -i: invalid option +command: usage: command [-pVv] command [arg ...] +./errors.tests: line 212: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 213: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 216: trap: NOSIG: invalid signal specification +./errors.tests: line 219: trap: -s: invalid option +trap: usage: trap [-lp] [arg signal_spec ...] +./errors.tests: line 225: return: can only `return' from a function or sourced script +./errors.tests: line 229: break: 0: loop count out of range +./errors.tests: line 233: continue: 0: loop count out of range +./errors.tests: line 238: builtin: bash: not a shell builtin +./errors.tests: line 242: bg: no job control +./errors.tests: line 243: fg: no job control +./errors.tests: line 246: kill: -s: option requires an argument +./errors.tests: line 248: kill: S: invalid signal specification +./errors.tests: line 250: kill: `': not a pid or valid job spec +kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec] +./errors.tests: line 255: set: trackall: invalid option name +./errors.tests: line 262: `!!': not a valid identifier diff --git a/tests/errors.tests b/tests/errors.tests new file mode 100644 index 0000000..4ead467 --- /dev/null +++ b/tests/errors.tests @@ -0,0 +1,265 @@ +# These should all be safe +LC_ALL=C +LC_CTYPE=C +LC_COLLATE=C +LC_MESSAGES=C + +# these tests should all generate errors + +# make sure we don't exit prematurely +set +e +set +o posix + +# various alias/unalias errors + +# at some point, this may mean to `export' an alias, like ksh, but +# for now it is an error +alias -x foo=barz +unalias -x fooaha +alias hoowah +unalias hoowah + +# the iteration variable must be a valid identifier +for 1 in a b c; do echo $1; done + +# try to rebind a read-only function +func() +{ + echo func +} +readonly -f func +# make sure `readonly' and `declare' play well together +declare -Fr +func() +{ + echo bar +} + +# bad option +unset -x func + +# cannot unset readonly functions or variables +unset -f func +# or make them not readonly +declare -fr func +declare -f +r func + +XPATH=$PATH +declare -r XPATH +unset -v XPATH + +# cannot unset invalid identifiers +unset /bin/sh + +# cannot unset function and variable at the same time +unset -f -v SHELL + +# bad option +declare -z +# cannot declare invalid identifiers +declare -- -z +declare /bin/sh + +# this is the syntax used to export functions in the environment, but +# it cannot be used with `declare' +declare -f func='() { echo "this is func"; }' + +# bad option to exec -- this should not exit the script +exec -i /bin/sh + +# try to export -f something that is not a function -- this should be +# an error, not create an `invisible function' +export -f XPATH + +# this depends on the setting of BREAK_COMPLAINS in config.h.in +break +continue + +# this should not exit the shell; it did in versions before 2.01 +shift label + +# other shells do not complain about the extra arguments; maybe someday +# we won't either +set -- a b c +shift $# label +# and get rid of the positional parameters +shift $# + +# let without an expression is an error, though maybe it should just return +# success +let + +# local outside a function is an error +local + +# logout of a non-login shell is an error +logout + +# try to hash a non-existant command +hash notthere + +# bad option to hash, although it may mean `verbose' at some future point +hash -v + +# turn off hashing, then try to hash something +set +o hashall +hash -p ${THIS_SH} ${THIS_SH##*/} + +# bad identifiers to declare/readonly/export +export AA[4] +readonly AA[4] + +declare -a AA +unset AA[-2] + +# try to assign to a readonly array +declare -r AA +AA=( one two three ) + +# make sure `readonly -n' doesn't turn off readonly status +readonly -n AA +AA=(one two three) + +# try to assign a readonly array with bad assignment syntax +# NOTE: this works in post-bash-2.05 (at least when I write this) +# readonly -a ZZZ=bbb + +# bad counts to `shift' +shopt -s shift_verbose +shift $(( $# + 5 )) +shift -2 + +# bad shell options +shopt -s no_such_option +shopt no_such_option + +# non-octal digits for umask and other errors +umask 09 +umask -S u=rwx:g=rwx:o=rx >/dev/null # 002 +umask -S u:rwx,g:rwx,o:rx >/dev/null # 002 + +# at some point, this may mean `invert', but for now it is an error +umask -i + +# bad assignments shouldn't change the umask +mask=$(umask) +umask g=u +mask2=$(umask) +if [ "$mask" != "$mask2" ]; then + echo "umask errors change process umask" +fi + +# assignment to a readonly variable in environment +VAR=4 +readonly VAR +VAR=7 : + +# more readonly variable tests +declare VAR=88 +declare +r VAR + +declare -p unset + +# iteration variable in a for statement being readonly +for VAR in 1 2 3 ; do echo $VAR; done + +# parser errors +: $( for z in 1 2 3; do ) +: $( for z in 1 2 3; done ) + +# various `cd' errors +( unset HOME ; cd ) +( HOME=/tmp/xyz.bash ; cd ) +# errors from cd +cd - +cd /bin/sh # error - not a directory +OLDPWD=/tmp/cd-notthere +cd - + +# various `source/.' errors +. +source + +# maybe someday this will work like in rc +. -i /dev/tty + +# make sure that this gives an error rather than setting $1 +set -q + +# enable non-builtins +enable sh bash + +# try to set and unset shell options simultaneously +shopt -s -u checkhash + +# this is an error -- bad timeout spec +read -t var < /dev/null + +# try to read into an invalid identifier +read /bin/sh < /dev/null + +# try to read into a readonly variable +read VAR < /dev/null + +# bad option to readonly/export +readonly -x foo + +# someday these may mean something, but for now they're errors +eval -i "echo $-" +command -i "echo $-" + +# this caused a core dump in bash-2.01 (fixed in bash-2.01.1) +eval echo \$[/bin/sh + 0] +eval echo '$((/bin/sh + 0))' + +# error to list trap for an unknown signal +trap -p NOSIG + +# maybe someday trap will take a -s argument like kill, but not now +trap -p -s NOSIG + +# we have a ksh-like ERR trap, post-bash-2.05 +#trap 'echo [$LINENO] -- error' ERR + +# can only return from a function or sourced script +return 2 + +# break and continue with arguments <= 0 +for z in 1 2 3; do + break 0 + echo $x +done +for z in 1 2 3; do + continue 0 + echo $x +done + +# builtin with non-builtin +builtin bash + +# maybe someday you will be able to use fg/bg when job control is not really +# active, but for now they are errors +bg +fg + +# argument required +kill -s +# bad argument +kill -S +# null argument +kill -INT '' +# argument required +kill -INT + +# bad shell option names +set -o trackall # bash is not ksh + +# 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 +# immediately +set -o posix +function !! () { fc -s "$@" ; } +set +o posix + +echo end diff --git a/tests/exec.right b/tests/exec.right new file mode 100644 index 0000000..d65b89d --- /dev/null +++ b/tests/exec.right @@ -0,0 +1,54 @@ +before exec1.sub: one two three +calling exec1.sub +aa bb cc dd ee +after exec1.sub with args: 0 + +after exec1.sub without args: 0 +./execscript: line 20: notthere: command not found +127 +/tmp/bash: notthere: No such file or directory +127 +/bin/sh: /bin/sh: cannot execute binary file +126 +./execscript: line 39: /: is a directory +126 +/: /: is a directory +126 +./execscript: line 46: .: /: is a directory +1 +127 +0 +this is bashenv +./exec3.sub: line 3: /tmp/bash-notthere: No such file or directory +./exec3.sub: line 3: exec: /tmp/bash-notthere: cannot execute: No such file or directory +126 +./execscript: line 68: notthere: No such file or directory +127 +./execscript: line 71: notthere: No such file or directory +127 +./execscript: line 74: notthere: No such file or directory +127 +this is sh +this is sh +unset +ok +5 +./exec5.sub: line 4: exec: bash-notthere: not found +127 +this is ohio-state +0 +1 +1 +0 +42 +42 +0 +1 +1 +0 +0 +1 +0 +1 +testb +after diff --git a/tests/exec1.sub b/tests/exec1.sub new file mode 100755 index 0000000..4a12501 --- /dev/null +++ b/tests/exec1.sub @@ -0,0 +1 @@ +echo "$@" diff --git a/tests/exec2.sub b/tests/exec2.sub new file mode 100644 index 0000000..c1caaea --- /dev/null +++ b/tests/exec2.sub @@ -0,0 +1,5 @@ +# make sure an exit command in an exit trap sets the shell's exit status +trap - 0 +trap 'exit 5' 0 + +exit 0 diff --git a/tests/exec3.sub b/tests/exec3.sub new file mode 100644 index 0000000..4f2f8e2 --- /dev/null +++ b/tests/exec3.sub @@ -0,0 +1,6 @@ +shopt -s execfail + +exec /tmp/bash-notthere +# make sure we're still around +echo $? + diff --git a/tests/exec4.sub b/tests/exec4.sub new file mode 100644 index 0000000..a60d8b3 --- /dev/null +++ b/tests/exec4.sub @@ -0,0 +1,8 @@ +# let's test out the noexec code +set -n + +fail +whoops +wow + +set +n diff --git a/tests/exec5.sub b/tests/exec5.sub new file mode 100644 index 0000000..1462f9e --- /dev/null +++ b/tests/exec5.sub @@ -0,0 +1,9 @@ +# try exec'ing a command that cannot be found in $PATH +shopt -s execfail + +exec bash-notthere +# make sure we're still around +echo $? + +# now we need to go away, but this should echo 'this is ohio-state' +exec -a ohio-state ${THIS_SH} -c 'echo this is $0' diff --git a/tests/exec6.sub b/tests/exec6.sub new file mode 100644 index 0000000..50d0e70 --- /dev/null +++ b/tests/exec6.sub @@ -0,0 +1,54 @@ +# builtins with exit status inverted + +( true ) +echo $? +( ! true ) +echo $? + +( false ) +echo $? +( ! false ) +echo $? + +# inverting shouldn't affect exit +(exit 42) +echo $? + +( ! exit 42 ) +echo $? + +# commands requiring an exec with exit status inverted -- broken in bash-2.04 + +( ls > /dev/null 2>&1 ) +echo $? +( ! ls > /dev/null 2>&1 ) +echo $? + +touch /tmp/notwrite +chmod 400 /tmp/notwrite + +# make sure redirection failures in commands whose exit status is inverted +# are handled correctly + +( ls > /tmp/notwrite ) 2>/dev/null +echo $? + +( ! ls > /tmp/notwrite ) 2>/dev/null +echo $? + +# now add exit traps, true and false for commands with and without exit +# status inversion + +(trap 'false' 0 ; ! ls > /tmp/notwrite ) 2>/dev/null +echo $? + +(trap 'false' 0 ; ls > /tmp/notwrite ) 2>/dev/null +echo $? + +(trap 'true' 0 ; ! ls > /tmp/notwrite ) 2>/dev/null +echo $? + +(trap 'true' 0 ; ls > /tmp/notwrite ) 2>/dev/null +echo $? + +rm -f /tmp/notwrite diff --git a/tests/exec7.sub b/tests/exec7.sub new file mode 100644 index 0000000..ea2fd06 --- /dev/null +++ b/tests/exec7.sub @@ -0,0 +1,20 @@ +# make sure that bash really checks the right things when deciding what +# constitutes an executable file + +[ $UID -eq 0 ] && { echo "exec7.sub: the test suite should not be run as root" >&2 ; } + +: ${TMPDIR:=/tmp} + +cd $TMPDIR || { echo "cannot cd to $TMPDIR" >&2 ; exit 2; } + +mkdir testa testb + +echo 'echo "testa"' > testa/foo +echo 'echo "testb"' > testb/foo + +chmod 655 testa/foo +chmod 755 testb/foo + +PATH=$TMPDIR/testa:$TMPDIR/testb $THIS_SH -c foo + +rm -rf testa testb diff --git a/tests/execscript b/tests/execscript new file mode 100644 index 0000000..09a4ba5 --- /dev/null +++ b/tests/execscript @@ -0,0 +1,110 @@ +export LC_ALL=C +export LANG=C + +if [ $UID -eq 0 ]; then + echo "execscript: the test suite should not be run as root" >&2 +fi + +set -- one two three +echo before exec1.sub: "$@" +echo calling exec1.sub +./exec1.sub aa bb cc dd ee +echo after exec1.sub with args: $? +./exec1.sub +echo after exec1.sub without args: $? + +# set up a fixed path so we know notthere will not be found +PATH=/usr/bin:/bin:/usr/local/bin: +export PATH + +notthere +echo $? + +# this is iffy, since the error messages may vary from system to system +# and /tmp might not exist +ln -s ${THIS_SH} /tmp/bash 2>/dev/null +if [ -f /tmp/bash ]; then + /tmp/bash notthere +else + ${THIS_SH} notthere +fi +echo $? +rm -f /tmp/bash + +# /bin/sh should be there on all systems +${THIS_SH} /bin/sh +echo $? + +# try executing a directory +/ +echo $? + +${THIS_SH} / +echo $? + +# try sourcing a directory +. / +echo $? + +# try sourcing a binary file -- post-2.04 versions don't do the binary file +# check, and will probably fail with `command not found', or status 127 +. ${THIS_SH} 2>/dev/null +echo $? + +# post-bash-2.05 versions allow sourcing non-regular files +. /dev/null +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 +${THIS_SH} ./exec3.sub +rm -f /tmp/bashenv +unset BASH_ENV + +# we're resetting the $PATH to empty, so this should be last +PATH= + +notthere +echo $? + +command notthere +echo $? + +command -p notthere +echo $? + +# but -p should guarantee that we find all the standard utilities, even +# with an empty or unset $PATH +command -p sh -c 'echo this is $0' +unset PATH +command -p sh -c 'echo this is $0' + +# a bug in bash before bash-2.01 caused PATH to be set to the empty string +# when command -p was run with PATH unset +echo ${PATH-unset} + +echo "echo ok" | ${THIS_SH} -t + +${THIS_SH} ./exec2.sub +echo $? + +${THIS_SH} ./exec4.sub + +# try exec'ing a command that cannot be found in $PATH +${THIS_SH} ./exec5.sub + +# this was a bug in bash versions before bash-2.04 +${THIS_SH} -c 'cat </dev/null | cat >/dev/null' >&- + +# checks for proper return values in subshell commands with inverted return +# values + +${THIS_SH} ./exec6.sub + +# checks for properly deciding what constitutes an executable file +${THIS_SH} ./exec7.sub + +true | `echo true` & + +echo after diff --git a/tests/exp-tests b/tests/exp-tests new file mode 100644 index 0000000..884b5a6 --- /dev/null +++ b/tests/exp-tests @@ -0,0 +1,380 @@ +# +# A suite of tests for bash word expansions +# +# This tests parameter and variable expansion, with an empahsis on +# proper quoting behavior. +# +# Chet Ramey + +# +# If you comment out the body of this function, you can do a diff against +# `expansion-tests.right' to see if the shell is behaving correctly +# +expect() +{ + echo expect "$@" +} + +# Test the substitution quoting characters (CTLESC and CTLNUL) in different +# combinations + +expect "<^A>" +recho `echo ''` +expect "<^A>" +recho `echo ""` +expect "<^B>" +recho `echo ''` +expect "<^B>" +recho `echo ""` +expect "<^A>" +recho `echo ` +expect "<^B>" +recho `echo ` + +# Test null strings without variable expansion +expect "<abcdefgh>" +recho abcd""efgh +expect "<abcdefgh>" +recho abcd''efgh +expect "<abcdefgh>" +recho ""abcdefgh +expect "<abcdefgh>" +recho ''abcdefgh +expect "<abcd>" +recho abcd"" +expect "<abcd>" +recho abcd'' + +# Test the quirky behavior of $@ in "" +expect nothing +recho "$@" +expect "< >" +recho " $@" +expect "<-->" +recho "-${@}-" + +# Test null strings with variable expansion that fails +expect '<>' +recho $xxx"" +expect '<>' +recho ""$xxx +expect '<>' +recho $xxx'' +expect '<>' +recho ''$xxx +expect '<>' +recho $xxx""$yyy +expect '<>' +recho $xxx''$yyy + +# Test null strings with variable expansion that succeeds +xxx=abc +yyy=def + +expect '<abc>' +recho $xxx"" +expect '<abc>' +recho ""$xxx +expect '<abc>' +recho $xxx'' +expect '<abc>' +recho ''$xxx +expect '<abcdef>' +recho $xxx""$yyy +expect '<abcdef>' +recho $xxx''$yyy + +unset xxx yyy + +# Test the unquoted special quoting characters +expect "<^A>" +recho +expect "<^B>" +recho +expect "<^A>" +recho "" +expect "<^B>" +recho "" +expect "<^A>" +recho '' +expect "<^B>" +recho '' + +# Test expansion of a variable that is unset +expect nothing +recho $xxx +expect '<>' +recho "$xxx" + +expect nothing +recho "$xxx${@}" + +# Test empty string expansion +expect '<>' +recho "" +expect '<>' +recho '' + +# Test command substitution with (disabled) history substitution +expect '<Hello World!>' +# set +H +recho "`echo \"Hello world!\"`" + +# Test some shell special characters +expect '<`>' +recho "\`" +expect '<">' +recho "\"" +expect '<\^A>' +recho "\" + +expect '<\$>' +recho "\\$" + +expect '<\\>' +recho "\\\\" + +# This should give argv[1] = a argv[2] = b +expect '<a> <b>' +FOO=`echo 'a b' | tr ' ' '\012'` +recho $FOO + +# This should give argv[1] = ^A argv[2] = ^B +expect '<^A> <^B>' +FOO=`echo ' ' | tr ' ' '\012'` +recho $FOO + +# Test quoted and unquoted globbing characters +expect '<**>' +recho "*"* + +expect '<\.\./*/>' +recho "\.\./*/" + +# Test patterns that come up when the shell quotes funny character +# combinations +expect '<^A^B^A^B>' +recho '' +expect '<^A^A>' +recho '' +expect '<^A^B>' +recho '' +expect '<^A^A^B>' +recho '' + +# More tests of "$@" +set abc def ghi jkl +expect '< abc> <def> <ghi> <jkl >' +recho " $@ " +expect '< abc> <def> <ghi> <jkl >' +recho "${1+ $@ }" + +set abc def ghi jkl +expect '<--abc> <def> <ghi> <jkl-->' +recho "--$@--" + +set "a b" cd ef gh +expect '<a b> <cd> <ef> <gh>' +recho ${1+"$@"} +expect '<a b> <cd> <ef> <gh>' +recho ${foo:-"$@"} +expect '<a b> <cd> <ef> <gh>' +recho "${@}" + +expect '< >' +recho " " +expect '< - >' +recho " - " + +# Test combinations of different types of quoting in a fully-quoted string +# (so the WHOLLY_QUOTED tests fail and it doesn't get set) +expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>' +recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/" + +# Test the various Posix parameter expansions + +expect '<foo bar>' +recho "${x:-$(echo "foo bar")}" +expect '<foo> <bar>' +recho ${x:-$(echo "foo bar")} + +unset X +expect '<abc>' +recho ${X:=abc} +expect '<abc>' +recho $X + +set a b c +expect '<posix>' +recho ${3:+posix} + +POSIX=/usr/posix +expect '<10>' +recho ${#POSIX} + +# remove shortest trailing match +x=file.c +expect '<file.o>' +recho ${x%.c}.o + +# remove longest trailing match +x=posix/src/std +expect '<posix>' +recho ${x%%/*} + +# remove shortest leading pattern +x=$HOME/src/cmd +expect '</src/cmd>' +recho ${x#$HOME} + +# remove longest leading pattern +x=/one/two/three +expect '<three>' +recho ${x##*/} + +# pattern removal of patterns that don't match +z=abcdef + +expect '<abcdef>' +recho ${z#xyz} +expect '<abcdef>' +recho ${z##xyz} + +expect '<abcdef>' +recho ${z%xyz} +expect '<abcdef>' +recho ${z%%xyz} + +# Command substitution and the quirky differences between `` and $() + +expect '<\$x>' +recho '\$x' + +expect '<$x>' +recho `echo '\$x'` + +expect '<\$x>' +recho $(echo '\$x') + +# The difference between $* "$*" and "$@" + +set "abc" "def ghi" "jkl" + +expect '<abc> <def> <ghi> <jkl>' +recho $* + +expect '<abc def ghi jkl>' +recho "$*" + +OIFS="$IFS" +IFS=":$IFS" + +# The special behavior of "$*", using the first character of $IFS as separator +expect '<abc:def ghi:jkl>' +recho "$*" + +IFS="$OIFS" + +expect '<abc> <def ghi> <jkl>' +recho "$@" + +expect '<xxabc> <def ghi> <jklyy>' +recho "xx$@yy" + +expect '<abc> <def ghi> <jklabc> <def ghi> <jkl>' +recho "$@$@" + +foo=abc +bar=def + +expect '<abcdef>' +recho "$foo""$bar" + +unset foo +set $foo bar '' xyz "$foo" abc + +expect '<bar> <> <xyz> <> <abc>' +recho "$@" + +# More tests of quoting and deferred evaluation + +foo=10 x=foo +y='$'$x +expect '<$foo>' +recho $y +eval y='$'$x +expect '<10>' +recho $y + +# case statements + +NL=' +' +x='ab +cd' + +expect '<newline expected>' +case "$x" in +*$NL*) recho "newline expected" ;; +esac + +expect '<got it>' +case \? in +*"?"*) recho "got it" ;; +esac + +expect '<got it>' +case \? in +*\?*) recho "got it" ;; +esac + +set one two three four five +expect '<one> <three> <five>' +recho $1 $3 ${5} $8 ${9} + +# length tests on positional parameters and some special parameters + +expect '<5> <5>' +recho $# ${#} +expect '<3>' +recho ${#1} +expect '<1>' +recho ${##} +expect '<1>' +recho ${#?} +expect '<5>' +recho ${#@} +expect '<5>' +recho ${#*} +expect '<5>' +recho "${#@}" +expect '<5>' +recho "${#*}" + +expect '<42>' +recho $((28 + 14)) +expect '<26>' +recho $[ 13 * 2 ] + +expect '<\>' +recho `echo \\\\` + +expect '<~>' +recho '~' + +expect nothing +recho $! +expect nothing +recho ${!} + +# test word splitting of assignment statements not preceding a command +a="a b c d e" +declare b=$a +expect '<a> <b> <c> <d> <e>' +recho $b + +a="a?b?c" + +echo ${a//\\?/ } + +echo ${a//\?/ } diff --git a/tests/exp.right b/tests/exp.right new file mode 100644 index 0000000..fdadbd9 --- /dev/null +++ b/tests/exp.right @@ -0,0 +1,147 @@ +argv[1] = <^A> +argv[1] = <^A> +argv[1] = <^B> +argv[1] = <^B> +argv[1] = <^A> +argv[1] = <^B> +argv[1] = <abcdefgh> +argv[1] = <abcdefgh> +argv[1] = <abcdefgh> +argv[1] = <abcdefgh> +argv[1] = <abcd> +argv[1] = <abcd> +argv[1] = < > +argv[1] = <--> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <^A> +argv[1] = <^B> +argv[1] = <^A> +argv[1] = <^B> +argv[1] = <^A> +argv[1] = <^B> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <Hello world!> +argv[1] = <`> +argv[1] = <"> +argv[1] = <\^A> +argv[1] = <\$> +argv[1] = <\\> +argv[1] = <a> +argv[2] = <b> +argv[1] = <^A> +argv[2] = <^B> +argv[1] = <**> +argv[1] = <\.\./*/> +argv[1] = <^A^B^A^B> +argv[1] = <^A^A> +argv[1] = <^A^B> +argv[1] = <^A^A^B> +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--> +argv[1] = <a b> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <a b> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <a b> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = < > +argv[1] = < - > +argv[1] = </^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/> +argv[1] = <foo bar> +argv[1] = <foo> +argv[2] = <bar> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <posix> +argv[1] = <10> +argv[1] = <file.o> +argv[1] = <posix> +argv[1] = </src/cmd> +argv[1] = <three> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <\$x> +argv[1] = <$x> +argv[1] = <\$x> +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +argv[1] = <abc def ghi jkl> +argv[1] = <abc:def ghi:jkl> +argv[1] = <abc> +argv[2] = <def ghi> +argv[3] = <jkl> +argv[1] = <xxabc> +argv[2] = <def ghi> +argv[3] = <jklyy> +argv[1] = <abc> +argv[2] = <def ghi> +argv[3] = <jklabc> +argv[4] = <def ghi> +argv[5] = <jkl> +argv[1] = <abcdef> +argv[1] = <bar> +argv[2] = <> +argv[3] = <xyz> +argv[4] = <> +argv[5] = <abc> +argv[1] = <$foo> +argv[1] = <10> +argv[1] = <newline expected> +argv[1] = <got it> +argv[1] = <got it> +argv[1] = <one> +argv[2] = <three> +argv[3] = <five> +argv[1] = <5> +argv[2] = <5> +argv[1] = <3> +argv[1] = <1> +argv[1] = <1> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <42> +argv[1] = <26> +argv[1] = <\> +argv[1] = <~> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +a?b?c +a b c diff --git a/tests/extglob.right b/tests/extglob.right new file mode 100644 index 0000000..f063b26 --- /dev/null +++ b/tests/extglob.right @@ -0,0 +1,80 @@ +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok 15 +ok 16 +ok 17 +ok 18 +ok 19 +ok 20 +ok 21 +ok 22 +ok 23 +ok 24 +ok 25 +ok 26 +ok 27 +ok 28 +ok 29 +ok 30 +ok 31 +ok 32 +ok 33 +ok 34 +ok 35 +ok 36 +!([*)* ++(a|b[)* +[a*(]*)z ++()c ++()x +abc ++(*)x +abc +no-file+(a|b)stuff +no-file+(a*(c)|b)stuff +abd acd +acd +abd +no +yes +yes +1: bcdef +2: def +3: abcde +4: abc +5: ef +6: ef +7: abcdef +ab abef +abcfef abef +abcdef +ab abcdef abcfef abef +abcdef abcfef abef +ok 37 +ok 38 +ok 39 +ok 40 +ok 41 +ok 42 +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 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 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] = <ef> diff --git a/tests/extglob.tests b/tests/extglob.tests new file mode 100644 index 0000000..2d93850 --- /dev/null +++ b/tests/extglob.tests @@ -0,0 +1,363 @@ +# test the ksh-like extended globbing features: [!@*?+](patlist) + +shopt -s extglob + +expect() +{ + echo expect "$@" +} + +case "/dev/udp/129.22.8.102/45" in +/dev/@(tcp|udp)/*/*) echo ok 1;; +*) echo bad 1;; +esac + +# valid numbers +case 12 in +0|[1-9]*([0-9])) echo ok 2;; +*) echo bad 2;; +esac + +case 12abc in +0|[1-9]*([0-9])) echo bad 3;; +*) echo ok 3;; +esac + +case 1 in +0|[1-9]*([0-9])) echo ok 4;; +*) echo bad 4;; +esac + +# octal numbers +case 07 in ++([0-7])) echo ok 5;; +*) echo bad 5;; +esac + +case 0377 in ++([0-7])) echo ok 6;; +*) echo bad 6;; +esac + +case 09 in ++([0-7])) echo bad 7;; +*) echo ok 7;; +esac + +# stuff from korn's book +case paragraph in +para@(chute|graph)) echo ok 8;; +*) echo bad 8;; +esac + +case paramour in +para@(chute|graph)) echo bad 9;; +*) echo ok 9;; +esac + +case para991 in +para?([345]|99)1) echo ok 10;; +*) echo bad 10;; +esac + +case para381 in +para?([345]|99)1) echo bad 11;; +*) echo ok 11;; +esac + +case paragraph in +para*([0-9])) echo bad 12;; +*) echo ok 12;; +esac + +case para in +para*([0-9])) echo ok 13;; +*) echo bad 13;; +esac + +case para13829383746592 in +para*([0-9])) echo ok 14;; +*) echo bad 14;; +esac + +case paragraph in +para*([0-9])) echo bad 15;; +*) echo ok 15;; +esac + +case para in +para+([0-9])) echo bad 16;; +*) echo ok 16;; +esac + +case para987346523 in +para+([0-9])) echo ok 17;; +*) echo bad 17;; +esac + +case paragraph in +para!(*.[0-9])) echo ok 18;; +*) echo bad 18;; +esac + +case para.38 in +para!(*.[0-9])) echo ok 19;; +*) echo bad 19;; +esac + +case para.graph in +para!(*.[0-9])) echo ok 20;; +*) echo bad 20;; +esac + +case para39 in +para!(*.[0-9])) echo ok 21;; +*) echo bad 21;; +esac + +# tests derived from those in rosenblatt's korn shell book + +case "" in +*(0|1|3|5|7|9)) echo ok 22;; +*) echo bad 22; +esac + +case 137577991 in +*(0|1|3|5|7|9)) echo ok 23;; +*) echo bad 23; +esac + +case 2468 in +*(0|1|3|5|7|9)) echo bad 24;; +*) echo ok 24; +esac + +case file.c in +*.c?(c)) echo ok 25;; +*) echo bad 25;; +esac + +case file.C in +*.c?(c)) echo bad 26;; +*) echo ok 26;; +esac + +case file.cc in +*.c?(c)) echo ok 27;; +*) echo bad 27;; +esac + +case file.ccc in +*.c?(c)) echo bad 28;; +*) echo ok 28;; +esac + +case parse.y in +!(*.c|*.h|Makefile.in|config*|README)) echo ok 29;; +*) echo bad 29;; +esac + +case shell.c in +!(*.c|*.h|Makefile.in|config*|README)) echo bad 30;; +*) echo ok 30;; +esac + +case Makefile in +!(*.c|*.h|Makefile.in|config*|README)) echo ok 31;; +*) echo bad 31;; +esac + +case "VMS.FILE;1" in +*\;[1-9]*([0-9])) echo ok 32;; +*) echo bad 32;; +esac + +case "VMS.FILE;0" in +*\;[1-9]*([0-9])) echo bad 33;; +*) echo ok 33;; +esac +case "VMS.FILE;" in +*\;[1-9]*([0-9])) echo bad 34;; +*) echo ok 34;; +esac +case "VMS.FILE;139" in +*\;[1-9]*([0-9])) echo ok 35;; +*) echo bad 35;; +esac +case "VMS.FILE;1N" in +*\;[1-9]*([0-9])) echo bad 36;; +*) echo ok 36;; +esac + +# tests derived from the pd-ksh test suite + +MYDIR=$PWD # save where we are + +TESTDIR=/tmp/eglob-test +mkdir $TESTDIR +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch abcx abcz bbc +expect '!([*)*' +echo !([*)* + +expect '+(a|b[)*' +echo +(a|b[)* + +expect '[a*(]*z' +echo [a*(]*)z + +rm -f abcx abcz bbc + +touch abc + +expect '+()c' +echo +()c +expect '+()x' +echo +()x +expect abc +echo +(*)c +expect '+(*)x' +echo +(*)x + +# extended globbing should not be performed on the output of substitutions +x='@(*)' +expect '@(*)' +echo $x + +expect 'no-file+(a|b)stuff' +echo no-file+(a|b)stuff +expect 'no-file+(a*(c)|b)stuff' +echo no-file+(a*(c)|b)stuff + +touch abd acd + +expect 'abd acd' +echo a+(b|c)d + +expect 'acd' +echo a!(@(b|B))d + +expect 'abd' +echo a[b*(foo|bar)]d + +# simple kleene star tests +expect no +case foo in *(a|b[)) echo yes;; *) echo no;; esac + +expect yes +case foo in *(a|b[)|f*) echo yes;; *) echo no;; esac + +# this doesn't work right yet; it is an incorrectly formed pattern +expect yes +case '*(a|b[)' in *(a|b[)) echo yes;; *) echo no;; esac + +# check extended globbing in pattern removal -- these don't work right yet +x=abcdef + +expect '1: bcdef' +echo 1: ${x#+(a|abc)} +expect '2: def' +echo 2: ${x##+(a|abc)} +expect '3: abcde' +echo 3: ${x%+(def|f)} +expect '4: abc' +echo 4: ${x%%+(f|def)} + +# these work ok + +expect '5: ef' +echo 5: ${x#*(a|b)cd} +expect '6: ef' +echo 6: "${x#*(a|b)cd}" +expect '7: abcdef' +echo 7: ${x#"*(a|b)cd"} + +# More tests derived from a bug report concerning extended glob patterns +# following a * +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch ab abcdef abef abcfef + +expect 'ab abef' +echo ab*(e|f) + +expect 'abcfef abef' +echo ab?*(e|f) + +expect abcdef +echo ab*d+(e|f) + +expect 'ab abcdef abcfef abef' +echo ab**(e|f) + +expect 'abcdef abcfef abef' +echo ab*+(e|f) + +case 'abcfefg' in +ab**(e|f)) echo ok 37;; +*) echo bad 37;; +esac + +case 'abcfefg' in +ab**(e|f)g) echo ok 38;; +*a) echo bad 38;; +esac + +case ab in +ab*+(e|f)) echo bad 39;; +*) echo ok 39;; +esac + +case abef in +ab***ef) echo ok 40;; +*) echo bad 40;; +esac + +case abef in +ab**) echo ok 41;; +*) echo bad 41;; +esac + +# bug in all versions up to and including bash-2.05b +case "123abc" in +*?(a)bc) echo ok 42;; +*) echo bad 42;; +esac + +# clean up and do the next one + +builtin cd / +rm -rf $TESTDIR + +mkdir $TESTDIR +builtin cd $TESTDIR + +LC_COLLATE=C # have to set this; it affects the sorting +touch a.b a,b a:b a-b a\;b a\ b a_b + +echo a[^[:alnum:]]b +echo a[-.,:\;\ _]b + +echo a@([^[:alnum:]])b +echo a@([-.,:; _])b +echo a@([.])b +echo a@([^.])b +echo a@([^x])b +echo a+([^[:alnum:]])b + +echo a@(.|[^[:alnum:]])b + +builtin cd / +rm -rf $TESTDIR + +x=abcdef +recho "${x#*(a|b)cd}" + +# this is for the benefit of pure coverage, so it writes the pcv file +# in the right place +builtin cd $MYDIR + +exit 0 diff --git a/tests/extglob2.right b/tests/extglob2.right new file mode 100644 index 0000000..f8a09df --- /dev/null +++ b/tests/extglob2.right @@ -0,0 +1,70 @@ +0: [[ fofo = *(f*(o)) ]] +0: [[ ffo = *(f*(o)) ]] +0: [[ foooofo = *(f*(o)) ]] +0: [[ foooofof = *(f*(o)) ]] +0: [[ fooofoofofooo = *(f*(o)) ]] +1: [[ foooofof = *(f+(o)) ]] +1: [[ xfoooofof = *(f*(o)) ]] +1: [[ foooofofx = *(f*(o)) ]] +0: [[ ofxoofxo = *(*(of*(o)x)o) ]] +1: [[ ofooofoofofooo = *(f*(o)) ]] +0: [[ foooxfooxfoxfooox = *(f*(o)x) ]] +1: [[ foooxfooxofoxfooox = *(f*(o)x) ]] +0: [[ foooxfooxfxfooox = *(f*(o)x) ]] +0: [[ ofxoofxo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxoofoooxoofxo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxoofoooxoofxoo = *(*(of*(o)x)o) ]] +1: [[ ofoooxoofxoofoooxoofxofo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxoofoooxoofxooofxofxo = *(*(of*(o)x)o) ]] +0: [[ aac = *(@(a))a@(c) ]] +0: [[ ac = *(@(a))a@(c) ]] +1: [[ c = *(@(a))a@(c) ]] +0: [[ aaac = *(@(a))a@(c) ]] +1: [[ baaac = *(@(a))a@(c) ]] +0: [[ abcd = ?@(a|b)*@(c)d ]] +0: [[ abcd = @(ab|a*@(b))*(c)d ]] +0: [[ acd = @(ab|a*(b))*(c)d ]] +0: [[ abbcd = @(ab|a*(b))*(c)d ]] +0: [[ effgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +0: [[ efgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +0: [[ egz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +0: [[ egzefffgzbcdij = *(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +1: [[ egz = @(b+(c)d|e+(f)g?|?(h)i@(j|k)) ]] +0: [[ ofoofo = *(of+(o)) ]] +0: [[ oxfoxoxfox = *(oxf+(ox)) ]] +1: [[ oxfoxfox = *(oxf+(ox)) ]] +0: [[ ofoofo = *(of+(o)|f) ]] +0: [[ foofoofo = @(foo|f|fo)*(f|of+(o)) ]] +0: [[ oofooofo = *(of|oof+(o)) ]] +0: [[ fffooofoooooffoofffooofff = *(*(f)*(o)) ]] +0: [[ fofoofoofofoo = *(fo|foo) ]] +0: [[ foo = !(x) ]] +0: [[ foo = !(x)* ]] +1: [[ foo = !(foo) ]] +0: [[ foo = !(foo)* ]] +0: [[ foobar = !(foo) ]] +0: [[ foobar = !(foo)* ]] +0: [[ moo.cow = !(*.*).!(*.*) ]] +1: [[ mad.moo.cow = !(*.*).!(*.*) ]] +1: [[ mucca.pazza = mu!(*(c))?.pa!(*(z))? ]] +0: [[ fff = !(f) ]] +0: [[ fff = *(!(f)) ]] +0: [[ fff = +(!(f)) ]] +0: [[ ooo = !(f) ]] +0: [[ ooo = *(!(f)) ]] +0: [[ ooo = +(!(f)) ]] +0: [[ foo = !(f) ]] +0: [[ foo = *(!(f)) ]] +0: [[ foo = +(!(f)) ]] +1: [[ f = !(f) ]] +1: [[ f = *(!(f)) ]] +1: [[ f = +(!(f)) ]] +0: [[ foot = @(!(z*)|*x) ]] +1: [[ zoot = @(!(z*)|*x) ]] +0: [[ foox = @(!(z*)|*x) ]] +0: [[ zoox = @(!(z*)|*x) ]] +0: [[ foo = *(!(foo)) ]] +1: [[ foob = !(foo)b* ]] +0: [[ foobb = !(foo)b* ]] +0 tests failed. diff --git a/tests/extglob2.tests b/tests/extglob2.tests new file mode 100755 index 0000000..f35c3e8 --- /dev/null +++ b/tests/extglob2.tests @@ -0,0 +1,90 @@ +# +# More ksh-like extended globbing tests, cribbed from zsh-3.1.5 +# +shopt -s extglob + +failed=0 +while read res str pat; do + [[ $res = '#' ]] && continue + [[ $str = ${pat} ]] + ts=$? + [[ $1 = -q ]] || echo "$ts: [[ $str = $pat ]]" + if [[ ( $ts -gt 0 && $res = t) || ($ts -eq 0 && $res = f) ]]; then + echo "Test failed: [[ $str = $pat ]]" + (( failed += 1 )) + fi +done <<EOT +t fofo *(f*(o)) +t ffo *(f*(o)) +t foooofo *(f*(o)) +t foooofof *(f*(o)) +t fooofoofofooo *(f*(o)) +f foooofof *(f+(o)) +f xfoooofof *(f*(o)) +f foooofofx *(f*(o)) +t ofxoofxo *(*(of*(o)x)o) +f ofooofoofofooo *(f*(o)) +t foooxfooxfoxfooox *(f*(o)x) +f foooxfooxofoxfooox *(f*(o)x) +t foooxfooxfxfooox *(f*(o)x) +t ofxoofxo *(*(of*(o)x)o) +t ofoooxoofxo *(*(of*(o)x)o) +t ofoooxoofxoofoooxoofxo *(*(of*(o)x)o) +t ofoooxoofxoofoooxoofxoo *(*(of*(o)x)o) +f ofoooxoofxoofoooxoofxofo *(*(of*(o)x)o) +t ofoooxoofxoofoooxoofxooofxofxo *(*(of*(o)x)o) +t aac *(@(a))a@(c) +t ac *(@(a))a@(c) +f c *(@(a))a@(c) +t aaac *(@(a))a@(c) +f baaac *(@(a))a@(c) +t abcd ?@(a|b)*@(c)d +t abcd @(ab|a*@(b))*(c)d +t acd @(ab|a*(b))*(c)d +t abbcd @(ab|a*(b))*(c)d +t effgz @(b+(c)d|e*(f)g?|?(h)i@(j|k)) +t efgz @(b+(c)d|e*(f)g?|?(h)i@(j|k)) +t egz @(b+(c)d|e*(f)g?|?(h)i@(j|k)) +t egzefffgzbcdij *(b+(c)d|e*(f)g?|?(h)i@(j|k)) +f egz @(b+(c)d|e+(f)g?|?(h)i@(j|k)) +t ofoofo *(of+(o)) +t oxfoxoxfox *(oxf+(ox)) +f oxfoxfox *(oxf+(ox)) +t ofoofo *(of+(o)|f) +# The following is supposed to match only as fo+ofo+ofo +t foofoofo @(foo|f|fo)*(f|of+(o)) +t oofooofo *(of|oof+(o)) +t fffooofoooooffoofffooofff *(*(f)*(o)) +# The following tests backtracking in alternation matches +t fofoofoofofoo *(fo|foo) +# Exclusion +t foo !(x) +t foo !(x)* +f foo !(foo) +t foo !(foo)* +t foobar !(foo) +t foobar !(foo)* +t moo.cow !(*.*).!(*.*) +f mad.moo.cow !(*.*).!(*.*) +f mucca.pazza mu!(*(c))?.pa!(*(z))? +t fff !(f) +t fff *(!(f)) +t fff +(!(f)) +t ooo !(f) +t ooo *(!(f)) +t ooo +(!(f)) +t foo !(f) +t foo *(!(f)) +t foo +(!(f)) +f f !(f) +f f *(!(f)) +f f +(!(f)) +t foot @(!(z*)|*x) +f zoot @(!(z*)|*x) +t foox @(!(z*)|*x) +t zoox @(!(z*)|*x) +t foo *(!(foo)) +f foob !(foo)b* +t foobb !(foo)b* +EOT +echo "$failed tests failed." diff --git a/tests/extglob3.right b/tests/extglob3.right new file mode 100644 index 0000000..db9447e --- /dev/null +++ b/tests/extglob3.right @@ -0,0 +1,27 @@ +match 1 +match 2 +match 3 +match 4 +match 1a +match 1b +match 2a +match 2b +match 3a +match 3b +match 4a +match 4b +match 5 +match 6 +match 7 +match 8 +match 9 +match 10 +match 11 +match 12 +match 13 +match 14 +match 15 +match 16 +match 17 +match 18 +ok 19 diff --git a/tests/extglob3.tests b/tests/extglob3.tests new file mode 100644 index 0000000..60454a2 --- /dev/null +++ b/tests/extglob3.tests @@ -0,0 +1,56 @@ +shopt -s extglob + +[[ ab/../ == @(ab|+([^/]))/..?(/) ]] && echo match 1 + +[[ ab/../ == +([^/])/..?(/) ]] && echo match 2 + +[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 3 + +[[ ab/../ == +([^/])/../ ]] && echo match 4 + +[[ ab/../ == +([!/])/..?(/) ]] && echo match 1a + +[[ ab/../ == @(ab|+([!/]))/..?(/) ]] && echo match 1b + +[[ ab/../ == +([!/])/../ ]] && echo match 2a + +[[ ab/../ == +([!/])/..?(/) ]] && echo match 2b + +[[ ab/../ == +([!/])/..@(/) ]] && echo match 3a + +[[ ab/../ == +(ab)/..?(/) ]] && echo match 3b + +[[ ab/../ == [!/][!/]/../ ]] && echo match 4a + +[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 4b + +[[ ab/../ == [^/][^/]/../ ]] && echo match 5 + +[[ ab/../ == ?b/..?(/) ]] && echo match 6 + +[[ ab/../ == +(?b)/..?(/) ]] && echo match 7 + +[[ ab/../ == +(?b|?b)/..?(/) ]] && echo match 8 + +[[ ab/../ == @(?b|?b)/..?(/) ]] && echo match 9 + +[[ ab/../ == @(a?|?b)/..?(/) ]] && echo match 10 + +[[ ab/../ == ?(ab)/..?(/) ]] && echo match 11 + +[[ ab/../ == ?(ab|??)/..?(/) ]] && echo match 12 + +[[ ab/../ == @(??)/..?(/) ]] && echo match 13 + +[[ ab/../ == @(??|a*)/..?(/) ]] && echo match 14 + +[[ ab/../ == @(a*)/..?(/) ]] && echo match 15 + +[[ ab/../ == +(??)/..?(/) ]] && echo match 16 + +[[ ab/../ == +(??|a*)/..?(/) ]] && echo match 17 + +[[ ab/../ == +(a*)/..?(/) ]] && echo match 18 + +# +j="@(x)" ; [[ x == $j ]] && echo ok 19 diff --git a/tests/func.right b/tests/func.right new file mode 100644 index 0000000..e51d92b --- /dev/null +++ b/tests/func.right @@ -0,0 +1,150 @@ +a returns 5 +b returns 4 +c returns 3 +d returns 2 +in e +e returned 25 +x is 25 +ZZ +abcde +defghi +ZZ +5 +0 +AVAR +AVAR +foo +foo +AVAR +5 +5 +f1 +f1 () +{ + ( return 5 ); + status=$?; + echo $status; + return $status +} +before: try to assign to FUNCNAME +outside: FUNCNAME = +before: FUNCNAME = func +FUNCNAME = func2 +after: FUNCNAME = func +outside2: FUNCNAME = +function +zf is a function +zf () +{ + echo this is zf +} +f is a function +f () +{ + echo f-x; + echo f-y +} 1>&2 +subshell +f is a function +f () +{ + echo f-x; + echo f-y +} 1>&2 +f2 is a function +f2 () +{ + echo f2-a; + function f3 () + { + echo f3-a; + echo f3-b + } 1>&2; + f3 +} +subshell +f2 is a function +f2 () +{ + echo f2-a; + function f3 () + { + echo f3-a; + echo f3-b + } 1>&2; + f3 +} +f4 is a function +f4 () +{ + echo f4-a; + function f5 () + { + echo f5-a; + echo f5-b + } 1>&2; + f5 +} 2>&1 +subshell +f4 is a function +f4 () +{ + echo f4-a; + function f5 () + { + echo f5-a; + echo f5-b + } 1>&2; + f5 +} 2>&1 +testgrp is a function +testgrp () +{ + echo testgrp-a; + { + echo tg-x; + echo tg-y + } 1>&2; + echo testgrp-b +} +subshell +testgrp is a function +testgrp () +{ + echo testgrp-a; + { + echo tg-x; + echo tg-y + } 1>&2; + echo testgrp-b +} +funca is a function +funca () +{ + ( echo func-a ) +} +funcb is a function +funcb () +{ + ( echo func-b ) +} +funcc is a function +funcc () +{ + ( echo func-c ) 2>&1 +} +func-a +func-b +func-c +expect 5 10 +5 10 +expect 20 +20 +expect 5 20 +5 20 +expect 5 30 +5 30 +expect 2 40 +2 40 +expect 5 20 +5 20 diff --git a/tests/func.tests b/tests/func.tests new file mode 100644 index 0000000..063f4e0 --- /dev/null +++ b/tests/func.tests @@ -0,0 +1,168 @@ +a() +{ + x=$((x - 1)) + return 5 +} + +b() +{ + x=$((x - 1)) + a + echo a returns $? + return 4 +} + +c() +{ + x=$((x - 1)) + b + echo b returns $? + return 3 +} + +d() +{ + x=$((x - 1)) + c + echo c returns $? + return 2 +} + +e() +{ + d + echo d returns $? + echo in e + x=$((x - 1)) + return $x +} + +f() +{ + e + echo e returned $? + echo x is $x + return 0 +} + +x=30 +f + +# make sure unsetting a local variable preserves the `local' attribute +f1() +{ + local zz + zz=abcde + echo $zz + unset zz + zz=defghi + echo $zz +} + +zz=ZZ +echo $zz +f1 +echo $zz + +unset -f f1 +f1() +{ + return 5 +} + +( f1 ) +echo $? + +unset -f f1 +f1() +{ + sleep 5 + return 5 +} + +f1 & +wait +echo $? + +unset -f f1 + +f1() +{ + echo $AVAR + printenv AVAR +} + +AVAR=AVAR +echo $AVAR +f1 +AVAR=foo f1 +echo $AVAR + +unset -f f1 +# make sure subshells can do a `return' if we're executing in a function +f1() +{ + ( return 5 ) + status=$? + echo $status + return $status +} + +f1 +echo $? + +declare -F f1 # should print just the name +declare -f f1 # should print the definition, too + +# no functions should be exported, right? +declare -xF +declare -xf + +# FUNCNAME tests +func2() +{ + echo FUNCNAME = $FUNCNAME +} + +func() +{ + echo before: FUNCNAME = $FUNCNAME + func2 + echo after: FUNCNAME = $FUNCNAME +} + +echo before: try to assign to FUNCNAME +FUCNAME=7 + +echo outside: FUNCNAME = $FUNCNAME +func +echo outside2: FUNCNAME = $FUNCNAME + +# test exported functions (and cached exportstr) +zf() +{ + echo this is zf +} +export -f zf + +${THIS_SH} -c 'type -t zf' +${THIS_SH} -c 'type zf' + +${THIS_SH} ./func1.sub + +# tests for functions whose bodies are not group commands, with and without +# attached redirections +${THIS_SH} ./func2.sub + +# test for some posix-specific function behavior +${THIS_SH} ./func3.sub + +unset -f myfunction +myfunction() { + echo "bad shell function redirection" +} >> /dev/null + +myfunction +myfunction | cat + +exit 0 diff --git a/tests/func1.sub b/tests/func1.sub new file mode 100644 index 0000000..345645f --- /dev/null +++ b/tests/func1.sub @@ -0,0 +1,55 @@ +# +# Test that redirections attached to shell functions are printed correctly. +# This was a bug in all bash versions before bash-2.04. +# +f() +{ + echo f-x + echo f-y +} >&2 + +type f +export -f f +${THIS_SH} -c 'echo subshell; type f' + +f2() +{ + echo f2-a + f3() + { + echo f3-a + echo f3-b + } >&2 + f3 +} + +type f2 + +export -f f2 +${THIS_SH} -c 'echo subshell; type f2' + +f4() +{ + echo f4-a + f5() + { + echo f5-a + echo f5-b + } >&2 + f5 +} 2>&1 + +type f4 +export -f f4 +${THIS_SH} -c 'echo subshell; type f4' + +testgrp() +{ + echo testgrp-a + { echo tg-x; echo tg-y; } >&2 + echo testgrp-b +} +type testgrp + +export -f testgrp +${THIS_SH} -c 'echo subshell; type testgrp' diff --git a/tests/func2.sub b/tests/func2.sub new file mode 100644 index 0000000..2f9d5ce --- /dev/null +++ b/tests/func2.sub @@ -0,0 +1,17 @@ +funca() ( + echo func-a +) + +funcb() ( echo func-b ) + +funcc() ( + echo func-c +) 2>&1 + +type funca +type funcb +type funcc + +funca +funcb +funcc diff --git a/tests/func3.sub b/tests/func3.sub new file mode 100644 index 0000000..9d3d069 --- /dev/null +++ b/tests/func3.sub @@ -0,0 +1,54 @@ +# +# test some posix-mode-specific function behavior +# +set -o posix +func() +{ + return 5 +} + +myfunction () { + var=20 return +} +var=10 +echo expect 5 10 +func +echo $? $var + +myfunction +echo expect 20 +echo $var + +echo expect 5 20 +func +echo $? $var + +echo expect 5 30 +var=30 func +echo $? $var + +: ${TMPDIR:=/tmp} +TMPFILE=$TMPDIR/func3.sub.$$ + +rm -f $TMPFILE +echo 'var=40 return 2' > $TMPFILE + +# test the behavior of `return' and preceding variable assignments here +# because it's convenient +var=10 +echo expect 2 40 +. $TMPFILE +echo $? $var + +rm -f $TMPFILE + +#set -o posix +var=0 +func() +{ + var=20 return 5 +} + +echo expect 5 20 +var=30 func +echo $? $var diff --git a/tests/getopts.right b/tests/getopts.right new file mode 100644 index 0000000..9226103 --- /dev/null +++ b/tests/getopts.right @@ -0,0 +1,56 @@ +getopts: usage: getopts optstring name [arg] +2 +getopts: usage: getopts optstring name [arg] +2 +./getopts.tests: line 10: getopts: -a: invalid option +getopts: usage: getopts optstring name [arg] +-a specified +-b bval specified +remaining args: one two three +-a specified +-b bval specified +remaining args: one two three four five six seven eight nine ten eleven twelve +./getopts1.sub: option requires an argument -- b +Usage: ./getopts1.sub [-a] [-b value] args +-a specified +-c cval specified +-d specified +-a specified +-b 3 specified +remaining args: one two three four five +-a specified +-b bval specified +remaining args: one two three +-a specified +-b bval specified +remaining args: one two three +./getopts4.sub: error: option `b' requires an argument +Usage: ./getopts4.sub [-a] [-b value] args +./getopts4.sub: error: illegal option character `c' +Usage: ./getopts4.sub [-a] [-b value] args +-a specified +remaining args: -b bval one two three +OPTERR=0 +a here +something else here +OPTIND=3 +getop: OPTERR=1 +a here +./getopts5.sub: illegal option -- c +something else here +./getopts5.sub: illegal option -- d +something else here +./getopts5.sub: illegal option -- e +something else here +getop: OPTIND=5 +OPTIND=3 +OPTERR=0 +-a specified +remaining args: +-a specified +remaining args: +-a specified +remaining args: +0 +./getopts7.sub: line 4: getopts: `opt-var': not a valid identifier +remaining args: diff --git a/tests/getopts.tests b/tests/getopts.tests new file mode 100644 index 0000000..1814d78 --- /dev/null +++ b/tests/getopts.tests @@ -0,0 +1,38 @@ +# getopts tests +# this should fail +getopts +echo $? +getopts opts +echo $? + +# maybe someday we will have a ksh93-like -a argument to set the name +# used in error messages, but not yet +getopts -a opts name + +${THIS_SH} ./getopts1.sub -a -b bval one two three +# make sure getopts works when there are more than 9 positional parameters +${THIS_SH} ./getopts1.sub -a -b bval one two three four five six seven eight nine ten eleven twelve +${THIS_SH} ./getopts1.sub -a -b + +${THIS_SH} ./getopts2.sub -ad -c cval three four five + +${THIS_SH} ./getopts3.sub + +# make sure that `-b bval' and `-bbval' are equivalent +${THIS_SH} ./getopts4.sub -a -b bval one two three +${THIS_SH} ./getopts4.sub -a -bbval one two three +# this tests `silent' error reporting +${THIS_SH} ./getopts4.sub -a -b +${THIS_SH} ./getopts4.sub -a -c + +# make sure that `--' can be used to end the list of options +${THIS_SH} ./getopts4.sub -a -- -b bval one two three + +${THIS_SH} ./getopts5.sub -a -c + +${THIS_SH} ./getopts6.sub -a +${THIS_SH} ./getopts6.sub -a -c +${THIS_SH} ./getopts6.sub -ac +echo $? # this should be 2 + +${THIS_SH} ./getopts7.sub -a diff --git a/tests/getopts1.sub b/tests/getopts1.sub new file mode 100644 index 0000000..df0a342 --- /dev/null +++ b/tests/getopts1.sub @@ -0,0 +1,26 @@ +aflag= +bflag= + +while getopts ab: name +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + ?) echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts2.sub b/tests/getopts2.sub new file mode 100644 index 0000000..d91fd26 --- /dev/null +++ b/tests/getopts2.sub @@ -0,0 +1,26 @@ +aflag= +bflag= + +while getopts ab:c:de name "$@" +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + c) cflag=1 + cval=$OPTARG ;; + d) dflag=1 ;; + e) eflag=1;; + ?) echo Usage: $0 [-a] [-b value] [-c value] -[de] args + exit 2;; + esac + +done + +[ ! -z "$aflag" ] && echo -a specified +[ ! -z "$bflag" ] && echo -b $bval specified +[ ! -z "$cflag" ] && echo -c $cval specified +[ ! -z "$dflag" ] && echo -d specified +[ ! -z "$eflag" ] && { echo -n - ; echo e specified; } + +exit 0 diff --git a/tests/getopts3.sub b/tests/getopts3.sub new file mode 100644 index 0000000..2d8b316 --- /dev/null +++ b/tests/getopts3.sub @@ -0,0 +1,27 @@ +aflag= +bflag= + +while getopts ab: name -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + ?) echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +set -- -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts4.sub b/tests/getopts4.sub new file mode 100644 index 0000000..9cd5aef --- /dev/null +++ b/tests/getopts4.sub @@ -0,0 +1,30 @@ +aflag= +bflag= + +while getopts :ab: name "$@" +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + :) echo $0: error: option \`$OPTARG\' requires an argument + echo Usage: $0 [-a] [-b value] args + exit 2;; + ?) echo $0: error: illegal option character \`$OPTARG\' + echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts5.sub b/tests/getopts5.sub new file mode 100644 index 0000000..c6e3888 --- /dev/null +++ b/tests/getopts5.sub @@ -0,0 +1,50 @@ +#!/local/bin/bash +#Time-stamp: <95/06/07 07:40:40 hrue@imf.unit.no> + +getop () { + + local OPTIND + local OPTERR=1 + + echo getop: OPTERR=$OPTERR + while getopts ab arg "$@"; do + case $arg in + a) + echo a here + ;; + b) + echo b here + ;; + :|?|*) + echo something else here + ;; + esac + done + echo getop: OPTIND=$OPTIND +} + +OPTIND= +OPTERR=0 + +echo OPTERR=$OPTERR +while getopts ab arg; do + case $arg in + a) + echo a here + ;; + b) + echo b here + ;; + :|?|*) + + echo something else here + ;; + esac +done + +echo OPTIND=$OPTIND + +getop "$@" -d -e + +echo OPTIND=$OPTIND +echo OPTERR=$OPTERR diff --git a/tests/getopts6.sub b/tests/getopts6.sub new file mode 100644 index 0000000..75d768c --- /dev/null +++ b/tests/getopts6.sub @@ -0,0 +1,27 @@ +aflag= +bflag= + +while getopts :ac name "$@" +do + case $name in + a) aflag=1 ;; + c) cflag=1 ;; + ?) exit 2;; + esac + + # this came in in a bug report -- it's really a usage error + # but it shouldn't cause the shell to crash + shift +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$cflag" ] ; then echo -c specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts7.sub b/tests/getopts7.sub new file mode 100644 index 0000000..a20a6df --- /dev/null +++ b/tests/getopts7.sub @@ -0,0 +1,30 @@ +aflag= +bflag= + +while getopts :ab: opt-var "$@" +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + :) echo $0: error: option \`$OPTARG\' requires an argument + echo Usage: $0 [-a] [-b value] args + exit 2;; + ?) echo $0: error: illegal option character \`$OPTARG\' + echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/glob-test b/tests/glob-test new file mode 100644 index 0000000..d435708 --- /dev/null +++ b/tests/glob-test @@ -0,0 +1,388 @@ +LC_COLLATE=C +# +# test the shell globbing +# +expect() +{ + echo expect "$@" +} + +# First, a test that bash-2.01.1 fails +${THIS_SH} ./glob1.sub + +MYDIR=$PWD # save where we are + +TESTDIR=/tmp/glob-test +mkdir $TESTDIR +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch a b c d abc abd abe bb bcd ca cb dd de Beware +mkdir bdir + +# see if `regular' globbing works right +expect '<a> <abc> <abd> <abe> <X*>' +recho a* X* + +expect '<a> <abc> <abd> <abe>' +recho \a* + +# see if null glob expansion works +shopt -s nullglob + +expect '<a> <abc> <abd> <abe>' +recho a* X* + +shopt -u nullglob + +# see if the failglob option works + +mkdir tmp +touch tmp/l1 tmp/l2 tmp/l3 +builtin echo tmp/l[12] tmp/*4 tmp/*3 +shopt -s failglob +builtin echo tmp/l[12] tmp/*4 tmp/*3 +rm -r tmp +shopt -u failglob + +# see if the code that expands directories only works +expect '<bdir/>' +recho b*/ + +# Test quoted and unquoted globbing characters +expect '<*>' +recho \* + +expect '<a*>' +recho 'a*' + +expect '<a*>' +recho a\* + +expect '<c> <ca> <cb> <a*> <*q*>' +recho c* a\* *q* + +expect '<**>' +recho "*"* + +expect '<**>' +recho \** + +expect '<\.\./*/>' +recho "\.\./*/" + +expect '<s/\..*//>' +recho 's/\..*//' + +# Pattern from Larry Wall's Configure that caused bash to blow up +expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>' +recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/" + +# Make sure character classes work properly + +expect '<abc> <abd> <abe> <bb> <cb>' +recho [a-c]b* + +expect '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' +recho [a-y]*[^c] + +expect '<abd> <abe>' +recho a*[^c] + +touch a-b aXb +expect '<a-b> <aXb>' +recho a[X-]b + +touch .x .y +expect '<Beware> <d> <dd> <de>' +recho [^a-c]* + +# Make sure that filenames with embedded globbing characters are handled +# properly +mkdir a\*b +> a\*b/ooo + +expect '<a*b/ooo>' +recho a\*b/* + +expect '<a*b/ooo>' +recho a\*?/* + +expect '<no match>' +cmd='echo !7' +case "$cmd" in +*\\!*) echo match ;; +*) echo no match ;; +esac + +expect '<not there>' +file='r.*' +case $file in +*.\*) echo not there ;; +*) echo there ;; +esac + +# examples from the Posix.2 spec (d11.2, p. 243) +expect '<abc>' +recho a[b]c + +expect '<abc>' +recho a["b"]c + +expect '<abc>' +recho a[\b]c + +expect '<abc>' +recho a?c + +expect '<match 1>' +case abc in +a"b"c) echo 'match 1' ;; +*) echo 'BAD match 1' ;; +esac + +expect '<match 2>' +case abc in +a*c) echo 'match 2' ;; +*) echo 'BAD match 2' ;; +esac + +expect '<ok 1>' +case abc in +"a?c") echo 'bad 1' ;; +*) echo 'ok 1' ;; +esac + +expect '<ok 2>' +case abc in +a\*c) echo 'bad 2' ;; +*) echo 'ok 2' ;; +esac + +expect '<ok 3>' +case abc in +a\[b]c) echo 'bad 3' ;; +*) echo 'ok 3' ;; +esac + +expect '<ok 4>' +case "$nosuchvar" in +"") echo 'ok 4' ;; +*) echo 'bad 4' ;; +esac + +# This is very odd, but sh and ksh seem to agree +expect '<ok 5>' +case abc in +a["\b"]c) echo 'ok 5' ;; +*) echo 'bad 5' ;; +esac + +mkdir man +mkdir man/man1 +touch man/man1/bash.1 +expect '<man/man1/bash.1>' +recho */man*/bash.* +expect '<man/man1/bash.1>' +recho $(echo */man*/bash.*) +expect '<man/man1/bash.1>' +recho "$(echo */man*/bash.*)" + +# tests with multiple `*'s +case abc in +a***c) echo ok 1;; +esac + +case abc in +a*****?c) echo ok 2;; +esac + +case abc in +?*****??) echo ok 3;; +esac + +case abc in +*****??) echo ok 4;; +esac + +case abc in +*****??c) echo ok 5;; +esac + +case abc in +?*****?c) echo ok 6;; +esac + +case abc in +?***?****c) echo ok 7;; +esac + +case abc in +?***?****?) echo ok 8;; +esac + +case abc in +?***?****) echo ok 9;; +esac + +case abc in +*******c) echo ok 10;; +esac + +case abc in +*******?) echo ok 11;; +esac + +case abcdecdhjk in +a*cd**?**??k) echo ok 20;; +esac + +case abcdecdhjk in +a**?**cd**?**??k) echo ok 21;; +esac + +case abcdecdhjk in +a**?**cd**?**??k***) echo ok 22;; +esac + +case abcdecdhjk in +a**?**cd**?**??***k) echo ok 23;; +esac + +case abcdecdhjk in +a**?**cd**?**??***k**) echo ok 24;; +esac + +case abcdecdhjk in +a****c**?**??*****) echo ok 25;; +esac + +case '-' in +[-abc]) echo ok 26 ;; +esac + +case '-' in +[abc-]) echo ok 27 ;; +esac + +case '\' in +\\) echo ok 28 ;; +esac + +case '\' in +[\\]) echo ok 29 ;; +esac + +case '\' in +'\') echo ok 30 ;; +esac + +case '[' in +[[]) echo ok 31 ;; +esac + +# a `[' without a closing `]' is just another character to match, in the +# bash implementation +case '[' in +[) echo ok 32 ;; +esac + +case '[abc' in +[*) echo 'ok 33';; +esac + +# a right bracket shall lose its special meaning and represent itself in +# a bracket expression if it occurs first in the list. -- POSIX.2 2.8.3.2 +case ']' in +[]]) echo ok 34 ;; +esac + +case '-' in +[]-]) echo ok 35 ;; +esac + +# a backslash should just escape the next character in this context +case p in +[a-\z]) echo ok 36 ;; +esac + +# this was a bug in all versions up to bash-2.04-release +case "/tmp" in +[/\\]*) echo ok 37 ;; +esac + +# none of these should output anything + +case abc in +??**********?****?) echo bad 1;; +esac + +case abc in +??**********?****c) echo bad 2;; +esac + +case abc in +?************c****?****) echo bad 3;; +esac + +case abc in +*c*?**) echo bad 4;; +esac + +case abc in +a*****c*?**) echo bad 5;; +esac + +case abc in +a********???*******) echo bad 6;; +esac + +case 'a' in +[]) echo bad 7 ;; +esac + +case '[' in +[abc) echo bad 8;; +esac + +# let's start testing the case-insensitive globbing code +recho b* + +shopt -s nocaseglob +recho b* + +recho [b]* +shopt -u nocaseglob + +# make sure set -f works right +set -f +recho * +set +f + +# test out the GLOBIGNORE code +GLOBIGNORE='.*:*c:*e:?' +recho * + +GLOBIGNORE='.*:*b:*d:?' +recho * + +# see if GLOBIGNORE can substitute for `set -f' +GLOBIGNORE='.*:*' +recho * + +unset GLOBIGNORE +expect '<man/man1/bash.1>' +recho */man*/bash.* + +# make sure null values for GLOBIGNORE have no effect +GLOBIGNORE= +expect '<man/man1/bash.1>' +recho */man*/bash.* + +# this is for the benefit of pure coverage, so it writes the pcv file +# in the right place, and for gprof +builtin cd $MYDIR + +rm -rf $TESTDIR + +exit 0 diff --git a/tests/glob.right b/tests/glob.right new file mode 100644 index 0000000..46ac4d3 --- /dev/null +++ b/tests/glob.right @@ -0,0 +1,135 @@ +foo/bar foobar/bar +argv[1] = <a> +argv[2] = <abc> +argv[3] = <abd> +argv[4] = <abe> +argv[5] = <X*> +argv[1] = <a> +argv[2] = <abc> +argv[3] = <abd> +argv[4] = <abe> +argv[1] = <a> +argv[2] = <abc> +argv[3] = <abd> +argv[4] = <abe> +tmp/l1 tmp/l2 tmp/*4 tmp/l3 +./glob-test: line 44: no match: tmp/*4 +argv[1] = <bdir/> +argv[1] = <*> +argv[1] = <a*> +argv[1] = <a*> +argv[1] = <c> +argv[2] = <ca> +argv[3] = <cb> +argv[4] = <a*> +argv[5] = <*q*> +argv[1] = <**> +argv[1] = <**> +argv[1] = <\.\./*/> +argv[1] = <s/\..*//> +argv[1] = </^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/> +argv[1] = <abc> +argv[2] = <abd> +argv[3] = <abe> +argv[4] = <bb> +argv[5] = <cb> +argv[1] = <abd> +argv[2] = <abe> +argv[3] = <bb> +argv[4] = <bcd> +argv[5] = <bdir> +argv[6] = <ca> +argv[7] = <cb> +argv[8] = <dd> +argv[9] = <de> +argv[1] = <abd> +argv[2] = <abe> +argv[1] = <a-b> +argv[2] = <aXb> +argv[1] = <Beware> +argv[2] = <d> +argv[3] = <dd> +argv[4] = <de> +argv[1] = <a*b/ooo> +argv[1] = <a*b/ooo> +no match +not there +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +match 1 +match 2 +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +argv[1] = <man/man1/bash.1> +argv[1] = <man/man1/bash.1> +argv[1] = <man/man1/bash.1> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 20 +ok 21 +ok 22 +ok 23 +ok 24 +ok 25 +ok 26 +ok 27 +ok 28 +ok 29 +ok 30 +ok 31 +ok 32 +ok 33 +ok 34 +ok 35 +ok 36 +ok 37 +argv[1] = <b> +argv[2] = <bb> +argv[3] = <bcd> +argv[4] = <bdir> +argv[1] = <Beware> +argv[2] = <b> +argv[3] = <bb> +argv[4] = <bcd> +argv[5] = <bdir> +argv[1] = <Beware> +argv[2] = <b> +argv[3] = <bb> +argv[4] = <bcd> +argv[5] = <bdir> +argv[1] = <*> +argv[1] = <a*b> +argv[2] = <a-b> +argv[3] = <aXb> +argv[4] = <abd> +argv[5] = <bb> +argv[6] = <bcd> +argv[7] = <bdir> +argv[8] = <ca> +argv[9] = <cb> +argv[10] = <dd> +argv[11] = <man> +argv[1] = <Beware> +argv[2] = <abc> +argv[3] = <abe> +argv[4] = <bdir> +argv[5] = <ca> +argv[6] = <de> +argv[7] = <man> +argv[1] = <*> +argv[1] = <man/man1/bash.1> +argv[1] = <man/man1/bash.1> diff --git a/tests/glob1.sub b/tests/glob1.sub new file mode 100644 index 0000000..8745cd9 --- /dev/null +++ b/tests/glob1.sub @@ -0,0 +1,14 @@ +# bash-2.01.1 failed this test +FN=/tmp/bash-glob.$$ +mkdir $FN +cd $FN +mkdir foo +mkdir foobar +touch foo/bar +touch foobar/bar +chmod 311 foo foobar +echo f*/bar + +chmod 777 foo foobar +cd / +rm -rf $FN diff --git a/tests/heredoc.right b/tests/heredoc.right new file mode 100644 index 0000000..d71781e --- /dev/null +++ b/tests/heredoc.right @@ -0,0 +1,43 @@ +there +one - alpha +two - beta +three - gamma +hi\ +there$a +stuff +hi\ +there +EO\ +F +hi +hi +tab 1 +tab 2 +tab 3 +abc +def ghi +jkl mno +fff is a function +fff () +{ + ed /tmp/foo >/dev/null <<ENDOFINPUT +/^name/d +w +q +ENDOFINPUT + + aa=1 +} +fff is a function +fff () +{ + ed /tmp/foo >/dev/null <<ENDOFINPUT +/^name/d +w +q +ENDOFINPUT + + aa=1 +} +hi +there diff --git a/tests/heredoc.tests b/tests/heredoc.tests new file mode 100644 index 0000000..c07ef64 --- /dev/null +++ b/tests/heredoc.tests @@ -0,0 +1,94 @@ +# check order and content of multiple here docs + +cat << EOF1 << EOF2 +hi +EOF1 +there +EOF2 + +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done <<EOF1 3<<EOF2 +one +two +three +EOF1 +alpha +beta +gamma +EOF2 + + +# check quoted here-doc is protected + +a=foo +cat << 'EOF' +hi\ +there$a +stuff +EOF + +# check that quoted here-documents don't have \newline processing done + +cat << 'EOF' +hi\ +there +EO\ +F +EOF +true + +# check that \newline is removed at start of here-doc +cat << EO\ +F +hi +EOF + +# check that \newline removal works for here-doc delimiter +cat << EOF +hi +EO\ +F + +# check operation of tab removal in here documents +cat <<- EOF + tab 1 + tab 2 + tab 3 + EOF + +# check appending of text to file from here document +rm -f /tmp/bash-zzz +cat > /tmp/bash-zzz << EOF +abc +EOF +cat >> /tmp/bash-zzz << EOF +def ghi +jkl mno +EOF +cat /tmp/bash-zzz +rm -f /tmp/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 +/^name/d +w +q +ENDOFINPUT +aa=1 +} + +type fff +export -f fff +${THIS_SH} -c 'type fff' + +# check that end of file delimits a here-document +# THIS MUST BE LAST! + +cat << EOF +hi +there diff --git a/tests/herestr.right b/tests/herestr.right new file mode 100644 index 0000000..80b01cf --- /dev/null +++ b/tests/herestr.right @@ -0,0 +1,28 @@ +abcde +yo +hot damn +what a fabulous window treatment +double"quote +onetwothree +first second third +f1 () +{ + cat <<< "abcde"; + cat <<< "yo"; + cat <<< "$a $b"; + cat <<< 'what a fabulous window treatment'; + cat <<< 'double"quote' +} +f2 () +{ + cat <<< onetwothree +} +f3 () +{ + cat <<< "$@" +} +echo $(echo hi) +echo ho +echo off to work we go +declare -a uu='([0]="" [1]="kghfjk" [2]="jkfzuk" [3]="i +")' diff --git a/tests/herestr.tests b/tests/herestr.tests new file mode 100644 index 0000000..f77b229 --- /dev/null +++ b/tests/herestr.tests @@ -0,0 +1,39 @@ +a=hot +b=damn +f1() +{ +cat <<< "abcde" + +cat <<< "yo" + +cat <<< "$a $b" + +cat <<< 'what a fabulous window treatment' + +cat <<< 'double"quote' +} + +f2() +{ +cat <<< onetwothree +} + +f3() +{ +cat <<< "$@" +} + +f1 +f2 +f3 first second third + +typeset -f + +cat <<< 'echo $(echo hi)' + +cat <<< "echo ho" + +cat <<< "echo $(echo off to work we go)" + +IFS="/" read -r -d $'\000' -a uu <<< /kghfjk/jkfzuk/i +declare -p uu diff --git a/tests/histexp.right b/tests/histexp.right new file mode 100644 index 0000000..f1c9e9d --- /dev/null +++ b/tests/histexp.right @@ -0,0 +1,129 @@ +echo $BASH_VERSION +./histexp.tests: line 24: history: !!:z: history expansion failed + 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 + 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 HISTFILE=/tmp/newhistory + 6 echo line 2 for history +echo line 2 for history +echo line 2 for history +set -H +echo line 2 for history +line 2 for history + 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 HISTFILE=/tmp/newhistory + 6 echo line 2 for history + 7 set -H + 8 echo line 2 for history +a b c d e +echo a b c d e +a b c d e +echo line 2 for history +line 2 for history +echo line 8 for history +line 8 for history +/bin/sh -c 'echo this is $0' +this is /bin/sh +echo sh +sh +echo /bin +/bin +echo e +e +a b c d e +echo b c d e +b c d e +echo b c d +b c d +echo d e +d e +echo d e +d e +echo b c d +b c d +file.c +echo file +file +echo .c +.c +echo 'file' +file +bax.c +echo $file +bax +echo .c +.c +echo '$file' +$file +a b c d e +echo 'a' 'b' 'c' 'd' 'e' +a b c d e +echo 'a b c d e' +a b c d e +foo.c foo.o foo.html foo.h +echo bar.c foo.o foo.html foo.h +bar.c foo.o foo.html foo.h +echo bar.c bar.o bar.html bar.h +bar.c bar.o bar.html bar.h +echo xbar.c xbar.o xbar.html xbar.h +xbar.c xbar.o xbar.html xbar.h +echo xbar.c xbar.o xbar.html xbar.h +xbar.c xbar.o xbar.html xbar.h +echo xwhix.c xwhix.o xwhix.html xwhix.h +xwhix.c xwhix.o xwhix.html xwhix.h +echo xwhix.c xwhix.o xwhix.html xwhix.h +echo 'xwhix' +xwhix +echo 'xwhix.h' +xwhix.h +echo 'xwhix.h' +xwhix.h +echo 'xwhix.h' +xwhix.h + 7 set -H + 8 echo line 2 for history + 9 echo a b c d e + 10 echo line 2 for history + 11 echo line 8 for history + 12 /bin/sh -c 'echo this is $0' + 13 echo sh + 14 echo /bin + 15 echo e + 16 echo a b c d e + 17 echo b c d e + 18 echo b c d + 19 echo d e + 20 echo b c d + 21 echo file.c + 22 echo file + 23 echo .c + 24 echo 'file' + 25 echo $file.c + 26 echo $file + 27 echo .c + 28 echo '$file' + 29 echo a b c d e + 30 echo 'a' 'b' 'c' 'd' 'e' + 31 echo 'a b c d e' + 32 echo foo.c foo.o foo.html foo.h + 33 echo bar.c foo.o foo.html foo.h + 34 echo bar.c bar.o bar.html bar.h + 35 echo xbar.c xbar.o xbar.html xbar.h + 36 echo xwhix.c xwhix.o xwhix.html xwhix.h + 37 echo 'xwhix' + 38 echo 'xwhix.h' +!! +!! +echo '!!' \!\! +!! !! +ok 1 +ok 2 +ok 3 diff --git a/tests/histexp.tests b/tests/histexp.tests new file mode 100644 index 0000000..721208c --- /dev/null +++ b/tests/histexp.tests @@ -0,0 +1,124 @@ +LC_ALL=C +LANG=C +trap 'rm /tmp/newhistory' 0 + +file=bax +histchars='!^#' # make sure history comment char is set correctly + +unset HISTFILESIZE + +history -c + +HISTFILE=history.list +HISTCONTROL=ignoreboth +HISTIGNORE='&:#*:history*:fc*' +# we will end up exercising the history stifling code as a result +HISTSIZE=32 + +shopt -s cmdhist +set -o history + +history -p '!!' + +# this should result in a failed history expansion error +history -p '!!:z' + +history + +HISTFILE=/tmp/newhistory +history -a + +history -w + +history -s "echo line 2 for history" +history +history -p '!e' +history -p '!!' + +set -H +!! +!e + +history + +echo a b c d e +!?ch? +!-2 +^2^8 + +!2 + +# we're selecting /bin/sh -c ...; we want `sh' +echo !-1:0:t +# we're selecting /bin/sh -c ...; we want `/bin' +echo !-2:0:h +# we're selecting `echo a b c d e'; we want `e' +echo !?d?:5 + +echo a b c d e +echo !-1:2-$ +echo !-2:2-4 +echo !-2:3* +echo !!:* + +echo !?a?:2- + +echo file.c +echo !!:$:r +echo !-2:$:e +echo !-3:$:r:q + +echo $file.c +echo !!:$:r +echo !-2:^:e +echo !-3:$:r:q + +echo a b c d e +echo !!:1-$:x +echo !-2:1-$:q + +echo foo.c foo.o foo.html foo.h +!!:s/foo/bar/ +!-2:gs/foo/bar/ +!!:gs/bar/x&/ +!-2:g& + +# make sure we can use any delimiter in the substitution, not just `/' +!!:gs+bar+whix+ + +!!:p + +# wow +echo !?.o?:%:r:q + +!!:0 !?.h?:%:q +!!:-$ +!:-$ + +history + +# make sure single quotes inhibit history expansion +echo '!!' + +# make sure backslashes can quote the history expansion character +echo \!\! + +# but other expansions on the line should still be processed + +echo '!!' !!:* +history -c +unset HISTFILE + +# make sure that the special bash cases are not history expanded +case p in +[!A-Z]) echo ok 1;; +esac + +var1='ok 2' +var2=var1 + +echo ${!var2} + +# Bash-2.01[.1] fails this test -- it attempts history expansion after the +# history_expansion_char +echo ok 3 # !1200 diff --git a/tests/history.list b/tests/history.list new file mode 100644 index 0000000..2a4c222 --- /dev/null +++ b/tests/history.list @@ -0,0 +1,4 @@ +for i in one two three; do echo $i; done +/bin/sh -c 'echo this is $0' +ls +echo $BASH_VERSION diff --git a/tests/history.right b/tests/history.right new file mode 100644 index 0000000..556a312 --- /dev/null +++ b/tests/history.right @@ -0,0 +1,111 @@ +./history.tests: line 4: history: -x: invalid option +history: usage: history [-c] [-d offset] [n] or history -awrn [filename] or history -ps arg [arg...] +./history.tests: line 6: history: cannot use more than one of -anrw +./history.tests: line 9: fc: -v: invalid option +fc: usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd] + 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 +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 + for i in one two three; do echo $i; done + /bin/sh -c 'echo this is $0' + ls + echo $BASH_VERSION +4 echo $BASH_VERSION +3 ls +2 /bin/sh -c 'echo this is $0' +1 for i in one two three; do echo $i; done + echo $BASH_VERSION + ls + /bin/sh -c 'echo this is $0' + for i in one two three; do echo $i; done + 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 +echo line for history + for i in one two three; do echo $i; done + /bin/sh -c 'echo this is $0' + ls + echo $BASH_VERSION + echo line for history +displaying $HISTFILE after history -a +echo line for history +HISTFILE=/tmp/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 + 7 echo displaying \$HISTFILE after history -a + 8 cat $HISTFILE +for i in one two three; do echo $i; done +/bin/sh -c 'echo this is $0' +ls +echo $BASH_VERSION +echo line for history +HISTFILE=/tmp/newhistory +echo displaying \$HISTFILE after history -a +cat $HISTFILE + 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 + 7 echo displaying \$HISTFILE after history -a + 8 cat $HISTFILE + 9 echo line 2 for history +echo line 2 for history +echo line 2 for history + 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 + 7 echo displaying \$HISTFILE after history -a + 8 cat $HISTFILE + 9 echo line 2 for history + 10 # this should show up as one history entry + 11 for x in one two three; do :; done +set -H +echo line 2 for history +line 2 for history +4 echo $BASH_VERSION +5 echo line for history +6 HISTFILE=/tmp/newhistory +7 echo displaying \$HISTFILE after history -a +8 cat $HISTFILE +9 echo line 2 for history +10 # this should show up as one history entry +11 for x in one two three; do :; done +12 # just a basic test. a full test suite for history expansion should be +13 # created +14 set -H +15 echo line 2 for history +16 unset HISTSIZE +17 unset HISTFILE +4 echo $BASH_VERSION +5 echo line for history +6 HISTFILE=/tmp/newhistory +7 echo displaying \$HISTFILE after history -a +8 cat $HISTFILE +./history.tests: line 75: fc: history specification out of range + 14 set -H + 15 echo line 2 for history + 16 unset HISTSIZE + 17 unset HISTFILE +aa ab ac +echo xx xb xc +xx xb xc +echo 44 48 4c +44 48 4c +./history.tests: line 90: fc: no command found +1 diff --git a/tests/history.tests b/tests/history.tests new file mode 100644 index 0000000..833cf3a --- /dev/null +++ b/tests/history.tests @@ -0,0 +1,98 @@ +trap 'rm /tmp/newhistory' 0 + +# bad options +history -x +# cannot use -r and -w at the same time +history -r -w /dev/null + +# bad option +fc -v + +unset HISTFILESIZE + +# all of these should result in an empty history list +history -c +history -r /dev/null +history -n /dev/null +history -c + +HISTFILE=history.list +HISTCONTROL=ignoreboth +HISTIGNORE='&:history*:fc*' +HISTSIZE=32 + +shopt -s cmdhist +set -o history + +history + +fc -l +fc -nl + +fc -lr +fc -nlr + +history -s "echo line for history" +history + +history -p '!!' + +fc -nl + +HISTFILE=/tmp/newhistory +history -a +echo displaying \$HISTFILE after history -a +cat $HISTFILE + +history +history -w +cat $HISTFILE + +history -s "echo line 2 for history" +history +history -p '!e' +history -p '!!' + +# this should show up as one history entry +for x in one two three +do + : +done +history + +# just a basic test. a full test suite for history expansion should be +# created +set -H +!! +!e + +unset HISTSIZE +unset HISTFILE + +fc -l 4 +fc -l 4 8 + +fc -l one=two three=four 502 + +history 4 + +shopt -so history +shopt -s expand_aliases + +alias r="fc -s" + +echo aa ab ac + +r a=x +r x=4 b=8 + +# this had better fail with `no command found' +r cc + +unalias -a +alias + +set +o history + +shopt -q -o history +echo $? diff --git a/tests/ifs-posix.right b/tests/ifs-posix.right new file mode 100644 index 0000000..f3bdccc --- /dev/null +++ b/tests/ifs-posix.right @@ -0,0 +1 @@ +# tests 6856 passed 6856 failed 0 diff --git a/tests/ifs-posix.tests b/tests/ifs-posix.tests new file mode 100644 index 0000000..cf9a898 --- /dev/null +++ b/tests/ifs-posix.tests @@ -0,0 +1,257 @@ +# Usage: $SHELL ifs.sh +# +# This script generates 6856 tests for the set(1) and read(1) +# builtins w.r.t. IFS whitespace and non-whitespace characters. +# Each failed test produces one line on the standard output that +# contains the test along with the expected and actual results. +# The last output line contains the test result counts. ordered>0 +# are the number of tests where IFS=": " produced different results +# than IFS=" :". If a test fails the same way for IFS=": " and +# IFS=" :" then the second output line is suppressed. + +TESTS=6856 + +ksh_read=0 +echo 1 | read ksh_read +ksh_arith=0 +eval '((ksh_arith+=1))' 2>/dev/null + +failed=0 +ordered=0 +passed=0 + +split() +{ + i=$1 s=$2 r=$3 S='' R='' + for ifs in ': ' ' :' + do IFS=$ifs + set x $i + shift + IFS=' ' + g="[$#]" + while : + do case $# in + 0) break ;; + esac + g="$g($1)" + shift + done + case $g in + "$s") case $ksh_arith in + 1) ((passed+=1)) ;; + *) passed=`expr $passed + 1` ;; + esac + case $S in + '') S=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + ;; + "$S") case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + ;; + *) case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + case $s in + "$S") ;; + ?0*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#]\" # expected \"$s\" got \"$g\"" ;; + ?1*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)\" # expected \"$s\" got \"$g\"" ;; + ?2*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)(\$2)\" # expected \"$s\" got \"$g\"" ;; + ?3*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)(\$2)(\$3)\" # expected \"$s\" got \"$g\"" ;; + *) echo TEST ERROR i="'$i'" s="'$s'" ;; + esac + case $S in + '') S=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + esac + case $ksh_read in + 1) echo "$i" | IFS=$ifs read x y; g="($x)($y)" ;; + *) g=`export ifs; echo "$i" | ( IFS=$ifs; read x y; echo "($x)($y)" )` ;; + esac + case $g in + "$r") case $ksh_arith in + 1) ((passed+=1)) ;; + *) passed=`expr $passed + 1` ;; + esac + case $R in + '') R=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + ;; + "$R") case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + ;; + *) case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + case $r in + "$R") ;; + *) echo "echo \"$i\" | ( IFS=\"$ifs\" read x y; echo \"(\$x)(\$y)\" ) # expected \"$r\" got \"$g\"" ;; + esac + case $R in + '') R=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + ;; + esac + done +} + +for str in \ + '-' \ + 'a' \ + '- -' \ + '- a' \ + 'a -' \ + 'a b' \ + '- - -' \ + '- - a' \ + '- a -' \ + '- a b' \ + 'a - -' \ + 'a - b' \ + 'a b -' \ + 'a b c' \ + +do + IFS=' ' + set x $str + + shift + case $# in + 0) continue ;; + esac + + f1=$1 + case $f1 in + '-') f1='' ;; + esac + + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f1$d1 in + '') split "$d0$f1$d1" "[0]" "()()" ;; + ' ') ;; + *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;; + esac + done + done + continue + ;; + esac + f2=$1 + case $f2 in + '-') f2='' ;; + esac + + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in ' ' ':' ' :' ': ' ' : ' + do + case ' ' in + $f1$d1|$d1$f2) continue ;; + esac + for d2 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f2$d2 in + '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;; + ' ') ;; + *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;; + esac + done + done + done + continue + ;; + esac + f3=$1 + case $f3 in + '-') f3='' ;; + esac + + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in ':' ' :' ': ' ' : ' + do + case ' ' in + $f1$d1|$d1$f2) continue ;; + esac + for d2 in ' ' ':' ' :' ': ' ' : ' + do + case $f2$d2 in + ' ') continue ;; + esac + case ' ' in + $f2$d2|$d2$f3) continue ;; + esac + for d3 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f3$d3 in + '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; + ' ') ;; + *) x=$f2$d2$f3$d3 + x=${x#' '} + x=${x%' '} + split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" + ;; + esac + done + done + done + done + continue + ;; + esac +done +case $ksh_arith in +1) ((tests=passed+failed)) ;; +*) tests=`expr $passed + $failed` ;; +esac +case $ordered in +0) ordered="" ;; +*) ordered=" ordered $ordered" ;; +esac +case $tests in +$TESTS) fatal="" ;; +*) fatal=" -- fundamental IFS error -- $TESTS tests expected" +esac +echo "# tests $tests passed $passed failed $failed$ordered$fatal" diff --git a/tests/ifs.right b/tests/ifs.right new file mode 100644 index 0000000..512f6ee --- /dev/null +++ b/tests/ifs.right @@ -0,0 +1,10 @@ +a:b:c +a:b:c +a:b:c +a b c d e +a:b:c:d:e +a b c d e +a:b:c:d:e +a:b:c:d:e +a b c d e +a b c d e diff --git a/tests/ifs.tests b/tests/ifs.tests new file mode 100644 index 0000000..763e2a0 --- /dev/null +++ b/tests/ifs.tests @@ -0,0 +1,61 @@ +OIFS="$IFS" +IFS=":$IFS" +eval foo="a:b:c" +IFS="$OIFS" +echo $foo + +OIFS=$IFS +IFS=":$IFS" +foo=$(echo a:b:c) +IFS=$OIFS + +for i in $foo +do + echo $i +done + +OIFS=$IFS +IFS=":$IFS" +foo=`echo a:b:c` +IFS=$OIFS + +for i in $foo +do + echo $i +done + +DEFIFS=$' \t\n' + +# local copy of IFS that shadows global version +function f +{ + typeset IFS=: + + echo $1 +} + +function ff +{ + echo $1 +} + +f a:b:c:d:e +x=a:b:c:d:e +echo $x + +IFS=: ff a:b:c:d:e +echo $x + +# doesn't get word split +IFS=$DEFIFS +# variable assignment doesn't use new value for word splitting +IFS=: echo $x +# but does this time because of the eval +IFS=: eval echo \$x + +# in posix mode, assignments preceding special builtins and functions are global +set -o posix +IFS=: export x +echo $x + +IFS="$DEFIFS" diff --git a/tests/input-line.sh b/tests/input-line.sh new file mode 100644 index 0000000..3f66c81 --- /dev/null +++ b/tests/input-line.sh @@ -0,0 +1,4 @@ +echo before calling input-line.sub +${THIS_SH} ./input-line.sub +this line for input-line.sub +echo finished with input-line.sub diff --git a/tests/input-line.sub b/tests/input-line.sub new file mode 100644 index 0000000..7bc8df2 --- /dev/null +++ b/tests/input-line.sub @@ -0,0 +1,2 @@ +read line +echo line read by $0 was \`$line\' diff --git a/tests/input.right b/tests/input.right new file mode 100644 index 0000000..8733feb --- /dev/null +++ b/tests/input.right @@ -0,0 +1,3 @@ +before calling input-line.sub +line read by ./input-line.sub was `this line for input-line.sub' +finished with input-line.sub diff --git a/tests/intl.right b/tests/intl.right new file mode 100644 index 0000000..21a3b4f --- /dev/null +++ b/tests/intl.right @@ -0,0 +1,10 @@ +é +1 +AéB +B +B +ok 1 +ok 2 +aéb +0000000 141 303 251 142 +0000004 diff --git a/tests/intl.tests b/tests/intl.tests new file mode 100644 index 0000000..0dc33cb --- /dev/null +++ b/tests/intl.tests @@ -0,0 +1,38 @@ +export LANG=en_US.UTF-8 + +a=$'\303\251' + +echo "$a" + +echo ${#a} + +b=$'A\303\251B' + +echo "$b" + +echo ${b: -1} + +c=AeB + +echo ${c: -1} + +unset a +a=$(printf '%b' 'A\303\251B') +IFS=$(printf '%b' '\303\251') + +case "$a" in +"A${IFS}B") echo ok 1 ;; +*) echo bad 1 ;; +esac + +set $a + +case $1 in +A) echo ok 2 ;; +*) echo bad 2 ;; +esac + +set a b + +printf '%s\n' "$*" +printf '%s' "$*" | od -b diff --git a/tests/invert.right b/tests/invert.right new file mode 100644 index 0000000..5a9239a --- /dev/null +++ b/tests/invert.right @@ -0,0 +1,10 @@ +1 +1 +1 +0 +0 +1 +0 +1 +0 +1 diff --git a/tests/invert.tests b/tests/invert.tests new file mode 100644 index 0000000..8393d95 --- /dev/null +++ b/tests/invert.tests @@ -0,0 +1,19 @@ +# tests of return value inversion +# placeholder for future expansion + +# user subshells (...) did this wrong in bash versions before 2.04 + +! ( echo hello | grep h >/dev/null 2>&1 ); echo $? +! echo hello | grep h >/dev/null 2>&1 ; echo $? + +! true ; echo $? +! false; echo $? + +! (false) ; echo $? +! (true); echo $? + +! true | false ; echo $? +! false | true ; echo $? + +! (true | false) ; echo $? +! (false | true) ; echo $? diff --git a/tests/iquote.right b/tests/iquote.right new file mode 100644 index 0000000..d164f10 --- /dev/null +++ b/tests/iquote.right @@ -0,0 +1,61 @@ +argv[1] = <xxxyyy> +argv[1] = <xxx^?yyy> +argv[1] = <xy> +argv[1] = <x^?y> +argv[1] = <--> +argv[1] = <-^?-> +argv[1] = <> +argv[1] = <> +argv[1] = <^?> +argv[1] = <^?yy> +0x7f +0x7f +0x7f +argv[1] = <^?> +argv[1] = <^?@> +argv[1] = <@^?@> +argv[1] = <@^?> +argv[1] = <^?> +argv[1] = <^?@> +argv[1] = <@^?@> +argv[1] = <@^?> +argv[1] = <1> +argv[2] = <^?> +argv[3] = <^?> +argv[1] = <2> +argv[2] = <^?a> +argv[3] = <^?a> +argv[1] = <2> +argv[2] = <^?a> +argv[3] = <^?a> +argv[1] = <3> +argv[2] = <^?aa> +argv[3] = <^?aa> +argv[1] = <> +argv[1] = <--> +argv[1] = <--> +argv[1] = <^?> +argv[1] = <-^?-> +argv[1] = <^?> +argv[1] = <-^?-> +ok +argv[1] = <aaa^?bbb> +argv[1] = <ccc^?ddd> +argv[1] = <eee^?fff> +argv[1] = <ggg^?hhh> +argv[1] = <aaabbb> +argv[1] = <cccddd> +argv[1] = <eeefff> +argv[1] = <ggghhh> +argv[1] = <aaa^?bbb> +argv[1] = <ccc^?ddd> +argv[1] = <eee^?fff> +argv[1] = <ggg^?hhh> +argv[1] = <aaabbb> +argv[1] = <cccddd> +argv[1] = <eeefff> +argv[1] = <ggghhh> +argv[1] = <aaa^?bbb> +argv[1] = <ccc^?ddd> +argv[1] = <eee^?fff> +argv[1] = <ggg^?hhh> diff --git a/tests/iquote.tests b/tests/iquote.tests new file mode 100644 index 0000000..a2cdf4f --- /dev/null +++ b/tests/iquote.tests @@ -0,0 +1,143 @@ +# bug in bash up to and including bash-3.0 (including patches) +# +# problem is conflict between CTLNUL used internally to denote quoted null +# characters and its value (0x7f) appearing in the expansion of a variable +# +unset x +recho "xxx${x}yyy" + +y=$'\177' +recho "xxx${y}yyy" + +unset y + +unset undef + +set "" +recho ${undef-"x$*y"} + +set $'\177' +recho ${undef-"x$*y"} + +shift $# + +f() +{ + recho "-${*-x}-" +} + +f '' +f $'\177' + +unset -f f + +x=12345 + +recho "${x:6:1}" + +x= +recho "${x:0:1}" + +y=$'\177' +recho "${y:0:1}" + +y=xxx$'\177'yyy +recho "${y:3:3}" + +unset x y + +eval tmp=`printf "$'\\\\\x%x'\n" 127` +printf "%#1x\n" "'$tmp" + +x=$'\177' +printf "%#1x\n" "'$x" + +a=127 +eval c=\$\'\\$(printf '%o' $a)\' +printf "%#1x\n" "'$c" + +recho "$c" +recho "$c"@ +recho @"$c"@ +recho @"$c" + +recho "$c" +recho "$c@" +recho "@$c@" +recho "@$c" + +unset tmp x a c + +qtest() +{ + recho ${#q} "${q}" ${q} +} + +q=$'\x7f' +qtest + +q=${q}a +qtest + +q=$'\x7fa' +qtest + +q="${q}a" +qtest + +unset -f qtest +unset q + +set -- '' +recho "${*:1}" +recho ${*:1} +recho -${*:1}- +recho -"${*:1}"- + +set $'\177' +recho "${*:1}" +recho "-${*:1}-" + +recho ${*:1} +recho -${*:1}- + +shift $# + +DEL=`awk 'END{printf("%c", 0+127)}' </dev/null` +T1=a\ $DEL +T2="a $DEL" +set -- x $(echo $T1|wc -c) $(echo $T2|wc -c); shift +L1=$1; L2=$2 +case "$L1/$L2" in +4/4) echo ok;; +*) echo CTLNUL bug: L1=$L1, L2=$L2;; +esac + +x=$'\177' +recho "aaa${x}bbb" +recho ccc"${x}"ddd +recho eee"$x"fff +recho ggg"$(echo $x)"hhh + +x= +recho "aaa${x}bbb" +recho ccc"${x}"ddd +recho eee"$x"fff +recho ggg"$(echo $x)"hhh + +set -- $'\177' +recho "aaa${1}bbb" +recho ccc"${1}"ddd +recho eee"$1"fff +recho ggg"$(echo $1)"hhh + +set -- "" +recho "aaa${1}bbb" +recho ccc"${1}"ddd +recho eee"$1"fff +recho ggg"$(echo $1)"hhh + +recho aaa$'\177'bbb +recho ccc""ddd +recho "eeefff" +recho ggg"$(echo $'\177')"hhh diff --git a/tests/jobs.right b/tests/jobs.right new file mode 100644 index 0000000..0a6fce9 --- /dev/null +++ b/tests/jobs.right @@ -0,0 +1,105 @@ +./jobs2.sub: line 9: fg: job 1 started without job control +fg: 1 +Waiting for job 0 +job 0 returns 0 +Waiting for job 1 +job 1 returns 0 +Waiting for job 2 +job 2 returns 0 +Waiting for job 3 +job 3 returns 0 +Waiting for job 4 +job 4 returns 0 +Waiting for job 5 +job 5 returns 0 +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 ) & +4 +0 +i killed it +0 +./jobs.tests: line 19: wait: %1: no such job +./jobs.tests: line 24: fg: no job control +wait-for-pid +wait-errors +./jobs.tests: line 37: wait: `1-1': not a pid or valid job spec +./jobs.tests: line 38: 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 60: wait: %2: no such job +127 +async list wait-for-job +forked +fg-bg 1 +sleep 5 +fg-bg 2 +sleep 5 +fg-bg 3 +sleep 5 +fg-bg 4 +sleep 5 +fg-bg 5 +./jobs.tests: line 87: fg: %2: no such job +./jobs.tests: line 88: bg: job 1 already in background +fg-bg 6 +./jobs.tests: line 95: fg: -s: invalid option +fg: usage: fg [job_spec] +./jobs.tests: line 96: bg: -s: invalid option +bg: usage: bg [job_spec ...] +./jobs.tests: line 101: disown: -s: invalid option +disown: usage: disown [-h] [-ar] [jobspec ...] +./jobs.tests: line 105: disown: %1: no such job +./jobs.tests: line 108: disown: %2: no such job +wait-for-non-child +./jobs.tests: line 111: wait: pid 1 is not a child of this shell +127 +3 -- 1 2 3 -- 1 - 2 - 3 +[1] Running sleep 300 & +[2]- Running sleep 350 & +[3]+ Running sleep 400 & +running jobs: +[1] Running sleep 300 & +[2]- Running sleep 350 & +[3]+ Running sleep 400 & +./jobs.tests: line 127: kill: %4: no such job +./jobs.tests: line 129: jobs: %4: no such job +current job: +[3]+ Running sleep 400 & +previous job: +[2]- Running sleep 350 & +after kill -STOP +running jobs: +[1] Running sleep 300 & +[3]- Running sleep 400 & +stopped jobs: +[2]+ Stopped sleep 350 +after disown +[2]+ Stopped sleep 350 +[3]- Running sleep 400 & +running jobs: +[3]- Running sleep 400 & +stopped jobs: +[2]+ Stopped sleep 350 +after kill -s CONT +running jobs: +[2]+ Running sleep 350 & +[3]- Running sleep 400 & +stopped jobs: +after kill -STOP, backgrounding %3: +[3]+ sleep 400 & +killing... +done +after KILL -STOP, foregrounding %1 +sleep 10 +done diff --git a/tests/jobs.tests b/tests/jobs.tests new file mode 100644 index 0000000..5866b0c --- /dev/null +++ b/tests/jobs.tests @@ -0,0 +1,183 @@ +# test out %+, jobs -p, and $! agreement in a subshell first +${THIS_SH} ./jobs1.sub + +# test out fg/bg failure in a subshell +${THIS_SH} ./jobs2.sub + +# test out behavior of waiting for background pids -- bug in versions +# before 2.03 +${THIS_SH} ./jobs3.sub + +# test out behavior of using job control notation when job control is not +# active +${THIS_SH} ./jobs4.sub + +jobs +echo $? + +# a no-such-job error, since we can use job control notation without job control +wait %1 + +# make sure we can't fg a job started when job control was not active +sleep 30 & +pid=$! +fg %1 +# make sure the killed processes don't cause a message +exec 5>&2 +exec 2>/dev/null +kill -n 9 $pid +wait # make sure we reap the processes while stderr is still redirected +exec 2>&5 + +echo wait-for-pid +sleep 10 & +wait $! + +echo wait-errors +wait 1-1 +wait -- -4 + +echo wait-for-background-pids +sleep 5 & +sleep 8 & +wait + +echo async list wait-for-background-pids +sleep 5 & sleep 8 & +wait + +echo async list wait for child +sleep 5 & echo forked +wait + +echo wait-when-no-children +wait + +set -m + +echo wait-for-job +sleep 5 & +wait %2 # this should be a no-such-job error +echo $? +wait %1 + +echo async list wait-for-job +sleep 5 & echo forked +wait %1 + +echo fg-bg 1 +sleep 5 & +%1 + +echo fg-bg 2 +sleep 5 & +fg %% + +echo fg-bg 3 +sleep 5 & +fg %s + +echo fg-bg 4 +sleep 5 & +fg %?ee + +# these next two are error cases +echo fg-bg 5 +sleep 15 & +fg %2 # this should be a no-such-job error +bg %1 # this should be a `bg background job?' error +wait + +# these may someday mean to start the jobs, but not print the line +# describing the status, but for now they are errors +echo fg-bg 6 +sleep 5 & +fg -s %1 +bg -s %1 +wait + +# someday this may mean to disown all stopped jobs, but for now it is +# an error +disown -s + +# this is an error -- the job with the pid that is the value of $! is +# retained only until a `wait' is performed +disown %1 + +# this, however, is an error +disown %2 + +echo wait-for-non-child +wait 1 +echo $? + +exit 1 | exit 2 | exit 3 +echo $? -- ${PIPESTATUS[@]} -- ${PIPESTATUS[0]} - ${PIPESTATUS[1]} - ${PIPESTATUS[2]} + +sleep 300 & +sleep 350 & +sleep 400 & + +jobs + +echo running jobs: +jobs -r + +# should be an error +kill -n 1 %4 +# should be an error +jobs %4 +echo current job: +jobs %+ +echo previous job: +jobs %- + +kill -STOP %2 +sleep 5 # give time for the shell to get the stop notification +echo after kill -STOP +echo running jobs: +jobs -r +echo stopped jobs: +jobs -s + +disown %1 + +echo after disown +jobs +echo running jobs: +jobs -r +echo stopped jobs: +jobs -s + +kill -s CONT %2 +echo after kill -s CONT +echo running jobs: +jobs -r +echo stopped jobs: +jobs -s + +kill -STOP %3 +sleep 5 # give time for the shell to get the stop notification +echo after kill -STOP, backgrounding %3: +bg %3 + +disown -h %2 + +# make sure the killed processes don't cause a message +exec 5>&2 +exec 2>/dev/null + +echo killing... +kill -n 9 %2 %3 +wait # make sure we reap the processes while stderr is still redirected +echo done + +exec 2>&5 + +sleep 10 & +kill -STOP %1 +sleep 5 # give time for the shell to get the stop notification +echo after KILL -STOP, foregrounding %1 +fg %1 + +echo done diff --git a/tests/jobs1.sub b/tests/jobs1.sub new file mode 100644 index 0000000..aa9a372 --- /dev/null +++ b/tests/jobs1.sub @@ -0,0 +1,17 @@ +# make sure that jobs -p, %+, and $! all agree +set -m +sleep 60 & + +FN=/tmp/jobs-pid.$$ + +pid1=$! +jobs -p %+ > $FN +pid2=$(< $FN) +rm $FN + +if [ $pid1 -ne $pid2 ]; then + echo 'oops - $! and jobs -p %+ disagree!' +fi + +exec 2>/dev/null +kill -9 $pid1 diff --git a/tests/jobs2.sub b/tests/jobs2.sub new file mode 100644 index 0000000..496519b --- /dev/null +++ b/tests/jobs2.sub @@ -0,0 +1,13 @@ +# make sure fg and bg don't work on jobs started without job control, +# even if they are executed when job control is active +set +o monitor + +sleep 30 & +pid=$! + +set -m +fg %1 +echo fg: $? + +exec 2>/dev/null +kill -9 $pid diff --git a/tests/jobs3.sub b/tests/jobs3.sub new file mode 100644 index 0000000..6efd58b --- /dev/null +++ b/tests/jobs3.sub @@ -0,0 +1,26 @@ +#! /bin/bash +NJOB=8 +i=0 + +while [ $i -lt $NJOB ] +do + /bin/sh -c "sleep 4; exit 0" & + rv=$? + pid=$! + eval bg_pid_$i=$pid +# echo $$: Job $i: pid is $pid rv=$rv + i=$((i + 1)) +done + + + +i=0 +while [ $i -lt $NJOB ] +do + eval wpid=\$bg_pid_$i + echo Waiting for job $i #'('pid $wpid')' + wait $wpid + rv=$? + echo job $i returns $rv + i=$((i + 1)) +done diff --git a/tests/jobs4.sub b/tests/jobs4.sub new file mode 100644 index 0000000..2eb4197 --- /dev/null +++ b/tests/jobs4.sub @@ -0,0 +1,24 @@ +# test being able to use job control notation in jobs/kill/wait without +# job control active, as the SUS requires + +sleep 5 & + +sleep 5 & +sleep 5 & +sleep 5 & +(sleep 5 ; exit 4) & + +jobs + +wait %% +echo $? + +wait %1 +echo $? + +wait + +# the sleep is intended to give the kill time to execute before the job +# exits +(sleep 1 ; cat ) & +kill -1 %% && echo i killed it || echo could not kill it diff --git a/tests/misc/dev-tcp.tests b/tests/misc/dev-tcp.tests new file mode 100644 index 0000000..0f3a228 --- /dev/null +++ b/tests/misc/dev-tcp.tests @@ -0,0 +1,16 @@ +exec 9<>/dev/tcp/129.22.8.162/25 + +read banner <&9 +echo "$banner" + +echo quit >&9 + +read msg <&9 +echo "$msg" + +exec 9<&- + +# nifty date command that queries the date/time server +cat < /dev/tcp/129.22.8.102/13 + +exit 0 diff --git a/tests/misc/perf-script b/tests/misc/perf-script new file mode 100644 index 0000000..e1172a9 --- /dev/null +++ b/tests/misc/perf-script @@ -0,0 +1,81 @@ +#!/bin/bash + +typeset -i m2 m1 M n2 n1 N m n +typeset -i MM=5 NN=5 + +case $# in + 0) : + ;; + 1) MM=$1; NN=$1 + ;; + 2) MM=$1; NN=$2 + ;; + *) echo 1>&2 "Usage: $0 [m [n]]" + ;; +esac + +EMPTYLINE=: # echo +echo 'a = { ' # mathematica + +let "M=1" # for (M=1; M<=MM; M++) +while let "M <= MM"; do + let "N=1" # for (N=1; N<=NN; N++) + while let "N <= NN"; do + + let "m1 = M - 1" + let "m2 = M + 1" + let "n1 = N - 1" + let "n2 = N + 1" + + + echo -n '{ ' # math + let "m=1" # for(m=1; m<=MM; m++) + while let "m <= MM"; do + let "n=1" # for(n=1; n<=NN; n++) + while let "n <= NN"; do + + let "x = (m-m1)*(m-M)*(m-m2)" + let "y = (n-n1)*(n-N)*(n-n2)" + + if let "(x*x + (n-N)*(n-N)) * ((m-M)*(m-M) + y*y)"; then + echo -n "0," + else # neighbour + echo -n "1," + fi + + let "n=n+1" + done + echo -n " "; let "m=m+1" # ". " + done + echo '},' + + + let "N=N+1" + $EMPTYLINE + done + $EMPTYLINE + let "M=M+1" +done + +echo '}' + + + +echo -n 'o = { ' +let "m=1" +while let "m <= MM"; do + let "n=1" + while let "n <= NN"; do + echo -n "1," + let "n=n+1" + done + let "m=m+1" +done +echo " }" + + +echo 'x = LinearSolve[a,o] ' + +exit 0 + + diff --git a/tests/misc/perftest b/tests/misc/perftest new file mode 100644 index 0000000..ee3f2c6 --- /dev/null +++ b/tests/misc/perftest @@ -0,0 +1,10 @@ +# originally from Mike Haertel +foo() { case $1 in a*) ;; *) ;; esac ;} +bar() { case $1 in [abc]*) ;; *);; esac ;} +baz() { case $1 in xyzzy) ;; *) ;; esac ;} +for x in /usr/lib/*/* +do + foo $x + bar $x + baz $x +done diff --git a/tests/misc/read-nchars.tests b/tests/misc/read-nchars.tests new file mode 100644 index 0000000..40b1f98 --- /dev/null +++ b/tests/misc/read-nchars.tests @@ -0,0 +1,11 @@ +# interactive + +# from tty +read -n 3 -p 'enter three chars: ' xyz +echo +echo $xyz + +# using readline +read -p 'enter 3 chars: ' -e -n 3 abc +# readline outputs a newline for us, so we don't need the extra echo +echo $abc diff --git a/tests/misc/redir-t2.sh b/tests/misc/redir-t2.sh new file mode 100644 index 0000000..44b2624 --- /dev/null +++ b/tests/misc/redir-t2.sh @@ -0,0 +1,17 @@ +read line1 + +echo read line 1 \"$line1\" + +exec 4<&0 + +exec 0</dev/tty + +read line2 + +echo line read from tty = \"$line2\" + +exec 0<&4 + +read line3 + +echo read line 3 \"$line3\" diff --git a/tests/misc/run-r2.sh b/tests/misc/run-r2.sh new file mode 100755 index 0000000..0321a1b --- /dev/null +++ b/tests/misc/run-r2.sh @@ -0,0 +1 @@ +../../bash ./redir-t2.sh < /etc/passwd diff --git a/tests/misc/sigint-1.sh b/tests/misc/sigint-1.sh new file mode 100755 index 0000000..7b74c30 --- /dev/null +++ b/tests/misc/sigint-1.sh @@ -0,0 +1,9 @@ +echo before trap +trap 'echo caught sigint' 2 +echo after trap + +for i in 1 2 3 +do + echo $i + sleep 5 +done diff --git a/tests/misc/sigint-2.sh b/tests/misc/sigint-2.sh new file mode 100755 index 0000000..69eaf56 --- /dev/null +++ b/tests/misc/sigint-2.sh @@ -0,0 +1,7 @@ +echo before loop + +for i in 1 2 3 +do + echo $i + sleep 5 +done diff --git a/tests/misc/sigint-3.sh b/tests/misc/sigint-3.sh new file mode 100755 index 0000000..2627fe6 --- /dev/null +++ b/tests/misc/sigint-3.sh @@ -0,0 +1,11 @@ +sleep 5 & +sleep 5 & +sleep 5 & + +echo wait 1 +wait + +echo wait 2 +wait + +exit diff --git a/tests/misc/sigint-4.sh b/tests/misc/sigint-4.sh new file mode 100755 index 0000000..587dd26 --- /dev/null +++ b/tests/misc/sigint-4.sh @@ -0,0 +1,13 @@ +trap 'echo sigint' 2 + +sleep 5 & +sleep 5 & +sleep 5 & + +echo wait 1 +wait + +echo wait 2 +wait + +exit diff --git a/tests/misc/test-minus-e.1 b/tests/misc/test-minus-e.1 new file mode 100644 index 0000000..77cc3f2 --- /dev/null +++ b/tests/misc/test-minus-e.1 @@ -0,0 +1,9 @@ +touch .file +while set -e ; test -r .file ; do + echo -n "stop loop? " + read reply + case "$reply" in + y*) rm .file non-dash-file ;; + esac + set +e +done diff --git a/tests/misc/test-minus-e.2 b/tests/misc/test-minus-e.2 new file mode 100644 index 0000000..f66966e --- /dev/null +++ b/tests/misc/test-minus-e.2 @@ -0,0 +1,11 @@ +touch .file +set -e +while set +e ; test -r .file ; do + echo -n "stop loop? [yes to quit] " + read reply + if [ "$reply" = yes ] ; then + rm .file non-dash-file + fi + set -e +done +rm -f .file diff --git a/tests/misc/wait-bg.tests b/tests/misc/wait-bg.tests new file mode 100644 index 0000000..95c98b0 --- /dev/null +++ b/tests/misc/wait-bg.tests @@ -0,0 +1,25 @@ +#! /bin/bash + +i=0 +while [ $i -lt $1 ] +do + /bin/sh -c "sleep 4; exit 0" & + rv=$? + pid=$! + eval bg_pid_$i=$pid + echo $$: Job $i: pid is $pid rv=$rv + i=$((i + 1)) +done + + + +i=0 +while [ $i -lt $1 ] +do + eval wpid=\$bg_pid_$i + echo Waiting for job $i '('pid $wpid')' + wait $wpid + rv=$? + echo Return value is $rv + i=$((i + 1)) +done diff --git a/tests/more-exp.right b/tests/more-exp.right new file mode 100644 index 0000000..91a375c --- /dev/null +++ b/tests/more-exp.right @@ -0,0 +1,214 @@ +argv[1] = <aaa bbb ccc> +argv[1] = <aaa bbb ccc> +argv[1] = <baz:bar> +argv[1] = <baz:bar> +argv[1] = <aaa bbb ccc> +argv[1] = <bar> +argv[1] = <bar> +argv[1] = <bar> +argv[1] = <abcde> +argv[1] = <abcde> +argv[1] = <xyz> +argv[1] = <a b> +argv[2] = <c> +argv[3] = <d> +argv[4] = <e> +argv[5] = <f> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a b> +argv[2] = <c> +argv[3] = <d> +argv[4] = <e> +argv[5] = <f> +argv[1] = <a b> +argv[2] = <c> +argv[3] = <d> +argv[4] = <e> +argv[5] = <f> +argv[1] = </usr/homes/chet> +argv[1] = <~> +argv[1] = <~> +argv[1] = <\~> +argv[1] = <\ \~> +argv[1] = <\ \ \~> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = <$HOME> +argv[1] = <\ $HOME> +argv[1] = <\ \ $HOME> +argv[1] = <'bar'> +argv[1] = <'bar'> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <*@*> +argv[1] = <*@*> +argv[1] = <*@*> +argv[1] = <*@*> +argv[1] = <abcd> +argv[1] = <efghijkl> +argv[1] = <4> +argv[2] = <2> +argv[1] = <1> +argv[1] = <bar> +argv[1] = <2> +argv[1] = <bar> +argv[1] = <2> +argv[1] = <4> +argv[1] = <--\> +argv[2] = <--> +argv[1] = <--\^J--> +argv[1] = <--+\> +argv[2] = <+--> +argv[1] = <--+\^J+--> +argv[1] = <-+\> +argv[2] = <+-\> +argv[3] = <-> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <> +argv[1] = <> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <> +argv[1] = <> +argv[1] = <x> +argv[1] = <x> +argv[1] = <> +argv[1] = <x> +argv[1] = <x> +argv[1] = <x> +argv[1] = <x> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <x> +argv[1] = <x> +argv[1] = <> +argv[2] = <abd> +argv[3] = <x> +argv[1] = <> +argv[2] = <abd> +argv[3] = <> +argv[1] = <a,b,c,d,e,f> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[6] = <f> +./more-exp.tests: line 272: abc=def: command not found +argv[1] = <a b c d e> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <foo)> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\\a> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\\a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <$a> +argv[1] = <\foo> +argv[1] = <$a> +argv[1] = <\foo> +argv[1] = <\$a> +argv[1] = <\\$a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <G> +argv[2] = <{> +argv[3] = <I> +argv[4] = <K> +argv[5] = <}> +argv[1] = <hi> +argv[2] = <K> +argv[3] = <}> +argv[1] = <a*> +Number of args: 0 +<${*-x}>: <x> +<${@-x}>: <x> +Number of args: 1 +<${*-x}>: <> +<${@-x}>: <> +Number of args: 2 +<${*-x}>: < > +<${@-x}>: < > +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <posparams> +argv[1] = <posparams> +argv[1] = <2> +argv[1] = <0> +argv[1] = <0> +argv[1] = <1> +argv[1] = <5> +argv[1] = <5> +argv[1] = <0> +./more-exp.tests: line 423: ${#:}: bad substitution +./more-exp.tests: line 425: ${#/}: bad substitution +./more-exp.tests: line 427: ${#%}: bad substitution +./more-exp.tests: line 429: ${#=}: bad substitution +./more-exp.tests: line 431: ${#+}: bad substitution +./more-exp.tests: line 433: ${#1xyz}: bad substitution +./more-exp.tests: line 436: #: %: syntax error: operand expected (error token is "%") +argv[1] = <0> +argv[1] = <a+b> +argv[1] = <+> +argv[1] = <+> +argv[1] = <+> +argv[1] = <G { I > +argv[2] = <K> +argv[3] = <}> +argv[1] = <hi> +argv[2] = <K> +argv[3] = <}> +argv[1] = <xxx> +argv[2] = <yyy> +1 +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <:a:> +argv[1] = <:b:> +argv[1] = <> +argv[1] = <> diff --git a/tests/more-exp.tests b/tests/more-exp.tests new file mode 100644 index 0000000..4a3cb7f --- /dev/null +++ b/tests/more-exp.tests @@ -0,0 +1,504 @@ +expect() +{ + echo expect "$@" +} + +tool_var() { + eval $1=\"\${$1:-$2}\" + export $1 +} + +A="aaa bbb ccc" + +unset B + +tool_var B ${B:-"$A"} + +expect '<aaa bbb ccc>' +recho "$A" +expect '<aaa bbb ccc>' +recho "$B" + +eto_prepend() { + eval $1=\'$2\''${'$1':+":"${'$1'}}'; export $1 +} + +foo=bar; export foo +eto_prepend foo baz +expect '<baz:bar>' +recho $foo +expect '<baz:bar>' +recho ${foo-"bar"} + +aa='aaa bbb ccc' + +expect '<aaa bbb ccc>' +recho ${zzz-"$aa"} +expect '<bar>' +recho ${zzz:-"bar"} +expect '<bar>' +recho "${zzz:-bar}" +expect '<bar>' +recho "${zzz:-"bar"}" + +var=abcde +expect '<abcde>' +recho "${var:-xyz}" +expect '<abcde>' +recho "${var:=xyz}" +expect '<xyz>' +recho "${var:+xyz}" + +set 'a b' c d e f +expect '<a b> <c> <d> <e> <f>' +recho ${1+"$@"} +expect '<a b>' +recho "${1-"$@"}" +expect '<a> <b>' +recho ${1-"$@"} +expect '<a b> <c> <d> <e> <f>' +recho "${1+$@}" +expect '<a b> <c> <d> <e> <f>' +recho "${1+"$@"}" + +HOME=/usr/homes/chet +somevar= +expect "<$HOME>" +recho ${somevar:-~} +# This changed after bash-3.0, when the tilde implementation was redone. It's +# not backward compatible, but it's very hard to be backward-compatible here, +# and I think the old behavior was a bug +expect '<~>' +recho "${somevar:-~}" +expect '<~>' +recho "${somevar:-"~"}" +expect '<\~>' +recho "${somevar:-\~}" +expect '<\ \~>' +recho "${somevar:-\ \~}" +expect '<\ \ \~>' +recho "${somevar:-\ \ \~}" + +expect "<$HOME>" +recho ${somevar:-$HOME} +expect "<$HOME>" +recho "${somevar:-$HOME}" +expect "<$HOME>" +recho "${somevar:-"$HOME"}" +expect '<$HOME>' +recho "${somevar:-\$HOME}" +expect '<\ $HOME>' +recho "${somevar:-\ \$HOME}" +expect '<\ \ $HOME>' +recho "${somevar:-\ \ \$HOME}" + +foo=bar +expect "<'bar'>" +recho "${foo+'$foo'}" +expect "<'bar'>" +recho "${fox='$foo'}" + +P='*@*' +expect '<*@>' +recho "${P%"*"}" +expect '<*@>' +recho "${P%'*'}" + +expect '<*@>' +recho ${P%"*"} +expect '<*@>' +recho ${P%'*'} + +expect '<*@*>' +recho ${P%""} +expect '<*@*>' +recho ${P#""} + +expect '<*@*>' +recho ${P#"$foobar"} +expect '<*@*>' +recho ${P%"$foobar"} + +s1=abcdefghijkl +s2=efgh + +first=${s1/$s2*/} +expect '<abcd>' +recho $first + +last=${s1##$first} +expect '<efghijkl>' +recho $last + +shift $# +UNAME_RELEASE=${1:-4.2MP} + +RELEASE=`expr "$UNAME_RELEASE" : '[^0-9]*\([0-9]*\)'` # 4 +case "$RELEASE" in +"") RELEASE=0 ;; +*) RELEASE=`expr "$RELEASE" + 0` ;; +esac +REL_LEVEL=`expr "$UNAME_RELEASE" : '[^0-9]*[0-9]*.\([0-9]*\)'` # 1 +REL_SUBLEVEL=`expr "$UNAME_RELEASE" : '[^0-9]*[0-9]*.[0-9]*.\([0-9]*\)'` # 2 + +expect '<4> <2>' +recho $RELEASE $REL_LEVEL $REL_SUBLEVEL + +b1() +{ + b2 ${1+"$@"} +} + +b2() +{ + recho $* + recho $# +} + +expect '<1>' +b1 '' + +expect '<bar> <2>' +b1 bar '' + +expect '<bar> <2>' +b1 '' bar + +expect '<4>' +b1 '' '' '' '' + +NL="\\ +" + +NNL="+$NL+" + +expect '<--\> <-->' +recho --$NL-- +expect '<--\^J-->' +recho "--$NL--" + +expect '<--+\> <+-->' +recho --$NNL-- +expect '<--+\^J+-->' +recho "--$NNL--" + +expect '<-+\> <+-\> <->' +recho -$NNL-$NL- + +set '' +expect '<xy>' +recho "$*xy" +expect '<xy>' +recho "x$*y" +expect '<xy>' +recho "xy$*" +expect '<xy>' +recho x"$*"y +expect '<xy>' +recho xy"$*" +expect '<xy>' +recho "$*"xy +expect '<>' +recho "$*" +expect nothing +recho $* + +unset undef ; set "" + +expect '<>' +recho ${undef-"$*"} +expect '<xy>' +recho ${undef-"x$*y"} +expect '<xy>' +recho ${undef-"$*xy"} +expect '<xy>' +recho ${undef-"xy$*"} +expect '<xy>' +recho ${undef-x"$*"y} +expect '<xy>' +recho ${undef-xy"$*"} +expect '<xy>' +recho ${undef-"$*"xy} +expect '<>' +recho "${undef-$*}" +expect nothing +recho ${undef-$*} + +expect '<>' +recho ${undef-"$zzz"} +expect '<x>' +recho x${undef-"$zzz"} +expect '<x>' +recho x${undef-"$@"} +expect nothing +recho ${undef-"$@"} +expect '<x>' +recho ${undef-"$zzz"}x +expect '<x>' +recho ${undef-"$@"}x +expect '<x>' +recho "$@"x +expect '<x>' +recho "$zzz"x +expect '<^?>' +recho ${undef-} +expect '<^?>' +recho ${undef-""} + +yyy="" +recho "$xxx"x +recho "$yyy"x + +set "" "abd" "" +recho "$@"x +recho "$@"$xxx + +OIFS="$IFS" + +arg=a,b,c,d,e,f + +IFS=, + +export z=$arg + +eval z1=\"$arg\" + +IFS="$OIFS" + +recho $z +recho $z1 + +# should give an error +abc\=def + +zz="a b c d e" +declare a=$zz + +recho "$a" +recho $a + +recho $(echo "foo$(echo ")")") + +# test backslash escapes + +recho \a +recho \\a + +recho "\a" +recho "\\a" + +recho '\a' +recho '\\a' + +recho $(zecho \a) +recho $(zecho \\a) + +recho $(zecho "\a") +recho $(zecho "\\a") + +recho $(zecho '\a') +recho $(zecho '\\a') + +recho `zecho \a` +recho `zecho \\a` + +recho `zecho "\a"` +recho `zecho "\\a"` + +recho `zecho '\a'` +recho `zecho '\\a'` + +a=foo + +recho \$a +recho \\$a + +recho "\$a" +recho "\\$a" + +recho '\$a' +recho '\\$a' + +recho $(zecho `zecho \a`) +recho $(zecho `zecho \\a`) + +recho $(zecho `zecho "\a"`) +recho $(zecho `zecho "\\a"`) + +recho $(zecho `zecho '\a'`) +recho $(zecho `zecho '\\a'`) + +# should echo G { I K } +recho ${abc:-G { I } K } + +abc=hi + +# should echo hi K } +recho ${abc:-G { I } K } + +# should echo a* +unset foo +recho "${foo:-"a"}*" + +f () +{ + echo "Number of args: $#" + echo "<\${*-x}>: <${*-x}>" + echo "<\${@-x}>: <${@-x}>" +} + +f +f '' +f '' '' + +set 1 2 3 4 5 + +expect '<5>' +recho ${#} +expect '<5>' +recho ${#:foo} +expect '<5>' +recho ${#:-foo} +expect '<5>' +recho ${#-posparams} +expect '<5>' +recho ${#:-posparams} + +expect '<0>' +recho ${#!} + +expect nothing +recho $! +expect nothing +recho ${!} + +expect nothing +recho $8 +expect nothing +recho ${8} + +shift $# + +expect '<0>' +recho ${#} +expect '<0>' +recho ${#:foo} +expect '<0>' +recho ${#:-foo} +expect '<0>' +recho ${#-posparams} +expect '<0>' +recho ${#:-posparams} + +expect '<posparams>' +recho ${!-posparams} +expect '<posparams>' +recho ${!:-posparams} + +expect '<2>' +recho ${#-} + +expect '<0>' +recho ${#-posparams} + +expect '<0>' +recho ${#?:-xyz} + +expect '<1>' +recho ${#?} + +set a b c d e + +expect '<5>' +recho ${#} +expect '<5>' +recho ${#?:-xyz} + +shift $# + +expect '<0>' +recho ${#:-foo} + +expect a bad substitution error +recho ${#:} +expect a bad substitution error +recho ${#/} +expect a bad substitution error +recho ${#%} +expect a bad substitution error +recho ${#=} +expect a bad substitution error +recho ${#+} +expect a bad substitution error +recho ${#1xyz} + +expect a math syntax error +recho ${#:%} + +expect '<0>' +recho ${#:-} + +set -- +unset a b + +x=a +y=b + +IFS=+ + +expect '<a+b>' +recho $x+$y +expect '<+>' +recho $a+$b + +expect '<+>' +recho + "$@" +expect '<+>' +recho +"$@" + +# variants of nested curly braces inside ${...} expressions + +# IFS is not the standard one + +expect '<G { I>' '<K>' '<}>' +recho ${gik:-G { I } K } + +abc=hi + +expect '<hi>' '<K>' '<}>' +recho ${abc:-G { I } K } + +# reset IFS to the default +IFS=' +' + +# nested ${...} inside ${...} are handled specially +unset XXX FOO BAR +expect '<xxx>' '<yyy>' +XXX=xxx +FOO=${BAR:-${XXX} yyy} +recho $FOO + +# this was a bug in versions of bash prior to bash-2.04-release +set -- '' +expect 1 +echo $# +expect '<>' +recho "${@}" +expect '<>' +recho "${@-}" +expect '<>' +recho "${@:-}" + +# this was a bug in bash-2.04, fixed in 2.05 +set -- a b +expect '<:a:>' '<:b:>' +for i in "${@-}"; do recho :$i:; done + +# I believe that ksh93 does these wrong -- we're using the rhs, so shouldn't +# it behave the same as ""? +set -- +expect '<>' +recho "${@-}" +expect '<>' +recho "${@:-}" diff --git a/tests/new-exp.right b/tests/new-exp.right new file mode 100644 index 0000000..8866835 --- /dev/null +++ b/tests/new-exp.right @@ -0,0 +1,505 @@ +argv[1] = <foo bar> +argv[1] = <foo> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +./new-exp.tests: line 24: HOME: }: syntax error: operand expected (error token is "}") +unset +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <@*> +argv[1] = <)> +argv[1] = <")"> +argv[1] = <-abcd> +argv[2] = <-> +argv[1] = <-abcd> +argv[2] = <-> +argv[1] = <-abcd-> +bar foo +bar foo +bar foo +barfoo +barfoo +\x +argv[1] = <abcd> +argv[1] = <efg> +argv[2] = <nop> +argv[1] = <efg> +argv[2] = <nop> +argv[1] = <hijklmnop> +argv[1] = <abcdefghijklmnop> +argv[1] = <abcdefghijklmnop> +argv[1] = <ab cd> +argv[2] = <ef> +argv[1] = <gh ij> +argv[2] = <kl mn> +argv[1] = <gh ij> +argv[2] = <kl mn> +argv[3] = <op> +argv[1] = <ab cd> +argv[2] = <ef> +argv[3] = <gh ij> +argv[4] = <kl mn> +argv[5] = <op> +argv[1] = </home/chet/foo//bar/abcabcabc> +argv[1] = <home/chet/foo//bar/abcabcabc> +argv[1] = <home> +argv[1] = <home> +argv[1] = <home> +argv[1] = <home> +argv[1] = <abcdefghijklmnop> +argv[1] = <4> +argv[1] = <op> +argv[1] = <abcdefghijklmnop> +argv[1] = <abcdefghijklmnop> +./new-exp.tests: line 172: ABX: unbound variable +./new-exp.tests: line 176: $6: cannot assign in this way +argv[1] = <xxcde> +argv[1] = <axxde> +argv[1] = <abxyz> +argv[1] = <abbcde> +argv[1] = <abcde> +argv[1] = <abcabe> +argv[1] = <abcdlast> +argv[1] = <abcde> +argv[1] = <xxcd> +argv[1] = <abxx> +argv[1] = <xxgh> +argv[1] = <efgh> +argv[1] = <xxfgh> +argv[1] = <zagh> +argv[1] = <zaza> +argv[1] = <zagh> +argv[1] = <efza> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <efgh> +argv[3] = <ijkl> +argv[4] = <mnop> +argv[5] = <qrst> +argv[6] = <uvwx> +argv[1] = <abxx> +argv[2] = <efxx> +argv[3] = <ijxx> +argv[4] = <mnxx> +argv[5] = <qrxx> +argv[6] = <uvxx> +argv[1] = <xxcd> +argv[1] = <xxcd> +argv[2] = <xxgh> +argv[3] = <xxkl> +argv[4] = <xxop> +argv[5] = <xxst> +argv[6] = <xxwx> +argv[1] = <abxx> +argv[2] = <efxx> +argv[3] = <ijxx> +argv[4] = <mnxx> +argv[5] = <qrxx> +argv[6] = <uvxx> +argv[1] = <zaza> +argv[1] = <ijza> +argv[1] = <zaza> +argv[2] = <zaza> +argv[3] = <zaza> +argv[4] = <zaza> +argv[5] = <zaza> +argv[6] = <zaza> +argv[1] = <zacd> +argv[2] = <zagh> +argv[3] = <zakl> +argv[4] = <zaop> +argv[5] = <zast> +argv[6] = <zawx> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <efgh> +argv[3] = <ijkl> +argv[4] = <mnop> +argv[5] = <qrst> +argv[6] = <uvwx> +argv[1] = <abcd> +argv[2] = <efgh> +argv[3] = <ijkl> +argv[4] = <mnop> +argv[5] = <qrst> +argv[6] = <uvwyyy> + +This +string +has +multiple +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 +1 +argv[1] = <6> +./new-exp.tests: line 277: ${#:}: bad substitution +argv[1] = <'> +argv[1] = <"> +argv[1] = <"hello"> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <abcdef> +argv[1] = <abc def> +argv[1] = <abcdef> +argv[1] = <abc> +argv[2] = <def> +argv[1] = <abcdef> +argv[1] = <abc def> +argv[1] = <abcdef> +argv[1] = <abc def> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <hijklmnopqrstuv> +argv[1] = <pqrstuv> +argv[1] = <uvwxyz> +argv[1] = <abcdefghijklmnopqrstuvwxyz> +argv[1] = <abcdefghijklmnopqrst> +argv[1] = <klmnopq> +argv[1] = <klmnopq> +argv[1] = <klmnopq> +argv[1] = <"2 3"> +argv[1] = <"2:3"> +argv[1] = <"34"> +argv[1] = <"3456"> +argv[1] = <"3456"> +argv[1] = <"3456"> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <one/two> +argv[1] = <one/two> +argv[1] = <two> +argv[1] = <oneonetwo> +argv[1] = <onetwo> +argv[1] = <two> +argv[1] = <oneonetwo> +./new-exp.tests: line 421: -2: substring expression < 0 +argv[1] = <defghi> +argv[1] = <efghi> +argv[1] = <e*docrine> +argv[1] = <e*docri*e> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = </usr/bin> +argv[2] = </bin> +argv[3] = </usr/local/bin> +argv[4] = </usr/gnu/bin> +argv[5] = </usr/bin/X11> +argv[6] = </sbin> +argv[7] = </usr/sbin> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +./new-exp.tests: line 480: $9: unbound variable +./new-exp.tests: line 481: 9: unbound variable +./new-exp.tests: line 482: UNSET: unbound variable +./new-exp.tests: line 483: UNSET: unbound variable +./new-exp.tests: line 484: UNSET: unbound variable +./new-exp.tests: line 485: UNSET: unbound variable +./new-exp.tests: line 486: UNSET: unbound variable +argv[1] = <5> +argv[1] = <#> +argv[1] = <#> +argv[1] = <> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +argv[1] = <_QUANTITY-_QUART-_QUEST-_QUILL-_QUOTA-_QUOTE> +./new-exp3.sub: line 19: ${!_Q* }: bad substitution +./new-exp3.sub: line 24: ${!1*}: bad substitution +./new-exp3.sub: line 26: ${!@*}: bad substitution +Case01---3---A:B:C--- +Case02---1---A B C::--- +Case03---3---A:B:C--- +Case04---3---A:B:C--- +Case05---3---A:B:C--- +Case06---1---A B C::--- +Case07---3---A:B:C--- +Case08---3---A:B:C--- +./new-exp.tests: line 506: ${$(($#-1))}: bad substitution +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[6] = <f> +argv[7] = <g> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <a> +argv[1] = <a> +argv[2] = <b> +argv[1] = <> +./new-exp.tests: line 525: $(($# - 2)): substring expression < 0 +argv[1] = <bin> +argv[2] = <bin> +argv[3] = <ucb> +argv[4] = <bin> +argv[5] = <.> +argv[6] = <sbin> +argv[7] = <sbin> +argv[1] = </> +argv[2] = </> +argv[3] = </> +argv[4] = </> +argv[5] = </> +argv[6] = </> +argv[1] = <bin> +argv[2] = <usr/bin> +argv[3] = <usr/ucb> +argv[4] = <usr/local/bin> +argv[5] = <.> +argv[6] = <sbin> +argv[7] = <usr/sbin> +argv[1] = </bin> +argv[2] = </usr/bin> +argv[3] = </usr/ucb> +argv[4] = </usr/local/bin> +argv[5] = <.> +argv[6] = </sbin> +argv[7] = </usr/sbin> +argv[1] = </full/path/to> +argv[1] = </> +argv[1] = <full/path/to/x16> +argv[1] = <x16> +two +one +ne +one + +one +one +one +1 2 3 4 5 6 7 8 9 +9 +9 +0 +9 +8 9 +123456789 +9 +9 +h +h +--blah +--blah +lah +lah +./new-exp.tests: line 558: ABXD: parameter unset diff --git a/tests/new-exp.tests b/tests/new-exp.tests new file mode 100644 index 0000000..e0c2702 --- /dev/null +++ b/tests/new-exp.tests @@ -0,0 +1,558 @@ +# must do this because posix mode causes process substitution to be disabled +# and flagged as a syntax error, which causes the shell to exit +set +o posix + +expect() +{ + echo expect "$@" +} + +HOME=/usr/homes/chet # to make the check against new-exp.right work +expect '<foo bar>' +recho "${undef-"foo bar"}" # should be foo bar +expect '<foo>' +recho "${und="foo"}" # should be foo + +expect "<$HOME>" +recho ${HOME-"}"} +expect "<$HOME>" +recho "${HOME-'}'}" +expect "<$HOME>" +recho "${HOME-"}"}" + +expect $0: 'HOME: }: syntax error: operand expected (error token is "}")' +recho "${HOME:`echo }`}" # should be a math error -- bad substring substitution + +expect unset +_ENV=oops +x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} +echo ${x:-unset} + +expect "<$HOME>" +recho ${HOME} +expect "<$HOME>" +recho ${HOME:-`echo }`} +expect "<$HOME>" +recho ${HOME:-`echo "}"`} +expect "<$HOME>" +recho "${HOME:-`echo "}"`}" +expect "<$HOME>" +recho "$(echo "${HOME}")" +expect "<$HOME>" +recho "$(echo "$(echo ${HOME})")" +expect "<$HOME>" +recho "$(echo "$(echo "${HOME}")")" + +P=*@* +expect '<*@>' +recho "${P%"*"}" # +expect '<*@>' +recho "${P%'*'}" # +expect '<@*>' +recho "${P#\*}" # should be @* + +expect '<)>' +recho "$(echo ")")" # should be ) +expect '<")">' +recho "$(echo "\")\"")" # should be ")" + +foo='abcd ' +expect '<-abcd> <->' +recho -${foo}- # should be -abcd - +expect '<-abcd> <->' +recho -${foo% *}- # should be -abcd - +expect '<-abcd->' +recho -${foo%% *}- # should be -abcd- + +foo=bar +expect '<bar foo>' +echo -n $foo' ' ; echo foo + +expect '<bar foo>' +echo -n $foo" " ; echo foo + +expect '<bar foo>' +echo -n "$foo " ; echo foo + +expect '<barfoo>' +echo -e "$foo\c " ; echo foo + +expect '<barfoo>' +echo -e $foo"\c " ; echo foo + +# make sure backslashes are preserved in front of characters that are not +# valid backslash escapes +expect '<\x>' +echo -e '\x' + +# substring tests +z=abcdefghijklmnop +expect '<abcd>' +recho ${z:0:4} + +expect '<efg> <nop>' +recho ${z:4:3} ${z:${#z}-3:3} + +expect '<efg> <nop>' +recho ${z:4:3} ${z: -3:3} + +expect '<hijklmnop>' +recho ${z:7:30} + +expect '<abcdefghijklmnop>' +recho ${z:0:100} + +expect '<abcdefghijklmnop>' +recho ${z:0:${#z}} + +set 'ab cd' 'ef' 'gh ij' 'kl mn' 'op' +expect '<ab cd> <ef>' +recho "${@:1:2}" + +expect '<gh ij> <kl mn>' +recho "${@:3:2}" + +expect '<gh ij> <kl mn> <op>' +recho "${@:3:4}" + +expect '<ab cd> <ef> <gh ij> <kl mn> <op>' +recho "${@:1:$#}" + +# code to ad-hoc parse arithmetic expressions in substring expansions was +# broken until post-2.04 +base=/home/chet/foo//bar +string1=$base/abcabcabc +x=1 j=4 + +expect '</home/chet/foo//bar/abcabcabc>' +recho ${string1:0} + +expect '<home/chet/foo//bar/abcabcabc>' +recho ${string1:1} + +expect '<home>' +recho ${string1:(j?1:0):j} + +expect '<home>' +recho ${string1:j?1:0:j} + +expect '<home>' +recho ${string1:(j?(x?1:0):0):j} + +expect '<home>' +recho ${string1:j?(x?1:0):0:j} + +unset base string1 x j + +# indirect variable references +expect '<abcdefghijklmnop>' +recho ${!9:-$z} + +ef=4 +expect '<4>' +recho ${!2} + +expect '<op>' +recho ${!#} + +set a b c d e +a= +expect '<abcdefghijklmnop>' +recho ${a:-$z} +expect '<abcdefghijklmnop>' +recho ${!1:-$z} + +expect nothing +recho ${a-$z} +expect nothing +recho ${!1-$z} + +set -u +expect $0: ABX: unbound variable +( recho ${ABX} ) +set +u + +expect $0: '$6: cannot assign in this way' +recho ${6="arg6"} + +v=abcde + +# sed-like variable substitution +expect '<xxcde>' +recho ${v/a[a-z]/xx} +expect '<axxde>' +recho ${v/a??/axx} +expect '<abxyz>' +recho ${v/c??/xyz} +expect '<abbcde>' +recho ${v/#a/ab} +expect '<abcde>' +recho ${v/#d/ab} +expect '<abcabe>' +recho ${v/d/ab} +expect '<abcdlast>' +recho ${v/%?/last} +expect '<abcde>' +recho ${v/%x/last} + +av=(abcd efgh ijkl mnop qrst uvwx) + +expect '<xxcd>' +recho ${av/??/xx} +expect '<abxx>' +recho ${av/%??/xx} +expect '<xxgh>' +recho ${av[1]/??/xx} +expect '<efgh>' +recho ${av[1]/%ab/xx} +expect '<xxfgh>' +recho ${av[1]/#?/xx} +expect '<zagh>' +recho ${av[1]/??/za} +expect '<zaza>' +recho ${av[1]//??/za} +expect '<zagh>' +recho ${av[1]//#??/za} +expect '<efza>' +recho ${av[1]//%??/za} + +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${av[@]/*/yyy} +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${av[@]/#*/yyy} +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${av[@]/%*/yyy} +expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>' +recho ${av[@]/a*/yyy} +expect '<abxx> <efxx> <ijxx> <mnxx> <qrxx> <uvxx>' +recho ${av[@]/%??/xx} + +set abcd efgh ijkl mnop qrst uvwx + +expect '<xxcd>' +recho ${1/??/xx} +expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>' +recho ${@/??/xx} +expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>' +recho ${@/%??/xx} +expect '<zaza>' +recho ${3//??/za} +expect '<efza>' +recho ${3//%??/za} +expect '<zaza> <zaza> <zaza> <zaza> <zaza> <zaza>' +recho ${@//??/za} +expect '<zacd> <zagh> <zakl> <zaop> <zast> <zawx>' +recho ${@//#??/za} +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${@//*/yyy} +expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>' +recho ${@//a*/yyy} +expect '<abcd> <efgh> <ijkl> <mnop> <qrst> <uvwyyy>' +recho ${@//%x*/yyy} + +expect a newline +echo $abmcde + +# sneaky way to replace a newline in a variable value with something else +AVAR=$'This\nstring\nhas\nmultiple\nlines.' +echo "${AVAR}" + +eval BVAR=\"\${AVAR//$'\n'/-}\" +echo "$BVAR" + +unset AVAR BVAR + +# run process substitution tests in a subshell so that syntax errors +# caused by a shell not implementing process substitution (e.g., one +# built on a NeXT) will not cause the whole test to exit prematurely +${THIS_SH} ./new-exp1.sub + +# run the tests of $(<filename) in a subshell to avoid cluttering up +# this script +${THIS_SH} ./new-exp2.sub + +expect '<6>' +recho ${#:-foo} +expect $0: '${#:}: bad substitution' +echo ${#:} + +expect "<'>" +recho "'" +expect '<">' +recho '"' +expect '<"hello">' +recho "\"hello\"" + +shift $# +unset foo +z=abcdef +z1='abc def' + +expect '<>' +recho ${foo:-""} +expect nothing +recho ${foo:-"$@"} +expect '<>' +recho "${foo:-$@}" + +# unset var +expect '<>' +recho ${foo:-"$zbcd"} +expect nothing +recho ${foo:-$zbcd} + +# set var +expect '<abcdef>' +recho ${foo:-"$z"} +expect '<abc def>' +recho ${foo:-"$z1"} + +expect '<abcdef>' +recho ${foo:-$z} +expect '<abc> <def>' +recho ${foo:-$z1} + +expect '<abcdef>' +recho "${foo:-$z}" +expect '<abc def>' +recho "${foo:-$z1}" + +expect '<abcdef>' +recho "${foo:-"$z"}" +# this disagrees with sh and ksh, but I think it is right according +# to posix.2. +expect '<abc def>' +recho "${foo:-"$z1"}" + +set ab cd ef gh +expect '<ab> <cd> <ef> <gh>' +recho ${foo:-"$@"} +expect '<ab> <cd> <ef> <gh>' +recho "${foo:-$@}" +expect '<ab> <cd> <ef> <gh>' +recho "${foo:-"$@"}" + +shift $# +expect nothing +recho $xxx"$@" +expect nothing +recho ${foo:-$xxx"$@"} +expect '<>' +recho "${foo:-$xxx$@}" +expect '<>' +recho "${foo:-$xxx"$@"}" + +expect nothing +recho $xxx"$@" +expect nothing +recho "$xxx$@" +expect nothing +recho "$@"$xxx + +expect '<>' +recho $xxx"" +expect '<>' +recho $xxx'' +expect '<>' +recho ''$xxx +expect '<>' +recho ""$xxx + +AB='abcdefghijklmnopqrstuvwxyz' + +recho ${AB:7:15} +recho ${AB:15:7} + +recho ${AB:20} + +recho ${AB:0} +recho ${AB:0:20} + +recho ${AB:10:7} +recho ${AB:10:3+4} +recho ${AB:20/2:3+4} + +set 1 2 3 4 5 6 +recho \""${*:2:2}"\" + +IFS=: +recho \""${*:2:2}"\" + +IFS=$' \t\n' + +z=123456 + +recho \""${z:2:2}"\" +recho \""${z:2}"\" +recho \""${z:2:4}"\" +recho \""${z:2:6}"\" + +set $'\1' $'\2' $'\177' + +recho $* +recho $@ + +recho ${*} +recho ${@} + +xx=one/two/two +recho ${xx%/*} +recho ${xx/\/two} + +yy=oneonetwo +recho ${yy//one} +recho ${yy/\/one} + +xx=oneonetwo + +recho ${xx/one} +recho ${xx//one} +recho ${xx/\/one} + +# out-of-range substrings +var=abc +c=${var:3} +expect nothing +recho $c +c=${var:4} +expect nothing +recho $c +expect '<./new-exp.tests: -2: substring expression < 0>' +c=${var:0:-2} + +var=abcdefghi +c=${var:3:12} +recho $c +c=${var:4:20} +recho $c + +# make sure null patterns work +xxx=endocrine +yyy=n +unset zzz + +recho ${xxx/$yyy/*} +recho ${xxx//$yyy/*} + +recho ${xxx/$zzz/*} +recho ${xxx//$zzz/*} + +recho ${xxx//%${zzz}/} +recho ${xxx//%${zzz}} +recho ${xxx//#${zzz}/} +recho ${xxx//#${zzz}} + +# another case that caused a core dump in bash-2.0 +XPATH=/usr/bin:/bin:/usr/local/bin:/usr/gnu/bin::/usr/bin/X11:/sbin:/usr/sbin + +recho ${XPATH//:/ } + +xx=(ar as at au av aw ax ay az) + +recho ${xx[@]/a/} +recho ${xx[@]//a/} + +recho ${xx[*]/a/} +recho ${xx[*]//a/} + +recho ${xx[@]%?} +recho ${xx[*]%?} + +recho ${xx[@]#?} +recho ${xx[*]#?} + +set -- ar as at au av aw ax ay az + +recho ${@/a/} +recho ${@//a/} + +recho ${*/a/} +recho ${*//a/} + +recho ${@%?} +recho ${*%?} + +recho ${@#?} +recho ${*#?} + +shift $# +set -u +( recho $9 ; echo after 1) +( recho ${9} ; echo after 2) +( recho $UNSET ; echo after 3) +( recho ${UNSET} ; echo after 4) +( recho "$UNSET" ; echo after 5) +( recho "${UNSET}" ; echo after 6) +( recho "${#UNSET}" ; echo after 7) +set +u + +RECEIVED="12345" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" +RECEIVED="12345#" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" +RECEIVED="#" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" +RECEIVED="" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" + +# tests of new prefix expansion ${!prefix*} +${THIS_SH} ./new-exp3.sub + +# bug with indirect expansion through bash-2.05b +${THIS_SH} ./new-exp4.sub + +# these caused errors and core dumps in versions before bash-2.04 +c="" +echo ${c//${$(($#-1))}/x/} + +set a b c d e f g +recho "$@" + +set -- ${@:1:$(($# - 2))} +recho "$@" + +set a b +recho ${@:1:$(($# - 2))} + +recho ${@:1:0} +recho ${@:1:1} +recho ${@:1:2} + +recho "${*:1:0}" + +# this is an error -- negative expression +set a +recho ${@:1:$(($# - 2))} + +XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin +set $( IFS=: ; echo $XPATH ) + +recho ${@##*/} +recho ${@%%[!/]*} + +recho ${@#/*} +recho ${@%*/} + +set /full/path/to/x16 /another/full/path + +recho ${1%/*} +recho ${1%%[!/]*} +recho ${1#*/} +recho ${1##*/} + +${THIS_SH} ./new-exp5.sub + +unset var +var=blah + +# these had better agree +echo ${var[@]:3} +echo ${var:3} +echo ${var[@]//#/--} +echo ${var//#/--} +echo ${var[@]##?} +echo ${var##?} + +# this must be last! +expect $0: 'ABXD: parameter unset' +recho ${ABXD:?"parameter unset"} diff --git a/tests/new-exp1.sub b/tests/new-exp1.sub new file mode 100644 index 0000000..c015c22 --- /dev/null +++ b/tests/new-exp1.sub @@ -0,0 +1,11 @@ +expect() +{ + echo 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 +expect this is test 2 +cat <(cat /tmp/x) +rm -f /tmp/x diff --git a/tests/new-exp2.sub b/tests/new-exp2.sub new file mode 100644 index 0000000..5e922aa --- /dev/null +++ b/tests/new-exp2.sub @@ -0,0 +1,36 @@ +export LC_ALL=C +export LANG=C + +# test out the new $(< filename) code +# it should be exactly equivalent to $(cat filename) + +FILENAME=/tmp/bashtmp.x$$ + +trap 'rm -f $FILENAME' 0 + +cat >$FILENAME << EOF +line 1 +line 2 +line 3 +EOF + +LINES1=$(cat $FILENAME) +LINES2=$(< $FILENAME) + +if [[ $LINES1 != $LINES2 ]]; then + echo 'whoops: $(< filename) failed' +fi + +LINES2=$(< /tmp/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*) +set +o posix + +# now see what happens when we try it with a non-existant file +LINES3=$(< /tmp/redir-notthere) +echo $? diff --git a/tests/new-exp3.sub b/tests/new-exp3.sub new file mode 100644 index 0000000..3107ef1 --- /dev/null +++ b/tests/new-exp3.sub @@ -0,0 +1,26 @@ +: +# Set up some dummy variables beginning with _Q +_QUANTITY= +_QUOTA= +_QUOTE= +_QUILL= +_QUEST= +_QUART= + +recho ${!_Q*} + +IFS="-$IFS" + +recho ${!_Q*} +recho "${!_Q*}" + +recho ${!_Y*} + +recho "${!_Q* }" + +IFS=$' \t\n' + +set a b c d e f g h i j k l m n o p +recho ${!1*} + +recho ${!@*} diff --git a/tests/new-exp4.sub b/tests/new-exp4.sub new file mode 100644 index 0000000..45439a0 --- /dev/null +++ b/tests/new-exp4.sub @@ -0,0 +1,31 @@ +#!/bin/bash + +arrayA=("A" "B" "C") + +arrayB=( ${arrayA[*]} ) +echo "Case01---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${arrayA[*]}" ) +echo "Case02---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( ${arrayA[@]} ) +echo "Case03---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${arrayA[@]}" ) +echo "Case04---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +xx="arrayA[*]" + +arrayB=( ${!xx} ) +echo "Case05---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${!xx}" ) +echo "Case06---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +xx="arrayA[@]" + +arrayB=( ${!xx} ) +echo "Case07---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${!xx}" ) +echo "Case08---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" diff --git a/tests/new-exp5.sub b/tests/new-exp5.sub new file mode 100644 index 0000000..9b3e1b3 --- /dev/null +++ b/tests/new-exp5.sub @@ -0,0 +1,30 @@ +x=(one two) +echo ${x[@]:1} +echo ${x[@]:0:1} + +x=(one) +echo ${x[0]:1} +echo ${x[0]:0} +echo ${x[@]:1} +echo ${x[@]:0} + +echo ${x[@]: -1} +echo ${x[@]: ${#x[@]}-1} + +x=(0 1 2 3 4 5 6 7 8 9) +echo ${x[@]:1} + +echo ${x[@]: -1} +echo ${x[@]: ${#x[@]}-1} + +set -- ${x[@]} + +echo $1 +echo ${@: -1} +echo ${@: $#-1} + +a=0123456789 + +echo ${a:1} +echo ${a: -1} +echo ${a: ${#a}-1} diff --git a/tests/nquote.right b/tests/nquote.right new file mode 100644 index 0000000..904467b --- /dev/null +++ b/tests/nquote.right @@ -0,0 +1,32 @@ +argv[1] = <^J^J^J> +argv[1] = <++^J++> +argv[1] = <> +argv[1] = <^J^I > +argv[1] = <abc> +argv[1] = <^M^[^Gabc> +argv[1] = <hello,> +argv[2] = <world> +argv[1] = <hello, world> +argv[1] = <> +argv[1] = <$hello, world> +argv[1] = <hello, $world> +argv[1] = <hello, "world"> +argv[1] = <hello, $"world"> +argv[1] = <hello, $"world"> +argv[1] = <$hello, chet> +argv[1] = <hello, chet> +ok +'abcd' +'abcd' +\'abcd\' +\'abcd\' +argv[1] = <A\CB> +argv[1] = <A\CB> +argv[1] = <ab$cde> +A\CB +A\CB +A\CB +argv[1] = <hello, $"world"> +argv[1] = <hello, \$"world"> +argv[1] = <hello, $"world"> +argv[1] = <hello, $world> diff --git a/tests/nquote.tests b/tests/nquote.tests new file mode 100644 index 0000000..b25fbe3 --- /dev/null +++ b/tests/nquote.tests @@ -0,0 +1,102 @@ +expect() +{ + echo expect "$@" +} + +expect '<^J^J^J>' +recho $'\n\n\n' + +expect '<++^J++>' +f=$'\n' +recho "++$f++" +unset f + +z1=$'' +expect '<>' +recho "$z1" + +ZIFS=$'\n'$'\t'$' ' + +expect '<^J^I >' +recho "$ZIFS" + +expect '<abc>' +recho $'abc' + +expect '<^M^[^Gabc>' +recho $'\r\e\aabc' + +D=$"hello"," "$"world" + +expect '<hello,> <world>' +recho $D + +expect '<hello, world>' +recho "$D" + +D=$"" +expect '<>' +recho "$D" + +world=chet + +expect '<$hello, world>' +recho \$"hello, world" + +expect '<hello, $world>' +recho $"hello, \$world" + +expect '<hello, "world">' +recho $"hello, \"world\"" + +expect '<hello, $"world">' +recho $"hello"', $"world"' + +expect '<hello, $"world">' +recho $'hello, $"world"' + +expect '<$hello, chet>' +recho \$"hello, $world" + +expect '<hello, chet>' +recho $"hello, $world" + +z=$'\v\f\a\b' +case "$z" in +$'\v\f\a\b') echo ok;; +*) echo bad;; +esac + +# Dave Korn says this should be allowed and echo 'abcd' +echo $'\'abcd\'' + +# printf translates \' to ' ... +printf "\'abcd\'\n" + +# but echo -e doesn't +echo -e "\'abcd\'" +echo -e "\\'abcd\\'" + +# and what do we do about unrecognized escape sequences? + +shopt -s xpg_echo + +recho $'A\CB' + +recho "A\CB" + +cde=c +recho $'ab$cde' + +printf "%b\n" 'A\CB' +printf 'A\CB\n' + +echo 'A\CB' + +world=chet + +recho $'hello, $"world"' +recho $'hello, \$"world"' +recho $'hello, $\"world"' + +recho "hello, $"world"" diff --git a/tests/nquote1.right b/tests/nquote1.right new file mode 100644 index 0000000..26e16b9 --- /dev/null +++ b/tests/nquote1.right @@ -0,0 +1,121 @@ +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <e1> +argv[2] = <v^A^A> +argv[1] = <e2> +argv[2] = <v^A^A> +argv[1] = <e3> +argv[2] = <v^A^A> +argv[1] = <e4> +argv[2] = <v^A^A> +argv[1] = <a1> +argv[2] = <uv^A^A> +argv[1] = <a2> +argv[2] = <uv^A^A> +argv[1] = <a3> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <a4> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p1> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p2> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p1> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p2> +argv[2] = <uv^A^Awx uv^A^Awx> +argv[1] = <uv^A^Awx> +argv[1] = <uv^A^Awx> +argv[1] = <uv^A^Awx> +^A +^A +^B +argv[1] = <f1> +argv[2] = <v^Aw> +argv[1] = <f2> +argv[2] = <v^Aw> +argv[1] = <a1> +argv[2] = <uv^Aw> +argv[1] = <a2> +argv[2] = <uv^Aw> +argv[1] = <a3> +argv[2] = <uv^Aw> +argv[1] = <a4> +argv[2] = <uv^Aw> +argv[1] = <e1> +argv[2] = <uv^Aw> +argv[1] = <e2> +argv[2] = <uv^Aw> +argv[1] = <d1> +argv[2] = <^Aw> +argv[1] = <d2> +argv[2] = <^Aw> +argv[1] = <@1> +argv[2] = <uv^Aw^Axy> +argv[3] = <uv^Aw^Axy> +argv[1] = <@2> +argv[2] = <uv^Aw^Axy> +argv[3] = <uv^Aw^Axy> diff --git a/tests/nquote1.tests b/tests/nquote1.tests new file mode 100644 index 0000000..0970e77 --- /dev/null +++ b/tests/nquote1.tests @@ -0,0 +1,97 @@ +a=$'a\001b' + +set $a + +b=$a +c=$1 +d="$1" + +e=$'uv\001\001wx' + +recho a $a ${#a} +recho 1 $1 ${#1} +recho b $b ${#b} +recho c $c ${#c} +recho d $d ${#d} + +recho a ${a} ${#a} +recho 1 ${1} ${#1} +recho b ${b} ${#b} +recho c ${c} ${#c} +recho d ${d} ${#d} + +recho a "$a" ${#a} +recho 1 "$1" ${#1} +recho b "$b" ${#b} +recho c "$c" ${#c} +recho d "$d" ${#d} + +recho a "${a}" ${#a} +recho 1 "${1}" ${#1} +recho b "${b}" ${#b} +recho c "${c}" ${#c} +recho d "${d}" ${#d} + +set $e + +recho e1 ${e:1:3} +recho e2 "${e:1:3}" +recho e3 ${1:1:3} +recho e4 "${1:1:3}" + +arr[0]=$e +arr[1]=$e + +recho a1 ${arr:0:4} +recho a2 "${arr:0:4}" + +recho a3 ${arr[@]:0:2} +recho a4 "${arr[@]:0:2}" + +set $e $e + +recho p1 ${@:1:2} +recho p2 "${@:1:2}" + +recho p1 ${*:1:2} +recho p2 "${*:1:2}" + +recho $e + +recho 'uvwx' + +f='uvwx' + +recho $f + +echo -en "\01" | cat -v +echo + +huhu() { echo "$1"; }; + +huhu $(echo -en "\01") | cat -v +huhu $(echo -en "\02") | cat -v + +f=$'uv\001w\001xy' + +set $f $f + +recho f1 ${f:1:3} +recho f2 "${f:1:3}" + +arr[0]=$f +arr[1]=$f + +recho a1 ${arr:0:4} +recho a2 "${arr:0:4}" +recho a3 ${arr[0]:0:4} +recho a4 "${arr[0]:0:4}" + +recho e1 ${f:0:4} +recho e2 "${f:0:4}" + +recho d1 ${1:2:2} +recho d2 "${1:2:2}" + +recho @1 ${@:1:2} +recho @2 "${@:1:2}" diff --git a/tests/nquote2.right b/tests/nquote2.right new file mode 100644 index 0000000..e7fb21e --- /dev/null +++ b/tests/nquote2.right @@ -0,0 +1,76 @@ +argv[1] = <a^Ab> +argv[1] = <uv^A^Awx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvA^Awx> +argv[1] = <uvA^Awx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvAAwx> +argv[1] = <uvAAwx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <uvA^Awx> +argv[2] = <uvA^Awx> +argv[1] = <uvA^Awx> +argv[2] = <uvA^Awx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <uvAAwx> +argv[2] = <uvAAwx> +argv[1] = <uvAAwx> +argv[2] = <uvAAwx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <a^Ab> +argv[1] = <uv^A^Awx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvA^Awx> +argv[1] = <uvA^Awx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvAAwx> +argv[1] = <uvAAwx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <aAb> +argv[2] = <uvA^Awx> +argv[1] = <aAb> +argv[2] = <uvA^Awx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> +argv[1] = <aAb> +argv[2] = <uvAAwx> +argv[1] = <aAb> +argv[2] = <uvAAwx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> diff --git a/tests/nquote2.tests b/tests/nquote2.tests new file mode 100644 index 0000000..c07bd9b --- /dev/null +++ b/tests/nquote2.tests @@ -0,0 +1,82 @@ +a=$'a\001b' + +e=$'uv\001\001wx' + +recho $a +recho $e + +recho ${a/$'\001'/A} +recho "${a/$'\001'/A}" +recho ${e/$'\001'/A} +recho "${e/$'\001'/A}" + +recho ${a/b/B} +recho "${a/b/B}" +recho ${e/w/W} +recho "${e/w/W}" + +recho ${a//$'\001'/A} +recho "${a//$'\001'/A}" +recho ${e//$'\001'/A} +recho "${e//$'\001'/A}" + +recho ${a//b/B} +recho "${a//b/B}" +recho ${e//w/W} +recho "${e//w/W}" + +# pos params pat subst + +set $e $e + +recho ${@/$'\001'/A} +recho "${@/$'\001'/A}" +recho ${@/w/W} +recho "${@/w/W}" + +recho ${@//$'\001'/A} +recho "${@//$'\001'/A}" +recho ${@//w/W} +recho "${@//w/W}" + +arr[0]=$a +arr[1]=$e + +recho ${arr[0]} +recho ${arr[1]} + +recho ${arr[0]/$'\001'/A} +recho "${arr[0]/$'\001'/A}" +recho ${arr[1]/$'\001'/A} +recho "${arr[1]/$'\001'/A}" + +recho ${arr[0]/b/B} +recho "${arr[0]/b/B}" +recho ${arr[1]/w/W} +recho "${arr[1]/w/W}" + +recho ${arr[0]//$'\001'/A} +recho "${arr[0]//$'\001'/A}" +recho ${arr[1]//$'\001'/A} +recho "${arr[1]//$'\001'/A}" + +recho ${arr[0]//b/B} +recho "${arr[0]//b/B}" +recho ${arr[1]//w/W} +recho "${arr[1]//w/W}" + +recho ${arr[@]/$'\001'/A} +recho "${arr[@]/$'\001'/A}" + +recho ${arr[@]/b/B} +recho "${arr[@]/b/B}" +recho ${arr[@]/w/W} +recho "${arr[@]/w/W}" + +recho ${arr[@]//$'\001'/A} +recho "${arr[@]//$'\001'/A}" + +recho ${arr[@]//b/B} +recho "${arr[@]//b/B}" +recho ${arr[@]//w/W} +recho "${arr[@]//w/W}" diff --git a/tests/nquote3.right b/tests/nquote3.right new file mode 100644 index 0000000..d01eecc --- /dev/null +++ b/tests/nquote3.right @@ -0,0 +1,60 @@ +argv[1] = <uv^A^A> +argv[1] = <uv^A^A> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Ab> +argv[1] = <^Ab> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <wx> +argv[2] = <xy> +argv[1] = <uv^A^Awx> +argv[2] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <wx> +argv[2] = <xy> +argv[1] = <uv^A^Awx> +argv[2] = <uv^Aw^Axy> diff --git a/tests/nquote3.tests b/tests/nquote3.tests new file mode 100644 index 0000000..a83ff56 --- /dev/null +++ b/tests/nquote3.tests @@ -0,0 +1,85 @@ +a=$'a\001b' + +set $a + +b=$a +c=$1 +d="$1" + +e=$'uv\001\001wx' +f=$'uv\001w\001xy' + +set $e $e + +recho ${e%%??} +recho "${e%%??}" + +recho ${e%%???} +recho "${e%%???}" + +recho ${a#?} +recho "${a#?}" + +# simple variables + +recho ${f##*$'\001'} +recho "${f##*$'\001'}" +recho ${f##*''} # literal ^A +recho "${f##*'^A'}" # two characters, `^' and `A' + +recho ${e%$'\001'*} +recho "${e%$'\001'*}" +recho ${e#*$'\001'} +recho "${e#*$'\001'}" + +# array members + +arr[0]=$e +arr[1]=$f + +recho ${arr[1]##*$'\001'} +recho "${arr[1]##*$'\001'}" +recho ${arr[1]##*''} # literal ^A +recho "${arr[1]##*'^A'}" # two characters, `^' and `A' + +recho ${arr[0]%$'\001'*} +recho "${arr[0]%$'\001'*}" +recho ${arr[0]#*$'\001'} +recho "${arr[0]#*$'\001'}" + +recho ${arr%$'\001'*} +recho "${arr%$'\001'*}" +recho ${arr#*$'\001'} +recho "${arr#*$'\001'}" + +# positional parameters + +set $e $f + +recho ${2##*$'\001'} +recho "${2##*$'\001'}" +recho ${2##*''} # literal ^A +recho "${2##*''}" # literal ^A +recho ${2##*'^A'} # two characters, `^' and `A' +recho "${2##*'^A'}" # two characters, `^' and `A' + +recho ${1%$'\001'*} +recho "${1%$'\001'*}" +recho ${1#*$'\001'} +recho "${1#*$'\001'}" + +recho ${@%$'\001'*} +recho "${@%$'\001'*}" +recho ${@#*$'\001'} +recho "${@#*$'\001'}" +recho ${@##*''} # literal ^A +recho "${@##*'^A'}" # two characters, `^' and `A' + +# arrays treated as a whole + +recho ${arr[@]%$'\001'*} +recho "${arr[@]%$'\001'*}" +recho ${arr[@]#*$'\001'} +recho "${arr[@]#*$'\001'}" +recho ${arr[@]##*''} # literal ^A +recho "${arr[@]##*'^A'}" # two characters, `^' and `A' diff --git a/tests/nquote4.right b/tests/nquote4.right new file mode 100644 index 0000000..1f7ae17 --- /dev/null +++ b/tests/nquote4.right @@ -0,0 +1,18 @@ +argv[1] = <ab> +argv[1] = <abAcd> +argv[1] = <abAcd> +argv[1] = <ab^Dcd> +argv[1] = <abLd> +argv[1] = <abÞ> +argv[1] = <abÞ> +argv[1] = <abÍe> +argv[1] = <ab^Lde> +argv[1] = <¼X> +argv[1] = <«cX> +argv[1] = <> +argv[1] = <> +argv[1] = <gX> +argv[1] = <Ab> +argv[1] = <> +argv[1] = <^Abcd> +argv[1] = <Þ> diff --git a/tests/nquote4.tests b/tests/nquote4.tests new file mode 100644 index 0000000..ed73467 --- /dev/null +++ b/tests/nquote4.tests @@ -0,0 +1,24 @@ +recho $'ab\x{}cd' +recho $'ab\x{41}cd' +recho $'ab\x41cd' + +recho $'ab\x{4}cd' +recho $'ab\x4cd' + +recho $'ab\x{cde' + +recho $'ab\x{cde' +recho $'ab\x{cd}e' +recho $'ab\x{c}de' + +recho $'\x{abcX' +recho $'\x{ab}cX' +recho $'\x{}X' +recho $'\x{X' +recho $'\x{01234567X' + +recho $'\x{41}b' +recho $'\x{}bc' +recho $'\x{1}bcd' + +recho $'\x{bde' diff --git a/tests/posix2.right b/tests/posix2.right new file mode 100644 index 0000000..df30c4f --- /dev/null +++ b/tests/posix2.right @@ -0,0 +1,2 @@ +Testing for POSIX.2 conformance +All tests passed diff --git a/tests/posix2.tests b/tests/posix2.tests new file mode 100644 index 0000000..a186e78 --- /dev/null +++ b/tests/posix2.tests @@ -0,0 +1,179 @@ +#! /bin/sh +# posix-2.sh - Simple identification tests for POSIX.2 features +# commonly missing or incorrectly implemented. +# Time-stamp: <96/04/10 16:43:48 gildea> +# By Stephen Gildea <gildea@x.org> March 1995 +# +# Copyright (c) 1995 Stephen Gildea +# Permission is hereby granted to deal in this Software without restriction. +# THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. +# +# MODIFIED BY chet@po.cwru.edu to make part of the bash test suite. +# last change: Wed Jun 19 12:24:24 EDT 1996 +# +# some of the tests: +# +# shell functions (do we care?) +# var=${var:-val} +# unset +# set -- +# IFS parsing +## not exiting with -e and failed "if", the way Ultrix does (Ultrix 4.2?) +# "$@" expands to zero arguments if passed zero arguments +# $SHELL -c 'echo $1' bad good +# test -x +# positional parameters greater than 9 +# arithmetic expansion $(( ... )) +# getopts + +# For some tests we must run a sub-shell; $TESTSHELL says what to use. +# If set, TESTSHELL must be an absolute pathname. +# For example, on HP-UX 9, /bin/posix/sh is the supposedly-compliant shell. +TESTSHELL=${THIS_SH:-$PWD/../bash} + +# these tests create temp files with names $TMPDIR/conf* +: ${TMPDIR:=/tmp} + +exitval=0 +numtests=0 + +echo "Testing for POSIX.2 conformance" + +newtest() +{ + numtests=$(($numtests + 1)) +} + +testfail() +{ + echo "$1 test failed" + exitval=$(($exitval + 1)) +} + +newtest +empty="" +test "${empty:-ok}" = ok || testfail "empty var colon" +newtest +test "${empty-bad}" = "" || testfail "got \"${empty-bad}\": empty var nocolon" +newtest +test "${unsetvar-ok}" = ok || testfail "unset var" +newtest +unset empty +test "${empty-ok}" = ok || testfail "unset" + +newtest +set -- -Z +test "x$1" = x-Z || testfail '\"set -- arg\"' +# this should empty the argument list +newtest +set -- +test $# = 0 || testfail "still $# args: \"set --\"" + +# IFS parsing: +newtest +names=one/good/three +saved_ifs="$IFS" +IFS=/ +set $names lose +test "$2" = good || testfail "got \"$2\": IFS parsing" +IFS="$saved_ifs" + +# "$@" with 0 arguments should expand to 0 arguments +newtest +cat > $TMPDIR/conftest1 << EOF +$TMPDIR/conftest2 "\$@" +EOF +cat > $TMPDIR/conftest2 << "EOF" +#! /bin/sh +echo $# +EOF +chmod +x $TMPDIR/conftest1 $TMPDIR/conftest2 +numargs=$($TESTSHELL $TMPDIR/conftest1) +if [ "$?" != 0 ]; then + testfail 'running $@' +else + test "$numargs" = 0 || testfail '"$@" got '"$numargs args: expansion w 0 args" +fi +rm -f $TMPDIR/conftest1 $TMPDIR/conftest2 + +newtest +val=$("$TESTSHELL" -c 'echo $1' csh good) +test "$val" = good || testfail "got \"$val\": sh -c" + +newtest +# do these tests in a sub-shell because failure will exit +val=$("$TESTSHELL" -c 'echo ${10}' 0 1 2 3 4 5 6 7 8 9 ten 11 2> /dev/null) +test "$val" = ten || testfail "accessing more than 9 positional params" + +a=abc_def_ghi +export a +newtest; val=`"$TESTSHELL" -c 'echo "${a%_*}"' 2> /dev/null` +test "$val" = abc_def || testfail "parameter % op" +newtest; val=`"$TESTSHELL" -c 'echo "${a%%_*}"' 2> /dev/null` +test "$val" = abc || testfail "parameter %% op" +newtest; val=`"$TESTSHELL" -c 'echo "${a#*_}"' 2> /dev/null` +test "$val" = def_ghi || testfail "parameter # op" +newtest; val=`"$TESTSHELL" -c 'echo "${a##*_}"' 2> /dev/null` +test "$val" = ghi || testfail "parameter ## op" + +newtest +"$TESTSHELL" -c 'export a=value' 2> /dev/null || testfail "export with value" + +newtest +a=5; test "$(( ($a+1)/2 ))" = 3 || testfail "arithmetic expansion" + +# does "test" support the -x switch? +newtest +touch $TMPDIR/conftest +chmod -x $TMPDIR/conftest +test -x $TMPDIR/conftest && testfail "negative test -x" +chmod +x $TMPDIR/conftest +test -x $TMPDIR/conftest || testfail "positive test -x" +rm -f $TMPDIR/conftest + +newtest +test "$OPTIND" = 1 || testfail "OPTIND initial value" + +newtest +getopts a: store -a aoptval +if [ "$OPTIND" != 3 ] || [ "$store" != a ] || [ "$OPTARG" != aoptval ]; then + testfail "getopts" +fi + +# if I change the default quoting style for variable values, these +# next four must change + +newtest +SQUOTE="'" +val1=$(set | sed -n 's:^SQUOTE=::p') +if [ "$val1" != "''\\'''" ]; then + testfail "variable quoting 1" +fi + +newtest +VTILDE='~' +val1=$(set | sed -n 's:^VTILDE=::p') +if [ "$val1" != "'~'" ]; then + testfail "variable quoting 2" +fi + +newtest +VHASH=ab#cd +val1=$(set | sed -n 's:^VHASH=::p') +if [ "$val1" != "ab#cd" ]; then + testfail "variable quoting 3" +fi + +newtest +VHASH2=#abcd +val1=$(set | sed -n 's:^VHASH2=::p') +if [ "$val1" != "'#abcd'" ]; then + testfail "variable quoting 4" +fi + +if [ $exitval = 0 ]; then + echo "All tests passed" +else + echo "$exitval of $numtests tests failed" +fi +exit $exitval diff --git a/tests/posixpat.right b/tests/posixpat.right new file mode 100644 index 0000000..deb01bf --- /dev/null +++ b/tests/posixpat.right @@ -0,0 +1,42 @@ +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok 15 +ok 16 +ok 17 +ok 18 +ok 19 +ok 20 +ok 21 +ok -- space +ok -- blank +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok 15 +ok 16 +ok 1 +ok 2 +ok 3 diff --git a/tests/posixpat.tests b/tests/posixpat.tests new file mode 100644 index 0000000..91fac3b --- /dev/null +++ b/tests/posixpat.tests @@ -0,0 +1,233 @@ +# A test suite for the POSIX.2 (BRE) pattern matching code +LC_ALL=C +LANG=C + +# First, test POSIX.2 character classes + +case e in +[[:xdigit:]]) echo ok 1;; +esac + +case a in +[[:alpha:]123]) echo ok 2;; +esac + +case 1 in +[[:alpha:]123]) echo ok 3;; +esac + +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 + +case a in +[[:al:]) echo ok 6;; +esac + +case '!' in +[abc[:punct:][0-9]) echo ok 7;; +esac + +# let's try to match the start of a valid sh identifier +case 'PATH' in +[_[:alpha:]]*) echo ok 8;; +esac + +# let's try to match the first two characters of a valid sh identifier +case PATH in +[_[:alpha:]][_[:alnum:]]*) echo ok 9;; +esac + +# is ^C a cntrl character? +case $'\003' in +[[:cntrl:]]) echo ok 10;; +esac + +# how about A? +case A in +[[:cntrl:]]) echo oops -- cntrl ;; +*) echo ok 11;; +esac + +case 9 in +[[:digit:]]) echo ok 12;; +esac + +case X in +[[:digit:]]) echo oops -- digit;; +*) echo ok 13;; +esac + +case $'\033' in +[[:graph:]]) echo oops -- graph;; +*) echo ok 14;; +esac + +case $'\040' in +[[:graph:]]) echo oops -- graph 2;; +*) echo ok 15;; +esac + +case ' ' in +[[:graph:]]) echo oops -- graph 3;; +*) echo ok 16;; +esac + +case 'aB' in +[[:lower:]][[:upper:]]) echo ok 17;; +esac + +case $'\040' in +[[:print:]]) echo ok 18;; +*) echo oops -- print;; +esac + +case PS3 in +[_[:alpha:]][_[:alnum:]][_[:alnum:]]*) echo ok 19;; +esac + +case a in +[[:alpha:][:digit:]]) echo ok 20;; +*) echo oops - skip brackpat ;; +esac + +case a in +[[:alpha:]\]) echo oops -- dangling backslash in brackpat ;; +*) echo ok 21 ;; +esac + +# what's a newline? is it a blank? a space? +case $'\n' in +[[:blank:]]) echo ok -- blank ;; +[[:space:]]) echo ok -- space ;; +*) echo oops newline ;; +esac + +# OK, what's a tab? is it a blank? a space? +case $'\t' in +[[:blank:]]) echo ok -- blank ;; +[[:space:]]) echo ok -- space ;; +*) echo oops newline ;; +esac + +# let's check out characters in the ASCII range +case $'\377' in +[[:ascii:]]) echo oops -- ascii\?;; +esac + +case 9 in +[1[:alpha:]123]) echo oops 1;; +esac + +# however, an unterminated brace expression containing a valid char class +# that matches had better fail +case a in +[[:alpha:]) echo oops 2;; +esac + +case $'\b' in +[[:graph:]]) echo oops 3;; +esac + +case $'\b' in +[[:print:]]) echo oops 4;; +esac + +case $' ' in +[[:punct:]]) echo oops 5;; +esac + +# Next, test POSIX.2 collating symbols + +case 'a' in +[[.a.]]) echo ok 1;; +esac + +case '-' in +[[.hyphen.]-9]) echo ok 2;; +esac + +case 'p' in +[[.a.]-[.z.]]) echo ok 3;; +esac + +case '-' in +[[.-.]]) echo ok 4;; +esac + +case ' ' in +[[.space.]]) echo ok 5;; +esac + +case ' ' in +[[.grave-accent.]]) echo oops - grave;; +*) echo ok 6;; +esac + +case '4' in +[[.-.]-9]) echo ok 7;; +esac + +# an invalid collating symbol cannot be the first part of a range +case 'c' in +[[.yyz.]-[.z.]]) echo oops - yyz;; +*) echo ok 8;; +esac + +case 'c' in +[[.yyz.][.a.]-z]) echo ok 9;; +esac + +# but when not part of a range is not an error +case 'c' in +[[.yyz.][.a.]-[.z.]]) echo ok 10 ;; +esac + +case 'p' in +[[.a.]-[.Z.]]) echo oops -- bad range ;; +*) echo ok 11;; +esac + +case p in +[[.a.]-[.zz.]p]) echo ok 12;; +*) echo oops -- bad range 2;; +esac + +case p in +[[.aa.]-[.z.]p]) echo ok 13;; +*) echo oops -- bad range 3;; +esac + +case c in +[[.yyz.]cde]) echo ok 14;; +esac + +case abc in +[[.cb.]a-Za]*) echo ok 15;; +esac + +case $'\t' in +[[.space.][.tab.][.newline.]]) echo ok 16;; +esac + +# and finally, test POSIX.2 equivalence classes + +case "abc" in +[[:alpha:]][[=b=]][[:ascii:]]) echo ok 1;; +esac + +case "abc" in +[[:alpha:]][[=B=]][[:ascii:]]) echo oops -- =B=;; +*) echo ok 2 ;; +esac + +case a in +[[=b=]) echo oops;; # an incomplete equiv class is just a string +*) echo ok 3;; +esac + diff --git a/tests/prec.right b/tests/prec.right new file mode 100644 index 0000000..e6af552 --- /dev/null +++ b/tests/prec.right @@ -0,0 +1,28 @@ +`Say' echos its argument. Its return value is of no interest. +`Truth' echos its argument and returns a TRUE result. +`False' echos its argument and returns a FALSE result. + + Truth 1 && Truth 2 || Say 3 output=12 +( Truth 1 && Truth 2 ) || Say 3 output=12 + + Truth 1 && False 2 || Say 3 output=123 +( Truth 1 && False 2 ) || Say 3 output=123 + + False 1 && Truth 2 || Say 3 output=13 +( False 1 && Truth 2 ) || Say 3 output=13 + + False 1 && False 2 || Say 3 output=13 +( False 1 && False 2 ) || Say 3 output=13 + +Truth 1 || Truth 2 && Say 3 output=13 +Truth 1 || ( Truth 2 && Say 3 ) output=1 + +Truth 1 || False 2 && Say 3 output=13 +Truth 1 || ( False 2 && Say 3 ) output=1 + +False 1 || Truth 2 && Say 3 output=123 +False 1 || ( Truth 2 && Say 3 ) output=123 + +False 1 || False 2 && Say 3 output=12 +False 1 || ( False 2 && Say 3 ) output=12 + diff --git a/tests/precedence b/tests/precedence new file mode 100755 index 0000000..9bbdb97 --- /dev/null +++ b/tests/precedence @@ -0,0 +1,75 @@ +# @(#)precedence_test 1.0 91/07/24 Maarten Litmaath +# test of relative precedences for `&&' and `||' operators + +echo "\`Say' echos its argument. Its return value is of no interest." +case `echo -n` in + '') Say () { echo -n "$*" ; } ;; + *) Say () { echo "$*\c" ; } ;; +esac + +echo "\`Truth' echos its argument and returns a TRUE result." +Truth () { + Say $1; + return 0; +} + +echo "\`False' echos its argument and returns a FALSE result." +False () { + Say $1; + return 1; +} + +echo "" + +cmd1='$open $test1 && $test2 $close || $test3' +cmd2='$test1 || $open $test2 && $test3 $close' + +grouping_sh= +grouping_C='( )' + +test3='Say 3' + +for i in 1 2 +do + eval proto=\$cmd$i + + for test1 in 'Truth 1' 'False 1' + do + for test2 in 'Truth 2' 'False 2' + do + for precedence in sh C + do + eval set x \$grouping_$precedence + shift + open=${1-' '} + close=${2-' '} + eval cmd=\""$proto"\" + Say "$cmd output=" + output=`eval "$cmd"` + Say "$output" + read correct || { echo 'Input fubar. Abort.' >&2; exit 1; } + test "X$output" = "X$correct" || echo " correct=$correct" + echo '' + done + + echo '' + done + done +done << EOF +12 +12 +123 +123 +13 +13 +13 +13 +13 +1 +13 +1 +123 +123 +12 +12 +EOF diff --git a/tests/printf.right b/tests/printf.right Binary files differnew file mode 100644 index 0000000..656b198 --- /dev/null +++ b/tests/printf.right diff --git a/tests/printf.tests b/tests/printf.tests new file mode 100644 index 0000000..9cd7302 --- /dev/null +++ b/tests/printf.tests @@ -0,0 +1,248 @@ +LC_ALL=C +LC_NUMERIC=C + +# these should output error messages -- the format is required +printf +printf -- + +# these should output nothing +printf "" +printf -- "" + +# in the future this may mean to put the output into VAR, but for +# now it is an error +# 2005-03-15 no longer an error +unset var +printf -v var "%10d" $RANDOM +echo ${#var} + +# this should expand escape sequences in the format string, nothing else +printf "\tone\n" + +# this should not cut off output after the \c +printf "one\ctwo\n" + +# and unrecognized backslash escapes should have the backslash preserverd +printf "4\.2\n" + +printf "no newline " ; printf "now newline\n" + +# %% -> % +printf "%%\n" + +# this was a bug caused by pre-processing the string for backslash escapes +# before doing the `%' format processing -- all versions before bash-2.04 +printf "\045" ; echo +printf "\045d\n" + +# simple character output +printf "%c\n" ABCD + +# test simple string output +printf "%s\n" unquoted + +# test quoted string output +printf "%s %q\n" unquoted quoted +printf "%s%10q\n" unquoted quoted + +printf "%q\n" 'this&that' + +# make sure the format string is reused to use up arguments +printf "%d " 1 2 3 4 5; printf "\n" + +# make sure that extra format characters get null arguments +printf "%s %d %d %d\n" onestring + +printf "%s %d %u %4.2f\n" onestring + +printf -- "--%s %s--\n" 4.2 '' +printf -- "--%s %s--\n" 4.2 + +# test %b escapes + +# 8 is a non-octal digit, so the `81' should be output +printf -- "--%b--\n" '\n\081' + +printf -- "--%b--\n" '\t\0101' +printf -- "--%b--\n" '\t\101' + +# these should all display `A7' +echo -e "\1017" +echo -e "\x417" + +printf "%b\n" '\01017' +printf "%b\n" '\1017' +printf "%b\n" '\x417' + +printf -- "--%b--\n" '\"abcd\"' +printf -- "--%b--\n" "\'abcd\'" + +printf -- "--%b--\n" 'a\\x' + +printf -- "--%b--\n" '\x' + +Z1=$(printf -- "%b\n" '\a\b\e\f\r\v') +Z2=$'\a\b\e\f\r\v' + +if [ "$Z1" != "$Z2" ]; then + echo "whoops: printf %b and $'' differ" >&2 +fi +unset Z1 Z2 + +printf -- "--%b--\n" '' +printf -- "--%b--\n" + +# the stuff following the \c should be ignored, as well as the rest +# of the format string +printf -- "--%b--\n" '4.2\c5.4\n'; printf "\n" + +# unrecognized escape sequences should by displayed unchanged +printf -- "--%b--\n" '4\.2' + +# a bare \ should not be processed as an escape sequence +printf -- "--%b--\n" '\' + +# make sure extra arguments are ignored if the format string doesn't +# actually use them +printf "\n" 4.4 BSD +printf " " 4.4 BSD ; printf "\n" + +# make sure that a fieldwidth and precision of `*' are handled right +printf "%10.8s\n" 4.4BSD +printf "%*.*s\n" 10 8 4.4BSD + +printf "%10.8q\n" 4.4BSD +printf "%*.*q\n" 10 8 4.4BSD + +printf "%6b\n" 4.4BSD +printf "%*b\n" 6 4.4BSD + +# we handle this crap with homemade code in printf.def +printf "%10b\n" 4.4BSD +printf -- "--%-10b--\n" 4.4BSD +printf "%4.2b\n" 4.4BSD +printf "%.3b\n" 4.4BSD +printf -- "--%-8b--\n" 4.4BSD + +# test numeric conversions -- these four lines should echo identically +printf "%d %u %i 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 +printf "%d %u %i %#o %#x %#X\n" 255 255 255 255 255 255 + +printf "%ld %lu %li 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 +printf "%ld %lu %li %#o %#x %#X\n" 255 255 255 255 255 255 + +printf "%10d\n" 42 +printf "%10d\n" -42 + +printf "%*d\n" 10 42 +printf "%*d\n" 10 -42 + +# test some simple floating point formats +printf "%4.2f\n" 4.2 +printf "%#4.2f\n" 4.2 +printf "%#4.1f\n" 4.2 + +printf "%*.*f\n" 4 2 4.2 +printf "%#*.*f\n" 4 2 4.2 +printf "%#*.*f\n" 4 1 4.2 + +printf "%E\n" 4.2 +printf "%e\n" 4.2 +printf "%6.1E\n" 4.2 +printf "%6.1e\n" 4.2 + +printf "%G\n" 4.2 +printf "%g\n" 4.2 +printf "%6.2G\n" 4.2 +printf "%6.2g\n" 4.2 + +# test some of the more esoteric features of POSIX.1 printf +printf "%d\n" "'string'" +printf "%d\n" '"string"' + +printf "%#o\n" "'string'" +printf "%#o\n" '"string"' + +printf "%#x\n" "'string'" +printf "%#X\n" '"string"' + +printf "%6.2f\n" "'string'" +printf "%6.2f\n" '"string"' + +# output from these two lines had better be the same +printf -- "--%6.4s--\n" abcdefghijklmnopqrstuvwxyz +printf -- "--%6.4b--\n" abcdefghijklmnopqrstuvwxyz + +# and these two also +printf -- "--%12.10s--\n" abcdefghijklmnopqrstuvwxyz +printf -- "--%12.10b--\n" abcdefghijklmnopqrstuvwxyz + +# tests for translating \' to ' and \\ to \ +# printf translates \' to ' in the format string... +printf "\'abcd\'\n" + +# but not when the %b format specification is used +printf "%b\n" \\\'abcd\\\' + +# but both translate \\ to \ +printf '\\abcd\\\n' +printf "%b\n" '\\abcd\\' + +# this was reported as a bug in bash-2.03 +# these three lines should all echo `26' +printf "%d\n" 0x1a +printf "%d\n" 032 +printf "%d\n" 26 + +# error messages + +# this should be an overflow, but error messages vary between systems +# printf "%lu\n" 4294967296 + +# ...but we cannot use this because some systems (SunOS4, for example), +# happily ignore overflow conditions in strtol(3) +#printf "%ld\n" 4294967296 + +printf "%10" +printf "ab%Mcd\n" + +# this caused an infinite loop in older versions of printf +printf "%y" 0 + +# these should print a warning and `0', according to POSIX.2 +printf "%d\n" GNU +printf "%o\n" GNU + +# failures in all bash versions through bash-2.05 +printf "%.0s" foo +printf "%.*s" 0 foo + +printf '%.0b-%.0s\n' foo bar +printf '(%*b)(%*s)\n' -4 foo -4 bar + +format='%'`printf '%0100384d' 0`'d\n' +printf $format 0 + +# failures in all bash versions through bash-3.0 - undercounted characters +unset vv +printf " %s %s %s \n%n" ab cd ef vv +echo "$vv" + +# this doesn't work with printf(3) on all systems +#printf "%'s\n" foo + +# test cases from an austin-group list discussion +# prints ^G as an extension +printf '%b\n' '\7' + +# prints ^G +printf '%b\n' '\0007' + +# prints NUL then 7 +printf '\0007\n' + +# prints no more than two hex digits +printf '\x07e\n' + +# additional backslash escapes +printf '\"\?\n' diff --git a/tests/quote.right b/tests/quote.right new file mode 100644 index 0000000..8d71f5d --- /dev/null +++ b/tests/quote.right @@ -0,0 +1,42 @@ +Single Quote +foo +bar +foo +bar +foo\ +bar +Double Quote +foo +bar +foo +bar +foobar +Backslash Single Quote +foo bar +foo bar +foobar +Backslash Double Quote +foo bar +foo bar +foobar +Double Quote Backslash Single Quote +foo +bar +foo +bar +foobar +Dollar Paren Single Quote +foo bar +foo bar +foo\ bar +Dollar Paren Double Quote +foo bar +foo bar +foobar +Double Quote Dollar Paren Single Quote +foo +bar +foo +bar +foo\ +bar diff --git a/tests/quote.tests b/tests/quote.tests new file mode 100644 index 0000000..152ea5a --- /dev/null +++ b/tests/quote.tests @@ -0,0 +1,63 @@ +echo "Single Quote" +echo 'foo +bar' +echo 'foo +bar' +echo 'foo\ +bar' + +echo "Double Quote" +echo "foo +bar" +echo "foo +bar" +echo "foo\ +bar" + +echo "Backslash Single Quote" +echo `echo 'foo +bar'` +echo `echo 'foo +bar'` +echo `echo 'foo\ +bar'` + +echo "Backslash Double Quote" +echo `echo "foo +bar"` +echo `echo "foo +bar"` +echo `echo "foo\ +bar"` + +echo "Double Quote Backslash Single Quote" +echo "`echo 'foo +bar'`" +echo "`echo 'foo +bar'`" +echo "`echo 'foo\ +bar'`" + +echo "Dollar Paren Single Quote" +echo $(echo 'foo +bar') +echo $(echo 'foo +bar') +echo $(echo 'foo\ +bar') + +echo "Dollar Paren Double Quote" +echo $(echo "foo +bar") +echo $(echo "foo +bar") +echo $(echo "foo\ +bar") + +echo "Double Quote Dollar Paren Single Quote" +echo "$(echo 'foo +bar')" +echo "$(echo 'foo +bar')" +echo "$(echo 'foo\ +bar')" diff --git a/tests/read.right b/tests/read.right new file mode 100644 index 0000000..8f0b2bf --- /dev/null +++ b/tests/read.right @@ -0,0 +1,62 @@ +a. +-a-b- +-a-b - +-a b- +-a b- +-a-b\- +-a b\- +-\-a b\- +-\ a b\- +-\-a b\- +-\ a b\- +argv[1] = <^A> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <abcd> +1: x[A] y[B] z[] +1a: +2: x[A B] +[A B ] +[ A B ] +==aa== +==== +==== +argv[1] = < foo> +argv[1] = < foo> +argv[1] = <foo> +argv[1] = < foo> +argv[1] = <foo> +argv[1] = <foo> +argv[1] = < foo> +a = abcdefg +a = xyz +a = -xyz 123- +a = abc +1 +4 +1 +4 +./read2.sub: line 13: read: -3: invalid timeout specification +1 +4 +abcde +./read3.sub: line 4: read: -1: invalid number +abc +ab +# +while read -u 3 var +do +echo "$var" +done 3<$0 +argv[1] = <> +argv[1] = <> +argv[1] = <> +FOO +argv[1] = <> +argv[1] = <3> +argv[1] = <> +argv[2] = <> +argv[3] = <> +FOO + 0 0 0 diff --git a/tests/read.tests b/tests/read.tests new file mode 100644 index 0000000..f9c78c5 --- /dev/null +++ b/tests/read.tests @@ -0,0 +1,95 @@ +echo " a " | (read x; echo "$x.") + +echo " a b " | ( read x y ; echo -"$x"-"$y"- ) +echo " a b\ " | ( read x y ; echo -"$x"-"$y"- ) +echo " a b " | ( read x ; echo -"$x"- ) +echo " a b\ " | ( read x ; echo -"$x"- ) + +echo " a b\ " | ( read -r x y ; echo -"$x"-"$y"- ) +echo " a b\ " | ( read -r x ; echo -"$x"- ) + +echo "\ a b\ " | ( read -r x y ; echo -"$x"-"$y"- ) +echo "\ a b\ " | ( read -r x ; echo -"$x"- ) +echo " \ a b\ " | ( read -r x y ; echo -"$x"-"$y"- ) +echo " \ a b\ " | ( read -r x ; echo -"$x"- ) + +# make sure that CTLESC and CTLNUL are passed through correctly +echo $'\001' | ( read var ; recho "$var" ) +echo $'\001' | ( read ; recho "$REPLY" ) + +echo $'\177' | ( read var ; recho "$var" ) +echo $'\177' | ( read ; recho "$REPLY" ) + +# make sure a backslash-quoted \\n still disappears from the input when +# we're not reading in `raw' mode, and no stray CTLESC chars are left in +# the input stream +echo $'ab\\\ncd' | ( read ; recho "$REPLY" ) + +echo "A B " > /tmp/IN +unset x y z +read x y z < /tmp/IN +echo 1: "x[$x] y[$y] z[$z]" +echo 1a: ${z-z not set} +read x < /tmp/IN +echo 2: "x[$x]" +rm /tmp/IN + +# this is where the bash `read' behavior with respect to $REPLY differs +# from ksh93 +echo "A B " > /tmp/IN + +read < /tmp/IN +echo "[$REPLY]" + +rm /tmp/IN + +echo " A B " > /tmp/IN + +read < /tmp/IN +echo "[$REPLY]" + +rm /tmp/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 =="$avar"== +echo =="$bvar"== +echo =="$cvar"== + +rm /tmp/IN + +# test behavior of read with various settings of IFS + +echo " foo" | { IFS= read line; recho "$line"; } + +echo " foo" | { IFS= ; read line; recho "$line"; } + +echo " foo" | { unset IFS ; read line; recho "$line"; } + +echo " foo" | { IFS=$'\n' ; read line; recho "$line"; } + +echo " foo" | { IFS=$' \n' ; read line; recho "$line"; } + +echo " foo" | { IFS=$' \t\n' ; read line; recho "$line"; } + +echo " foo" | { IFS=$':' ; read line; recho "$line"; } + +# test read -d delim behavior +${THIS_SH} ./read1.sub + +# test read -t timeout behavior +${THIS_SH} ./read2.sub + +# test read -n nchars behavior +${THIS_SH} ./read3.sub + +# test read -u fd behavior +${THIS_SH} ./read4.sub + +# test behavior when IFS is not the default -- bug through bash-2.05b +${THIS_SH} ./read5.sub diff --git a/tests/read1.sub b/tests/read1.sub new file mode 100644 index 0000000..2a36449 --- /dev/null +++ b/tests/read1.sub @@ -0,0 +1,23 @@ +a=7 +echo 'abcdefg|xyz' | { + read -d '|' a + echo a = "${a-unset}" +} + +echo xyz 123 | { + read -d ' ' a + echo a = "${a-unset}" +} + +echo xyz 123 | { + read -d $'\n' a + echo a = -"${a-unset}"- +} + +a=44 +echo abcd | { + read -d d a + echo a = $a +} + +exit 0 diff --git a/tests/read2.sub b/tests/read2.sub new file mode 100644 index 0000000..176cf86 --- /dev/null +++ b/tests/read2.sub @@ -0,0 +1,22 @@ +a=4 + +read -t 2 a < /dev/tty +echo $? + +echo $a + +sleep 5 | read -t 1 a +echo $? + +echo $a + +read -t -3 a < /dev/tty +echo $? + +echo $a + +# the above should all time out +echo abcde | { + read -t 2 a + echo $a +} diff --git a/tests/read3.sub b/tests/read3.sub new file mode 100644 index 0000000..22088cb --- /dev/null +++ b/tests/read3.sub @@ -0,0 +1,19 @@ +# non-interactive + +# error +read -n -1 + +# from pipe -- should work, but doesn't change tty attributes +echo abcdefg | { + read -n 3 xyz + echo $xyz +} + +# fewer chars than specified +echo ab | { + read -n 3 xyz + echo $xyz +} + +read -n 1 < $0 +echo "$REPLY" diff --git a/tests/read4.sub b/tests/read4.sub new file mode 100644 index 0000000..80bc9fc --- /dev/null +++ b/tests/read4.sub @@ -0,0 +1,4 @@ +while read -u 3 var +do + echo "$var" +done 3<$0 diff --git a/tests/read5.sub b/tests/read5.sub new file mode 100644 index 0000000..58b992d --- /dev/null +++ b/tests/read5.sub @@ -0,0 +1,36 @@ +IFS=: read x y z << EOF +::: +EOF +recho $x +recho "$x" +recho $y +recho "$y" +recho $z +recho "$z" + +if [ -z "$x" ]; then + echo FOO +else + echo BAR +fi + +IFS=: read -a A << EOF +::: +EOF + +recho ${A[0]} +recho "${A[0]}" + +recho ${#A[@]} + +recho "${A[@]}" + +if [ -z "${A[0]}" ]; then + echo FOO +else + echo BAR +fi + +echo -n ${A[0]} | cat -vet +echo -n ${A[0]} | wc + diff --git a/tests/redir.right b/tests/redir.right new file mode 100644 index 0000000..68bea52 --- /dev/null +++ b/tests/redir.right @@ -0,0 +1,102 @@ +abc +./redir.tests: line 13: /tmp/redir-test: cannot overwrite existing file +abc +def +def +./redir.tests: line 29: $z: ambiguous redirect +Point 1 +Point 2 +to a +to b +Point 3 +to a +to a +to b +to b +Point 4 +to c +Point 5 +this is redir1.sub +this is redir2.sub +read line1 "ab" +read line2 "root" +read line3 "cd" +read line4 "daemon" +from stdin: aa +to stdout +./redir4.sub: line 32: $fd: ambiguous redirect +./redir4.sub: line 33: $fd: ambiguous redirect +/tmp/err-and-out: +to stdout +to stderr +/tmp/err-and-out: +to stdout +to stderr +0 -- 3 0 +0 -- 4 0 +ab +cd +ef +gh +ij +kl +0 +ab +cd +cd +./redir.tests: line 152: redir1.*: No such file or directory +# tests of ksh93-like dup-and-close redirection operators +exec 9<$0 + +f() +{ +exec 5<$0 + +exec 0<&5- + +while read line; do +echo "$line" +done +} + +f + +typeset -f f + +# make sure it was closed +read -u 5 foo +echo after read + +exec 5<&0 + +exec <&- + +read abcde + +exec 0<&9- +read line +echo $line +f () +{ + exec 5<$0; + exec 0<&5-; + while read line; do + echo "$line"; + done +} +./redir5.sub: line 20: read: 5: invalid file descriptor: Bad file descriptor +after read +./redir5.sub: line 27: read: read error: 0: Bad file descriptor +# tests of ksh93-like dup-and-close redirection operators +/ +/ +/ +0 +0 +0 +before block +after block +c1 is 1 +c2 is 2 +c3 is 3 +c4 is 4 diff --git a/tests/redir.tests b/tests/redir.tests new file mode 100644 index 0000000..2669cd4 --- /dev/null +++ b/tests/redir.tests @@ -0,0 +1,174 @@ +export LC_ALL=C +export LANG=C + +# catch-all for remaining untested redirection stuff +set +o posix + +echo abc > /tmp/redir-test +cat /tmp/redir-test + +set -o noclobber + +#this should be an error +echo def > /tmp/redir-test +cat /tmp/redir-test + +# but this should succeed +echo def > /tmp/redir-test-2 +cat /tmp/redir-test-2 + +# and so should this +echo def >| /tmp/redir-test +cat /tmp/redir-test + +set +o noclobber +rm /tmp/redir-test /tmp/redir-test-2 + +# this should be an error +z="a b" +cat < $z + +echo "Point 1" + +exec 3</etc/passwd +exec 4>/tmp/bash-a +exec 5>/tmp/bash-b +echo "Point 2" + +echo to a 1>&4 +echo to b 1>&5 +cat /tmp/bash-a +cat /tmp/bash-b +exec 11</dev/null +echo "Point 3" + +echo to a 1>&4 +echo to b 1>&5 +cat /tmp/bash-a +cat /tmp/bash-b + +exec 11<&- +echo "Point 4" + +exec 6<>/tmp/bash-c +echo to c 1>&6 +cat /tmp/bash-c +echo "Point 5" + +rm -f /tmp/bash-a /tmp/bash-b /tmp/bash-c + +# +# Test the effect of input buffering on the shell's input +# +${THIS_SH} < redir1.sub + +# more open, close, duplicate file descriptors +${THIS_SH} ./redir3.sub < ./redir3.in1 + +# still more redirections +${THIS_SH} ./redir4.sub < redir4.in1 + +# various forms of null redirection +testf() +{ + if [ -f "$1" ]; then + rm -f "$1" + else + echo oops -- $1 not found + fi +} + +> /tmp/null-redir-a +testf /tmp/null-redir-a + +$EXIT > /tmp/null-redir-b +testf /tmp/null-redir-b + +( > /tmp/null-redir-c ) +testf /tmp/null-redir-c + +$EXIT > /tmp/null-redir-d & +wait +testf /tmp/null-redir-d + +exit 3 | $EXIT > /tmp/null-redir-e +echo $? -- ${PIPESTATUS[@]} +testf /tmp/null-redir-e + +exit 4 | > /tmp/null-redir-f +echo $? -- ${PIPESTATUS[@]} +testf /tmp/null-redir-f + +> /tmp/null-redir-g & +wait +testf /tmp/null-redir-g + +exec >/tmp/null-redir-h & +wait +testf /tmp/null-redir-h + +# make sure async commands don't get /dev/null as stdin when an explicit +# input redirection is supplied +for x in 1 2 3; do + { read line ; echo $line ; } & + wait + { read line ; echo $line ; } & + wait +done << EOF +ab +cd +ef +gh +ij +kl +EOF + +# make sure async commands get /dev/null as stdin in the absence of any +# input redirection +/bin/cat & +wait +echo $? + +# make sure that loops work OK with here documents and are not run in +# subshells +while read line; do + echo $line + l2=$line +done << EOF +ab +cd +EOF +echo $l2 + +# These should not echo anything -- bug in versions before 2.04 +( ( echo hello 1>&3 ) 3>&1 ) >/dev/null 2>&1 + +( ( echo hello 1>&3 ) 3>&1 ) >/dev/null 2>&1 | cat + +# in posix mode, non-interactive shells are not allowed to perform +# filename expansion on input redirections, even if they expand to +# a single filename +set -o posix +cat < redir1.* + +# test ksh93 dup-and-close (move fd) redirections +${THIS_SH} ./redir5.sub + +# test behavior after a write error with a builtin command +${THIS_SH} ./redir6.sub + +# problem with redirections using fds bash uses internally +: ${TMPDIR:=/tmp} + +trap 'rm -f $TMPDIR/bash-redir-$$' 0 1 2 3 6 15 + +echo before block +{ + echo before redir + exec 10>&1 + echo after redir +} > $TMPDIR/bash-redir-$$ + +echo after block + +${THIS_SH} ./redir7.sub diff --git a/tests/redir1.sub b/tests/redir1.sub new file mode 100644 index 0000000..f1082e9 --- /dev/null +++ b/tests/redir1.sub @@ -0,0 +1,8 @@ +# +# Test the effect of input buffering on the shell's input +# +echo this is redir1.sub + +exec 0< redir2.sub + +echo BUG: after exec in redir1.sub diff --git a/tests/redir2.sub b/tests/redir2.sub new file mode 100644 index 0000000..0820f70 --- /dev/null +++ b/tests/redir2.sub @@ -0,0 +1 @@ +echo this is redir2.sub diff --git a/tests/redir3.in1 b/tests/redir3.in1 new file mode 100644 index 0000000..dbd1fc3 --- /dev/null +++ b/tests/redir3.in1 @@ -0,0 +1,2 @@ +ab +cd diff --git a/tests/redir3.in2 b/tests/redir3.in2 new file mode 100644 index 0000000..5a1c32b --- /dev/null +++ b/tests/redir3.in2 @@ -0,0 +1,2 @@ +root +daemon diff --git a/tests/redir3.sub b/tests/redir3.sub new file mode 100644 index 0000000..c486253 --- /dev/null +++ b/tests/redir3.sub @@ -0,0 +1,26 @@ +read line1 + +echo read line1 \"$line1\" + +exec 4<./redir3.in2 + +exec 5<&0 +exec 0<&4 + +read line2 + +echo read line2 \"$line2\" + +exec 0<&5 + +read line3 + +echo read line3 \"$line3\" + +exec 0<&4 + +read line4 + +echo read line4 \"$line4\" + +exec 4<&- diff --git a/tests/redir4.in1 b/tests/redir4.in1 new file mode 100644 index 0000000..e61ef7b --- /dev/null +++ b/tests/redir4.in1 @@ -0,0 +1 @@ +aa diff --git a/tests/redir4.sub b/tests/redir4.sub new file mode 100644 index 0000000..4734455 --- /dev/null +++ b/tests/redir4.sub @@ -0,0 +1,56 @@ +minus=- + +# standard input +fd=0 + +exec 3<&$fd + +read line <&3 +echo from stdin: $line + +# close fd 3 +exec 3<&${minus} + +# should give `bad fd', but exact error messages vary +# read line <&3 + +# standard output +fd=1 + +exec 4>&$fd + +echo to stdout >&4 + +exec 4>&$minus + +# should give `bad fd', but exact error messages vary +# echo to stdout >&4 + +unset fd + +# these are ambiguous redirects +exec 3<&$fd +exec 4>&$fd + +exec 3>&1 4>&2 + +exec >&/tmp/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 + +rm /tmp/err-and-out + +fd=/tmp/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 + +rm /tmp/err-and-out diff --git a/tests/redir5.sub b/tests/redir5.sub new file mode 100644 index 0000000..5d59d39 --- /dev/null +++ b/tests/redir5.sub @@ -0,0 +1,31 @@ +# tests of ksh93-like dup-and-close redirection operators +exec 9<$0 + +f() +{ +exec 5<$0 + +exec 0<&5- + +while read line; do + echo "$line" +done +} + +f + +typeset -f f + +# make sure it was closed +read -u 5 foo +echo after read + +exec 5<&0 + +exec <&- + +read abcde + +exec 0<&9- +read line +echo $line diff --git a/tests/redir6.sub b/tests/redir6.sub new file mode 100644 index 0000000..60cc68b --- /dev/null +++ b/tests/redir6.sub @@ -0,0 +1,8 @@ +cd / +pwd +help >&- +pwd +pwd +echo $? +echo $? +echo $? diff --git a/tests/redir7.sub b/tests/redir7.sub new file mode 100644 index 0000000..3fd371c --- /dev/null +++ b/tests/redir7.sub @@ -0,0 +1,69 @@ +# weird redirections that caused trouble and were fixed in post-3.0 bash +stuff() +{ + c=1 + ( sleep 5 < /dev/null >/dev/null 2>&1 & ) & +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c1 is $c + +unset -f stuff + +stuff() +{ + c=2 + ( sleep 5 < /dev/null >/dev/null 2>&1 & ) +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c2 is $c + +unset -f stuff + +stuff() +{ + c=3 + { sleep 5 < /dev/null >/dev/null 2>&1 & } & +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c3 is $c + +unset -f stuff + +stuff() +{ + c=4 + { sleep 5 < /dev/null >/dev/null 2>&1 & } +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c4 is $c + +# fixed in bash-3.1 +echo 'exec <&3' | ${THIS_SH} 3<&0 diff --git a/tests/rhs-exp.right b/tests/rhs-exp.right new file mode 100644 index 0000000..c5dca42 --- /dev/null +++ b/tests/rhs-exp.right @@ -0,0 +1,74 @@ +argv[1] = <TDEFAULTS = -DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\'&m68kcoff_vec\'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS = -DSELECT_VECS="&m68kcoff_vec"> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\&m68kcoff_vec\> +argv[1] = <TDEFAULTS = -DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS = -DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS = -DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS = -DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\&m68kcoff_vec> +argv[1] = <TDEFAULTS = -DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS="&m68kcoff_vec"> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\&m68kcoff_vec\> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\&m68kcoff_vec> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\'&m68kcoff_vec\'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=p> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\p> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\'> +argv[1] = <TDEFAULTS = -DSELECT_VECS='> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\p> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=p> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS='> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\'> +a*b +ab +a?b +ab +a/b +ab diff --git a/tests/rhs-exp.tests b/tests/rhs-exp.tests new file mode 100644 index 0000000..d457198 --- /dev/null +++ b/tests/rhs-exp.tests @@ -0,0 +1,49 @@ +selvecs='&m68kcoff_vec' +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'$selvecs\'}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="$selvecs"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\"$selvecs\"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\$selvecs\\}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=$selvecs}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\$selvecs}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\$selvecs"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'"$null"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\$selvecs"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'$selvecs\'"}" + +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'$selvecs\'} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="$selvecs"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\"$selvecs\"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\$selvecs\\} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=$selvecs} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\$selvecs} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\$selvecs"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'"$null"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\$selvecs"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'$selvecs\'"} + +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\p"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\p}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'"}" + +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\p"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\p} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'"} + +# more tests for bash-3.0 behavior + +var="a*b" ; echo "${var//\\*/}" +var="a*b" ; echo "${var//\*/}" + +var="a?b" ; echo "${var//\\?/}" +var="a?b" ; echo "${var//\?/}" + +var="a/b" ; echo "${var//\\//}" +var="a/b" ; echo "${var//\//}" diff --git a/tests/rsh.right b/tests/rsh.right new file mode 100644 index 0000000..e673b94 --- /dev/null +++ b/tests/rsh.right @@ -0,0 +1,13 @@ +./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 +set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] +./rsh.tests: line 29: set: restricted: invalid option name +./rsh.tests: line 31: exec: restricted +./rsh.tests: after exec diff --git a/tests/rsh.tests b/tests/rsh.tests new file mode 100644 index 0000000..ffdf6e5 --- /dev/null +++ b/tests/rsh.tests @@ -0,0 +1,33 @@ +# test restricted shell mode -- these should all be errors +# +# things not tested for: +# adding builtins dynamically with enable -f +# importing function definitions from environment + +set -r + +cd / +PATH=$PATH:/usr/local/bin +SHELL=/bin/sh +/bin/sh -c 'echo /bin/sh executed' + +. ./source.sub3 + +rm -f /tmp/restricted +echo abc > /tmp/restricted +if [ -f /tmp/restricted ]; then + echo oops 1 -- output +fi +echo abc >> /tmp/restricted +if [ -f /tmp/restricted ]; then + echo oops 2 -- append +fi + +command -p date + +set +r +set +o restricted + +exec /bin/date + +echo $0: after exec diff --git a/tests/run-alias b/tests/run-alias new file mode 100644 index 0000000..6a20b06 --- /dev/null +++ b/tests/run-alias @@ -0,0 +1,2 @@ +${THIS_SH} ./alias.tests > /tmp/xx 2>&1 +diff /tmp/xx alias.right && rm -f /tmp/xx diff --git a/tests/run-all b/tests/run-all new file mode 100644 index 0000000..d3f3a0e --- /dev/null +++ b/tests/run-all @@ -0,0 +1,29 @@ +#! /bin/sh + +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 + +: ${THIS_SH:=../bash} +export THIS_SH + +${THIS_SH} ./version + +rm -f /tmp/xx + +echo Any output from any test, unless otherwise noted, indicates a possible anomaly + +for x in run-* +do + case $x in + $0|run-minimal|run-gprof) ;; + *.orig|*~) ;; + *) echo $x ; sh $x ;; + esac +done + +exit 0 diff --git a/tests/run-appendop b/tests/run-appendop new file mode 100644 index 0000000..c5bffbc --- /dev/null +++ b/tests/run-appendop @@ -0,0 +1,2 @@ +${THIS_SH} ./appendop.tests > /tmp/xx 2>&1 +diff /tmp/xx appendop.right && rm -f /tmp/xx diff --git a/tests/run-arith b/tests/run-arith new file mode 100644 index 0000000..f9f573c --- /dev/null +++ b/tests/run-arith @@ -0,0 +1,2 @@ +${THIS_SH} ./arith.tests > /tmp/xx 2>&1 +diff /tmp/xx arith.right && rm -f /tmp/xx diff --git a/tests/run-arith-for b/tests/run-arith-for new file mode 100644 index 0000000..1d13075 --- /dev/null +++ b/tests/run-arith-for @@ -0,0 +1,2 @@ +${THIS_SH} ./arith-for.tests > /tmp/xx 2>&1 +diff /tmp/xx arith-for.right && rm -f /tmp/xx diff --git a/tests/run-array b/tests/run-array new file mode 100644 index 0000000..44207d9 --- /dev/null +++ b/tests/run-array @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell" >&2 +${THIS_SH} ./array.tests > /tmp/xx 2>&1 +diff /tmp/xx array.right && rm -f /tmp/xx diff --git a/tests/run-array2 b/tests/run-array2 new file mode 100644 index 0000000..dd94ec8 --- /dev/null +++ b/tests/run-array2 @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell" >&2 +${THIS_SH} ./array-at-star > /tmp/xx 2>&1 +diff /tmp/xx array2.right && rm -f /tmp/xx diff --git a/tests/run-braces b/tests/run-braces new file mode 100644 index 0000000..53d4f1b --- /dev/null +++ b/tests/run-braces @@ -0,0 +1,2 @@ +${THIS_SH} ./braces.tests > /tmp/xx +diff /tmp/xx braces.right && rm -f /tmp/xx diff --git a/tests/run-builtins b/tests/run-builtins new file mode 100644 index 0000000..53d963e --- /dev/null +++ b/tests/run-builtins @@ -0,0 +1,2 @@ +${THIS_SH} ./builtins.tests > /tmp/xx 2>&1 +diff /tmp/xx builtins.right && rm -f /tmp/xx diff --git a/tests/run-cond b/tests/run-cond new file mode 100644 index 0000000..6b119a6 --- /dev/null +++ b/tests/run-cond @@ -0,0 +1,7 @@ +echo "warning: all of these tests will fail if the conditional command has not" >&2 +echo "warning: been compiled into the shell" >&2 +echo "warning: some of these tests will fail if extended pattern matching has not" >&2 +echo "warning: been compiled into the shell" >&2 + +${THIS_SH} ./cond.tests > /tmp/xx 2>&1 +diff /tmp/xx cond.right && rm -f /tmp/xx diff --git a/tests/run-cprint b/tests/run-cprint new file mode 100644 index 0000000..5f202e4 --- /dev/null +++ b/tests/run-cprint @@ -0,0 +1,2 @@ +${THIS_SH} ./cprint.tests > /tmp/xx 2>&1 +diff /tmp/xx cprint.right && rm -f /tmp/xx diff --git a/tests/run-dbg-support b/tests/run-dbg-support new file mode 100755 index 0000000..9e9c649 --- /dev/null +++ b/tests/run-dbg-support @@ -0,0 +1,11 @@ +#!../bash +#$Id: run-dbg-support,v 1.5 2002/11/14 06:08:16 rockyb Exp $ + +TEST_NAME='dbg-support' +TEST_FILE="/tmp/${TEST_NAME}.check" +${THIS_SH} ./${TEST_NAME}.tests > $TEST_FILE 2>&1 < /dev/null +set -f +diff $TEST_FILE ${TEST_NAME}.right && rm -f $TEST_FILE + +# Return code tells testing mechanism whether passed or not. +exit $? diff --git a/tests/run-dbg-support2 b/tests/run-dbg-support2 new file mode 100755 index 0000000..f62583f --- /dev/null +++ b/tests/run-dbg-support2 @@ -0,0 +1,16 @@ +#!../bash +#$Id: run-dbg-support2,v 1.3 2002/11/14 06:08:16 rockyb Exp $ + +TEST_NAME='dbg-support2' +TEST_FILE="/tmp/${TEST_NAME}.check" +${THIS_SH} ./${TEST_NAME}.tests > $TEST_FILE 2>&1 < /dev/null +set -f +diff $TEST_FILE ${TEST_NAME}.right && rm -f $TEST_FILE + +# Return code tells testing mechanism whether passed or not. +exit $? + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/run-dirstack b/tests/run-dirstack new file mode 100644 index 0000000..6390d1b --- /dev/null +++ b/tests/run-dirstack @@ -0,0 +1,5 @@ +${THIS_SH} ./dstack.tests > /tmp/xx 2>&1 +diff /tmp/xx dstack.right && rm -f /tmp/xx + +${THIS_SH} ./dstack2.tests > /tmp/xx 2>&1 +diff /tmp/xx dstack2.right && rm -f /tmp/xx diff --git a/tests/run-dollars b/tests/run-dollars new file mode 100644 index 0000000..0ced414 --- /dev/null +++ b/tests/run-dollars @@ -0,0 +1,2 @@ +${THIS_SH} ./dollar-at-star > /tmp/xx 2>&1 +diff /tmp/xx dollar.right && rm -f /tmp/xx diff --git a/tests/run-errors b/tests/run-errors new file mode 100644 index 0000000..6be4e0c --- /dev/null +++ b/tests/run-errors @@ -0,0 +1,2 @@ +${THIS_SH} ./errors.tests > /tmp/xx 2>&1 +diff /tmp/xx errors.right && rm -f /tmp/xx diff --git a/tests/run-execscript b/tests/run-execscript new file mode 100644 index 0000000..f97ab21 --- /dev/null +++ b/tests/run-execscript @@ -0,0 +1,9 @@ +echo "warning: the text of a system error message may vary between systems and" >&2 +echo "warning: produce diff output." >&2 +echo "warning: if the text of the error messages concerning \`notthere' or" >&2 +echo "warning: \`/tmp/bash-notthere' not being found or \`/' being a directory" >&2 +echo "warning: produce diff output, please do not consider this a test failure" >&2 +echo "warning: if diff output differing only in the location of the bash" >&2 +echo "warning: binary appears, please do not consider this a test failure" >&2 +${THIS_SH} ./execscript > /tmp/xx 2>&1 +diff /tmp/xx exec.right && rm -f /tmp/xx diff --git a/tests/run-exp-tests b/tests/run-exp-tests new file mode 100644 index 0000000..c55f714 --- /dev/null +++ b/tests/run-exp-tests @@ -0,0 +1,2 @@ +${THIS_SH} ./exp-tests | grep -v '^expect' > /tmp/xx +diff /tmp/xx exp.right && rm -f /tmp/xx diff --git a/tests/run-extglob b/tests/run-extglob new file mode 100644 index 0000000..06316ad --- /dev/null +++ b/tests/run-extglob @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./extglob.tests | grep -v '^expect' > /tmp/xx +diff /tmp/xx extglob.right && rm -f /tmp/xx diff --git a/tests/run-extglob2 b/tests/run-extglob2 new file mode 100644 index 0000000..0a6f728 --- /dev/null +++ b/tests/run-extglob2 @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./extglob2.tests | grep -v '^expect' > /tmp/xx +diff /tmp/xx extglob2.right && rm -f /tmp/xx diff --git a/tests/run-extglob3 b/tests/run-extglob3 new file mode 100644 index 0000000..2675196 --- /dev/null +++ b/tests/run-extglob3 @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./extglob3.tests > /tmp/xx +diff /tmp/xx extglob3.right && rm -f /tmp/xx diff --git a/tests/run-func b/tests/run-func new file mode 100644 index 0000000..f449eb8 --- /dev/null +++ b/tests/run-func @@ -0,0 +1,5 @@ +echo "warning: if you have exported functions defined in your environment," >&2 +echo "warning: they may show up as diff output." >&2 +echo "warning: if so, please do not consider this a test failure" >&2 +${THIS_SH} ./func.tests > /tmp/xx 2>&1 +diff /tmp/xx func.right && rm -f /tmp/xx diff --git a/tests/run-getopts b/tests/run-getopts new file mode 100644 index 0000000..1e8b5fb --- /dev/null +++ b/tests/run-getopts @@ -0,0 +1,2 @@ +${THIS_SH} ./getopts.tests > /tmp/xx 2>&1 +diff /tmp/xx getopts.right && rm -f /tmp/xx diff --git a/tests/run-glob-test b/tests/run-glob-test new file mode 100644 index 0000000..659112a --- /dev/null +++ b/tests/run-glob-test @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./glob-test 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx glob.right && rm -f /tmp/xx diff --git a/tests/run-heredoc b/tests/run-heredoc new file mode 100644 index 0000000..c4e3168 --- /dev/null +++ b/tests/run-heredoc @@ -0,0 +1,2 @@ +${THIS_SH} ./heredoc.tests > /tmp/xx 2>&1 +diff /tmp/xx heredoc.right && rm -f /tmp/xx diff --git a/tests/run-herestr b/tests/run-herestr new file mode 100644 index 0000000..8c5b36d --- /dev/null +++ b/tests/run-herestr @@ -0,0 +1,2 @@ +${THIS_SH} ./herestr.tests > /tmp/xx 2>&1 +diff /tmp/xx herestr.right && rm -f /tmp/xx diff --git a/tests/run-histexpand b/tests/run-histexpand new file mode 100644 index 0000000..06a415b --- /dev/null +++ b/tests/run-histexpand @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if history has not been compiled" >&2 +echo "warning: into the shell" >&2 +${THIS_SH} ./histexp.tests > /tmp/xx 2>&1 +diff /tmp/xx histexp.right && rm -f /tmp/xx diff --git a/tests/run-history b/tests/run-history new file mode 100644 index 0000000..ea356b1 --- /dev/null +++ b/tests/run-history @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if history has not been compiled" >&2 +echo "warning: into the shell" >&2 +${THIS_SH} ./history.tests > /tmp/xx 2>&1 +diff /tmp/xx history.right && rm -f /tmp/xx diff --git a/tests/run-ifs b/tests/run-ifs new file mode 100644 index 0000000..3f9d820 --- /dev/null +++ b/tests/run-ifs @@ -0,0 +1,2 @@ +${THIS_SH} ./ifs.tests > /tmp/xx 2>&1 +diff /tmp/xx ifs.right && rm -f /tmp/xx diff --git a/tests/run-ifs-posix b/tests/run-ifs-posix new file mode 100644 index 0000000..e578e8d --- /dev/null +++ b/tests/run-ifs-posix @@ -0,0 +1,2 @@ +${THIS_SH} ./ifs-posix.tests > /tmp/xx 2>&1 +diff /tmp/xx ifs-posix.right && rm -f /tmp/xx diff --git a/tests/run-input-test b/tests/run-input-test new file mode 100644 index 0000000..aaa5d35 --- /dev/null +++ b/tests/run-input-test @@ -0,0 +1,2 @@ +${THIS_SH} < ./input-line.sh > /tmp/xx +diff /tmp/xx input.right && rm -f /tmp/xx diff --git a/tests/run-intl b/tests/run-intl new file mode 100644 index 0000000..6a9234a --- /dev/null +++ b/tests/run-intl @@ -0,0 +1,8 @@ +# See whether or not we can use `diff -a' +( diff -a ./intl.right ./intl.right >/dev/null 2>&1 ) && AFLAG=-a + +echo "warning: some of these tests will fail if you do not have UTF-8" >&2 +echo "warning: locales installed on your system." >&2 +echo "warning: please ignore any differences consisting only of white space" >&2 +${THIS_SH} ./intl.tests > /tmp/xx +diff $AFLAG /tmp/xx intl.right && rm -f /tmp/xx diff --git a/tests/run-invert b/tests/run-invert new file mode 100644 index 0000000..67e0879 --- /dev/null +++ b/tests/run-invert @@ -0,0 +1,2 @@ +${THIS_SH} ./invert.tests | grep -v '^expect' > /tmp/xx +diff /tmp/xx invert.right && rm -f /tmp/xx diff --git a/tests/run-iquote b/tests/run-iquote new file mode 100644 index 0000000..61a8aa7 --- /dev/null +++ b/tests/run-iquote @@ -0,0 +1,2 @@ +${THIS_SH} ./iquote.tests >/tmp/xx 2>&1 +diff /tmp/xx iquote.right && rm -f /tmp/xx diff --git a/tests/run-jobs b/tests/run-jobs new file mode 100644 index 0000000..bfd4fa0 --- /dev/null +++ b/tests/run-jobs @@ -0,0 +1,7 @@ +echo "warning: some of these tests may fail if job control has not been compiled" >&2 +echo "warning: into the shell" >&2 +echo "warning: there may be a message regarding a cat process dying due to a" >&2 +echo "warning: SIGHUP. Please disregard." >&2 + +${THIS_SH} ./jobs.tests > /tmp/xx 2>&1 +diff /tmp/xx jobs.right && rm -f /tmp/xx diff --git a/tests/run-minimal b/tests/run-minimal new file mode 100644 index 0000000..5c5dcc4 --- /dev/null +++ b/tests/run-minimal @@ -0,0 +1,36 @@ +#! /bin/sh +# +# run-minimal - a version of run-all for shells configured with +# --enable-minimal-config +# +PATH=.:$PATH # just to get the right version of printenv +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 + +: ${THIS_SH:=../bash} +export THIS_SH + +${THIS_SH} ./version.mini + +rm -f /tmp/xx + +echo Testing ${THIS_SH} +echo Any output from any test, unless otherwise noted, indicates a possible anomaly +for x in run-* +do + case $x in + $0) ;; + *.orig|*~) ;; + run-dollars|run-execscript|run-func|run-getopts|run-heredoc) echo $x ; sh $x ;; + run-ifs-tests|run-input-test|run-invert|run-more-exp|run-nquote) echo $x ; sh $x ;; + run-ifs-0posix|run-posix2|run-posixpat) echo $x ; sh $x ;; + run-precedence|run-quote|run-read|run-rhs-exp|run-strip|run-tilde) echo $x ; sh $x ;; + *) ;; + esac +done + +exit 0 diff --git a/tests/run-more-exp b/tests/run-more-exp new file mode 100644 index 0000000..60f55cb --- /dev/null +++ b/tests/run-more-exp @@ -0,0 +1,2 @@ +${THIS_SH} ./more-exp.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx more-exp.right && rm -f /tmp/xx diff --git a/tests/run-new-exp b/tests/run-new-exp new file mode 100644 index 0000000..2e3d7c9 --- /dev/null +++ b/tests/run-new-exp @@ -0,0 +1,10 @@ +echo "warning: two of these tests will fail if your OS does not support" >&2 +echo "warning: named pipes or the /dev/fd filesystem. If the tests of the" >&2 +echo "warning: process substitution mechanism fail, please do not consider" >&2 +echo "warning: this a test failure" >&2 +echo "warning: if you have exported variables beginning with the string _Q," >&2 +echo "warning: diff output may be generated. If so, please do not consider" >&2 +echo "warning: this a test failure" >&2 + +${THIS_SH} ./new-exp.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx new-exp.right && rm -f /tmp/xx diff --git a/tests/run-nquote b/tests/run-nquote new file mode 100644 index 0000000..006872c --- /dev/null +++ b/tests/run-nquote @@ -0,0 +1,2 @@ +${THIS_SH} ./nquote.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx nquote.right && rm -f /tmp/xx diff --git a/tests/run-nquote1 b/tests/run-nquote1 new file mode 100644 index 0000000..a71740f --- /dev/null +++ b/tests/run-nquote1 @@ -0,0 +1,4 @@ +echo "warning: several of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell." >&2 +${THIS_SH} ./nquote1.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx nquote1.right && rm -f /tmp/xx diff --git a/tests/run-nquote2 b/tests/run-nquote2 new file mode 100644 index 0000000..80d1a8d --- /dev/null +++ b/tests/run-nquote2 @@ -0,0 +1,4 @@ +echo "warning: several of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell." >&2 +${THIS_SH} ./nquote2.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx nquote2.right && rm -f /tmp/xx diff --git a/tests/run-nquote3 b/tests/run-nquote3 new file mode 100644 index 0000000..45ba5f7 --- /dev/null +++ b/tests/run-nquote3 @@ -0,0 +1,4 @@ +echo "warning: several of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell." >&2 +${THIS_SH} ./nquote3.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx nquote3.right && rm -f /tmp/xx diff --git a/tests/run-nquote4 b/tests/run-nquote4 new file mode 100644 index 0000000..f7d05bb --- /dev/null +++ b/tests/run-nquote4 @@ -0,0 +1,4 @@ +echo warning: some of these tests will fail if you do not have UTF-8 >&2 +echo warning: locales installed on your system +${THIS_SH} ./nquote4.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx nquote4.right && rm -f /tmp/xx diff --git a/tests/run-posix2 b/tests/run-posix2 new file mode 100644 index 0000000..52eea2f --- /dev/null +++ b/tests/run-posix2 @@ -0,0 +1,2 @@ +${THIS_SH} ./posix2.tests 2>&1 | grep -v '^expect' > /tmp/xx +diff /tmp/xx posix2.right && rm -f /tmp/xx diff --git a/tests/run-posixpat b/tests/run-posixpat new file mode 100644 index 0000000..ef2b140 --- /dev/null +++ b/tests/run-posixpat @@ -0,0 +1,2 @@ +${THIS_SH} ./posixpat.tests > /tmp/xx +diff /tmp/xx posixpat.right && rm -f /tmp/xx diff --git a/tests/run-precedence b/tests/run-precedence new file mode 100644 index 0000000..d81a868 --- /dev/null +++ b/tests/run-precedence @@ -0,0 +1,2 @@ +${THIS_SH} ./precedence > /tmp/xx +diff /tmp/xx prec.right && rm -f /tmp/xx diff --git a/tests/run-printf b/tests/run-printf new file mode 100644 index 0000000..4555c62 --- /dev/null +++ b/tests/run-printf @@ -0,0 +1,5 @@ +# See whether or not we can use `diff -a' +( diff -a ./printf.tests ./printf.tests >/dev/null 2>&1 ) && AFLAG=-a + +${THIS_SH} ./printf.tests > /tmp/xx 2>&1 +diff $AFLAG /tmp/xx printf.right && rm -f /tmp/xx diff --git a/tests/run-quote b/tests/run-quote new file mode 100644 index 0000000..6905042 --- /dev/null +++ b/tests/run-quote @@ -0,0 +1,2 @@ +${THIS_SH} ./quote.tests >/tmp/xx 2>&1 +diff /tmp/xx quote.right && rm -f /tmp/xx diff --git a/tests/run-read b/tests/run-read new file mode 100644 index 0000000..47e4188 --- /dev/null +++ b/tests/run-read @@ -0,0 +1,4 @@ +echo "warning: please do not consider output differing only in the amount of" >&2 +echo "warning: white space to be an error." >&2 +${THIS_SH} ./read.tests > /tmp/xx 2>&1 +diff /tmp/xx read.right && rm -f /tmp/xx diff --git a/tests/run-redir b/tests/run-redir new file mode 100644 index 0000000..2be45dd --- /dev/null +++ b/tests/run-redir @@ -0,0 +1,7 @@ +echo "warning: the text of a system error message may vary between systems and" >&2 +echo "warning: produce diff output." >&2 +echo "warning: if the text of an error message concerning \`redir1.*' not being" >&2 +echo "warning: found or messages concerning bad file descriptors produce diff" >&2 +echo "warning: output, please do not consider it a test failure" >&2 +${THIS_SH} ./redir.tests > /tmp/xx 2>&1 +diff /tmp/xx redir.right && rm -f /tmp/xx diff --git a/tests/run-rhs-exp b/tests/run-rhs-exp new file mode 100644 index 0000000..1f89d0b --- /dev/null +++ b/tests/run-rhs-exp @@ -0,0 +1,2 @@ +${THIS_SH} ./rhs-exp.tests 2>&1 > /tmp/xx +diff /tmp/xx rhs-exp.right && rm -f /tmp/xx diff --git a/tests/run-rsh b/tests/run-rsh new file mode 100644 index 0000000..ef23583 --- /dev/null +++ b/tests/run-rsh @@ -0,0 +1,2 @@ +${THIS_SH} ./rsh.tests > /tmp/xx 2>&1 +diff /tmp/xx rsh.right && rm -f /tmp/xx diff --git a/tests/run-set-e b/tests/run-set-e new file mode 100644 index 0000000..cca61cd --- /dev/null +++ b/tests/run-set-e @@ -0,0 +1,2 @@ +${THIS_SH} ./set-e-test > /tmp/xx +diff /tmp/xx set-e.right && rm -f /tmp/xx diff --git a/tests/run-set-x b/tests/run-set-x new file mode 100755 index 0000000..b999e69 --- /dev/null +++ b/tests/run-set-x @@ -0,0 +1,11 @@ +#!../bash +#$Id: run-set-x,v 1.1 2002/12/09 13:12:37 rockyb Exp $ + +TEST_NAME='set-x' +TEST_FILE="/tmp/${TEST_NAME}.check" +${THIS_SH} ./${TEST_NAME}.tests > $TEST_FILE 2>&1 < /dev/null +set -f +diff $TEST_FILE ${TEST_NAME}.right && rm -f $TEST_FILE + +# Return code tells testing mechanism whether passed or not. +exit $? diff --git a/tests/run-shopt b/tests/run-shopt new file mode 100644 index 0000000..100a3de --- /dev/null +++ b/tests/run-shopt @@ -0,0 +1,2 @@ +${THIS_SH} ./shopt.tests > /tmp/xx 2>&1 +diff /tmp/xx shopt.right && rm -f /tmp/xx diff --git a/tests/run-strip b/tests/run-strip new file mode 100644 index 0000000..0d32115 --- /dev/null +++ b/tests/run-strip @@ -0,0 +1,2 @@ +${THIS_SH} ./strip.tests > /tmp/xx +diff /tmp/xx strip.right && rm -f /tmp/xx diff --git a/tests/run-test b/tests/run-test new file mode 100644 index 0000000..b2482c3 --- /dev/null +++ b/tests/run-test @@ -0,0 +1,4 @@ +unset GROUPS UID 2>/dev/null + +${THIS_SH} ./test.tests >/tmp/xx 2>&1 +diff /tmp/xx test.right && rm -f /tmp/xx diff --git a/tests/run-tilde b/tests/run-tilde new file mode 100644 index 0000000..b8569c1 --- /dev/null +++ b/tests/run-tilde @@ -0,0 +1,2 @@ +${THIS_SH} ./tilde.tests > /tmp/xx +diff /tmp/xx tilde.right && rm -f /tmp/xx diff --git a/tests/run-tilde2 b/tests/run-tilde2 new file mode 100644 index 0000000..4446989 --- /dev/null +++ b/tests/run-tilde2 @@ -0,0 +1,2 @@ +${THIS_SH} ./tilde2.tests > /tmp/xx +diff /tmp/xx tilde2.right && rm -f /tmp/xx diff --git a/tests/run-trap b/tests/run-trap new file mode 100644 index 0000000..b448443 --- /dev/null +++ b/tests/run-trap @@ -0,0 +1,6 @@ +echo "warning: UNIX versions number signals differently. If output differing" >&2 +echo "warning: only in line numbers is produced, please do not consider this" >&2 +echo "warning: a test failure." >&2 + +${THIS_SH} ./trap.tests > /tmp/xx 2>&1 +diff /tmp/xx trap.right && rm -f /tmp/xx diff --git a/tests/run-type b/tests/run-type new file mode 100644 index 0000000..4d195b0 --- /dev/null +++ b/tests/run-type @@ -0,0 +1,2 @@ +${THIS_SH} ./type.tests > /tmp/xx 2>&1 +diff /tmp/xx type.right && rm -f /tmp/xx diff --git a/tests/run-varenv b/tests/run-varenv new file mode 100644 index 0000000..f0ce195 --- /dev/null +++ b/tests/run-varenv @@ -0,0 +1,2 @@ +${THIS_SH} ./varenv.sh | grep -v '^expect' > /tmp/xx +diff /tmp/xx varenv.right && rm -f /tmp/xx diff --git a/tests/set-e-test b/tests/set-e-test new file mode 100644 index 0000000..fe1549c --- /dev/null +++ b/tests/set-e-test @@ -0,0 +1,84 @@ +if : ; then + set -e + N=95 + while :; do + # expr returns 1 if expression is null or 0 + set +e + N_MOD_100=`expr $N % 100` + set -e + echo $N_MOD_100 + N=`expr $N + 1` + if [ $N -eq 110 ]; then + break + fi + done + set +e +fi + +( +set -e +false +echo bad +) +echo $? + +x=$( +set -e +false +echo bad +) +echo $? $x + +# command subst should not inherit -e +set -e +echo $(false; echo ok) + +if set +e +then + false +fi +echo hi + +set -e + +# a failing command in the compound list following a while, until, or +# if should not cause the shell to exit + +while false; do + echo hi +done +echo while succeeded + +x=1 +until (( x == 4 )); do + x=4 +done +echo until succeeded: $x + +if false; then + echo oops +fi +echo if succeeded + +# failing commands that are part of an AND or OR list should not +# cause the shell to exit +false && echo AND list failed +echo AND list succeeded + +false || echo OR list succeeded + +! false +echo ! succeeded + +# make sure eval preserves the state of the -e flag and `!' reserved word +set -e +if eval false; then + echo oops +fi +echo eval succeeded + +! eval false +echo ! eval succeeded -- 1 + +! eval '(exit 5)' +echo ! eval succeeded -- 2 diff --git a/tests/set-e.right b/tests/set-e.right new file mode 100644 index 0000000..6448413 --- /dev/null +++ b/tests/set-e.right @@ -0,0 +1,28 @@ +95 +96 +97 +98 +99 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +1 +1 +ok +hi +while succeeded +until succeeded: 4 +if succeeded +AND list succeeded +OR list succeeded +! succeeded +eval succeeded +! eval succeeded -- 1 +! eval succeeded -- 2 diff --git a/tests/set-x.right b/tests/set-x.right new file mode 100644 index 0000000..fc55bd8 --- /dev/null +++ b/tests/set-x.right @@ -0,0 +1,28 @@ ++ (( i=0 )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ for i in 0 1 2 ++ x=i ++ for i in 0 1 2 ++ x=i ++ for i in 0 1 2 ++ x=i ++ case x in ++ x=i diff --git a/tests/set-x.tests b/tests/set-x.tests new file mode 100755 index 0000000..323b772 --- /dev/null +++ b/tests/set-x.tests @@ -0,0 +1,21 @@ +#!../bash +# $Id: set-x.tests,v 1.1 2002/12/09 13:12:37 rockyb Exp $ +# +# Test that "set -x" shows what we think it should. +# +set -x +for ((i=0; i<=5; i++ )) ; do + x=0 +done +for i in 0 1 2 ; do + x=i +done +case x in + 0) x=i ;; + *) x=i ;; +esac + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/shopt.right b/tests/shopt.right new file mode 100644 index 0000000..b2fc219 --- /dev/null +++ b/tests/shopt.right @@ -0,0 +1,238 @@ +./shopt.tests: line 2: shopt: -z: invalid option +shopt: usage: shopt [-pqsu] [-o long-option] optname [optname...] +-- +shopt -u cdable_vars +shopt -s cdspell +shopt -u checkhash +shopt -u checkwinsize +shopt -s cmdhist +shopt -u dotglob +shopt -u execfail +shopt -s expand_aliases +shopt -u extdebug +shopt -u extglob +shopt -s extquote +shopt -u failglob +shopt -s force_fignore +shopt -u gnu_errfmt +shopt -u histappend +shopt -u histreedit +shopt -u histverify +shopt -s hostcomplete +shopt -u huponexit +shopt -s interactive_comments +shopt -u lithist +shopt -u login_shell +shopt -u mailwarn +shopt -u no_empty_cmd_completion +shopt -u nocaseglob +shopt -u nocasematch +shopt -u nullglob +shopt -s progcomp +shopt -s promptvars +shopt -u restricted_shell +shopt -u shift_verbose +shopt -s sourcepath +shopt -u xpg_echo +-- +shopt -u huponexit +shopt -u checkwinsize +shopt -s sourcepath +-- +shopt -s cdspell +shopt -s cmdhist +shopt -s expand_aliases +shopt -s extquote +shopt -s force_fignore +shopt -s hostcomplete +shopt -s interactive_comments +shopt -s progcomp +shopt -s promptvars +shopt -s sourcepath +-- +shopt -u cdable_vars +shopt -u checkhash +shopt -u checkwinsize +shopt -u dotglob +shopt -u execfail +shopt -u extdebug +shopt -u extglob +shopt -u failglob +shopt -u gnu_errfmt +shopt -u histappend +shopt -u histreedit +shopt -u histverify +shopt -u huponexit +shopt -u lithist +shopt -u login_shell +shopt -u mailwarn +shopt -u no_empty_cmd_completion +shopt -u nocaseglob +shopt -u nocasematch +shopt -u nullglob +shopt -u restricted_shell +shopt -u shift_verbose +shopt -u xpg_echo +-- +cdable_vars off +checkhash off +checkwinsize off +dotglob off +execfail off +extdebug off +extglob off +failglob off +gnu_errfmt off +histappend off +histreedit off +histverify off +huponexit off +lithist off +login_shell off +mailwarn off +no_empty_cmd_completion off +nocaseglob off +nocasematch off +nullglob off +restricted_shell off +shift_verbose off +xpg_echo off +-- +set +o allexport +set -o braceexpand +set -o emacs +set +o errexit +set +o errtrace +set +o functrace +set -o hashall +set -o histexpand +set -o history +set +o ignoreeof +set -o interactive-comments +set +o keyword +set -o monitor +set +o noclobber +set +o noexec +set +o noglob +set +o nolog +set +o notify +set +o nounset +set +o onecmd +set +o physical +set +o pipefail +set +o posix +set -o privileged +set +o verbose +set +o vi +set +o xtrace +-- +allexport off +braceexpand on +emacs on +errexit off +errtrace off +functrace off +hashall on +histexpand on +history on +ignoreeof off +interactive-comments on +keyword off +monitor on +noclobber off +noexec off +noglob off +nolog off +notify off +nounset off +onecmd off +physical off +pipefail off +posix off +privileged on +verbose off +vi off +xtrace off +-- +set +o allexport +set -o braceexpand +set -o emacs +set +o errexit +set +o errtrace +set +o functrace +set -o hashall +set -o histexpand +set -o history +set +o ignoreeof +set -o interactive-comments +set +o keyword +set -o monitor +set +o noclobber +set +o noexec +set +o noglob +set +o nolog +set +o notify +set +o nounset +set +o onecmd +set +o physical +set +o pipefail +set +o posix +set -o privileged +set +o verbose +set +o vi +set +o xtrace +-- +set -o history +set +o verbose +-- +set -o braceexpand +set -o emacs +set -o hashall +set -o histexpand +set -o history +set -o interactive-comments +set -o monitor +set -o privileged +-- +set +o allexport +set +o errexit +set +o errtrace +set +o functrace +set +o ignoreeof +set +o keyword +set +o noclobber +set +o noexec +set +o noglob +set +o nolog +set +o notify +set +o nounset +set +o onecmd +set +o physical +set +o pipefail +set +o posix +set +o verbose +set +o vi +set +o xtrace +-- +allexport off +errexit off +errtrace off +functrace off +ignoreeof off +keyword off +noclobber off +noexec off +noglob off +nolog off +notify off +nounset off +onecmd off +physical off +pipefail off +posix off +verbose off +vi off +xtrace off +-- +./shopt.tests: line 93: shopt: xyz1: invalid shell option name +./shopt.tests: line 94: shopt: xyz1: invalid option name diff --git a/tests/shopt.tests b/tests/shopt.tests new file mode 100644 index 0000000..d4f2a8b --- /dev/null +++ b/tests/shopt.tests @@ -0,0 +1,94 @@ +# let's try an error message first +shopt -z + +# first, set up a known environment +shopt -u cdable_vars +shopt -s cdspell +shopt -u checkhash +shopt -u checkwinsize +shopt -s cmdhist +shopt -u dotglob +shopt -u execfail +shopt -s expand_aliases +shopt -u extglob +shopt -u histreedit +shopt -u histappend +shopt -u histverify +shopt -s hostcomplete +shopt -u huponexit +shopt -s interactive_comments +shopt -u lithist +shopt -u mailwarn +shopt -u nocaseglob +shopt -u nullglob +shopt -s promptvars +shopt -u shift_verbose +shopt -s sourcepath +shopt -u xpg_echo + +# Now, start checking the output +builtin printf -- "--\n" +shopt -p # list 'em all +builtin printf -- "--\n" +# test specific variables +shopt -p huponexit +shopt -p checkwinsize +shopt -p sourcepath + +builtin printf -- "--\n" +shopt -s -p +builtin printf -- "--\n" +shopt -u -p +builtin printf -- "--\n" +shopt -u + +# Now set up another known environment +set +o allexport +set -o braceexpand +set +o errexit +set -o hashall +set -o histexpand +set +o keyword +set -o monitor +set +o noclobber +set +o noexec +set +o noglob +set +o notify +set +o nounset +set +o onecmd +set +o physical +set -o privileged +set +o verbose +set +o xtrace +set -o history +set +o ignoreeof +set -o interactive-comments +set +o posix +set -o emacs +set +o vi + +# list 'em all +builtin printf -- "--\n" +shopt -o -p + +builtin printf -- "--\n" +set -o +builtin printf -- "--\n" +set +o + +# test specific variables +builtin printf -- "--\n" +shopt -p -o history +shopt -p -o verbose + +builtin printf -- "--\n" +shopt -s -p -o +builtin printf -- "--\n" +shopt -u -p -o +builtin printf -- "--\n" +shopt -u -o + +# errors +builtin printf -- "--\n" +shopt -p xyz1 +shopt -o -p xyz1 diff --git a/tests/source1.sub b/tests/source1.sub new file mode 100644 index 0000000..8b8586f --- /dev/null +++ b/tests/source1.sub @@ -0,0 +1 @@ +echo $AVAR diff --git a/tests/source2.sub b/tests/source2.sub new file mode 100644 index 0000000..7a031a1 --- /dev/null +++ b/tests/source2.sub @@ -0,0 +1,5 @@ +echo in source.sub2, calling return + +return 5 + +echo oops -- return in source.sub2 failed diff --git a/tests/source3.sub b/tests/source3.sub new file mode 100644 index 0000000..4a12501 --- /dev/null +++ b/tests/source3.sub @@ -0,0 +1 @@ +echo "$@" diff --git a/tests/source4.sub b/tests/source4.sub new file mode 100644 index 0000000..717c1ab --- /dev/null +++ b/tests/source4.sub @@ -0,0 +1 @@ +set -- m n o p diff --git a/tests/source5.sub b/tests/source5.sub new file mode 100644 index 0000000..813ffae --- /dev/null +++ b/tests/source5.sub @@ -0,0 +1,19 @@ +LC_ALL=en_US +unset LC_ALL +unset LANG +export LC_ALL=C +export LANG=C + +set +o posix + +# attempting to source a non-existant file is not an error... +. /tmp/source-notthere + +echo after bad source 1 + +set -o posix + +# ...unless you're in posix mode +. /tmp/source-notthere + +echo after bad source 2 diff --git a/tests/strip.right b/tests/strip.right new file mode 100644 index 0000000..dfab897 --- /dev/null +++ b/tests/strip.right @@ -0,0 +1,12 @@ +'' +' ab ' +' ' +'' +'' +'' +'ababababababab' +'ababababababab ' +'ababababababab ' +'abababa +bababab ' +'' diff --git a/tests/strip.tests b/tests/strip.tests new file mode 100644 index 0000000..b669b52 --- /dev/null +++ b/tests/strip.tests @@ -0,0 +1,22 @@ +v=`echo "" ; echo "" ; echo ""` +echo "'$v'" +v=`echo -n " ab "` +echo "'$v'" +v=`echo -n " "` +echo "'$v'" +v=`echo -n ""` +echo "'$v'" +v=`echo ""` +echo "'$v'" +v=`echo` +echo "'$v'" +v=`echo ababababababab` +echo "'$v'" +v=`echo "ababababababab "` +echo "'$v'" +v=`echo -n "ababababababab "` +echo "'$v'" +v=`echo -ne "abababa\nbababab "` +echo "'$v'" +v="`echo -e '\n\n\n\n'`" +echo "'$v'" diff --git a/tests/test.right b/tests/test.right new file mode 100644 index 0000000..beb3af6 --- /dev/null +++ b/tests/test.right @@ -0,0 +1,284 @@ +t -a noexist +1 +t -a run-all +0 +t -b run-all +1 +t -b /dev/jb1a +1 +t -c run-all +1 +t -c /dev/tty +0 +t -d run-all +1 +t -d /etc +0 +t -d "" +1 +b -d "" +1 +t -e noexist +1 +t -e run-all +0 +t -f noexist +1 +t -f /dev/tty +1 +t -f run-all +0 +t -g run-all +1 +t -g /tmp/test.setgid +0 +t -k run-all +1 +t -n "" +1 +t -n "hello" +0 +t -p run-all +1 +t -r noexist +1 +t -r /tmp/test.noread +1 +t -r run-all +0 +t -s noexist +1 +t -s /dev/null +1 +t -s run-all +0 +t -t 20 +1 +t -t 0 +0 +t -u noexist +1 +t -u run-all +1 +t -u /tmp/test.setuid +0 +t -w noexist +1 +t -w /tmp/test.nowrite +1 +t -w /dev/null +0 +t -x noexist +1 +t -x /tmp/test.exec +0 +t -x /tmp/test.noexec +1 +t -z "" +0 +t -z "foo" +1 +t "foo" +0 +t "" +1 +t -O /tmp/test.owner +0 +t -S /tmp/test.socket +1 +t -N /tmp/test.newer +0 +t "hello" = "hello" +0 +t "hello" = "goodbye" +1 +t "hello" == "hello" +0 +t "hello" == "goodbye" +1 +t "hello" != "hello" +1 +t "hello" != "goodbye" +0 +t "hello" < "goodbye" +1 +t "hello" > "goodbye" +0 +t ! "hello" > "goodbye" +1 +t 200 -eq 200 +0 +t 34 -eq 222 +1 +t -32 -eq 32 +1 +t 200 -ne 200 +1 +t 34 -ne 222 +0 +t 200 -gt 200 +1 +t 340 -gt 222 +0 +t 200 -ge 200 +0 +t 34 -ge 222 +1 +t 200 -lt 200 +1 +t 34 -lt 222 +0 +t 200 -le 200 +0 +t 340 -le 222 +1 +t 700 -le 1000 -a -n "1" -a "20" = "20" +0 +t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \) +1 +t /tmp/abc -nt /tmp/def +1 +t /tmp/abc -ot /tmp/def +0 +t /tmp/def -nt /tmp/abc +0 +t /tmp/def -ot /tmp/abc +1 +t /tmp/abc -ef /tmp/def +1 +t /tmp/abc -ef /tmp/ghi +0 +t -r /dev/fd/0 +0 +t -w /dev/fd/1 +0 +t -w /dev/fd/2 +0 +t -r /dev/stdin +0 +t -w /dev/stdout +0 +t -w /dev/stderr +0 +t +1 +b +1 +t 12 -eq 34 +1 +t ! 12 -eq 34 +0 +t -n abcd -o aaa +0 +t -n abcd -o -z aaa +0 +t -n abcd -a aaa +0 +t -n abcd -a -z aaa +1 +t -o allexport +1 +t ! -o allexport +0 +t xx -a yy +0 +t xx -o "" +0 +t xx -a "" +1 +t -X -a -X +0 +t -X -o -X +0 +t -X -o "" +0 +t -X -a "" +1 +t "" -a -X +1 +t "" -o -X +0 +t "" -a "" +1 +t "" -o "" +1 +t true -o -X +0 +t true -a -X +0 +t ( -E ) +0 +t ( "" ) +1 +t ! -z "$z" +0 +t ! -n "$z" +1 +t "$zero" +1 +t ! "$zero" +0 +b "$zero" +1 +b ! "$zero" +0 +t -G /tmp/test.group +0 +t -h /tmp/test.symlink +0 +t 4+3 -eq 7 +./test.tests: line 13: test: 4+3: integer expression expected +2 +b 4-5 -eq 7 +./test.tests: line 7: [: 4+3: integer expression expected +2 +t 9 -eq 4+5 +./test.tests: line 13: test: 4+5: integer expression expected +2 +b 9 -eq 4+5 +./test.tests: line 7: [: 4+5: integer expression expected +2 +t A -eq 7 +./test.tests: line 13: test: A: integer expression expected +2 +b A -eq 7 +./test.tests: line 7: [: A: integer expression expected +2 +t 9 -eq B +./test.tests: line 13: test: B: integer expression expected +2 +b 9 -eq B +./test.tests: line 7: [: B: integer expression expected +2 +t ( 1 = 2 +./test.tests: line 13: test: `)' expected +2 +b ( 1 = 2 +./test.tests: line 7: [: `)' expected, found ] +2 +./test.tests: line 13: test: a: unary operator expected +2 +./test.tests: line 13: test: b: binary operator expected +2 +./test.tests: line 13: test: -A: unary operator expected +2 +./test.tests: line 13: test: too many arguments +2 +./test.tests: line 13: test: too many arguments +2 +./test.tests: line 406: [: missing `]' +2 +./test.tests: line 13: test: (: unary operator expected +2 +t -t a +1 +t -t addsds +1 +t -t 42 +1 +t -t /dev/tty +1 +t -t /dev/tty4 +1 +t -t /dev/tty4444444... +1 diff --git a/tests/test.tests b/tests/test.tests new file mode 100644 index 0000000..a915c4e --- /dev/null +++ b/tests/test.tests @@ -0,0 +1,423 @@ +if (( $UID == 0 )); then + echo "test-tests: the test suite should not be run as root" >&2 +fi + +b() +{ + [ "$@" ] + echo $? +} + +t() +{ + test "$@" + echo $? +} + +echo 't -a noexist' +t -a noexist +echo 't -a run-all' +t -a run-all + +echo 't -b run-all' +t -b run-all +echo 't -b /dev/jb1a' +t -b /dev/jb1a + +echo 't -c run-all' +t -c run-all +echo 't -c /dev/tty' +t -c /dev/tty + +echo 't -d run-all' +t -d run-all +echo 't -d /etc' +t -d /etc +echo 't -d ""' +t -d "" +echo 'b -d ""' +b -d "" + +echo 't -e noexist' +t -e noexist +echo 't -e run-all' +t -e run-all + +echo 't -f noexist' +t -f noexist +echo 't -f /dev/tty' +t -f /dev/tty +echo 't -f run-all' +t -f run-all + +echo 't -g run-all' +t -g run-all + +touch /tmp/test.setgid +chgrp ${GROUPS[0]} /tmp/test.setgid +chmod ug+x /tmp/test.setgid +chmod g+s /tmp/test.setgid +echo 't -g /tmp/test.setgid' +t -g /tmp/test.setgid +rm -f /tmp/test.setgid + +echo 't -k run-all' +t -k run-all + +echo 't -n ""' +t -n "" +echo 't -n "hello"' +t -n "hello" + +echo 't -p run-all' +t -p run-all + +echo 't -r noexist' +t -r noexist + +if (( $UID != 0 )); then + touch /tmp/test.noread + chmod a-r /tmp/test.noread + echo 't -r /tmp/test.noread' + t -r /tmp/test.noread + rm -f /tmp/test.noread +else + echo 't -r /tmp/test.noread' + echo 1 +fi + +echo 't -r run-all' +t -r run-all + +echo 't -s noexist' +t -s noexist +echo 't -s /dev/null' +t -s /dev/null +echo 't -s run-all' +t -s run-all + +echo 't -t 20' +t -t 20 +echo 't -t 0' +t -t 0 < /dev/tty + +echo 't -u noexist' +t -u noexist + +echo 't -u run-all' +t -u run-all + +touch /tmp/test.setuid +chmod u+x /tmp/test.setuid # some systems require this to turn on setuid bit +chmod u+s /tmp/test.setuid +echo 't -u /tmp/test.setuid' +t -u /tmp/test.setuid +rm -f /tmp/test.setuid + +echo 't -w noexist' +t -w noexist + +if (( $UID != 0 )); then + touch /tmp/test.nowrite + chmod a-w /tmp/test.nowrite + echo 't -w /tmp/test.nowrite' + t -w /tmp/test.nowrite + rm -f /tmp/test.nowrite +else + echo 't -w /tmp/test.nowrite' + echo 1 +fi + +echo 't -w /dev/null' +t -w /dev/null + +echo 't -x noexist' +t -x noexist + +touch /tmp/test.exec +chmod u+x /tmp/test.exec +echo 't -x /tmp/test.exec' +t -x /tmp/test.exec +rm -f /tmp/test.exec + +touch /tmp/test.noexec +chmod u-x /tmp/test.noexec +echo 't -x /tmp/test.noexec' +t -x /tmp/test.noexec +rm -f /tmp/test.noexec + +echo 't -z ""' +t -z "" +echo 't -z "foo"' +t -z "foo" + +echo 't "foo"' +t "foo" +echo 't ""' +t "" + +touch /tmp/test.owner +echo 't -O /tmp/test.owner' +t -O /tmp/test.owner +rm -f /tmp/test.owner + +touch /tmp/test.socket +echo 't -S /tmp/test.socket' +t -S /tmp/test.socket # false +rm -f /tmp/test.socket + +touch /tmp/test.newer +echo 't -N /tmp/test.newer' +t -N /tmp/test.newer +rm -f /tmp/test.newer + +echo 't "hello" = "hello"' +t "hello" = "hello" +echo 't "hello" = "goodbye"' +t "hello" = "goodbye" + +echo 't "hello" == "hello"' +t "hello" == "hello" +echo 't "hello" == "goodbye"' +t "hello" == "goodbye" + +echo 't "hello" != "hello"' +t "hello" != "hello" +echo 't "hello" != "goodbye"' +t "hello" != "goodbye" + +echo 't "hello" < "goodbye"' +t "hello" \< "goodbye" +echo 't "hello" > "goodbye"' +t "hello" \> "goodbye" + +echo 't ! "hello" > "goodbye"' +t "! hello" \> "goodbye" + +echo 't 200 -eq 200' +t 200 -eq 200 +echo 't 34 -eq 222' +t 34 -eq 222 +echo 't -32 -eq 32' +t -32 -eq 32 + +echo 't 200 -ne 200' +t 200 -ne 200 +echo 't 34 -ne 222' +t 34 -ne 222 + +echo 't 200 -gt 200' +t 200 -gt 200 +echo 't 340 -gt 222' +t 340 -gt 222 + +echo 't 200 -ge 200' +t 200 -ge 200 +echo 't 34 -ge 222' +t 34 -ge 222 + +echo 't 200 -lt 200' +t 200 -lt 200 +echo 't 34 -lt 222' +t 34 -lt 222 + +echo 't 200 -le 200' +t 200 -le 200 +echo 't 340 -le 222' +t 340 -le 222 + +echo 't 700 -le 1000 -a -n "1" -a "20" = "20"' +t 700 -le 1000 -a -n "1" -a "20" = "20" +echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)' +t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \) + +touch /tmp/abc +sleep 2 +touch /tmp/def + +echo 't /tmp/abc -nt /tmp/def' +t /tmp/abc -nt /tmp/def +echo 't /tmp/abc -ot /tmp/def' +t /tmp/abc -ot /tmp/def +echo 't /tmp/def -nt /tmp/abc' +t /tmp/def -nt /tmp/abc +echo 't /tmp/def -ot /tmp/abc' +t /tmp/def -ot /tmp/abc + +echo 't /tmp/abc -ef /tmp/def' +t /tmp/abc -ef /tmp/def +ln /tmp/abc /tmp/ghi +echo 't /tmp/abc -ef /tmp/ghi' +t /tmp/abc -ef /tmp/ghi + +rm /tmp/abc /tmp/def /tmp/ghi + +echo 't -r /dev/fd/0' +t -r /dev/fd/0 +echo 't -w /dev/fd/1' +t -w /dev/fd/1 +echo 't -w /dev/fd/2' +t -w /dev/fd/2 + +echo 't -r /dev/stdin' +t -r /dev/stdin +echo 't -w /dev/stdout' +t -w /dev/stdout +echo 't -w /dev/stderr' +t -w /dev/stderr + +echo 't' +t +echo 'b' +b + +echo 't 12 -eq 34' +t 12 -eq 34 +echo 't ! 12 -eq 34' +t ! 12 -eq 34 + +echo 't -n abcd -o aaa' +t -n abcd -o aaa +echo 't -n abcd -o -z aaa' +t -n abcd -o -z aaa + +echo 't -n abcd -a aaa' +t -n abcd -a aaa +echo 't -n abcd -a -z aaa' +t -n abcd -a -z aaa + +set +o allexport +echo 't -o allexport' +t -o allexport +echo 't ! -o allexport' +t ! -o allexport + +echo 't xx -a yy' +t xx -a yy +echo 't xx -o ""' +t xx -o "" +echo 't xx -a ""' +t xx -a "" + +echo 't -X -a -X' +t -X -a -X +echo 't -X -o -X' +t -X -o -X +echo 't -X -o ""' +t -X -o "" +echo 't -X -a ""' +t -X -a "" +echo 't "" -a -X' +t "" -a -X +echo 't "" -o -X' +t "" -o -X +echo 't "" -a ""' +t "" -a "" +echo 't "" -o ""' +t "" -o "" +echo 't true -o -X' +t true -o -X +echo 't true -a -X' +t true -a -X + +echo 't ( -E )' +t \( -E \) +echo 't ( "" )' +t \( "" \) + +z=42 + +echo 't ! -z "$z"' +t ! -z "$z" + +echo 't ! -n "$z"' +t ! -n "$z" + +zero= +echo 't "$zero"' +t "$zero" +echo 't ! "$zero"' +t ! "$zero" +echo 'b "$zero"' +b "$zero" +echo 'b ! "$zero"' +b ! "$zero" + +touch /tmp/test.group +chgrp ${GROUPS[0]} /tmp/test.group +echo 't -G /tmp/test.group' +t -G /tmp/test.group +rm /tmp/test.group + +case "${THIS_SH}" in +/*) SHNAME=${THIS_SH} ;; +*) SHNAME=${PWD}/${THIS_SH} ;; +esac + +if ln -s ${SHNAME} /tmp/test.symlink 2>/dev/null; then + chgrp ${GROUPS[0]} /tmp/test.symlink 2>/dev/null + echo 't -h /tmp/test.symlink' + t -h /tmp/test.symlink + # some systems don't let you remove this + rm -f /tmp/test.symlink 2>/dev/null +else + echo 't -h /tmp/test.symlink' + echo 0 +fi + +# arithmetic constant errors +echo "t 4+3 -eq 7" +t 4+3 -eq 7 +echo "b 4-5 -eq 7" +b 4+3 -eq 7 + +echo "t 9 -eq 4+5" +t 9 -eq 4+5 +echo "b 9 -eq 4+5" +b 9 -eq 4+5 + +A=7 +echo "t A -eq 7" +t A -eq 7 +echo "b A -eq 7" +b A -eq 7 + +B=9 +echo "t 9 -eq B" +t 9 -eq B +echo "b 9 -eq B" +b 9 -eq B + +# badly formed expressions +echo 't ( 1 = 2' +t \( 1 = 2 +echo 'b ( 1 = 2' +b \( 1 = 2 + +# more errors +t a b +t a b c +t -A v +# too many arguments -- argument expected is also reasonable +t 4 -eq 4 -a 2 -ne 5 -a 4 -ne +# too many arguments +t 4 -eq 4 -a 3 4 + +[ +echo $? + +t \( \) + +# non-numeric arguments to `test -t' should return failure -- fix in 2.05 +echo 't -t a' +t -t a +echo 't -t addsds' +t -t addsds +echo 't -t 42' +t -t 42 +echo 't -t /dev/tty' +t -t /dev/tty +echo 't -t /dev/tty4' +t -t /dev/tty4 +echo 't -t /dev/tty4444444...' +t -t /dev/tty4444444... diff --git a/tests/tilde.right b/tests/tilde.right new file mode 100644 index 0000000..b22dabf --- /dev/null +++ b/tests/tilde.right @@ -0,0 +1,24 @@ +~chet +/usr/xyz/foo +~chet/foo +~chet/foo +~chet/bar +~chet/bar +~chet/bar +:~chet/ +abcd~chet +SHELL=~/bash +/usr/xyz/bash +abcd:~chet +/usr/ucb:/bin:/usr/xyz/bin:/usr/xyz/tmp/bin:/usr/bin +/usr +/tmp +/bin:/usr/bin:.:/usr/xyz/bin +/bin:/usr/bin:.:~/bin +/bin:/usr/bin:.:/usr/xyz/bin +/bin:/usr/bin:.:/usr/xyz/bin +/bin:/usr/bin:.:~/bin +/bin:/usr/bin:.:~/bin +ok 1 +ok 2 +ok 3 diff --git a/tests/tilde.tests b/tests/tilde.tests new file mode 100644 index 0000000..f5f5309 --- /dev/null +++ b/tests/tilde.tests @@ -0,0 +1,66 @@ +# 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, +# the next-to-last test fails +set +o posix + +HOME=/usr/xyz +SHELL=~/bash +echo ~ch\et +echo ~/"foo" +echo "~chet"/"foo" +echo \~chet/"foo" +echo \~chet/bar +echo ~\chet/bar +echo ~chet""/bar +echo ":~chet/" +echo abcd~chet +echo "SHELL=~/bash" +echo $SHELL +echo abcd:~chet +path=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin +echo $path + +cd /usr +cd /tmp +echo ~- +echo ~+ + +XPATH=/bin:/usr/bin:. + +# yes tilde expansion +PPATH=$XPATH:~/bin +echo "$PPATH" + +# no tilde expansion +PPATH="$XPATH:~/bin" +echo "$PPATH" + +# yes tilde expansion +export PPATH=$XPATH:~/bin +echo "$PPATH" +declare -x PPATH=$XPATH:~/bin +echo "$PPATH" + +# no tilde expansion +export PPATH="$XPATH:~/bin" +echo "$PPATH" +declare -x PPATH="$XPATH:~/bin" +echo "$PPATH" + +# more tests of tilde expansion when executing case commands +case ~ in +$HOME) echo ok 1;; +*) echo bad 1 ;; +esac + +case ~ in +~) echo ok 2 ;; +\~) echo bad 2a ;; +*) echo bad 2b ;; +esac + +case $unset in +"") echo ok 3 ;; +*) echo bad 3 ;; +esac diff --git a/tests/tilde2.right b/tests/tilde2.right new file mode 100644 index 0000000..fce0468 --- /dev/null +++ b/tests/tilde2.right @@ -0,0 +1,24 @@ +PATH=~/bin:/bin:/usr/bin:. +/usr/xyz/bin:~/bin2:/bin:/usr/bin:. +PATH=~/bin:~/bin2:/bin:/usr/bin:. +~/bin +~ +/usr/xyz +~ +~ +~ +argv[1] = <\a> +argv[1] = <\a> +/usr/xyz/bash +ok +~ +~ +make -k FOO=/usr/xyz/mumble +/usr/xyz/mumble +HOME=~ +HOME=~ +/usr/$x/abc +HOME=~ +/usr/$x/abc +HOME=/usr/$x/abc +/usr/$x/abc diff --git a/tests/tilde2.tests b/tests/tilde2.tests new file mode 100644 index 0000000..ff6c76f --- /dev/null +++ b/tests/tilde2.tests @@ -0,0 +1,70 @@ +HOME=/usr/xyz +XPATH=/bin:/usr/bin:. + +ADDPATH=PATH=~/bin:$XPATH + +echo $ADDPATH + +unset ADDPATH +: ${ADDPATH:=~/bin:~/bin2:$XPATH} +echo $ADDPATH + +unset ADDPATH +: ${ADDPATH:=PATH=~/bin:~/bin2:$XPATH} +echo $ADDPATH + +cat << ! +~/bin +! + +echo "~" + +echo ${TPATH:-~} +echo "${TPATH:-~}" +echo "${TPATH:-"~"}" + +echo "${XPATH+~}" + +recho "\a" +recho "${TPATH:-\a}" + +SHELL=~/bash +echo $SHELL + +case $SHELL in +~/bash) echo ok;; +*) echo bad;; +esac + +somevar= +echo "${somevar:-~}" +echo "${somevar:-"~"}" + +echo make -k FOO=~/mumble + +typeset FOO=~/mumble +echo "$FOO" + +h=HOME=~ +echo $h + +export h=HOME=~ +echo $h + +x=1234 +HOME='/usr/$x/abc' + +echo ~ + +# behavior differs here in posix mode +set -o posix + +eval echo $h +eval $h +echo $HOME + +set +o posix + +eval echo $h +eval $h +echo $HOME diff --git a/tests/trap.right b/tests/trap.right new file mode 100644 index 0000000..72f3b6d --- /dev/null +++ b/tests/trap.right @@ -0,0 +1,74 @@ +subshell exit +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +[20] debug +debug line +[22] debug +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- 'echo [$LINENO] debug' DEBUG +[24] debug +func[16] funcdebug +funcdebug line +[26] debug +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- 'echo [$LINENO] debug' DEBUG +[28] debug +./trap.tests[33] debug +./trap.tests[34] debug +func2[30] debug +func2[31] debug +func2debug line +./trap.tests[36] debug +./trap.tests[38] debug +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- '' DEBUG +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- 'echo exiting' EXIT +trap -- '' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +0 +ERRTRAP +ERRTRAP +ERRTRAP +after falses +if negation ok +after negation +after while +before false in trap2a.sub +after false in trap2a.sub +command substitution +caught a child death +caught a child death +caught a child death +trap -- 'echo caught a child death' SIGCHLD +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo caught a child death' SIGCHLD +trap -- '' SIGUSR2 +exiting diff --git a/tests/trap.tests b/tests/trap.tests new file mode 100644 index 0000000..9aac725 --- /dev/null +++ b/tests/trap.tests @@ -0,0 +1,86 @@ +# test the trap code + +trap 'echo exiting' 0 +trap 'echo aborting' 1 2 3 6 15 + +# make sure a user-specified subshell runs the exit trap, but does not +# inherit the exit trap from a parent shell +( trap 'echo subshell exit' 0; exit 0 ) +( exit 0 ) + +trap + +func() +{ + trap 'echo ${FUNCNAME:-$0}[$LINENO] funcdebug' DEBUG + echo funcdebug line +} + +trap 'echo [$LINENO] debug' DEBUG +echo debug line + +trap + +func + +trap + +trap 'echo ${FUNCNAME:-$0}[$LINENO] debug' DEBUG +func2() +{ + echo func2debug line +} +declare -ft func2 +func2 + +unset -f func2 + +trap '' DEBUG + +trap + +trap - debug + +trap + +trap - HUP +trap hup +trap '' INT +trap '' int + +trap + +# exit 0 in exit trap should set exit status +( +set -e +trap 'exit 0' EXIT +false +echo bad +) +echo $? + +# hmmm...should this set the handling to SIG_IGN for children, too? +trap '' USR2 +./trap1.sub + +# test ERR trap +./trap2.sub + +# +# show that setting a trap on SIGCHLD is not disastrous. +# +set -o monitor + +trap 'echo caught a child death' SIGCHLD + +sleep 7 & sleep 6 & sleep 5 & + +wait + +trap -p SIGCHLD + +# Now reset some of the signals the shell handles specially back to +# their default values (with or without the SIG prefix) +trap - SIGINT QUIT TERM + +trap diff --git a/tests/trap1.sub b/tests/trap1.sub new file mode 100755 index 0000000..48f8530 --- /dev/null +++ b/tests/trap1.sub @@ -0,0 +1,4 @@ +# signals ignored at shell startup cannot be trapped or reset +trap 'echo USR2' USR2 + +trap -p USR2 diff --git a/tests/trap2.sub b/tests/trap2.sub new file mode 100755 index 0000000..73357df --- /dev/null +++ b/tests/trap2.sub @@ -0,0 +1,25 @@ +set +e +trap 'echo ERRTRAP' ERR + +false +false +false + +echo after falses + +if ! false; then + echo if negation ok +fi + +! false +echo after negation + +while false; do + echo while negation ok +done + +echo after while + +./trap2a.sub + +echo $(false ; echo command substitution) diff --git a/tests/trap2a.sub b/tests/trap2a.sub new file mode 100755 index 0000000..44d6b50 --- /dev/null +++ b/tests/trap2a.sub @@ -0,0 +1,3 @@ +echo before false in trap2a.sub +false +echo after false in trap2a.sub diff --git a/tests/type.right b/tests/type.right new file mode 100644 index 0000000..dbd51ca --- /dev/null +++ b/tests/type.right @@ -0,0 +1,48 @@ +./type.tests: line 9: type: -r: invalid option +type: usage: type [-afptP] name [name ...] +./type.tests: line 12: type: notthere: not found +function +keyword +builtin +file +file +file +func is a function +func () +{ + echo this is func +} +while is a shell keyword +while is a shell keyword +builtin is a shell builtin +/bin/sh is /bin/sh +func +func is a function +func () +{ + echo this is func +} +while +while is a shell keyword +./type.tests: line 43: type: m: not found +alias m='more' +alias m='more' +m is aliased to `more' +alias +alias m='more' +alias m='more' +alias m='more' +m is aliased to `more' +builtin +builtin is a shell builtin +/bin/sh +/bin/sh is /bin/sh +./type.tests: line 65: type: func: not found +./type.tests: line 67: type: m: not found +/bin/sh +/tmp/bash +bash is hashed (/tmp/bash) +file +hits command + 3 /tmp/bash + 1 /bin/sh diff --git a/tests/type.tests b/tests/type.tests new file mode 100644 index 0000000..d47ae64 --- /dev/null +++ b/tests/type.tests @@ -0,0 +1,82 @@ +set +o posix + +hash -r +unalias -a + +# this should echo nothing +type +# this should be a usage error +type -r ${THIS_SH} + +# these should behave identically +type notthere +command -v notthere + +alias m=more + +unset -f func 2>/dev/null +func() { echo this is func; } + +type -t func +type -t while +type -t builtin +type -t /bin/sh +type -t ${THIS_SH} +type -t mv + +type func +# the following two should produce identical output +type while +type -a while +type builtin +type /bin/sh + +command -v func +command -V func +command -v while +command -V while + +# the following two lines should produce the same output +# post-3.0 patch makes command -v silent, as posix specifies +# first test with alias expansion off (should all fail or produce no output) +type -t m +type m +command -v m +alias -p +alias m + +# then test with alias expansion on +shopt -s expand_aliases +type m +type -t m +command -v m +alias -p +alias m + +command -V m +shopt -u expand_aliases + +command -v builtin +command -V builtin +command -v /bin/sh +command -V /bin/sh + +unset -f func +type func +unalias m +type m + +hash -r + +hash -p /bin/sh sh +type -p sh + +SHBASE=${THIS_SH##*/} +hash -p /tmp/$SHBASE $SHBASE +type -p $SHBASE +type $SHBASE + +type -t $SHBASE + +# make sure the hash table looks right +hash diff --git a/tests/varenv.right b/tests/varenv.right new file mode 100644 index 0000000..df8086d --- /dev/null +++ b/tests/varenv.right @@ -0,0 +1,56 @@ +3 4 +5 6 7 8 9 +7 8 9 +/usr/chet +/usr/chet +/usr/chet +/a/b/c +/usr/chet +/usr/chet 7 +/a/b/c 9 /a/b/c +/a/b/c 9 /a/b/c +/a/b/c /a/b/c +1 2 +1 1 +unset +toronto airport +AVAR +song by rush +BVAR +toronto airport +AVAR +AVAR +42 +/bin:/usr/bin:/usr/local/bin:. +avar=([0]="/bin:/usr/bin:/usr/local/bin:.") +z=yy +42 +declare -i ivar="10" +unset +declare -x ivar="42" +hB +braceexpand:hashall:interactive-comments +hBP +braceexpand:hashall:interactive-comments:physical +declare -r SHELLOPTS="braceexpand:hashall:interactive-comments:physical" +abcde +20 +30 +40 +50 +|0|10| +10 +|0|10| +10 +|0|10| +10 +|4| +4 +|0|11| +after fff3: x=4 +|0|12| +|y| +|y| +a=z +a=b +a=z diff --git a/tests/varenv.sh b/tests/varenv.sh new file mode 100644 index 0000000..77776f9 --- /dev/null +++ b/tests/varenv.sh @@ -0,0 +1,206 @@ +# +# varenv.sh +# +# Test the behavior of the shell with respect to variable and environment +# assignments +# +expect() +{ + echo expect "$@" +} + +a=1 +b=2 +c=3 +d=4 +e=5 +f=6 g=7 h=8 + +a=3 b=4 $CHMOD $MODE $FN + +# This should echo "3 4" according to Posix.2 +expect "3 4" +echo $a $b + +set -k + +# Assignment statements made when no words are left affect the shell's +# environment +a=5 b=6 $CHMOD c=7 $MODE d=8 $FN e=9 + +expect "5 6 7 8 9" +echo $a $b $c $d $e + +$CHMOD f=7 $MODE g=8 $FN h=9 +expect "7 8 9" +echo $f $g $h + +set +k + +# The temporary environment does not affect variable expansion, only the +# environment given to the command + +export HOME=/usr/chet +expect $HOME +echo $HOME + +expect $HOME +HOME=/a/b/c /bin/echo $HOME + +expect $HOME +echo $HOME + +# This should echo /a/b/c +expect /a/b/c +HOME=/a/b/c printenv HOME + +set -k + +# This should echo $HOME 9, NOT /a/b/c 9 + +expect "$HOME" +HOME=/a/b/c /bin/echo $HOME c=9 +expect "$HOME 7" +echo $HOME $c + +# I claim the next two echo calls should give identical output. +# ksh agrees, the System V.3 sh does not + +expect "/a/b/c 9 /a/b/c" +HOME=/a/b/c $ECHO a=$HOME c=9 +echo $HOME $c $a + +expect "/a/b/c 9 /a/b/c" +HOME=/a/b/c a=$HOME c=9 +echo $HOME $c $a +set +k + +# How do assignment statements affect subsequent assignments on the same +# line? +expect "/a/b/c /a/b/c" +HOME=/a/b/c a=$HOME +echo $HOME $a + +# The system V.3 sh does this wrong; the last echo should output "1 1", +# but the system V.3 sh has it output "2 2". Posix.2 says the assignment +# statements are processed left-to-right. bash and ksh output the right +# thing +c=1 +d=2 +expect "1 2" +echo $c $d +d=$c c=$d +expect "1 1" +echo $c $d + +# just for completeness +unset d c +expect unset +echo ${d-unset} + +# no output +export a +a=bcde +export a +/bin/true 2>/dev/null + +func() +{ + local YYZ + + YYZ="song by rush" + echo $YYZ + echo $A +} + +YYZ="toronto airport" +A="AVAR" +echo $YYZ +echo $A +A=BVAR func +echo $YYZ +echo $A + +export A +# Make sure expansion doesn't use assignment statements preceding a builtin +A=ZVAR echo $A + +XPATH=/bin:/usr/bin:/usr/local/bin:. +func2() +{ + local z=yy + local -a avar=( ${XPATH//: } ) + echo ${avar[@]} + local +} + +avar=42 +echo $avar +func2 +echo $avar + +# try to set an attribute for an unset variable; make sure it persists +# when the variable is assigned a value +declare -i ivar + +ivar=10 + +declare -p ivar +unset ivar + +# export an unset variable, make sure it is not suddenly set, but make +# sure the export attribute persists when the variable is assigned a +# value +export ivar +echo ${ivar-unset} + +ivar=42 +declare -p ivar + +# make sure set [-+]o ignoreeof and $IGNOREEOF are reflected +unset IGNOREEOF +set +o ignoreeof +set -o ignoreeof +if [ "$IGNOREEOF" -ne 10 ]; then + echo "./varenv.sh: set -o ignoreeof is not reflected in IGNOREEOF" >&2 +fi +unset IGNOREEOF +set +o ignoreeof + +# older versions of bash used to not reset RANDOM in subshells correctly +[[ $RANDOM -eq $(echo $RANDOM) ]] && echo "RANDOM: problem with subshells" + +# make sure that shopt -o is reflected in $SHELLOPTS +# first, get rid of things that might be set automatically via shell +# variables +set +o posix +set +o ignoreeof +set +o monitor +echo $- +echo ${SHELLOPTS} +shopt -so physical +echo $- +echo ${SHELLOPTS} + +# and make sure it is readonly +readonly -p | grep SHELLOPTS + +# This was an error in bash versions prior to bash-2.04. The `set -a' +# should cause the assignment statement that's an argument to typeset +# to create an exported variable +unset FOOFOO +FOOFOO=bar +set -a +typeset FOOFOO=abcde + +printenv FOOFOO + +# test out export behavior of variable assignments preceding builtins and +# functions +$THIS_SH ./varenv1.sub + +# more tests; bugs in bash up to version 2.05a +$THIS_SH ./varenv2.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/varenv1.sub b/tests/varenv1.sub new file mode 100644 index 0000000..168f87b --- /dev/null +++ b/tests/varenv1.sub @@ -0,0 +1,28 @@ +# test out the export behavior of variable assignments preceding `eval', `.' +# and shell functions + +func() +{ + printenv var +} + +export var=10 +echo expect 20 +var=20 eval printenv var + +: ${TMPDIR:=/tmp} +TMPFILE=$TMPDIR/evalsub.$$ + +rm -f $TMPFILE +echo 'printenv var' > $TMPFILE + +echo expect 30 +var=30 . $TMPFILE + +rm -f $TMPFILE + +echo expect 40 +var=40 func + +echo expect 50 +var=50 command printenv var diff --git a/tests/varenv2.sub b/tests/varenv2.sub new file mode 100644 index 0000000..b293572 --- /dev/null +++ b/tests/varenv2.sub @@ -0,0 +1,44 @@ +fff() +{ + typeset i=0 x=10 + echo "|$i|$x|" + export x + printenv x +} + +fff2() +{ + echo "|$x|" + export x + printenv x +} + +fff3() +{ + typeset i=0 x="${x-10}" + echo "|$i|$x|" +} + +fff4() +{ + typeset i=0 x + x="${x-10}" + echo "|$i|$x|" +} + +fff5() +{ + z=y typeset z + echo "|$z|" +} + +fff +x=10 fff +x=1 fff +x=4 fff2 +x=11 fff3 +echo after fff3: x=$x +x=12 fff4 + +fff5 +z=42 fff5 diff --git a/tests/version b/tests/version new file mode 100644 index 0000000..bd74020 --- /dev/null +++ b/tests/version @@ -0,0 +1,8 @@ +echo Testing ${THIS_SH} + +echo version: $BASH_VERSION +echo versinfo: ${BASH_VERSINFO[@]} + +echo HOSTTYPE = $HOSTTYPE +echo OSTYPE = $OSTYPE +echo MACHTYPE = $MACHTYPE diff --git a/tests/version.mini b/tests/version.mini new file mode 100644 index 0000000..72e4bf9 --- /dev/null +++ b/tests/version.mini @@ -0,0 +1,8 @@ +echo Testing ${THIS_SH} + +echo version: $BASH_VERSION +#echo versinfo: ${BASH_VERSINFO[@]} + +echo HOSTTYPE = $HOSTTYPE +echo OSTYPE = $OSTYPE +echo MACHTYPE = $MACHTYPE |