# Functionality covered: this file contains a collection of tests for the # procedures in tclNamesp.c that implement Tcl's basic support for # namespaces. Other namespace-related tests appear in variable.test. # # Sourcing this file into Tcl runs the tests and generates output for # errors. No output means no errors were found. # # Copyright (c) 1997 Sun Microsystems, Inc. # Copyright (c) 1998-2000 by Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: namespace.test,v 1.66.2.3 2007/11/21 06:30:57 dgp Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* } # # REMARK: the tests for 'namespace upvar' are not done here. They are to be # found in the file 'upvar.test'. # # Clear out any namespaces called test_ns_* catch {namespace delete {*}[namespace children :: test_ns_*]} test namespace-1.1 {TclInitNamespaces, GetNamespaceFromObj, NamespaceChildrenCmd} { namespace children :: test_ns_* } {} catch {unset l} test namespace-2.1 {Tcl_GetCurrentNamespace} { list [namespace current] [namespace eval {} {namespace current}] \ [namespace eval {} {namespace current}] } {:: :: ::} test namespace-2.2 {Tcl_GetCurrentNamespace} { set l {} lappend l [namespace current] namespace eval test_ns_1 { lappend l [namespace current] namespace eval foo { lappend l [namespace current] } } lappend l [namespace current] set l } {:: ::test_ns_1 ::test_ns_1::foo ::} test namespace-3.1 {Tcl_GetGlobalNamespace} { namespace eval test_ns_1 {namespace eval foo {namespace eval bar {} } } # namespace children uses Tcl_GetGlobalNamespace namespace eval test_ns_1 {namespace children foo b*} } {::test_ns_1::foo::bar} test namespace-4.1 {Tcl_PushCallFrame with isProcCallFrame=1} { namespace eval test_ns_1 { variable v 123 proc p {} { variable v return $v } } test_ns_1::p ;# does Tcl_PushCallFrame to push p's namespace } {123} test namespace-4.2 {Tcl_PushCallFrame with isProcCallFrame=0} { namespace eval test_ns_1::baz {} ;# does Tcl_PushCallFrame to create baz proc test_ns_1::baz::p {} { variable v set v 789 set v} test_ns_1::baz::p } {789} test namespace-5.1 {Tcl_PopCallFrame, no vars} { namespace eval test_ns_1::blodge {} ;# pushes then pops frame } {} test namespace-5.2 {Tcl_PopCallFrame, local vars must be deleted} { proc test_ns_1::r {} { set a 123 } test_ns_1::r ;# pushes then pop's r's frame } {123} test namespace-6.1 {Tcl_CreateNamespace} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [lsort [namespace children :: test_ns_*]] \ [namespace eval test_ns_1 {namespace current}] \ [namespace eval test_ns_2 {namespace current}] \ [namespace eval ::test_ns_3 {namespace current}] \ [namespace eval ::test_ns_4 \ {namespace eval foo {namespace current}}] \ [namespace eval ::test_ns_5 \ {namespace eval ::test_ns_6 {namespace current}}] \ [lsort [namespace children :: test_ns_*]] } {{} ::test_ns_1 ::test_ns_2 ::test_ns_3 ::test_ns_4::foo ::test_ns_6 {::test_ns_1 ::test_ns_2 ::test_ns_3 ::test_ns_4 ::test_ns_5 ::test_ns_6}} test namespace-6.2 {Tcl_CreateNamespace, odd number of :'s in name is okay} { list [namespace eval :::test_ns_1::::foo {namespace current}] \ [namespace eval test_ns_2:::::foo {namespace current}] } {::test_ns_1::foo ::test_ns_2::foo} test namespace-6.3 {Tcl_CreateNamespace, trailing ::s in ns name are ignored} { list [catch {namespace eval test_ns_7::: {namespace current}} msg] $msg } {0 ::test_ns_7} test namespace-6.4 {Tcl_CreateNamespace, trailing ::s in ns name are ignored} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1:: { namespace eval test_ns_2:: {} namespace eval test_ns_3:: {} } lsort [namespace children ::test_ns_1] } [lsort {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_3}] test namespace-6.5 {Tcl_CreateNamespace, relative ns names now only looked up in current ns} { set trigger { namespace eval test_ns_2 {namespace current} } set l {} lappend l [namespace eval test_ns_1 $trigger] namespace eval test_ns_1::test_ns_2 {} lappend l [namespace eval test_ns_1 $trigger] } {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_2} test namespace-7.1 {Tcl_DeleteNamespace, active call frames in ns} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1 { proc p {} { namespace delete [namespace current] return [namespace current] } } list [test_ns_1::p] [catch {test_ns_1::p} msg] $msg } {::test_ns_1 1 {invalid command name "test_ns_1::p"}} test namespace-7.2 {Tcl_DeleteNamespace, no active call frames in ns} { namespace eval test_ns_2 { proc p {} { return [namespace current] } } list [test_ns_2::p] [namespace delete test_ns_2] } {::test_ns_2 {}} test namespace-7.3 {recursive Tcl_DeleteNamespace, active call frames in ns} { # [Bug 1355942] namespace eval test_ns_2 { set x 1 trace add variable x unset "namespace delete [namespace current];#" namespace delete [namespace current] } } {} test namespace-7.4 {recursive Tcl_DeleteNamespace, active call frames in ns} { # [Bug 1355942] namespace eval test_ns_2 { proc x {} {} trace add command x delete "namespace delete [namespace current];#" namespace delete [namespace current] } } {} test namespace-7.5 {recursive Tcl_DeleteNamespace, no active call frames in ns} { # [Bug 1355942] namespace eval test_ns_2 { set x 1 trace add variable x unset "namespace delete [namespace current];#" } namespace delete test_ns_2 } {} test namespace-7.6 {recursive Tcl_DeleteNamespace, no active call frames in ns} { # [Bug 1355942] namespace eval test_ns_2 { proc x {} {} trace add command x delete "namespace delete [namespace current];#" } namespace delete test_ns_2 } {} test namespace-7.7 {Bug 1655305} -setup { interp create slave # Can't invoke through the ensemble, since deleting the global namespace # (indirectly, via deleting ::tcl) deletes the ensemble. slave eval {rename ::tcl::info::commands ::infocommands} slave hide infocommands slave eval { proc foo {} { namespace delete :: } } } -body { slave eval foo slave invokehidden infocommands } -cleanup { interp delete slave } -result {} test namespace-8.1 {TclTeardownNamespace, delete global namespace} { catch {interp delete test_interp} interp create test_interp interp eval test_interp { namespace eval test_ns_1 { namespace export p proc p {} { return [namespace current] } } namespace eval test_ns_2 { namespace import ::test_ns_1::p variable v 27 proc q {} { variable v return "[p] $v" } } set x [test_ns_2::q] catch {set xxxx} } list [interp eval test_interp {test_ns_2::q}] \ [interp eval test_interp {namespace delete ::}] \ [catch {interp eval test_interp {set a 123}} msg] $msg \ [interp delete test_interp] } {{::test_ns_1 27} {} 1 {invalid command name "set"} {}} test namespace-8.2 {TclTeardownNamespace, remove deleted ns from parent} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1::test_ns_2::test_ns_3a {proc p {} {}} namespace eval test_ns_1::test_ns_2::test_ns_3b {proc q {} {}} list [namespace children test_ns_1] \ [namespace delete test_ns_1::test_ns_2] \ [namespace children test_ns_1] } {::test_ns_1::test_ns_2 {} {}} test namespace-8.3 {TclTeardownNamespace, delete child namespaces} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1::test_ns_2::test_ns_3a {proc p {} {}} namespace eval test_ns_1::test_ns_2::test_ns_3b {proc q {} {}} list [namespace children test_ns_1] \ [namespace delete test_ns_1::test_ns_2] \ [namespace children test_ns_1] \ [catch {namespace children test_ns_1::test_ns_2} msg] $msg \ [info commands test_ns_1::test_ns_2::test_ns_3a::*] } {::test_ns_1::test_ns_2 {} {} 1 {namespace "test_ns_1::test_ns_2" not found in "::"} {}} test namespace-8.4 {TclTeardownNamespace, cmds imported from deleted ns go away} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_export { namespace export cmd1 cmd2 proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_import { namespace import ::test_ns_export::* proc p {} {return foo} } list [lsort [info commands test_ns_import::*]] \ [namespace delete test_ns_export] \ [info commands test_ns_import::*] } [list [lsort {::test_ns_import::p ::test_ns_import::cmd1 ::test_ns_import::cmd2}] {} ::test_ns_import::p] test namespace-8.5 {TclTeardownNamespace: preserve errorInfo; errorCode values} { interp create slave slave eval {trace add execution error leave {namespace delete :: ;#}} catch {slave eval error foo bar baz} interp delete slave set ::errorInfo } {bar invoked from within "slave eval error foo bar baz"} test namespace-8.6 {TclTeardownNamespace: preserve errorInfo; errorCode values} { interp create slave slave eval {trace add variable errorCode write {namespace delete :: ;#}} catch {slave eval error foo bar baz} interp delete slave set ::errorInfo } {bar invoked from within "slave eval error foo bar baz"} test namespace-8.7 {TclTeardownNamespace: preserve errorInfo; errorCode values} { interp create slave slave eval {trace add execution error leave {namespace delete :: ;#}} catch {slave eval error foo bar baz} interp delete slave set ::errorCode } baz test namespace-9.1 {Tcl_Import, empty import pattern} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace eval test_ns_import {namespace import {}}} msg] $msg } {1 {empty import pattern}} test namespace-9.2 {Tcl_Import, unknown namespace in import pattern} { list [catch {namespace eval test_ns_import {namespace import fred::x}} msg] $msg } {1 {unknown namespace in import pattern "fred::x"}} test namespace-9.3 {Tcl_Import, import ns == export ns} { list [catch {namespace eval test_ns_import {namespace import ::test_ns_import::puts}} msg] $msg } {1 {import pattern "::test_ns_import::puts" tries to import from namespace "test_ns_import" into itself}} test namespace-9.4 {Tcl_Import, simple import} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_export { namespace export cmd1 proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_import { namespace import ::test_ns_export::* proc p {} {return [cmd1 123]} } test_ns_import::p } {cmd1: 123} test namespace-9.5 {Tcl_Import, can't redefine cmd unless allowOverwrite!=0} { list [catch {namespace eval test_ns_import {namespace import ::test_ns_export::*}} msg] $msg } {0 {}} test namespace-9.6 {Tcl_Import, cmd redefinition ok if allowOverwrite!=0} { namespace eval test_ns_import { namespace import -force ::test_ns_export::* cmd1 555 } } {cmd1: 555} test namespace-9.7 {Tcl_Import, links are preserved if cmd is redefined} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_export { namespace export cmd1 proc cmd1 {args} {return "cmd1: $args"} } namespace eval test_ns_import { namespace import -force ::test_ns_export::* } list [test_ns_import::cmd1 a b c] \ [test_ns_export::cmd1 d e f] \ [proc test_ns_export::cmd1 {args} {return "new1: $args"}] \ [namespace origin test_ns_import::cmd1] \ [namespace origin test_ns_export::cmd1] \ [test_ns_import::cmd1 g h i] \ [test_ns_export::cmd1 j k l] } {{cmd1: a b c} {cmd1: d e f} {} ::test_ns_export::cmd1 ::test_ns_export::cmd1 {new1: g h i} {new1: j k l}} test namespace-9.8 {Tcl_Import: Bug 1017299} -setup { namespace eval one { namespace export cmd proc cmd {} {} } namespace eval two { namespace export cmd proc other args {} } namespace eval two \ [list namespace import [namespace current]::one::cmd] namespace eval three \ [list namespace import [namespace current]::two::cmd] namespace eval three { rename cmd other namespace export other } } -body { namespace eval two [list namespace import -force \ [namespace current]::three::other] namespace origin two::other } -cleanup { namespace delete one two three } -match glob -result *::one::cmd test namespace-9.9 {Tcl_Import: Bug 1017299} -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-10.1 {Tcl_ForgetImport, check for valid namespaces} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace forget xyzzy::*} msg] $msg } {1 {unknown namespace in namespace forget pattern "xyzzy::*"}} test namespace-10.2 {Tcl_ForgetImport, ignores patterns that don't match} { namespace eval test_ns_export { namespace export cmd1 proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_import { namespace forget ::test_ns_export::wombat } } {} test namespace-10.3 {Tcl_ForgetImport, deletes matching imported cmds} { namespace eval test_ns_import { namespace import ::test_ns_export::* proc p {} {return [cmd1 123]} set l {} lappend l [lsort [info commands ::test_ns_import::*]] namespace forget ::test_ns_export::cmd1 lappend l [info commands ::test_ns_import::*] lappend l [catch {cmd1 777} msg] $msg } } [list [lsort {::test_ns_import::p ::test_ns_import::cmd1}] ::test_ns_import::p 1 {invalid command name "cmd1"}] test namespace-10.4 {Tcl_ForgetImport: Bug 560297} -setup { namespace eval origin { namespace export cmd proc cmd {} {} } namespace eval unrelated { proc cmd {} {} } namespace eval my \ [list namespace import [namespace current]::origin::cmd] } -body { namespace eval my \ [list namespace forget [namespace current]::unrelated::cmd] my::cmd } -cleanup { namespace delete origin unrelated my } test namespace-10.5 {Tcl_ForgetImport: Bug 560297} -setup { namespace eval origin { namespace export cmd proc cmd {} {} } namespace eval my \ [list namespace import [namespace current]::origin::cmd] namespace eval my rename cmd newname } -body { namespace eval my \ [list namespace forget [namespace current]::origin::cmd] my::newname } -cleanup { namespace delete origin my } -returnCodes error -match glob -result * test namespace-10.6 {Tcl_ForgetImport: Bug 560297} -setup { namespace eval origin { namespace export cmd proc cmd {} {} } namespace eval my \ [list namespace import [namespace current]::origin::cmd] namespace eval your {} namespace eval my \ [list rename cmd [namespace current]::your::newname] } -body { namespace eval your namespace forget newname your::newname } -cleanup { namespace delete origin my your } -returnCodes error -match glob -result * test namespace-10.7 {Tcl_ForgetImport: Bug 560297} -setup { namespace eval origin { namespace export cmd proc cmd {} {} } namespace eval link namespace export cmd namespace eval link \ [list namespace import [namespace current]::origin::cmd] namespace eval link2 namespace export cmd namespace eval link2 \ [list namespace import [namespace current]::link::cmd] namespace eval my \ [list namespace import [namespace current]::link2::cmd] } -body { namespace eval my \ [list namespace forget [namespace current]::origin::cmd] my::cmd } -cleanup { namespace delete origin link link2 my } -returnCodes error -match glob -result * test namespace-10.8 {Tcl_ForgetImport: Bug 560297} -setup { namespace eval origin { namespace export cmd proc cmd {} {} } namespace eval link namespace export cmd namespace eval link \ [list namespace import [namespace current]::origin::cmd] namespace eval link2 namespace export cmd namespace eval link2 \ [list namespace import [namespace current]::link::cmd] namespace eval my \ [list namespace import [namespace current]::link2::cmd] } -body { namespace eval my \ [list namespace forget [namespace current]::link::cmd] my::cmd } -cleanup { namespace delete origin link link2 my } test namespace-10.9 {Tcl_ForgetImport: Bug 560297} -setup { namespace eval origin { namespace export cmd proc cmd {} {} } namespace eval link namespace export cmd namespace eval link \ [list namespace import [namespace current]::origin::cmd] namespace eval link2 namespace export cmd namespace eval link2 \ [list namespace import [namespace current]::link::cmd] namespace eval my \ [list namespace import [namespace current]::link2::cmd] } -body { namespace eval my \ [list namespace forget [namespace current]::link2::cmd] my::cmd } -cleanup { namespace delete origin link link2 my } -returnCodes error -match glob -result * test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_export { namespace export cmd1 proc cmd1 {args} {return "cmd1: $args"} } list [namespace origin set] [namespace origin test_ns_export::cmd1] } {::set ::test_ns_export::cmd1} test namespace-11.2 {TclGetOriginalCommand, directly imported cmd} { namespace eval test_ns_import1 { namespace import ::test_ns_export::* namespace export * proc p {} {namespace origin cmd1} } list [test_ns_import1::p] [namespace origin test_ns_import1::cmd1] } {::test_ns_export::cmd1 ::test_ns_export::cmd1} test namespace-11.3 {TclGetOriginalCommand, indirectly imported cmd} { namespace eval test_ns_import2 { namespace import ::test_ns_import1::* proc q {} {return [cmd1 123]} } list [test_ns_import2::q] [namespace origin test_ns_import2::cmd1] } {{cmd1: 123} ::test_ns_export::cmd1} test namespace-12.1 {InvokeImportedCmd} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_export { namespace export cmd1 proc cmd1 {args} {namespace current} } namespace eval test_ns_import { namespace import ::test_ns_export::* } list [test_ns_import::cmd1] } {::test_ns_export} test namespace-13.1 {DeleteImportedCmd, deletes imported cmds} { namespace eval test_ns_import { set l {} lappend l [info commands ::test_ns_import::*] namespace forget ::test_ns_export::cmd1 lappend l [info commands ::test_ns_import::*] } } {::test_ns_import::cmd1 {}} test namespace-14.1 {TclGetNamespaceForQualName, absolute names} { catch {namespace delete {*}[namespace children :: test_ns_*]} variable v 10 namespace eval test_ns_1::test_ns_2 { variable v 20 } namespace eval test_ns_2 { variable v 30 } namespace eval test_ns_1 { list $::v $::test_ns_2::v $::test_ns_1::test_ns_2::v \ [lsort [namespace children :: test_ns_*]] } } [list 10 30 20 [lsort {::test_ns_1 ::test_ns_2}]] test namespace-14.2 {TclGetNamespaceForQualName, invalid absolute names} { namespace eval test_ns_1 { list [catch {set ::test_ns_777::v} msg] $msg \ [catch {namespace children test_ns_777} msg] $msg } } {1 {can't read "::test_ns_777::v": no such variable} 1 {namespace "test_ns_777" not found in "::test_ns_1"}} test namespace-14.3 {TclGetNamespaceForQualName, relative names} { namespace eval test_ns_1 { list $v $test_ns_2::v } } {10 20} test namespace-14.4 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} { namespace eval test_ns_1::test_ns_2 { namespace eval foo {} } namespace eval test_ns_1 { list [namespace children test_ns_2] \ [catch {namespace children test_ns_1} msg] $msg } } {::test_ns_1::test_ns_2::foo 1 {namespace "test_ns_1" not found in "::test_ns_1"}} test namespace-14.5 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} { namespace eval ::test_ns_2 { namespace eval bar {} } namespace eval test_ns_1 { set l [list [catch {namespace delete test_ns_2::bar} msg] $msg] } set l } {1 {unknown namespace "test_ns_2::bar" in namespace delete command}} test namespace-14.6 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} { namespace eval test_ns_1::test_ns_2 { namespace eval foo {} } namespace eval test_ns_1 { list [namespace children test_ns_2] \ [catch {namespace children test_ns_1} msg] $msg } } {::test_ns_1::test_ns_2::foo 1 {namespace "test_ns_1" not found in "::test_ns_1"}} test namespace-14.7 {TclGetNamespaceForQualName, ignore extra :s if ns} { namespace children test_ns_1::: } {::test_ns_1::test_ns_2} test namespace-14.8 {TclGetNamespaceForQualName, ignore extra :s if ns} { namespace children :::test_ns_1:::::test_ns_2::: } {::test_ns_1::test_ns_2::foo} test namespace-14.9 {TclGetNamespaceForQualName, extra ::s are significant for vars} { set l {} lappend l [catch {set test_ns_1::test_ns_2::} msg] $msg namespace eval test_ns_1::test_ns_2 {variable {} 2525} lappend l [set test_ns_1::test_ns_2::] } {1 {can't read "test_ns_1::test_ns_2::": no such variable} 2525} test namespace-14.10 {TclGetNamespaceForQualName, extra ::s are significant for vars} { catch {unset test_ns_1::test_ns_2::} set l {} lappend l [catch {set test_ns_1::test_ns_2::} msg] $msg set test_ns_1::test_ns_2:: 314159 lappend l [set test_ns_1::test_ns_2::] } {1 {can't read "test_ns_1::test_ns_2::": no such variable} 314159} test namespace-14.11 {TclGetNamespaceForQualName, extra ::s are significant for commands} { catch {rename test_ns_1::test_ns_2:: {}} set l {} lappend l [catch {test_ns_1::test_ns_2:: hello} msg] $msg proc test_ns_1::test_ns_2:: {args} {return "\{\}: $args"} lappend l [test_ns_1::test_ns_2:: hello] } {1 {invalid command name "test_ns_1::test_ns_2::"} {{}: hello}} test namespace-14.12 {TclGetNamespaceForQualName, extra ::s are significant for vars} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1 { variable {} set test_ns_1::(x) y } set test_ns_1::(x) } y test namespace-14.13 {TclGetNamespaceForQualName, namespace other than global ns can't have empty name} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace eval test_ns_1 {proc {} {} {}; namespace eval {} {}; {}}} msg] $msg } {1 {can't create namespace "": only global namespace can have empty name}} test namespace-15.1 {Tcl_FindNamespace, absolute name found} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_delete { namespace eval test_ns_delete2 {} proc cmd {args} {namespace current} } list [namespace delete ::test_ns_delete::test_ns_delete2] \ [namespace children ::test_ns_delete] } {{} {}} test namespace-15.2 {Tcl_FindNamespace, absolute name not found} { list [catch {namespace delete ::test_ns_delete::test_ns_delete2} msg] $msg } {1 {unknown namespace "::test_ns_delete::test_ns_delete2" in namespace delete command}} test namespace-15.3 {Tcl_FindNamespace, relative name found} { namespace eval test_ns_delete { namespace eval test_ns_delete2 {} namespace eval test_ns_delete3 {} list [namespace delete test_ns_delete2] \ [namespace children [namespace current]] } } {{} ::test_ns_delete::test_ns_delete3} test namespace-15.4 {Tcl_FindNamespace, relative name not found} { namespace eval test_ns_delete2 {} namespace eval test_ns_delete { list [catch {namespace delete test_ns_delete2} msg] $msg } } {1 {unknown namespace "test_ns_delete2" in namespace delete command}} test namespace-16.1 {Tcl_FindCommand, absolute name found} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1 { proc cmd {args} {return "[namespace current]::cmd: $args"} variable v "::test_ns_1::cmd" eval $v one } } {::test_ns_1::cmd: one} test namespace-16.2 {Tcl_FindCommand, absolute name found} { eval $test_ns_1::v two } {::test_ns_1::cmd: two} test namespace-16.3 {Tcl_FindCommand, absolute name not found} { namespace eval test_ns_1 { variable v2 "::test_ns_1::ladidah" list [catch {eval $v2} msg] $msg } } {1 {invalid command name "::test_ns_1::ladidah"}} # save the "unknown" proc, which is redefined by the following two tests catch {rename unknown unknown.old} proc unknown {args} { return "unknown: $args" } test namespace-16.4 {Tcl_FindCommand, absolute name and TCL_GLOBAL_ONLY} { ::test_ns_1::foobar x y z } {unknown: ::test_ns_1::foobar x y z} test namespace-16.5 {Tcl_FindCommand, absolute name and TCL_GLOBAL_ONLY} { ::foobar 1 2 3 4 5 } {unknown: ::foobar 1 2 3 4 5} test namespace-16.6 {Tcl_FindCommand, relative name and TCL_GLOBAL_ONLY} { test_ns_1::foobar x y z } {unknown: test_ns_1::foobar x y z} test namespace-16.7 {Tcl_FindCommand, relative name and TCL_GLOBAL_ONLY} { foobar 1 2 3 4 5 } {unknown: foobar 1 2 3 4 5} # restore the "unknown" proc saved previously catch {rename unknown {}} catch {rename unknown.old unknown} test namespace-16.8 {Tcl_FindCommand, relative name found} { namespace eval test_ns_1 { cmd a b c } } {::test_ns_1::cmd: a b c} test namespace-16.9 {Tcl_FindCommand, relative name found} { catch {rename cmd2 {}} proc cmd2 {args} {return "[namespace current]::cmd2: $args"} namespace eval test_ns_1 { cmd2 a b c } } {::::cmd2: a b c} test namespace-16.10 {Tcl_FindCommand, relative name found, only look in current then global ns} { namespace eval test_ns_1 { proc cmd2 {args} { return "[namespace current]::cmd2 in test_ns_1: $args" } namespace eval test_ns_12 { cmd2 a b c } } } {::::cmd2: a b c} test namespace-16.11 {Tcl_FindCommand, relative name not found} { namespace eval test_ns_1 { list [catch {cmd3 a b c} msg] $msg } } {1 {invalid command name "cmd3"}} catch {unset x} test namespace-17.1 {Tcl_FindNamespaceVar, absolute name found} { catch {namespace delete {*}[namespace children :: test_ns_*]} set x 314159 namespace eval test_ns_1 { set ::x } } {314159} test namespace-17.2 {Tcl_FindNamespaceVar, absolute name found} { namespace eval test_ns_1 { variable x 777 set ::test_ns_1::x } } {777} test namespace-17.3 {Tcl_FindNamespaceVar, absolute name found} { namespace eval test_ns_1 { namespace eval test_ns_2 { variable x 1111 } set ::test_ns_1::test_ns_2::x } } {1111} test namespace-17.4 {Tcl_FindNamespaceVar, absolute name not found} { namespace eval test_ns_1 { namespace eval test_ns_2 { variable x 1111 } list [catch {set ::test_ns_1::test_ns_2::y} msg] $msg } } {1 {can't read "::test_ns_1::test_ns_2::y": no such variable}} test namespace-17.5 {Tcl_FindNamespaceVar, absolute name and TCL_GLOBAL_ONLY} { namespace eval test_ns_1 { namespace eval test_ns_3 { variable ::test_ns_1::test_ns_2::x 2222 } } set ::test_ns_1::test_ns_2::x } {2222} test namespace-17.6 {Tcl_FindNamespaceVar, relative name found} { namespace eval test_ns_1 { set x } } {777} test namespace-17.7 {Tcl_FindNamespaceVar, relative name found} { namespace eval test_ns_1 { unset x set x ;# must be global x now } } {314159} test namespace-17.8 {Tcl_FindNamespaceVar, relative name not found} { namespace eval test_ns_1 { list [catch {set wuzzat} msg] $msg } } {1 {can't read "wuzzat": no such variable}} test namespace-17.9 {Tcl_FindNamespaceVar, relative name and TCL_GLOBAL_ONLY} { namespace eval test_ns_1 { variable a hello } set test_ns_1::a } {hello} test namespace-17.10 {Tcl_FindNamespaceVar, interference with cached varNames} { namespace eval test_ns_1 {} proc test_ns {} { set ::test_ns_1::a 0 } test_ns rename test_ns {} namespace eval test_ns_1 unset a set a 0 namespace eval test_ns_1 set a 1 namespace delete test_ns_1 set a } 1 catch {unset a} catch {unset x} catch {unset l} catch {rename foo {}} test namespace-18.1 {TclResetShadowedCmdRefs, one-level check for command shadowing} { catch {namespace delete {*}[namespace children :: test_ns_*]} proc foo {} {return "global foo"} namespace eval test_ns_1 { proc trigger {} { return [foo] } } set l "" lappend l [test_ns_1::trigger] namespace eval test_ns_1 { # force invalidation of cached ref to "foo" in proc trigger proc foo {} {return "foo in test_ns_1"} } lappend l [test_ns_1::trigger] set l } {{global foo} {foo in test_ns_1}} test namespace-18.2 {TclResetShadowedCmdRefs, multilevel check for command shadowing} { namespace eval test_ns_2 { proc foo {} {return "foo in ::test_ns_2"} } namespace eval test_ns_1 { namespace eval test_ns_2 {} proc trigger {} { return [test_ns_2::foo] } } set l "" lappend l [test_ns_1::trigger] namespace eval test_ns_1 { namespace eval test_ns_2 { # force invalidation of cached ref to "foo" in proc trigger proc foo {} {return "foo in ::test_ns_1::test_ns_2"} } } lappend l [test_ns_1::trigger] set l } {{foo in ::test_ns_2} {foo in ::test_ns_1::test_ns_2}} catch {unset l} catch {rename foo {}} test namespace-19.1 {GetNamespaceFromObj, global name found} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1::test_ns_2 {} namespace children ::test_ns_1 } {::test_ns_1::test_ns_2} test namespace-19.2 {GetNamespaceFromObj, relative name found} { namespace eval test_ns_1 { namespace children test_ns_2 } } {} test namespace-19.3 {GetNamespaceFromObj, name not found} -body { namespace eval test_ns_1 { namespace children test_ns_99 } } -returnCodes error -result {namespace "test_ns_99" not found in "::test_ns_1"} test namespace-19.4 {GetNamespaceFromObj, invalidation of cached ns refs} { namespace eval test_ns_1 { proc foo {} { return [namespace children test_ns_2] } list [catch {namespace children test_ns_99} msg] $msg } set l {} lappend l [test_ns_1::foo] namespace delete test_ns_1::test_ns_2 namespace eval test_ns_1::test_ns_2::test_ns_3 {} lappend l [test_ns_1::foo] set l } {{} ::test_ns_1::test_ns_2::test_ns_3} test namespace-20.1 {Tcl_NamespaceObjCmd, bad subcommand} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace} msg] $msg } {1 {wrong # args: should be "namespace subcommand ?arg ...?"}} test namespace-20.2 {Tcl_NamespaceObjCmd, bad subcommand} -body { namespace wombat {} } -returnCodes error -match glob -result {bad option "wombat": must be *} test namespace-20.3 {Tcl_NamespaceObjCmd, abbreviations are okay} { namespace ch :: test_ns_* } {} test namespace-21.1 {NamespaceChildrenCmd, no args} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1::test_ns_2 {} expr {[string first ::test_ns_1 [namespace children]] != -1} } {1} test namespace-21.2 {NamespaceChildrenCmd, no args} { namespace eval test_ns_1 { namespace children } } {::test_ns_1::test_ns_2} test namespace-21.3 {NamespaceChildrenCmd, ns name given} { namespace children ::test_ns_1 } {::test_ns_1::test_ns_2} test namespace-21.4 {NamespaceChildrenCmd, ns name given} { namespace eval test_ns_1 { namespace children test_ns_2 } } {} test namespace-21.5 {NamespaceChildrenCmd, too many args} { namespace eval test_ns_1 { list [catch {namespace children test_ns_2 xxx yyy} msg] $msg } } {1 {wrong # args: should be "namespace children ?name? ?pattern?"}} test namespace-21.6 {NamespaceChildrenCmd, glob-style pattern given} { namespace eval test_ns_1::test_ns_foo {} namespace children test_ns_1 *f* } {::test_ns_1::test_ns_foo} test namespace-21.7 {NamespaceChildrenCmd, glob-style pattern given} { namespace eval test_ns_1::test_ns_foo {} lsort [namespace children test_ns_1 test*] } [lsort {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_foo}] test namespace-21.8 {NamespaceChildrenCmd, trivial pattern starting with ::} { namespace eval test_ns_1 {} namespace children [namespace current] \ [string trimright [namespace current] :]::test_ns_1 } [string trimright [namespace current] :]::test_ns_1 test namespace-22.1 {NamespaceCodeCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace code} msg] $msg \ [catch {namespace code xxx yyy} msg] $msg } {1 {wrong # args: should be "namespace code arg"} 1 {wrong # args: should be "namespace code arg"}} test namespace-22.2 {NamespaceCodeCmd, arg is already scoped value} { namespace eval test_ns_1 { proc cmd {} {return "test_ns_1::cmd"} } namespace code {namespace inscope ::test_ns_1 cmd} } {namespace inscope ::test_ns_1 cmd} test namespace-22.3 {NamespaceCodeCmd, arg is already scoped value} { namespace code {namespace inscope ::test_ns_1 cmd} } {namespace inscope ::test_ns_1 cmd} test namespace-22.4 {NamespaceCodeCmd, in :: namespace} { namespace code unknown } {::namespace inscope :: unknown} test namespace-22.5 {NamespaceCodeCmd, in other namespace} { namespace eval test_ns_1 { namespace code cmd } } {::namespace inscope ::test_ns_1 cmd} test namespace-22.6 {NamespaceCodeCmd, in other namespace} { namespace eval test_ns_1 { variable v 42 } namespace eval test_ns_2 { proc namespace args {} } namespace eval test_ns_2 [namespace eval test_ns_1 { namespace code {set v} }] } {42} test namespace-23.1 {NamespaceCurrentCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace current xxx} msg] $msg \ [catch {namespace current xxx yyy} msg] $msg } {1 {wrong # args: should be "namespace current"} 1 {wrong # args: should be "namespace current"}} test namespace-23.2 {NamespaceCurrentCmd, at global level} { namespace current } {::} test namespace-23.3 {NamespaceCurrentCmd, in nested ns} { namespace eval test_ns_1::test_ns_2 { namespace current } } {::test_ns_1::test_ns_2} test namespace-24.1 {NamespaceDeleteCmd, no args} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace delete } {} test namespace-24.2 {NamespaceDeleteCmd, one arg} { namespace eval test_ns_1::test_ns_2 {} namespace delete ::test_ns_1 } {} test namespace-24.3 {NamespaceDeleteCmd, two args} { namespace eval test_ns_1::test_ns_2 {} list [namespace delete ::test_ns_1::test_ns_2] [namespace delete ::test_ns_1] } {{} {}} test namespace-24.4 {NamespaceDeleteCmd, unknown ns} { list [catch {namespace delete ::test_ns_foo} msg] $msg } {1 {unknown namespace "::test_ns_foo" in namespace delete command}} test namespace-25.1 {NamespaceEvalCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace eval} msg] $msg } {1 {wrong # args: should be "namespace eval name arg ?arg...?"}} test namespace-25.2 {NamespaceEvalCmd, bad args} -body { namespace test_ns_1 } -returnCodes error -match glob -result {bad option "test_ns_1": must be *} catch {unset v} test namespace-25.3 {NamespaceEvalCmd, new namespace} { set v 123 namespace eval test_ns_1 { variable v 314159 proc p {} { variable v return $v } } test_ns_1::p } {314159} test namespace-25.4 {NamespaceEvalCmd, existing namespace} { namespace eval test_ns_1 { proc q {} {return [expr {[p]+1}]} } test_ns_1::q } {314160} test namespace-25.5 {NamespaceEvalCmd, multiple args} { namespace eval test_ns_1 "set" "v" } {314159} test namespace-25.6 {NamespaceEvalCmd, error in eval'd script} { list [catch {namespace eval test_ns_1 {xxxx}} msg] $msg $::errorInfo } {1 {invalid command name "xxxx"} {invalid command name "xxxx" while executing "xxxx" (in namespace eval "::test_ns_1" script line 1) invoked from within "namespace eval test_ns_1 {xxxx}"}} test namespace-25.7 {NamespaceEvalCmd, error in eval'd script} { list [catch {namespace eval test_ns_1 {error foo bar baz}} msg] $msg $::errorInfo } {1 foo {bar (in namespace eval "::test_ns_1" script line 1) invoked from within "namespace eval test_ns_1 {error foo bar baz}"}} test namespace-25.8 {NamespaceEvalCmd, error in eval'd script} { list [catch {namespace eval test_ns_1 error foo bar baz} msg] $msg $::errorInfo } {1 foo {bar (in namespace eval "::test_ns_1" script line 1) invoked from within "namespace eval test_ns_1 error foo bar baz"}} catch {unset v} test namespace-25.9 {NamespaceEvalCmd, 545325} { namespace eval test_ns_1 info level 0 } {namespace eval test_ns_1 info level 0} test namespace-26.1 {NamespaceExportCmd, no args and new ns} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace export } {} test namespace-26.2 {NamespaceExportCmd, just -clear arg} { namespace export -clear } {} test namespace-26.3 {NamespaceExportCmd, pattern can't specify a namespace} { namespace eval test_ns_1 { list [catch {namespace export ::zzz} msg] $msg } } {1 {invalid export pattern "::zzz": pattern can't specify a namespace}} test namespace-26.4 {NamespaceExportCmd, one pattern} { namespace eval test_ns_1 { namespace export cmd1 proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} proc cmd3 {args} {return "cmd3: $args"} proc cmd4 {args} {return "cmd4: $args"} } namespace eval test_ns_2 { namespace import ::test_ns_1::* } list [info commands test_ns_2::*] [test_ns_2::cmd1 hello] } {::test_ns_2::cmd1 {cmd1: hello}} test namespace-26.5 {NamespaceExportCmd, sequence of patterns, patterns accumulate} { namespace eval test_ns_1 { namespace export cmd1 cmd3 } namespace eval test_ns_2 { namespace import -force ::test_ns_1::* } list [lsort [info commands test_ns_2::*]] [test_ns_2::cmd3 hello] } [list [lsort {::test_ns_2::cmd1 ::test_ns_2::cmd3}] {cmd3: hello}] test namespace-26.6 {NamespaceExportCmd, no patterns means return uniq'ed export list} { namespace eval test_ns_1 { namespace export } } {cmd1 cmd3} test namespace-26.7 {NamespaceExportCmd, -clear resets export list} { namespace eval test_ns_1 { namespace export -clear cmd4 } namespace eval test_ns_2 { namespace import ::test_ns_1::* } list [lsort [info commands test_ns_2::*]] [test_ns_2::cmd4 hello] } [list [lsort {::test_ns_2::cmd4 ::test_ns_2::cmd1 ::test_ns_2::cmd3}] {cmd4: hello}] test namespace-27.1 {NamespaceForgetCmd, no args} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace forget } {} test namespace-27.2 {NamespaceForgetCmd, args must be valid namespaces} { list [catch {namespace forget ::test_ns_1::xxx} msg] $msg } {1 {unknown namespace in namespace forget pattern "::test_ns_1::xxx"}} test namespace-27.3 {NamespaceForgetCmd, arg is forgotten} { namespace eval test_ns_1 { namespace export cmd* proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_2 { namespace import ::test_ns_1::* namespace forget ::test_ns_1::cmd1 } info commands ::test_ns_2::* } {::test_ns_2::cmd2} test namespace-28.1 {NamespaceImportCmd, no args} { catch {namespace delete {*}[namespace children :: test_ns_*]} lsort [namespace import] } {bytestring cleanupTests configure customMatch debug errorChannel errorFile getMatchingFiles interpreter limitConstraints loadFile loadScript loadTestedCommands mainThread makeDirectory makeFile match matchDirectories matchFiles normalizeMsg normalizePath outputChannel outputFile preserveCore removeDirectory removeFile restoreState runAllTests saveState singleProcess skip skipDirectories skipFiles temporaryDirectory test testConstraint testsDirectory threadReap verbose viewFile workingDirectory} test namespace-28.2 {NamespaceImportCmd, no args and just "-force"} { namespace import -force } {} test namespace-28.3 {NamespaceImportCmd, arg is imported} { namespace eval test_ns_1 { namespace export cmd2 proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_2 { namespace import ::test_ns_1::* namespace forget ::test_ns_1::cmd1 } info commands test_ns_2::* } {::test_ns_2::cmd2} test namespace-29.1 {NamespaceInscopeCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace inscope} msg] $msg } {1 {wrong # args: should be "namespace inscope name arg ?arg...?"}} test namespace-29.2 {NamespaceInscopeCmd, bad args} { list [catch {namespace inscope ::} msg] $msg } {1 {wrong # args: should be "namespace inscope name arg ?arg...?"}} test namespace-29.3 {NamespaceInscopeCmd, specified ns must exist} -body { namespace inscope test_ns_1 {set v} } -returnCodes error -result {namespace "test_ns_1" not found in "::"} test namespace-29.4 {NamespaceInscopeCmd, simple case} { namespace eval test_ns_1 { variable v 747 proc cmd {args} { variable v return "[namespace current]::cmd: v=$v, args=$args" } } namespace inscope test_ns_1 cmd } {::test_ns_1::cmd: v=747, args=} test namespace-29.5 {NamespaceInscopeCmd, has lappend semantics} { list [namespace inscope test_ns_1 cmd x y z] \ [namespace eval test_ns_1 [concat cmd [list x y z]]] } {{::test_ns_1::cmd: v=747, args=x y z} {::test_ns_1::cmd: v=747, args=x y z}} test namespace-29.6 {NamespaceInscopeCmd, 1400572} { namespace inscope test_ns_1 {info level 0} } {namespace inscope test_ns_1 {info level 0}} test namespace-30.1 {NamespaceOriginCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace origin} msg] $msg } {1 {wrong # args: should be "namespace origin name"}} test namespace-30.2 {NamespaceOriginCmd, bad args} { list [catch {namespace origin x y} msg] $msg } {1 {wrong # args: should be "namespace origin name"}} test namespace-30.3 {NamespaceOriginCmd, command not found} { list [catch {namespace origin fred} msg] $msg } {1 {invalid command name "fred"}} test namespace-30.4 {NamespaceOriginCmd, command isn't imported} { namespace origin set } {::set} test namespace-30.5 {NamespaceOriginCmd, imported command} { namespace eval test_ns_1 { namespace export cmd* proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_2 { namespace export * namespace import ::test_ns_1::* proc p {} {} } namespace eval test_ns_3 { namespace import ::test_ns_2::* list [namespace origin foreach] \ [namespace origin p] \ [namespace origin cmd1] \ [namespace origin ::test_ns_2::cmd2] } } {::foreach ::test_ns_2::p ::test_ns_1::cmd1 ::test_ns_1::cmd2} test namespace-31.1 {NamespaceParentCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace parent a b} msg] $msg } {1 {wrong # args: should be "namespace parent ?name?"}} test namespace-31.2 {NamespaceParentCmd, no args} { namespace parent } {} test namespace-31.3 {NamespaceParentCmd, namespace specified} { namespace eval test_ns_1 { namespace eval test_ns_2 { namespace eval test_ns_3 {} } } list [namespace parent ::] \ [namespace parent test_ns_1::test_ns_2] \ [namespace eval test_ns_1::test_ns_2::test_ns_3 {namespace parent ::test_ns_1::test_ns_2}] } {{} ::test_ns_1 ::test_ns_1} test namespace-31.4 {NamespaceParentCmd, bad namespace specified} -body { namespace parent test_ns_1::test_ns_foo } -returnCodes error -result {namespace "test_ns_1::test_ns_foo" not found in "::"} test namespace-32.1 {NamespaceQualifiersCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace qualifiers} msg] $msg } {1 {wrong # args: should be "namespace qualifiers string"}} test namespace-32.2 {NamespaceQualifiersCmd, bad args} { list [catch {namespace qualifiers x y} msg] $msg } {1 {wrong # args: should be "namespace qualifiers string"}} test namespace-32.3 {NamespaceQualifiersCmd, simple name} { namespace qualifiers foo } {} test namespace-32.4 {NamespaceQualifiersCmd, leading ::} { namespace qualifiers ::x::y::z } {::x::y} test namespace-32.5 {NamespaceQualifiersCmd, no leading ::} { namespace qualifiers a::b } {a} test namespace-32.6 {NamespaceQualifiersCmd, :: argument} { namespace qualifiers :: } {} test namespace-32.7 {NamespaceQualifiersCmd, odd number of :s} { namespace qualifiers ::::: } {} test namespace-32.8 {NamespaceQualifiersCmd, odd number of :s} { namespace qualifiers foo::: } {foo} test namespace-33.1 {NamespaceTailCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace tail} msg] $msg } {1 {wrong # args: should be "namespace tail string"}} test namespace-33.2 {NamespaceTailCmd, bad args} { list [catch {namespace tail x y} msg] $msg } {1 {wrong # args: should be "namespace tail string"}} test namespace-33.3 {NamespaceTailCmd, simple name} { namespace tail foo } {foo} test namespace-33.4 {NamespaceTailCmd, leading ::} { namespace tail ::x::y::z } {z} test namespace-33.5 {NamespaceTailCmd, no leading ::} { namespace tail a::b } {b} test namespace-33.6 {NamespaceTailCmd, :: argument} { namespace tail :: } {} test namespace-33.7 {NamespaceTailCmd, odd number of :s} { namespace tail ::::: } {} test namespace-33.8 {NamespaceTailCmd, odd number of :s} { namespace tail foo::: } {} test namespace-34.1 {NamespaceWhichCmd, bad args} { catch {namespace delete {*}[namespace children :: test_ns_*]} list [catch {namespace which} msg] $msg } {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}} test namespace-34.2 {NamespaceWhichCmd, bad args} { list [catch {namespace which -fred x} msg] $msg } {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}} test namespace-34.3 {NamespaceWhichCmd, single arg is always command name} { namespace which -command } {} test namespace-34.4 {NamespaceWhichCmd, bad args} { list [catch {namespace which a b} msg] $msg } {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}} test namespace-34.5 {NamespaceWhichCmd, command lookup} { namespace eval test_ns_1 { namespace export cmd* variable v1 111 proc cmd1 {args} {return "cmd1: $args"} proc cmd2 {args} {return "cmd2: $args"} } namespace eval test_ns_2 { namespace export * namespace import ::test_ns_1::* variable v2 222 proc p {} {} } namespace eval test_ns_3 { namespace import ::test_ns_2::* variable v3 333 list [namespace which -command foreach] \ [namespace which -command p] \ [namespace which -command cmd1] \ [namespace which -command ::test_ns_2::cmd2] \ [catch {namespace which -command ::test_ns_2::noSuchCmd} msg] $msg } } {::foreach ::test_ns_3::p ::test_ns_3::cmd1 ::test_ns_2::cmd2 0 {}} test namespace-34.6 {NamespaceWhichCmd, -command is default} { namespace eval test_ns_3 { list [namespace which foreach] \ [namespace which p] \ [namespace which cmd1] \ [namespace which ::test_ns_2::cmd2] } } {::foreach ::test_ns_3::p ::test_ns_3::cmd1 ::test_ns_2::cmd2} test namespace-34.7 {NamespaceWhichCmd, variable lookup} { namespace eval test_ns_3 { list [namespace which -variable env] \ [namespace which -variable v3] \ [namespace which -variable ::test_ns_2::v2] \ [catch {namespace which -variable ::test_ns_2::noSuchVar} msg] $msg } } {::env ::test_ns_3::v3 ::test_ns_2::v2 0 {}} test namespace-35.1 {FreeNsNameInternalRep, resulting ref count > 0} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1 { proc p {} { namespace delete [namespace current] return [namespace current] } } test_ns_1::p } {::test_ns_1} test namespace-35.2 {FreeNsNameInternalRep, resulting ref count == 0} { namespace eval test_ns_1 { proc q {} { return [namespace current] } } list [test_ns_1::q] \ [namespace delete test_ns_1] \ [catch {test_ns_1::q} msg] $msg } {::test_ns_1 {} 1 {invalid command name "test_ns_1::q"}} catch {unset x} catch {unset y} test namespace-36.1 {DupNsNameInternalRep} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1 {} set x "::test_ns_1" list [namespace parent $x] [set y $x] [namespace parent $y] } {:: ::test_ns_1 ::} catch {unset x} catch {unset y} test namespace-37.1 {SetNsNameFromAny, ns name found} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval test_ns_1::test_ns_2 {} namespace eval test_ns_1 { namespace children ::test_ns_1 } } {::test_ns_1::test_ns_2} test namespace-37.2 {SetNsNameFromAny, ns name not found} -body { namespace eval test_ns_1 { namespace children ::test_ns_1::test_ns_foo } } -returnCodes error -result {namespace "::test_ns_1::test_ns_foo" not found} test namespace-38.1 {UpdateStringOfNsName} { catch {namespace delete {*}[namespace children :: test_ns_*]} ;# Tcl_NamespaceObjCmd calls UpdateStringOfNsName to get subcmd name list [namespace eval {} {namespace current}] \ [namespace eval {} {namespace current}] } {:: ::} test namespace-39.1 {NamespaceExistsCmd} { catch {namespace delete {*}[namespace children :: test_ns_*]} namespace eval ::test_ns_z::test_me { variable foo } list [namespace exists ::] \ [namespace exists ::bogus_namespace] \ [namespace exists ::test_ns_z] \ [namespace exists test_ns_z] \ [namespace exists ::test_ns_z::foo] \ [namespace exists ::test_ns_z::test_me] \ [namespace eval ::test_ns_z { namespace exists ::test_me }] \ [namespace eval ::test_ns_z { namespace exists test_me }] \ [namespace exists :::::test_ns_z] } {1 0 1 1 0 1 0 1 1} test namespace-39.2 {NamespaceExistsCmd error} { list [catch {namespace exists} msg] $msg } {1 {wrong # args: should be "namespace exists name"}} test namespace-39.3 {NamespaceExistsCmd error} { list [catch {namespace exists a b} msg] $msg } {1 {wrong # args: should be "namespace exists name"}} test namespace-40.1 {Ignoring namespace proc "unknown"} { rename unknown _unknown proc unknown args {return global} namespace eval ns {proc unknown args {return local}} set l [list [namespace eval ns aaa bbb] [namespace eval ns aaa]] rename unknown {} rename _unknown unknown namespace delete ns set l } {global global} test namespace-41.1 {Shadowing byte-compiled commands, Bug: 231259} { set res {} namespace eval ns { set res {} proc test {} { set ::g 0 } lappend ::res [test] proc set {a b} { ::set a [incr b] } lappend ::res [test] } namespace delete ns set res } {0 1} test namespace-41.2 {Shadowing byte-compiled commands, Bug: 231259} { set res {} namespace eval ns {} proc ns::a {i} { variable b proc set args {return "New proc is called"} return [set b $i] } ns::a 1 set res [ns::a 2] namespace delete ns set res } {New proc is called} test namespace-41.3 {Shadowing byte-compiled commands, Bugs: 231259, 729692} { set res {} namespace eval ns { variable b 0 } proc ns::a {i} { variable b proc set args {return "New proc is called"} return [set b $i] } set res [list [ns::a 1] $ns::b] namespace delete ns set res } {{New proc is called} 0} # Ensembles (TIP#112) test namespace-42.1 {ensembles: basic} { namespace eval ns { namespace export x proc x {} {format 1} namespace ensemble create } list [info command ns] [ns x] [namespace delete ns] [info command ns] } {ns 1 {} {}} test namespace-42.2 {ensembles: basic} { namespace eval ns { namespace export x proc x {} {format 1} namespace ensemble create } rename ns foo list [info command foo] [foo x] [namespace delete ns] [info command foo] } {foo 1 {} {}} test namespace-42.3 {ensembles: basic} { namespace eval ns { namespace export x* proc x1 {} {format 1} proc x2 {} {format 2} namespace ensemble create } set result [list [ns x1] [ns x2]] lappend result [catch {ns x} msg] $msg rename ns {} lappend result [info command ns::x1] namespace delete ns lappend result [info command ns::x1] } {1 2 1 {unknown or ambiguous subcommand "x": must be x1, or x2} ::ns::x1 {}} test namespace-42.4 {ensembles: basic} { namespace eval ns { namespace export y* proc x1 {} {format 1} proc x2 {} {format 2} namespace ensemble create } set result [list [catch {ns x} msg] $msg] namespace delete ns set result } {1 {unknown subcommand "x": namespace ::ns does not export any commands}} test namespace-42.5 {ensembles: basic} { namespace eval ns { namespace export x* proc x1 {} {format 1} proc x2 {} {format 2} proc x3 {} {format 3} namespace ensemble create } set result [list [catch {ns x} msg] $msg] namespace delete ns set result } {1 {unknown or ambiguous subcommand "x": must be x1, x2, or x3}} test namespace-42.6 {ensembles: nested} { namespace eval ns { namespace export x* namespace eval x0 { proc z {} {format 0} namespace export z namespace ensemble create } proc x1 {} {format 1} proc x2 {} {format 2} proc x3 {} {format 3} namespace ensemble create } set result [list [ns x0 z] [ns x1] [ns x2] [ns x3]] namespace delete ns set result } {0 1 2 3} test namespace-42.7 {ensembles: nested} { namespace eval ns { namespace export x* namespace eval x0 { proc z {} {list [info level] [info level 1]} namespace export z namespace ensemble create } proc x1 {} {format 1} proc x2 {} {format 2} proc x3 {} {format 3} namespace ensemble create } set result [list [ns x0 z] [ns x1] [ns x2] [ns x3]] namespace delete ns set result } {{1 ::ns::x0::z} 1 2 3} test namespace-42.8 {ensembles: [Bug 1670091]} -setup { proc demo args {} variable target [list [namespace which demo] x] proc trial args {variable target; string length $target} trace add execution demo enter [namespace code trial] namespace ensemble create -command foo -map [list bar $target] } -body { foo bar } -cleanup { unset target rename demo {} rename trial {} rename foo {} } -result {} test namespace-43.1 {ensembles: dict-driven} { namespace eval ns { namespace export x* proc x1 {} {format 1} proc x2 {} {format 2} namespace ensemble create -map {a x1 b x2} } set result [list [catch {ns c} msg] $msg [namespace ensemble exists ns]] rename ns {} lappend result [namespace ensemble exists ns] } {1 {unknown or ambiguous subcommand "c": must be a, or b} 1 0} test namespace-43.2 {ensembles: dict-driven} { namespace eval ns { namespace export x* proc x1 {args} {list 1 $args} proc x2 {args} {list 2 [llength $args]} namespace ensemble create -map { a ::ns::x1 b ::ns::x2 c {::ns::x1 .} d {::ns::x2 .} } } set result [list [ns a] [ns b] [ns c] [ns c foo] [ns d] [ns d foo]] namespace delete ns set result } {{1 {}} {2 0} {1 .} {1 {. foo}} {2 1} {2 2}} set SETUP { namespace eval ns { namespace export a b proc a args {format 1,[llength $args]} proc b args {format 2,[llength $args]} proc c args {format 3,[llength $args]} proc d args {format 4,[llength $args]} namespace ensemble create -subcommands {b c} } } test namespace-43.3 {ensembles: list-driven} -setup $SETUP -body { namespace delete ns } -result {} test namespace-43.4 {ensembles: list-driven} -setup $SETUP -body { ns a foo bar boo spong wibble } -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "a": must be b, or c} test namespace-43.5 {ensembles: list-driven} -setup $SETUP -body { ns b foo bar boo spong wibble } -cleanup {namespace delete ns} -result 2,5 test namespace-43.6 {ensembles: list-driven} -setup $SETUP -body { ns c foo bar boo spong wibble } -cleanup {namespace delete ns} -result 3,5 test namespace-43.7 {ensembles: list-driven} -setup $SETUP -body { ns d foo bar boo spong wibble } -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "d": must be b, or c} set SETUP { namespace eval ns { namespace export a b proc a args {format 1,[llength $args]} proc b args {format 2,[llength $args]} proc c args {format 3,[llength $args]} proc d args {format 4,[llength $args]} namespace ensemble create -subcommands {b c} -map {c ::ns::d} } } test namespace-43.8 {ensembles: list-and-map-driven} -setup $SETUP -body { namespace delete ns } -result {} test namespace-43.9 {ensembles: list-and-map-driven} -setup $SETUP -body { ns a foo bar boo spong wibble } -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "a": must be b, or c} test namespace-43.10 {ensembles: list-and-map-driven} -setup $SETUP -body { ns b foo bar boo spong wibble } -cleanup {namespace delete ns} -result 2,5 test namespace-43.11 {ensembles: list-and-map-driven} -setup $SETUP -body { ns c foo bar boo spong wibble } -cleanup {namespace delete ns} -result 4,5 test namespace-43.12 {ensembles: list-and-map-driven} -setup $SETUP -body { ns d foo bar boo spong wibble } -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "d": must be b, or c} set SETUP { namespace eval ns { namespace export * proc foo args {format bar} proc spong args {format wibble} namespace ensemble create -prefixes off } } test namespace-43.13 {ensembles: turn off prefixes} -setup $SETUP -body { namespace delete ns } -result {} test namespace-43.14 {ensembles: turn off prefixes} -setup $SETUP -body { ns fo } -cleanup {namespace delete ns} -returnCodes error -result {unknown subcommand "fo": must be foo, or spong} test namespace-43.15 {ensembles: turn off prefixes} -setup $SETUP -body { ns foo } -cleanup {namespace delete ns} -result bar test namespace-43.16 {ensembles: turn off prefixes} -setup $SETUP -body { ns s } -cleanup {namespace delete ns} -returnCodes error -result {unknown subcommand "s": must be foo, or spong} test namespace-43.17 {ensembles: turn off prefixes} -setup $SETUP -body { ns spong } -cleanup {namespace delete ns} -result wibble test namespace-44.1 {ensemble: errors} { list [catch {namespace ensemble} msg] $msg } {1 {wrong # args: should be "namespace ensemble subcommand ?arg ...?"}} test namespace-44.2 {ensemble: errors} { list [catch {namespace ensemble ?} msg] $msg } {1 {bad subcommand "?": must be configure, create, or exists}} test namespace-44.3 {ensemble: errors} { namespace eval ns { list [catch {namespace ensemble create -map x} msg] $msg } } {1 {missing value to go with key}} test namespace-44.4 {ensemble: errors} { namespace eval ns { list [catch {namespace ensemble create -map {x {}}} msg] $msg } } {1 {ensemble subcommand implementations must be non-empty lists}} test namespace-44.5 {ensemble: errors} -setup { namespace ensemble create -command foobar -subcommands {foobarcget foobarconfigure} } -body { foobar foobarcon } -cleanup { rename foobar {} } -returnCodes error -result {invalid command name "::foobarconfigure"} test namespace-45.1 {ensemble: introspection} { namespace eval ns { namespace export x proc x {} {} namespace ensemble create set ::result [namespace ensemble configure ::ns] } namespace delete ns set result } {-map {} -namespace ::ns -prefixes 1 -subcommands {} -unknown {}} test namespace-45.2 {ensemble: introspection} { namespace eval ns { namespace export x proc x {} {} namespace ensemble create -map {A x} set ::result [namespace ensemble configure ::ns -map] } namespace delete ns set result } {A ::ns::x} test namespace-46.1 {ensemble: modification} { namespace eval ns { namespace export x proc x {} {format 123} # Ensemble maps A->x namespace ensemble create -command ns -map {A ::ns::x} set ::result [list [namespace ensemble configure ns -map] [ns A]] # Ensemble maps B->x namespace ensemble configure ns -map {B ::ns::x} lappend ::result [namespace ensemble configure ns -map] [ns B] # Ensemble maps x->x namespace ensemble configure ns -map {} lappend ::result [namespace ensemble configure ns -map] [ns x] } namespace delete ns set result } {{A ::ns::x} 123 {B ::ns::x} 123 {} 123} test namespace-46.2 {ensemble: ensembles really use current export list} { namespace eval ns { namespace export x1 proc x1 {} {format 1} proc x2 {} {format 1} namespace ensemble create } catch {ns ?} msg; set result [list $msg] namespace eval ns {namespace export x*} catch {ns ?} msg; lappend result $msg rename ns::x1 {} catch {ns ?} msg; lappend result $msg namespace delete ns set result } {{unknown or ambiguous subcommand "?": must be x1} {unknown or ambiguous subcommand "?": must be x1, or x2} {unknown or ambiguous subcommand "?": must be x2}} test namespace-46.3 {ensemble: implementation errors} { namespace eval ns { variable count 0 namespace ensemble create -map { a {::lappend ::result} b {::incr ::ns::count} } } set result {} lappend result [catch { ns } msg] $msg ns a [ns b 10] catch {rename p {}} rename ns p p a [p b 3000] lappend result $ns::count namespace delete ns lappend result [info command p] } {1 {wrong # args: should be "ns subcommand ?argument ...?"} 10 3010 3010 {}} test namespace-46.4 {ensemble: implementation errors} { namespace eval ns { namespace ensemble create } set result [info command ns] lappend result [catch {ns ?} msg] $msg namespace delete ns set result } {ns 1 {unknown subcommand "?": namespace ::ns does not export any commands}} test namespace-46.5 {ensemble: implementation errors} { namespace eval ns { namespace ensemble create -map {makeError ::error} } list [catch {ns makeError "an error happened"} msg] $msg $::errorInfo [namespace delete ns] } {1 {an error happened} {an error happened while executing "ns makeError "an error happened""} {}} test namespace-46.6 {ensemble: implementation renames/deletes itself} { namespace eval ns { namespace ensemble create -map {to ::rename} } ns to ns foo foo to foo bar bar to bar spong spong to spong {} namespace delete ns } {} test namespace-46.7 {ensemble: implementation deletes its namespace} { namespace eval ns { namespace ensemble create -map {kill {::namespace delete}} } ns kill ns } {} test namespace-46.8 {ensemble: implementation deletes its namespace} { namespace eval ns { namespace export * proc foo {} { variable x 1 bar # Tricky; what is the correct return value anyway? info exist x } proc bar {} { namespace delete [namespace current] } namespace ensemble create } list [ns foo] [info exist ns::x] } {1 0} test namespace-46.9 {ensemble: configuring really configures things} { namespace eval ns { namespace ensemble create -map {a a} -prefixes 0 } set result [list [catch {ns x} msg] $msg] namespace ensemble configure ns -map {b b} lappend result [catch {ns x} msg] $msg namespace delete ns set result } {1 {unknown subcommand "x": must be a} 1 {unknown subcommand "x": must be b}} test namespace-47.1 {ensemble: unknown handler} { set log {} namespace eval ns { namespace export {[a-z]*} proc Magic {ensemble subcmd args} { global log if {[string match {[a-z]*} $subcmd]} { lappend log "making $subcmd" proc $subcmd args { global log lappend log "running [info level 0]" llength $args } } else { lappend log "unknown $subcmd - args = $args" return -code error \ "unknown or protected subcommand \"$subcmd\"" } } namespace ensemble create -unknown ::ns::Magic } set result {} lappend result [catch {ns a b c} msg] $msg lappend result [catch {ns a b c} msg] $msg lappend result [catch {ns b c d} msg] $msg lappend result [catch {ns c d e} msg] $msg lappend result [catch {ns Magic foo bar spong wibble} msg] $msg list $result [lsort [info commands ::ns::*]] $log [namespace delete ns] } {{0 2 0 2 0 2 0 2 1 {unknown or protected subcommand "Magic"}} {::ns::Magic ::ns::a ::ns::b ::ns::c} {{making a} {running ::ns::a b c} {running ::ns::a b c} {making b} {running ::ns::b c d} {making c} {running ::ns::c d e} {unknown Magic - args = foo bar spong wibble}} {}} test namespace-47.2 {ensemble: unknown handler} { namespace eval ns { namespace export {[a-z]*} proc Magic {ensemble subcmd args} { error foobar } namespace ensemble create -unknown ::ns::Magic } list [catch {ns spong} msg] $msg $::errorInfo [namespace delete ns] } {1 foobar {foobar while executing "error foobar" (procedure "::ns::Magic" line 2) invoked from within "::ns::Magic ::ns spong" (ensemble unknown subcommand handler) invoked from within "ns spong"} {}} test namespace-47.3 {ensemble: unknown handler} { namespace eval ns { variable count 0 namespace export {[a-z]*} proc a {} {} proc c {} {} proc Magic {ensemble subcmd args} { variable count incr count proc b {} {} } namespace ensemble create -unknown ::ns::Magic } list [catch {ns spong} msg] $msg $ns::count [namespace delete ns] } {1 {unknown or ambiguous subcommand "spong": must be a, b, or c} 1 {}} test namespace-47.4 {ensemble: unknown handler} { namespace eval ns { namespace export {[a-z]*} proc Magic {ensemble subcmd args} { return -code break } namespace ensemble create -unknown ::ns::Magic } list [catch {ns spong} msg] $msg $::errorInfo [namespace delete ns] } {1 {unknown subcommand handler returned bad code: break} {unknown subcommand handler returned bad code: break result of ensemble unknown subcommand handler: ::ns::Magic ::ns spong invoked from within "ns spong"} {}} test namespace-47.5 {ensemble: unknown handler} { namespace ensemble create -command foo -unknown bar proc bar {args} { global result target lappend result "LOG $args" return $target } set result {} set target {} lappend result [catch {foo bar} msg] $msg set target {lappend result boo hoo} lappend result [catch {foo bar} msg] $msg [namespace ensemble config foo] rename foo {} set result } {{LOG ::foo bar} 1 {unknown subcommand "bar": namespace :: does not export any commands} {LOG ::foo bar} boo hoo 0 {{LOG ::foo bar} 1 {unknown subcommand "bar": namespace :: does not export any commands} {LOG ::foo bar} boo hoo} {-map {} -namespace :: -prefixes 1 -subcommands {} -unknown bar}} test namespace-47.6 {ensemble: unknown handler} { namespace ensemble create -command foo -unknown bar proc bar {args} { return "\{" } set result [list [catch {foo bar} msg] $msg $::errorInfo] rename foo {} set result } {1 {unmatched open brace in list} {unmatched open brace in list while parsing result of ensemble unknown subcommand handler invoked from within "foo bar"}} test namespace-47.7 {ensemble: unknown handler, commands with spaces} { namespace ensemble create -command foo -unknown bar proc bar {args} { list ::set ::x [join $args |] } set result [foo {one two three}] rename foo {} set result } {::foo|one two three} test namespace-47.8 {ensemble: unknown handler, commands with spaces} { namespace ensemble create -command foo -unknown {bar boo} proc bar {args} { list ::set ::x [join $args |] } set result [foo {one two three}] rename foo {} set result } {boo|::foo|one two three} test namespace-48.1 {ensembles and namespace import: unknown handler} { namespace eval foo { namespace export bar namespace ensemble create -command bar -unknown ::foo::u -subcomm x proc u {ens args} { global result lappend result $ens $args namespace ensemble config $ens -subcommand {x y} } proc u2 {ens args} { global result lappend result $ens $args namespace ensemble config ::bar -subcommand {x y z} } proc x args { global result lappend result XXX $args } proc y args { global result lappend result YYY $args } proc z args { global result lappend result ZZZ $args } } namespace import -force foo::bar set result [list [namespace ensemble config bar]] bar x 123 bar y 456 namespace ensemble config bar -unknown ::foo::u2 bar z 789 namespace delete foo set result } {{-map {} -namespace ::foo -prefixes 1 -subcommands x -unknown ::foo::u} XXX 123 ::foo::bar {y 456} YYY 456 ::foo::bar {z 789} ZZZ 789} test namespace-48.2 {ensembles and namespace import: exists} { namespace eval foo { namespace ensemble create -command ::foo::bar namespace export bar } set result [namespace ensemble exist foo::bar] lappend result [namespace ensemble exist bar] namespace import foo::bar lappend result [namespace ensemble exist bar] rename foo::bar foo::bar2 lappend result [namespace ensemble exist bar] \ [namespace ensemble exist spong] rename bar spong lappend result [namespace ensemble exist bar] \ [namespace ensemble exist spong] rename foo::bar2 {} lappend result [namespace ensemble exist spong] namespace delete foo set result } {1 0 1 1 0 0 1 0} test namespace-48.3 {ensembles and namespace import: config} { catch {rename spong {}} namespace eval foo { namespace ensemble create -command ::foo::bar namespace export bar boo proc boo {} {} } namespace import foo::bar foo::boo set result [namespace ensemble config bar -namespace] lappend result [catch {namespace ensemble config boo} msg] $msg lappend result [catch {namespace ensemble config spong} msg] $msg namespace delete foo set result } {::foo 1 {"boo" is not an ensemble command} 1 {unknown command "spong"}} test namespace-49.1 {ensemble subcommand caching} -body { namespace ens cre -command a -map {b {lappend result 1}} namespace ens cre -command c -map {b {lappend result 2}} proc x {} {a b; c b; a b; c b} x } -result {1 2 1 2} -cleanup { rename a {} rename c {} rename x {} } test namespace-49.2 {strange delete crash} -body { namespace eval foo {namespace ensemble create -command ::bar} trace add command ::bar delete DeleteTrace proc DeleteTrace {old new op} { trace remove command ::bar delete DeleteTrace rename $old "" # This next line caused a bus error in [Bug 1220058] namespace delete foo } rename ::bar "" } -result "" -cleanup { rename DeleteTrace "" } test namespace-50.1 {ensembles affect proc arguments error messages} -body { namespace ens cre -command a -map {b {bb foo}} proc bb {c d {e f} args} {list $c $args} a b } -returnCodes error -result "wrong # args: should be \"a b d ?e? ...\"" -cleanup { rename a {} rename bb {} } test namespace-50.2 {ensembles affect WrongNumArgs error messages} -body { namespace ens cre -command a -map {b {string is}} a b boolean } -returnCodes error -result "wrong # args: should be \"a b class ?-strict? ?-failindex var? str\"" -cleanup { rename a {} } test namespace-50.3 {chained ensembles affect error messages} -body { namespace ens cre -command a -map {b c} namespace ens cre -command c -map {d e} proc e f {} a b d } -returnCodes error -result "wrong # args: should be \"a b d f\"" -cleanup { rename a {} } test namespace-50.4 {chained ensembles affect error messages} -body { namespace ens cre -command a -map {b {c d}} namespace ens cre -command c -map {d {e f}} proc e f {} a b d } -returnCodes error -result "wrong # args: should be \"a b\"" -cleanup { rename a {} } test namespace-51.1 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace eval test_ns_2 { proc pathtestA {} { ::return [pathtestB],[pathtestC],[pathtestD],[namespace path] } proc pathtestC {} { ::return 2 } } proc pathtestB {} { return 1 } proc pathtestC {} { return 1 } namespace path ::test_ns_1 } proc ::pathtestB {} { return global } proc ::pathtestD {} { return global } test_ns_1::test_ns_2::pathtestA } -result "global,2,global," -cleanup { namespace delete ::test_ns_1 catch {rename ::pathtestB {}} catch {rename ::pathtestD {}} } test namespace-51.2 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace eval test_ns_2 { namespace path ::test_ns_1 proc pathtestA {} { ::return [pathtestB],[pathtestC],[pathtestD],[namespace path] } proc pathtestC {} { ::return 2 } } proc pathtestB {} { return 1 } proc pathtestC {} { return 1 } } proc ::pathtestB {} { return global } proc ::pathtestD {} { return global } ::test_ns_1::test_ns_2::pathtestA } -result "1,2,global,::test_ns_1" -cleanup { namespace delete ::test_ns_1 catch {rename ::pathtestB {}} catch {rename ::pathtestD {}} } test namespace-51.3 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace eval test_ns_2 { proc pathtestA {} { ::return [pathtestB],[pathtestC],[pathtestD],[namespace path] } proc pathtestC {} { ::return 2 } } proc pathtestB {} { return 1 } proc pathtestC {} { return 1 } } proc ::pathtestB {} { return global } proc ::pathtestD {} { return global } set result [::test_ns_1::test_ns_2::pathtestA] namespace eval ::test_ns_1::test_ns_2 { namespace path ::test_ns_1 } lappend result [::test_ns_1::test_ns_2::pathtestA] rename ::test_ns_1::pathtestB {} lappend result [::test_ns_1::test_ns_2::pathtestA] } -result "global,2,global, 1,2,global,::test_ns_1 global,2,global,::test_ns_1" -cleanup { namespace delete ::test_ns_1 catch {rename ::pathtestB {}} catch {rename ::pathtestD {}} } test namespace-51.4 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace eval test_ns_2 { proc pathtestA {} { ::return [pathtestB],[pathtestC],[pathtestD],[namespace path] } proc pathtestC {} { ::return 2 } } proc pathtestB {} { return 1 } proc pathtestC {} { return 1 } } proc ::pathtestB {} { return global } proc ::pathtestD {} { return global } set result [::test_ns_1::test_ns_2::pathtestA] namespace eval ::test_ns_1::test_ns_2 { namespace path ::test_ns_1 } lappend result [::test_ns_1::test_ns_2::pathtestA] namespace eval ::test_ns_1::test_ns_2 { namespace path {} } lappend result [::test_ns_1::test_ns_2::pathtestA] } -result "global,2,global, 1,2,global,::test_ns_1 global,2,global," -cleanup { namespace delete ::test_ns_1 catch {rename ::pathtestB {}} catch {rename ::pathtestD {}} } test namespace-51.5 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace eval test_ns_2 { proc pathtestA {} { ::return [pathtestB],[pathtestC],[pathtestD],[namespace path] } proc pathtestC {} { ::return 2 } namespace path ::test_ns_1 } proc pathtestB {} { return 1 } proc pathtestC {} { return 1 } proc pathtestD {} { return 1 } } proc ::pathtestB {} { return global } proc ::pathtestD {} { return global } set result [::test_ns_1::test_ns_2::pathtestA] namespace eval ::test_ns_1::test_ns_2 { namespace path {:: ::test_ns_1} } lappend result [::test_ns_1::test_ns_2::pathtestA] rename ::test_ns_1::test_ns_2::pathtestC {} lappend result [::test_ns_1::test_ns_2::pathtestA] } -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1}" -cleanup { namespace delete ::test_ns_1 catch {rename ::pathtestB {}} catch {rename ::pathtestD {}} } test namespace-51.6 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace eval test_ns_2 { proc pathtestA {} { ::return [pathtestB],[pathtestC],[pathtestD],[namespace path] } proc pathtestC {} { ::return 2 } namespace path ::test_ns_1 } proc pathtestB {} { return 1 } proc pathtestC {} { return 1 } proc pathtestD {} { return 1 } } proc ::pathtestB {} { return global } proc ::pathtestD {} { return global } set result [::test_ns_1::test_ns_2::pathtestA] namespace eval ::test_ns_1::test_ns_2 { namespace path {:: ::test_ns_1} } lappend result [::test_ns_1::test_ns_2::pathtestA] rename ::test_ns_1::test_ns_2::pathtestC {} lappend result [::test_ns_1::test_ns_2::pathtestA] proc ::pathtestC {} { return global } lappend result [::test_ns_1::test_ns_2::pathtestA] } -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1} {global,global,global,:: ::test_ns_1}" -cleanup { namespace delete ::test_ns_1 catch {rename ::pathtestB {}} catch {rename ::pathtestD {}} } test namespace-51.7 {name resolution path control} -body { namespace eval ::test_ns_1 { } namespace eval ::test_ns_2 { namespace path ::test_ns_1 proc getpath {} {namespace path} } list [::test_ns_2::getpath] [namespace delete ::test_ns_1] [::test_ns_2::getpath] } -result {::test_ns_1 {} {}} -cleanup { catch {namespace delete ::test_ns_1} namespace delete ::test_ns_2 } test namespace-51.8 {name resolution path control} -body { namespace eval ::test_ns_1 { } namespace eval ::test_ns_2 { } namespace eval ::test_ns_3 { } namespace eval ::test_ns_4 { namespace path {::test_ns_1 ::test_ns_2 ::test_ns_3} proc getpath {} {namespace path} } list [::test_ns_4::getpath] [namespace delete ::test_ns_2] [::test_ns_4::getpath] } -result {{::test_ns_1 ::test_ns_2 ::test_ns_3} {} {::test_ns_1 ::test_ns_3}} -cleanup { catch {namespace delete ::test_ns_1} catch {namespace delete ::test_ns_2} catch {namespace delete ::test_ns_3} catch {namespace delete ::test_ns_4} } test namespace-51.9 {name resolution path control} -body { namespace eval ::test_ns_1 { } namespace eval ::test_ns_2 { } namespace eval ::test_ns_3 { } namespace eval ::test_ns_4 { namespace path {::test_ns_1 ::test_ns_2 ::test_ns_3} proc getpath {} {namespace path} } list [::test_ns_4::getpath] [namespace delete ::test_ns_2] [namespace eval ::test_ns_2 {}] [::test_ns_4::getpath] } -result {{::test_ns_1 ::test_ns_2 ::test_ns_3} {} {} {::test_ns_1 ::test_ns_3}} -cleanup { catch {namespace delete ::test_ns_1} catch {namespace delete ::test_ns_2} catch {namespace delete ::test_ns_3} catch {namespace delete ::test_ns_4} } test namespace-51.10 {name resolution path control} -body { namespace eval ::test_ns_1 { namespace path does::not::exist } } -returnCodes error -result {namespace "does::not::exist" not found in "::test_ns_1"} -cleanup { catch {namespace delete ::test_ns_1} } test namespace-51.11 {name resolution path control} -body { namespace eval ::test_ns_1 { proc foo {} {return 1} } namespace eval ::test_ns_2 { proc foo {} {return 2} } namespace eval ::test_ns_3 { namespace path ::test_ns_1 } namespace eval ::test_ns_4 { namespace path {::test_ns_3 ::test_ns_2} foo } } -result 2 -cleanup { catch {namespace delete ::test_ns_1} catch {namespace delete ::test_ns_2} catch {namespace delete ::test_ns_3} catch {namespace delete ::test_ns_4} } test namespace-51.12 {name resolution path control} -body { namespace eval ::test_ns_1 { proc foo {} {return 1} } namespace eval ::test_ns_2 { proc foo {} {return 2} } namespace eval ::test_ns_3 { namespace path ::test_ns_1 } namespace eval ::test_ns_4 { namespace path {::test_ns_3 ::test_ns_2} list [foo] [namespace delete ::test_ns_3] [foo] } } -result {2 {} 2} -cleanup { catch {namespace delete ::test_ns_1} catch {namespace delete ::test_ns_2} catch {namespace delete ::test_ns_3} catch {namespace delete ::test_ns_4} } test namespace-51.13 {name resolution path control} -body { set ::result {} namespace eval ::test_ns_1 { proc foo {} {lappend ::result 1} } namespace eval ::test_ns_2 { proc foo {} {lappend ::result 2} trace add command foo delete {namespace eval ::test_ns_3 foo;#} } namespace eval ::test_ns_3 { proc foo {} { lappend ::result 3 namespace delete [namespace current] ::test_ns_4::bar } } namespace eval ::test_ns_4 { namespace path {::test_ns_2 ::test_ns_3 ::test_ns_1} proc bar {} { list [foo] [namespace delete ::test_ns_2] [foo] } bar } # Should the result be "2 {} {2 3 2 1}" instead? } -result {2 {} {2 3 1 1}} -cleanup { catch {namespace delete ::test_ns_1} catch {namespace delete ::test_ns_2} catch {namespace delete ::test_ns_3} catch {namespace delete ::test_ns_4} } test namespace-51.14 {name resolution path control} -body { foreach cmd [info commands foo*] { rename $cmd {} } proc foo0 {} {} namespace eval ::test_ns_1 { proc foo1 {} {} } namespace eval ::test_ns_2 { proc foo2 {} {} } namespace eval ::test_ns_3 { variable result {} lappend result [info commands foo*] namespace path {::test_ns_1 ::test_ns_2} lappend result [info commands foo*] proc foo2 {} {} lappend result [info commands foo*] rename foo2 {} lappend result [info commands foo*] namespace delete ::test_ns_1 lappend result [info commands foo*] } } -result {foo0 {foo1 foo2 foo0} {foo2 foo1 foo0} {foo1 foo2 foo0} {foo2 foo0}} -cleanup { catch {namespace delete ::test_ns_1} catch {namespace delete ::test_ns_2} catch {namespace delete ::test_ns_3} } test namespace-51.15 {namespace resolution path control} -body { namespace eval ::test_ns_2 { proc foo {} {return 2} } namespace eval ::test_ns_1 { namespace eval test_ns_2 { proc foo {} {return 1_2} } namespace eval test_ns_3 { namespace path ::test_ns_1 test_ns_2::foo } } } -result 1_2 -cleanup { namespace delete ::test_ns_1 namespace delete ::test_ns_2 } test namespace-51.16 {Bug 1566526} { interp create slave slave eval namespace eval demo namespace path :: interp delete slave } {} # TIP 181 - namespace unknown tests test namespace-52.1 {unknown: default handler ::unknown} { set result [list [namespace eval foobar { namespace unknown }]] lappend result [namespace eval :: { namespace unknown }] namespace delete foobar set result } {{} ::unknown} test namespace-52.2 {unknown: default resolution global} { proc ::foo {} { return "GLOBAL" } namespace eval ::bar { proc foo {} { return "NAMESPACE" } } namespace eval ::bar::jim { proc test {} { foo } } set result [::bar::jim::test] namespace delete ::bar rename ::foo {} set result } {GLOBAL} test namespace-52.3 {unknown: default resolution local} { proc ::foo {} { return "GLOBAL" } namespace eval ::bar { proc foo {} { return "NAMESPACE" } proc test {} { foo } } set result [::bar::test] namespace delete ::bar rename ::foo {} set result } {NAMESPACE} test namespace-52.4 {unknown: set handler} { namespace eval foo { namespace unknown [list dispatch] proc dispatch {args} { return $args } proc test {} { UnknownCmd a b c } } set result [foo::test] namespace delete foo set result } {UnknownCmd a b c} test namespace-52.5 {unknown: search path before unknown is unaltered} { proc ::test2 {args} { return "TEST2: $args" } namespace eval foo { namespace unknown [list dispatch] proc dispatch {args} { return "UNKNOWN: $args" } proc test1 {args} { return "TEST1: $args" } proc test {} { set result [list [test1 a b c]] lappend result [test2 a b c] lappend result [test3 a b c] return $result } } set result [foo::test] namespace delete foo rename ::test2 {} set result } {{TEST1: a b c} {TEST2: a b c} {UNKNOWN: test3 a b c}} test namespace-52.6 {unknown: deleting handler restores default} { rename ::unknown ::_unknown_orig proc ::unknown {args} { return "DEFAULT: $args" } namespace eval foo { namespace unknown dummy namespace unknown {} } set result [namespace eval foo { dummy a b c }] rename ::unknown {} rename ::_unknown_orig ::unknown namespace delete foo set result } {DEFAULT: dummy a b c} test namespace-52.7 {unknown: setting global unknown handler} { proc ::myunknown {args} { return "MYUNKNOWN: $args" } namespace eval :: { namespace unknown ::myunknown } set result [namespace eval foo { dummy a b c }] namespace eval :: { namespace unknown {} } rename ::myunknown {} namespace delete foo set result } {MYUNKNOWN: dummy a b c} test namespace-52.8 {unknown: destroying and redefining global namespace} { set i [interp create] $i hide proc $i hide namespace $i hide return $i invokehidden namespace delete :: $i expose return $i invokehidden proc unknown args { return "FINE" } $i eval { foo bar bob } } {FINE} test namespace-52.9 {unknown: refcounting} -setup { proc this args { unset args ;# stop sharing set copy [namespace unknown] string length $copy ;# shimmer away list rep info level 0 } set handler [namespace unknown] namespace unknown {this is a test} catch {rename noSuchCommand {}} } -body { noSuchCommand } -cleanup { namespace unknown $handler rename this {} } -result {this is a test noSuchCommand} testConstraint testevalobjv [llength [info commands testevalobjv]] test namespace-52.10 {unknown: with TCL_EVAL_GLOBAL} -constraints { testevalobjv } -setup { rename ::unknown unknown.save proc ::unknown args { set caller [uplevel 1 {namespace current}] namespace eval $caller { variable foo return $foo } } catch {rename ::noSuchCommand {}} } -body { namespace eval :: { variable foo SUCCESS } namespace eval test_ns_1 { variable foo FAIL testevalobjv 1 noSuchCommand } } -cleanup { unset -nocomplain ::foo namespace delete test_ns_1 rename ::unknown {} rename unknown.save ::unknown } -result SUCCESS test namespace-52.11 {unknown: with TCL_EVAL_INVOKE} -setup { set handler [namespace eval :: {namespace unknown}] namespace eval :: {namespace unknown unknown} rename ::unknown unknown.save namespace eval :: { proc unknown args { return SUCCESS } } catch {rename ::noSuchCommand {}} set ::slave [interp create] } -body { $::slave alias bar noSuchCommand namespace eval test_ns_1 { namespace unknown unknown proc unknown args { return FAIL } $::slave eval bar } } -cleanup { interp delete $::slave unset ::slave namespace delete test_ns_1 rename ::unknown {} rename unknown.save ::unknown namespace eval :: [list namespace unknown $handler] } -result SUCCESS # cleanup catch {rename cmd1 {}} catch {unset l} catch {unset msg} catch {unset trigger} namespace delete {*}[namespace children :: test_ns_*] ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: