mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
556 lines
11 KiB
Text
556 lines
11 KiB
Text
# Tests for the zsh/param/private module
|
|
|
|
%prep
|
|
|
|
if ! zmodload zsh/param/private 2>/dev/null; then
|
|
ZTST_unimplemented="can't load the zsh/param/private module for testing"
|
|
else
|
|
# Do not use .tmp here, ztst.zsh will remove it too soon (see %cleanup)
|
|
mkdir private.TMP
|
|
sed -e 's,# test_zsh_param_private,zmodload zsh/param/private,' < $ZTST_srcdir/B02typeset.ztst > private.TMP/B02
|
|
fi
|
|
|
|
setopt TYPESET_TO_UNSET
|
|
|
|
%test
|
|
|
|
(zmodload -u zsh/param/private && zmodload zsh/param/private)
|
|
0:unload and reload the module without crashing
|
|
|
|
typeset scalar_test=toplevel
|
|
() {
|
|
print $scalar_test
|
|
private scalar_test
|
|
typeset +m scalar_test
|
|
unset scalar_test
|
|
print $+scalar_test
|
|
}
|
|
print $scalar_test
|
|
0:basic scope hiding
|
|
>toplevel
|
|
>local hide scalar_test
|
|
>0
|
|
>toplevel
|
|
|
|
typeset scalar_test=toplevel
|
|
print $scalar_test
|
|
() {
|
|
private scalar_test=function
|
|
print $scalar_test
|
|
}
|
|
print $scalar_test
|
|
0:enter and exit a scope
|
|
>toplevel
|
|
>function
|
|
>toplevel
|
|
|
|
print $+unset_test
|
|
() {
|
|
private unset_test
|
|
typeset +m unset_test
|
|
unset_test=setme
|
|
print $unset_test
|
|
}
|
|
print $+unset_test
|
|
0:variable defined only in scope
|
|
>0
|
|
>local hide unset_test
|
|
>setme
|
|
>0
|
|
|
|
# Depends on zsh-5.0.9 typeset keyword
|
|
typeset -a array_test=(top level)
|
|
() {
|
|
local -Pa array_test=(in function)
|
|
() {
|
|
private array_test
|
|
typeset +m array_test
|
|
}
|
|
print $array_test
|
|
}
|
|
print $array_test
|
|
0:nested scope with different type, correctly restored
|
|
>local hide array_test
|
|
>in function
|
|
>top level
|
|
|
|
typeset -a array_test=(top level)
|
|
() {
|
|
private array_test
|
|
array_test=(in function)
|
|
}
|
|
1:type of private may not be changed by assignment
|
|
?(anon):2: array_test: attempt to assign array value to non-array
|
|
|
|
typeset -A hash_test=(top level)
|
|
() {
|
|
setopt localoptions noglob
|
|
private hash_test[top]
|
|
}
|
|
1:associative array fields may not be private
|
|
?(anon):private:2: hash_test[top]: can't create local array elements
|
|
|
|
() {
|
|
private path
|
|
}
|
|
1:tied params may not be private, part 1
|
|
?(anon):private:1: can't change scope of existing param: path
|
|
|
|
() {
|
|
private PATH
|
|
}
|
|
1:tied params may not be private, part 2
|
|
?(anon):private:1: can't change scope of existing param: PATH
|
|
|
|
() {
|
|
private -h path
|
|
print X$path
|
|
}
|
|
0:privates may hide tied parameters
|
|
>X
|
|
|
|
# Deliberate type mismatch here
|
|
typeset -a hash_test=(top level)
|
|
typeset -p hash_test
|
|
inner () {
|
|
typeset -p hash_test
|
|
print ${(t)hash_test} ${(kv)hash_test}
|
|
}
|
|
outer () {
|
|
local -PA hash_test=(in function)
|
|
private + hash_test
|
|
inner
|
|
}
|
|
outer
|
|
print ${(kv)hash_test}
|
|
0:private hides value from surrounding scope in nested scope
|
|
>typeset -a hash_test=( top level )
|
|
>hash_test=( [in]=function )
|
|
>typeset -g -a hash_test=( top level )
|
|
>array-local top level
|
|
>top level
|
|
F:note "typeset" rather than "private" in output from outer
|
|
|
|
() {
|
|
private -a array_test
|
|
local array_test=scalar
|
|
}
|
|
1:private cannot be re-declared as local
|
|
?(anon):local:2: array_test: inconsistent type for assignment
|
|
|
|
() {
|
|
local hash_test=scalar
|
|
private -A hash_test
|
|
}
|
|
1:local cannot be re-declared as private
|
|
?(anon):private:2: can't change scope of existing param: hash_test
|
|
|
|
inner () {
|
|
print $+scalar_test
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
|
|
}
|
|
() {
|
|
private -x scalar_test=whaat
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
|
|
inner
|
|
print Y $scalar_test
|
|
}
|
|
0:exported private behaves like a local, part 1
|
|
>X whaat
|
|
>0
|
|
>X whaat
|
|
>Y whaat
|
|
|
|
inner () {
|
|
typeset -p array_test
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $array_test'
|
|
}
|
|
() {
|
|
local -Pax array_test=(whaat)
|
|
print Y $array_test
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $array_test'
|
|
inner
|
|
}
|
|
0:exported private behaves like a local, part 2 (arrays do not export)
|
|
?inner:typeset:1: no such variable: array_test
|
|
>Y whaat
|
|
>X
|
|
>X
|
|
|
|
inner () {
|
|
print $+scalar_test
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
|
|
}
|
|
() {
|
|
private scalar_test=whaat
|
|
export scalar_test
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
|
|
inner
|
|
() {
|
|
print $+scalar_test
|
|
$ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
|
|
}
|
|
print Y $scalar_test
|
|
}
|
|
0:exported private behaves like a local, part 3 (export does not change scope)
|
|
>X whaat
|
|
>0
|
|
>X whaat
|
|
>0
|
|
>X whaat
|
|
>Y whaat
|
|
|
|
typeset -A hash_test=(top level)
|
|
() {
|
|
local -PA hash_test=(in function)
|
|
() {
|
|
print X ${(kv)hash_test}
|
|
}
|
|
print Y ${(kv)hash_test}
|
|
}
|
|
print ${(kv)hash_test}
|
|
0:privates are not visible in anonymous functions, part 1
|
|
>X top level
|
|
>Y in function
|
|
>top level
|
|
|
|
typeset -A hash_test=(top level)
|
|
() {
|
|
local -PA hash_test=(in function)
|
|
() {
|
|
print X ${(kv)hash_test}
|
|
hash_test[in]=deeper
|
|
}
|
|
print Y ${(kv)hash_test}
|
|
}
|
|
print ${(okv)hash_test}
|
|
0:privates are not visible in anonymous functions, part 2
|
|
>X top level
|
|
>Y in function
|
|
>deeper in level top
|
|
|
|
typeset -A hash_test=(top level)
|
|
() {
|
|
local -Pa array_test=(in function)
|
|
local -PA hash_test=($array_test)
|
|
() {
|
|
print X ${(kv)hash_test}
|
|
hash_test=(even deeper)
|
|
{
|
|
array_test+=(${(kv)hash_test})
|
|
} always {
|
|
print ${array_test-array_test not set} ${(t)array_test}
|
|
}
|
|
}
|
|
print Y ${(kv)hash_test} Z $array_test
|
|
}
|
|
print ${(kv)hash_test} ${(t)array_test}
|
|
1:privates are not visible in anonymous functions, part 3
|
|
>X top level
|
|
>array_test not set
|
|
?(anon):4: array_test: can't modify read-only parameter
|
|
F:future revision will create a global with this assignment
|
|
|
|
typeset -a array_test
|
|
typeset -A hash_test=(top level)
|
|
() {
|
|
local -Pa array_test=(in function)
|
|
local -PA hash_test=($array_test)
|
|
() {
|
|
print X ${(kv)hash_test}
|
|
hash_test=(even deeper)
|
|
array_test+=(${(kv)hash_test})
|
|
}
|
|
print Y ${(kv)hash_test} Z $array_test
|
|
}
|
|
print ${(kv)hash_test} $array_test
|
|
0:privates are not visible in anonymous functions, part 4
|
|
>X top level
|
|
>Y in function Z in function
|
|
>even deeper even deeper
|
|
|
|
typeset -A hash_test=(top level)
|
|
() {
|
|
local -PA hash_test=(in function)
|
|
() {
|
|
print X ${(kv)hash_test}
|
|
unset hash_test
|
|
}
|
|
print Y ${(kv)hash_test}
|
|
}
|
|
print ${(t)hash_test} ${(kv)hash_test}
|
|
0:privates are not visible in anonymous functions, part 5
|
|
>X top level
|
|
>Y in function
|
|
>
|
|
|
|
# Subshell because otherwise this silently dumps core when broken
|
|
( () { private SECONDS } )
|
|
1:special parameters cannot be made private
|
|
?(anon):private: can't change scope of existing param: SECONDS
|
|
|
|
() { private -h SECONDS }
|
|
0:private parameter may hide a special parameter
|
|
|
|
if (( UID )); then
|
|
ZTST_verbose=0 $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh private.TMP/B02
|
|
else
|
|
ZTST_skip="cannot re-run typeset tests when tests run as superuser"
|
|
fi
|
|
0:typeset still works with zsh/param/private module loaded
|
|
*>*
|
|
*>*
|
|
|
|
typeset top=TOP
|
|
() {
|
|
local -P -n test=top
|
|
print $top
|
|
() { print UP: $test }
|
|
}
|
|
0:nameref can be declared private
|
|
>TOP
|
|
>UP:
|
|
|
|
() {
|
|
typeset -a ary
|
|
local -P -n ref=ary
|
|
{
|
|
(){
|
|
ref=XX # Should be an error
|
|
typeset -p ary ref
|
|
}
|
|
} always {
|
|
TRY_BLOCK_ERROR=0
|
|
typeset -p ary ref
|
|
}
|
|
}
|
|
typeset -p ary
|
|
1:assignment to private nameref in wrong scope, part 1
|
|
>typeset -a ary
|
|
>typeset -hn ref=ary
|
|
*?*ref: can't modify read-only parameter
|
|
*?*no such variable: ary
|
|
|
|
() {
|
|
typeset -a ary
|
|
local -P -n ref=ary
|
|
{
|
|
(){
|
|
typeset ref=XX # Should create a local
|
|
typeset -p ary ref
|
|
}
|
|
} always {
|
|
TRY_BLOCK_ERROR=0
|
|
typeset -p ary ref
|
|
}
|
|
}
|
|
typeset -p ary
|
|
1:assignment to private nameref in wrong scope, part 2
|
|
>typeset -g -a ary
|
|
>typeset ref=XX
|
|
>typeset -a ary
|
|
>typeset -hn ref=ary
|
|
*?*no such variable: ary
|
|
|
|
() {
|
|
typeset -n ptr1=ptr2
|
|
private -n ptr2 # TYPESET_TO_UNSET makes this not a "placeholder"
|
|
typeset -p ptr1 ptr2
|
|
typeset val=LOCAL
|
|
() {
|
|
ptr1=val # Test dies here as ptr2 is private and unset
|
|
typeset -n
|
|
printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2"
|
|
}
|
|
typeset -p ptr1 ptr2
|
|
}
|
|
typeset -p ptr2
|
|
1:up-reference for private namerefs, end unset and not in scope
|
|
F:See K01nameref.ztst up-reference part 5
|
|
F:Here ptr1 finds private ptr2 by scope mismatch
|
|
>typeset -n ptr1=ptr2
|
|
>typeset -hn ptr2
|
|
*?*read-only variable: ptr2
|
|
|
|
() {
|
|
typeset -n ptr1=ptr2
|
|
private -n ptr2= # Assignment makes this a placeholder, not unset
|
|
typeset -p ptr1 ptr2
|
|
typeset val=LOCAL
|
|
() {
|
|
ptr1=val || print -u2 ptr1: assignment failed
|
|
typeset -n
|
|
printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2"
|
|
}
|
|
typeset -p ptr1 ptr2
|
|
}
|
|
typeset -p ptr2
|
|
1:up-reference for private namerefs, end not in scope
|
|
F:See K01nameref.ztst up-reference part 5
|
|
F:Here ptr1 finds private ptr2 by scope mismatch
|
|
>typeset -n ptr1=ptr2
|
|
>typeset -hn ptr2=''
|
|
>ptr1=ptr2
|
|
>ptr1=
|
|
>ptr2=
|
|
>typeset -n ptr1=ptr2
|
|
>typeset -hn ptr2=''
|
|
*?*ptr1: assignment failed
|
|
*?*no such variable: ptr2
|
|
|
|
typeset ptr2
|
|
() {
|
|
typeset -n ptr1=ptr2
|
|
private -n ptr2 # Set/unset is irrelevant, not referenced
|
|
typeset -p ptr1 ptr2
|
|
typeset val=LOCAL
|
|
() {
|
|
ptr1=val
|
|
typeset -n
|
|
printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2"
|
|
}
|
|
typeset -p ptr1 ptr2
|
|
}
|
|
typeset -p ptr2
|
|
0:up-reference for private namerefs, end is in scope
|
|
F:See K01typeset.ztst up-reference part 5
|
|
F:Here ptr1 points to global ptr2 so assignment succeeds
|
|
>typeset -n ptr1=ptr2
|
|
>typeset -hn ptr2
|
|
>ptr1=ptr2
|
|
>ptr2=val
|
|
>ptr1=val
|
|
>ptr2=val
|
|
>typeset -n ptr1=ptr2
|
|
>typeset -hn ptr2
|
|
>typeset ptr2=val
|
|
|
|
() {
|
|
setopt localoptions errreturn
|
|
private -n ptr2
|
|
typeset -n ptr1=ptr2
|
|
typeset -p ptr1 ptr2
|
|
typeset val=LOCAL
|
|
() {
|
|
ptr1=val
|
|
typeset -n
|
|
printf "v %s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2"
|
|
}
|
|
typeset -p ptr1 ptr2
|
|
}
|
|
typeset -p ptr1 ptr2
|
|
1:up-reference for private namerefs, end is in scope but private
|
|
F:Should we allow "public" namerefs to private parameters?
|
|
*?*ptr2: invalid reference
|
|
*?*no such variable: ptr1
|
|
*?*no such variable: ptr2
|
|
|
|
() {
|
|
private x=1
|
|
unset x
|
|
x=2
|
|
}
|
|
0:regression test for unset private
|
|
|
|
() {
|
|
private x=1
|
|
unset x
|
|
private x=2
|
|
print $x
|
|
}
|
|
0:private may be called twice
|
|
>2
|
|
|
|
() {
|
|
private x=1
|
|
private -a x
|
|
print $x
|
|
}
|
|
1:private may not change parameter type
|
|
?(anon):private:2: can't change type of private param: x
|
|
|
|
() {
|
|
private fd1 fd2
|
|
exec {fd1}>&1
|
|
print OK
|
|
() { exec {fd2}>&2 }
|
|
print BAD $fd2
|
|
}
|
|
1:redirection cannot assign private in wrong scope
|
|
F:Better if caught in checkclobberparam() but exec.c doesn't know scope
|
|
>OK
|
|
?(anon): fd2: can't modify read-only parameter
|
|
|
|
() {
|
|
private z=outer
|
|
print ${(t)z} $z
|
|
print ${|
|
|
print ${(t)z} $z
|
|
REPLY=$z
|
|
}
|
|
}
|
|
0:nofork may read private in calling function
|
|
>scalar-local-hide-special outer
|
|
>scalar-local-hide-special outer
|
|
>outer
|
|
|
|
() {
|
|
private z=outer
|
|
print ${(t)z} $z
|
|
print ${| REPLY=${{z} z=nofork} }
|
|
print ${(t)z} $z
|
|
}
|
|
0:nofork may write to private in calling function
|
|
>scalar-local-hide-special outer
|
|
>nofork
|
|
>scalar-local-hide-special nofork
|
|
|
|
() {
|
|
local q=outer
|
|
print ${|
|
|
private q=nofork
|
|
REPLY=${| REPLY=$q}
|
|
}
|
|
}
|
|
0:nofork cannot see private in surrounding nofork
|
|
>outer
|
|
|
|
() {
|
|
private z=outer
|
|
print ${(t)z} $z
|
|
print ${{z}
|
|
private q
|
|
z=${{q} q=nofork}
|
|
}
|
|
print ${(t)z} $z
|
|
}
|
|
1:nofork may not change private in surrounding nofork
|
|
>scalar-local-hide-special outer
|
|
*?*: q: can't modify read-only parameter
|
|
|
|
() {
|
|
private q=outer
|
|
print ${|
|
|
() { REPLY="{$q}" }
|
|
}
|
|
print ${{q}
|
|
() { q=nofork }
|
|
}
|
|
}
|
|
1:function may not access private from inside nofork
|
|
>{}
|
|
*?*: q: can't modify read-only parameter
|
|
|
|
() {
|
|
print ${|
|
|
private q
|
|
() { q=nofork }
|
|
}
|
|
}
|
|
1:function may not access private declared in nofork
|
|
*?*: q: can't modify read-only parameter
|
|
|
|
%clean
|
|
|
|
unsetopt TYPESET_TO_UNSET
|
|
rm -r private.TMP
|