| [25] | 1 | # Tests that the stack size is big enough for the application. | 
|---|
 | 2 | # | 
|---|
 | 3 | # This file contains a collection of tests for one or more of the Tcl | 
|---|
 | 4 | # built-in commands.  Sourcing this file into Tcl runs the tests and | 
|---|
 | 5 | # generates output for errors.  No output means no errors were found. | 
|---|
 | 6 | # | 
|---|
 | 7 | # Copyright (c) 1998-2000 Ajuba Solutions. | 
|---|
 | 8 | # | 
|---|
 | 9 | # See the file "license.terms" for information on usage and redistribution | 
|---|
 | 10 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. | 
|---|
 | 11 | # | 
|---|
 | 12 | # RCS: @(#) $Id: stack.test,v 1.22 2007/12/13 15:26:07 dgp Exp $ | 
|---|
 | 13 |  | 
|---|
 | 14 | if {[lsearch [namespace children] ::tcltest] == -1} { | 
|---|
 | 15 |     package require tcltest 2 | 
|---|
 | 16 |     namespace import -force ::tcltest::* | 
|---|
 | 17 | } | 
|---|
 | 18 |  | 
|---|
 | 19 | # Note that a failure in this test results in a crash of the executable. | 
|---|
 | 20 | # In order to avoid that, we do a basic check of the current stacksize. | 
|---|
 | 21 | # This size can be changed with ulimit (ksh/bash/sh) or limit (csh/tcsh). | 
|---|
 | 22 |  | 
|---|
 | 23 | # This doesn't catch all cases, for example threads of lower stacksize | 
|---|
 | 24 | # can still squeak through.  A core check is really needed. -- JH | 
|---|
 | 25 |  | 
|---|
 | 26 | testConstraint minStack2400 1 | 
|---|
 | 27 | if {[testConstraint unix]} { | 
|---|
 | 28 |     set stackSize [exec /bin/sh -c "ulimit -s"] | 
|---|
 | 29 |     if {[string is integer $stackSize] && ($stackSize < 2400)} { | 
|---|
 | 30 |         puts stderr "WARNING: the default application stacksize of $stackSize\ | 
|---|
 | 31 |                 may cause Tcl to\ncrash due to stack overflow before the\ | 
|---|
 | 32 |                 recursion limit is reached.\nA minimum stacksize of 2400\ | 
|---|
 | 33 |                 kbytes is recommended.\nSkipping infinite recursion test." | 
|---|
 | 34 |         testConstraint minStack2400 0 | 
|---|
 | 35 |     } | 
|---|
 | 36 | } | 
|---|
 | 37 |  | 
|---|
 | 38 | # | 
|---|
 | 39 | # Custom match to detect a stack overflow independently of the mechanism that | 
|---|
 | 40 | # triggered the error. | 
|---|
 | 41 | # | 
|---|
 | 42 |  | 
|---|
 | 43 | customMatch stackOverflow StackOverflow | 
|---|
 | 44 | proc StackOverflow {- res} { | 
|---|
 | 45 |     set msgList [list \ | 
|---|
 | 46 |             "too many nested evaluations (infinite loop?)"\ | 
|---|
 | 47 |             "out of stack space (infinite loop?)"] | 
|---|
 | 48 |     expr {$res in $msgList} | 
|---|
 | 49 | } | 
|---|
 | 50 |  | 
|---|
 | 51 | test stack-1.1 {maxNestingDepth reached on infinite recursion} -constraints { | 
|---|
 | 52 |     minStack2400 | 
|---|
 | 53 | } -body { | 
|---|
 | 54 |     # do this in a sub process in case it segfaults | 
|---|
 | 55 |     exec [interpreter] << { | 
|---|
 | 56 |         proc recurse {} { recurse } | 
|---|
 | 57 |         catch { recurse } rv | 
|---|
 | 58 |         puts $rv | 
|---|
 | 59 |     } | 
|---|
 | 60 | } -match stackOverflow | 
|---|
 | 61 |  | 
|---|
 | 62 | test stack-2.1 {maxNestingDepth reached on infinite recursion} -constraints { | 
|---|
 | 63 |     minStack2400 | 
|---|
 | 64 | } -body { | 
|---|
 | 65 |     # do this in a sub process in case it segfaults | 
|---|
 | 66 |     exec [interpreter] << { | 
|---|
 | 67 |         interp alias {} unknown {} notaknownproc | 
|---|
 | 68 |         catch { unknown } msg | 
|---|
 | 69 |         puts $msg | 
|---|
 | 70 |     } | 
|---|
 | 71 | } -match stackOverflow  | 
|---|
 | 72 |      | 
|---|
 | 73 | # Make sure that there is enough stack to run regexp even if we're | 
|---|
 | 74 | # close to the recursion limit. [Bug 947070] [Patch 746378] | 
|---|
 | 75 | test stack-3.1 {enough room for regexp near recursion limit} -body { | 
|---|
 | 76 |     # do this in a sub process in case it segfaults | 
|---|
 | 77 |     exec [interpreter] << { | 
|---|
 | 78 |         interp recursionlimit {} 10000 | 
|---|
 | 79 |         set depth 0 | 
|---|
 | 80 |         proc a { max } { | 
|---|
 | 81 |             if { [info level] < $max } { | 
|---|
 | 82 |                 set ::depth [info level] | 
|---|
 | 83 |                 a $max | 
|---|
 | 84 |             } else { | 
|---|
 | 85 |                 regexp {^ ?} x | 
|---|
 | 86 |             } | 
|---|
 | 87 |         } | 
|---|
 | 88 |         catch { a 10001 } | 
|---|
 | 89 |         set depth2 $depth | 
|---|
 | 90 |         puts [list [a $depth] [expr { $depth2 - $depth }]] | 
|---|
 | 91 |     } | 
|---|
 | 92 | } -result {1 1} | 
|---|
 | 93 |  | 
|---|
 | 94 | # cleanup | 
|---|
 | 95 | ::tcltest::cleanupTests | 
|---|
 | 96 | return | 
|---|
 | 97 |  | 
|---|
 | 98 | # Local Variables: | 
|---|
 | 99 | # mode: tcl | 
|---|
 | 100 | # End: | 
|---|