sl@0
|
1 |
# This file contains tests for the tclBasic.c source file. Tests appear in
|
sl@0
|
2 |
# the same order as the C code that they test. The set of tests is
|
sl@0
|
3 |
# currently incomplete since it currently includes only new tests for
|
sl@0
|
4 |
# code changed for the addition of Tcl namespaces. Other variable-
|
sl@0
|
5 |
# related tests appear in several other test files including
|
sl@0
|
6 |
# assocd.test, cmdInfo.test, eval.test, expr.test, interp.test,
|
sl@0
|
7 |
# and trace.test.
|
sl@0
|
8 |
#
|
sl@0
|
9 |
# Sourcing this file into Tcl runs the tests and generates output for
|
sl@0
|
10 |
# errors. No output means no errors were found.
|
sl@0
|
11 |
#
|
sl@0
|
12 |
# Copyright (c) 1997 Sun Microsystems, Inc.
|
sl@0
|
13 |
# Copyright (c) 1998-1999 by Scriptics Corporation.
|
sl@0
|
14 |
#
|
sl@0
|
15 |
# See the file "license.terms" for information on usage and redistribution
|
sl@0
|
16 |
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
sl@0
|
17 |
#
|
sl@0
|
18 |
# RCS: @(#) $Id: basic.test,v 1.25.2.7 2005/03/18 16:33:43 dgp Exp $
|
sl@0
|
19 |
#
|
sl@0
|
20 |
|
sl@0
|
21 |
package require tcltest 2
|
sl@0
|
22 |
namespace import -force ::tcltest::*
|
sl@0
|
23 |
|
sl@0
|
24 |
testConstraint testcmdtoken [llength [info commands testcmdtoken]]
|
sl@0
|
25 |
testConstraint testcmdtrace [llength [info commands testcmdtrace]]
|
sl@0
|
26 |
testConstraint testcreatecommand [llength [info commands testcreatecommand]]
|
sl@0
|
27 |
testConstraint testevalex [llength [info commands testevalex]]
|
sl@0
|
28 |
testConstraint exec [llength [info commands exec]]
|
sl@0
|
29 |
|
sl@0
|
30 |
# This variable needs to be changed when the major or minor version number for
|
sl@0
|
31 |
# Tcl changes.
|
sl@0
|
32 |
set tclvers 8.4
|
sl@0
|
33 |
|
sl@0
|
34 |
catch {namespace delete test_ns_basic}
|
sl@0
|
35 |
catch {interp delete test_interp}
|
sl@0
|
36 |
catch {rename p ""}
|
sl@0
|
37 |
catch {rename q ""}
|
sl@0
|
38 |
catch {rename cmd ""}
|
sl@0
|
39 |
catch {unset x}
|
sl@0
|
40 |
|
sl@0
|
41 |
test basic-1.1 {Tcl_CreateInterp, creates interp's global namespace} {
|
sl@0
|
42 |
catch {interp delete test_interp}
|
sl@0
|
43 |
interp create test_interp
|
sl@0
|
44 |
interp eval test_interp {
|
sl@0
|
45 |
namespace eval test_ns_basic {
|
sl@0
|
46 |
proc p {} {
|
sl@0
|
47 |
return [namespace current]
|
sl@0
|
48 |
}
|
sl@0
|
49 |
}
|
sl@0
|
50 |
}
|
sl@0
|
51 |
list [interp eval test_interp {test_ns_basic::p}] \
|
sl@0
|
52 |
[interp delete test_interp]
|
sl@0
|
53 |
} {::test_ns_basic {}}
|
sl@0
|
54 |
|
sl@0
|
55 |
test basic-2.1 {TclHideUnsafeCommands} {emptyTest} {
|
sl@0
|
56 |
} {}
|
sl@0
|
57 |
|
sl@0
|
58 |
test basic-3.1 {Tcl_CallWhenDeleted: see dcall.test} {emptyTest} {
|
sl@0
|
59 |
} {}
|
sl@0
|
60 |
|
sl@0
|
61 |
test basic-4.1 {Tcl_DontCallWhenDeleted: see dcall.test} {emptyTest} {
|
sl@0
|
62 |
} {}
|
sl@0
|
63 |
|
sl@0
|
64 |
test basic-5.1 {Tcl_SetAssocData: see assoc.test} {emptyTest} {
|
sl@0
|
65 |
} {}
|
sl@0
|
66 |
|
sl@0
|
67 |
test basic-6.1 {Tcl_DeleteAssocData: see assoc.test} {emptyTest} {
|
sl@0
|
68 |
} {}
|
sl@0
|
69 |
|
sl@0
|
70 |
test basic-7.1 {Tcl_GetAssocData: see assoc.test} {emptyTest} {
|
sl@0
|
71 |
} {}
|
sl@0
|
72 |
|
sl@0
|
73 |
test basic-8.1 {Tcl_InterpDeleted} {emptyTest} {
|
sl@0
|
74 |
} {}
|
sl@0
|
75 |
|
sl@0
|
76 |
test basic-9.1 {Tcl_DeleteInterp: see interp.test} {emptyTest} {
|
sl@0
|
77 |
} {}
|
sl@0
|
78 |
|
sl@0
|
79 |
test basic-10.1 {DeleteInterpProc, destroys interp's global namespace} {
|
sl@0
|
80 |
catch {interp delete test_interp}
|
sl@0
|
81 |
interp create test_interp
|
sl@0
|
82 |
interp eval test_interp {
|
sl@0
|
83 |
namespace eval test_ns_basic {
|
sl@0
|
84 |
namespace export p
|
sl@0
|
85 |
proc p {} {
|
sl@0
|
86 |
return [namespace current]
|
sl@0
|
87 |
}
|
sl@0
|
88 |
}
|
sl@0
|
89 |
namespace eval test_ns_2 {
|
sl@0
|
90 |
namespace import ::test_ns_basic::p
|
sl@0
|
91 |
variable v 27
|
sl@0
|
92 |
proc q {} {
|
sl@0
|
93 |
variable v
|
sl@0
|
94 |
return "[p] $v"
|
sl@0
|
95 |
}
|
sl@0
|
96 |
}
|
sl@0
|
97 |
}
|
sl@0
|
98 |
list [interp eval test_interp {test_ns_2::q}] \
|
sl@0
|
99 |
[interp eval test_interp {namespace delete ::}] \
|
sl@0
|
100 |
[catch {interp eval test_interp {set a 123}} msg] $msg \
|
sl@0
|
101 |
[interp delete test_interp]
|
sl@0
|
102 |
} {{::test_ns_basic 27} {} 1 {invalid command name "set"} {}}
|
sl@0
|
103 |
|
sl@0
|
104 |
test basic-11.1 {HiddenCmdsDeleteProc, invalidate cached refs to deleted hidden cmd} {
|
sl@0
|
105 |
catch {interp delete test_interp}
|
sl@0
|
106 |
interp create test_interp
|
sl@0
|
107 |
interp eval test_interp {
|
sl@0
|
108 |
proc p {} {
|
sl@0
|
109 |
return 27
|
sl@0
|
110 |
}
|
sl@0
|
111 |
}
|
sl@0
|
112 |
interp alias {} localP test_interp p
|
sl@0
|
113 |
list [interp eval test_interp {p}] \
|
sl@0
|
114 |
[localP] \
|
sl@0
|
115 |
[test_interp hide p] \
|
sl@0
|
116 |
[catch {localP} msg] $msg \
|
sl@0
|
117 |
[interp delete test_interp] \
|
sl@0
|
118 |
[catch {localP} msg] $msg
|
sl@0
|
119 |
} {27 27 {} 1 {invalid command name "p"} {} 1 {invalid command name "localP"}}
|
sl@0
|
120 |
|
sl@0
|
121 |
# NB: More tests about hide/expose are found in interp.test
|
sl@0
|
122 |
|
sl@0
|
123 |
test basic-12.1 {Tcl_HideCommand, names of hidden cmds can't have namespace qualifiers} {
|
sl@0
|
124 |
catch {interp delete test_interp}
|
sl@0
|
125 |
interp create test_interp
|
sl@0
|
126 |
interp eval test_interp {
|
sl@0
|
127 |
namespace eval test_ns_basic {
|
sl@0
|
128 |
proc p {} {
|
sl@0
|
129 |
return [namespace current]
|
sl@0
|
130 |
}
|
sl@0
|
131 |
}
|
sl@0
|
132 |
}
|
sl@0
|
133 |
list [catch {test_interp hide test_ns_basic::p x} msg] $msg \
|
sl@0
|
134 |
[catch {test_interp hide x test_ns_basic::p} msg1] $msg1 \
|
sl@0
|
135 |
[interp delete test_interp]
|
sl@0
|
136 |
} {1 {can only hide global namespace commands (use rename then hide)} 1 {cannot use namespace qualifiers in hidden command token (rename)} {}}
|
sl@0
|
137 |
|
sl@0
|
138 |
test basic-12.2 {Tcl_HideCommand, a hidden cmd remembers its containing namespace} {
|
sl@0
|
139 |
catch {namespace delete test_ns_basic}
|
sl@0
|
140 |
catch {rename cmd ""}
|
sl@0
|
141 |
proc cmd {} { ;# note that this is global
|
sl@0
|
142 |
return [namespace current]
|
sl@0
|
143 |
}
|
sl@0
|
144 |
namespace eval test_ns_basic {
|
sl@0
|
145 |
proc hideCmd {} {
|
sl@0
|
146 |
interp hide {} cmd
|
sl@0
|
147 |
}
|
sl@0
|
148 |
proc exposeCmd {} {
|
sl@0
|
149 |
interp expose {} cmd
|
sl@0
|
150 |
}
|
sl@0
|
151 |
proc callCmd {} {
|
sl@0
|
152 |
cmd
|
sl@0
|
153 |
}
|
sl@0
|
154 |
}
|
sl@0
|
155 |
list [test_ns_basic::callCmd] \
|
sl@0
|
156 |
[test_ns_basic::hideCmd] \
|
sl@0
|
157 |
[catch {cmd} msg] $msg \
|
sl@0
|
158 |
[test_ns_basic::exposeCmd] \
|
sl@0
|
159 |
[test_ns_basic::callCmd] \
|
sl@0
|
160 |
[namespace delete test_ns_basic]
|
sl@0
|
161 |
} {:: {} 1 {invalid command name "cmd"} {} :: {}}
|
sl@0
|
162 |
|
sl@0
|
163 |
test basic-13.1 {Tcl_ExposeCommand, a command stays in the global namespace and can not go to another namespace} {
|
sl@0
|
164 |
catch {namespace delete test_ns_basic}
|
sl@0
|
165 |
catch {rename cmd ""}
|
sl@0
|
166 |
proc cmd {} { ;# note that this is global
|
sl@0
|
167 |
return [namespace current]
|
sl@0
|
168 |
}
|
sl@0
|
169 |
namespace eval test_ns_basic {
|
sl@0
|
170 |
proc hideCmd {} {
|
sl@0
|
171 |
interp hide {} cmd
|
sl@0
|
172 |
}
|
sl@0
|
173 |
proc exposeCmdFailing {} {
|
sl@0
|
174 |
interp expose {} cmd ::test_ns_basic::newCmd
|
sl@0
|
175 |
}
|
sl@0
|
176 |
proc exposeCmdWorkAround {} {
|
sl@0
|
177 |
interp expose {} cmd;
|
sl@0
|
178 |
rename cmd ::test_ns_basic::newCmd;
|
sl@0
|
179 |
}
|
sl@0
|
180 |
proc callCmd {} {
|
sl@0
|
181 |
cmd
|
sl@0
|
182 |
}
|
sl@0
|
183 |
}
|
sl@0
|
184 |
list [test_ns_basic::callCmd] \
|
sl@0
|
185 |
[test_ns_basic::hideCmd] \
|
sl@0
|
186 |
[catch {test_ns_basic::exposeCmdFailing} msg] $msg \
|
sl@0
|
187 |
[test_ns_basic::exposeCmdWorkAround] \
|
sl@0
|
188 |
[test_ns_basic::newCmd] \
|
sl@0
|
189 |
[namespace delete test_ns_basic]
|
sl@0
|
190 |
} {:: {} 1 {can not expose to a namespace (use expose to toplevel, then rename)} {} ::test_ns_basic {}}
|
sl@0
|
191 |
test basic-13.2 {Tcl_ExposeCommand, invalidate cached refs to cmd now being exposed} {
|
sl@0
|
192 |
catch {rename p ""}
|
sl@0
|
193 |
catch {rename cmd ""}
|
sl@0
|
194 |
proc p {} {
|
sl@0
|
195 |
cmd
|
sl@0
|
196 |
}
|
sl@0
|
197 |
proc cmd {} {
|
sl@0
|
198 |
return 42
|
sl@0
|
199 |
}
|
sl@0
|
200 |
list [p] \
|
sl@0
|
201 |
[interp hide {} cmd] \
|
sl@0
|
202 |
[proc cmd {} {return Hello}] \
|
sl@0
|
203 |
[cmd] \
|
sl@0
|
204 |
[rename cmd ""] \
|
sl@0
|
205 |
[interp expose {} cmd] \
|
sl@0
|
206 |
[p]
|
sl@0
|
207 |
} {42 {} {} Hello {} {} 42}
|
sl@0
|
208 |
|
sl@0
|
209 |
test basic-14.1 {Tcl_CreateCommand, new cmd goes into a namespace specified in its name, if any} {testcreatecommand} {
|
sl@0
|
210 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
211 |
list [testcreatecommand create] \
|
sl@0
|
212 |
[test_ns_basic::createdcommand] \
|
sl@0
|
213 |
[testcreatecommand delete]
|
sl@0
|
214 |
} {{} {CreatedCommandProc in ::test_ns_basic} {}}
|
sl@0
|
215 |
test basic-14.2 {Tcl_CreateCommand, namespace code ignore single ":"s in middle or end of names} {testcreatecommand} {
|
sl@0
|
216 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
217 |
catch {rename value:at: ""}
|
sl@0
|
218 |
list [testcreatecommand create2] \
|
sl@0
|
219 |
[value:at:] \
|
sl@0
|
220 |
[testcreatecommand delete2]
|
sl@0
|
221 |
} {{} {CreatedCommandProc2 in ::} {}}
|
sl@0
|
222 |
|
sl@0
|
223 |
test basic-15.1 {Tcl_CreateObjCommand, new cmd goes into a namespace specified in its name, if any} {
|
sl@0
|
224 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
225 |
namespace eval test_ns_basic {}
|
sl@0
|
226 |
proc test_ns_basic::cmd {} { ;# proc requires that ns already exist
|
sl@0
|
227 |
return [namespace current]
|
sl@0
|
228 |
}
|
sl@0
|
229 |
list [test_ns_basic::cmd] \
|
sl@0
|
230 |
[namespace delete test_ns_basic]
|
sl@0
|
231 |
} {::test_ns_basic {}}
|
sl@0
|
232 |
|
sl@0
|
233 |
test basic-16.1 {TclInvokeStringCommand} {emptyTest} {
|
sl@0
|
234 |
} {}
|
sl@0
|
235 |
|
sl@0
|
236 |
test basic-17.1 {TclInvokeObjCommand} {emptyTest} {
|
sl@0
|
237 |
} {}
|
sl@0
|
238 |
|
sl@0
|
239 |
test basic-18.1 {TclRenameCommand, name of existing cmd can have namespace qualifiers} {
|
sl@0
|
240 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
241 |
catch {rename cmd ""}
|
sl@0
|
242 |
namespace eval test_ns_basic {
|
sl@0
|
243 |
proc p {} {
|
sl@0
|
244 |
return "p in [namespace current]"
|
sl@0
|
245 |
}
|
sl@0
|
246 |
}
|
sl@0
|
247 |
list [test_ns_basic::p] \
|
sl@0
|
248 |
[rename test_ns_basic::p test_ns_basic::q] \
|
sl@0
|
249 |
[test_ns_basic::q]
|
sl@0
|
250 |
} {{p in ::test_ns_basic} {} {p in ::test_ns_basic}}
|
sl@0
|
251 |
test basic-18.2 {TclRenameCommand, existing cmd must be found} {
|
sl@0
|
252 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
253 |
list [catch {rename test_ns_basic::p test_ns_basic::q} msg] $msg
|
sl@0
|
254 |
} {1 {can't rename "test_ns_basic::p": command doesn't exist}}
|
sl@0
|
255 |
test basic-18.3 {TclRenameCommand, delete cmd if new name is empty} {
|
sl@0
|
256 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
257 |
namespace eval test_ns_basic {
|
sl@0
|
258 |
proc p {} {
|
sl@0
|
259 |
return "p in [namespace current]"
|
sl@0
|
260 |
}
|
sl@0
|
261 |
}
|
sl@0
|
262 |
list [info commands test_ns_basic::*] \
|
sl@0
|
263 |
[rename test_ns_basic::p ""] \
|
sl@0
|
264 |
[info commands test_ns_basic::*]
|
sl@0
|
265 |
} {::test_ns_basic::p {} {}}
|
sl@0
|
266 |
test basic-18.4 {TclRenameCommand, bad new name} {
|
sl@0
|
267 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
268 |
namespace eval test_ns_basic {
|
sl@0
|
269 |
proc p {} {
|
sl@0
|
270 |
return "p in [namespace current]"
|
sl@0
|
271 |
}
|
sl@0
|
272 |
}
|
sl@0
|
273 |
rename test_ns_basic::p :::george::martha
|
sl@0
|
274 |
} {}
|
sl@0
|
275 |
test basic-18.5 {TclRenameCommand, new name must not already exist} {
|
sl@0
|
276 |
namespace eval test_ns_basic {
|
sl@0
|
277 |
proc q {} {
|
sl@0
|
278 |
return 42
|
sl@0
|
279 |
}
|
sl@0
|
280 |
}
|
sl@0
|
281 |
list [catch {rename test_ns_basic::q :::george::martha} msg] $msg
|
sl@0
|
282 |
} {1 {can't rename to ":::george::martha": command already exists}}
|
sl@0
|
283 |
test basic-18.6 {TclRenameCommand, check for command shadowing by newly renamed cmd} {
|
sl@0
|
284 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
285 |
catch {rename p ""}
|
sl@0
|
286 |
catch {rename q ""}
|
sl@0
|
287 |
proc p {} {
|
sl@0
|
288 |
return "p in [namespace current]"
|
sl@0
|
289 |
}
|
sl@0
|
290 |
proc q {} {
|
sl@0
|
291 |
return "q in [namespace current]"
|
sl@0
|
292 |
}
|
sl@0
|
293 |
namespace eval test_ns_basic {
|
sl@0
|
294 |
proc callP {} {
|
sl@0
|
295 |
p
|
sl@0
|
296 |
}
|
sl@0
|
297 |
}
|
sl@0
|
298 |
list [test_ns_basic::callP] \
|
sl@0
|
299 |
[rename q test_ns_basic::p] \
|
sl@0
|
300 |
[test_ns_basic::callP]
|
sl@0
|
301 |
} {{p in ::} {} {q in ::test_ns_basic}}
|
sl@0
|
302 |
|
sl@0
|
303 |
test basic-19.1 {Tcl_SetCommandInfo} {emptyTest} {
|
sl@0
|
304 |
} {}
|
sl@0
|
305 |
|
sl@0
|
306 |
test basic-20.1 {Tcl_GetCommandInfo, names for commands created inside namespaces} {testcmdtoken} {
|
sl@0
|
307 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
308 |
catch {rename p ""}
|
sl@0
|
309 |
catch {rename q ""}
|
sl@0
|
310 |
catch {unset x}
|
sl@0
|
311 |
set x [namespace eval test_ns_basic::test_ns_basic2 {
|
sl@0
|
312 |
# the following creates a cmd in the global namespace
|
sl@0
|
313 |
testcmdtoken create p
|
sl@0
|
314 |
}]
|
sl@0
|
315 |
list [testcmdtoken name $x] \
|
sl@0
|
316 |
[rename ::p q] \
|
sl@0
|
317 |
[testcmdtoken name $x]
|
sl@0
|
318 |
} {{p ::p} {} {q ::q}}
|
sl@0
|
319 |
test basic-20.2 {Tcl_GetCommandInfo, names for commands created outside namespaces} {testcmdtoken} {
|
sl@0
|
320 |
catch {rename q ""}
|
sl@0
|
321 |
set x [testcmdtoken create test_ns_basic::test_ns_basic2::p]
|
sl@0
|
322 |
list [testcmdtoken name $x] \
|
sl@0
|
323 |
[rename test_ns_basic::test_ns_basic2::p q] \
|
sl@0
|
324 |
[testcmdtoken name $x]
|
sl@0
|
325 |
} {{p ::test_ns_basic::test_ns_basic2::p} {} {q ::q}}
|
sl@0
|
326 |
|
sl@0
|
327 |
test basic-21.1 {Tcl_GetCommandName} {emptyTest} {
|
sl@0
|
328 |
} {}
|
sl@0
|
329 |
|
sl@0
|
330 |
test basic-22.1 {Tcl_GetCommandFullName} {
|
sl@0
|
331 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
332 |
namespace eval test_ns_basic1 {
|
sl@0
|
333 |
namespace export cmd*
|
sl@0
|
334 |
proc cmd1 {} {}
|
sl@0
|
335 |
proc cmd2 {} {}
|
sl@0
|
336 |
}
|
sl@0
|
337 |
namespace eval test_ns_basic2 {
|
sl@0
|
338 |
namespace export *
|
sl@0
|
339 |
namespace import ::test_ns_basic1::*
|
sl@0
|
340 |
proc p {} {}
|
sl@0
|
341 |
}
|
sl@0
|
342 |
namespace eval test_ns_basic3 {
|
sl@0
|
343 |
namespace import ::test_ns_basic2::*
|
sl@0
|
344 |
proc q {} {}
|
sl@0
|
345 |
list [namespace which -command foreach] \
|
sl@0
|
346 |
[namespace which -command q] \
|
sl@0
|
347 |
[namespace which -command p] \
|
sl@0
|
348 |
[namespace which -command cmd1] \
|
sl@0
|
349 |
[namespace which -command ::test_ns_basic2::cmd2]
|
sl@0
|
350 |
}
|
sl@0
|
351 |
} {::foreach ::test_ns_basic3::q ::test_ns_basic3::p ::test_ns_basic3::cmd1 ::test_ns_basic2::cmd2}
|
sl@0
|
352 |
|
sl@0
|
353 |
test basic-23.1 {Tcl_DeleteCommand} {emptyTest} {
|
sl@0
|
354 |
} {}
|
sl@0
|
355 |
|
sl@0
|
356 |
test basic-24.1 {Tcl_DeleteCommandFromToken, invalidate all compiled code if cmd has compile proc} {
|
sl@0
|
357 |
catch {interp delete test_interp}
|
sl@0
|
358 |
catch {unset x}
|
sl@0
|
359 |
interp create test_interp
|
sl@0
|
360 |
interp eval test_interp {
|
sl@0
|
361 |
proc useSet {} {
|
sl@0
|
362 |
return [set a 123]
|
sl@0
|
363 |
}
|
sl@0
|
364 |
}
|
sl@0
|
365 |
set x [interp eval test_interp {useSet}]
|
sl@0
|
366 |
interp eval test_interp {
|
sl@0
|
367 |
rename set ""
|
sl@0
|
368 |
proc set {args} {
|
sl@0
|
369 |
return "set called with $args"
|
sl@0
|
370 |
}
|
sl@0
|
371 |
}
|
sl@0
|
372 |
list $x \
|
sl@0
|
373 |
[interp eval test_interp {useSet}] \
|
sl@0
|
374 |
[interp delete test_interp]
|
sl@0
|
375 |
} {123 {set called with a 123} {}}
|
sl@0
|
376 |
test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command epoch} {
|
sl@0
|
377 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
378 |
catch {rename p ""}
|
sl@0
|
379 |
proc p {} {
|
sl@0
|
380 |
return "global p"
|
sl@0
|
381 |
}
|
sl@0
|
382 |
namespace eval test_ns_basic {
|
sl@0
|
383 |
proc p {} {
|
sl@0
|
384 |
return "namespace p"
|
sl@0
|
385 |
}
|
sl@0
|
386 |
proc callP {} {
|
sl@0
|
387 |
p
|
sl@0
|
388 |
}
|
sl@0
|
389 |
}
|
sl@0
|
390 |
list [test_ns_basic::callP] \
|
sl@0
|
391 |
[rename test_ns_basic::p ""] \
|
sl@0
|
392 |
[test_ns_basic::callP]
|
sl@0
|
393 |
} {{namespace p} {} {global p}}
|
sl@0
|
394 |
test basic-24.3 {Tcl_DeleteCommandFromToken, delete imported cmds that refer to a deleted cmd} {
|
sl@0
|
395 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
396 |
catch {rename p ""}
|
sl@0
|
397 |
namespace eval test_ns_basic {
|
sl@0
|
398 |
namespace export p
|
sl@0
|
399 |
proc p {} {return 42}
|
sl@0
|
400 |
}
|
sl@0
|
401 |
namespace eval test_ns_basic2 {
|
sl@0
|
402 |
namespace import ::test_ns_basic::*
|
sl@0
|
403 |
proc callP {} {
|
sl@0
|
404 |
p
|
sl@0
|
405 |
}
|
sl@0
|
406 |
}
|
sl@0
|
407 |
list [test_ns_basic2::callP] \
|
sl@0
|
408 |
[info commands test_ns_basic2::*] \
|
sl@0
|
409 |
[rename test_ns_basic::p ""] \
|
sl@0
|
410 |
[catch {test_ns_basic2::callP} msg] $msg \
|
sl@0
|
411 |
[info commands test_ns_basic2::*]
|
sl@0
|
412 |
} {42 {::test_ns_basic2::callP ::test_ns_basic2::p} {} 1 {invalid command name "p"} ::test_ns_basic2::callP}
|
sl@0
|
413 |
|
sl@0
|
414 |
test basic-25.1 {TclCleanupCommand} {emptyTest} {
|
sl@0
|
415 |
} {}
|
sl@0
|
416 |
|
sl@0
|
417 |
test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} {
|
sl@0
|
418 |
# If object isn't preserved, errorInfo would be set to
|
sl@0
|
419 |
# "foo\n while executing\n\"garbage bytes\"" because the object's
|
sl@0
|
420 |
# string would have been freed, leaving garbage bytes for the error
|
sl@0
|
421 |
# message.
|
sl@0
|
422 |
|
sl@0
|
423 |
proc bgerror {args} {set ::x $::errorInfo}
|
sl@0
|
424 |
set fName [makeFile {} test1]
|
sl@0
|
425 |
set f [open $fName w]
|
sl@0
|
426 |
fileevent $f writable "fileevent $f writable {}; error foo"
|
sl@0
|
427 |
set x {}
|
sl@0
|
428 |
vwait x
|
sl@0
|
429 |
close $f
|
sl@0
|
430 |
removeFile test1
|
sl@0
|
431 |
rename bgerror {}
|
sl@0
|
432 |
set x
|
sl@0
|
433 |
} "foo\n while executing\n\"error foo\""
|
sl@0
|
434 |
|
sl@0
|
435 |
test basic-26.2 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} {
|
sl@0
|
436 |
#
|
sl@0
|
437 |
# Follow the pure-list branch in a manner that
|
sl@0
|
438 |
# a - the pure-list internal rep is destroyed by shimmering
|
sl@0
|
439 |
# b - the command returns an error
|
sl@0
|
440 |
# As the error code in Tcl_EvalObjv accesses the list elements, this will
|
sl@0
|
441 |
# cause a segfault if [Bug 1119369] has not been fixed.
|
sl@0
|
442 |
#
|
sl@0
|
443 |
|
sl@0
|
444 |
set SRC [list foo 1] ;# pure-list command
|
sl@0
|
445 |
proc foo str {
|
sl@0
|
446 |
# Shimmer pure-list to cmdName, cleanup and error
|
sl@0
|
447 |
proc $::SRC {} {}; $::SRC
|
sl@0
|
448 |
error "BAD CALL"
|
sl@0
|
449 |
}
|
sl@0
|
450 |
catch {eval $SRC}
|
sl@0
|
451 |
} 1
|
sl@0
|
452 |
|
sl@0
|
453 |
test basic-27.1 {Tcl_ExprLong} {emptyTest} {
|
sl@0
|
454 |
} {}
|
sl@0
|
455 |
|
sl@0
|
456 |
test basic-28.1 {Tcl_ExprDouble} {emptyTest} {
|
sl@0
|
457 |
} {}
|
sl@0
|
458 |
|
sl@0
|
459 |
test basic-29.1 {Tcl_ExprBoolean} {emptyTest} {
|
sl@0
|
460 |
} {}
|
sl@0
|
461 |
|
sl@0
|
462 |
test basic-30.1 {Tcl_ExprLongObj} {emptyTest} {
|
sl@0
|
463 |
} {}
|
sl@0
|
464 |
|
sl@0
|
465 |
test basic-31.1 {Tcl_ExprDoubleObj} {emptyTest} {
|
sl@0
|
466 |
} {}
|
sl@0
|
467 |
|
sl@0
|
468 |
test basic-32.1 {Tcl_ExprBooleanObj} {emptyTest} {
|
sl@0
|
469 |
} {}
|
sl@0
|
470 |
|
sl@0
|
471 |
test basic-33.1 {TclInvoke} {emptyTest} {
|
sl@0
|
472 |
} {}
|
sl@0
|
473 |
|
sl@0
|
474 |
test basic-34.1 {TclGlobalInvoke} {emptyTest} {
|
sl@0
|
475 |
} {}
|
sl@0
|
476 |
|
sl@0
|
477 |
test basic-35.1 {TclObjInvokeGlobal} {emptyTest} {
|
sl@0
|
478 |
} {}
|
sl@0
|
479 |
|
sl@0
|
480 |
test basic-36.1 {TclObjInvoke, lookup of "unknown" command} {
|
sl@0
|
481 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
482 |
catch {interp delete test_interp}
|
sl@0
|
483 |
interp create test_interp
|
sl@0
|
484 |
interp eval test_interp {
|
sl@0
|
485 |
proc unknown {args} {
|
sl@0
|
486 |
return "global unknown"
|
sl@0
|
487 |
}
|
sl@0
|
488 |
namespace eval test_ns_basic {
|
sl@0
|
489 |
proc unknown {args} {
|
sl@0
|
490 |
return "namespace unknown"
|
sl@0
|
491 |
}
|
sl@0
|
492 |
}
|
sl@0
|
493 |
}
|
sl@0
|
494 |
list [interp alias test_interp newAlias test_interp doesntExist] \
|
sl@0
|
495 |
[catch {interp eval test_interp {newAlias}} msg] $msg \
|
sl@0
|
496 |
[interp delete test_interp]
|
sl@0
|
497 |
} {newAlias 0 {global unknown} {}}
|
sl@0
|
498 |
|
sl@0
|
499 |
test basic-37.1 {Tcl_ExprString: see expr.test} {emptyTest} {
|
sl@0
|
500 |
} {}
|
sl@0
|
501 |
|
sl@0
|
502 |
test basic-38.1 {Tcl_ExprObj} {emptyTest} {
|
sl@0
|
503 |
} {}
|
sl@0
|
504 |
|
sl@0
|
505 |
test basic-39.1 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
|
sl@0
|
506 |
testcmdtrace tracetest {set stuff [expr 14 + 16]}
|
sl@0
|
507 |
} {{expr 14 + 16} {expr 14 + 16} {set stuff [expr 14 + 16]} {set stuff 30}}
|
sl@0
|
508 |
test basic-39.2 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
|
sl@0
|
509 |
testcmdtrace tracetest {set stuff [info tclversion]}
|
sl@0
|
510 |
} [list {info tclversion} {info tclversion} {set stuff [info tclversion]} "set stuff $tclvers"]
|
sl@0
|
511 |
test basic-39.3 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
|
sl@0
|
512 |
testcmdtrace deletetest {set stuff [info tclversion]}
|
sl@0
|
513 |
} $tclvers
|
sl@0
|
514 |
test basic-39.4 {Tcl_CreateTrace, check that tracing doesn't cause memory faults} {testcmdtrace} {
|
sl@0
|
515 |
# Note that the proc call is the same as the variable name, and that
|
sl@0
|
516 |
# the call can be direct or indirect by way of another procedure
|
sl@0
|
517 |
proc tracer {args} {}
|
sl@0
|
518 |
proc tracedLoop {level} {
|
sl@0
|
519 |
incr level
|
sl@0
|
520 |
tracer
|
sl@0
|
521 |
foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}
|
sl@0
|
522 |
}
|
sl@0
|
523 |
testcmdtrace tracetest {tracedLoop 0}
|
sl@0
|
524 |
} {{tracedLoop 0} {tracedLoop 0} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {1 2} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}}}
|
sl@0
|
525 |
catch {rename tracer {}}
|
sl@0
|
526 |
catch {rename tracedLoop {}}
|
sl@0
|
527 |
|
sl@0
|
528 |
test basic-39.5 {Tcl_CreateObjTrace, status return TCL_ERROR} {testcmdtrace} {
|
sl@0
|
529 |
proc Error { args } { error "Shouldn't get here" }
|
sl@0
|
530 |
set x 1;
|
sl@0
|
531 |
list [catch {testcmdtrace resulttest {Error $x}} result] [set result]
|
sl@0
|
532 |
} {1 {Error $x}}
|
sl@0
|
533 |
|
sl@0
|
534 |
test basic-39.6 {Tcl_CreateObjTrace, status return TCL_RETURN} {testcmdtrace} {
|
sl@0
|
535 |
proc Return { args } { error "Shouldn't get here" }
|
sl@0
|
536 |
set x 1;
|
sl@0
|
537 |
list [catch {testcmdtrace resulttest {Return $x}} result] [set result]
|
sl@0
|
538 |
} {2 {}}
|
sl@0
|
539 |
|
sl@0
|
540 |
test basic-39.7 {Tcl_CreateObjTrace, status return TCL_BREAK} {testcmdtrace} {
|
sl@0
|
541 |
proc Break { args } { error "Shouldn't get here" }
|
sl@0
|
542 |
set x 1;
|
sl@0
|
543 |
list [catch {testcmdtrace resulttest {Break $x}} result] [set result]
|
sl@0
|
544 |
} {3 {}}
|
sl@0
|
545 |
|
sl@0
|
546 |
test basic-39.8 {Tcl_CreateObjTrace, status return TCL_CONTINUE} {testcmdtrace} {
|
sl@0
|
547 |
proc Continue { args } { error "Shouldn't get here" }
|
sl@0
|
548 |
set x 1;
|
sl@0
|
549 |
list [catch {testcmdtrace resulttest {Continue $x}} result] [set result]
|
sl@0
|
550 |
} {4 {}}
|
sl@0
|
551 |
|
sl@0
|
552 |
test basic-39.9 {Tcl_CreateObjTrace, status return unknown} {testcmdtrace} {
|
sl@0
|
553 |
proc OtherStatus { args } { error "Shouldn't get here" }
|
sl@0
|
554 |
set x 1;
|
sl@0
|
555 |
list [catch {testcmdtrace resulttest {OtherStatus $x}} result] [set result]
|
sl@0
|
556 |
} {6 {}}
|
sl@0
|
557 |
|
sl@0
|
558 |
test basic-39.10 {Tcl_CreateTrace, correct level interpretation} {testcmdtrace} {
|
sl@0
|
559 |
proc foo {} {uplevel 1 bar}
|
sl@0
|
560 |
proc bar {} {uplevel 1 grok}
|
sl@0
|
561 |
proc grok {} {uplevel 1 spock}
|
sl@0
|
562 |
proc spock {} {uplevel 1 fascinating}
|
sl@0
|
563 |
proc fascinating {} {}
|
sl@0
|
564 |
testcmdtrace leveltest {foo}
|
sl@0
|
565 |
} {foo {foo} {uplevel 1 bar} {uplevel 1 bar} bar {bar} {uplevel 1 grok} {uplevel 1 grok}}
|
sl@0
|
566 |
|
sl@0
|
567 |
test basic-40.1 {Tcl_DeleteTrace} {emptyTest} {
|
sl@0
|
568 |
# the above tests have tested Tcl_DeleteTrace
|
sl@0
|
569 |
} {}
|
sl@0
|
570 |
|
sl@0
|
571 |
test basic-41.1 {Tcl_AddErrorInfo} {emptyTest} {
|
sl@0
|
572 |
} {}
|
sl@0
|
573 |
|
sl@0
|
574 |
test basic-42.1 {Tcl_AddObjErrorInfo} {emptyTest} {
|
sl@0
|
575 |
} {}
|
sl@0
|
576 |
|
sl@0
|
577 |
test basic-43.1 {Tcl_VarEval} {emptyTest} {
|
sl@0
|
578 |
} {}
|
sl@0
|
579 |
|
sl@0
|
580 |
test basic-44.1 {Tcl_GlobalEval} {emptyTest} {
|
sl@0
|
581 |
} {}
|
sl@0
|
582 |
|
sl@0
|
583 |
test basic-45.1 {Tcl_SetRecursionLimit: see interp.test} {emptyTest} {
|
sl@0
|
584 |
} {}
|
sl@0
|
585 |
|
sl@0
|
586 |
test basic-46.1 {Tcl_AllowExceptions: exception return not allowed} {stdio} {
|
sl@0
|
587 |
catch {close $f}
|
sl@0
|
588 |
set res [catch {
|
sl@0
|
589 |
set f [open |[list [interpreter]] w+]
|
sl@0
|
590 |
fconfigure $f -buffering line
|
sl@0
|
591 |
puts $f {fconfigure stdout -buffering line}
|
sl@0
|
592 |
puts $f continue
|
sl@0
|
593 |
puts $f {puts $errorInfo}
|
sl@0
|
594 |
puts $f {puts DONE}
|
sl@0
|
595 |
set newMsg {}
|
sl@0
|
596 |
set msg {}
|
sl@0
|
597 |
while {$newMsg != "DONE"} {
|
sl@0
|
598 |
set newMsg [gets $f]
|
sl@0
|
599 |
append msg "${newMsg}\n"
|
sl@0
|
600 |
}
|
sl@0
|
601 |
close $f
|
sl@0
|
602 |
} error]
|
sl@0
|
603 |
list $res $msg
|
sl@0
|
604 |
} {1 {invoked "continue" outside of a loop
|
sl@0
|
605 |
while executing
|
sl@0
|
606 |
"continue"
|
sl@0
|
607 |
DONE
|
sl@0
|
608 |
}}
|
sl@0
|
609 |
|
sl@0
|
610 |
test basic-46.2 {Tcl_AllowExceptions: exception return not allowed} -setup {
|
sl@0
|
611 |
set fName [makeFile {
|
sl@0
|
612 |
puts hello
|
sl@0
|
613 |
break
|
sl@0
|
614 |
} BREAKtest]
|
sl@0
|
615 |
} -constraints {
|
sl@0
|
616 |
exec
|
sl@0
|
617 |
} -body {
|
sl@0
|
618 |
exec [interpreter] $fName
|
sl@0
|
619 |
} -cleanup {
|
sl@0
|
620 |
removeFile BREAKtest
|
sl@0
|
621 |
} -returnCodes error -match glob -result {hello
|
sl@0
|
622 |
invoked "break" outside of a loop
|
sl@0
|
623 |
while executing
|
sl@0
|
624 |
"break"
|
sl@0
|
625 |
(file "*BREAKtest" line 3)}
|
sl@0
|
626 |
|
sl@0
|
627 |
test basic-46.3 {Tcl_AllowExceptions: exception return not allowed} -setup {
|
sl@0
|
628 |
set fName [makeFile {
|
sl@0
|
629 |
interp alias {} patch {} info patchlevel
|
sl@0
|
630 |
patch
|
sl@0
|
631 |
break
|
sl@0
|
632 |
} BREAKtest]
|
sl@0
|
633 |
} -constraints {
|
sl@0
|
634 |
exec
|
sl@0
|
635 |
} -body {
|
sl@0
|
636 |
exec [interpreter] $fName
|
sl@0
|
637 |
} -cleanup {
|
sl@0
|
638 |
removeFile BREAKtest
|
sl@0
|
639 |
} -returnCodes error -match glob -result {invoked "break" outside of a loop
|
sl@0
|
640 |
while executing
|
sl@0
|
641 |
"break"
|
sl@0
|
642 |
(file "*BREAKtest" line 4)}
|
sl@0
|
643 |
|
sl@0
|
644 |
test basic-46.4 {Tcl_AllowExceptions: exception return not allowed} -setup {
|
sl@0
|
645 |
set fName [makeFile {
|
sl@0
|
646 |
foo [set a 1] [break]
|
sl@0
|
647 |
} BREAKtest]
|
sl@0
|
648 |
} -constraints {
|
sl@0
|
649 |
exec
|
sl@0
|
650 |
} -body {
|
sl@0
|
651 |
exec [interpreter] $fName
|
sl@0
|
652 |
} -cleanup {
|
sl@0
|
653 |
removeFile BREAKtest
|
sl@0
|
654 |
} -returnCodes error -match glob -result {invoked "break" outside of a loop
|
sl@0
|
655 |
while executing*
|
sl@0
|
656 |
"foo \[set a 1] \[break]"
|
sl@0
|
657 |
(file "*BREAKtest" line 2)}
|
sl@0
|
658 |
|
sl@0
|
659 |
test basic-46.5 {Tcl_AllowExceptions: exception return not allowed} -setup {
|
sl@0
|
660 |
set fName [makeFile {
|
sl@0
|
661 |
return -code return
|
sl@0
|
662 |
} BREAKtest]
|
sl@0
|
663 |
} -constraints {
|
sl@0
|
664 |
exec
|
sl@0
|
665 |
} -body {
|
sl@0
|
666 |
exec [interpreter] $fName
|
sl@0
|
667 |
} -cleanup {
|
sl@0
|
668 |
removeFile BREAKtest
|
sl@0
|
669 |
} -returnCodes error -match glob -result {command returned bad code: 2
|
sl@0
|
670 |
while executing
|
sl@0
|
671 |
"return -code return"
|
sl@0
|
672 |
(file "*BREAKtest" line 2)}
|
sl@0
|
673 |
|
sl@0
|
674 |
test basic-47.1 {Tcl_EvalEx: check for missing close-bracket} -body {
|
sl@0
|
675 |
subst {a[set b [format cd]}
|
sl@0
|
676 |
} -returnCodes error -result {missing close-bracket}
|
sl@0
|
677 |
|
sl@0
|
678 |
test basic-49.1 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex {
|
sl@0
|
679 |
set ::x global
|
sl@0
|
680 |
namespace eval ns {
|
sl@0
|
681 |
variable x namespace
|
sl@0
|
682 |
testevalex {set x changed} global
|
sl@0
|
683 |
set ::result [list $::x $x]
|
sl@0
|
684 |
}
|
sl@0
|
685 |
namespace delete ns
|
sl@0
|
686 |
set ::result
|
sl@0
|
687 |
} {changed namespace}
|
sl@0
|
688 |
test basic-49.2 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex {
|
sl@0
|
689 |
set ::x global
|
sl@0
|
690 |
namespace eval ns {
|
sl@0
|
691 |
variable x namespace
|
sl@0
|
692 |
testevalex {set ::context $x} global
|
sl@0
|
693 |
}
|
sl@0
|
694 |
namespace delete ns
|
sl@0
|
695 |
set ::context
|
sl@0
|
696 |
} {global}
|
sl@0
|
697 |
|
sl@0
|
698 |
# cleanup
|
sl@0
|
699 |
catch {eval namespace delete [namespace children :: test_ns_*]}
|
sl@0
|
700 |
catch {namespace delete george}
|
sl@0
|
701 |
catch {interp delete test_interp}
|
sl@0
|
702 |
catch {rename p ""}
|
sl@0
|
703 |
catch {rename q ""}
|
sl@0
|
704 |
catch {rename cmd ""}
|
sl@0
|
705 |
catch {rename value:at: ""}
|
sl@0
|
706 |
catch {unset x}
|
sl@0
|
707 |
::tcltest::cleanupTests
|
sl@0
|
708 |
return
|