| 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: | 
|---|