mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-24 23:14:14 +00:00
690 lines
16 KiB
Bash
Executable file
690 lines
16 KiB
Bash
Executable file
########################################################################
|
|
# #
|
|
# 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 <dgk@research.att.com> #
|
|
# #
|
|
########################################################################
|
|
#
|
|
# Written by Roland Mainz <roland.mainz@nrubsig.org>
|
|
#
|
|
|
|
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 visibility 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))
|