archie/tcl7.3/tests/trace.test
2024-05-27 16:13:40 +02:00

915 lines
27 KiB
Plaintext

# Commands covered: trace
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# All rights reserved.
#
# Permission is hereby granted, without written agreement and without
# license or royalty fees, to use, copy, modify, and distribute this
# software and its documentation for any purpose, provided that the
# above copyright notice and the following two paragraphs appear in
# all copies of this software.
#
# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
# $Header: /user6/ouster/tcl/tests/RCS/trace.test,v 1.20 93/10/11 09:05:38 ouster Exp $ (Berkeley)
if {[string compare test [info procs test]] == 1} then {source defs}
proc traceScalar {name1 name2 op} {
global info
set info [list $name1 $name2 $op [catch {uplevel set $name1} msg] $msg]
}
proc traceArray {name1 name2 op} {
global info
set info [list $name1 $name2 $op [catch {uplevel set [set name1]($name2)} msg] $msg]
}
proc traceProc {name1 name2 op} {
global info
set info [concat $info [list $name1 $name2 $op]]
}
proc traceTag {tag args} {
global info
set info [concat $info $tag]
}
proc traceError {args} {
error "trace returned error"
}
proc traceCheck {cmd args} {
global info
set info [list [catch $cmd msg] $msg]
}
proc traceCrtElement {value name1 name2 op} {
uplevel set ${name1}($name2) $value
}
# Read-tracing on variables
test trace-1.1 {trace variable reads} {
catch {unset x}
set info {}
trace var x r traceScalar
list [catch {set x} msg] $msg $info
} {1 {can't read "x": no such variable} {x {} r 1 {can't read "x": no such variable}}}
test trace-1.2 {trace variable reads} {
catch {unset x}
set x 123
set info {}
trace var x r traceScalar
list [catch {set x} msg] $msg $info
} {0 123 {x {} r 0 123}}
test trace-1.3 {trace variable reads} {
catch {unset x}
set info {}
trace var x r traceScalar
set x 123
set info
} {}
test trace-1.4 {trace array element reads} {
catch {unset x}
set info {}
trace var x(2) r traceArray
list [catch {set x(2)} msg] $msg $info
} {1 {can't read "x(2)": no such element in array} {x 2 r 1 {can't read "x(2)": no such element in array}}}
test trace-1.5 {trace array element reads} {
catch {unset x}
set x(2) zzz
set info {}
trace var x(2) r traceArray
list [catch {set x(2)} msg] $msg $info
} {0 zzz {x 2 r 0 zzz}}
test trace-1.6 {trace reads on whole arrays} {
catch {unset x}
set info {}
trace var x r traceArray
list [catch {set x(2)} msg] $msg $info
} {1 {can't read "x(2)": no such variable} {}}
test trace-1.7 {trace reads on whole arrays} {
catch {unset x}
set x(2) zzz
set info {}
trace var x r traceArray
list [catch {set x(2)} msg] $msg $info
} {0 zzz {x 2 r 0 zzz}}
test trace-1.8 {trace variable reads} {
catch {unset x}
set x 444
set info {}
trace var x r traceScalar
unset x
set info
} {}
# Basic write-tracing on variables
test trace-2.1 {trace variable writes} {
catch {unset x}
set info {}
trace var x w traceScalar
set x 123
set info
} {x {} w 0 123}
test trace-2.2 {trace writes to array elements} {
catch {unset x}
set info {}
trace var x(33) w traceArray
set x(33) 444
set info
} {x 33 w 0 444}
test trace-2.3 {trace writes on whole arrays} {
catch {unset x}
set info {}
trace var x w traceArray
set x(abc) qq
set info
} {x abc w 0 qq}
test trace-2.4 {trace variable writes} {
catch {unset x}
set x 1234
set info {}
trace var x w traceScalar
set x
set info
} {}
test trace-2.5 {trace variable writes} {
catch {unset x}
set x 1234
set info {}
trace var x w traceScalar
unset x
set info
} {}
# Basic unset-tracing on variables
test trace-3.1 {trace variable unsets} {
catch {unset x}
set info {}
trace var x u traceScalar
catch {unset x}
set info
} {x {} u 1 {can't read "x": no such variable}}
test trace-3.2 {variable mustn't exist during unset trace} {
catch {unset x}
set x 1234
set info {}
trace var x u traceScalar
unset x
set info
} {x {} u 1 {can't read "x": no such variable}}
test trace-3.3 {unset traces mustn't be called during reads and writes} {
catch {unset x}
set info {}
trace var x u traceScalar
set x 44
set x
set info
} {}
test trace-3.4 {trace unsets on array elements} {
catch {unset x}
set x(0) 18
set info {}
trace var x(1) u traceArray
catch {unset x(1)}
set info
} {x 1 u 1 {can't read "x(1)": no such element in array}}
test trace-3.5 {trace unsets on array elements} {
catch {unset x}
set x(1) 18
set info {}
trace var x(1) u traceArray
unset x(1)
set info
} {x 1 u 1 {can't read "x(1)": no such element in array}}
test trace-3.6 {trace unsets on array elements} {
catch {unset x}
set x(1) 18
set info {}
trace var x(1) u traceArray
unset x
set info
} {x 1 u 1 {can't read "x(1)": no such variable}}
test trace-3.7 {trace unsets on whole arrays} {
catch {unset x}
set x(1) 18
set info {}
trace var x u traceProc
catch {unset x(0)}
set info
} {}
test trace-3.8 {trace unsets on whole arrays} {
catch {unset x}
set x(1) 18
set x(2) 144
set x(3) 14
set info {}
trace var x u traceProc
unset x(1)
set info
} {x 1 u}
test trace-3.9 {trace unsets on whole arrays} {
catch {unset x}
set x(1) 18
set x(2) 144
set x(3) 14
set info {}
trace var x u traceProc
unset x
set info
} {x {} u}
# Trace multiple trace types at once.
test trace-4.1 {multiple ops traced at once} {
catch {unset x}
set info {}
trace var x rwu traceProc
catch {set x}
set x 22
set x
set x 33
unset x
set info
} {x {} r x {} w x {} r x {} w x {} u}
test trace-4.2 {multiple ops traced on array element} {
catch {unset x}
set info {}
trace var x(0) rwu traceProc
catch {set x(0)}
set x(0) 22
set x(0)
set x(0) 33
unset x(0)
unset x
set info
} {x 0 r x 0 w x 0 r x 0 w x 0 u}
test trace-4.3 {multiple ops traced on whole array} {
catch {unset x}
set info {}
trace var x rwu traceProc
catch {set x(0)}
set x(0) 22
set x(0)
set x(0) 33
unset x(0)
unset x
set info
} {x 0 w x 0 r x 0 w x 0 u x {} u}
# Check order of invocation of traces
test trace-5.1 {order of invocation of traces} {
catch {unset x}
set info {}
trace var x r "traceTag 1"
trace var x r "traceTag 2"
trace var x r "traceTag 3"
catch {set x}
set x 22
set x
set info
} {3 2 1 3 2 1}
test trace-5.2 {order of invocation of traces} {
catch {unset x}
set x(0) 44
set info {}
trace var x(0) r "traceTag 1"
trace var x(0) r "traceTag 2"
trace var x(0) r "traceTag 3"
set x(0)
set info
} {3 2 1}
test trace-5.3 {order of invocation of traces} {
catch {unset x}
set x(0) 44
set info {}
trace var x(0) r "traceTag 1"
trace var x r "traceTag A1"
trace var x(0) r "traceTag 2"
trace var x r "traceTag A2"
trace var x(0) r "traceTag 3"
trace var x r "traceTag A3"
set x(0)
set info
} {A3 A2 A1 3 2 1}
# Check effects of errors in trace procedures
test trace-6.1 {error returns from traces} {
catch {unset x}
set x 123
set info {}
trace var x r "traceTag 1"
trace var x r traceError
list [catch {set x} msg] $msg $info
} {1 {can't read "x": trace returned error} {}}
test trace-6.2 {error returns from traces} {
catch {unset x}
set x 123
set info {}
trace var x w "traceTag 1"
trace var x w traceError
list [catch {set x 44} msg] $msg $info
} {1 {can't set "x": trace returned error} {}}
test trace-6.3 {error returns from traces} {
catch {unset x}
set x 123
set info {}
trace var x u "traceTag 1"
trace var x u traceError
list [catch {unset x} msg] $msg $info
} {0 {} 1}
test trace-6.4 {error returns from traces} {
catch {unset x}
set x(0) 123
set info {}
trace var x(0) r "traceTag 1"
trace var x r "traceTag 2"
trace var x r traceError
trace var x r "traceTag 3"
list [catch {set x(0)} msg] $msg $info
} {1 {can't read "x(0)": trace returned error} 3}
test trace-6.5 {error returns from traces} {
catch {unset x}
set x 123
trace var x u traceError
list [catch {unset x} msg] $msg
} {0 {}}
test trace-6.6 {error returns from traces} {
# This test just makes sure that the memory for the error message
# gets deallocated correctly when the trace is invoked again or
# when the trace is deleted.
catch {unset x}
set x 123
trace var x r traceError
catch {set x}
catch {set x}
trace vdelete x r traceError
} {}
# Check to see that variables are expunged before trace
# procedures are invoked, so trace procedure can even manipulate
# a new copy of the variables.
test trace-7.1 {be sure variable is unset before trace is called} {
catch {unset x}
set x 33
set info {}
trace var x u {traceCheck {uplevel set x}}
unset x
set info
} {1 {can't read "x": no such variable}}
test trace-7.2 {be sure variable is unset before trace is called} {
catch {unset x}
set x 33
set info {}
trace var x u {traceCheck {uplevel set x 22}}
unset x
concat $info [list [catch {set x} msg] $msg]
} {0 22 0 22}
test trace-7.3 {be sure traces are cleared before unset trace called} {
catch {unset x}
set x 33
set info {}
trace var x u {traceCheck {uplevel trace vinfo x}}
unset x
set info
} {0 {}}
test trace-7.4 {set new trace during unset trace} {
catch {unset x}
set x 33
set info {}
trace var x u {traceCheck {global x; trace var x u traceProc}}
unset x
concat $info [trace vinfo x]
} {0 {} {u traceProc}}
test trace-8.1 {make sure array elements are unset before traces are called} {
catch {unset x}
set x(0) 33
set info {}
trace var x(0) u {traceCheck {uplevel set x(0)}}
unset x(0)
set info
} {1 {can't read "x(0)": no such element in array}}
test trace-8.2 {make sure array elements are unset before traces are called} {
catch {unset x}
set x(0) 33
set info {}
trace var x(0) u {traceCheck {uplevel set x(0) zzz}}
unset x(0)
concat $info [list [catch {set x(0)} msg] $msg]
} {0 zzz 0 zzz}
test trace-8.3 {array elements are unset before traces are called} {
catch {unset x}
set x(0) 33
set info {}
trace var x(0) u {traceCheck {global x; trace vinfo x(0)}}
unset x(0)
set info
} {0 {}}
test trace-8.4 {set new array element trace during unset trace} {
catch {unset x}
set x(0) 33
set info {}
trace var x(0) u {traceCheck {uplevel {trace variable x(0) r {}}}}
catch {unset x(0)}
concat $info [trace vinfo x(0)]
} {0 {} {r {}}}
test trace-9.1 {make sure arrays are unset before traces are called} {
catch {unset x}
set x(0) 33
set info {}
trace var x u {traceCheck {uplevel set x(0)}}
unset x
set info
} {1 {can't read "x(0)": no such variable}}
test trace-9.2 {make sure arrays are unset before traces are called} {
catch {unset x}
set x(y) 33
set info {}
trace var x u {traceCheck {uplevel set x(y) 22}}
unset x
concat $info [list [catch {set x(y)} msg] $msg]
} {0 22 0 22}
test trace-9.3 {make sure arrays are unset before traces are called} {
catch {unset x}
set x(y) 33
set info {}
trace var x u {traceCheck {uplevel array names x}}
unset x
set info
} {1 {"x" isn't an array}}
test trace-9.4 {make sure arrays are unset before traces are called} {
catch {unset x}
set x(y) 33
set info {}
set cmd {traceCheck {uplevel {trace vinfo x}}}
trace var x u $cmd
unset x
set info
} {0 {}}
test trace-9.5 {set new array trace during unset trace} {
catch {unset x}
set x(y) 33
set info {}
trace var x u {traceCheck {global x; trace var x r {}}}
unset x
concat $info [trace vinfo x]
} {0 {} {r {}}}
test trace-9.6 {create scalar during array unset trace} {
catch {unset x}
set x(y) 33
set info {}
trace var x u {traceCheck {global x; set x 44}}
unset x
concat $info [list [catch {set x} msg] $msg]
} {0 44 0 44}
# Check special conditions (e.g. errors) in Tcl_TraceVar2.
test trace-10.1 {creating array when setting variable traces} {
catch {unset x}
set info {}
trace var x(0) w traceProc
list [catch {set x 22} msg] $msg
} {1 {can't set "x": variable is array}}
test trace-10.2 {creating array when setting variable traces} {
catch {unset x}
set info {}
trace var x(0) w traceProc
list [catch {set x(0)} msg] $msg
} {1 {can't read "x(0)": no such element in array}}
test trace-10.3 {creating array when setting variable traces} {
catch {unset x}
set info {}
trace var x(0) w traceProc
set x(0) 22
set info
} {x 0 w}
test trace-10.4 {creating variable when setting variable traces} {
catch {unset x}
set info {}
trace var x w traceProc
list [catch {set x} msg] $msg
} {1 {can't read "x": no such variable}}
test trace-10.5 {creating variable when setting variable traces} {
catch {unset x}
set info {}
trace var x w traceProc
set x 22
set info
} {x {} w}
test trace-10.6 {creating variable when setting variable traces} {
catch {unset x}
set info {}
trace var x w traceProc
set x(0) 22
set info
} {x 0 w}
test trace-10.7 {create array element during read trace} {
catch {unset x}
set x(2) zzz
trace var x r {traceCrtElement xyzzy}
list [catch {set x(3)} msg] $msg
} {0 xyzzy}
test trace-10.8 {errors when setting variable traces} {
catch {unset x}
set x 44
list [catch {trace var x(0) w traceProc} msg] $msg
} {1 {can't trace "x(0)": variable isn't array}}
# Check deleting one trace from another.
test trace-11.1 {delete one trace from another} {
proc delTraces {args} {
global x
trace vdel x r {traceTag 2}
trace vdel x r {traceTag 3}
trace vdel x r {traceTag 4}
}
catch {unset x}
set x 44
set info {}
trace var x r {traceTag 1}
trace var x r {traceTag 2}
trace var x r {traceTag 3}
trace var x r {traceTag 4}
trace var x r delTraces
trace var x r {traceTag 5}
set x
set info
} {5 1}
# Check operation and syntax of "trace" command.
test trace-12.1 {trace command (overall)} {
list [catch {trace} msg] $msg
} {1 {too few args: should be "trace option [arg arg ...]"}}
test trace-12.2 {trace command (overall)} {
list [catch {trace gorp} msg] $msg
} {1 {bad option "gorp": should be variable, vdelete, or vinfo}}
test trace-12.3 {trace command ("variable" option)} {
list [catch {trace variable x y} msg] $msg
} {1 {wrong # args: should be "trace variable name ops command"}}
test trace-12.4 {trace command ("variable" option)} {
list [catch {trace var x y z z2} msg] $msg
} {1 {wrong # args: should be "trace variable name ops command"}}
test trace-12.5 {trace command ("variable" option)} {
list [catch {trace var x y z} msg] $msg
} {1 {bad operations "y": should be one or more of rwu}}
test trace-12.6 {trace command ("vdelete" option)} {
list [catch {trace vdelete x y} msg] $msg
} {1 {wrong # args: should be "trace vdelete name ops command"}}
test trace-12.7 {trace command ("vdelete" option)} {
list [catch {trace vdelete x y z foo} msg] $msg
} {1 {wrong # args: should be "trace vdelete name ops command"}}
test trace-12.8 {trace command ("vdelete" option)} {
list [catch {trace vdelete x y z} msg] $msg
} {1 {bad operations "y": should be one or more of rwu}}
test trace-12.9 {trace command ("vdelete" option)} {
catch {unset x}
set info {}
trace var x w traceProc
trace vdelete x w traceProc
} {}
test trace-12.10 {trace command ("vdelete" option)} {
catch {unset x}
set info {}
trace var x w traceProc
trace vdelete x w traceProc
set x 12345
set info
} {}
test trace-12.11 {trace command ("vdelete" option)} {
catch {unset x}
set info {}
trace var x w {traceTag 1}
trace var x w traceProc
trace var x w {traceTag 2}
set x yy
trace vdelete x w traceProc
set x 12345
trace vdelete x w {traceTag 1}
set x foo
trace vdelete x w {traceTag 2}
set x gorp
set info
} {2 x {} w 1 2 1 2}
test trace-12.12 {trace command ("vdelete" option)} {
catch {unset x}
set info {}
trace var x w {traceTag 1}
trace vdelete x w non_existent
set x 12345
set info
} {1}
test trace-12.13 {trace command ("vinfo" option)} {
list [catch {trace vinfo} msg] $msg]
} {1 {wrong # args: should be "trace vinfo name"]}}
test trace-12.14 {trace command ("vinfo" option)} {
list [catch {trace vinfo x y} msg] $msg]
} {1 {wrong # args: should be "trace vinfo name"]}}
test trace-12.15 {trace command ("vinfo" option)} {
catch {unset x}
trace var x w {traceTag 1}
trace var x w traceProc
trace var x w {traceTag 2}
trace vinfo x
} {{w {traceTag 2}} {w traceProc} {w {traceTag 1}}}
test trace-12.16 {trace command ("vinfo" option)} {
catch {unset x}
trace vinfo x
} {}
test trace-12.17 {trace command ("vinfo" option)} {
catch {unset x}
trace vinfo x(0)
} {}
test trace-12.18 {trace command ("vinfo" option)} {
catch {unset x}
set x 44
trace vinfo x(0)
} {}
test trace-12.19 {trace command ("vinfo" option)} {
catch {unset x}
set x 44
trace var x w {traceTag 1}
proc check {} {global x; trace vinfo x}
check
} {{w {traceTag 1}}}
# Check fancy trace commands (long ones, weird arguments, etc.)
test trace-13.1 {long trace command} {
catch {unset x}
set info {}
trace var x w {traceTag {This is a very very long argument. It's \
designed to test out the facilities of TraceVarProc for dealing \
with such long arguments by malloc-ing space. One possibility \
is that space doesn't get freed properly. If this happens, then \
invoking this test over and over again will eventually leak memory.}}
set x 44
set info
} {This is a very very long argument. It's \
designed to test out the facilities of TraceVarProc for dealing \
with such long arguments by malloc-ing space. One possibility \
is that space doesn't get freed properly. If this happens, then \
invoking this test over and over again will eventually leak memory.}
test trace-13.2 {long trace command result to ignore} {
proc longResult {args} {return "quite a bit of text, designed to
generate a core leak if this command file is invoked over and over again
and memory isn't being recycled correctly"}
catch {unset x}
trace var x w longResult
set x 44
set x 5
set x abcde
} abcde
test trace-13.3 {special list-handling in trace commands} {
catch {unset "x y z"}
set "x y z(a\n\{)" 44
set info {}
trace var "x y z(a\n\{)" w traceProc
set "x y z(a\n\{)" 33
set info
} "{x y z} a\\n\\{ w"
# Check for proper handling of unsets during traces.
proc traceUnset {unsetName args} {
global info
upvar $unsetName x
lappend info [catch {unset x} msg] $msg [catch {set x} msg] $msg
}
proc traceReset {unsetName resetName args} {
global info
upvar $unsetName x $resetName y
lappend info [catch {unset x} msg] $msg [catch {set y xyzzy} msg] $msg
}
proc traceReset2 {unsetName resetName args} {
global info
lappend info [catch {uplevel unset $unsetName} msg] $msg \
[catch {uplevel set $resetName xyzzy} msg] $msg
}
proc traceAppend {string name1 name2 op} {
global info
lappend info $string
}
test trace-14.1 {unsets during read traces} {
catch {unset y}
set y 1234
set info {}
trace var y r {traceUnset y}
trace var y u {traceAppend unset}
lappend info [catch {set y} msg] $msg
} {unset 0 {} 1 {can't read "x": no such variable} 1 {can't read "y": no such variable}}
test trace-14.2 {unsets during read traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) r {traceUnset y(0)}
lappend info [catch {set y(0)} msg] $msg
} {0 {} 1 {can't read "x": no such variable} 1 {can't read "y(0)": no such element in array}}
test trace-14.3 {unsets during read traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) r {traceUnset y}
lappend info [catch {set y(0)} msg] $msg
} {0 {} 1 {can't read "x": no such variable} 1 {can't read "y(0)": no such variable}}
test trace-14.4 {unsets during read traces} {
catch {unset y}
set y 1234
set info {}
trace var y r {traceReset y y}
lappend info [catch {set y} msg] $msg
} {0 {} 0 xyzzy 0 xyzzy}
test trace-14.5 {unsets during read traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) r {traceReset y(0) y(0)}
lappend info [catch {set y(0)} msg] $msg
} {0 {} 0 xyzzy 0 xyzzy}
test trace-14.6 {unsets during read traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) r {traceReset y y(0)}
lappend info [catch {set y(0)} msg] $msg [catch {set y(0)} msg] $msg
} {0 {} 1 {can't set "y": upvar refers to element in deleted array} 1 {can't read "y(0)": no such variable} 1 {can't read "y(0)": no such variable}}
test trace-14.7 {unsets during read traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) r {traceReset2 y y(0)}
lappend info [catch {set y(0)} msg] $msg [catch {set y(0)} msg] $msg
} {0 {} 0 xyzzy 1 {can't read "y(0)": no such element in array} 0 xyzzy}
test trace-14.8 {unsets during write traces} {
catch {unset y}
set y 1234
set info {}
trace var y w {traceUnset y}
trace var y u {traceAppend unset}
lappend info [catch {set y xxx} msg] $msg
} {unset 0 {} 1 {can't read "x": no such variable} 0 {}}
test trace-14.9 {unsets during write traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) w {traceUnset y(0)}
lappend info [catch {set y(0) xxx} msg] $msg
} {0 {} 1 {can't read "x": no such variable} 0 {}}
test trace-14.10 {unsets during write traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) w {traceUnset y}
lappend info [catch {set y(0) xxx} msg] $msg
} {0 {} 1 {can't read "x": no such variable} 0 {}}
test trace-14.11 {unsets during write traces} {
catch {unset y}
set y 1234
set info {}
trace var y w {traceReset y y}
lappend info [catch {set y xxx} msg] $msg
} {0 {} 0 xyzzy 0 xyzzy}
test trace-14.12 {unsets during write traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) w {traceReset y(0) y(0)}
lappend info [catch {set y(0) xxx} msg] $msg
} {0 {} 0 xyzzy 0 xyzzy}
test trace-14.13 {unsets during write traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) w {traceReset y y(0)}
lappend info [catch {set y(0) xxx} msg] $msg [catch {set y(0)} msg] $msg
} {0 {} 1 {can't set "y": upvar refers to element in deleted array} 0 {} 1 {can't read "y(0)": no such variable}}
test trace-14.14 {unsets during write traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) w {traceReset2 y y(0)}
lappend info [catch {set y(0) xxx} msg] $msg [catch {set y(0)} msg] $msg
} {0 {} 0 xyzzy 0 {} 0 xyzzy}
test trace-14.15 {unsets during unset traces} {
catch {unset y}
set y 1234
set info {}
trace var y u {traceUnset y}
lappend info [catch {unset y} msg] $msg [catch {set y} msg] $msg
} {1 {can't unset "x": no such variable} 1 {can't read "x": no such variable} 0 {} 1 {can't read "y": no such variable}}
test trace-14.16 {unsets during unset traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) u {traceUnset y(0)}
lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
} {1 {can't unset "x": no such variable} 1 {can't read "x": no such variable} 0 {} 1 {can't read "y(0)": no such element in array}}
test trace-14.17 {unsets during unset traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) u {traceUnset y}
lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
} {0 {} 1 {can't read "x": no such variable} 0 {} 1 {can't read "y(0)": no such variable}}
test trace-14.18 {unsets during unset traces} {
catch {unset y}
set y 1234
set info {}
trace var y u {traceReset2 y y}
lappend info [catch {unset y} msg] $msg [catch {set y} msg] $msg
} {1 {can't unset "y": no such variable} 0 xyzzy 0 {} 0 xyzzy}
test trace-14.19 {unsets during unset traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) u {traceReset2 y(0) y(0)}
lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
} {1 {can't unset "y(0)": no such element in array} 0 xyzzy 0 {} 0 xyzzy}
test trace-14.20 {unsets during unset traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) u {traceReset2 y y(0)}
lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
} {0 {} 0 xyzzy 0 {} 0 xyzzy}
test trace-14.21 {unsets cancelling traces} {
catch {unset y}
set y 1234
set info {}
trace var y r {traceAppend first}
trace var y r {traceUnset y}
trace var y r {traceAppend third}
trace var y u {traceAppend unset}
lappend info [catch {set y} msg] $msg
} {third unset 0 {} 1 {can't read "x": no such variable} 1 {can't read "y": no such variable}}
test trace-14.22 {unsets cancelling traces} {
catch {unset y}
set y(0) 1234
set info {}
trace var y(0) r {traceAppend first}
trace var y(0) r {traceUnset y}
trace var y(0) r {traceAppend third}
trace var y(0) u {traceAppend unset}
lappend info [catch {set y(0)} msg] $msg
} {third unset 0 {} 1 {can't read "x": no such variable} 1 {can't read "y(0)": no such variable}}
# Check various non-interference between traces and other things.
test trace-15.1 {trace doesn't prevent unset errors} {
catch {unset x}
set info {}
trace var x u {traceProc}
list [catch {unset x} msg] $msg $info
} {1 {can't unset "x": no such variable} {x {} u}}
test trace-15.2 {traced variables must survive procedure exits} {
catch {unset x}
proc p1 {} {global x; trace var x w traceProc}
p1
trace vinfo x
} {{w traceProc}}
test trace-15.3 {traced variables must survive procedure exits} {
catch {unset x}
set info {}
proc p1 {} {global x; trace var x w traceProc}
p1
set x 44
set info
} {x {} w}
# Be sure that procedure frames are released before unset traces
# are invoked.
test trace-16.1 {unset traces on procedure returns} {
proc p1 {x y} {set a 44; p2 14}
proc p2 {z} {trace var z u {traceCheck {lsort [uplevel {info vars}]}}}
set info {}
p1 foo bar
set info
} {0 {a x y}}
# Delete arrays when done, so they can be re-used as scalars
# elsewhere.
catch {unset x}
catch {unset y}
concat {}