os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/tests/compile.test
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 # This file contains tests for the files tclCompile.c, tclCompCmds.c
     2 # and tclLiteral.c
     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) 1997 by 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: compile.test,v 1.24.2.3 2004/10/26 20:14:36 dgp Exp $
    15 
    16 package require tcltest 2
    17 namespace import -force ::tcltest::*
    18 
    19 # The following tests are very incomplete, although the rest of the
    20 # test suite covers this file fairly well.
    21 
    22 catch {rename p ""}
    23 catch {namespace delete test_ns_compile}
    24 catch {unset x}
    25 catch {unset y}
    26 catch {unset a}
    27 
    28 test compile-1.1 {TclCompileString: look up cmds in proc ns, not current ns} {
    29     catch {namespace delete test_ns_compile}
    30     catch {unset x}
    31     set x 123
    32     namespace eval test_ns_compile {
    33         proc set {args} {
    34             global x
    35             lappend x test_ns_compile::set
    36         }
    37         proc p {} {
    38             set 0
    39         }
    40     }
    41     list [test_ns_compile::p] [set x]
    42 } {{123 test_ns_compile::set} {123 test_ns_compile::set}}
    43 test compile-1.2 {TclCompileString, error result is reset if TclGetLong determines word isn't an integer} {
    44     proc p {x} {info commands 3m}
    45     list [catch {p} msg] $msg
    46 } {1 {wrong # args: should be "p x"}}
    47 test compile-2.1 {TclCompileDollarVar: global scalar name with ::s} {
    48     catch {unset x}
    49     set x 123
    50     list $::x [expr {[lsearch -exact [info globals] x] != 0}]
    51 } {123 1}
    52 test compile-2.2 {TclCompileDollarVar: global scalar name with ::s} {
    53     catch {unset y}
    54     proc p {} {
    55         set ::y 789
    56         return $::y
    57     }
    58     list [p] $::y [expr {[lsearch -exact [info globals] y] != 0}]
    59 } {789 789 1}
    60 test compile-2.3 {TclCompileDollarVar: global array name with ::s} {
    61     catch {unset a}
    62     set ::a(1) 2
    63     list $::a(1) [set ::a($::a(1)) 3] $::a(2) [expr {[lsearch -exact [info globals] a] != 0}]
    64 } {2 3 3 1}
    65 test compile-2.4 {TclCompileDollarVar: global scalar name with ::s} {
    66     catch {unset a}
    67     proc p {} {
    68         set ::a(1) 1
    69         return $::a($::a(1))
    70     }
    71     list [p] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
    72 } {1 1 1}
    73 test compile-2.5 {TclCompileDollarVar: global array, called as ${arrName(0)}} {
    74     catch {unset a}
    75     proc p {} {
    76 	global a
    77         set a(1) 1
    78         return ${a(1)}$::a(1)$a(1)
    79     }
    80     list [p] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
    81 } {111 1 1}
    82 
    83 test compile-3.1 {TclCompileCatchCmd: only catch cmds with scalar vars are compiled inline} {
    84     catch {unset a}
    85     set a(1) xyzzyx
    86     proc p {} {
    87         global a
    88         catch {set x 123} a(1)
    89     }
    90     list [p] $a(1)
    91 } {0 123}
    92 test compile-3.2 {TclCompileCatchCmd: non-local variables} {
    93     set ::foo 1
    94     proc catch-test {} {
    95 	catch {set x 3} ::foo
    96     }
    97     catch-test
    98     set ::foo
    99 } 3
   100 test compile-3.3 {TclCompileCatchCmd: overagressive compiling [bug 219184]} {
   101     proc catch-test {str} {
   102 	catch [eval $str GOOD]
   103 	error BAD
   104     }
   105     catch {catch-test error} ::foo
   106     set ::foo
   107 } {GOOD}
   108 test compile-3.4 {TclCompileCatchCmd: bcc'ed [return] is caught} {
   109     proc foo {} {
   110 	set fail [catch {
   111 	    return 1
   112 	}] ; # {}	
   113 	return 2
   114     }
   115     foo
   116 } {2}
   117 
   118 test compile-3.5 {TclCompileCatchCmd: recover from error, [Bug 705406]} {
   119     proc foo {} {
   120 	catch {
   121 	    if {[a]} {
   122 		if b {}
   123 	    }   
   124 	}   
   125     }
   126     list [catch foo msg] $msg
   127 } {0 1}
   128 
   129 test compile-4.1 {TclCompileForCmd: command substituted test expression} {
   130     set i 0
   131     set j 0
   132     # Should be "forever"
   133     for {} [expr $i < 3] {} {
   134 	set j [incr i]
   135 	if {$j > 3} break
   136     }
   137     set j
   138 } {4}
   139 
   140 test compile-5.1 {TclCompileForeachCmd: exception stack} {
   141     proc foreach-exception-test {} {
   142 	foreach array(index) [list 1 2 3] break
   143 	foreach array(index) [list 1 2 3] break
   144 	foreach scalar [list 1 2 3] break
   145     }
   146     list [catch foreach-exception-test result] $result
   147 } {0 {}}
   148 test compile-5.2 {TclCompileForeachCmd: non-local variables} {
   149     set ::foo 1
   150     proc foreach-test {} {
   151 	foreach ::foo {1 2 3} {}
   152     }
   153     foreach-test
   154     set ::foo
   155 } 3
   156 
   157 test compile-6.1 {TclCompileSetCmd: global scalar names with ::s} {
   158     catch {unset x}
   159     catch {unset y}
   160     set x 123
   161     proc p {} {
   162         set ::y 789
   163         return $::y
   164     }
   165     list $::x [expr {[lsearch -exact [info globals] x] != 0}] \
   166          [p] $::y [expr {[lsearch -exact [info globals] y] != 0}]
   167 } {123 1 789 789 1}
   168 test compile-6.2 {TclCompileSetCmd: global array names with ::s} {
   169     catch {unset a}
   170     set ::a(1) 2
   171     proc p {} {
   172         set ::a(1) 1
   173         return $::a($::a(1))
   174     }
   175     list $::a(1) [p] [set ::a($::a(1)) 3] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
   176 } {2 1 3 3 1}
   177 test compile-6.3 {TclCompileSetCmd: namespace var names with ::s} {
   178     catch {namespace delete test_ns_compile}
   179     catch {unset x}
   180     namespace eval test_ns_compile {
   181         variable v hello
   182         variable arr
   183         set ::x $::test_ns_compile::v
   184 	set ::test_ns_compile::arr(1) 123
   185     }
   186     list $::x $::test_ns_compile::arr(1)
   187 } {hello 123}
   188 
   189 test compile-7.1 {TclCompileWhileCmd: command substituted test expression} {
   190     set i 0
   191     set j 0
   192     # Should be "forever"
   193     while [expr $i < 3] {
   194 	set j [incr i]
   195 	if {$j > 3} break
   196     }
   197     set j
   198 } {4}
   199 
   200 test compile-8.1 {CollectArgInfo: binary data} {
   201     list [catch "string length \000foo" msg] $msg
   202 } {0 4}
   203 test compile-8.2 {CollectArgInfo: binary data} {
   204     list [catch "string length foo\000" msg] $msg
   205 } {0 4}
   206 test compile-8.3 {CollectArgInfo: handle "]" at end of command properly} {
   207     set x ]
   208 } {]}
   209 
   210 test compile-9.1 {UpdateStringOfByteCode: called for duplicate of compiled empty object} {
   211     proc p {} {
   212         set x {}
   213         eval $x
   214         append x { }
   215         eval $x
   216     }
   217     p
   218 } {}
   219 
   220 test compile-10.1 {BLACKBOX: exception stack overflow} {
   221     set x {{0}}
   222     set y 0
   223     while {$y < 100} {
   224 	if !$x {incr y}
   225     }
   226 } {}
   227 
   228 test compile-11.1 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   229     proc p {} {
   230 	# shared object - Interp result && Var 'r'
   231 	set r [list foobar]
   232 	# command that will add error to result
   233 	lindex a bogus
   234     }
   235     list [catch {p} msg] $msg
   236 } {1 {bad index "bogus": must be integer or end?-integer?}}
   237 test compile-11.2 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   238     proc p {} { set r [list foobar] ; string index a bogus }
   239     list [catch {p} msg] $msg
   240 } {1 {bad index "bogus": must be integer or end?-integer?}}
   241 test compile-11.3 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   242     proc p {} { set r [list foobar] ; string index a 09 }
   243     list [catch {p} msg] $msg
   244 } {1 {bad index "09": must be integer or end?-integer? (looks like invalid octal number)}}
   245 test compile-11.4 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   246     proc p {} { set r [list foobar] ; array set var {one two many} }
   247     list [catch {p} msg] $msg
   248 } {1 {list must have an even number of elements}}
   249 test compile-11.5 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   250     proc p {} { set r [list foobar] ; incr foo }
   251     list [catch {p} msg] $msg
   252 } {1 {can't read "foo": no such variable}}
   253 test compile-11.6 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   254     proc p {} { set r [list foobar] ; incr foo bogus }
   255     list [catch {p} msg] $msg
   256 } {1 {expected integer but got "bogus"}}
   257 test compile-11.7 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   258     proc p {} { set r [list foobar] ; expr !a }
   259     list [catch {p} msg] $msg
   260 } {1 {syntax error in expression "!a": variable references require preceding $}}
   261 test compile-11.8 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   262     proc p {} { set r [list foobar] ; expr {!a} }
   263     list [catch {p} msg] $msg
   264 } {1 {syntax error in expression "!a": variable references require preceding $}}
   265 test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
   266     proc p {} { set r [list foobar] ; llength "\{" }
   267     list [catch {p} msg] $msg
   268 } {1 {unmatched open brace in list}}
   269 
   270 # 
   271 # Special section for tests of tclLiteral.c
   272 # The following tests check for incorrect memory handling in
   273 # TclReleaseLiteral. They are only effective when tcl is compiled 
   274 # with TCL_MEM_DEBUG
   275 #
   276 # Special test for leak on interp delete [Bug 467523]. 
   277 ::tcltest::testConstraint exec [llength [info commands exec]]
   278 ::tcltest::testConstraint memDebug [llength [info commands memory]]
   279 
   280 test compile-12.1 {testing literal leak on interp delete} {memDebug} {
   281     proc getbytes {} {
   282 	set lines [split [memory info] "\n"]
   283 	lindex [lindex $lines 3] 3
   284     }
   285     
   286     set end [getbytes]
   287     for {set i 0} {$i < 5} {incr i} {
   288 	interp create foo 
   289 	foo eval { 
   290 	    namespace eval bar {}
   291 	} 
   292 	interp delete foo
   293 	set tmp $end
   294 	set end [getbytes]
   295     }    
   296     rename getbytes {}
   297     set leak [expr {$end - $tmp}]
   298 } 0
   299 # Special test for a memory error in a preliminary fix of [Bug 467523]. 
   300 # It requires executing a helpfile.  Presumably the child process is
   301 # used because when this test fails, it crashes.
   302 test compile-12.2 {testing error on literal deletion} {memDebug exec} {
   303     makeFile {
   304 	for {set i 0} {$i < 5} {incr i} {
   305 	    namespace eval bar {}
   306 	    namespace delete bar
   307 	}
   308 	puts 0
   309     } source.file
   310     set res [catch {
   311 	exec [interpreter] source.file 
   312     }]
   313     catch {removeFile source.file}
   314     set res
   315 } 0
   316 # Test to catch buffer overrun in TclCompileTokens from buf 530320
   317 test compile-12.3 {check for a buffer overrun} {
   318     proc crash {} {
   319 	puts $array([expr {a+2}])
   320     }
   321     list [catch crash msg] $msg
   322 } {1 {syntax error in expression "a+2": variable references require preceding $}}
   323 
   324 test compile-12.4 {TclCleanupLiteralTable segfault} {
   325     # Tcl Bug 1001997
   326     # Here, we're trying to test a case that causes a crash in
   327     # TclCleanupLiteralTable.  The conditions that we're trying to
   328     # establish are:
   329     # - TclCleanupLiteralTable is attempting to clean up a bytecode
   330     #   object in the literal table.
   331     # - The bytecode object in question contains the only reference
   332     #   to another literal.
   333     # - The literal in question is in the same hash bucket as the bytecode
   334     #   object, and immediately follows it in the chain.
   335     # Since newly registered literals are added at the FRONT of the
   336     # bucket chains, and since the bytecode object is registered before
   337     # its literals, this is difficult to achieve.  What we do is:
   338     #  (a) do a [namespace eval] of a string that's calculated to
   339     #      hash into the same bucket as a literal that it contains.
   340     #      In this case, the script and the variable 'bugbug' 
   341     #      land in the same bucket.
   342     #  (b) do a [namespace eval] of a string that contains enough
   343     #      literals to force TclRegisterLiteral to rebuild the global
   344     #      literal table.  The newly created hash buckets will contain
   345     #      the literals, IN REVERSE ORDER, thus putting the bytecode
   346     #      immediately ahead of 'bugbug' and 'bug4345bug'.  The bytecode
   347     #      object will contain the only references to those two literals.
   348     #  (c) Delete the interpreter to invoke TclCleanupLiteralTable
   349     #      and tickle the bug.
   350     proc foo {} {
   351     set i [interp create]
   352     $i eval {
   353         namespace eval ::w {concat 4649; variable bugbug}
   354         namespace eval ::w {
   355             concat x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 \
   356                 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 \
   357                 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 \
   358                 x31 x32 X33 X34 X35 X36 X37 X38 X39 X40 \
   359                 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 \
   360                 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 \
   361                 x61 x62 x63 x64
   362             concat y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 \
   363                 y11 y12 y13 y14 y15 y16 y17 y18 y19 y20 \
   364                 y21 y22 y23 y24 y25 y26 y27 y28 y29 y30 \
   365                 y31 y32 Y33 Y34 Y35 Y36 Y37 Y38 Y39 Y40 \
   366                 y41 y42 y43 y44 y45 y46 y47 y48 y49 y50 \
   367                 y51 y52 y53 y54 y55 y56 y57 y58 y59 y60 \
   368                 y61 y62 y63 y64
   369             concat z1 z2 z3 z4 z5 z6 z7 z8 z9 z10 \
   370                 z11 z12 z13 z14 z15 z16 z17 z18 z19 z20 \
   371                 z21 z22 z23 z24 z25 z26 z27 z28 z29 z30 \
   372                 z31 z32
   373         }
   374     }
   375     interp delete $i; # must not crash
   376     return ok
   377     }
   378     foo
   379 } ok
   380 
   381 
   382 # Special test for underestimating the maxStackSize required for a
   383 # compiled command. A failure will cause a segfault in the child 
   384 # process.
   385 test compile-13.1 {testing underestimate of maxStackSize in list cmd} {exec} {
   386     set body {set x [list}
   387     for {set i 0} {$i < 3000} {incr i} {
   388 	append body " $i"
   389     }
   390     append body {]; puts OK}
   391     regsub BODY {proc crash {} {BODY}; crash} $body script
   392     list [catch {exec [interpreter] << $script} msg] $msg
   393 } {0 OK}
   394 
   395 # Special test for compiling tokens from a copy of the source
   396 # string [Bug #599788]
   397 test compile-14.1 {testing errors in element name; segfault?} {} {
   398      catch {set a([error])} msg1
   399      catch {set bubba([join $abba $jubba]) $vol} msg2
   400      list $msg1 $msg2
   401 } {{wrong # args: should be "error message ?errorInfo? ?errorCode?"} {can't read "abba": no such variable}}
   402 
   403 # Next 4 tests cover Tcl Bug 633204
   404 test compile-15.1 {proper TCL_RETURN code from [return]} {
   405     proc p {} {catch return}
   406     set result [p]
   407     rename p {}
   408     set result
   409 } 2
   410 test compile-15.2 {proper TCL_RETURN code from [return]} {
   411     proc p {} {catch {return foo}}
   412     set result [p]
   413     rename p {}
   414     set result
   415 } 2
   416 test compile-15.3 {proper TCL_RETURN code from [return]} {
   417     proc p {} {catch {return $::tcl_library}}
   418     set result [p]
   419     rename p {}
   420     set result
   421 } 2
   422 test compile-15.4 {proper TCL_RETURN code from [return]} {
   423     proc p {} {catch {return [info library]}}
   424     set result [p]
   425     rename p {}
   426     set result
   427 } 2
   428 test compile-15.5 {proper TCL_RETURN code from [return]} {
   429     proc p {} {catch {set a 1}; return}
   430     set result [p]
   431     rename p {}
   432     set result
   433 } ""
   434 
   435 
   436 # cleanup
   437 catch {rename p ""}
   438 catch {namespace delete test_ns_compile}
   439 catch {unset x}
   440 catch {unset y}
   441 catch {unset a}
   442 ::tcltest::cleanupTests
   443 return