riscv-openocd-wch/jimtcl/tests/namespace.test

568 lines
17 KiB
Plaintext

source [file dirname [info script]]/testing.tcl
needs cmd namespace
test namespace-1.1 {usage for "namespace" command} -body {
namespace
} -returnCodes error -match glob -result {wrong # args: should be *}
test namespace-1.2 {global namespace's name is "::" or {}} {
list [namespace current] [namespace eval {} {namespace current}] [namespace eval :: {namespace current}]
} {:: :: ::}
test namespace-1.3 {usage for "namespace eval"} -body {
namespace eval
} -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"}
test namespace-1.5 {access a new namespace} {
namespace eval ns1 { namespace current }
} {::ns1}
test namespace-1.7 {usage for "namespace eval"} -body {
namespace eval ns1
} -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"}
test namespace-1.8 {command "namespace eval" concatenates args} {
namespace eval ns1 namespace current
} {::ns1}
test namespace-1.9 {simple namespace elements} {
namespace eval ns1 {
variable v1 1
proc p1 {a} {variable v1; list $a $v1}
p1 3
}
} {3 1}
test namespace-1.10 {commands in a namespace} {
namespace eval ns1 {
info commands [namespace current]::*
}
} {::ns1::p1}
test namespace-1.11 {variables in a namespace} {
namespace eval ns1 {
info vars [namespace current]::*
}
} {::ns1::v1}
test namespace-1.12 {global vars are separate from locals vars} {
set v1 2
list [ns1::p1 123] [set ns1::v1] [set ::v1]
} {{123 1} 1 2}
test namespace-1.13 {add to an existing namespace} {
namespace eval ns1 {
variable v2 22
proc p2 {script} {variable v2; eval $script}
p2 {return $v2}
}
} 22
test namespace-1.14 {commands in a namespace} {
lsort [namespace eval ns1 {info commands [namespace current]::*}]
} {::ns1::p1 ::ns1::p2}
test namespace-1.15 {variables in a namespace} {
lsort [namespace eval ns1 {info vars [namespace current]::*}]
} {::ns1::v1 ::ns1::v2}
# Tcl produces fully scoped names here
test namespace-1.16 {variables in a namespace} jim {
lsort [info vars ns1::*]
} {ns1::v1 ns1::v2}
test namespace-1.17 {commands in a namespace are hidden} -body {
v2 {return 3}
} -returnCodes error -result {invalid command name "v2"}
test namespace-1.18 {using namespace qualifiers} {
ns1::p2 {return 44}
} 44
test namespace-1.19 {using absolute namespace qualifiers} {
::ns1::p2 {return 55}
} 55
test namespace-1.20 {variables in a namespace are hidden} -body {
set v2
} -returnCodes error -result {can't read "v2": no such variable}
test namespace-1.21 {using namespace qualifiers} {
list $ns1::v1 $ns1::v2
} {1 22}
test namespace-1.22 {using absolute namespace qualifiers} {
list $::ns1::v1 $::ns1::v2
} {1 22}
test namespace-1.23 {variables can be accessed within a namespace} {
ns1::p2 {
variable v1
variable v2
list $v1 $v2
}
} {1 22}
test namespace-1.24 {setting global variables} {
ns1::p2 {
variable v1
set v1 new
}
namespace eval ns1 {
variable v1
variable v2
list $v1 $v2
}
} {new 22}
test namespace-1.25 {qualified variables don't need a global declaration} {
namespace eval ns2 { variable x 456 }
set cmd {set ::ns2::x}
ns1::p2 "$cmd some-value"
set ::ns2::x
} {some-value}
test namespace-1.26 {namespace qualifiers are okay after $'s} {
namespace eval ns1 { variable x; variable y; set x 12; set y 34 }
set cmd {list $::ns1::x $::ns1::y}
list [ns1::p2 $cmd] [eval $cmd]
} {{12 34} {12 34}}
test namespace-1.27 {can create commands with null names} {
proc ns1:: {args} {return $args}
ns1:: x
} {x}
test namespace-1.28 {namespace variable with array element syntax} -body {
namespace eval ns1 {
variable x(3) y
}
} -returnCodes error -result {can't define "x(3)": name refers to an element in an array}
test namespace-1.29 {namespace variable too many args} -body {
namespace eval ns1 {
variable x(3) y a b c
}
} -returnCodes error -result {wrong # args: should be "variable name ?value?"}
test namespace-1.30 {namespace current too many args} -body {
namespace current a
} -returnCodes error -result {wrong # args: should be "namespace current"}
# TODO: Add tests for canonical option
test namespace-1.31 {namespace canonical too many args} -body {
namespace canonical a b c
} -returnCodes error -result {wrong # args: should be "namespace canonical ?current? ?name?"}
unset -nocomplain ns1::x ns1::y
# -----------------------------------------------------------------------
# TEST: using "info" in namespace contexts
# -----------------------------------------------------------------------
test namespace-2.1 {querying: info commands} {
lsort [ns1::p2 {info commands [namespace current]::*}]
} {::ns1:: ::ns1::p1 ::ns1::p2}
test namespace-2.2 {querying: info procs} {
lsort [ns1::p2 {info procs}]
} {{} p1 p2}
# Tcl produces fully scoped names here
test namespace-2.3 {querying: info vars} jim {
lsort [info vars ns1::*]
} {ns1::v1 ns1::v2}
test namespace-2.4 {querying: info vars} {
lsort [ns1::p2 {info vars [namespace current]::*}]
} {::ns1::v1 ::ns1::v2}
test namespace-2.5 {querying: info locals} {
lsort [ns1::p2 {info locals}]
} {script}
test namespace-2.6 {querying: info exists} {
ns1::p2 {info exists v1}
} {0}
test namespace-2.7 {querying: info exists} {
ns1::p2 {info exists v2}
} {1}
test namespace-2.8 {querying: info args} {
info args ns1::p2
} {script}
test namespace-2.9 {querying: info body} {
string trim [info body ns1::p1]
} {variable v1; list $a $v1}
# -----------------------------------------------------------------------
# TEST: namespace qualifiers, namespace tail
# -----------------------------------------------------------------------
test namespace-3.1 {usage for "namespace qualifiers"} {
list [catch "namespace qualifiers" msg] $msg
} {1 {wrong # args: should be "namespace qualifiers string"}}
test namespace-3.2 {querying: namespace qualifiers} {
list [namespace qualifiers ""] \
[namespace qualifiers ::] \
[namespace qualifiers x] \
[namespace qualifiers ::x] \
[namespace qualifiers foo::x] \
[namespace qualifiers ::foo::bar::xyz]
} {{} {} {} {} foo ::foo::bar}
test namespace-3.3 {usage for "namespace tail"} {
list [catch "namespace tail" msg] $msg
} {1 {wrong # args: should be "namespace tail string"}}
test namespace-3.4 {querying: namespace tail} {
list [namespace tail ""] \
[namespace tail ::] \
[namespace tail x] \
[namespace tail ::x] \
[namespace tail foo::x] \
[namespace tail ::foo::bar::xyz]
} {{} {} x x x xyz}
# -----------------------------------------------------------------------
# TEST: namespace hierarchy
# -----------------------------------------------------------------------
test namespace-5.1 {define nested namespaces} {
set test_ns_var_global "var in ::"
proc test_ns_cmd_global {} {return "cmd in ::"}
namespace eval nsh1 {
set test_ns_var_hier1 "particular to hier1"
proc test_ns_cmd_hier1 {} {return "particular to hier1"}
proc test_ns_show {} {return "[namespace current]: 1"}
namespace eval nsh2 {
set test_ns_var_hier2 "particular to hier2"
proc test_ns_cmd_hier2 {} {return "particular to hier2"}
proc test_ns_show {} {return "[namespace current]: 2"}
namespace eval nsh3a {}
namespace eval nsh3b {}
}
namespace eval nsh2a {}
namespace eval nsh2b {}
}
} {}
test namespace-5.2 {namespaces can be nested} {
list [namespace eval nsh1 {namespace current}] \
[namespace eval nsh1 {
namespace eval nsh2 {namespace current}
}]
} {::nsh1 ::nsh1::nsh2}
test namespace-5.3 {namespace qualifiers work in namespace command} {
list [namespace eval ::nsh1 {namespace current}] \
[namespace eval nsh1::nsh2 {namespace current}] \
[namespace eval ::nsh1::nsh2 {namespace current}]
} {::nsh1 ::nsh1::nsh2 ::nsh1::nsh2}
test namespace-5.4 {nested namespaces can access global namespace} {
list [namespace eval nsh1 {set ::test_ns_var_global}] \
[namespace eval nsh1 {test_ns_cmd_global}] \
[namespace eval nsh1::nsh2 {set ::test_ns_var_global}] \
[namespace eval nsh1::nsh2 {test_ns_cmd_global}]
} {{var in ::} {cmd in ::} {var in ::} {cmd in ::}}
test namespace-5.6 {commands in different namespaces don't conflict} {
list [nsh1::test_ns_show] \
[nsh1::nsh2::test_ns_show]
} {{::nsh1: 1} {::nsh1::nsh2: 2}}
test namespace-5.7 {nested namespaces don't see variables in parent} {
set cmd {
namespace eval nsh1::nsh2 {set test_ns_var_hier1}
}
list [catch $cmd msg] $msg
} {1 {can't read "test_ns_var_hier1": no such variable}}
test namespace-5.8 {nested namespaces don't see commands in parent} {
set cmd {
namespace eval nsh1::nsh2 {test_ns_cmd_hier1}
}
list [catch $cmd msg] $msg
} {1 {invalid command name "test_ns_cmd_hier1"}}
test namespace-5.18 {usage for "namespace parent"} {
list [catch {namespace parent x y} msg] $msg
} {1 {wrong # args: should be "namespace parent ?name?"}}
test namespace-5.20 {querying namespace parent} {
list [namespace eval :: {namespace parent}] \
[namespace eval nsh1 {namespace parent}] \
[namespace eval nsh1::nsh2 {namespace parent}] \
[namespace eval nsh1::nsh2::nsh3a {namespace parent}] \
} {{} :: ::nsh1 ::nsh1::nsh2}
test namespace-5.21 {querying namespace parent for explicit namespace} {
list [namespace parent ::] \
[namespace parent nsh1] \
[namespace parent nsh1::nsh2] \
[namespace parent nsh1::nsh2::nsh3a]
} {{} :: ::nsh1 ::nsh1::nsh2}
test namespace-5.22 {query namespace parent with fully qualified names} {
list [namespace eval :: {namespace parent}] \
[namespace eval ::nsh1 {namespace parent}] \
[namespace eval ::nsh1::nsh2 {namespace parent}] \
[namespace eval nsh1::nsh2::nsh3a {namespace parent ::nsh1::nsh2}] \
} {{} :: ::nsh1 ::nsh1}
# -----------------------------------------------------------------------
# TEST: name resolution and caching
# -----------------------------------------------------------------------
test namespace-6.1 {relative ns names only looked up in current ns} {
namespace eval tns1 {}
namespace eval tns2 {}
namespace eval tns2::test_ns_cache3 {}
set trigger {
namespace eval tns2 {namespace current}
}
set trigger2 {
namespace eval tns2::test_ns_cache3 {namespace current}
}
list [namespace eval tns1 $trigger] \
[namespace eval tns1 $trigger2]
} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
test namespace-6.2 {relative ns names only looked up in current ns} {
namespace eval tns1::tns2 {}
list [namespace eval tns1 $trigger] \
[namespace eval tns1 $trigger2]
} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
test namespace-6.3 {relative ns names only looked up in current ns} {
namespace eval tns1::tns2::test_ns_cache3 {}
list [namespace eval tns1 $trigger] \
[namespace eval tns1 $trigger2]
} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
test namespace-6.4 {relative ns names only looked up in current ns} {
namespace delete tns1::tns2
list [namespace eval tns1 $trigger] \
[namespace eval tns1 $trigger2]
} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
test namespace-6.5 {define test commands} {
proc testcmd {} {
return "global version"
}
namespace eval tns1 {
proc trigger {} {
testcmd
}
}
tns1::trigger
} {global version}
test namespace-6.6 {one-level check for command shadowing} {
proc tns1::testcmd {} {
return "cache1 version"
}
tns1::trigger
} {cache1 version}
test namespace-6.7 {renaming commands changes command epoch} {
namespace eval tns1 {
rename testcmd testcmd_new
}
tns1::trigger
} {global version}
test namespace-6.8 {renaming back handles shadowing} {
namespace eval tns1 {
rename testcmd_new testcmd
}
tns1::trigger
} {cache1 version}
test namespace-6.9 {deleting commands changes command epoch} {
namespace eval tns1 {
rename testcmd ""
}
tns1::trigger
} {global version}
test namespace-6.10 {define test namespaces} {
namespace eval tns2 {
proc testcmd {} {
return "global cache2 version"
}
}
namespace eval tns1 {
proc trigger {} {
tns2::testcmd
}
}
namespace eval tns1::tns2 {
proc trigger {} {
testcmd
}
}
list [tns1::trigger] [tns1::tns2::trigger]
} {{global cache2 version} {global version}}
test namespace-6.11 {commands affect all parent namespaces} {
proc tns1::tns2::testcmd {} {
return "cache2 version"
}
list [tns1::trigger] [tns1::tns2::trigger]
} {{cache2 version} {cache2 version}}
# -----------------------------------------------------------------------
# TEST: uplevel/upvar across namespace boundaries
# -----------------------------------------------------------------------
# Note that Tcl behaves a little differently for uplevel and upvar
test namespace-7.1 {uplevel in namespace eval} jim {
set x 66
namespace eval uns1 {
variable y 55
set x 33
uplevel 1 set x
}
} {66}
test namespace-7.2 {upvar in ns proc} jim {
proc uns1::getvar {v} {
variable y
upvar $v var
list $var $y
}
uns1::getvar x
} {66 55}
# -----------------------------------------------------------------------
# TEST: scoped values
# -----------------------------------------------------------------------
test namespace-10.1 {define namespace for scope test} {
namespace eval ins1 {
variable x "x-value"
proc show {args} {
return "show: $args"
}
proc do {args} {
return [eval $args]
}
list [set x] [show test]
}
} {x-value {show: test}}
test namespace-10.2 {command "namespace code" requires one argument} {
list [catch {namespace code} msg] $msg
} {1 {wrong # args: should be "namespace code arg"}}
test namespace-10.3 {command "namespace code" requires one argument} {
list [catch {namespace code first "second arg" third} msg] $msg
} {1 {wrong # args: should be "namespace code arg"}}
test namespace-10.4 {command "namespace code" gets current namesp context} {
namespace eval ins1 {
namespace code {"1 2 3" "4 5" 6}
}
} {::namespace inscope ::ins1 {"1 2 3" "4 5" 6}}
test namespace-10.5 {with one arg, first "scope" sticks} {
set sval [namespace eval ins1 {namespace code {one two}}]
namespace code $sval
} {::namespace inscope ::ins1 {one two}}
test namespace-10.6 {with many args, each "scope" adds new args} {
set sval [namespace eval ins1 {namespace code {one two}}]
namespace code "$sval three"
} {::namespace inscope ::ins1 {one two} three}
test namespace-10.7 {scoped commands work with eval} {
set cref [namespace eval ins1 {namespace code show}]
list [eval $cref "a" "b c" "d e f"]
} {{show: a b c d e f}}
test namespace-10.8 {scoped commands execute in namespace context} {
set cref [namespace eval ins1 {
namespace code {variable x; set x "some new value"}
}]
list [set ins1::x] [eval $cref] [set ins1::x]
} {x-value {some new value} {some new value}}
test namespace-11.1 {command caching} {
proc cmd1 {} { return global }
set result {}
namespace eval ns1 {
proc cmd1 {} { return ns1 }
proc cmd2 {} {
uplevel 1 cmd1
}
lappend ::result [cmd2]
}
lappend result [ns1::cmd2]
} {ns1 global}
test namespace-12.1 {namespace import} {
namespace eval test_ns_scope1 {
proc a {} { return a }
namespace export a
}
namespace eval test_ns_scope2 {
namespace import ::test_ns_scope1::a
a
}
} {a}
test namespace-12.2 {namespace import recursive} -body {
namespace eval test_ns_scope1 {
namespace import [namespace current]::*
}
} -returnCodes error -match glob -result {import pattern "*" tries to import from namespace "*" into itself}
test namespace-12.3 {namespace import loop} -setup {
namespace eval one {
namespace export cmd
proc cmd {} {}
}
namespace eval two namespace export cmd
namespace eval two \
[list namespace import [namespace current]::one::cmd]
namespace eval three namespace export cmd
namespace eval three \
[list namespace import [namespace current]::two::cmd]
} -body {
namespace eval two [list namespace import -force \
[namespace current]::three::cmd]
namespace origin two::cmd
} -cleanup {
namespace delete one two three
} -returnCodes error -match glob -result {import pattern * would create a loop*}
test namespace-12.4 {namespace import} {
namespace eval ::test_ns_one {}
proc ::test_ns_one::testcmd args { return 2 }
namespace import ::test_ns_one::*
testcmd
} 2
foreach cmd [info commands test_ns_*] {
rename $cmd ""
}
catch {rename cmd {}}
catch {rename cmd1 {}}
catch {rename cmd2 {}}
catch {rename ncmd {}}
catch {rename ncmd1 {}}
catch {rename ncmd2 {}}
catch {unset cref}
catch {unset trigger}
catch {unset trigger2}
catch {unset sval}
catch {unset msg}
catch {unset x}
catch {unset test_ns_var_global}
catch {unset cmd}
catch {eval namespace delete [namespace children :: test_ns_*]}
# cleanup
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End: