Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/tests/info.test @ 68

Last change on this file since 68 was 25, checked in by landauf, 16 years ago

added tcl to libs

File size: 38.7 KB
Line 
1# -*- tcl -*-
2# Commands covered:  info
3#
4# This file contains a collection of tests for one or more of the Tcl
5# built-in commands.  Sourcing this file into Tcl runs the tests and
6# generates output for errors.  No output means no errors were found.
7#
8# Copyright (c) 1991-1994 The Regents of the University of California.
9# Copyright (c) 1994-1997 Sun Microsystems, Inc.
10# Copyright (c) 1998-1999 by Scriptics Corporation.
11# Copyright (c) 2006      ActiveState
12#
13# See the file "license.terms" for information on usage and redistribution
14# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15#
16# RCS: @(#) $Id: info.test,v 1.47 2007/12/13 15:26:06 dgp Exp $
17
18if {[lsearch [namespace children] ::tcltest] == -1} {
19    package require tcltest 2
20    namespace import -force ::tcltest::*
21}
22
23# Set up namespaces needed to test operation of "info args", "info body",
24# "info default", and "info procs" with imported procedures.
25
26catch {namespace delete test_ns_info1 test_ns_info2}
27
28namespace eval test_ns_info1 {
29    namespace export *
30    proc p {x} {return "x=$x"}
31    proc q {{y 27} {z {}}} {return "y=$y"}
32}
33
34test info-1.1 {info args option} {
35    proc t1 {a bbb c} {return foo}
36    info args t1
37} {a bbb c}
38test info-1.2 {info args option} {
39    proc t1 {{a default1} {bbb default2} {c default3} args} {return foo}
40    info a t1
41} {a bbb c args}
42test info-1.3 {info args option} {
43    proc t1 "" {return foo}
44    info args t1
45} {}
46test info-1.4 {info args option} -body {
47    catch {rename t1 {}}
48    info args t1
49} -returnCodes error -result {"t1" isn't a procedure}
50test info-1.5 {info args option} -body {
51    info args set
52} -returnCodes error -result {"set" isn't a procedure}
53test info-1.6 {info args option} {
54    proc t1 {a b} {set c 123; set d $c}
55    t1 1 2
56    info args t1
57} {a b}
58test info-1.7 {info args option} {
59    catch {namespace delete test_ns_info2}
60    namespace eval test_ns_info2 {
61        namespace import ::test_ns_info1::*
62        list [info args p] [info args q]
63    }
64} {x {y z}}
65
66test info-2.1 {info body option} {
67    proc t1 {} {body of t1}
68    info body t1
69} {body of t1}
70test info-2.2 {info body option} -body {
71    info body set
72} -returnCodes error -result {"set" isn't a procedure}
73test info-2.3 {info body option} -body {
74    info args set 1
75} -returnCodes error -result {wrong # args: should be "info args procname"}
76test info-2.4 {info body option} {
77    catch {namespace delete test_ns_info2}
78    namespace eval test_ns_info2 {
79        namespace import ::test_ns_info1::*
80        list [info body p] [info body q]
81    }
82} {{return "x=$x"} {return "y=$y"}}
83# Prior to 8.3.0 this would cause a crash because [info body]
84# would return the bytecompiled version of foo, which the catch
85# would then try and eval out of the foo context, accessing
86# compiled local indices
87test info-2.5 {info body option, returning bytecompiled bodies} {
88    catch {unset args}
89    proc foo {args} {
90        foreach v $args {
91            upvar $v var
92            return "variable $v existence: [info exists var]"
93        }
94    }
95    foo a
96    list [catch [info body foo] msg] $msg
97} {1 {can't read "args": no such variable}}
98# Fix for problem tested for in info-2.5 caused problems when
99# procedure body had no string rep (i.e. was not yet bytecode)
100# causing an empty string to be returned [Bug #545644]
101test info-2.6 {info body option, returning list bodies} {
102    proc foo args [list subst bar]
103    list [string bytelength [info body foo]] \
104            [foo; string bytelength [info body foo]]
105} {9 9}
106
107proc testinfocmdcount {} {
108    set x [info cmdcount]
109    set y 12345
110    set z [info cm]
111    expr $z-$x
112}
113test info-3.1 {info cmdcount compiled} {
114    testinfocmdcount
115} 4
116test info-3.2 {info cmdcount evaled} {
117    set x [info cmdcount]
118    set y 12345
119    set z [info cm]
120    expr $z-$x
121} 4
122test info-3.3 {info cmdcount evaled} [info body testinfocmdcount] 4
123test info-3.4 {info cmdcount option} -body {
124    info cmdcount 1
125} -returnCodes error -result {wrong # args: should be "info cmdcount"}
126
127test info-4.1 {info commands option} {
128    proc t1 {} {}
129    proc t2 {} {}
130    set x " [info commands] "
131    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
132            [string match {* set *} $x] [string match {* list *} $x]
133} {1 1 1 1}
134test info-4.2 {info commands option} {
135    proc t1 {} {}
136    rename t1 {}
137    set x [info comm]
138    string match {* t1 *} $x
139} 0
140test info-4.3 {info commands option} {
141    proc _t1_ {} {}
142    proc _t2_ {} {}
143    info commands _t1_
144} _t1_
145test info-4.4 {info commands option} {
146    proc _t1_ {} {}
147    proc _t2_ {} {}
148    lsort [info commands _t*]
149} {_t1_ _t2_}
150catch {rename _t1_ {}}
151catch {rename _t2_ {}}
152test info-4.5 {info commands option} -returnCodes error -body {
153    info commands a b
154} -result {wrong # args: should be "info commands ?pattern?"}
155# Also some tests in namespace.test
156
157test info-5.1 {info complete option} -body {
158    info complete
159} -returnCodes error -result {wrong # args: should be "info complete command"}
160test info-5.2 {info complete option} {
161    info complete abc
162} 1
163test info-5.3 {info complete option} {
164    info complete "\{abcd "
165} 0
166test info-5.4 {info complete option} {
167    info complete {# Comment should be complete command}
168} 1
169test info-5.5 {info complete option} {
170    info complete {[a [b] }
171} 0
172test info-5.6 {info complete option} {
173    info complete {[a [b]}
174} 0
175
176test info-6.1 {info default option} {
177    proc t1 {a b {c d} {e "long default value"}} {}
178    info default t1 a value
179} 0
180test info-6.2 {info default option} {
181    proc t1 {a b {c d} {e "long default value"}} {}
182    set value 12345
183    info d t1 a value
184    set value
185} {}
186test info-6.3 {info default option} {
187    proc t1 {a b {c d} {e "long default value"}} {}
188    info default t1 c value
189} 1
190test info-6.4 {info default option} {
191    proc t1 {a b {c d} {e "long default value"}} {}
192    set value 12345
193    info default t1 c value
194    set value
195} d
196test info-6.5 {info default option} {
197    proc t1 {a b {c d} {e "long default value"}} {}
198    set value 12345
199    set x [info default t1 e value]
200    list $x $value
201} {1 {long default value}}
202test info-6.6 {info default option} -returnCodes error -body {
203    info default a b
204} -result {wrong # args: should be "info default procname arg varname"}
205test info-6.7 {info default option} -returnCodes error -body {
206    info default _nonexistent_ a b
207} -result {"_nonexistent_" isn't a procedure}
208test info-6.8 {info default option} -returnCodes error -body {
209    proc t1 {a b} {}
210    info default t1 x value
211} -result {procedure "t1" doesn't have an argument "x"}
212test info-6.9 {info default option} -returnCodes error -setup {
213    catch {unset a}
214} -body {
215    set a(0) 88
216    proc t1 {a b} {}
217    info default t1 a a
218} -returnCodes error -result {couldn't store default value in variable "a"}
219test info-6.10 {info default option} -setup {
220    catch {unset a}
221} -body {
222    set a(0) 88
223    proc t1 {{a 18} b} {}
224    info default t1 a a
225} -returnCodes error -result {couldn't store default value in variable "a"}
226test info-6.11 {info default option} {
227    catch {namespace delete test_ns_info2}
228    namespace eval test_ns_info2 {
229        namespace import ::test_ns_info1::*
230        list [info default p x foo] $foo [info default q y bar] $bar
231    }
232} {0 {} 1 27}
233catch {unset a}
234
235test info-7.1 {info exists option} {
236    set value foo
237    info exists value
238} 1
239catch {unset _nonexistent_}
240test info-7.2 {info exists option} {
241    info exists _nonexistent_
242} 0
243test info-7.3 {info exists option} {
244    proc t1 {x} {return [info exists x]}
245    t1 2
246} 1
247test info-7.4 {info exists option} {
248    proc t1 {x} {
249        global _nonexistent_
250        return [info exists _nonexistent_]
251    }
252    t1 2
253} 0
254test info-7.5 {info exists option} {
255    proc t1 {x} {
256        set y 47
257        return [info exists y]
258    }
259    t1 2
260} 1
261test info-7.6 {info exists option} {
262    proc t1 {x} {return [info exists value]}
263    t1 2
264} 0
265test info-7.7 {info exists option} -setup {
266    catch {unset x}
267} -body {
268    set x(2) 44
269    list [info exists x] [info exists x(1)] [info exists x(2)]
270} -result {1 0 1}
271catch {unset x}
272test info-7.8 {info exists option} -body {
273    info exists
274} -returnCodes error -result {wrong # args: should be "info exists varName"}
275test info-7.9 {info exists option} -body {
276    info exists 1 2
277} -returnCodes error -result {wrong # args: should be "info exists varName"}
278
279test info-8.1 {info globals option} {
280    set x 1
281    set y 2
282    set value 23
283    set a " [info globals] "
284    list [string match {* x *} $a] [string match {* y *} $a] \
285            [string match {* value *} $a] [string match {* _foobar_ *} $a]
286} {1 1 1 0}
287test info-8.2 {info globals option} {
288    set _xxx1 1
289    set _xxx2 2
290    lsort [info g _xxx*]
291} {_xxx1 _xxx2}
292test info-8.3 {info globals option} -returnCodes error -body {
293    info globals 1 2
294} -result {wrong # args: should be "info globals ?pattern?"}
295test info-8.4 {info globals option: may have leading namespace qualifiers} {
296    set x 0
297    list [info globals x] [info globals :x] [info globals ::x] [info globals :::x] [info globals ::::x]
298} {x {} x x x}
299test info-8.5 {info globals option: only return existing global variables} {
300    -setup {
301        catch {unset ::NO_SUCH_VAR}
302        proc evalInProc script {eval $script}
303    }
304    -body {
305        evalInProc {global NO_SUCH_VAR; info globals NO_SUCH_VAR}
306    }
307    -cleanup {
308        rename evalInProc {}
309    }
310    -result {}
311}
312
313test info-9.1 {info level option} {
314    info level
315} 0
316test info-9.2 {info level option} {
317    proc t1 {a b} {
318        set x [info le]
319        set y [info level 1]
320        list $x $y
321    }
322    t1 146 testString
323} {1 {t1 146 testString}}
324test info-9.3 {info level option} {
325    proc t1 {a b} {
326        t2 [expr $a*2] $b
327    }
328    proc t2 {x y} {
329        list [info level] [info level 1] [info level 2] [info level -1] \
330                [info level 0]
331    }
332    t1 146 {a {b c} {{{c}}}}
333} {2 {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}} {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}}}
334test info-9.4 {info level option} {
335    proc t1 {} {
336        set x [info level]
337        set y [info level 1]
338        list $x $y
339    }
340    t1
341} {1 t1}
342test info-9.5 {info level option} -body {
343    info level 1 2
344} -returnCodes error -result {wrong # args: should be "info level ?number?"}
345test info-9.6 {info level option} -body {
346    info level 123a
347} -returnCodes error -result {expected integer but got "123a"}
348test info-9.7 {info level option} -body {
349    info level 0
350} -returnCodes error -result {bad level "0"}
351test info-9.8 {info level option} -body {
352    proc t1 {} {info level -1}
353    t1
354} -returnCodes error -result {bad level "-1"}
355test info-9.9 {info level option} -body {
356    proc t1 {x} {info level $x}
357    t1 -3
358} -returnCodes error -result {bad level "-3"}
359test info-9.10 {info level option, namespaces} {
360    set msg [namespace eval t {info level 0}]
361    namespace delete t
362    set msg
363} {namespace eval t {info level 0}}
364test info-9.11 {info level option, aliases} -constraints knownBug -setup {
365    proc w {x y z} {info level 0}
366    interp alias {} a {} w a b
367} -body {
368    a c
369} -cleanup {
370    rename a {}
371    rename w {}
372} -result {a c}
373test info-9.12 {info level option, ensembles} -constraints knownBug -setup {
374    proc w {x y z} {info level 0}
375    namespace ensemble create -command a -map {foo ::w}
376} -body {
377    a foo 1 2 3
378} -cleanup {
379    rename a {}
380    rename w {}
381} -result {a foo 1 2 3}
382
383set savedLibrary $tcl_library
384test info-10.1 {info library option} -body {
385    info library x
386} -returnCodes error -result {wrong # args: should be "info library"}
387test info-10.2 {info library option} {
388    set tcl_library 12345
389    info library
390} {12345}
391test info-10.3 {info library option} -body {
392    unset tcl_library
393    info library
394} -returnCodes error -result {no library has been specified for Tcl}
395set tcl_library $savedLibrary
396
397test info-11.1 {info loaded option} -body {
398    info loaded a b
399} -returnCodes error -result {wrong # args: should be "info loaded ?interp?"}
400test info-11.2 {info loaded option} {
401    list [catch {info loaded {}}] [catch {info loaded gorp} msg] $msg
402} {0 1 {could not find interpreter "gorp"}}
403
404test info-12.1 {info locals option} {
405    set a 22
406    proc t1 {x y} {
407        set b 13
408        set c testing
409        global a
410        global aa
411        set aa 23
412        return [info locals]
413    }
414    lsort [t1 23 24]
415} {b c x y}
416test info-12.2 {info locals option} {
417    proc t1 {x y} {
418        set xx1 2
419        set xx2 3
420        set y 4
421        return [info loc x*]
422    }
423    lsort [t1 2 3]
424} {x xx1 xx2}
425test info-12.3 {info locals option} -body {
426    info locals 1 2
427} -returnCodes error -result {wrong # args: should be "info locals ?pattern?"}
428test info-12.4 {info locals option} {
429    info locals
430} {}
431test info-12.5 {info locals option} {
432    proc t1 {} {return [info locals]}
433    t1
434} {}
435test info-12.6 {info locals vs unset compiled locals} {
436    proc t1 {lst} {
437        foreach $lst $lst {}
438        unset lst
439        return [info locals]
440    }
441    lsort [t1 {a b c c d e f}]
442} {a b c d e f}
443test info-12.7 {info locals with temporary variables} {
444    proc t1 {} {
445        foreach a {b c} {}
446        info locals
447    }
448    t1
449} {a}
450
451test info-13.1 {info nameofexecutable option} -returnCodes error -body {
452    info nameofexecutable foo
453} -result {wrong # args: should be "info nameofexecutable"}
454
455test info-14.1 {info patchlevel option} {
456    set a [info patchlevel]
457    regexp {[0-9]+\.[0-9]+([p[0-9]+)?} $a
458} 1
459test info-14.2 {info patchlevel option} -returnCodes error -body {
460    info patchlevel a
461} -result {wrong # args: should be "info patchlevel"}
462test info-14.3 {info patchlevel option} -setup {
463    set t $tcl_patchLevel
464} -body {
465    unset tcl_patchLevel
466    info patchlevel
467} -cleanup {
468    set tcl_patchLevel $t
469} -returnCodes error -result {can't read "tcl_patchLevel": no such variable}
470
471test info-15.1 {info procs option} {
472    proc t1 {} {}
473    proc t2 {} {}
474    set x " [info procs] "
475    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
476            [string match {* _undefined_ *} $x]
477} {1 1 0}
478test info-15.2 {info procs option} {
479    proc _tt1 {} {}
480    proc _tt2 {} {}
481    lsort [info pr _tt*]
482} {_tt1 _tt2}
483catch {rename _tt1 {}}
484catch {rename _tt2 {}}
485test info-15.3 {info procs option} -body {
486    info procs 2 3
487} -returnCodes error -result {wrong # args: should be "info procs ?pattern?"}
488test info-15.4 {info procs option} -setup {
489    catch {namespace delete test_ns_info2}
490} -body {
491    namespace eval test_ns_info2 {
492        namespace import ::test_ns_info1::*
493        proc r {} {}
494        list [info procs] [info procs p*]
495    }
496} -result {{p q r} p}
497test info-15.5 {info procs option with a proc in a namespace} -setup {
498    catch {namespace delete test_ns_info2}
499} -body {
500    namespace eval test_ns_info2 {
501        proc p1 { arg } {
502            puts cmd
503        }
504        proc p2 { arg } {
505            puts cmd
506        }
507    }
508    info procs ::test_ns_info2::p1
509} -result {::test_ns_info2::p1}
510test info-15.6 {info procs option with a pattern in a namespace} -setup {
511    catch {namespace delete test_ns_info2}
512} -body {
513    namespace eval test_ns_info2 {
514        proc p1 { arg } {
515            puts cmd
516        }
517        proc p2 { arg } {
518            puts cmd
519        }
520    }
521    lsort [info procs ::test_ns_info2::p*]
522} -result [lsort [list ::test_ns_info2::p1 ::test_ns_info2::p2]]
523test info-15.7 {info procs option with a global shadowing proc} -setup {
524    catch {namespace delete test_ns_info2}
525} -body {
526    proc string_cmd { arg } {
527        puts cmd
528    }
529    namespace eval test_ns_info2 {
530        proc string_cmd { arg } {
531            puts cmd
532        }
533    }
534    info procs test_ns_info2::string*
535} -result {::test_ns_info2::string_cmd}
536# This regression test is currently commented out because it requires
537# that the implementation of "info procs" looks into the global namespace,
538# which it does not (in contrast to "info commands")
539test info-15.8 {info procs option with a global shadowing proc} -setup {
540    catch {namespace delete test_ns_info2}
541} -constraints knownBug -body {
542    proc string_cmd { arg } {
543        puts cmd
544    }
545    proc string_cmd2 { arg } {
546        puts cmd
547    }
548    namespace eval test_ns_info2 {
549        proc string_cmd { arg } {
550            puts cmd
551        }
552    }
553    namespace eval test_ns_info2 {
554        lsort [info procs string*]
555    }
556} -result [lsort [list string_cmd string_cmd2]]
557
558test info-16.1 {info script option} -returnCodes error -body {
559    info script x x
560} -result {wrong # args: should be "info script ?filename?"}
561test info-16.2 {info script option} {
562    file tail [info sc]
563} "info.test"
564set gorpfile [makeFile "info script\n" gorp.info]
565test info-16.3 {info script option} {
566    list [source $gorpfile] [file tail [info script]]
567} [list $gorpfile info.test]
568test info-16.4 {resetting "info script" after errors} {
569    catch {source ~_nobody_/foo}
570    file tail [info script]
571} "info.test"
572test info-16.5 {resetting "info script" after errors} {
573    catch {source _nonexistent_}
574    file tail [info script]
575} "info.test"
576test info-16.6 {info script option} {
577    set script [info script]
578    list [file tail [info script]] \
579            [info script newname.txt] \
580            [file tail [info script $script]]
581} [list info.test newname.txt info.test]
582test info-16.7 {info script option} {
583    set script [info script]
584    info script newname.txt
585    list [source $gorpfile] [file tail [info script]] \
586            [file tail [info script $script]]
587} [list $gorpfile newname.txt info.test]
588removeFile gorp.info
589set gorpfile [makeFile {list [info script] [info script foo.bar]} gorp.info]
590test info-16.8 {info script option} {
591    list [source $gorpfile] [file tail [info script]]
592} [list [list $gorpfile foo.bar] info.test]
593removeFile gorp.info
594
595test info-17.1 {info sharedlibextension option} -returnCodes error -body {
596    info sharedlibextension foo
597} -result {wrong # args: should be "info sharedlibextension"}
598
599test info-18.1 {info tclversion option} {
600    scan [info tclversion] "%d.%d%c" a b c
601} 2
602test info-18.2 {info tclversion option} -body {
603    info t 2
604} -returnCodes error -result {wrong # args: should be "info tclversion"}
605test info-18.3 {info tclversion option} -body {
606    unset tcl_version
607    info tclversion
608} -returnCodes error -setup {
609    set t $tcl_version
610} -cleanup {
611    set tcl_version $t
612} -result {can't read "tcl_version": no such variable}
613
614test info-19.1 {info vars option} {
615    set a 1
616    set b 2
617    proc t1 {x y} {
618        global a b
619        set c 33
620        return [info vars]
621    }
622    lsort [t1 18 19]
623} {a b c x y}
624test info-19.2 {info vars option} {
625    set xxx1 1
626    set xxx2 2
627    proc t1 {xxa y} {
628        global xxx1 xxx2
629        set c 33
630        return [info vars x*]
631    }
632    lsort [t1 18 19]
633} {xxa xxx1 xxx2}
634test info-19.3 {info vars option} {
635    lsort [info vars]
636} [lsort [info globals]]
637test info-19.4 {info vars option} -returnCodes error -body {
638    info vars a b
639} -result {wrong # args: should be "info vars ?pattern?"}
640test info-19.5 {info vars with temporary variables} {
641    proc t1 {} {
642        foreach a {b c} {}
643        info vars
644    }
645    t1
646} {a}
647test info-19.6 {info vars: Bug 1072654} -setup {
648    namespace eval :: unset -nocomplain foo
649    catch {namespace delete x}
650} -body {
651    namespace eval x info vars foo
652} -cleanup {
653    namespace delete x
654} -result {}
655
656set functions {abs acos asin atan atan2 bool ceil cos cosh double entier exp floor fmod hypot int isqrt log log10 max min pow rand round sin sinh sqrt srand tan tanh wide}
657# Check whether the extra testing functions are defined...
658if {!([catch {expr T1()} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} {
659    set functions "T1 T2 T3 $functions"  ;# A lazy way of prepending!
660}
661test info-20.1 {info functions option} {info functions sin} sin
662test info-20.2 {info functions option} {lsort [info functions]} $functions
663test info-20.3 {info functions option} {
664    lsort [info functions a*]
665} {abs acos asin atan atan2}
666test info-20.4 {info functions option} {
667    lsort [info functions *tan*]
668} {atan atan2 tan tanh}
669test info-20.5 {info functions option} -returnCodes error -body {
670    info functions raise an error
671} -result {wrong # args: should be "info functions ?pattern?"}
672
673test info-21.1 {miscellaneous error conditions} -returnCodes error -body {
674    info
675} -result {wrong # args: should be "info subcommand ?argument ...?"}
676test info-21.2 {miscellaneous error conditions} -returnCodes error -body {
677    info gorp
678} -result {unknown or ambiguous subcommand "gorp": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
679test info-21.3 {miscellaneous error conditions} -returnCodes error -body {
680    info c
681} -result {unknown or ambiguous subcommand "c": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
682test info-21.4 {miscellaneous error conditions} -returnCodes error -body {
683    info l
684} -result {unknown or ambiguous subcommand "l": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
685test info-21.5 {miscellaneous error conditions} -returnCodes error -body {
686    info s
687} -result {unknown or ambiguous subcommand "s": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
688
689##
690# ### ### ### ######### ######### #########
691## info frame
692
693## Helper
694# For the more complex results we cut the file name down to remove
695# path dependencies, and we use only part of the first line of the
696# reported command. The latter is required because otherwise the whole
697# test case may appear in some results, but the result is part of the
698# testcase. An infinite string would be required to describe that. The
699# cutting-down breaks this.
700
701proc reduce {frame} {
702    set  pos [lsearch -exact $frame cmd]
703    incr pos
704    set  cmd [lindex $frame $pos]
705    if {[regexp \n $cmd]} {
706        set first [string range [lindex [split $cmd \n] 0] 0 end-4]
707        set frame [lreplace $frame $pos $pos $first]
708    }
709    set pos [lsearch -exact $frame file]
710    if {$pos >=0} {
711        incr pos
712        set tail  [file tail [lindex $frame $pos]]
713        set frame [lreplace $frame $pos $pos $tail]
714    }
715    set frame
716}
717
718## Helper
719# Generate a stacktrace from the current location to top.  This code
720# not only depends on the exact location of things, but also on the
721# implementation of tcltest. Any changes and these tests will have to
722# be updated.
723
724proc etrace {} {
725    set res {}
726    set level [info frame]
727    while {$level} {
728        lappend res [list $level [reduce [info frame $level]]]
729        incr level -1
730    }
731    return $res
732}
733
734##
735
736test info-22.0 {info frame, levels} {!singleTestInterp} {
737    info frame
738} 7
739test info-22.1 {info frame, bad level relative} {!singleTestInterp} {
740    # catch is another level!, i.e. we have 8, not 7
741    catch {info frame -8} msg
742    set msg
743} {bad level "-8"}
744test info-22.2 {info frame, bad level absolute} {!singleTestInterp} {
745    # catch is another level!, i.e. we have 8, not 7
746    catch {info frame 9} msg
747    set msg
748} {bad level "9"}
749test info-22.3 {info frame, current, relative} {
750    info frame 0
751} {type eval line 2 cmd {info frame 0}}
752test info-22.4 {info frame, current, relative, nested} {
753    set res [info frame 0]
754} {type eval line 2 cmd {info frame 0}}
755test info-22.5 {info frame, current, absolute} {!singleTestInterp} {
756    reduce [info frame 7]
757} {type eval line 2 cmd {info frame 7}}
758test info-22.6 {info frame, global, relative} {!singleTestInterp} {
759    reduce [info frame -6]
760} {type source line 758 file info.test cmd test\ info-22.6\ \{info\ frame,\ global,\ relative\}\ \{!singleTestInter level 0}
761test info-22.7 {info frame, global, absolute} {!singleTestInterp} {
762    reduce [info frame 1]
763} {type source line 761 file info.test cmd test\ info-22.7\ \{info\ frame,\ global,\ absolute\}\ \{!singleTestInter level 0}
764test info-22.8 {info frame, basic trace} {knownBug !singleTestInterp} {
765    join [etrace] \n
766} {8 {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
7677 {type eval line 2 cmd etrace}
7686 {type source line 2299 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::RunTest}
7695 {type eval line 1 cmd {::tcltest::RunTest info-22}}
7704 {type source line 1621 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::Eval}
7713 {type eval line 1 cmd ::tcltest::Eval\ \{::tcltest::RunTest\ info-22}
7722 {type source line 1967 file tcltest.tcl cmd {uplevel 1 [list [namespace origin Eval] $command 1]} proc ::tcltest::test}
7731 {type source line 764 file info.test cmd test\ info-22.8\ \{info\ frame,\ basic\ trace\}\ \{!singleTestInter level 1}}
774
775## The line 1967 is off by 5 from the true value of 1972. This is a knownBug, see testcase 30.0
776test info-23.0 {eval'd info frame} {!singleTestInterp} {
777    eval {info frame}
778} 8
779test info-23.1 {eval'd info frame, semi-dynamic} {!singleTestInterp} {
780    eval info frame
781} 8
782test info-23.2 {eval'd info frame, dynamic} {!singleTestInterp} {
783    set script {info frame}
784    eval $script
785} 8
786test info-23.3 {eval'd info frame, literal} {
787    eval {
788        info frame 0
789    }
790} {type eval line 2 cmd {info frame 0}}
791test info-23.4 {eval'd info frame, semi-dynamic} {
792    eval info frame 0
793} {type eval line 1 cmd {info frame 0}}
794test info-23.5 {eval'd info frame, dynamic} {
795    set script {info frame 0}
796    eval $script
797} {type eval line 1 cmd {info frame 0}}
798test info-23.6 {eval'd info frame, trace} {knownBug !singleTestInterp} {
799    set script {etrace}
800    join [eval $script] \n
801} {9 {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
8028 {type eval line 1 cmd etrace}
8037 {type eval line 3 cmd {eval $script}}
8046 {type source line 2299 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::RunTest}
8055 {type eval line 1 cmd {::tcltest::RunTest info-23}}
8064 {type source line 1621 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::Eval}
8073 {type eval line 1 cmd ::tcltest::Eval\ \{::tcltest::RunTest\ info-23}
8082 {type source line 1967 file tcltest.tcl cmd {uplevel 1 [list [namespace origin Eval] $command 1]} proc ::tcltest::test}
8091 {type source line 798 file info.test cmd test\ info-23.6\ \{eval'd\ info\ frame,\ trace\}\ \{!singleTestInter level 1}}
810## The line 1967 is off by 5 from the true value of 1972. This is a knownBug, see testcase 30.0
811# -------------------------------------------------------------------------
812
813# Procedures defined in scripts which are arguments to control
814# structures (like 'namespace eval', 'interp eval', 'if', 'while',
815# 'switch', 'catch', 'for', 'foreach', etc.) have no absolute
816# location. The command implementations execute such scripts through
817# Tcl_EvalObjEx. Flag 0 causes it to use the bytecode compiler. This
818# causes the connection to the context to be lost. Currently only
819# procedure bodies are able to remember their context.
820
821# NOTE THAT THESE DO NOT USE THE -setup OPTION TO [test]
822
823# -------------------------------------------------------------------------
824
825namespace eval foo {
826    proc bar {} {info frame 0}
827}
828
829test info-24.0 {info frame, interaction, namespace eval} -body {
830    reduce [foo::bar]
831} -cleanup {
832    namespace delete foo
833} -result {type source line 826 file info.test cmd {info frame 0} proc ::foo::bar level 0}
834
835# -------------------------------------------------------------------------
836
837set flag 1
838if {$flag} {
839    namespace eval foo {}
840    proc ::foo::bar {} {info frame 0}
841}
842
843test info-24.1 {info frame, interaction, if} -body {
844    reduce [foo::bar]
845} -cleanup {
846    namespace delete foo
847} -result {type source line 840 file info.test cmd {info frame 0} proc ::foo::bar level 0}
848
849# -------------------------------------------------------------------------
850
851set flag 1
852while {$flag} {
853    namespace eval foo {}
854    proc ::foo::bar {} {info frame 0}
855    set flag 0
856}
857
858test info-24.2 {info frame, interaction, while} -body {
859    reduce [foo::bar]
860} -cleanup {
861    namespace delete foo
862} -result {type source line 854 file info.test cmd {info frame 0} proc ::foo::bar level 0}
863
864# -------------------------------------------------------------------------
865
866catch {
867    namespace eval foo {}
868    proc ::foo::bar {} {info frame 0}
869}
870
871test info-24.3 {info frame, interaction, catch} -body {
872    reduce [foo::bar]
873} -cleanup {
874    namespace delete foo
875} -result {type source line 868 file info.test cmd {info frame 0} proc ::foo::bar level 0}
876
877# -------------------------------------------------------------------------
878
879foreach var val {
880    namespace eval foo {}
881    proc ::foo::bar {} {info frame 0}
882    break
883}
884
885test info-24.4 {info frame, interaction, foreach} -body {
886    reduce [foo::bar]
887} -cleanup {
888    namespace delete foo
889} -result {type source line 881 file info.test cmd {info frame 0} proc ::foo::bar level 0}
890
891# -------------------------------------------------------------------------
892
893for {} {1} {} {
894    namespace eval foo {}
895    proc ::foo::bar {} {info frame 0}
896    break
897}
898
899test info-24.5 {info frame, interaction, for} -body {
900    reduce [foo::bar]
901} -cleanup {
902    namespace delete foo
903} -result {type source line 895 file info.test cmd {info frame 0} proc ::foo::bar level 0}
904
905# -------------------------------------------------------------------------
906
907eval {
908    proc bar {} {info frame 0}
909}
910
911test info-25.0 {info frame, proc in eval} {
912    reduce [bar]
913} {type source line 908 file info.test cmd {info frame 0} proc ::bar level 0}
914# Don't need to clean up yet...
915
916proc bar {} {info frame 0}
917
918test info-25.1 {info frame, regular proc} {
919    reduce [bar]
920} {type source line 916 file info.test cmd {info frame 0} proc ::bar level 0}
921
922rename bar {}
923
924# -------------------------------------------------------------------------
925
926test info-30.0 {bs+nl in literal words} knownBug {
927    if {1} {
928        set res \
929            [reduce [info frame 0]]
930    }
931    set res
932    # This is reporting line 3 instead of the correct 4 because the
933    # bs+nl combination is subst by the parser before the 'if'
934    # command, and the the bcc sees the word. To fix record the
935    # offsets of all bs+nl sequences in literal words, then use the
936    # information in the bcc to bump line numbers when parsing over
937    # the location. Also affected: testcases 22.8 and 23.6.
938} {type eval line 4 cmd {info frame 0} proc ::tcltest::RunTest}
939
940# -------------------------------------------------------------------------
941# See 24.0 - 24.5 for similar situations, using literal scripts.
942
943set body {set flag 0
944    set a c
945    set res [info frame 0]} ;# line 3!
946
947test info-31.0 {ns eval, script in variable} {
948    namespace eval foo $body
949    set res
950} {type eval line 3 cmd {info frame 0} level 0}
951catch {namespace delete foo}
952
953test info-31.1 {if, script in variable} {
954    if 1 $body
955    set res
956} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
957
958test info-31.1a {if, script in variable} {
959    if 1 then $body
960    set res
961} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
962
963test info-31.2 {while, script in variable} {
964    set flag 1
965    while {$flag} $body
966    set res
967} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
968
969# .3 - proc - scoping prevent return of result ...
970
971test info-31.4 {foreach, script in variable} {
972    foreach var val $body
973    set res
974} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
975
976test info-31.5 {for, script in variable} {
977    set flag 1
978    for {} {$flag} {} $body
979    set res
980} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
981
982test info-31.6 {eval, script in variable} {
983    eval $body
984    set res
985} {type eval line 3 cmd {info frame 0}}
986
987# -------------------------------------------------------------------------
988
989namespace eval foo {}
990set x foo
991switch -exact -- $x {
992    foo {
993        proc ::foo::bar {} {info frame 0}
994    }
995}
996
997test info-24.6.0 {info frame, interaction, switch, list body} -body {
998    reduce [foo::bar]
999} -cleanup {
1000    namespace delete foo
1001    unset x
1002} -result {type source line 993 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1003
1004# -------------------------------------------------------------------------
1005
1006namespace eval foo {}
1007set x foo
1008switch -exact -- $x foo {
1009    proc ::foo::bar {} {info frame 0}
1010}
1011
1012test info-24.6.1 {info frame, interaction, switch, multi-body} -body {
1013    reduce [foo::bar]
1014} -cleanup {
1015    namespace delete foo
1016    unset x
1017} -result {type source line 1009 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1018
1019# -------------------------------------------------------------------------
1020
1021namespace eval foo {}
1022set x foo
1023switch -exact -- $x [list foo {
1024    proc ::foo::bar {} {info frame 0}
1025}]
1026
1027test info-24.6.2 {info frame, interaction, switch, list body, dynamic} -body {
1028    reduce [foo::bar]
1029} -cleanup {
1030    namespace delete foo
1031    unset x
1032} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
1033
1034# -------------------------------------------------------------------------
1035
1036set body {
1037    foo {
1038        proc ::foo::bar {} {info frame 0}
1039    }
1040}
1041
1042namespace eval foo {}
1043set x foo
1044switch -exact -- $x $body
1045
1046test info-31.7 {info frame, interaction, switch, dynamic} -body {
1047    reduce [foo::bar]
1048} -cleanup {
1049    namespace delete foo
1050    unset x
1051} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
1052
1053# -------------------------------------------------------------------------
1054
1055set body {
1056    proc ::foo::bar {} {info frame 0}
1057}
1058
1059namespace eval foo {}
1060eval $body
1061
1062test info-32.0 {info frame, dynamic procedure} -body {
1063    reduce [foo::bar]
1064} -cleanup {
1065    namespace delete foo
1066} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
1067
1068# -------------------------------------------------------------------------
1069
1070namespace {*}{
1071    eval
1072    foo
1073    {proc bar {} {info frame 0}}
1074}
1075test info-33.0 {{*}, literal, direct} -body {
1076    reduce [foo::bar]
1077} -cleanup {
1078    namespace delete foo
1079} -result {type source line 1073 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1080
1081# -------------------------------------------------------------------------
1082
1083namespace eval foo {}
1084proc foo::bar {} {
1085    set flag 1
1086    if {*}{
1087        {$flag}
1088        {info frame 0}
1089    }
1090}
1091test info-33.1 {{*}, literal, simple, bytecompiled} -body {
1092    reduce [foo::bar]
1093} -cleanup {
1094    namespace delete foo
1095} -result {type source line 1088 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1096
1097# -------------------------------------------------------------------------
1098
1099set body {
1100    eval
1101    foo
1102    {proc bar {} {
1103        info frame 0
1104    }}
1105}
1106namespace {*}$body
1107test info-34.0 {{*}, dynamic, direct} {
1108    reduce [foo::bar]
1109} {type proc line 2 cmd {info frame 0} proc ::foo::bar level 0}
1110
1111unset body
1112namespace delete foo
1113
1114# -------------------------------------------------------------------------
1115
1116namespace eval foo {}
1117set body {
1118    {$flag}
1119    {info frame 0}
1120}
1121proc foo::bar {} {
1122    global body ; set flag 1
1123    if {*}$body
1124}
1125test info-34.1 {{*}, literal, bytecompiled} {
1126    reduce [foo::bar]
1127} {type eval line 1 cmd {info frame 0} proc ::foo::bar level 0}
1128
1129unset body
1130namespace delete foo
1131
1132# -------------------------------------------------------------------------
1133
1134proc foo {} {
1135    apply {
1136        {x y}
1137        {info frame 0}
1138    } 0 0
1139}
1140test info-35.0 {apply, literal} {
1141    reduce [foo]
1142} {type source line 1137 file info.test cmd {info frame 0} lambda {
1143        {x y}
1144        {info frame 0}
1145    } level 0}
1146rename foo {}
1147
1148set lambda {
1149    {x y}
1150    {info frame 0}
1151}
1152test info-35.1 {apply, dynamic} {
1153    reduce [apply $lambda 0 0]
1154} {type proc line 1 cmd {info frame 0} lambda {
1155    {x y}
1156    {info frame 0}
1157} level 0}
1158unset lambda
1159
1160# -------------------------------------------------------------------------
1161
1162namespace eval foo {}
1163dict for {k v} {foo bar} {
1164    proc ::foo::bar {} {info frame 0}
1165}
1166
1167test info-24.7 {info frame, interaction, dict for} {
1168    reduce [foo::bar]
1169} {type source line 1164 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1170
1171namespace delete foo
1172
1173# -------------------------------------------------------------------------
1174
1175namespace eval foo {}
1176set thedict {foo bar}
1177dict with thedict {
1178    proc ::foo::bar {} {info frame 0}
1179}
1180
1181test info-24.8 {info frame, interaction, dict with} {
1182    reduce [foo::bar]
1183} {type source line 1178 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1184
1185namespace delete foo
1186unset thedict
1187
1188# -------------------------------------------------------------------------
1189
1190namespace eval foo {}
1191dict filter {foo bar} script {k v} {
1192    proc ::foo::bar {} {info frame 0}
1193    set x 1
1194}
1195
1196test info-24.9 {info frame, interaction, dict filter} {
1197    reduce [foo::bar]
1198} {type source line 1192 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1199
1200namespace delete foo
1201unset x
1202
1203# -------------------------------------------------------------------------
1204
1205namespace eval foo {}
1206proc foo::bar {} {
1207    dict for {k v} {foo bar} {
1208        set x [info frame 0]
1209    }
1210    set x
1211}
1212test info-36.0 {info frame, dict for, bcc} {
1213    reduce [foo::bar]
1214} {type source line 1208 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1215
1216namespace delete foo
1217
1218# -------------------------------------------------------------------------
1219
1220namespace eval foo {}
1221proc foo::bar {} {
1222    set x foo
1223    switch -exact -- $x {
1224        foo {set y [info frame 0]}
1225    }
1226    set y
1227}
1228
1229test info-36.1.0 {switch, list literal, bcc} {
1230    reduce [foo::bar]
1231} {type source line 1224 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1232
1233namespace delete foo
1234
1235# -------------------------------------------------------------------------
1236
1237namespace eval foo {}
1238proc foo::bar {} {
1239    set x foo
1240    switch -exact -- $x foo {set y [info frame 0]}
1241    set y
1242}
1243
1244test info-36.1.1 {switch, multi-body literals, bcc} {
1245    reduce [foo::bar]
1246} {type source line 1240 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1247
1248namespace delete foo
1249
1250# -------------------------------------------------------------------------
1251
1252namespace {*}"
1253    eval
1254    foo
1255    {proc bar {} {info frame 0}}
1256"
1257test info-33.2 {{*}, literal, direct} {
1258    reduce [foo::bar]
1259} {type source line 1255 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1260
1261namespace delete foo
1262
1263# -------------------------------------------------------------------------
1264
1265namespace {*}"eval\nfoo\n{proc bar {} {info frame 0}}\n"
1266
1267test info-33.2a {{*}, literal, not simple, direct} {
1268    reduce [foo::bar]
1269} {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
1270
1271namespace delete foo
1272
1273# -------------------------------------------------------------------------
1274
1275namespace eval foo {}
1276proc foo::bar {} {
1277    set flag 1
1278    if {*}"
1279        {1}
1280        {info frame 0}
1281    "
1282}
1283test info-33.3 {{*}, literal, simple, bytecompiled} {
1284    reduce [foo::bar]
1285} {type source line 1280 file info.test cmd {info frame 0} proc ::foo::bar level 0}
1286
1287namespace delete foo
1288
1289# -------------------------------------------------------------------------
1290
1291namespace eval foo {}
1292proc foo::bar {} {
1293    set flag 1
1294    if {*}"\n{1}\n{info frame 0}"
1295}
1296test info-33.3a {{*}, literal, not simple, bytecompiled} {
1297    reduce [foo::bar]
1298} {type eval line 1 cmd {info frame 0} proc ::foo::bar level 0}
1299
1300namespace delete foo
1301
1302# -------------------------------------------------------------------------
1303
1304# cleanup
1305catch {namespace delete test_ns_info1 test_ns_info2}
1306::tcltest::cleanupTests
1307return
Note: See TracBrowser for help on using the repository browser.