######################################################################## # # # This software is part of the ast package # # Copyright (c) 1982-2011 AT&T Intellectual Property # # and is licensed under the # # Eclipse Public License, Version 1.0 # # by AT&T Intellectual Property # # # # A copy of the License is available at # # http://www.eclipse.org/org/documents/epl-v10.html # # (with md5 checksum b35adb5213ca9657e911e9befb180842) # # # # Information and Software Systems Research # # AT&T Research # # Florham Park NJ # # # # David Korn # # # ######################################################################## # # Written by Roland Mainz # function err_exit { print -u2 -n "\t" print -u2 -r ${Command}[$1]: "${@:2}" (( Errors < 127 && Errors++ )) } alias err_exit='err_exit $LINENO' set -o nounset Command=${0##*/} integer Errors=0 typeset -T test_t=( typeset name typeset cmd typeset expected_output ) function testfunc { integer line_number=$1 typeset cmd="$2" typeset expected_output="$3" typeset output output="$($SHELL -c "${cmd}" 2>&1 )" [[ "${output}" == "${expected_output}" ]] || err_exit ${line_number} "${output} != ${expected_output}" } # test1: basic tests function test1 { # string testfunc ${LINENO} '(function l { typeset -S x ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true)' "###" testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true' ">###" testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; (l false) ; l true' ">##" testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false; ( ulimit -c 0 ; l false) ; l true' ">##" # integer # (normal) testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3" testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2" # (int) testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3" testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2" # (short) testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3" testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2" # float testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; l false ; l true )' "2" testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "1.5" return 0 } # test2: test the more complex datatypes function test2 { compound out=( typeset stdout stderr ; integer res ) integer i test_t -r -a tests=( ( name='compound' cmd=$' function l { compound -S s=( integer a=1 integer b=2 ) (( s.a++, s.b++ )) $1 && printf "a=%d, b=%d\n" s.a s.b } (l false ; l false ; l true ; printf ";") (l false ; l false ; l true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='compound_nameref' cmd=$' function l_n { nameref sn=$2 (( sn.a++, sn.b++ )) $1 && printf "a=%d, b=%d\n" sn.a sn.b } function l { compound -S s=( a=1 b=2 ) l_n $1 s } (l false ; l false ; l true ; printf ";") (l false ; l false ; l true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='type' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function l { ab_t -S s s.increment $1 && printf "a=%d, b=%d\n" s.a s.b } (l false ; l false ; l true ; printf ";") (l false ; l false ; l true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='type_nameref' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function l_n { nameref sn=$2 sn.increment $1 && printf "a=%d, b=%d\n" sn.a sn.b } function l { ab_t -S s l_n $1 s } (l false ; l false ; l true ; printf ";") (l false ; l false ; l true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='indexed_string_array_appendelement' cmd=$' function ar { typeset -a -S s=( "hello" ) s+=( "an element" ) $1 && { printf "%s" "${s[@]}" ; printf "\n" ; } } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;' ) ( name='indexed_string_array_nameref_appendelement' cmd=$' function ar_n { nameref sn=$2 sn+=( "an element" ) $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; } } function ar { typeset -a -S s=( "hello" ) ar_n $1 s } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;' ) ( name='associative_string_array_appendelement' cmd=$' function ar { typeset -A -S s=( [0]="hello" ) s[$(( ${#s[@]} + 1))]="an element" $1 && { printf "%s" "${s[@]}" ; printf "\n" ; } } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;' ) ( name='associative_string_array_nameref_appendelement' cmd=$' function ar_n { nameref sn=$2 sn[$(( ${#sn[@]} + 1))]="an element" $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; } } function ar { typeset -A -S s=( [0]="hello" ) ar_n $1 s } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;' ) ( name='indexed_compound_array_editelement' cmd=$' function ar { compound -S -a s=( [5]=( integer a=1 integer b=2 ) ) (( s[5].a++, s[5].b++ )) $1 && printf "a=%d, b=%d\n" s[5].a s[5].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='indexed_compound_array_nameref_editelement' cmd=$' function ar_n { nameref sn=$2 (( sn.a++, sn.b++ )) $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { compound -S -a s=( [5]=( integer a=1 integer b=2 ) ) ar_n $1 s[5] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='2d_indexed_compound_array_editelement' cmd=$' function ar { compound -S -a s=( [8][5]=( integer a=1 integer b=2 ) ) (( s[8][5].a++, s[8][5].b++ )) $1 && printf "a=%d, b=%d\n" s[8][5].a s[8][5].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='2d_indexed_compound_array_nameref_editelement' cmd=$' function ar_n { nameref sn=$2 (( sn.a++, sn.b++ )) $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { compound -S -a s=( [8][5]=( integer a=1 integer b=2 ) ) ar_n $1 s[8][5] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='4d_indexed_compound_array_editelement' cmd=$' function ar { compound -S -a s=( [8][5][0][9]=( integer a=1 integer b=2 ) ) (( s[8][5][0][9].a++, s[8][5][0][9].b++ )) $1 && printf "a=%d, b=%d\n" s[8][5][0][9].a s[8][5][0][9].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='4d_indexed_compound_array_nameref_editelement' cmd=$' function ar_n { nameref sn=$2 (( sn.a++, sn.b++ )) $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { compound -S -a s=( [8][5][0][9]=( integer a=1 integer b=2 ) ) ar_n $1 s[8][5][0][9] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='associative_compound_array_editelement' cmd=$' function ar { compound -S -A s=( [5]=( integer a=1 integer b=2 ) ) (( s[5].a++, s[5].b++ )) $1 && printf "a=%d, b=%d\n" s[5].a s[5].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='associative_compound_array_nameref_editelement' cmd=$' function ar_n { nameref sn=$2 (( sn.a++, sn.b++ )) $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { compound -S -A s=( [5]=( integer a=1 integer b=2 ) ) ar_n $1 s[5] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='indexed_type_array_editelement' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function ar { ab_t -S -a s [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ? s[5].increment $1 && printf "a=%d, b=%d\n" s[5].a s[5].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='indexed_type_array_nameref_editelement' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function ar_n { nameref sn=$2 sn.increment $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { ab_t -S -a s [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ? ar_n $1 s[5] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='2d_indexed_type_array_editelement' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function ar { ab_t -S -a s [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ? s[9][5].increment $1 && printf "a=%d, b=%d\n" s[9][5].a s[9][5].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='2d_indexed_type_array_nameref_editelement' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function ar_n { nameref sn=$2 sn.increment $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { ab_t -S -a s [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ? ar_n $1 s[9][5] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='associative_type_array_editelement' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function ar { ab_t -S -A s [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ? s[5].increment $1 && printf "a=%d, b=%d\n" s[5].a s[5].b } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ( name='associative_type_array_nameref_editelement' cmd=$' typeset -T ab_t=( integer a=1 integer b=2 function increment { (( _.a++, _.b++ )) } ) function ar_n { nameref sn=$2 sn.increment $1 && printf "a=%d, b=%d\n" sn.a sn.b } function ar { ab_t -S -A s [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ? ar_n $1 s[5] } (ar false ; ar false ; ar true ; printf ";") (ar false ; ar false ; ar true ; printf ";") ' expected_output=$'a=4, b=5\n;a=4, b=5\n;' ) ) for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do nameref currtest=tests[i] #print -u2 -- "${currtest.cmd}" out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${currtest.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }" (( out.res == 0 )) || err_exit "${currtest.name}: Test shell returned with exit code ${out.res}" [[ "${out.stdout}" == "${currtest.expected_output}" ]] || err_exit "${currtest.name}: Expected stdout == $(printf "%q\n" "${currtest.expected_output}"), got $(printf "%q\n" "${out.stdout}")" [[ "${out.stderr}" == '' ]] || err_exit "${currtest.name}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")" done return 0 } # run tests test1 test2 # Test visibilty of "global" vs. "static" variables. if we have a "static" variable in a # function and "unset" it we should see a global variable with the same # name, right ? integer hx=5 function test_hx_scope { integer -S hx=9 $2 && unset hx $1 && printf 'hx=%d\n' hx } test_hx_scope false false test_hx_scope false false # first test the "unset" call in a $(...) subshell... [[ "$( test_hx_scope true true )" == 'hx=5' ]] || err_exit "can't see global variable hx after unsetting static variable hx" # ... end then test whether the value has changed. [[ "${ test_hx_scope true false ;}" == 'hx=9' ]] || err_exit "hx variable somehow changed" out=$(function fun2 { nameref sn=$1 (( sn.a++, sn.b++ )) $2 && printf "a=%d, b=%d\n" sn.a sn.b } function fun1 { compound -S s=( a=0 b=0 ) fun2 s $1 } (fun1 false ; fun1 false ; fun1 true) (fun1 false ; fun1 false ; fun1 true) ) [[ $out == $'a=3, b=3\na=3, b=3' ]] || err_exit 'static variables in functions with initializers not working' exit $((Errors<125?Errors:125))