1 source [file dirname [info script]]/testing.tcl
4 test namespace-1.1 {usage for "namespace" command} -body {
6 } -returnCodes error -match glob -result {wrong # args: should be *}
8 test namespace-1.2 {global namespace's name is "::" or {}} {
9 list [namespace current] [namespace eval {} {namespace current}] [namespace eval :: {namespace current}]
12 test namespace-1.3 {usage for "namespace eval"} -body {
14 } -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"}
16 test namespace-1.5 {access a new namespace} {
17 namespace eval ns1 { namespace current }
20 test namespace-1.7 {usage for "namespace eval"} -body {
22 } -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"}
24 test namespace-1.8 {command "namespace eval" concatenates args} {
25 namespace eval ns1 namespace current
28 test namespace-1.9 {simple namespace elements} {
31 proc p1 {a} {variable v1; list $a $v1}
36 test namespace-1.10 {commands in a namespace} {
38 info commands [namespace current]::*
42 test namespace-1.11 {variables in a namespace} {
44 info vars [namespace current]::*
48 test namespace-1.12 {global vars are separate from locals vars} {
50 list [ns1::p1 123] [set ns1::v1] [set ::v1]
53 test namespace-1.13 {add to an existing namespace} {
56 proc p2 {script} {variable v2; eval $script}
61 test namespace-1.14 {commands in a namespace} {
62 lsort [namespace eval ns1 {info commands [namespace current]::*}]
63 } {::ns1::p1 ::ns1::p2}
65 test namespace-1.15 {variables in a namespace} {
66 lsort [namespace eval ns1 {info vars [namespace current]::*}]
67 } {::ns1::v1 ::ns1::v2}
69 # Tcl produces fully scoped names here
70 test namespace-1.16 {variables in a namespace} jim {
71 lsort [info vars ns1::*]
74 test namespace-1.17 {commands in a namespace are hidden} -body {
76 } -returnCodes error -result {invalid command name "v2"}
78 test namespace-1.18 {using namespace qualifiers} {
82 test namespace-1.19 {using absolute namespace qualifiers} {
86 test namespace-1.20 {variables in a namespace are hidden} -body {
88 } -returnCodes error -result {can't read "v2": no such variable}
90 test namespace-1.21 {using namespace qualifiers} {
91 list $ns1::v1 $ns1::v2
94 test namespace-1.22 {using absolute namespace qualifiers} {
95 list $::ns1::v1 $::ns1::v2
98 test namespace-1.23 {variables can be accessed within a namespace} {
106 test namespace-1.24 {setting global variables} {
118 test namespace-1.25 {qualified variables don't need a global declaration} {
119 namespace eval ns2 { variable x 456 }
120 set cmd {set ::ns2::x}
121 ns1::p2 "$cmd some-value"
125 test namespace-1.26 {namespace qualifiers are okay after $'s} {
126 namespace eval ns1 { variable x; variable y; set x 12; set y 34 }
127 set cmd {list $::ns1::x $::ns1::y}
128 list [ns1::p2 $cmd] [eval $cmd]
131 test namespace-1.27 {can create commands with null names} {
132 proc ns1:: {args} {return $args}
136 test namespace-1.28 {namespace variable with array element syntax} -body {
140 } -returnCodes error -result {can't define "x(3)": name refers to an element in an array}
142 unset -nocomplain ns1::x ns1::y
144 # -----------------------------------------------------------------------
145 # TEST: using "info" in namespace contexts
146 # -----------------------------------------------------------------------
147 test namespace-2.1 {querying: info commands} {
148 lsort [ns1::p2 {info commands [namespace current]::*}]
149 } {::ns1:: ::ns1::p1 ::ns1::p2}
151 test namespace-2.2 {querying: info procs} {
152 lsort [ns1::p2 {info procs}]
155 # Tcl produces fully scoped names here
156 test namespace-2.3 {querying: info vars} jim {
157 lsort [info vars ns1::*]
160 test namespace-2.4 {querying: info vars} {
161 lsort [ns1::p2 {info vars [namespace current]::*}]
162 } {::ns1::v1 ::ns1::v2}
164 test namespace-2.5 {querying: info locals} {
165 lsort [ns1::p2 {info locals}]
168 test namespace-2.6 {querying: info exists} {
169 ns1::p2 {info exists v1}
172 test namespace-2.7 {querying: info exists} {
173 ns1::p2 {info exists v2}
176 test namespace-2.8 {querying: info args} {
180 test namespace-2.9 {querying: info body} {
181 string trim [info body ns1::p1]
182 } {variable v1; list $a $v1}
184 # -----------------------------------------------------------------------
185 # TEST: namespace qualifiers, namespace tail
186 # -----------------------------------------------------------------------
187 test namespace-3.1 {usage for "namespace qualifiers"} {
188 list [catch "namespace qualifiers" msg] $msg
189 } {1 {wrong # args: should be "namespace qualifiers string"}}
191 test namespace-3.2 {querying: namespace qualifiers} {
192 list [namespace qualifiers ""] \
193 [namespace qualifiers ::] \
194 [namespace qualifiers x] \
195 [namespace qualifiers ::x] \
196 [namespace qualifiers foo::x] \
197 [namespace qualifiers ::foo::bar::xyz]
198 } {{} {} {} {} foo ::foo::bar}
200 test namespace-3.3 {usage for "namespace tail"} {
201 list [catch "namespace tail" msg] $msg
202 } {1 {wrong # args: should be "namespace tail string"}}
204 test namespace-3.4 {querying: namespace tail} {
205 list [namespace tail ""] \
206 [namespace tail ::] \
208 [namespace tail ::x] \
209 [namespace tail foo::x] \
210 [namespace tail ::foo::bar::xyz]
213 # -----------------------------------------------------------------------
214 # TEST: namespace hierarchy
215 # -----------------------------------------------------------------------
216 test namespace-5.1 {define nested namespaces} {
217 set test_ns_var_global "var in ::"
218 proc test_ns_cmd_global {} {return "cmd in ::"}
219 namespace eval nsh1 {
220 set test_ns_var_hier1 "particular to hier1"
221 proc test_ns_cmd_hier1 {} {return "particular to hier1"}
222 proc test_ns_show {} {return "[namespace current]: 1"}
223 namespace eval nsh2 {
224 set test_ns_var_hier2 "particular to hier2"
225 proc test_ns_cmd_hier2 {} {return "particular to hier2"}
226 proc test_ns_show {} {return "[namespace current]: 2"}
227 namespace eval nsh3a {}
228 namespace eval nsh3b {}
230 namespace eval nsh2a {}
231 namespace eval nsh2b {}
235 test namespace-5.2 {namespaces can be nested} {
236 list [namespace eval nsh1 {namespace current}] \
237 [namespace eval nsh1 {
238 namespace eval nsh2 {namespace current}
240 } {::nsh1 ::nsh1::nsh2}
242 test namespace-5.3 {namespace qualifiers work in namespace command} {
243 list [namespace eval ::nsh1 {namespace current}] \
244 [namespace eval nsh1::nsh2 {namespace current}] \
245 [namespace eval ::nsh1::nsh2 {namespace current}]
246 } {::nsh1 ::nsh1::nsh2 ::nsh1::nsh2}
248 test namespace-5.4 {nested namespaces can access global namespace} {
249 list [namespace eval nsh1 {set ::test_ns_var_global}] \
250 [namespace eval nsh1 {test_ns_cmd_global}] \
251 [namespace eval nsh1::nsh2 {set ::test_ns_var_global}] \
252 [namespace eval nsh1::nsh2 {test_ns_cmd_global}]
253 } {{var in ::} {cmd in ::} {var in ::} {cmd in ::}}
255 test namespace-5.6 {commands in different namespaces don't conflict} {
256 list [nsh1::test_ns_show] \
257 [nsh1::nsh2::test_ns_show]
258 } {{::nsh1: 1} {::nsh1::nsh2: 2}}
259 test namespace-5.7 {nested namespaces don't see variables in parent} {
261 namespace eval nsh1::nsh2 {set test_ns_var_hier1}
263 list [catch $cmd msg] $msg
264 } {1 {can't read "test_ns_var_hier1": no such variable}}
265 test namespace-5.8 {nested namespaces don't see commands in parent} {
267 namespace eval nsh1::nsh2 {test_ns_cmd_hier1}
269 list [catch $cmd msg] $msg
270 } {1 {invalid command name "test_ns_cmd_hier1"}}
272 test namespace-5.18 {usage for "namespace parent"} {
273 list [catch {namespace parent x y} msg] $msg
274 } {1 {wrong # args: should be "namespace parent ?name?"}}
276 test namespace-5.20 {querying namespace parent} {
277 list [namespace eval :: {namespace parent}] \
278 [namespace eval nsh1 {namespace parent}] \
279 [namespace eval nsh1::nsh2 {namespace parent}] \
280 [namespace eval nsh1::nsh2::nsh3a {namespace parent}] \
281 } {{} :: ::nsh1 ::nsh1::nsh2}
283 test namespace-5.21 {querying namespace parent for explicit namespace} {
284 list [namespace parent ::] \
285 [namespace parent nsh1] \
286 [namespace parent nsh1::nsh2] \
287 [namespace parent nsh1::nsh2::nsh3a]
288 } {{} :: ::nsh1 ::nsh1::nsh2}
290 # -----------------------------------------------------------------------
291 # TEST: name resolution and caching
292 # -----------------------------------------------------------------------
293 test namespace-6.1 {relative ns names only looked up in current ns} {
294 namespace eval tns1 {}
295 namespace eval tns2 {}
296 namespace eval tns2::test_ns_cache3 {}
298 namespace eval tns2 {namespace current}
301 namespace eval tns2::test_ns_cache3 {namespace current}
303 list [namespace eval tns1 $trigger] \
304 [namespace eval tns1 $trigger2]
305 } {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
306 test namespace-6.2 {relative ns names only looked up in current ns} {
307 namespace eval tns1::tns2 {}
308 list [namespace eval tns1 $trigger] \
309 [namespace eval tns1 $trigger2]
310 } {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
311 test namespace-6.3 {relative ns names only looked up in current ns} {
312 namespace eval tns1::tns2::test_ns_cache3 {}
313 list [namespace eval tns1 $trigger] \
314 [namespace eval tns1 $trigger2]
315 } {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
316 test namespace-6.4 {relative ns names only looked up in current ns} {
317 namespace delete tns1::tns2
318 list [namespace eval tns1 $trigger] \
319 [namespace eval tns1 $trigger2]
320 } {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
322 test namespace-6.5 {define test commands} {
324 return "global version"
326 namespace eval tns1 {
334 test namespace-6.6 {one-level check for command shadowing} {
335 proc tns1::testcmd {} {
336 return "cache1 version"
341 test namespace-6.7 {renaming commands changes command epoch} {
342 namespace eval tns1 {
343 rename testcmd testcmd_new
347 test namespace-6.8 {renaming back handles shadowing} {
348 namespace eval tns1 {
349 rename testcmd_new testcmd
353 test namespace-6.9 {deleting commands changes command epoch} {
354 namespace eval tns1 {
359 test namespace-6.10 {define test namespaces} {
360 namespace eval tns2 {
362 return "global cache2 version"
365 namespace eval tns1 {
370 namespace eval tns1::tns2 {
375 list [tns1::trigger] [tns1::tns2::trigger]
376 } {{global cache2 version} {global version}}
378 test namespace-6.11 {commands affect all parent namespaces} {
379 proc tns1::tns2::testcmd {} {
380 return "cache2 version"
382 list [tns1::trigger] [tns1::tns2::trigger]
383 } {{cache2 version} {cache2 version}}
385 # -----------------------------------------------------------------------
386 # TEST: uplevel/upvar across namespace boundaries
387 # -----------------------------------------------------------------------
388 # Note that Tcl behaves a little differently for uplevel and upvar
390 test namespace-7.1 {uplevel in namespace eval} jim {
392 namespace eval uns1 {
399 test namespace-7.2 {upvar in ns proc} jim {
400 proc uns1::getvar {v} {
408 # -----------------------------------------------------------------------
409 # TEST: scoped values
410 # -----------------------------------------------------------------------
411 test namespace-10.1 {define namespace for scope test} {
412 namespace eval ins1 {
420 list [set x] [show test]
422 } {x-value {show: test}}
424 test namespace-10.2 {command "namespace code" requires one argument} {
425 list [catch {namespace code} msg] $msg
426 } {1 {wrong # args: should be "namespace code arg"}}
428 test namespace-10.3 {command "namespace code" requires one argument} {
429 list [catch {namespace code first "second arg" third} msg] $msg
430 } {1 {wrong # args: should be "namespace code arg"}}
432 test namespace-10.4 {command "namespace code" gets current namesp context} {
433 namespace eval ins1 {
434 namespace code {"1 2 3" "4 5" 6}
436 } {::namespace inscope ::ins1 {"1 2 3" "4 5" 6}}
438 test namespace-10.5 {with one arg, first "scope" sticks} {
439 set sval [namespace eval ins1 {namespace code {one two}}]
441 } {::namespace inscope ::ins1 {one two}}
443 test namespace-10.6 {with many args, each "scope" adds new args} {
444 set sval [namespace eval ins1 {namespace code {one two}}]
445 namespace code "$sval three"
446 } {::namespace inscope ::ins1 {one two} three}
448 test namespace-10.7 {scoped commands work with eval} {
449 set cref [namespace eval ins1 {namespace code show}]
450 list [eval $cref "a" "b c" "d e f"]
451 } {{show: a b c d e f}}
453 test namespace-10.8 {scoped commands execute in namespace context} {
454 set cref [namespace eval ins1 {
455 namespace code {variable x; set x "some new value"}
457 list [set ins1::x] [eval $cref] [set ins1::x]
458 } {x-value {some new value} {some new value}}
460 test namespace-11.1 {command caching} {
461 proc cmd1 {} { return global }
464 proc cmd1 {} { return ns1 }
468 lappend ::result [cmd2]
470 lappend result [ns1::cmd2]
473 test namespace-12.1 {namespace import} {
474 namespace eval test_ns_scope1 {
475 proc a {} { return a }
478 namespace eval test_ns_scope2 {
479 namespace import ::test_ns_scope1::a
484 test namespace-12.2 {namespace import recursive} -body {
486 } -returnCodes error -match glob -result {import pattern "*" tries to import from namespace "*" into itself}
488 foreach cmd [info commands test_ns_*] {
492 catch {rename cmd {}}
493 catch {rename cmd1 {}}
494 catch {rename cmd2 {}}
495 catch {rename ncmd {}}
496 catch {rename ncmd1 {}}
497 catch {rename ncmd2 {}}
499 catch {unset trigger}
500 catch {unset trigger2}
504 catch {unset test_ns_var_global}
506 catch {eval namespace delete [namespace children :: test_ns_*]}
509 ::tcltest::cleanupTests