sl@0: # This file contains tests for the tclBasic.c source file. Tests appear in sl@0: # the same order as the C code that they test. The set of tests is sl@0: # currently incomplete since it currently includes only new tests for sl@0: # code changed for the addition of Tcl namespaces. Other variable- sl@0: # related tests appear in several other test files including sl@0: # assocd.test, cmdInfo.test, eval.test, expr.test, interp.test, sl@0: # and trace.test. sl@0: # sl@0: # Sourcing this file into Tcl runs the tests and generates output for sl@0: # errors. No output means no errors were found. sl@0: # sl@0: # Copyright (c) 1997 Sun Microsystems, Inc. sl@0: # Copyright (c) 1998-1999 by Scriptics Corporation. sl@0: # sl@0: # See the file "license.terms" for information on usage and redistribution sl@0: # of this file, and for a DISCLAIMER OF ALL WARRANTIES. sl@0: # sl@0: # RCS: @(#) $Id: basic.test,v 1.25.2.7 2005/03/18 16:33:43 dgp Exp $ sl@0: # sl@0: sl@0: package require tcltest 2 sl@0: namespace import -force ::tcltest::* sl@0: sl@0: testConstraint testcmdtoken [llength [info commands testcmdtoken]] sl@0: testConstraint testcmdtrace [llength [info commands testcmdtrace]] sl@0: testConstraint testcreatecommand [llength [info commands testcreatecommand]] sl@0: testConstraint testevalex [llength [info commands testevalex]] sl@0: testConstraint exec [llength [info commands exec]] sl@0: sl@0: # This variable needs to be changed when the major or minor version number for sl@0: # Tcl changes. sl@0: set tclvers 8.4 sl@0: sl@0: catch {namespace delete test_ns_basic} sl@0: catch {interp delete test_interp} sl@0: catch {rename p ""} sl@0: catch {rename q ""} sl@0: catch {rename cmd ""} sl@0: catch {unset x} sl@0: sl@0: test basic-1.1 {Tcl_CreateInterp, creates interp's global namespace} { sl@0: catch {interp delete test_interp} sl@0: interp create test_interp sl@0: interp eval test_interp { sl@0: namespace eval test_ns_basic { sl@0: proc p {} { sl@0: return [namespace current] sl@0: } sl@0: } sl@0: } sl@0: list [interp eval test_interp {test_ns_basic::p}] \ sl@0: [interp delete test_interp] sl@0: } {::test_ns_basic {}} sl@0: sl@0: test basic-2.1 {TclHideUnsafeCommands} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-3.1 {Tcl_CallWhenDeleted: see dcall.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-4.1 {Tcl_DontCallWhenDeleted: see dcall.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-5.1 {Tcl_SetAssocData: see assoc.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-6.1 {Tcl_DeleteAssocData: see assoc.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-7.1 {Tcl_GetAssocData: see assoc.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-8.1 {Tcl_InterpDeleted} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-9.1 {Tcl_DeleteInterp: see interp.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-10.1 {DeleteInterpProc, destroys interp's global namespace} { sl@0: catch {interp delete test_interp} sl@0: interp create test_interp sl@0: interp eval test_interp { sl@0: namespace eval test_ns_basic { sl@0: namespace export p sl@0: proc p {} { sl@0: return [namespace current] sl@0: } sl@0: } sl@0: namespace eval test_ns_2 { sl@0: namespace import ::test_ns_basic::p sl@0: variable v 27 sl@0: proc q {} { sl@0: variable v sl@0: return "[p] $v" sl@0: } sl@0: } sl@0: } sl@0: list [interp eval test_interp {test_ns_2::q}] \ sl@0: [interp eval test_interp {namespace delete ::}] \ sl@0: [catch {interp eval test_interp {set a 123}} msg] $msg \ sl@0: [interp delete test_interp] sl@0: } {{::test_ns_basic 27} {} 1 {invalid command name "set"} {}} sl@0: sl@0: test basic-11.1 {HiddenCmdsDeleteProc, invalidate cached refs to deleted hidden cmd} { sl@0: catch {interp delete test_interp} sl@0: interp create test_interp sl@0: interp eval test_interp { sl@0: proc p {} { sl@0: return 27 sl@0: } sl@0: } sl@0: interp alias {} localP test_interp p sl@0: list [interp eval test_interp {p}] \ sl@0: [localP] \ sl@0: [test_interp hide p] \ sl@0: [catch {localP} msg] $msg \ sl@0: [interp delete test_interp] \ sl@0: [catch {localP} msg] $msg sl@0: } {27 27 {} 1 {invalid command name "p"} {} 1 {invalid command name "localP"}} sl@0: sl@0: # NB: More tests about hide/expose are found in interp.test sl@0: sl@0: test basic-12.1 {Tcl_HideCommand, names of hidden cmds can't have namespace qualifiers} { sl@0: catch {interp delete test_interp} sl@0: interp create test_interp sl@0: interp eval test_interp { sl@0: namespace eval test_ns_basic { sl@0: proc p {} { sl@0: return [namespace current] sl@0: } sl@0: } sl@0: } sl@0: list [catch {test_interp hide test_ns_basic::p x} msg] $msg \ sl@0: [catch {test_interp hide x test_ns_basic::p} msg1] $msg1 \ sl@0: [interp delete test_interp] sl@0: } {1 {can only hide global namespace commands (use rename then hide)} 1 {cannot use namespace qualifiers in hidden command token (rename)} {}} sl@0: sl@0: test basic-12.2 {Tcl_HideCommand, a hidden cmd remembers its containing namespace} { sl@0: catch {namespace delete test_ns_basic} sl@0: catch {rename cmd ""} sl@0: proc cmd {} { ;# note that this is global sl@0: return [namespace current] sl@0: } sl@0: namespace eval test_ns_basic { sl@0: proc hideCmd {} { sl@0: interp hide {} cmd sl@0: } sl@0: proc exposeCmd {} { sl@0: interp expose {} cmd sl@0: } sl@0: proc callCmd {} { sl@0: cmd sl@0: } sl@0: } sl@0: list [test_ns_basic::callCmd] \ sl@0: [test_ns_basic::hideCmd] \ sl@0: [catch {cmd} msg] $msg \ sl@0: [test_ns_basic::exposeCmd] \ sl@0: [test_ns_basic::callCmd] \ sl@0: [namespace delete test_ns_basic] sl@0: } {:: {} 1 {invalid command name "cmd"} {} :: {}} sl@0: sl@0: test basic-13.1 {Tcl_ExposeCommand, a command stays in the global namespace and can not go to another namespace} { sl@0: catch {namespace delete test_ns_basic} sl@0: catch {rename cmd ""} sl@0: proc cmd {} { ;# note that this is global sl@0: return [namespace current] sl@0: } sl@0: namespace eval test_ns_basic { sl@0: proc hideCmd {} { sl@0: interp hide {} cmd sl@0: } sl@0: proc exposeCmdFailing {} { sl@0: interp expose {} cmd ::test_ns_basic::newCmd sl@0: } sl@0: proc exposeCmdWorkAround {} { sl@0: interp expose {} cmd; sl@0: rename cmd ::test_ns_basic::newCmd; sl@0: } sl@0: proc callCmd {} { sl@0: cmd sl@0: } sl@0: } sl@0: list [test_ns_basic::callCmd] \ sl@0: [test_ns_basic::hideCmd] \ sl@0: [catch {test_ns_basic::exposeCmdFailing} msg] $msg \ sl@0: [test_ns_basic::exposeCmdWorkAround] \ sl@0: [test_ns_basic::newCmd] \ sl@0: [namespace delete test_ns_basic] sl@0: } {:: {} 1 {can not expose to a namespace (use expose to toplevel, then rename)} {} ::test_ns_basic {}} sl@0: test basic-13.2 {Tcl_ExposeCommand, invalidate cached refs to cmd now being exposed} { sl@0: catch {rename p ""} sl@0: catch {rename cmd ""} sl@0: proc p {} { sl@0: cmd sl@0: } sl@0: proc cmd {} { sl@0: return 42 sl@0: } sl@0: list [p] \ sl@0: [interp hide {} cmd] \ sl@0: [proc cmd {} {return Hello}] \ sl@0: [cmd] \ sl@0: [rename cmd ""] \ sl@0: [interp expose {} cmd] \ sl@0: [p] sl@0: } {42 {} {} Hello {} {} 42} sl@0: sl@0: test basic-14.1 {Tcl_CreateCommand, new cmd goes into a namespace specified in its name, if any} {testcreatecommand} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: list [testcreatecommand create] \ sl@0: [test_ns_basic::createdcommand] \ sl@0: [testcreatecommand delete] sl@0: } {{} {CreatedCommandProc in ::test_ns_basic} {}} sl@0: test basic-14.2 {Tcl_CreateCommand, namespace code ignore single ":"s in middle or end of names} {testcreatecommand} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {rename value:at: ""} sl@0: list [testcreatecommand create2] \ sl@0: [value:at:] \ sl@0: [testcreatecommand delete2] sl@0: } {{} {CreatedCommandProc2 in ::} {}} sl@0: sl@0: test basic-15.1 {Tcl_CreateObjCommand, new cmd goes into a namespace specified in its name, if any} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: namespace eval test_ns_basic {} sl@0: proc test_ns_basic::cmd {} { ;# proc requires that ns already exist sl@0: return [namespace current] sl@0: } sl@0: list [test_ns_basic::cmd] \ sl@0: [namespace delete test_ns_basic] sl@0: } {::test_ns_basic {}} sl@0: sl@0: test basic-16.1 {TclInvokeStringCommand} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-17.1 {TclInvokeObjCommand} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-18.1 {TclRenameCommand, name of existing cmd can have namespace qualifiers} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {rename cmd ""} sl@0: namespace eval test_ns_basic { sl@0: proc p {} { sl@0: return "p in [namespace current]" sl@0: } sl@0: } sl@0: list [test_ns_basic::p] \ sl@0: [rename test_ns_basic::p test_ns_basic::q] \ sl@0: [test_ns_basic::q] sl@0: } {{p in ::test_ns_basic} {} {p in ::test_ns_basic}} sl@0: test basic-18.2 {TclRenameCommand, existing cmd must be found} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: list [catch {rename test_ns_basic::p test_ns_basic::q} msg] $msg sl@0: } {1 {can't rename "test_ns_basic::p": command doesn't exist}} sl@0: test basic-18.3 {TclRenameCommand, delete cmd if new name is empty} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: namespace eval test_ns_basic { sl@0: proc p {} { sl@0: return "p in [namespace current]" sl@0: } sl@0: } sl@0: list [info commands test_ns_basic::*] \ sl@0: [rename test_ns_basic::p ""] \ sl@0: [info commands test_ns_basic::*] sl@0: } {::test_ns_basic::p {} {}} sl@0: test basic-18.4 {TclRenameCommand, bad new name} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: namespace eval test_ns_basic { sl@0: proc p {} { sl@0: return "p in [namespace current]" sl@0: } sl@0: } sl@0: rename test_ns_basic::p :::george::martha sl@0: } {} sl@0: test basic-18.5 {TclRenameCommand, new name must not already exist} { sl@0: namespace eval test_ns_basic { sl@0: proc q {} { sl@0: return 42 sl@0: } sl@0: } sl@0: list [catch {rename test_ns_basic::q :::george::martha} msg] $msg sl@0: } {1 {can't rename to ":::george::martha": command already exists}} sl@0: test basic-18.6 {TclRenameCommand, check for command shadowing by newly renamed cmd} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {rename p ""} sl@0: catch {rename q ""} sl@0: proc p {} { sl@0: return "p in [namespace current]" sl@0: } sl@0: proc q {} { sl@0: return "q in [namespace current]" sl@0: } sl@0: namespace eval test_ns_basic { sl@0: proc callP {} { sl@0: p sl@0: } sl@0: } sl@0: list [test_ns_basic::callP] \ sl@0: [rename q test_ns_basic::p] \ sl@0: [test_ns_basic::callP] sl@0: } {{p in ::} {} {q in ::test_ns_basic}} sl@0: sl@0: test basic-19.1 {Tcl_SetCommandInfo} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-20.1 {Tcl_GetCommandInfo, names for commands created inside namespaces} {testcmdtoken} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {rename p ""} sl@0: catch {rename q ""} sl@0: catch {unset x} sl@0: set x [namespace eval test_ns_basic::test_ns_basic2 { sl@0: # the following creates a cmd in the global namespace sl@0: testcmdtoken create p sl@0: }] sl@0: list [testcmdtoken name $x] \ sl@0: [rename ::p q] \ sl@0: [testcmdtoken name $x] sl@0: } {{p ::p} {} {q ::q}} sl@0: test basic-20.2 {Tcl_GetCommandInfo, names for commands created outside namespaces} {testcmdtoken} { sl@0: catch {rename q ""} sl@0: set x [testcmdtoken create test_ns_basic::test_ns_basic2::p] sl@0: list [testcmdtoken name $x] \ sl@0: [rename test_ns_basic::test_ns_basic2::p q] \ sl@0: [testcmdtoken name $x] sl@0: } {{p ::test_ns_basic::test_ns_basic2::p} {} {q ::q}} sl@0: sl@0: test basic-21.1 {Tcl_GetCommandName} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-22.1 {Tcl_GetCommandFullName} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: namespace eval test_ns_basic1 { sl@0: namespace export cmd* sl@0: proc cmd1 {} {} sl@0: proc cmd2 {} {} sl@0: } sl@0: namespace eval test_ns_basic2 { sl@0: namespace export * sl@0: namespace import ::test_ns_basic1::* sl@0: proc p {} {} sl@0: } sl@0: namespace eval test_ns_basic3 { sl@0: namespace import ::test_ns_basic2::* sl@0: proc q {} {} sl@0: list [namespace which -command foreach] \ sl@0: [namespace which -command q] \ sl@0: [namespace which -command p] \ sl@0: [namespace which -command cmd1] \ sl@0: [namespace which -command ::test_ns_basic2::cmd2] sl@0: } sl@0: } {::foreach ::test_ns_basic3::q ::test_ns_basic3::p ::test_ns_basic3::cmd1 ::test_ns_basic2::cmd2} sl@0: sl@0: test basic-23.1 {Tcl_DeleteCommand} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-24.1 {Tcl_DeleteCommandFromToken, invalidate all compiled code if cmd has compile proc} { sl@0: catch {interp delete test_interp} sl@0: catch {unset x} sl@0: interp create test_interp sl@0: interp eval test_interp { sl@0: proc useSet {} { sl@0: return [set a 123] sl@0: } sl@0: } sl@0: set x [interp eval test_interp {useSet}] sl@0: interp eval test_interp { sl@0: rename set "" sl@0: proc set {args} { sl@0: return "set called with $args" sl@0: } sl@0: } sl@0: list $x \ sl@0: [interp eval test_interp {useSet}] \ sl@0: [interp delete test_interp] sl@0: } {123 {set called with a 123} {}} sl@0: test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command epoch} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {rename p ""} sl@0: proc p {} { sl@0: return "global p" sl@0: } sl@0: namespace eval test_ns_basic { sl@0: proc p {} { sl@0: return "namespace p" sl@0: } sl@0: proc callP {} { sl@0: p sl@0: } sl@0: } sl@0: list [test_ns_basic::callP] \ sl@0: [rename test_ns_basic::p ""] \ sl@0: [test_ns_basic::callP] sl@0: } {{namespace p} {} {global p}} sl@0: test basic-24.3 {Tcl_DeleteCommandFromToken, delete imported cmds that refer to a deleted cmd} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {rename p ""} sl@0: namespace eval test_ns_basic { sl@0: namespace export p sl@0: proc p {} {return 42} sl@0: } sl@0: namespace eval test_ns_basic2 { sl@0: namespace import ::test_ns_basic::* sl@0: proc callP {} { sl@0: p sl@0: } sl@0: } sl@0: list [test_ns_basic2::callP] \ sl@0: [info commands test_ns_basic2::*] \ sl@0: [rename test_ns_basic::p ""] \ sl@0: [catch {test_ns_basic2::callP} msg] $msg \ sl@0: [info commands test_ns_basic2::*] sl@0: } {42 {::test_ns_basic2::callP ::test_ns_basic2::p} {} 1 {invalid command name "p"} ::test_ns_basic2::callP} sl@0: sl@0: test basic-25.1 {TclCleanupCommand} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} { sl@0: # If object isn't preserved, errorInfo would be set to sl@0: # "foo\n while executing\n\"garbage bytes\"" because the object's sl@0: # string would have been freed, leaving garbage bytes for the error sl@0: # message. sl@0: sl@0: proc bgerror {args} {set ::x $::errorInfo} sl@0: set fName [makeFile {} test1] sl@0: set f [open $fName w] sl@0: fileevent $f writable "fileevent $f writable {}; error foo" sl@0: set x {} sl@0: vwait x sl@0: close $f sl@0: removeFile test1 sl@0: rename bgerror {} sl@0: set x sl@0: } "foo\n while executing\n\"error foo\"" sl@0: sl@0: test basic-26.2 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} { sl@0: # sl@0: # Follow the pure-list branch in a manner that sl@0: # a - the pure-list internal rep is destroyed by shimmering sl@0: # b - the command returns an error sl@0: # As the error code in Tcl_EvalObjv accesses the list elements, this will sl@0: # cause a segfault if [Bug 1119369] has not been fixed. sl@0: # sl@0: sl@0: set SRC [list foo 1] ;# pure-list command sl@0: proc foo str { sl@0: # Shimmer pure-list to cmdName, cleanup and error sl@0: proc $::SRC {} {}; $::SRC sl@0: error "BAD CALL" sl@0: } sl@0: catch {eval $SRC} sl@0: } 1 sl@0: sl@0: test basic-27.1 {Tcl_ExprLong} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-28.1 {Tcl_ExprDouble} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-29.1 {Tcl_ExprBoolean} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-30.1 {Tcl_ExprLongObj} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-31.1 {Tcl_ExprDoubleObj} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-32.1 {Tcl_ExprBooleanObj} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-33.1 {TclInvoke} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-34.1 {TclGlobalInvoke} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-35.1 {TclObjInvokeGlobal} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-36.1 {TclObjInvoke, lookup of "unknown" command} { sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {interp delete test_interp} sl@0: interp create test_interp sl@0: interp eval test_interp { sl@0: proc unknown {args} { sl@0: return "global unknown" sl@0: } sl@0: namespace eval test_ns_basic { sl@0: proc unknown {args} { sl@0: return "namespace unknown" sl@0: } sl@0: } sl@0: } sl@0: list [interp alias test_interp newAlias test_interp doesntExist] \ sl@0: [catch {interp eval test_interp {newAlias}} msg] $msg \ sl@0: [interp delete test_interp] sl@0: } {newAlias 0 {global unknown} {}} sl@0: sl@0: test basic-37.1 {Tcl_ExprString: see expr.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-38.1 {Tcl_ExprObj} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-39.1 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} { sl@0: testcmdtrace tracetest {set stuff [expr 14 + 16]} sl@0: } {{expr 14 + 16} {expr 14 + 16} {set stuff [expr 14 + 16]} {set stuff 30}} sl@0: test basic-39.2 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} { sl@0: testcmdtrace tracetest {set stuff [info tclversion]} sl@0: } [list {info tclversion} {info tclversion} {set stuff [info tclversion]} "set stuff $tclvers"] sl@0: test basic-39.3 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} { sl@0: testcmdtrace deletetest {set stuff [info tclversion]} sl@0: } $tclvers sl@0: test basic-39.4 {Tcl_CreateTrace, check that tracing doesn't cause memory faults} {testcmdtrace} { sl@0: # Note that the proc call is the same as the variable name, and that sl@0: # the call can be direct or indirect by way of another procedure sl@0: proc tracer {args} {} sl@0: proc tracedLoop {level} { sl@0: incr level sl@0: tracer sl@0: foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level} sl@0: } sl@0: testcmdtrace tracetest {tracedLoop 0} sl@0: } {{tracedLoop 0} {tracedLoop 0} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {1 2} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}}} sl@0: catch {rename tracer {}} sl@0: catch {rename tracedLoop {}} sl@0: sl@0: test basic-39.5 {Tcl_CreateObjTrace, status return TCL_ERROR} {testcmdtrace} { sl@0: proc Error { args } { error "Shouldn't get here" } sl@0: set x 1; sl@0: list [catch {testcmdtrace resulttest {Error $x}} result] [set result] sl@0: } {1 {Error $x}} sl@0: sl@0: test basic-39.6 {Tcl_CreateObjTrace, status return TCL_RETURN} {testcmdtrace} { sl@0: proc Return { args } { error "Shouldn't get here" } sl@0: set x 1; sl@0: list [catch {testcmdtrace resulttest {Return $x}} result] [set result] sl@0: } {2 {}} sl@0: sl@0: test basic-39.7 {Tcl_CreateObjTrace, status return TCL_BREAK} {testcmdtrace} { sl@0: proc Break { args } { error "Shouldn't get here" } sl@0: set x 1; sl@0: list [catch {testcmdtrace resulttest {Break $x}} result] [set result] sl@0: } {3 {}} sl@0: sl@0: test basic-39.8 {Tcl_CreateObjTrace, status return TCL_CONTINUE} {testcmdtrace} { sl@0: proc Continue { args } { error "Shouldn't get here" } sl@0: set x 1; sl@0: list [catch {testcmdtrace resulttest {Continue $x}} result] [set result] sl@0: } {4 {}} sl@0: sl@0: test basic-39.9 {Tcl_CreateObjTrace, status return unknown} {testcmdtrace} { sl@0: proc OtherStatus { args } { error "Shouldn't get here" } sl@0: set x 1; sl@0: list [catch {testcmdtrace resulttest {OtherStatus $x}} result] [set result] sl@0: } {6 {}} sl@0: sl@0: test basic-39.10 {Tcl_CreateTrace, correct level interpretation} {testcmdtrace} { sl@0: proc foo {} {uplevel 1 bar} sl@0: proc bar {} {uplevel 1 grok} sl@0: proc grok {} {uplevel 1 spock} sl@0: proc spock {} {uplevel 1 fascinating} sl@0: proc fascinating {} {} sl@0: testcmdtrace leveltest {foo} sl@0: } {foo {foo} {uplevel 1 bar} {uplevel 1 bar} bar {bar} {uplevel 1 grok} {uplevel 1 grok}} sl@0: sl@0: test basic-40.1 {Tcl_DeleteTrace} {emptyTest} { sl@0: # the above tests have tested Tcl_DeleteTrace sl@0: } {} sl@0: sl@0: test basic-41.1 {Tcl_AddErrorInfo} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-42.1 {Tcl_AddObjErrorInfo} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-43.1 {Tcl_VarEval} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-44.1 {Tcl_GlobalEval} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-45.1 {Tcl_SetRecursionLimit: see interp.test} {emptyTest} { sl@0: } {} sl@0: sl@0: test basic-46.1 {Tcl_AllowExceptions: exception return not allowed} {stdio} { sl@0: catch {close $f} sl@0: set res [catch { sl@0: set f [open |[list [interpreter]] w+] sl@0: fconfigure $f -buffering line sl@0: puts $f {fconfigure stdout -buffering line} sl@0: puts $f continue sl@0: puts $f {puts $errorInfo} sl@0: puts $f {puts DONE} sl@0: set newMsg {} sl@0: set msg {} sl@0: while {$newMsg != "DONE"} { sl@0: set newMsg [gets $f] sl@0: append msg "${newMsg}\n" sl@0: } sl@0: close $f sl@0: } error] sl@0: list $res $msg sl@0: } {1 {invoked "continue" outside of a loop sl@0: while executing sl@0: "continue" sl@0: DONE sl@0: }} sl@0: sl@0: test basic-46.2 {Tcl_AllowExceptions: exception return not allowed} -setup { sl@0: set fName [makeFile { sl@0: puts hello sl@0: break sl@0: } BREAKtest] sl@0: } -constraints { sl@0: exec sl@0: } -body { sl@0: exec [interpreter] $fName sl@0: } -cleanup { sl@0: removeFile BREAKtest sl@0: } -returnCodes error -match glob -result {hello sl@0: invoked "break" outside of a loop sl@0: while executing sl@0: "break" sl@0: (file "*BREAKtest" line 3)} sl@0: sl@0: test basic-46.3 {Tcl_AllowExceptions: exception return not allowed} -setup { sl@0: set fName [makeFile { sl@0: interp alias {} patch {} info patchlevel sl@0: patch sl@0: break sl@0: } BREAKtest] sl@0: } -constraints { sl@0: exec sl@0: } -body { sl@0: exec [interpreter] $fName sl@0: } -cleanup { sl@0: removeFile BREAKtest sl@0: } -returnCodes error -match glob -result {invoked "break" outside of a loop sl@0: while executing sl@0: "break" sl@0: (file "*BREAKtest" line 4)} sl@0: sl@0: test basic-46.4 {Tcl_AllowExceptions: exception return not allowed} -setup { sl@0: set fName [makeFile { sl@0: foo [set a 1] [break] sl@0: } BREAKtest] sl@0: } -constraints { sl@0: exec sl@0: } -body { sl@0: exec [interpreter] $fName sl@0: } -cleanup { sl@0: removeFile BREAKtest sl@0: } -returnCodes error -match glob -result {invoked "break" outside of a loop sl@0: while executing* sl@0: "foo \[set a 1] \[break]" sl@0: (file "*BREAKtest" line 2)} sl@0: sl@0: test basic-46.5 {Tcl_AllowExceptions: exception return not allowed} -setup { sl@0: set fName [makeFile { sl@0: return -code return sl@0: } BREAKtest] sl@0: } -constraints { sl@0: exec sl@0: } -body { sl@0: exec [interpreter] $fName sl@0: } -cleanup { sl@0: removeFile BREAKtest sl@0: } -returnCodes error -match glob -result {command returned bad code: 2 sl@0: while executing sl@0: "return -code return" sl@0: (file "*BREAKtest" line 2)} sl@0: sl@0: test basic-47.1 {Tcl_EvalEx: check for missing close-bracket} -body { sl@0: subst {a[set b [format cd]} sl@0: } -returnCodes error -result {missing close-bracket} sl@0: sl@0: test basic-49.1 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex { sl@0: set ::x global sl@0: namespace eval ns { sl@0: variable x namespace sl@0: testevalex {set x changed} global sl@0: set ::result [list $::x $x] sl@0: } sl@0: namespace delete ns sl@0: set ::result sl@0: } {changed namespace} sl@0: test basic-49.2 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex { sl@0: set ::x global sl@0: namespace eval ns { sl@0: variable x namespace sl@0: testevalex {set ::context $x} global sl@0: } sl@0: namespace delete ns sl@0: set ::context sl@0: } {global} sl@0: sl@0: # cleanup sl@0: catch {eval namespace delete [namespace children :: test_ns_*]} sl@0: catch {namespace delete george} sl@0: catch {interp delete test_interp} sl@0: catch {rename p ""} sl@0: catch {rename q ""} sl@0: catch {rename cmd ""} sl@0: catch {rename value:at: ""} sl@0: catch {unset x} sl@0: ::tcltest::cleanupTests sl@0: return