diff options
Diffstat (limited to 'tests/NRE.test')
-rw-r--r-- | tests/NRE.test | 476 |
1 files changed, 0 insertions, 476 deletions
diff --git a/tests/NRE.test b/tests/NRE.test index 4a279bc..e69de29 100644 --- a/tests/NRE.test +++ b/tests/NRE.test @@ -1,476 +0,0 @@ -# Commands covered: proc, apply, [interp alias], [namespce import], tailcall -# -# This file contains a collection of tests for the non-recursive executor that -# avoids recursive calls to TEBC. -# -# Copyright (c) 2008 by Miguel Sofer. -# -# See the file "license.terms" for information on usage and redistribution -# of this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: NRE.test,v 1.10 2008/08/01 00:44:05 msofer Exp $ - -if {[lsearch [namespace children] ::tcltest] == -1} { - package require tcltest - namespace import -force ::tcltest::* -} - -testConstraint tailcall [llength [info commands ::tcl::unsupported::tailcall]] -testConstraint testnrelevels [llength [info commands testnrelevels]] - -# -# The tests that risked blowing the C stack on failure have been removed: we -# can now actually measure using testnrelevels. -# - -if {[testConstraint testnrelevels]} { - namespace eval testnre { - # - # [testnrelevels] returns a 6-list with: C-stack depth, iPtr->numlevels, - # cmdFrame level, callFrame level, tosPtr and callback depth - # - variable last [testnrelevels] - proc depthDiff {} { - variable last - set depth [testnrelevels] - set res {} - foreach t $depth l $last { - lappend res [expr {$t-$l}] - } - set last $depth - return $res - } - proc setabs {} { - uplevel 1 variable abs -[lindex [testnrelevels] 0] - } - - variable body0 { - set x [depthDiff] - if {[incr i] > 10} { - variable abs - incr abs [lindex [testnrelevels] 0] - return [list [lrange $x 0 3] $abs] - } - } - proc makebody txt { - variable body0 - return "$body0; $txt" - } - namespace export * - } - namespace import testnre::* -} - -test NRE-1.1 {self-recursive procs} -setup { - proc a i [makebody {a $i}] -} -body { - setabs - a 0 -} -cleanup { - rename a {} - unset abs -} -result {{0 1 1 1} 0} - -test NRE-1.2 {self-recursive lambdas} -setup { - set a [list i [makebody {apply $::a $i}]] -} -body { - setabs - apply $a 0 -} -cleanup { - unset a abs -} -result {{0 1 1 1} 0} - -test NRE-1.3 {mutually recursive procs and lambdas} -setup { - proc a i { - apply $::b [incr i] - } - set b [list i [makebody {a $i}]] -} -body { - setabs - a 0 -} -cleanup { - rename a {} - unset b abs -} -result {{0 2 2 2} 0} - -# -# Test that aliases are non-recursive -# - -test NRE-2.1 {alias is not recursive} -setup { - proc a i [makebody {b $i}] - interp alias {} b {} a -} -body { - setabs - a 0 -} -cleanup { - rename a {} - rename b {} - unset abs -} -result {{0 2 1 1} 0} - -# -# Test that imports are non-recursive -# - -test NRE-3.1 {imports are not recursive} -setup { - namespace eval foo { - setabs - namespace export a - } - proc foo::a i [makebody {::a $i}] - namespace import foo::a -} -body { - a 0 -} -cleanup { - rename a {} - namespace delete ::foo -} -result {{0 2 1 1} 0} - -test NRE-4.1 {ensembles are not recursive} -setup { - proc a i [makebody {b foo $i}] - namespace ensemble create \ - -command b \ - -map [list foo a] -} -body { - setabs - a 0 -} -cleanup { - rename a {} - rename b {} - unset abs -} -result {{0 2 1 1} 0} - -test NRE-5.1 {[namespace eval] is not recursive} -setup { - namespace eval ::foo { - setabs - } - proc foo::a i [makebody {namespace eval ::foo [list a $i]}] -} -body { - ::foo::a 0 -} -cleanup { - namespace delete ::foo -} -result {{0 2 2 2} 0} - -test NRE-5.2 {[namespace eval] is not recursive} -setup { - namespace eval ::foo { - setabs - } - proc foo::a i [makebody {namespace eval ::foo "set x $i; a $i"}] -} -body { - foo::a 0 -} -cleanup { - namespace delete ::foo -} -result {{0 2 2 2} 0} - -test NRE-6.1 {[uplevel] is not recursive} -setup { - proc a i [makebody {uplevel 1 [list a $i]}] -} -body { - setabs - a 0 -} -cleanup { - rename a {} - unset abs -} -result {{0 2 2 0} 0} - -test NRE-6.2 {[uplevel] is not recursive} -setup { - setabs - proc a i [makebody {uplevel 1 "set x $i; a $i"}] -} -body { - a 0 -} -cleanup { - rename a {} - unset abs -} -result {{0 2 2 0} 0} - -test NRE-7.1 {[catch] is not recursive} -setup { - setabs - proc a i [makebody {uplevel 1 "catch {a $i} msg; set msg"}] -} -body { - a 0 -} -cleanup { - rename a {} - unset x abs -} -result {{0 3 3 0} 0} - -# -# Basic TclOO tests -# - -test NRE-oo.1 {really deep calls in oo - direct} -setup { - oo::object create foo - oo::objdefine foo method bar i [makebody {foo bar $i}] -} -body { - setabs - foo bar 0 -} -cleanup { - foo destroy - unset abs -} -result {{0 1 1 1} 0} - -test NRE-oo.2 {really deep calls in oo - call via [self]} -setup { - oo::object create foo - oo::objdefine foo method bar i [makebody {[self] bar $i}] -} -body { - setabs - foo bar 0 -} -cleanup { - foo destroy - unset abs -} -result {{0 1 1 1} 0} - -test NRE-oo.3 {really deep calls in oo - private calls} -setup { - oo::object create foo - oo::objdefine foo method bar i [makebody {my bar $i}] -} -body { - setabs - foo bar 0 -} -cleanup { - foo destroy - unset abs -} -result {{0 1 1 1} 0} - -test NRE-oo.4 {really deep calls in oo - overriding} -setup { - oo::class create foo { - method bar i [makebody {my bar $i}] - } - oo::class create boo { - superclass foo - method bar i [makebody {next $i}] - } -} -body { - setabs - [boo new] bar 0 -} -cleanup { - foo destroy - unset abs -} -result {{0 1 1 1} 0} - -test NRE-oo.5 {really deep calls in oo - forwards} -setup { - oo::object create foo - set body [makebody {my boo $i}] - oo::objdefine foo " - method bar i {$body} - forward boo ::foo bar - " -} -body { - setabs - foo bar 0 -} -cleanup { - foo destroy - unset abs -} -result {{0 2 1 1} 0} - - -# -# NASTY BUG found by tcllib's interp package -# - -test NRE-X.1 {eval in wrong interp} { - set i [interp create] - set res [$i eval { - set x {namespace children ::} - set y [list namespace children ::] - namespace delete {*}[{*}$y] - set j [interp create] - $j eval {namespace delete {*}[namespace children ::]} - namespace eval foo {} - set res [list [eval $x] [eval $y] [$j eval $x] [$j eval $y]] - interp delete $j - set res - }] - interp delete $i - set res -} {::foo ::foo {} {}} - -# -# Test tailcalls -# - -if {[testConstraint tailcall]} { - namespace eval tcl::unsupported namespace export tailcall - namespace import tcl::unsupported::tailcall -} - -test NRE-T.0 {tailcall is constant space} -constraints {tailcall} -setup { - proc a i { - if {[incr i] > 10} { - return [depthDiff] - } - depthDiff - tailcall a $i - } -} -body { - a 0 -} -cleanup { - rename a {} -} -result {0 0 0 0 0 0} - -test NRE-T.1 {tailcall} -constraints {tailcall} -body { - namespace eval a { - variable x *::a - proc xset {} { - set tmp {} - set ns {[namespace current]} - set level [info level] - for {set i 0} {$i <= [info level]} {incr i} { - uplevel #$i "set x $i$ns" - lappend tmp "$i [info level $i]" - } - lrange $tmp 1 end - } - proc foo {} {tailcall xset; set x noreach} - } - namespace eval b { - variable x *::b - proc xset args {error b::xset} - proc moo {} {set x 0; variable y [::a::foo]; set x} - } - variable x *:: - proc xset args {error ::xset} - list [::b::moo] | $x $a::x $b::x | $::b::y -} -cleanup { - unset x - rename xset {} - namespace delete a b -} -result {1::b | 0:: *::a *::b | {{1 ::b::moo} {2 xset}}} - - -test NRE-T.2 {tailcall in non-proc} -constraints {tailcall} -body { - list [catch {namespace eval a [list tailcall set x 1]} msg] $msg -} -result {1 {tailcall can only be called from a proc or lambda}} - -test NRE-T.3 {tailcall falls off tebc} -constraints {tailcall} -body { - unset -nocomplain x - proc foo {} {tailcall set x 1} - list [catch foo msg] $msg [set x] -} -cleanup { - rename foo {} - unset x -} -result {0 1 1} - -test NRE-T.4 {tailcall falls off tebc} -constraints {tailcall} -body { - set x 2 - proc foo {} {tailcall set x 1} - foo - set x -} -cleanup { - rename foo {} - unset x -} -result 1 - -test NRE-T.5 {tailcall falls off tebc} -constraints {tailcall} -body { - set x 2 - namespace eval bar { - variable x 3 - proc foo {} {tailcall set x 1} - } - bar::foo - list $x $bar::x -} -cleanup { - unset x - namespace delete bar -} -result {1 3} - -test NRE-T.6 {tailcall does remove callframes} -constraints {tailcall} -body { - proc foo {} {info level} - proc moo {} {tailcall foo} - proc boo {} {expr {[moo] - [info level]}} - boo -} -cleanup { - rename foo {} - rename moo {} - rename boo {} -} -result 1 - -test NRE-T.7 {tailcall does return} -constraints {tailcall} -setup { - namespace eval ::foo { - variable res {} - proc a {} { - variable res - append res a - tailcall set x 1 - append res a - } - proc b {} { - variable res - append res b - a - append res b - } - proc c {} { - variable res - append res c - b - append res c - } - } -} -body { - namespace eval ::foo c -} -cleanup { - namespace delete ::foo -} -result cbabc - -test NRE-T.8 {tailcall tailcall} -constraints {tailcall} -setup { - namespace eval ::foo { - variable res {} - proc a {} { - variable res - append res a - tailcall tailcall set x 1 - append res a - } - proc b {} { - variable res - append res b - a - append res b - } - proc c {} { - variable res - append res c - b - append res c - } - } -} -body { - namespace eval ::foo c -} -cleanup { - namespace delete ::foo -} -match glob -result *tailcall* -returnCodes error - -test NRE-T.9 {tailcall factorial} -constraints {tailcall} -setup { - proc fact {n {b 1}} { - if {$n == 1} { - return $b - } - tailcall fact [expr {$n-1}] [expr {$n*$b}] - } -} -body { - list [fact 1] [fact 5] [fact 10] [fact 15] -} -cleanup { - rename fact {} -} -result {1 120 3628800 1307674368000} - - -namespace forget tcl::unsupported::tailcall - -# -# Test that ensembles are non-recursive -# - - - -# cleanup -::tcltest::cleanupTests - -if {[testConstraint testnrelevels]} { - namespace forget testnre::* - namespace delete testnre -} - -if {[testConstraint tailcall]} { - namespace forget tcl::unsupported::tailcall -} - -return |