trace.test
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:74k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # Commands covered:  trace
  2. #
  3. # This file contains a collection of tests for one or more of the Tcl
  4. # built-in commands.  Sourcing this file into Tcl runs the tests and
  5. # generates output for errors.  No output means no errors were found.
  6. #
  7. # Copyright (c) 1991-1993 The Regents of the University of California.
  8. # Copyright (c) 1994 Sun Microsystems, Inc.
  9. # Copyright (c) 1998-1999 by Scriptics Corporation.
  10. #
  11. # See the file "license.terms" for information on usage and redistribution
  12. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13. #
  14. # RCS: @(#) $Id: trace.test,v 1.26.2.18 2007/08/14 15:15:39 dgp Exp $
  15. if {[lsearch [namespace children] ::tcltest] == -1} {
  16.     package require tcltest
  17.     namespace import -force ::tcltest::*
  18. }
  19. # Used for constraining memory leak tests
  20. testConstraint memory [llength [info commands memory]]
  21. testConstraint testevalobjv [llength [info commands testevalobjv]]
  22. proc getbytes {} {
  23.     set lines [split [memory info] "n"]
  24.     lindex [lindex $lines 3] 3
  25. }
  26. proc traceScalar {name1 name2 op} {
  27.     global info
  28.     set info [list $name1 $name2 $op [catch {uplevel set $name1} msg] $msg]
  29. }
  30. proc traceScalarAppend {name1 name2 op} {
  31.     global info
  32.     lappend info $name1 $name2 $op [catch {uplevel set $name1} msg] $msg
  33. }
  34. proc traceArray {name1 name2 op} {
  35.     global info
  36.     set info [list $name1 $name2 $op [catch {uplevel set [set name1]($name2)} msg] $msg]
  37. }
  38. proc traceArray2 {name1 name2 op} {
  39.     global info
  40.     set info [list $name1 $name2 $op]
  41. }
  42. proc traceProc {name1 name2 op} {
  43.     global info
  44.     set info [concat $info [list $name1 $name2 $op]]
  45. }
  46. proc traceTag {tag args} {
  47.     global info
  48.     set info [concat $info $tag]
  49. }
  50. proc traceError {args} {
  51.     error "trace returned error"
  52. }
  53. proc traceCheck {cmd args} {
  54.     global info
  55.     set info [list [catch $cmd msg] $msg]
  56. }
  57. proc traceCrtElement {value name1 name2 op} {
  58.     uplevel set ${name1}($name2) $value
  59. }
  60. proc traceCommand {oldName newName op} {
  61.     global info
  62.     set info [list $oldName $newName $op]
  63. }
  64. test trace-0.0 {memory corruption in trace (Tcl Bug 484339)} {
  65.     # You may need Purify or Electric Fence to reliably
  66.     # see this one fail.
  67.     catch {unset z}
  68.     trace add variable z array {set z(foo) 1 ;#}
  69.     set res "names: [array names z]"
  70.     catch {unset ::z}
  71.     trace variable ::z w {unset ::z; error "memory corruption";#}
  72.     list [catch {set ::z 1} msg] $msg
  73. } {1 {can't set "::z": memory corruption}}
  74. # Read-tracing on variables
  75. test trace-1.1 {trace variable reads} {
  76.     catch {unset x}
  77.     set info {}
  78.     trace add variable x read traceScalar
  79.     list [catch {set x} msg] $msg $info
  80. } {1 {can't read "x": no such variable} {x {} read 1 {can't read "x": no such variable}}}
  81. test trace-1.2 {trace variable reads} {
  82.     catch {unset x}
  83.     set x 123
  84.     set info {}
  85.     trace add variable x read traceScalar
  86.     list [catch {set x} msg] $msg $info
  87. } {0 123 {x {} read 0 123}}
  88. test trace-1.3 {trace variable reads} {
  89.     catch {unset x}
  90.     set info {}
  91.     trace add variable x read traceScalar
  92.     set x 123
  93.     set info
  94. } {}
  95. test trace-1.4 {trace array element reads} {
  96.     catch {unset x}
  97.     set info {}
  98.     trace add variable x(2) read traceArray
  99.     list [catch {set x(2)} msg] $msg $info
  100. } {1 {can't read "x(2)": no such element in array} {x 2 read 1 {can't read "x(2)": no such element in array}}}
  101. test trace-1.5 {trace array element reads} {
  102.     catch {unset x}
  103.     set x(2) zzz
  104.     set info {}
  105.     trace add variable x(2) read traceArray
  106.     list [catch {set x(2)} msg] $msg $info
  107. } {0 zzz {x 2 read 0 zzz}}
  108. test trace-1.6 {trace array element reads} {
  109.     catch {unset x}
  110.     set info {}
  111.     trace add variable x read traceArray2
  112.     proc p {} {
  113.         global x
  114.         set x(2) willi
  115.         return $x(2)
  116.     }
  117.     list [catch {p} msg] $msg $info
  118. } {0 willi {x 2 read}}
  119. test trace-1.7 {trace array element reads, create element undefined if nonexistant} {
  120.     catch {unset x}
  121.     set info {}
  122.     trace add variable x read q
  123.     proc q {name1 name2 op} {
  124.         global info
  125.         set info [list $name1 $name2 $op]
  126.         global $name1
  127.         set ${name1}($name2) wolf
  128.     }
  129.     proc p {} {
  130.         global x
  131.         set x(X) willi
  132.         return $x(Y)
  133.     }
  134.     list [catch {p} msg] $msg $info
  135. } {0 wolf {x Y read}}
  136. test trace-1.8 {trace reads on whole arrays} {
  137.     catch {unset x}
  138.     set info {}
  139.     trace add variable x read traceArray
  140.     list [catch {set x(2)} msg] $msg $info
  141. } {1 {can't read "x(2)": no such variable} {}}
  142. test trace-1.9 {trace reads on whole arrays} {
  143.     catch {unset x}
  144.     set x(2) zzz
  145.     set info {}
  146.     trace add variable x read traceArray
  147.     list [catch {set x(2)} msg] $msg $info
  148. } {0 zzz {x 2 read 0 zzz}}
  149. test trace-1.10 {trace variable reads} {
  150.     catch {unset x}
  151.     set x 444
  152.     set info {}
  153.     trace add variable x read traceScalar
  154.     unset x
  155.     set info
  156. } {}
  157. test trace-1.11 {read traces that modify the array structure} {
  158.     catch {unset x}
  159.     set x(bar) 0 
  160.     trace variable x r {set x(foo) 1 ;#} 
  161.     trace variable x r {unset -nocomplain x(bar) ;#} 
  162.     array get x
  163. } {}
  164. test trace-1.12 {read traces that modify the array structure} {
  165.     catch {unset x}
  166.     set x(bar) 0 
  167.     trace variable x r {unset -nocomplain x(bar) ;#} 
  168.     trace variable x r {set x(foo) 1 ;#} 
  169.     array get x
  170. } {}
  171. test trace-1.13 {read traces that modify the array structure} {
  172.     catch {unset x}
  173.     set x(bar) 0 
  174.     trace variable x r {set x(foo) 1 ;#} 
  175.     trace variable x r {unset -nocomplain x;#} 
  176.     list [catch {array get x} res] $res
  177. } {1 {can't read "x(bar)": no such variable}}
  178. test trace-1.14 {read traces that modify the array structure} {
  179.     catch {unset x}
  180.     set x(bar) 0 
  181.     trace variable x r {unset -nocomplain x;#} 
  182.     trace variable x r {set x(foo) 1 ;#} 
  183.     list [catch {array get x} res] $res
  184. } {1 {can't read "x(bar)": no such variable}}
  185. # Basic write-tracing on variables
  186. test trace-2.1 {trace variable writes} {
  187.     catch {unset x}
  188.     set info {}
  189.     trace add variable x write traceScalar
  190.     set x 123
  191.     set info
  192. } {x {} write 0 123}
  193. test trace-2.2 {trace writes to array elements} {
  194.     catch {unset x}
  195.     set info {}
  196.     trace add variable x(33) write traceArray
  197.     set x(33) 444
  198.     set info
  199. } {x 33 write 0 444}
  200. test trace-2.3 {trace writes on whole arrays} {
  201.     catch {unset x}
  202.     set info {}
  203.     trace add variable x write traceArray
  204.     set x(abc) qq
  205.     set info
  206. } {x abc write 0 qq}
  207. test trace-2.4 {trace variable writes} {
  208.     catch {unset x}
  209.     set x 1234
  210.     set info {}
  211.     trace add variable x write traceScalar
  212.     set x
  213.     set info
  214. } {}
  215. test trace-2.5 {trace variable writes} {
  216.     catch {unset x}
  217.     set x 1234
  218.     set info {}
  219.     trace add variable x write traceScalar
  220.     unset x
  221.     set info
  222. } {}
  223. test trace-2.6 {trace variable writes on compiled local} {
  224.     #
  225.     # Check correct function of whole array traces on compiled local
  226.     # arrays [Bug 1770591]. The corresponding function for read traces is
  227.     # already indirectly tested in trace-1.7
  228.     #
  229.     catch {unset x}
  230.     set info {}
  231.     proc p {} {
  232.         trace add variable x write traceArray
  233.         set x(X) willy
  234.     }
  235.     p
  236.     set info
  237. } {x X write 0 willy}
  238. test trace-2.7 {trace variable writes on errorInfo} -body {
  239.    #
  240.    # Check correct behaviour of write traces on errorInfo.
  241.    # [Bug 1773040]
  242.    trace add variable ::errorInfo write traceScalar
  243.    catch {set dne}
  244.    lrange [set info] 0 2
  245. } -cleanup {
  246.    # always remove trace on errorInfo otherwise further tests will fail
  247.    unset ::errorInfo
  248. } -result {::errorInfo {} write}
  249. # append no longer triggers read traces when fetching the old values of
  250. # variables before doing the append operation. However, lappend _does_
  251. # still trigger these read traces. Also lappend triggers only one write
  252. # trace: after appending all arguments to the list.
  253. test trace-3.1 {trace variable read-modify-writes} {
  254.     catch {unset x}
  255.     set info {}
  256.     trace add variable x read traceScalarAppend
  257.     append x 123
  258.     append x 456
  259.     lappend x 789
  260.     set info
  261. } {x {} read 0 123456}
  262. test trace-3.2 {trace variable read-modify-writes} {
  263.     catch {unset x}
  264.     set info {}
  265.     trace add variable x {read write} traceScalarAppend
  266.     append x 123
  267.     lappend x 456
  268.     set info
  269. } {x {} write 0 123 x {} read 0 123 x {} write 0 {123 456}}
  270. # Basic unset-tracing on variables
  271. test trace-4.1 {trace variable unsets} {
  272.     catch {unset x}
  273.     set info {}
  274.     trace add variable x unset traceScalar
  275.     catch {unset x}
  276.     set info
  277. } {x {} unset 1 {can't read "x": no such variable}}
  278. test trace-4.2 {variable mustn't exist during unset trace} {
  279.     catch {unset x}
  280.     set x 1234
  281.     set info {}
  282.     trace add variable x unset traceScalar
  283.     unset x
  284.     set info
  285. } {x {} unset 1 {can't read "x": no such variable}}
  286. test trace-4.3 {unset traces mustn't be called during reads and writes} {
  287.     catch {unset x}
  288.     set info {}
  289.     trace add variable x unset traceScalar
  290.     set x 44
  291.     set x
  292.     set info
  293. } {}
  294. test trace-4.4 {trace unsets on array elements} {
  295.     catch {unset x}
  296.     set x(0) 18
  297.     set info {}
  298.     trace add variable x(1) unset traceArray
  299.     catch {unset x(1)}
  300.     set info
  301. } {x 1 unset 1 {can't read "x(1)": no such element in array}}
  302. test trace-4.5 {trace unsets on array elements} {
  303.     catch {unset x}
  304.     set x(1) 18
  305.     set info {}
  306.     trace add variable x(1) unset traceArray
  307.     unset x(1)
  308.     set info
  309. } {x 1 unset 1 {can't read "x(1)": no such element in array}}
  310. test trace-4.6 {trace unsets on array elements} {
  311.     catch {unset x}
  312.     set x(1) 18
  313.     set info {}
  314.     trace add variable x(1) unset traceArray
  315.     unset x
  316.     set info
  317. } {x 1 unset 1 {can't read "x(1)": no such variable}}
  318. test trace-4.7 {trace unsets on whole arrays} {
  319.     catch {unset x}
  320.     set x(1) 18
  321.     set info {}
  322.     trace add variable x unset traceProc
  323.     catch {unset x(0)}
  324.     set info
  325. } {}
  326. test trace-4.8 {trace unsets on whole arrays} {
  327.     catch {unset x}
  328.     set x(1) 18
  329.     set x(2) 144
  330.     set x(3) 14
  331.     set info {}
  332.     trace add variable x unset traceProc
  333.     unset x(1)
  334.     set info
  335. } {x 1 unset}
  336. test trace-4.9 {trace unsets on whole arrays} {
  337.     catch {unset x}
  338.     set x(1) 18
  339.     set x(2) 144
  340.     set x(3) 14
  341.     set info {}
  342.     trace add variable x unset traceProc
  343.     unset x
  344.     set info
  345. } {x {} unset}
  346. # Array tracing on variables
  347. test trace-5.1 {array traces fire on accesses via [array]} {
  348.     catch {unset x}
  349.     set x(b) 2
  350.     trace add variable x array traceArray2
  351.     set ::info {}
  352.     array set x {a 1}
  353.     set ::info
  354. } {x {} array}
  355. test trace-5.2 {array traces do not fire on normal accesses} {
  356.     catch {unset x}
  357.     set x(b) 2
  358.     trace add variable x array traceArray2
  359.     set ::info {}
  360.     set x(a) 1
  361.     set x(b) $x(a)
  362.     set ::info
  363. } {}
  364. test trace-5.3 {array traces do not outlive variable} {
  365.     catch {unset x}
  366.     trace add variable x array traceArray2
  367.     set ::info {}
  368.     set x(a) 1
  369.     unset x
  370.     array set x {a 1}
  371.     set ::info
  372. } {}
  373. test trace-5.4 {array traces properly listed in trace information} {
  374.     catch {unset x}
  375.     trace add variable x array traceArray2
  376.     set result [trace info variable x]
  377.     set result
  378. } [list [list array traceArray2]]
  379. test trace-5.5 {array traces properly listed in trace information} {
  380.     catch {unset x}
  381.     trace variable x a traceArray2
  382.     set result [trace vinfo x]
  383.     set result
  384. } [list [list a traceArray2]]
  385. test trace-5.6 {array traces don't fire on scalar variables} {
  386.     catch {unset x}
  387.     set x foo
  388.     trace add variable x array traceArray2
  389.     set ::info {}
  390.     catch {array set x {a 1}}
  391.     set ::info
  392. } {}
  393. test trace-5.7 {array traces fire for undefined variables} {
  394.     catch {unset x}
  395.     trace add variable x array traceArray2
  396.     set ::info {}
  397.     array set x {a 1}
  398.     set ::info
  399. } {x {} array}
  400. test trace-5.8 {array traces fire for undefined variables} {
  401.     catch {unset x}
  402.     trace add variable x array {set x(foo) 1 ;#}
  403.     set res "names: [array names x]"
  404. } {names: foo}
  405.     
  406. # Trace multiple trace types at once.
  407. test trace-6.1 {multiple ops traced at once} {
  408.     catch {unset x}
  409.     set info {}
  410.     trace add variable x {read write unset} traceProc
  411.     catch {set x}
  412.     set x 22
  413.     set x
  414.     set x 33
  415.     unset x
  416.     set info
  417. } {x {} read x {} write x {} read x {} write x {} unset}
  418. test trace-6.2 {multiple ops traced on array element} {
  419.     catch {unset x}
  420.     set info {}
  421.     trace add variable x(0) {read write unset} traceProc
  422.     catch {set x(0)}
  423.     set x(0) 22
  424.     set x(0)
  425.     set x(0) 33
  426.     unset x(0)
  427.     unset x
  428.     set info
  429. } {x 0 read x 0 write x 0 read x 0 write x 0 unset}
  430. test trace-6.3 {multiple ops traced on whole array} {
  431.     catch {unset x}
  432.     set info {}
  433.     trace add variable x {read write unset} traceProc
  434.     catch {set x(0)}
  435.     set x(0) 22
  436.     set x(0)
  437.     set x(0) 33
  438.     unset x(0)
  439.     unset x
  440.     set info
  441. } {x 0 write x 0 read x 0 write x 0 unset x {} unset}
  442. # Check order of invocation of traces
  443. test trace-7.1 {order of invocation of traces} {
  444.     catch {unset x}
  445.     set info {}
  446.     trace add variable x read "traceTag 1"
  447.     trace add variable x read "traceTag 2"
  448.     trace add variable x read "traceTag 3"
  449.     catch {set x}
  450.     set x 22
  451.     set x
  452.     set info
  453. } {3 2 1 3 2 1}
  454. test trace-7.2 {order of invocation of traces} {
  455.     catch {unset x}
  456.     set x(0) 44
  457.     set info {}
  458.     trace add variable x(0) read "traceTag 1"
  459.     trace add variable x(0) read "traceTag 2"
  460.     trace add variable x(0) read "traceTag 3"
  461.     set x(0)
  462.     set info
  463. } {3 2 1}
  464. test trace-7.3 {order of invocation of traces} {
  465.     catch {unset x}
  466.     set x(0) 44
  467.     set info {}
  468.     trace add variable x(0) read "traceTag 1"
  469.     trace add variable x read "traceTag A1"
  470.     trace add variable x(0) read "traceTag 2"
  471.     trace add variable x read "traceTag A2"
  472.     trace add variable x(0) read "traceTag 3"
  473.     trace add variable x read "traceTag A3"
  474.     set x(0)
  475.     set info
  476. } {A3 A2 A1 3 2 1}
  477. # Check effects of errors in trace procedures
  478. test trace-8.1 {error returns from traces} {
  479.     catch {unset x}
  480.     set x 123
  481.     set info {}
  482.     trace add variable x read "traceTag 1"
  483.     trace add variable x read traceError
  484.     list [catch {set x} msg] $msg $info
  485. } {1 {can't read "x": trace returned error} {}}
  486. test trace-8.2 {error returns from traces} {
  487.     catch {unset x}
  488.     set x 123
  489.     set info {}
  490.     trace add variable x write "traceTag 1"
  491.     trace add variable x write traceError
  492.     list [catch {set x 44} msg] $msg $info
  493. } {1 {can't set "x": trace returned error} {}}
  494. test trace-8.3 {error returns from traces} {
  495.     catch {unset x}
  496.     set x 123
  497.     set info {}
  498.     trace add variable x write traceError
  499.     list [catch {append x 44} msg] $msg $info
  500. } {1 {can't set "x": trace returned error} {}}
  501. test trace-8.4 {error returns from traces} {
  502.     catch {unset x}
  503.     set x 123
  504.     set info {}
  505.     trace add variable x unset "traceTag 1"
  506.     trace add variable x unset traceError
  507.     list [catch {unset x} msg] $msg $info
  508. } {0 {} 1}
  509. test trace-8.5 {error returns from traces} {
  510.     catch {unset x}
  511.     set x(0) 123
  512.     set info {}
  513.     trace add variable x(0) read "traceTag 1"
  514.     trace add variable x read "traceTag 2"
  515.     trace add variable x read traceError
  516.     trace add variable x read "traceTag 3"
  517.     list [catch {set x(0)} msg] $msg $info
  518. } {1 {can't read "x(0)": trace returned error} 3}
  519. test trace-8.6 {error returns from traces} {
  520.     catch {unset x}
  521.     set x 123
  522.     trace add variable x unset traceError
  523.     list [catch {unset x} msg] $msg
  524. } {0 {}}
  525. test trace-8.7 {error returns from traces} {
  526.     # This test just makes sure that the memory for the error message
  527.     # gets deallocated correctly when the trace is invoked again or
  528.     # when the trace is deleted.
  529.     catch {unset x}
  530.     set x 123
  531.     trace add variable x read traceError
  532.     catch {set x}
  533.     catch {set x}
  534.     trace remove variable x read traceError
  535. } {}
  536. test trace-8.8 {error returns from traces} {
  537.     # Yet more elaborate memory corruption testing that checks nothing
  538.     # bad happens when the trace deletes itself and installs something
  539.     # new.  Alas, there is no neat way to guarantee that this test will
  540.     # fail if there is a problem, but that's life and with the new code
  541.     # it should *never* fail.
  542.     #
  543.     # Adapted from Bug #219393 reported by Don Porter.
  544.     catch {rename ::foo {}}
  545.     proc foo {old args} {
  546. trace remove variable ::x write [list foo $old]
  547. trace add    variable ::x write [list foo $::x]
  548. error "foo"
  549.     }
  550.     catch {unset ::x ::y}
  551.     set x junk
  552.     trace add variable ::x write [list foo $x]
  553.     for {set y 0} {$y<100} {incr y} {
  554. catch {set x junk}
  555.     }
  556.     unset x
  557. } {}
  558. # Check to see that variables are expunged before trace
  559. # procedures are invoked, so trace procedure can even manipulate
  560. # a new copy of the variables.
  561. test trace-9.1 {be sure variable is unset before trace is called} {
  562.     catch {unset x}
  563.     set x 33
  564.     set info {}
  565.     trace add variable x unset {traceCheck {uplevel set x}}
  566.     unset x
  567.     set info
  568. } {1 {can't read "x": no such variable}}
  569. test trace-9.2 {be sure variable is unset before trace is called} {
  570.     catch {unset x}
  571.     set x 33
  572.     set info {}
  573.     trace add variable x unset {traceCheck {uplevel set x 22}}
  574.     unset x
  575.     concat $info [list [catch {set x} msg] $msg]
  576. } {0 22 0 22}
  577. test trace-9.3 {be sure traces are cleared before unset trace called} {
  578.     catch {unset x}
  579.     set x 33
  580.     set info {}
  581.     trace add variable x unset {traceCheck {uplevel trace info variable x}}
  582.     unset x
  583.     set info
  584. } {0 {}}
  585. test trace-9.4 {set new trace during unset trace} {
  586.     catch {unset x}
  587.     set x 33
  588.     set info {}
  589.     trace add variable x unset {traceCheck {global x; trace add variable x unset traceProc}}
  590.     unset x
  591.     concat $info [trace info variable x]
  592. } {0 {} {unset traceProc}}
  593. test trace-10.1 {make sure array elements are unset before traces are called} {
  594.     catch {unset x}
  595.     set x(0) 33
  596.     set info {}
  597.     trace add variable x(0) unset {traceCheck {uplevel set x(0)}}
  598.     unset x(0)
  599.     set info
  600. } {1 {can't read "x(0)": no such element in array}}
  601. test trace-10.2 {make sure array elements are unset before traces are called} {
  602.     catch {unset x}
  603.     set x(0) 33
  604.     set info {}
  605.     trace add variable x(0) unset {traceCheck {uplevel set x(0) zzz}}
  606.     unset x(0)
  607.     concat $info [list [catch {set x(0)} msg] $msg]
  608. } {0 zzz 0 zzz}
  609. test trace-10.3 {array elements are unset before traces are called} {
  610.     catch {unset x}
  611.     set x(0) 33
  612.     set info {}
  613.     trace add variable x(0) unset {traceCheck {global x; trace info variable x(0)}}
  614.     unset x(0)
  615.     set info
  616. } {0 {}}
  617. test trace-10.4 {set new array element trace during unset trace} {
  618.     catch {unset x}
  619.     set x(0) 33
  620.     set info {}
  621.     trace add variable x(0) unset {traceCheck {uplevel {trace add variable x(0) read {}}}}
  622.     catch {unset x(0)}
  623.     concat $info [trace info variable x(0)]
  624. } {0 {} {read {}}}
  625. test trace-11.1 {make sure arrays are unset before traces are called} {
  626.     catch {unset x}
  627.     set x(0) 33
  628.     set info {}
  629.     trace add variable x unset {traceCheck {uplevel set x(0)}}
  630.     unset x
  631.     set info
  632. } {1 {can't read "x(0)": no such variable}}
  633. test trace-11.2 {make sure arrays are unset before traces are called} {
  634.     catch {unset x}
  635.     set x(y) 33
  636.     set info {}
  637.     trace add variable x unset {traceCheck {uplevel set x(y) 22}}
  638.     unset x
  639.     concat $info [list [catch {set x(y)} msg] $msg]
  640. } {0 22 0 22}
  641. test trace-11.3 {make sure arrays are unset before traces are called} {
  642.     catch {unset x}
  643.     set x(y) 33
  644.     set info {}
  645.     trace add variable x unset {traceCheck {uplevel array exists x}}
  646.     unset x
  647.     set info
  648. } {0 0}
  649. test trace-11.4 {make sure arrays are unset before traces are called} {
  650.     catch {unset x}
  651.     set x(y) 33
  652.     set info {}
  653.     set cmd {traceCheck {uplevel {trace info variable x}}}
  654.     trace add variable x unset $cmd
  655.     unset x
  656.     set info
  657. } {0 {}}
  658. test trace-11.5 {set new array trace during unset trace} {
  659.     catch {unset x}
  660.     set x(y) 33
  661.     set info {}
  662.     trace add variable x unset {traceCheck {global x; trace add variable x read {}}}
  663.     unset x
  664.     concat $info [trace info variable x]
  665. } {0 {} {read {}}}
  666. test trace-11.6 {create scalar during array unset trace} {
  667.     catch {unset x}
  668.     set x(y) 33
  669.     set info {}
  670.     trace add variable x unset {traceCheck {global x; set x 44}}
  671.     unset x
  672.     concat $info [list [catch {set x} msg] $msg]
  673. } {0 44 0 44}
  674. # Check special conditions (e.g. errors) in Tcl_TraceVar2.
  675. test trace-12.1 {creating array when setting variable traces} {
  676.     catch {unset x}
  677.     set info {}
  678.     trace add variable x(0) write traceProc
  679.     list [catch {set x 22} msg] $msg
  680. } {1 {can't set "x": variable is array}}
  681. test trace-12.2 {creating array when setting variable traces} {
  682.     catch {unset x}
  683.     set info {}
  684.     trace add variable x(0) write traceProc
  685.     list [catch {set x(0)} msg] $msg
  686. } {1 {can't read "x(0)": no such element in array}}
  687. test trace-12.3 {creating array when setting variable traces} {
  688.     catch {unset x}
  689.     set info {}
  690.     trace add variable x(0) write traceProc
  691.     set x(0) 22
  692.     set info
  693. } {x 0 write}
  694. test trace-12.4 {creating variable when setting variable traces} {
  695.     catch {unset x}
  696.     set info {}
  697.     trace add variable x write traceProc
  698.     list [catch {set x} msg] $msg
  699. } {1 {can't read "x": no such variable}}
  700. test trace-12.5 {creating variable when setting variable traces} {
  701.     catch {unset x}
  702.     set info {}
  703.     trace add variable x write traceProc
  704.     set x 22
  705.     set info
  706. } {x {} write}
  707. test trace-12.6 {creating variable when setting variable traces} {
  708.     catch {unset x}
  709.     set info {}
  710.     trace add variable x write traceProc
  711.     set x(0) 22
  712.     set info
  713. } {x 0 write}
  714. test trace-12.7 {create array element during read trace} {
  715.     catch {unset x}
  716.     set x(2) zzz
  717.     trace add variable x read {traceCrtElement xyzzy}
  718.     list [catch {set x(3)} msg] $msg
  719. } {0 xyzzy}
  720. test trace-12.8 {errors when setting variable traces} {
  721.     catch {unset x}
  722.     set x 44
  723.     list [catch {trace add variable x(0) write traceProc} msg] $msg
  724. } {1 {can't trace "x(0)": variable isn't array}}
  725. # Check trace deletion
  726. test trace-13.1 {delete one trace from another} {
  727.     proc delTraces {args} {
  728. global x
  729. trace remove variable x read {traceTag 2}
  730. trace remove variable x read {traceTag 3}
  731. trace remove variable x read {traceTag 4}
  732.     }
  733.     catch {unset x}
  734.     set x 44
  735.     set info {}
  736.     trace add variable x read {traceTag 1}
  737.     trace add variable x read {traceTag 2}
  738.     trace add variable x read {traceTag 3}
  739.     trace add variable x read {traceTag 4}
  740.     trace add variable x read delTraces 
  741.     trace add variable x read {traceTag 5}
  742.     set x
  743.     set info
  744. } {5 1}
  745. test trace-13.2 {leak when unsetting traced variable} 
  746.     -constraints memory -body {
  747. set end [getbytes]
  748. proc f args {}
  749. for {set i 0} {$i < 5} {incr i} {
  750.     trace add variable bepa write f
  751.     set bepa a
  752.     unset bepa
  753.     set tmp $end
  754.     set end [getbytes]
  755. }
  756. expr {$end - $tmp}
  757.     } -cleanup {
  758. unset -nocomplain end i tmp
  759.     } -result 0
  760. test trace-13.3 {leak when removing traces} 
  761.     -constraints memory -body {
  762. set end [getbytes]
  763. proc f args {}
  764. for {set i 0} {$i < 5} {incr i} {
  765.     trace add variable bepa write f
  766.     set bepa a
  767.     trace remove variable bepa write f
  768.     set tmp $end
  769.     set end [getbytes]
  770. }
  771. expr {$end - $tmp}
  772.     } -cleanup {
  773. unset -nocomplain end i tmp
  774.     } -result 0
  775. test trace-13.4 {leaks in error returns from traces} 
  776.     -constraints memory -body {
  777. set end [getbytes]
  778. for {set i 0} {$i < 5} {incr i} {
  779.     set apa {a 1 b 2}
  780.     set bepa [lrange $apa 0 end]
  781.     trace add variable bepa write {error hej}
  782.     catch {set bepa a}
  783.     unset bepa
  784.     set tmp $end
  785.     set end [getbytes]
  786. }
  787. expr {$end - $tmp}
  788.     } -cleanup {
  789. unset -nocomplain end i tmp
  790.     } -result 0
  791. # Check operation and syntax of "trace" command.
  792. # Syntax for adding/removing variable and command traces is basically the
  793. # same:
  794. # trace add variable name opList command
  795. # trace remove variable name opList command
  796. #
  797. # The following loops just get all the common "wrong # args" tests done.
  798. set i 0
  799. set start "wrong # args:"
  800. foreach type {variable command} {
  801.     foreach op {add remove} {
  802. test trace-14.0.[incr i] "trace command, wrong # args errors" {
  803.     list [catch {trace $op $type} msg] $msg
  804. } [list 1 "$start should be "trace $op $type name opList command""]
  805. test trace-14.0.[incr i] "trace command wrong # args errors" {
  806.     list [catch {trace $op $type foo} msg] $msg
  807. } [list 1 "$start should be "trace $op $type name opList command""]
  808. test trace-14.0.[incr i] "trace command, wrong # args errors" {
  809.     list [catch {trace $op $type foo bar} msg] $msg
  810. } [list 1 "$start should be "trace $op $type name opList command""]
  811. test trace-14.0.[incr i] "trace command, wrong # args errors" {
  812.     list [catch {trace $op $type foo bar baz boo} msg] $msg
  813. } [list 1 "$start should be "trace $op $type name opList command""]
  814.     }
  815.     test trace-14.0.[incr i] "trace command, wrong # args errors" {
  816. list [catch {trace info $type foo bar} msg] $msg
  817.     } [list 1 "$start should be "trace info $type name""]
  818.     test trace-14.0.[incr i] "trace command, wrong # args errors" {
  819. list [catch {trace info $type} msg] $msg
  820.     } [list 1 "$start should be "trace info $type name""]
  821. }
  822. test trace-14.1 "trace command, wrong # args errors" {
  823.     list [catch {trace} msg] $msg
  824. } [list 1 "wrong # args: should be "trace option ?arg arg ...?""]
  825. test trace-14.2 "trace command, wrong # args errors" {
  826.     list [catch {trace add} msg] $msg
  827. } [list 1 "wrong # args: should be "trace add type ?arg arg ...?""]
  828. test trace-14.3 "trace command, wrong # args errors" {
  829.     list [catch {trace remove} msg] $msg
  830. } [list 1 "wrong # args: should be "trace remove type ?arg arg ...?""]
  831. test trace-14.4 "trace command, wrong # args errors" {
  832.     list [catch {trace info} msg] $msg
  833. } [list 1 "wrong # args: should be "trace info type ?arg arg ...?""]
  834. test trace-14.5 {trace command, invalid option} {
  835.     list [catch {trace gorp} msg] $msg
  836. } [list 1 "bad option "gorp": must be add, info, remove, variable, vdelete, or vinfo"]
  837. # Again, [trace ... command] and [trace ... variable] share syntax and
  838. # error message styles for their opList options; these loops test those 
  839. # error messages.
  840. set i 0
  841. set errs [list "array, read, unset, or write" "delete or rename" "enter, leave, enterstep, or leavestep"]
  842. set abbvs [list {a r u w} {d r} {}]
  843. proc x {} {}
  844. foreach type {variable command execution} err $errs abbvlist $abbvs {
  845.     foreach op {add remove} {
  846. test trace-14.6.[incr i] "trace $op $type errors" {
  847.     list [catch {trace $op $type x {y z w} a} msg] $msg
  848. } [list 1 "bad operation "y": must be $err"]
  849. foreach abbv $abbvlist {
  850.     test trace-14.6.[incr i] "trace $op $type rejects abbreviations" {
  851. list [catch {trace $op $type x $abbv a} msg] $msg
  852.     } [list 1 "bad operation "$abbv": must be $err"]
  853. }
  854. test trace-14.6.[incr i] "trace $op $type rejects null opList" {
  855.     list [catch {trace $op $type x {} a} msg] $msg
  856. } [list 1 "bad operation list "": must be one or more of $err"]
  857.     }
  858. }
  859. rename x {}
  860. test trace-14.7 {trace command, "trace variable" errors} {
  861.     list [catch {trace variable} msg] $msg
  862. } [list 1 "wrong # args: should be "trace variable name ops command""]
  863. test trace-14.8 {trace command, "trace variable" errors} {
  864.     list [catch {trace variable x} msg] $msg
  865. } [list 1 "wrong # args: should be "trace variable name ops command""]
  866. test trace-14.9 {trace command, "trace variable" errors} {
  867.     list [catch {trace variable x y} msg] $msg
  868. } [list 1 "wrong # args: should be "trace variable name ops command""]
  869. test trace-14.10 {trace command, "trace variable" errors} {
  870.     list [catch {trace variable x y z w} msg] $msg
  871. } [list 1 "wrong # args: should be "trace variable name ops command""]
  872. test trace-14.11 {trace command, "trace variable" errors} {
  873.     list [catch {trace variable x y z} msg] $msg
  874. } [list 1 "bad operations "y": should be one or more of rwua"]
  875. test trace-14.12 {trace command ("remove variable" option)} {
  876.     catch {unset x}
  877.     set info {}
  878.     trace add variable x write traceProc
  879.     trace remove variable x write traceProc
  880. } {}
  881. test trace-14.13 {trace command ("remove variable" option)} {
  882.     catch {unset x}
  883.     set info {}
  884.     trace add variable x write traceProc
  885.     trace remove variable x write traceProc
  886.     set x 12345
  887.     set info
  888. } {}
  889. test trace-14.14 {trace command ("remove variable" option)} {
  890.     catch {unset x}
  891.     set info {}
  892.     trace add variable x write {traceTag 1}
  893.     trace add variable x write traceProc
  894.     trace add variable x write {traceTag 2}
  895.     set x yy
  896.     trace remove variable x write traceProc
  897.     set x 12345
  898.     trace remove variable x write {traceTag 1}
  899.     set x foo
  900.     trace remove variable x write {traceTag 2}
  901.     set x gorp
  902.     set info
  903. } {2 x {} write 1 2 1 2}
  904. test trace-14.15 {trace command ("remove variable" option)} {
  905.     catch {unset x}
  906.     set info {}
  907.     trace add variable x write {traceTag 1}
  908.     trace remove variable x write non_existent
  909.     set x 12345
  910.     set info
  911. } {1}
  912. test trace-14.16 {trace command ("info variable" option)} {
  913.     catch {unset x}
  914.     trace add variable x write {traceTag 1}
  915.     trace add variable x write traceProc
  916.     trace add variable x write {traceTag 2}
  917.     trace info variable x
  918. } {{write {traceTag 2}} {write traceProc} {write {traceTag 1}}}
  919. test trace-14.17 {trace command ("info variable" option)} {
  920.     catch {unset x}
  921.     trace info variable x
  922. } {}
  923. test trace-14.18 {trace command ("info variable" option)} {
  924.     catch {unset x}
  925.     trace info variable x(0)
  926. } {}
  927. test trace-14.19 {trace command ("info variable" option)} {
  928.     catch {unset x}
  929.     set x 44
  930.     trace info variable x(0)
  931. } {}
  932. test trace-14.20 {trace command ("info variable" option)} {
  933.     catch {unset x}
  934.     set x 44
  935.     trace add variable x write {traceTag 1}
  936.     proc check {} {global x; trace info variable x}
  937.     check
  938. } {{write {traceTag 1}}}
  939. # Check fancy trace commands (long ones, weird arguments, etc.)
  940. test trace-15.1 {long trace command} {
  941.     catch {unset x}
  942.     set info {}
  943.     trace add variable x write {traceTag {This is a very very long argument.  It's 
  944. designed to test out the facilities of TraceVarProc for dealing 
  945. with such long arguments by malloc-ing space.  One possibility 
  946. is that space doesn't get freed properly.  If this happens, then 
  947. invoking this test over and over again will eventually leak memory.}}
  948.     set x 44
  949.     set info
  950. } {This is a very very long argument.  It's 
  951. designed to test out the facilities of TraceVarProc for dealing 
  952. with such long arguments by malloc-ing space.  One possibility 
  953. is that space doesn't get freed properly.  If this happens, then 
  954. invoking this test over and over again will eventually leak memory.}
  955. test trace-15.2 {long trace command result to ignore} {
  956.     proc longResult {args} {return "quite a bit of text, designed to
  957. generate a core leak if this command file is invoked over and over again
  958. and memory isn't being recycled correctly"}
  959.     catch {unset x}
  960.     trace add variable x write longResult
  961.     set x 44
  962.     set x 5
  963.     set x abcde
  964. } abcde
  965. test trace-15.3 {special list-handling in trace commands} {
  966.     catch {unset "x y z"}
  967.     set "x y z(an{)" 44
  968.     set info {}
  969.     trace add variable "x y z(an{)" write traceProc
  970.     set "x y z(an{)" 33
  971.     set info
  972. } "{x y z} a\n\{ write"
  973. # Check for proper handling of unsets during traces.
  974. proc traceUnset {unsetName args} {
  975.     global info
  976.     upvar $unsetName x
  977.     lappend info [catch {unset x} msg] $msg [catch {set x} msg] $msg
  978. }
  979. proc traceReset {unsetName resetName args} {
  980.     global info
  981.     upvar $unsetName x $resetName y
  982.     lappend info [catch {unset x} msg] $msg [catch {set y xyzzy} msg] $msg
  983. }
  984. proc traceReset2 {unsetName resetName args} {
  985.     global info
  986.     lappend info [catch {uplevel unset $unsetName} msg] $msg 
  987.     [catch {uplevel set $resetName xyzzy} msg] $msg
  988. }
  989. proc traceAppend {string name1 name2 op} {
  990.     global info
  991.     lappend info $string
  992. }
  993. test trace-16.1 {unsets during read traces} {
  994.     catch {unset y}
  995.     set y 1234
  996.     set info {}
  997.     trace add variable y read {traceUnset y}
  998.     trace add variable y unset {traceAppend unset}
  999.     lappend info [catch {set y} msg] $msg
  1000. } {unset 0 {} 1 {can't read "x": no such variable} 1 {can't read "y": no such variable}}
  1001. test trace-16.2 {unsets during read traces} {
  1002.     catch {unset y}
  1003.     set y(0) 1234
  1004.     set info {}
  1005.     trace add variable y(0) read {traceUnset y(0)}
  1006.     lappend info [catch {set y(0)} msg] $msg
  1007. } {0 {} 1 {can't read "x": no such variable} 1 {can't read "y(0)": no such element in array}}
  1008. test trace-16.3 {unsets during read traces} {
  1009.     catch {unset y}
  1010.     set y(0) 1234
  1011.     set info {}
  1012.     trace add variable y(0) read {traceUnset y}
  1013.     lappend info [catch {set y(0)} msg] $msg
  1014. } {0 {} 1 {can't read "x": no such variable} 1 {can't read "y(0)": no such variable}}
  1015. test trace-16.4 {unsets during read traces} {
  1016.     catch {unset y}
  1017.     set y 1234
  1018.     set info {}
  1019.     trace add variable y read {traceReset y y}
  1020.     lappend info [catch {set y} msg] $msg
  1021. } {0 {} 0 xyzzy 0 xyzzy}
  1022. test trace-16.5 {unsets during read traces} {
  1023.     catch {unset y}
  1024.     set y(0) 1234
  1025.     set info {}
  1026.     trace add variable y(0) read {traceReset y(0) y(0)}
  1027.     lappend info [catch {set y(0)} msg] $msg
  1028. } {0 {} 0 xyzzy 0 xyzzy}
  1029. test trace-16.6 {unsets during read traces} {
  1030.     catch {unset y}
  1031.     set y(0) 1234
  1032.     set info {}
  1033.     trace add variable y(0) read {traceReset y y(0)}
  1034.     lappend info [catch {set y(0)} msg] $msg [catch {set y(0)} msg] $msg
  1035. } {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}}
  1036. test trace-16.7 {unsets during read traces} {
  1037.     catch {unset y}
  1038.     set y(0) 1234
  1039.     set info {}
  1040.     trace add variable y(0) read {traceReset2 y y(0)}
  1041.     lappend info [catch {set y(0)} msg] $msg [catch {set y(0)} msg] $msg
  1042. } {0 {} 0 xyzzy 1 {can't read "y(0)": no such element in array} 0 xyzzy}
  1043. test trace-16.8 {unsets during write traces} {
  1044.     catch {unset y}
  1045.     set y 1234
  1046.     set info {}
  1047.     trace add variable y write {traceUnset y}
  1048.     trace add variable y unset {traceAppend unset}
  1049.     lappend info [catch {set y xxx} msg] $msg
  1050. } {unset 0 {} 1 {can't read "x": no such variable} 0 {}}
  1051. test trace-16.9 {unsets during write traces} {
  1052.     catch {unset y}
  1053.     set y(0) 1234
  1054.     set info {}
  1055.     trace add variable y(0) write {traceUnset y(0)}
  1056.     lappend info [catch {set y(0) xxx} msg] $msg
  1057. } {0 {} 1 {can't read "x": no such variable} 0 {}}
  1058. test trace-16.10 {unsets during write traces} {
  1059.     catch {unset y}
  1060.     set y(0) 1234
  1061.     set info {}
  1062.     trace add variable y(0) write {traceUnset y}
  1063.     lappend info [catch {set y(0) xxx} msg] $msg
  1064. } {0 {} 1 {can't read "x": no such variable} 0 {}}
  1065. test trace-16.11 {unsets during write traces} {
  1066.     catch {unset y}
  1067.     set y 1234
  1068.     set info {}
  1069.     trace add variable y write {traceReset y y}
  1070.     lappend info [catch {set y xxx} msg] $msg
  1071. } {0 {} 0 xyzzy 0 xyzzy}
  1072. test trace-16.12 {unsets during write traces} {
  1073.     catch {unset y}
  1074.     set y(0) 1234
  1075.     set info {}
  1076.     trace add variable y(0) write {traceReset y(0) y(0)}
  1077.     lappend info [catch {set y(0) xxx} msg] $msg
  1078. } {0 {} 0 xyzzy 0 xyzzy}
  1079. test trace-16.13 {unsets during write traces} {
  1080.     catch {unset y}
  1081.     set y(0) 1234
  1082.     set info {}
  1083.     trace add variable y(0) write {traceReset y y(0)}
  1084.     lappend info [catch {set y(0) xxx} msg] $msg [catch {set y(0)} msg] $msg
  1085. } {0 {} 1 {can't set "y": upvar refers to element in deleted array} 0 {} 1 {can't read "y(0)": no such variable}}
  1086. test trace-16.14 {unsets during write traces} {
  1087.     catch {unset y}
  1088.     set y(0) 1234
  1089.     set info {}
  1090.     trace add variable y(0) write {traceReset2 y y(0)}
  1091.     lappend info [catch {set y(0) xxx} msg] $msg [catch {set y(0)} msg] $msg
  1092. } {0 {} 0 xyzzy 0 {} 0 xyzzy}
  1093. test trace-16.15 {unsets during unset traces} {
  1094.     catch {unset y}
  1095.     set y 1234
  1096.     set info {}
  1097.     trace add variable y unset {traceUnset y}
  1098.     lappend info [catch {unset y} msg] $msg [catch {set y} msg] $msg
  1099. } {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}}
  1100. test trace-16.16 {unsets during unset traces} {
  1101.     catch {unset y}
  1102.     set y(0) 1234
  1103.     set info {}
  1104.     trace add variable y(0) unset {traceUnset y(0)}
  1105.     lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
  1106. } {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}}
  1107. test trace-16.17 {unsets during unset traces} {
  1108.     catch {unset y}
  1109.     set y(0) 1234
  1110.     set info {}
  1111.     trace add variable y(0) unset {traceUnset y}
  1112.     lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
  1113. } {0 {} 1 {can't read "x": no such variable} 0 {} 1 {can't read "y(0)": no such variable}}
  1114. test trace-16.18 {unsets during unset traces} {
  1115.     catch {unset y}
  1116.     set y 1234
  1117.     set info {}
  1118.     trace add variable y unset {traceReset2 y y}
  1119.     lappend info [catch {unset y} msg] $msg [catch {set y} msg] $msg
  1120. } {1 {can't unset "y": no such variable} 0 xyzzy 0 {} 0 xyzzy}
  1121. test trace-16.19 {unsets during unset traces} {
  1122.     catch {unset y}
  1123.     set y(0) 1234
  1124.     set info {}
  1125.     trace add variable y(0) unset {traceReset2 y(0) y(0)}
  1126.     lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
  1127. } {1 {can't unset "y(0)": no such element in array} 0 xyzzy 0 {} 0 xyzzy}
  1128. test trace-16.20 {unsets during unset traces} {
  1129.     catch {unset y}
  1130.     set y(0) 1234
  1131.     set info {}
  1132.     trace add variable y(0) unset {traceReset2 y y(0)}
  1133.     lappend info [catch {unset y(0)} msg] $msg [catch {set y(0)} msg] $msg
  1134. } {0 {} 0 xyzzy 0 {} 0 xyzzy}
  1135. test trace-16.21 {unsets cancelling traces} {
  1136.     catch {unset y}
  1137.     set y 1234
  1138.     set info {}
  1139.     trace add variable y read {traceAppend first}
  1140.     trace add variable y read {traceUnset y}
  1141.     trace add variable y read {traceAppend third}
  1142.     trace add variable y unset {traceAppend unset}
  1143.     lappend info [catch {set y} msg] $msg
  1144. } {third unset 0 {} 1 {can't read "x": no such variable} 1 {can't read "y": no such variable}}
  1145. test trace-16.22 {unsets cancelling traces} {
  1146.     catch {unset y}
  1147.     set y(0) 1234
  1148.     set info {}
  1149.     trace add variable y(0) read {traceAppend first}
  1150.     trace add variable y(0) read {traceUnset y}
  1151.     trace add variable y(0) read {traceAppend third}
  1152.     trace add variable y(0) unset {traceAppend unset}
  1153.     lappend info [catch {set y(0)} msg] $msg
  1154. } {third unset 0 {} 1 {can't read "x": no such variable} 1 {can't read "y(0)": no such variable}}
  1155. # Check various non-interference between traces and other things.
  1156. test trace-17.1 {trace doesn't prevent unset errors} {
  1157.     catch {unset x}
  1158.     set info {}
  1159.     trace add variable x unset {traceProc}
  1160.     list [catch {unset x} msg] $msg $info
  1161. } {1 {can't unset "x": no such variable} {x {} unset}}
  1162. test trace-17.2 {traced variables must survive procedure exits} {
  1163.     catch {unset x}
  1164.     proc p1 {} {global x; trace add variable x write traceProc}
  1165.     p1
  1166.     trace info variable x
  1167. } {{write traceProc}}
  1168. test trace-17.3 {traced variables must survive procedure exits} {
  1169.     catch {unset x}
  1170.     set info {}
  1171.     proc p1 {} {global x; trace add variable x write traceProc}
  1172.     p1
  1173.     set x 44
  1174.     set info
  1175. } {x {} write}
  1176. # Be sure that procedure frames are released before unset traces
  1177. # are invoked.
  1178. test trace-18.1 {unset traces on procedure returns} {
  1179.     proc p1 {x y} {set a 44; p2 14}
  1180.     proc p2 {z} {trace add variable z unset {traceCheck {lsort [uplevel {info vars}]}}}
  1181.     set info {}
  1182.     p1 foo bar
  1183.     set info
  1184. } {0 {a x y}}
  1185. test trace-18.2 {namespace delete / trace vdelete combo} {
  1186.     namespace eval ::foo {
  1187. variable x 123
  1188.     }
  1189.     proc p1 args {
  1190. trace vdelete ::foo::x u p1
  1191.     }
  1192.     trace variable ::foo::x u p1
  1193.     namespace delete ::foo
  1194.     info exists ::foo::x
  1195. } 0
  1196. test trace-18.3 {namespace delete / trace vdelete combo, Bug #1337229} {
  1197.     namespace eval ::ns {}
  1198.     trace add variable ::ns::var unset {unset ::ns::var ;#}
  1199.     namespace delete ::ns
  1200. } {}
  1201. test trace-18.4 {namespace delete / trace vdelete combo, Bug #1338280} {
  1202.     namespace eval ::ref {}
  1203.     set ::ref::var1 AAA
  1204.     trace add variable ::ref::var1 unset doTrace
  1205.     set ::ref::var2 BBB
  1206.     trace add variable ::ref::var2 {unset} doTrace
  1207.     proc doTrace {vtraced vidx op} {
  1208. global info
  1209. append info [catch {set ::$vtraced}][llength [info vars ::ref::*]]
  1210.     }
  1211.     set info {}
  1212.     namespace delete ::ref
  1213.     rename doTrace {}
  1214.     set info
  1215. } 1110
  1216. # Delete arrays when done, so they can be re-used as scalars
  1217. # elsewhere.
  1218. catch {unset x}
  1219. catch {unset y}
  1220. test trace-19.0.1 {trace add command (command existence)} {
  1221.     # Just in case!
  1222.     catch {rename nosuchname ""}
  1223.     list [catch {trace add command nosuchname rename traceCommand} msg] $msg
  1224. } {1 {unknown command "nosuchname"}}
  1225. test trace-19.0.2 {trace add command (command existence in ns)} {
  1226.     list [catch {trace add command nosuchns::nosuchname rename traceCommand} msg] $msg
  1227. } {1 {unknown command "nosuchns::nosuchname"}}
  1228. test trace-19.1 {trace add command (rename option)} {
  1229.     proc foo {} {}
  1230.     catch {rename bar {}}
  1231.     trace add command foo rename traceCommand
  1232.     rename foo bar
  1233.     set info
  1234. } {::foo ::bar rename}
  1235. test trace-19.2 {traces stick with renamed commands} {
  1236.     proc foo {} {}
  1237.     catch {rename bar {}}
  1238.     trace add command foo rename traceCommand
  1239.     rename foo bar
  1240.     rename bar foo
  1241.     set info
  1242. } {::bar ::foo rename}
  1243. test trace-19.2.1 {trace add command rename trace exists} {
  1244.     proc foo {} {}
  1245.     trace add command foo rename traceCommand
  1246.     trace info command foo
  1247. } {{rename traceCommand}}
  1248. test trace-19.3 {command rename traces don't fire on command deletion} {
  1249.     proc foo {} {}
  1250.     set info {}
  1251.     trace add command foo rename traceCommand
  1252.     rename foo {}
  1253.     set info
  1254. } {}
  1255. test trace-19.4 {trace add command rename doesn't trace recreated commands} {
  1256.     proc foo {} {}
  1257.     catch {rename bar {}}
  1258.     trace add command foo rename traceCommand
  1259.     proc foo {} {}
  1260.     rename foo bar
  1261.     set info
  1262. } {}
  1263. test trace-19.5 {trace add command deleted removes traces} {
  1264.     proc foo {} {}
  1265.     trace add command foo rename traceCommand
  1266.     proc foo {} {}
  1267.     trace info command foo
  1268. } {}
  1269. namespace eval tc {}
  1270. proc tc::tcfoo {} {}
  1271. test trace-19.6 {trace add command rename in namespace} {
  1272.     trace add command tc::tcfoo rename traceCommand
  1273.     rename tc::tcfoo tc::tcbar
  1274.     set info
  1275. } {::tc::tcfoo ::tc::tcbar rename}
  1276. test trace-19.7 {trace add command rename in namespace back again} {
  1277.     rename tc::tcbar tc::tcfoo
  1278.     set info
  1279. } {::tc::tcbar ::tc::tcfoo rename}
  1280. test trace-19.8 {trace add command rename in namespace to out of namespace} {
  1281.     rename tc::tcfoo tcbar
  1282.     set info
  1283. } {::tc::tcfoo ::tcbar rename}
  1284. test trace-19.9 {trace add command rename back into namespace} {
  1285.     rename tcbar tc::tcfoo
  1286.     set info
  1287. } {::tcbar ::tc::tcfoo rename}
  1288. test trace-19.10 {trace add command failed rename doesn't trigger trace} {
  1289.     set info {}
  1290.     proc foo {} {}
  1291.     proc bar {} {}
  1292.     trace add command foo {rename delete} traceCommand
  1293.     catch {rename foo bar}
  1294.     set info
  1295. } {}
  1296. catch {rename foo {}}
  1297. catch {rename bar {}}
  1298. test trace-19.11 {trace add command qualifies when renamed in namespace} {
  1299.     set info {}
  1300.     namespace eval tc {rename tcfoo tcbar}
  1301.     set info
  1302. } {::tc::tcfoo ::tc::tcbar rename}
  1303. # Make sure it exists again
  1304. proc foo {} {}
  1305. test trace-20.1 {trace add command (delete option)} {
  1306.     trace add command foo delete traceCommand
  1307.     rename foo ""
  1308.     set info
  1309. } {::foo {} delete}
  1310. test trace-20.2 {trace add command delete doesn't trace recreated commands} {
  1311.     set info {}
  1312.     proc foo {} {}
  1313.     rename foo ""
  1314.     set info
  1315. } {}
  1316. test trace-20.2.1 {trace add command delete trace info} {
  1317.     proc foo {} {}
  1318.     trace add command foo delete traceCommand
  1319.     trace info command foo
  1320. } {{delete traceCommand}}
  1321. test trace-20.3 {trace add command implicit delete} {
  1322.     proc foo {} {}
  1323.     trace add command foo delete traceCommand
  1324.     proc foo {} {}
  1325.     set info
  1326. } {::foo {} delete}
  1327. test trace-20.3.1 {trace add command delete trace info} {
  1328.     proc foo {} {}
  1329.     trace info command foo
  1330. } {}
  1331. test trace-20.4 {trace add command rename followed by delete} {
  1332.     set infotemp {}
  1333.     proc foo {} {}
  1334.     trace add command foo {rename delete} traceCommand
  1335.     rename foo bar
  1336.     lappend infotemp $info
  1337.     rename bar {}
  1338.     lappend infotemp $info
  1339.     set info $infotemp
  1340.     unset infotemp
  1341.     set info
  1342. } {{::foo ::bar rename} {::bar {} delete}}
  1343. catch {rename foo {}}
  1344. catch {rename bar {}}
  1345. test trace-20.5 {trace add command rename and delete} {
  1346.     set infotemp {}
  1347.     set info {}
  1348.     proc foo {} {}
  1349.     trace add command foo {rename delete} traceCommand
  1350.     rename foo bar
  1351.     lappend infotemp $info
  1352.     rename bar {}
  1353.     lappend infotemp $info
  1354.     set info $infotemp
  1355.     unset infotemp
  1356.     set info
  1357. } {{::foo ::bar rename} {::bar {} delete}}
  1358. test trace-20.6 {trace add command rename and delete in subinterp} {
  1359.     set tc [interp create]
  1360.     foreach p {traceCommand} {
  1361. $tc eval [list proc $p [info args $p] [info body $p]]
  1362.     }
  1363.     $tc eval [list set infotemp {}]
  1364.     $tc eval [list set info {}]
  1365.     $tc eval [list proc foo {} {}]
  1366.     $tc eval [list trace add command foo {rename delete} traceCommand]
  1367.     $tc eval [list rename foo bar]
  1368.     $tc eval {lappend infotemp $info}
  1369.     $tc eval [list rename bar {}]
  1370.     $tc eval {lappend infotemp $info}
  1371.     $tc eval {set info $infotemp}
  1372.     $tc eval [list unset infotemp]
  1373.     set info [$tc eval [list set info]]
  1374.     interp delete $tc
  1375.     set info
  1376. } {{::foo ::bar rename} {::bar {} delete}}
  1377. # I'd like it if this test could give 'foo {} d' as a result,
  1378. # but interp deletion means there is no interp to evaluate
  1379. # the trace in.
  1380. test trace-20.7 {trace add command delete in subinterp while being deleted} {
  1381.     set info {}
  1382.     set tc [interp create]
  1383.     interp alias $tc traceCommand {} traceCommand
  1384.     $tc eval [list proc foo {} {}]
  1385.     $tc eval [list trace add command foo {rename delete} traceCommand]
  1386.     interp delete $tc
  1387.     set info
  1388. } {}
  1389. proc traceDelete {cmd old new op} {
  1390.     eval trace remove command $cmd [lindex [trace info command $cmd] 0]
  1391.     global info
  1392.     set info [list $old $new $op]
  1393. }
  1394. proc traceCmdrename {cmd old new op} {
  1395.     rename $old someothername
  1396. }
  1397. proc traceCmddelete {cmd old new op} {
  1398.     rename $old ""
  1399. }
  1400. test trace-20.8 {trace delete while trace is active} {
  1401.     set info {}
  1402.     proc foo {} {}
  1403.     catch {rename bar {}}
  1404.     trace add command foo {rename delete} [list traceDelete foo]
  1405.     rename foo bar
  1406.     list [set info] [trace info command bar]
  1407. } {{::foo ::bar rename} {}}
  1408. test trace-20.9 {rename trace deletes command} {
  1409.     set info {}
  1410.     proc foo {} {}
  1411.     catch {rename bar {}}
  1412.     catch {rename someothername {}}
  1413.     trace add command foo rename [list traceCmddelete foo]
  1414.     rename foo bar
  1415.     list [info commands foo] [info commands bar] [info commands someothername]
  1416. } {{} {} {}}
  1417. test trace-20.10 {rename trace renames command} {
  1418.     set info {}
  1419.     proc foo {} {}
  1420.     catch {rename bar {}}
  1421.     catch {rename someothername {}}
  1422.     trace add command foo rename [list traceCmdrename foo]
  1423.     rename foo bar
  1424.     set info [list [info commands foo] [info commands bar] [info commands someothername]]
  1425.     rename someothername {}
  1426.     set info
  1427. } {{} {} someothername}
  1428. test trace-20.11 {delete trace deletes command} {
  1429.     set info {}
  1430.     proc foo {} {}
  1431.     catch {rename bar {}}
  1432.     catch {rename someothername {}}
  1433.     trace add command foo delete [list traceCmddelete foo]
  1434.     rename foo {}
  1435.     list [info commands foo] [info commands bar] [info commands someothername]
  1436. } {{} {} {}}
  1437. test trace-20.12 {delete trace renames command} {
  1438.     set info {}
  1439.     proc foo {} {}
  1440.     catch {rename bar {}}
  1441.     catch {rename someothername {}}
  1442.     trace add command foo delete [list traceCmdrename foo]
  1443.     rename foo bar
  1444.     rename bar {}
  1445.     # None of these should exist.
  1446.     list [info commands foo] [info commands bar] [info commands someothername]
  1447. } {{} {} {}}
  1448. test trace-20.13 {rename trace discards result [Bug 1355342]} {
  1449.     proc foo {} {}
  1450.     trace add command foo rename {set w Aha!;#}
  1451.     list [rename foo bar] [rename bar {}]
  1452. } {{} {}}
  1453. test trace-20.14 {rename trace discards error result [Bug 1355342]} {
  1454.     proc foo {} {}
  1455.     trace add command foo rename {error}
  1456.     list [rename foo bar] [rename bar {}]
  1457. } {{} {}}
  1458. test trace-20.15 {delete trace discards result [Bug 1355342]} {
  1459.     proc foo {} {}
  1460.     trace add command foo delete {set w Aha!;#}
  1461.     rename foo {}
  1462. } {}
  1463. test trace-20.16 {delete trace discards error result [Bug 1355342]} {
  1464.     proc foo {} {}
  1465.     trace add command foo delete {error}
  1466.     rename foo {}
  1467. } {}
  1468. proc foo {b} { set a $b }
  1469. # Delete arrays when done, so they can be re-used as scalars
  1470. # elsewhere.
  1471. catch {unset x}
  1472. catch {unset y}
  1473. # Delete procedures when done, so we don't clash with other tests
  1474. # (e.g. foobar will clash with 'unknown' tests).
  1475. catch {rename foobar {}}
  1476. catch {rename foo {}}
  1477. catch {rename bar {}}
  1478. proc foo {a} {
  1479.     set b $a
  1480. }
  1481. proc traceExecute {args} {
  1482.     global info
  1483.     lappend info $args
  1484. }
  1485. test trace-21.1 {trace execution: enter} {
  1486.     set info {}
  1487.     trace add execution foo enter [list traceExecute foo]
  1488.     foo 1
  1489.     trace remove execution foo enter [list traceExecute foo]
  1490.     set info
  1491. } {{foo {foo 1} enter}}
  1492. test trace-21.2 {trace exeuction: leave} {
  1493.     set info {}
  1494.     trace add execution foo leave [list traceExecute foo]
  1495.     foo 2
  1496.     trace remove execution foo leave [list traceExecute foo]
  1497.     set info
  1498. } {{foo {foo 2} 0 2 leave}}
  1499. test trace-21.3 {trace exeuction: enter, leave} {
  1500.     set info {}
  1501.     trace add execution foo {enter leave} [list traceExecute foo]
  1502.     foo 3
  1503.     trace remove execution foo {enter leave} [list traceExecute foo]
  1504.     set info
  1505. } {{foo {foo 3} enter} {foo {foo 3} 0 3 leave}}
  1506. test trace-21.4 {trace execution: enter, leave, enterstep} {
  1507.     set info {}
  1508.     trace add execution foo {enter leave enterstep} [list traceExecute foo]
  1509.     foo 3
  1510.     trace remove execution foo {enter leave enterstep} [list traceExecute foo]
  1511.     set info
  1512. } {{foo {foo 3} enter} {foo {set b 3} enterstep} {foo {foo 3} 0 3 leave}}
  1513. test trace-21.5 {trace execution: enter, leave, enterstep, leavestep} {
  1514.     set info {}
  1515.     trace add execution foo {enter leave enterstep leavestep} [list traceExecute foo]
  1516.     foo 3
  1517.     trace remove execution foo {enter leave enterstep leavestep} [list traceExecute foo]
  1518.     set info
  1519. } {{foo {foo 3} enter} {foo {set b 3} enterstep} {foo {set b 3} 0 3 leavestep} {foo {foo 3} 0 3 leave}}
  1520. test trace-21.6 {trace execution: enterstep, leavestep} {
  1521.     set info {}
  1522.     trace add execution foo {enterstep leavestep} [list traceExecute foo]
  1523.     foo 3
  1524.     trace remove execution foo {enterstep leavestep} [list traceExecute foo]
  1525.     set info
  1526. } {{foo {set b 3} enterstep} {foo {set b 3} 0 3 leavestep}}
  1527. test trace-21.7 {trace execution: enterstep} {
  1528.     set info {}
  1529.     trace add execution foo {enterstep} [list traceExecute foo]
  1530.     foo 3
  1531.     trace remove execution foo {enterstep} [list traceExecute foo]
  1532.     set info
  1533. } {{foo {set b 3} enterstep}}
  1534. test trace-21.8 {trace execution: leavestep} {
  1535.     set info {}
  1536.     trace add execution foo {leavestep} [list traceExecute foo]
  1537.     foo 3
  1538.     trace remove execution foo {leavestep} [list traceExecute foo]
  1539.     set info
  1540. } {{foo {set b 3} 0 3 leavestep}}
  1541. test trace-21.9 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
  1542.     trace add execution foo enter soom
  1543.     proc ::soom args {lappend ::info SUCCESS [info level]}
  1544.     set ::info {}
  1545.     namespace eval test_ns_1 {
  1546.         proc soom args {lappend ::info FAIL [info level]}
  1547.         # [testevalobjv 1 ...] ought to produce the same
  1548. # results as [uplevel #0 ...].
  1549.         testevalobjv 1 foo x
  1550. uplevel #0 foo x
  1551.     }
  1552.     namespace delete test_ns_1
  1553.     trace remove execution foo enter soom
  1554.     set ::info
  1555. } {SUCCESS 1 SUCCESS 1}
  1556.     
  1557. test trace-21.10 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
  1558.     trace add execution foo leave soom
  1559.     proc ::soom args {lappend ::info SUCCESS [info level]}
  1560.     set ::info {}
  1561.     namespace eval test_ns_1 {
  1562.         proc soom args {lappend ::info FAIL [info level]}
  1563.         # [testevalobjv 1 ...] ought to produce the same
  1564. # results as [uplevel #0 ...].
  1565.         testevalobjv 1 foo x
  1566. uplevel #0 foo x
  1567.     }
  1568.     namespace delete test_ns_1
  1569.     trace remove execution foo leave soom
  1570.     set ::info
  1571. } {SUCCESS 1 SUCCESS 1}
  1572. test trace-21.11 {trace execution and alias} -setup {
  1573.     set res {}
  1574.     proc ::x {} {return ::}
  1575.     namespace eval a {}
  1576.     proc ::a::x {} {return ::a}
  1577.     interp alias {} y {} x
  1578. } -body {
  1579.     lappend res [namespace eval ::a y]
  1580.     trace add execution ::x enter {
  1581.       rename ::x {}
  1582. proc ::x {} {return ::}
  1583.     #}
  1584.     lappend res [namespace eval ::a y]
  1585. } -cleanup {
  1586.     namespace delete a
  1587.     rename ::x {}
  1588. } -result {:: ::}
  1589. proc factorial {n} {
  1590.     if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }
  1591.     return 1
  1592. }
  1593. test trace-22.1 {recursive(1) trace execution: enter} {
  1594.     set info {}
  1595.     trace add execution factorial {enter} [list traceExecute factorial]
  1596.     factorial 1
  1597.     trace remove execution factorial {enter} [list traceExecute factorial]
  1598.     set info
  1599. } {{factorial {factorial 1} enter}}
  1600. test trace-22.2 {recursive(2) trace execution: enter} {
  1601.     set info {}
  1602.     trace add execution factorial {enter} [list traceExecute factorial]
  1603.     factorial 2
  1604.     trace remove execution factorial {enter} [list traceExecute factorial]
  1605.     set info
  1606. } {{factorial {factorial 2} enter} {factorial {factorial 1} enter}}
  1607. test trace-22.3 {recursive(3) trace execution: enter} {
  1608.     set info {}
  1609.     trace add execution factorial {enter} [list traceExecute factorial]
  1610.     factorial 3
  1611.     trace remove execution factorial {enter} [list traceExecute factorial]
  1612.     set info
  1613. } {{factorial {factorial 3} enter} {factorial {factorial 2} enter} {factorial {factorial 1} enter}}
  1614. test trace-23.1 {recursive(1) trace execution: enter, leave, enterstep, leavestep} {
  1615.     set info {}
  1616.     trace add execution factorial {enter leave enterstep leavestep} [list traceExecute]
  1617.     factorial 1
  1618.     trace remove execution factorial {enter leave enterstep leavestep} [list traceExecute]
  1619.     join $info "n"
  1620. } {{factorial 1} enter
  1621. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} enterstep
  1622. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 0 {} leavestep
  1623. {return 1} enterstep
  1624. {return 1} 2 1 leavestep
  1625. {factorial 1} 0 1 leave}
  1626. test trace-23.2 {recursive(2) trace execution: enter, leave, enterstep, leavestep} {
  1627.     set info {}
  1628.     trace add execution factorial {enter leave enterstep leavestep} [list traceExecute]
  1629.     factorial 2
  1630.     trace remove execution factorial {enter leave enterstep leavestep} [list traceExecute]
  1631.     join $info "n"
  1632. } {{factorial 2} enter
  1633. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} enterstep
  1634. {expr {$n * [factorial [expr {$n -1 }]]}} enterstep
  1635. {expr {$n -1 }} enterstep
  1636. {expr {$n -1 }} 0 1 leavestep
  1637. {factorial 1} enterstep
  1638. {factorial 1} enter
  1639. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} enterstep
  1640. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 0 {} leavestep
  1641. {return 1} enterstep
  1642. {return 1} 2 1 leavestep
  1643. {factorial 1} 0 1 leave
  1644. {factorial 1} 0 1 leavestep
  1645. {expr {$n * [factorial [expr {$n -1 }]]}} 0 2 leavestep
  1646. {return 2} enterstep
  1647. {return 2} 2 2 leavestep
  1648. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 2 2 leavestep
  1649. {factorial 2} 0 2 leave}
  1650. test trace-23.3 {recursive(3) trace execution: enter, leave, enterstep, leavestep} {
  1651.     set info {}
  1652.     trace add execution factorial {enter leave enterstep leavestep} [list traceExecute]
  1653.     factorial 3
  1654.     trace remove execution factorial {enter leave enterstep leavestep} [list traceExecute]
  1655.     join $info "n"
  1656. } {{factorial 3} enter
  1657. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} enterstep
  1658. {expr {$n * [factorial [expr {$n -1 }]]}} enterstep
  1659. {expr {$n -1 }} enterstep
  1660. {expr {$n -1 }} 0 2 leavestep
  1661. {factorial 2} enterstep
  1662. {factorial 2} enter
  1663. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} enterstep
  1664. {expr {$n * [factorial [expr {$n -1 }]]}} enterstep
  1665. {expr {$n -1 }} enterstep
  1666. {expr {$n -1 }} 0 1 leavestep
  1667. {factorial 1} enterstep
  1668. {factorial 1} enter
  1669. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} enterstep
  1670. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 0 {} leavestep
  1671. {return 1} enterstep
  1672. {return 1} 2 1 leavestep
  1673. {factorial 1} 0 1 leave
  1674. {factorial 1} 0 1 leavestep
  1675. {expr {$n * [factorial [expr {$n -1 }]]}} 0 2 leavestep
  1676. {return 2} enterstep
  1677. {return 2} 2 2 leavestep
  1678. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 2 2 leavestep
  1679. {factorial 2} 0 2 leave
  1680. {factorial 2} 0 2 leavestep
  1681. {expr {$n * [factorial [expr {$n -1 }]]}} 0 6 leavestep
  1682. {return 6} enterstep
  1683. {return 6} 2 6 leavestep
  1684. {if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 2 6 leavestep
  1685. {factorial 3} 0 6 leave}
  1686. proc traceDelete {cmd args} {
  1687.     eval trace remove execution $cmd [lindex [trace info execution $cmd] 0]
  1688.     global info
  1689.     set info $args
  1690. }
  1691. test trace-24.1 {delete trace during enter trace} {
  1692.     set info {}
  1693.     trace add execution foo enter [list traceDelete foo]
  1694.     foo 1
  1695.     list $info [catch {trace info execution foo} res] $res
  1696. } {{{foo 1} enter} 0 {}}
  1697. test trace-24.2 {delete trace during leave trace} {
  1698.     set info {}
  1699.     trace add execution foo leave [list traceDelete foo]
  1700.     foo 1
  1701.     list $info [catch {trace info execution foo} res] $res
  1702. } {{{foo 1} 0 1 leave} 0 {}}
  1703. test trace-24.3 {delete trace during enter-leave trace} {
  1704.     set info {}
  1705.     trace add execution foo {enter leave} [list traceDelete foo]
  1706.     foo 1
  1707.     list $info [catch {trace info execution foo} res] $res
  1708. } {{{foo 1} enter} 0 {}}
  1709. test trace-24.4 {delete trace during all exec traces} {
  1710.     set info {}
  1711.     trace add execution foo {enter leave enterstep leavestep} [list traceDelete foo]
  1712.     foo 1
  1713.     list $info [catch {trace info execution foo} res] $res
  1714. } {{{foo 1} enter} 0 {}}
  1715. test trace-24.5 {delete trace during all exec traces except enter} {
  1716.     set info {}
  1717.     trace add execution foo {leave enterstep leavestep} [list traceDelete foo]
  1718.     foo 1
  1719.     list $info [catch {trace info execution foo} res] $res
  1720. } {{{set b 1} enterstep} 0 {}}
  1721. proc traceDelete {cmd args} {
  1722.     rename $cmd {}
  1723.     global info
  1724.     set info $args
  1725. }
  1726. proc foo {a} {
  1727.     set b $a
  1728. }
  1729. test trace-25.1 {delete command during enter trace} {
  1730.     set info {}
  1731.     trace add execution foo enter [list traceDelete foo]
  1732.     catch {foo 1} err
  1733.     list $err $info [catch {trace info execution foo} res] $res
  1734. } {{invalid command name "foo"} {{foo 1} enter} 1 {unknown command "foo"}}
  1735. proc foo {a} {
  1736.     set b $a
  1737. }
  1738. test trace-25.2 {delete command during leave trace} {
  1739.     set info {}
  1740.     trace add execution foo leave [list traceDelete foo]
  1741.     foo 1
  1742.     list $info [catch {trace info execution foo} res] $res
  1743. } {{{foo 1} 0 1 leave} 1 {unknown command "foo"}}
  1744. proc foo {a} {
  1745.     set b $a
  1746. }
  1747. test trace-25.3 {delete command during enter then leave trace} {
  1748.     set info {}
  1749.     trace add execution foo enter [list traceDelete foo]
  1750.     trace add execution foo leave [list traceDelete foo]
  1751.     catch {foo 1} err
  1752.     list $err $info [catch {trace info execution foo} res] $res
  1753. } {{invalid command name "foo"} {{foo 1} enter} 1 {unknown command "foo"}}
  1754. proc foo {a} {
  1755.     set b $a
  1756. }
  1757. proc traceExecute2 {args} {
  1758.     global info
  1759.     lappend info $args
  1760. }
  1761. # This shows the peculiar consequences of having two traces
  1762. # at the same time: as well as tracing the procedure you want
  1763. test trace-25.4 {order dependencies of two enter traces} {
  1764.     set info {}
  1765.     trace add execution foo enter [list traceExecute traceExecute]
  1766.     trace add execution foo enter [list traceExecute2 traceExecute2]
  1767.     catch {foo 1} err
  1768.     trace remove execution foo enter [list traceExecute traceExecute]
  1769.     trace remove execution foo enter [list traceExecute2 traceExecute2]
  1770.     join [list $err [join $info n] [trace info execution foo]] "n"
  1771. } {1
  1772. traceExecute2 {foo 1} enter
  1773. traceExecute {foo 1} enter
  1774. }
  1775. test trace-25.5 {order dependencies of two step traces} {
  1776.     set info {}
  1777.     trace add execution foo enterstep [list traceExecute traceExecute]
  1778.     trace add execution foo enterstep [list traceExecute2 traceExecute2]
  1779.     catch {foo 1} err
  1780.     trace remove execution foo enterstep [list traceExecute traceExecute]
  1781.     trace remove execution foo enterstep [list traceExecute2 traceExecute2]
  1782.     join [list $err [join $info n] [trace info execution foo]] "n"
  1783. } {1
  1784. traceExecute2 {set b 1} enterstep
  1785. traceExecute {set b 1} enterstep
  1786. }
  1787. # We don't want the result string (5th argument), or the results
  1788. # will get unmanageable.
  1789. proc tracePostExecute {args} {
  1790.     global info
  1791.     lappend info [concat [lrange $args 0 2] [lindex $args 4]]
  1792. }
  1793. proc tracePostExecute2 {args} {
  1794.     global info
  1795.     lappend info [concat [lrange $args 0 2] [lindex $args 4]]
  1796. }
  1797. test trace-25.6 {order dependencies of two leave traces} {
  1798.     set info {}
  1799.     trace add execution foo leave [list tracePostExecute tracePostExecute]
  1800.     trace add execution foo leave [list tracePostExecute2 tracePostExecute2]
  1801.     catch {foo 1} err
  1802.     trace remove execution foo leave [list tracePostExecute tracePostExecute]
  1803.     trace remove execution foo leave [list tracePostExecute2 tracePostExecute2]
  1804.     join [list $err [join $info n] [trace info execution foo]] "n"
  1805. } {1
  1806. tracePostExecute {foo 1} 0 leave
  1807. tracePostExecute2 {foo 1} 0 leave
  1808. }
  1809. test trace-25.7 {order dependencies of two leavestep traces} {
  1810.     set info {}
  1811.     trace add execution foo leavestep [list tracePostExecute tracePostExecute]
  1812.     trace add execution foo leavestep [list tracePostExecute2 tracePostExecute2]
  1813.     catch {foo 1} err
  1814.     trace remove execution foo leavestep [list tracePostExecute tracePostExecute]
  1815.     trace remove execution foo leavestep [list tracePostExecute2 tracePostExecute2]
  1816.     join [list $err [join $info n] [trace info execution foo]] "n"
  1817. } {1
  1818. tracePostExecute {set b 1} 0 leavestep
  1819. tracePostExecute2 {set b 1} 0 leavestep
  1820. }
  1821. proc foo {a} {
  1822.     set b $a
  1823. }
  1824. proc traceDelete {cmd args} {
  1825.     rename $cmd {}
  1826.     global info
  1827.     set info $args
  1828. }
  1829. test trace-25.8 {delete command during enter leave and enter/leave-step traces} {
  1830.     set info {}
  1831.     trace add execution foo enter [list traceDelete foo]
  1832.     trace add execution foo leave [list traceDelete foo]
  1833.     trace add execution foo enterstep [list traceDelete foo]
  1834.     trace add execution foo leavestep [list traceDelete foo]
  1835.     catch {foo 1} err
  1836.     list $err $info [catch {trace info execution foo} res] $res
  1837. } {{invalid command name "foo"} {{foo 1} enter} 1 {unknown command "foo"}}
  1838. proc foo {a} {
  1839.     set b $a
  1840. }
  1841. test trace-25.9 {delete command during enter leave and leavestep traces} {
  1842.     set info {}
  1843.     trace add execution foo enter [list traceDelete foo]
  1844.     trace add execution foo leave [list traceDelete foo]
  1845.     trace add execution foo leavestep [list traceDelete foo]
  1846.     catch {foo 1} err
  1847.     list $err $info [catch {trace info execution foo} res] $res
  1848. } {{invalid command name "foo"} {{foo 1} enter} 1 {unknown command "foo"}}
  1849. proc foo {a} {
  1850.     set b $a
  1851. }
  1852. test trace-25.10 {delete command during leave and leavestep traces} {
  1853.     set info {}
  1854.     trace add execution foo leave [list traceDelete foo]
  1855.     trace add execution foo leavestep [list traceDelete foo]
  1856.     catch {foo 1} err
  1857.     list $err $info [catch {trace info execution foo} res] $res
  1858. } {1 {{set b 1} 0 1 leavestep} 1 {unknown command "foo"}}
  1859. proc foo {a} {
  1860.     set b $a
  1861. }
  1862. test trace-25.11 {delete command during enter and enterstep traces} {
  1863.     set info {}
  1864.     trace add execution foo enter [list traceDelete foo]
  1865.     trace add execution foo enterstep [list traceDelete foo]
  1866.     catch {foo 1} err
  1867.     list $err $info [catch {trace info execution foo} res] $res
  1868. } {{invalid command name "foo"} {{foo 1} enter} 1 {unknown command "foo"}}
  1869. test trace-26.1 {trace targetCmd when invoked through an alias} {
  1870.     proc foo {args} {
  1871. set b $args
  1872.     }
  1873.     set info {}
  1874.     trace add execution foo enter [list traceExecute foo]
  1875.     interp alias {} bar {} foo 1
  1876.     bar 2
  1877.     trace remove execution foo enter [list traceExecute foo]
  1878.     set info
  1879. } {{foo {foo 1 2} enter}}
  1880. test trace-26.2 {trace targetCmd when invoked through an alias} {
  1881.     proc foo {args} {
  1882. set b $args
  1883.     }
  1884.     set info {}
  1885.     trace add execution foo enter [list traceExecute foo]
  1886.     interp create child
  1887.     interp alias child bar {} foo 1
  1888.     child eval bar 2
  1889.     interp delete child
  1890.     trace remove execution foo enter [list traceExecute foo]
  1891.     set info
  1892. } {{foo {foo 1 2} enter}}
  1893. test trace-27.1 {memory leak in rename trace (604609)} {
  1894.     catch {rename bar {}}
  1895.     proc foo {} {error foo}
  1896.     trace add command foo rename {rename foo "" ;#}
  1897.     rename foo bar
  1898.     info commands foo
  1899. } {}
  1900. test trace-27.2 {command trace remove nonsense} {
  1901.     list [catch {trace remove command thisdoesntexist 
  1902.       {delete rename} bar} res] $res
  1903. } {1 {unknown command "thisdoesntexist"}}
  1904. test trace-27.3 {command trace info nonsense} {
  1905.     list [catch {trace info command thisdoesntexist} res] $res
  1906. } {1 {unknown command "thisdoesntexist"}}
  1907. test trace-28.1 {enterstep and leavestep traces with update idletasks (615043)} {
  1908.     catch {rename foo {}}
  1909.     proc foo {} {
  1910.         set a 1
  1911.         update idletasks
  1912.         set b 1
  1913.     }
  1914.     set info {}
  1915.     trace add execution foo {enter enterstep leavestep leave} 
  1916.         [list traceExecute foo]
  1917.     update
  1918.     after idle {set a "idle"}
  1919.     foo
  1920.     trace remove execution foo {enter enterstep leavestep leave} 
  1921.         [list traceExecute foo]
  1922.     rename foo {}
  1923.     catch {unset a}
  1924.     join $info "n"
  1925. } {foo foo enter
  1926. foo {set a 1} enterstep
  1927. foo {set a 1} 0 1 leavestep
  1928. foo {update idletasks} enterstep
  1929. foo {set a idle} enterstep
  1930. foo {set a idle} 0 idle leavestep
  1931. foo {update idletasks} 0 {} leavestep
  1932. foo {set b 1} enterstep
  1933. foo {set b 1} 0 1 leavestep
  1934. foo foo 0 1 leave}
  1935. test trace-28.2 {exec traces with 'error'} {
  1936.     set info {}
  1937.     set res {}
  1938.     
  1939.     proc foo {} {
  1940. if {[catch {bar}]} {
  1941.     return "error"
  1942. } else {
  1943.     return "ok"
  1944. }
  1945.     }
  1946.     proc bar {} { error "msg" }
  1947.     lappend res [foo]
  1948.     trace add execution foo {enter enterstep leave leavestep} 
  1949.       [list traceExecute foo]
  1950.     # With the trace active
  1951.     lappend res [foo]
  1952.     trace remove execution foo {enter enterstep leave leavestep} 
  1953.       [list traceExecute foo]
  1954.     
  1955.     list $res [join $info n]
  1956. } {{error error} {foo foo enter
  1957. foo {if {[catch {bar}]} {
  1958.     return "error"
  1959. } else {
  1960.     return "ok"
  1961. }} enterstep
  1962. foo {catch bar} enterstep
  1963. foo bar enterstep
  1964. foo {error msg} enterstep
  1965. foo {error msg} 1 msg leavestep
  1966. foo bar 1 msg leavestep
  1967. foo {catch bar} 0 1 leavestep
  1968. foo {return error} enterstep
  1969. foo {return error} 2 error leavestep
  1970. foo {if {[catch {bar}]} {
  1971.     return "error"
  1972. } else {
  1973.     return "ok"
  1974. }} 2 error leavestep
  1975. foo foo 0 error leave}}
  1976. test trace-28.3 {exec traces with 'return -code error'} {
  1977.     set info {}
  1978.     set res {}
  1979.     
  1980.     proc foo {} {
  1981. if {[catch {bar}]} {
  1982.     return "error"
  1983. } else {
  1984.     return "ok"
  1985. }
  1986.     }
  1987.     proc bar {} { return -code error "msg" }
  1988.     lappend res [foo]
  1989.     trace add execution foo {enter enterstep leave leavestep} 
  1990.       [list traceExecute foo]
  1991.     # With the trace active
  1992.     lappend res [foo]
  1993.     trace remove execution foo {enter enterstep leave leavestep} 
  1994.       [list traceExecute foo]
  1995.     
  1996.     list $res [join $info n]
  1997. } {{error error} {foo foo enter
  1998. foo {if {[catch {bar}]} {
  1999.     return "error"
  2000. } else {
  2001.     return "ok"
  2002. }} enterstep
  2003. foo {catch bar} enterstep
  2004. foo bar enterstep
  2005. foo {return -code error msg} enterstep
  2006. foo {return -code error msg} 2 msg leavestep
  2007. foo bar 1 msg leavestep
  2008. foo {catch bar} 0 1 leavestep
  2009. foo {return error} enterstep
  2010. foo {return error} 2 error leavestep
  2011. foo {if {[catch {bar}]} {
  2012.     return "error"
  2013. } else {
  2014.     return "ok"
  2015. }} 2 error leavestep
  2016. foo foo 0 error leave}}
  2017. test trace-28.4 {exec traces in slave with 'return -code error'} {
  2018.     interp create slave
  2019.     interp alias slave traceExecute {} traceExecute
  2020.     set info {}
  2021.     set res [interp eval slave {
  2022. set info {}
  2023. set res {}
  2024. proc foo {} {
  2025.     if {[catch {bar}]} {
  2026. return "error"
  2027.     } else {
  2028. return "ok"
  2029.     }
  2030. }
  2031. proc bar {} { return -code error "msg" }
  2032. lappend res [foo]
  2033. trace add execution foo {enter enterstep leave leavestep} 
  2034.   [list traceExecute foo]
  2035. # With the trace active
  2036. lappend res [foo]
  2037. trace remove execution foo {enter enterstep leave leavestep} 
  2038.   [list traceExecute foo]
  2039. list $res
  2040.     }]
  2041.     interp delete slave
  2042.     lappend res [join $info n]
  2043. } {{error error} {foo foo enter
  2044. foo {if {[catch {bar}]} {
  2045. return "error"
  2046.     } else {
  2047. return "ok"
  2048.     }} enterstep
  2049. foo {catch bar} enterstep
  2050. foo bar enterstep
  2051. foo {return -code error msg} enterstep
  2052. foo {return -code error msg} 2 msg leavestep
  2053. foo bar 1 msg leavestep
  2054. foo {catch bar} 0 1 leavestep
  2055. foo {return error} enterstep
  2056. foo {return error} 2 error leavestep
  2057. foo {if {[catch {bar}]} {
  2058. return "error"
  2059.     } else {
  2060. return "ok"
  2061.     }} 2 error leavestep
  2062. foo foo 0 error leave}}
  2063. test trace-28.5 {exec traces} {
  2064.     set info {}
  2065.     proc foo {args} { set a 1 }
  2066.     trace add execution foo {enter enterstep leave leavestep} 
  2067.       [list traceExecute foo]
  2068.     after idle [list foo test-28.4]
  2069.     update
  2070.     # Complicated way of removing traces
  2071.     set ti [lindex [eval [list trace info execution ::foo]] 0]
  2072.     if {[llength $ti]} {
  2073. eval [concat [list trace remove execution foo] $ti]
  2074.     }
  2075.     join $info n
  2076. } {foo {foo test-28.4} enter
  2077. foo {set a 1} enterstep
  2078. foo {set a 1} 0 1 leavestep
  2079. foo {foo test-28.4} 0 1 leave}
  2080. test trace-28.6 {exec traces firing order} {
  2081.     set info {}
  2082.     proc enterStep {cmd op} {lappend ::info "enter $cmd/$op"}
  2083.     proc leaveStep {cmd code result op} {lappend ::info "leave $cmd/$code/$result/$op"}
  2084.     proc foo x {
  2085. set b x=$x
  2086. incr x
  2087.     }
  2088.     trace add execution foo enterstep enterStep
  2089.     trace add execution foo leavestep leaveStep
  2090.     foo 42
  2091.     rename foo {}
  2092.     join $info n
  2093. } {enter set b x=42/enterstep
  2094. leave set b x=42/0/x=42/leavestep
  2095. enter incr x/enterstep
  2096. leave incr x/0/43/leavestep}
  2097. test trace-28.7 {exec trace information} {
  2098.     set info {}
  2099.     proc foo x { incr x }
  2100.     proc bar {args} {}
  2101.     trace add execution foo {enter leave enterstep leavestep} bar
  2102.     set info [trace info execution foo]
  2103.     trace remove execution foo {enter leave enterstep leavestep} bar
  2104. } {}
  2105. test trace-28.8 {exec trace remove nonsense} {
  2106.     list [catch {trace remove execution thisdoesntexist 
  2107.       {enter leave enterstep leavestep} bar} res] $res
  2108. } {1 {unknown command "thisdoesntexist"}}
  2109. test trace-28.9 {exec trace info nonsense} {
  2110.     list [catch {trace info execution thisdoesntexist} res] $res
  2111. } {1 {unknown command "thisdoesntexist"}}
  2112. test trace-28.10 {exec trace info nonsense} {
  2113.     list [catch {trace remove execution} res] $res
  2114. } {1 {wrong # args: should be "trace remove execution name opList command"}}
  2115. # Missing test number to keep in sync with the 8.5 branch
  2116. # (want to backport those tests?)
  2117. test trace-31.1 {command and execution traces shared struct} {
  2118.     # Tcl Bug 807243
  2119.     proc foo {} {}
  2120.     trace add command foo delete foo
  2121.     trace add execution foo enter foo
  2122.     set result [trace info command foo]
  2123.     trace remove command foo delete foo
  2124.     trace remove execution foo enter foo
  2125.     rename foo {}
  2126.     set result
  2127. } [list [list delete foo]]
  2128. test trace-31.2 {command and execution traces shared struct} {
  2129.     # Tcl Bug 807243
  2130.     proc foo {} {}
  2131.     trace add command foo delete foo
  2132.     trace add execution foo enter foo
  2133.     set result [trace info execution foo]
  2134.     trace remove command foo delete foo
  2135.     trace remove execution foo enter foo
  2136.     rename foo {}
  2137.     set result
  2138. } [list [list enter foo]]
  2139. test trace-32.1 {
  2140.     TraceCommandInfo refcount decr in TraceCommandProc w/o loss of reference
  2141. } {
  2142.     # Tcl Bug 811483
  2143.     proc foo {} {}
  2144.     trace add command foo delete foo
  2145.     trace add execution foo enter foo
  2146.     set result [trace info command foo]
  2147.     rename foo {}
  2148.     set result
  2149. } [list [list delete foo]]
  2150. test trace-33.1 {variable match with remove variable} {
  2151.     unset -nocomplain x
  2152.     trace variable x w foo
  2153.     trace remove variable x write foo
  2154.     llength [trace info variable x]
  2155. } 0
  2156. test trace-34.1 {Bug 1201035} {
  2157.     set ::x [list]
  2158.     proc foo {} {lappend ::x foo}
  2159.     proc bar args {
  2160. lappend ::x $args
  2161. trace remove execution foo leavestep bar
  2162. trace remove execution foo enterstep bar
  2163. trace add execution foo leavestep bar
  2164. trace add execution foo enterstep bar
  2165. lappend ::x done
  2166.     }
  2167.     trace add execution foo leavestep bar
  2168.     trace add execution foo enterstep bar
  2169.     foo
  2170.     set ::x
  2171. } {{{lappend ::x foo} enterstep} done foo}
  2172. test trace-34.2 {Bug 1224585} {
  2173.     proc foo {} {}
  2174.     proc bar args {trace remove execution foo leave soom}
  2175.     trace add execution foo leave bar
  2176.     trace add execution foo leave soom
  2177.     foo
  2178. } {}
  2179. test trace-34.3 {Bug 1224585} {
  2180.     proc foo {} {set x {}}
  2181.     proc bar args {trace remove execution foo enterstep soom}
  2182.     trace add execution foo enterstep soom
  2183.     trace add execution foo enterstep bar
  2184.     foo
  2185. } {}
  2186. # We test here for the half-documented and currently valid interplay between
  2187. # delete traces and namespace deletion.
  2188. test trace-34.4 {Bug 1047286} {
  2189.     variable x notrace
  2190.     proc callback {old - -} {
  2191.         variable x "$old exists: [namespace which -command $old]"
  2192.     }
  2193.     namespace eval ::foo {proc bar {} {}}
  2194.     trace add command ::foo::bar delete [namespace code callback]
  2195.     namespace delete ::foo
  2196.     set x
  2197. } {::foo::bar exists: ::foo::bar}
  2198. test trace-34.5 {Bug 1047286} {
  2199.     variable x notrace
  2200.     proc callback {old - -} {
  2201.         variable x "$old exists: [namespace which -command $old]"
  2202.     }
  2203.     namespace eval ::foo {proc bar {} {}}
  2204.     trace add command ::foo::bar delete [namespace code callback]
  2205.     namespace eval ::foo namespace delete ::foo
  2206.     set x
  2207. } {::foo::bar exists: }
  2208. test trace-34.6 {Bug 1458266} -setup {
  2209.     proc dummy {} {}
  2210.     proc stepTraceHandler {cmdString args} {
  2211. variable log 
  2212. append log "[expr {[info level] - 1}]: [lindex [split $cmdString] 0]n"
  2213. dummy
  2214. isTracedInside_2
  2215.     }
  2216.     proc cmdTraceHandler {cmdString args} {
  2217. # silent
  2218.     }
  2219.     proc isTracedInside_1 {} {
  2220. isTracedInside_2
  2221.     }
  2222.     proc isTracedInside_2 {} {
  2223. set x 2
  2224.     }
  2225. } -body {
  2226.     variable log {}
  2227.     trace add execution isTracedInside_1 enterstep stepTraceHandler
  2228.     trace add execution isTracedInside_2 enterstep stepTraceHandler
  2229.     isTracedInside_1
  2230.     variable first $log
  2231.     set log {}
  2232.     trace add execution dummy enter cmdTraceHandler
  2233.     isTracedInside_1
  2234.     variable second $log
  2235.     expr {($first eq $second) ? "ok" : "n$firstnandnn$secondndiffer"}
  2236. } -cleanup {
  2237.     unset -nocomplain log first second
  2238.     rename dummy {}
  2239.     rename stepTraceHandler {}
  2240.     rename cmdTraceHandler {}
  2241.     rename isTracedInside_1 {}
  2242.     rename isTracedInside_2 {}
  2243. } -result ok
  2244. # Delete procedures when done, so we don't clash with other tests
  2245. # (e.g. foobar will clash with 'unknown' tests).
  2246. catch {rename foobar {}}
  2247. catch {rename foo {}}
  2248. catch {rename bar {}}
  2249. # Unset the varaible when done
  2250. catch {unset info}
  2251. # cleanup
  2252. ::tcltest::cleanupTests
  2253. return