OpenFPGA/libs/EXTERNAL/tcl8.6.12/tests/error.test

1212 lines
37 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Commands covered: error, catch, throw, try
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
testConstraint memory [llength [info commands memory]]
customMatch pairwise {apply {{a b} {
string equal [lindex $b 0] [lindex $b 1]
}}}
namespace eval ::tcl::test::error {
if {[testConstraint memory]} {
proc getbytes {} {
set lines [split [memory info] \n]
return [lindex $lines 3 3]
}
proc leaktest {script {iterations 3}} {
set end [getbytes]
for {set i 0} {$i < $iterations} {incr i} {
uplevel 1 $script
set tmp $end
set end [getbytes]
}
return [expr {$end - $tmp}]
}
}
proc foo {} {
global errorInfo
set a [catch {format [error glorp2]} b]
error {Human-generated}
}
proc foo2 {} {
global errorInfo
set a [catch {format [error glorp2]} b]
error {Human-generated} $errorInfo
}
# Catch errors occurring in commands and errors from "error" command
test error-1.1 {simple errors from commands} {
catch {format [string index]} b
} 1
test error-1.2 {simple errors from commands} {
catch {format [string index]} b
set b
} {wrong # args: should be "string index string charIndex"}
test error-1.3 {simple errors from commands} {
catch {format [string index]} b
set ::errorInfo
# This used to return '... while executing ...', but string index is fully
# compiled as of 8.4a3
} {wrong # args: should be "string index string charIndex"
while executing
"string index"}
test error-1.4 {simple errors from commands} {
catch {error glorp} b
} 1
test error-1.5 {simple errors from commands} {
catch {error glorp} b
set b
} glorp
test error-1.6 {simple errors from commands} {
catch {catch a b c d} b
} 1
test error-1.7 {simple errors from commands} {
catch {catch a b c d} b
set b
} {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"}
test error-1.8 {simple errors from commands} {
# This test is non-portable: it generates a memory fault on machines like
# DEC Alphas (infinite recursion overflows stack?)
#
# That claims sounds like a bug to be fixed rather than a portability
# problem. Anyhow, I believe it's out of date (bug's been fixed) so this
# test is re-enabled.
proc p {} {
uplevel 1 catch p error
}
p
} 0
# Check errors nested in procedures. Also check the optional argument to
# "error" to generate a new error trace.
test error-2.1 {errors in nested procedures} {
catch foo b
} 1
test error-2.2 {errors in nested procedures} {
catch foo b
set b
} {Human-generated}
test error-2.3 {errors in nested procedures} {
catch foo b
set ::errorInfo
} {Human-generated
while executing
"error {Human-generated}"
(procedure "foo" line 4)
invoked from within
"foo"}
test error-2.4 {errors in nested procedures} {
catch foo2 b
} 1
test error-2.5 {errors in nested procedures} {
catch foo2 b
set b
} {Human-generated}
test error-2.6 {errors in nested procedures} {
catch foo2 b
set ::errorInfo
} {glorp2
while executing
"error glorp2"
(procedure "foo2" line 3)
invoked from within
"foo2"}
# Error conditions related to "catch".
test error-3.1 {errors in catch command} {
list [catch {catch} msg] $msg
} {1 {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"}}
test error-3.2 {errors in catch command} {
list [catch {catch a b c} msg] $msg
} {0 1}
test error-3.3 {errors in catch command} {
catch {unset a}
set a(0) 22
list [catch {catch {format 44} a} msg] $msg
} {1 {can't set "a": variable is array}}
catch {unset a}
# More tests related to errorInfo and errorCode
test error-4.1 {errorInfo and errorCode variables} {
list [catch {error msg1 msg2 msg3} msg] $msg $::errorInfo $::errorCode
} {1 msg1 msg2 msg3}
test error-4.2 {errorInfo and errorCode variables} {
list [catch {error msg1 {} msg3} msg] $msg $::errorInfo $::errorCode
} {1 msg1 {msg1
while executing
"error msg1 {} msg3"} msg3}
test error-4.3 {errorInfo and errorCode variables} {
list [catch {error msg1 {}} msg] $msg $::errorInfo $::errorCode
} {1 msg1 {msg1
while executing
"error msg1 {}"} NONE}
test error-4.4 {errorInfo and errorCode variables} {
set ::errorCode bogus
list [catch {error msg1} msg] $msg $::errorInfo $::errorCode
} {1 msg1 {msg1
while executing
"error msg1"} NONE}
test error-4.5 {errorInfo and errorCode variables} {
set ::errorCode bogus
list [catch {error msg1 msg2 {}} msg] $msg $::errorInfo $::errorCode
} {1 msg1 msg2 {}}
test error-4.6 {errorstack via info } -body {
proc f x {g $x$x}
proc g x {error G:$x}
catch {f 12}
info errorstack
} -match glob -result {INNER * CALL {g 1212} CALL {f 12} UP 1}
test error-4.7 {errorstack via options dict } -body {
proc f x {g $x$x}
proc g x {error G:$x}
catch {f 12} m d
dict get $d -errorstack
} -match glob -result {INNER * CALL {g 1212} CALL {f 12} UP 1}
test error-4.8 {errorstack from exec traces} -body {
proc foo args {}
proc goo {} foo
trace add execution foo enter {error bar;#}
catch goo m d
dict get $d -errorstack
} -cleanup {
rename goo {}; rename foo {}
unset -nocomplain m d
} -result {INNER {error bar} CALL goo UP 1}
# Errors in error command itself
test error-5.1 {errors in error command} {
list [catch {error} msg] $msg
} {1 {wrong # args: should be "error message ?errorInfo? ?errorCode?"}}
test error-5.2 {errors in error command} {
list [catch {error a b c d} msg] $msg
} {1 {wrong # args: should be "error message ?errorInfo? ?errorCode?"}}
# Make sure that catch resets error information
test error-6.1 {catch must reset error state} {
catch {error outer [catch {error inner inner.errorInfo inner.errorCode}]}
list $::errorCode $::errorInfo
} {NONE 1}
test error-6.2 {catch must reset error state} {
catch {error outer [catch {return -level 0 -code error -errorcode BUG}]}
list $::errorCode $::errorInfo
} {NONE 1}
test error-6.3 {catch must reset error state} {
set ::errorCode BUG
catch {error outer [catch set]}
list $::errorCode $::errorInfo
} {NONE 1}
test error-6.4 {catch must reset error state} {
catch {error [catch {error foo bar baz}] 1}
list $::errorCode $::errorInfo
} {NONE 1}
test error-6.5 {catch must reset error state} {
catch {error [catch {return -level 0 -code error -errorcode BUG}] 1}
list $::errorCode $::errorInfo
} {NONE 1}
test error-6.6 {catch must reset error state} {
catch {return -level 0 -code error -errorinfo [catch {error foo bar baz}]}
list $::errorCode $::errorInfo
} {NONE 1}
test error-6.7 {catch must reset error state} {
proc foo {} {
return -code error -errorinfo [catch {error foo bar baz}]
}
catch foo
list $::errorCode
} {NONE}
test error-6.8 {catch must reset error state} {
catch {return -level 0 -code error [catch {error foo bar baz}]}
list $::errorCode
} {NONE}
test error-6.9 {catch must reset error state} {
proc foo {} {
return -code error [catch {error foo bar baz}]
}
catch foo
list $::errorCode
} {NONE}
test error-6.10 {catch must reset errorstack} -body {
proc f x {g $x$x}
proc g x {error G:$x}
catch {f 12}
set e1 [info errorstack]
catch {f 13}
set e2 [info errorstack]
list $e1 $e2
} -match glob -result {{INNER * CALL {g 1212} CALL {f 12} UP 1} {INNER * CALL {g 1313} CALL {f 13} UP 1}}
test error-7.1 {Bug 1397843} -body {
variable cmds
proc EIWrite args {
variable cmds
lappend cmds [lindex [info level -2] 0]
}
proc BadProc {} {
set i a
incr i
}
trace add variable ::errorInfo write [namespace code EIWrite]
catch BadProc
trace remove variable ::errorInfo write [namespace code EIWrite]
set cmds
} -match glob -result {*BadProc*}
# throw tests
test error-8.1 {throw produces error 1 at level 0} {
catch { throw FOO bar }
} {1}
test error-8.2 {throw behaves as error does at level 0} {
catch { throw FOO bar } em1 opts1
catch { error bar {} FOO } em2 opts2
dict set opts1 -result $em1
dict set opts2 -result $em2
foreach key {-code -level -result -errorcode} {
if { [dict get $opts1 $key] ne [dict get $opts2 $key] } {
error "error/throw outcome differs on '$key'"
}
}
} {}
test error-8.3 {throw produces error 1 at level > 0} {
proc throw_foo {} {
throw FOO bar
}
catch { throw_foo }
} {1}
test error-8.4 {throw behaves as error does at level > 0} {
proc throw_foo {} {
throw FOO bar
}
proc error_foo {} {
error bar {} FOO
}
catch { throw_foo } em1 opts1
catch { error_foo } em2 opts2
dict set opts1 -result $em1
dict set opts2 -result $em2
foreach key {-code -level -result -errorcode} {
if { [dict get $opts1 $key] ne [dict get $opts2 $key] } {
error "error/throw outcome differs on '$key'"
}
}
} {}
test error-8.5 {throw syntax checks} -returnCodes error -body {
throw
} -result {wrong # args: should be "throw type message"}
test error-8.6 {throw syntax checks} -returnCodes error -body {
throw a
} -result {wrong # args: should be "throw type message"}
test error-8.7 {throw syntax checks} -returnCodes error -body {
throw a b c
} -result {wrong # args: should be "throw type message"}
test error-8.8 {throw syntax checks} -returnCodes error -body {
throw "not a \{ list" foo
} -result {unmatched open brace in list}
test error-8.9 {throw syntax checks} -returnCodes error -body {
throw {} foo
} -result {type must be non-empty list}
test error-8.10 {Bug 33b7abb8a2: throw stack usage} -returnCodes error -body {
apply {code {throw $code foo}} {}
} -result {type must be non-empty list}
test error-8.11 {Bug 7174354ecb: throw error message} -returnCodes error -body {
throw {not {}a list} x[]y
} -result {list element in braces followed by "a" instead of space}
# simple try tests: body completes with code ok
test error-9.1 {try (ok, empty result) with no handlers} {
try list
} {}
test error-9.2 {try (ok, non-empty result) with no handlers} {
try { list a b c }
} {a b c}
test error-9.3 {try (ok, non-empty result) with trap handler} {
try { list a b c } trap {} {} { list d e f }
} {a b c}
test error-9.4 {try (ok, non-empty result) with on handler} {
try { list a b c } on break {} { list d e f }
} {a b c}
test error-9.5 {try (ok, non-empty result) with on ok handler} {
try { list a b c } on ok {} { list d e f }
} {d e f}
# simple try tests - "on" handler matching
test error-10.1 {try with on ok} {
try { list a b c } on ok {} { list d e f }
} {d e f}
test error-10.2 {try with on 0} {
try { list a b c } on 0 {} { list d e f }
} {d e f}
test error-10.3 {try with on error (using error)} {
try { error a b c } on error {} { list d e f }
} {d e f}
test error-10.4 {try with on error (using return -code)} {
try { return -level 0 -code 1 a } on error {} { list d e f }
} {d e f}
test error-10.5 {try with on error (using throw)} {
try { throw c a } on error {} { list d e f }
} {d e f}
test error-10.6 {try with on 1 (using error)} {
try { error a b c } on 1 {} { list d e f }
} {d e f}
test error-10.7 {try with on return} {
try { return [list a b c] } on return {} { list d e f }
} {d e f}
test error-10.8 {try with on break} {
try { break } on break {} { list d e f }
} {d e f}
test error-10.9 {try with on continue} {
try { continue } on continue {} { list d e f }
} {d e f}
test error-10.10 {try with on for arbitrary (decimal) return code} {
try { return -level 0 -code 123456 } on 123456 {} { list d e f }
} {d e f}
test error-10.11 {try with on for arbitrary (hex) return code} {
try { return -level 0 -code 0x123456 } on 0x123456 {} { list d e f }
} {d e f}
test error-10.12 {try with on for arbitrary return code (mixed number representations)} {
try { return -level 0 -code 0x10 } on 16 {} { list d e f }
} {d e f}
# simple try tests - "trap" handler matching
test error-11.1 {try with trap all} {
try { throw FOO bar } trap {} {} { list d e f }
} {d e f}
test error-11.2 {try with trap (exact)} {
try { throw FOO bar } trap {FOO} {} { list d e f }
} {d e f}
test error-11.3 {try with trap (prefix 1)} {
try { throw [list FOO A B C D] bar } trap {FOO} {} { list d e f }
} {d e f}
test error-11.4 {try with trap (prefix 2)} {
try { throw [list FOO A B C D] bar } trap {FOO A} {} { list d e f }
} {d e f}
test error-11.5 {try with trap (prefix 3)} {
try { throw [list FOO A B C D] bar } trap {FOO A B} {} { list d e f }
} {d e f}
test error-11.6 {try with trap (prefix 4)} {
try { throw [list FOO A B C D] bar } trap {FOO A B C} {} { list d e f }
} {d e f}
test error-11.7 {try with trap (exact, 5 elements)} {
try { throw [list FOO A B C D] bar } trap {FOO A B C D} {} { list d e f }
} {d e f}
# simple try tests - variable assignment and result handling
test error-12.1 {try with no variable assignment in on handler} {
try { throw FOO bar } on error {} { list d e f }
} {d e f}
test error-12.2 {try with result variable assignment in on handler} {
try { throw FOO bar } on error {res} { set res }
} {bar}
test error-12.3 {try with result variable assignment in on handler, var remains in scope} {
try { throw FOO bar } on error {res} { list d e f }
set res
} {bar}
test error-12.4 {try with result/opts variable assignment in on handler} {
try {
throw FOO bar
} on error {res opts} {
set r "$res,[dict get $opts -errorcode]"
}
} {bar,FOO}
test error-12.5 {try with result/opts variable assignment in on handler, vars remain in scope} {
try { throw FOO bar } on error {res opts} { list d e f }
set r "$res,[dict get $opts -errorcode]"
} {bar,FOO}
test error-12.6 {try result is propagated if no matching handler} {
try { list a b c } on error {} { list d e f }
} {a b c}
test error-12.7 {handler result is propagated if handler executes} {
try { throw FOO bar } on error {} { list d e f }
} {d e f}
# negative case try tests - bad args to try
test error-13.1 {try with no arguments} -body {
# warning: error message may change
try
} -returnCodes error -match glob -result {wrong # args: *}
test error-13.2 {try with body only (ok)} {
try list
} {}
test error-13.3 {try with missing finally body} -body {
# warning: error message may change
try list finally
} -returnCodes error -match glob -result {wrong # args to finally clause: *}
test error-13.4 {try with bad handler keyword} -body {
# warning: error message may change
try list then a b c
} -returnCodes error -match glob -result {bad handler *}
test error-13.5 {try with partial handler #1} -body {
# warning: error message may change
try list on
} -returnCodes error -match glob -result {wrong # args to on clause: *}
test error-13.6 {try with partial handler #2} -body {
# warning: error message may change
try list on error
} -returnCodes error -match glob -result {wrong # args to on clause: *}
test error-13.7 {try with partial handler #3} -body {
# warning: error message may change
try list on error {em opts}
} -returnCodes error -match glob -result {wrong # args to on clause: *}
test error-13.8 {try with multiple handlers and finally (ok)} {
try list on error {} {} trap {} {} {} finally {}
} {}
test error-13.9 {last handler body can't be a fallthrough #1} -body {
try list on error {} {} on break {} -
} -returnCodes error -result {last non-finally clause must not have a body of "-"}
test error-13.10 {last handler body can't be a fallthrough #2} -body {
try list on error {} {} on break {} - finally { list d e f }
} -returnCodes error -result {last non-finally clause must not have a body of "-"}
# try tests - multiple handlers (left-to-right matching, only one runs)
test error-14.1 {try with multiple handlers (only one matches) #1} {
try { throw FOO bar } on ok {} { list a b c } trap FOO {} { list d e f }
} {d e f}
test error-14.2 {try with multiple handlers (only one matches) #2} {
try { throw FOO bar } trap FOO {} { list d e f } on ok {} { list a b c }
} {d e f}
test error-14.3 {try with multiple handlers (only one matches) #3} {
try {
throw FOO bar
} on break {} {
list x y z
} trap FOO {} {
list d e f
} on ok {} {
list a b c
}
} {d e f}
test error-14.4 {try with multiple matching handlers (only the first in left-to-right order runs) #1} {
try { throw FOO bar } on error {} { list a b c } trap FOO {} { list d e f }
} {a b c}
test error-14.5 {try with multiple matching handlers (only the first in left-to-right order runs) #2} {
try { throw FOO bar } trap FOO {} { list d e f } on error {} { list a b c }
} {d e f}
test error-14.6 {try with multiple matching handlers (only the first in left-to-right order runs) #3} {
try { throw FOO bar } trap {} {} { list d e f } on 1 {} { list a b c }
} {d e f}
test error-14.7 {try with multiple matching handlers (only the first in left-to-right order runs) #4} {
try { throw FOO bar } on 1 {} { list a b c } trap {} {} { list d e f }
} {a b c}
test error-14.8 {try with handler-of-last-resort "trap {}"} {
try { throw FOO bar } trap FOX {} { list a b c } trap {} {} { list d e f }
} {d e f}
test error-14.9 {try with handler-of-last-resort "on error"} {
try { foo } trap FOX {} { list a b c } on error {} { list d e f }
} {d e f}
# try tests - propagation (no matching handlers)
test error-15.1 {try with no handler (ok result propagates)} {
try { list a b c }
} {a b c}
test error-15.2 {try with no matching handler (ok result propagates)} {
try { list a b c } on error {} { list d e f }
} {a b c}
test error-15.3 {try with no handler (error result propagates)} -body {
try { throw FOO bar }
} -returnCodes error -result {bar}
test error-15.4 {try with no matching handler (error result propagates)} -body {
try { throw FOO bar } trap FOX {} { list a b c }
} -returnCodes error -result {bar}
test error-15.5 {try with no handler (return result propagates)} -body {
try { return bar }
} -returnCodes 2 -result {bar}
test error-15.6 {try with no matching handler (break result propagates)} -body {
try { if {1} break } on error {} { list a b c }
} -returnCodes 3 -result {}
test error-15.7 {try with no matching handler (unknown integer result propagates)} -body {
try { return -level 0 -code 123456 } trap {} {} { list a b c }
} -returnCodes 123456 -result {}
foreach level {0 1 2 3} {
foreach code {0 1 2 3 4 5} {
# Following cases have different -errorinfo; avoid false alarms
# TODO: examine whether these difference are as they ought to be.
if {$level == 0 && $code == 1} continue
foreach extras {{} {-bar soom}} {
test error-15.8.$level.$code.[llength $extras] {[try] coverage} {
set script {return -level $level -code $code {*}$extras foo}
catch $script m1 o1
catch {try $script} m2 o2
set o1 [lsort -stride 2 $o1]
set o2 [lsort -stride 2 $o2]
expr {$o1 eq $o2 ? "ok" : "$o1\n\tis not equal to\n$o2"}
} ok
test error-15.9.$level.$code.[llength $extras] {[try] coverage} {
set script {return -level $level -code $code {*}$extras foo}
catch $script m1 o1
catch {try $script finally {}} m2 o2
set o1 [lsort -stride 2 $o1]
set o2 [lsort -stride 2 $o2]
expr {$o1 eq $o2 ? "ok" : "$o1\n\tis not equal to\n$o2"}
} ok
test error-15.10.$level.$code.[llength $extras] {[try] coverage} {
set script {return -level $level -code $code {*}$extras foo}
catch $script m1 o1
catch {try $script on $code {x y} {return -options $y $x}} m2 o2
set o1 [lsort -stride 2 $o1]
set o2 [lsort -stride 2 $o2]
expr {$o1 eq $o2 ? "ok" : "$o1\n\tis not equal to\n$o2"}
} ok
}
}
}
# try tests - propagation (exceptions in handlers, exception chaining)
test error-16.1 {try with successfully executed handler} {
try { throw FOO bar } trap FOO {} { list a b c }
} {a b c}
test error-16.2 {try with exception (error) in handler} -body {
try { throw FOO bar } trap FOO {} { throw BAR foo }
} -returnCodes error -result {foo}
test error-16.3 {try with exception (return) in handler} -body {
try { throw FOO bar } trap FOO {} { return BAR }
} -returnCodes 2 -result {BAR}
test error-16.4 {try with exception (break) in handler #1} -body {
try { throw FOO bar } trap FOO {} { break }
} -returnCodes 3 -result {}
test error-16.5 {try with exception (break) in handler #2} {
for { set i 5 } { $i < 10 } { incr i } {
try { throw FOO bar } trap FOO {} { break }
}
set i
} {5}
test error-16.6 {try with variable assignment and propagation #1} {
# Ensure that the handler variables preserve the exception off the
# try-body, and are not modified by the exception off the handler
catch {
try { throw FOO bar } trap FOO {em} { throw BAR baz }
}
set em
} {bar}
test error-16.7 {try with variable assignment and propagation #2} {
catch {
try { throw FOO bar } trap FOO {em opts} { throw BAR baz }
}
list $em [dict get $opts -errorcode]
} {bar FOO}
test error-16.8 {exception chaining (try=ok, handler=error)} -body {
#FIXME is the intent of this test correct?
catch {
try { list a b c } on ok {em opts} { throw BAR baz }
} tryem tryopts
list $opts [dict get $tryopts -during]
} -match pairwise -result equal
test error-16.9 {exception chaining (try=error, handler=error)} -body {
# The exception off the handler should chain to the exception off the
# try-body (using the -during option)
catch {
try { throw FOO bar } trap {} {em opts} { throw BAR baz }
} tryem tryopts
list $opts [dict get $tryopts -during]
} -match pairwise -result equal
test error-16.10 {no exception chaining when handler is successful} {
catch {
try { throw FOO bar } trap {} {em opts} { list d e f }
} tryem tryopts
dict exists $tryopts -during
} {0}
test error-16.11 {no exception chaining when handler is a non-error exception} {
catch {
try { throw FOO bar } trap {} {em opts} { break }
} tryem tryopts
dict exists $tryopts -during
} {0}
test error-16.12 {compiled try with successfully executed handler} {
apply {{} {
try { throw FOO bar } trap FOO {} { list a b c }
}}
} {a b c}
test error-16.13 {compiled try with exception (error) in handler} -body {
apply {{} {
try { throw FOO bar } trap FOO {} { throw BAR foo }
}}
} -returnCodes error -result {foo}
test error-16.14 {compiled try with exception (return) in handler} -body {
apply {{} {
list [catch {
try { throw FOO bar } trap FOO {} { return BAR }
} msg] $msg
}}
} -result {2 BAR}
test error-16.15 {compiled try with exception (break) in handler} {
apply {{} {
for { set i 5 } { $i < 10 } { incr i } {
try { throw FOO bar } trap FOO {} { break }
}
return $i
}}
} {5}
test error-16.16 {compiled try with exception (continue) in handler} {
apply {{} {
for { set i 5 } { $i < 10 } { incr i } {
try { throw FOO bar } trap FOO {} { continue }
incr i 20
}
return $i
}}
} {10}
test error-16.17 {compiled try with variable assignment and propagation #1} {
# Ensure that the handler variables preserve the exception off the
# try-body, and are not modified by the exception off the handler
apply {{} {
catch {
try { throw FOO bar } trap FOO {em} { throw BAR baz }
}
return $em
}}
} {bar}
test error-16.18 {compiled try with variable assignment and propagation #2} {
apply {{} {
catch {
try { throw FOO bar } trap FOO {em opts} { throw BAR baz }
}
list $em [dict get $opts -errorcode]
}}
} {bar FOO}
test error-16.19 {compiled try exception chaining (try=ok, handler=error)} -body {
#FIXME is the intent of this test correct?
apply {{} {
catch {
try { list a b c } on ok {em opts} { throw BAR baz }
} tryem tryopts
list $opts [dict get $tryopts -during]
}}
} -match pairwise -result equal
test error-16.20 {compiled try exception chaining (try=error, handler=error)} -body {
# The exception off the handler should chain to the exception off the
# try-body (using the -during option)
apply {{} {
catch {
try { throw FOO bar } trap {} {em opts} { throw BAR baz }
} tryem tryopts
list $opts [dict get $tryopts -during]
}}
} -match pairwise -result equal
test error-16.21 {compiled try exception chaining (try=error, finally=error)} {
# The exception off the handler should chain to the exception off the
# try-body (using the -during option)
apply {{} {
catch {
try { throw FOO bar } finally { throw BAR baz }
} tryem tryopts
dict get $tryopts -during -errorcode
}}
} FOO
test error-16.22 {compiled try: no exception chaining when handler is successful} {
apply {{} {
catch {
try { throw FOO bar } trap {} {em opts} { list d e f }
} tryem tryopts
dict exists $tryopts -during
}}
} {0}
test error-16.23 {compiled try: no exception chaining when handler is a non-error exception} {
apply {{} {
catch {
try { throw FOO bar } trap {} {em opts} { break }
} tryem tryopts
dict exists $tryopts -during
}}
} {0}
test error-16.24 {compiled try exception chaining (try=ok, handler=error, finally=error)} -body {
apply {{} {
catch {
try {
list a b c
} on ok {em opts} {
throw BAR baz
} finally {
throw DING dong
}
} tryem tryopts
list $opts [dict get $tryopts -during -during]
}}
} -match pairwise -result equal
test error-16.25 {compiled try exception chaining (all errors)} -body {
apply {{} {
catch {
try {
throw FOO bar
} on error {em opts} {
throw BAR baz
} finally {
throw DING dong
}
} tryem tryopts
list $opts [dict get $tryopts -during -during]
}}
} -match pairwise -result equal
# try tests - finally
test error-17.1 {finally always runs (try with ok result)} {
set RES {}
try { list a b c } finally { set RES done }
set RES
} {done}
test error-17.2 {finally always runs (try with error result)} {
set RES {}
catch {
try { throw FOO bar } finally { set RES done }
}
set RES
} {done}
test error-17.3 {finally always runs (try with matching handler)} {
set RES {}
try { throw FOO bar } trap FOO {} { list a b c } finally { set RES done }
set RES
} {done}
test error-17.4 {finally always runs (try with exception in handler)} {
set RES {}
catch {
try {
throw FOO bar
} trap FOO {} {
throw BAR baz
} finally {
set RES done
}
}
set RES
} {done}
test error-17.5 {successful finally doesn't modify try outcome (try=ok)} {
try { list a b c } finally { list d e f }
} {a b c}
test error-17.6 {successful finally doesn't modify try outcome (try=return)} -body {
try { return c } finally { list d e f }
} -returnCodes 2 -result {c}
test error-17.7 {successful finally doesn't modify try outcome (try=error)} -body {
try { error bar } finally { list d e f }
} -returnCodes 1 -result {bar}
test error-17.8 {successful finally doesn't modify handler outcome (handler=ok)} {
try { throw FOO bar } trap FOO {} { list a b c } finally { list d e f }
} {a b c}
test error-17.9 {successful finally doesn't modify handler outcome (handler=error)} -body {
try { throw FOO bar } trap FOO {} { throw BAR baz } finally { list d e f }
} -returnCodes error -result {baz}
test error-17.10 {successful finally doesn't affect variable assignment} {
catch {
try { throw FOO bar } trap FOO {em opts} { list d e f } finally { list d e f }
} result
list $em $result
} {bar {d e f}}
test error-17.11 {successful finally doesn't affect variable assignment or propagation} {
catch {
try { throw FOO bar } trap FOO {em opts} { throw BAR baz } finally { list d e f }
}
list $em [dict get $opts -errorcode]
} {bar FOO}
# try tests - propagation (exceptions in finally, exception chaining)
test error-18.1 {try (ok) with exception in finally (error)} -body {
try { list a b c } finally { throw BAR foo }
} -returnCodes error -result {foo}
test error-18.2 {try (error) with exception in finally (break)} -body {
try { throw FOO bar } finally { break }
} -returnCodes 3 -result {}
test error-18.3 {try (ok) with handler (ok) and exception in finally (error)} -body {
try { list a b c } on ok {} { list d e f } finally { throw BAR foo }
} -returnCodes error -result {foo}
test error-18.4 {try (error) with exception in handler (error) and in finally (arb code)} -body {
try { throw FOO bar } on error {} { throw BAR baz } finally { return -level 0 -code 99 zing }
} -returnCodes 99 -result {zing}
test error-18.5 {exception in finally doesn't affect variable assignment} {
catch {
try { throw FOO bar } trap FOO {em opts} { throw BAR baz } finally { throw BAZ zing }
}
list $em [dict get $opts -errorcode]
} {bar FOO}
test error-18.6 {exception chaining in finally (try=ok)} -body {
catch {
list a b c
} em expopts
catch {
try { list a b c } finally { throw BAR foo }
} em opts
list $expopts [dict get $opts -during]
} -match pairwise -result equal
test error-18.7 {exception chaining in finally (try=error)} {
catch {
try { throw FOO bar } finally { throw BAR baz }
} em opts
dict get $opts -during -errorcode
} {FOO}
test error-18.8 {exception chaining in finally (try=ok, handler=ok)} {
catch {
try { list a b c } on ok {} { list d e f } finally { throw BAR baz }
} em opts
list [dict get $opts -during -code] [dict exists $opts -during -during]
} {0 0}
test error-18.9 {exception chaining in finally (try=error, handler=ok)} {
catch {
try {
throw FOO bar
} on error {} {
list d e f
} finally {
throw BAR baz
}
} em opts
list [dict get $opts -during -code] [dict exists $opts -during -during]
} {0 0}
test error-18.10 {exception chaining in finally (try=error, handler=error)} {
catch {
try {
throw FOO bar
} on error {} {
throw BAR baz
} finally {
throw BAR baz
}
} em opts
list [dict get $opts -during -errorcode] [dict get $opts -during -during -errorcode]
} {BAR FOO}
test error-18.11 {no exception chaining if finally produces a non-error exception} {
catch {
try { throw FOO bar } on error {} { throw BAR baz } finally { break }
} em opts
dict exists $opts -during
} {0}
test error-18.12 {variable assignment unaffected by exception in finally} {
catch {
try {
throw FOO bar
} on error {em opts} {
list a b c
} finally {
throw BAR baz
}
}
list $em [dict get $opts -errorcode]
} {bar FOO}
# try tests - fallthough body cases
test error-19.1 {try with fallthrough body #1} {
set RES {}
try { list a b c } on ok { set RES 0 } - on error {} { set RES 1 }
set RES
} {1}
test error-19.2 {try with fallthrough body #2} {
set RES {}
try {
throw FOO bar
} trap BAR {} {
} trap FOO {} - trap {} {} {
set RES foo
} on error {} {
set RES err
}
set RES
} {foo}
test error-19.3 {try with cascade fallthrough} {
set RES {}
try {
throw FOO bar
} trap FOO {} - trap BAR {} - trap {} {} {
set RES trap
} on error {} { set RES err }
set RES
} {trap}
test error-19.4 {multiple unrelated fallthroughs #1} {
set RES {}
try {
throw FOO bar
} trap FOO {} - trap BAR {} {
set RES foo
} trap {} {} - on error {} {
set RES err
}
set RES
} {foo}
test error-19.5 {multiple unrelated fallthroughs #2} {
set RES {}
try {
throw BAZ zing
} trap FOO {} - trap BAR {} {
set RES foo
} trap {} {} - on error {} {
set RES err
}
set RES
} {err}
proc addmsg msg {
variable RES
lappend RES $msg
}
test error-19.6 {compiled try executes all clauses} -setup {
set RES {}
} -body {
apply {{} {
try {
addmsg a
throw bar hello
} trap bar {res opt} {
addmsg b
} finally {
addmsg c
}
addmsg d
} ::tcl::test::error}
} -cleanup {
unset RES
} -result {a b c d}
test error-19.7 {compiled try executes all clauses} -setup {
set RES {}
} -body {
apply {{} {
try {
addmsg a
} on error {res opt} {
addmsg b
} on ok {} {
addmsg c
} finally {
addmsg d
}
addmsg e
} ::tcl::test::error}
} -cleanup {
unset RES
} -result {a c d e}
test error-19.8 {compiled try executes all clauses} -setup {
set RES {}
} -body {
apply {{} {
try {
addmsg a
throw bar hello
} trap bar {res opt} {
addmsg b
}
addmsg c
} ::tcl::test::error}
} -cleanup {
unset RES
} -result {a b c}
test error-19.9 {compiled try executes all clauses} -setup {
set RES {}
} -body {
apply {{} {
try {
addmsg a
} on error {res opt} {
addmsg b
} on ok {} {
addmsg c
}
addmsg d
} ::tcl::test::error}
} -cleanup {
unset RES
} -result {a c d}
test error-19.10 {compiled try with chained clauses} -setup {
set RES {}
} -body {
list [apply {{} {
try {
return good
} on return {res} - on ok {res} {
addmsg ok
addmsg $res
return handler
} finally {
addmsg finally
}
} ::tcl::test::error}] $RES
} -cleanup {
unset RES
} -result {handler {ok good finally}}
test error-19.11 {compiled try and errors on variable write} -setup {
set RES {}
} -body {
apply {{} {
array set foo {bar boo}
set bar unset
catch {
try {
addmsg body
return a
} on return {bar foo} {
addmsg handler
return b
} finally {
addmsg finally,$bar
}
} msg
addmsg $msg
} ::tcl::test::error}
} -cleanup {
unset RES
} -result {body finally,a {can't set "foo": variable is array}}
test error-19.12 {interpreted try and errors on variable write} -setup {
set RES {}
} -body {
apply {try {
array set foo {bar boo}
set bar unset
catch {
$try {
addmsg body
return a
} on return {bar foo} {
addmsg handler
return b
} finally {
addmsg finally,$bar
}
} msg
addmsg $msg
} ::tcl::test::error} try
} -cleanup {
unset RES
} -result {body finally,a {can't set "foo": variable is array}}
test error-19.13 {compiled try and errors on variable write} -setup {
set RES {}
} -body {
apply {{} {
array set foo {bar boo}
set bar unset
catch {
try {
addmsg body
return a
} on return {bar foo} - on error {bar foo} {
addmsg handler
return b
} finally {
addmsg finally,$bar
}
} msg
addmsg $msg
} ::tcl::test::error}
} -cleanup {
unset RES
} -result {body finally,a {can't set "foo": variable is array}}
rename addmsg {}
# FIXME test what vars get set on fallthough ... what is the correct behavior?
# It would seem appropriate to set at least those for the matching handler and
# the executed body; possibly for each handler we fall through as well?
# negative case try tests - bad "on" handler
test error-20.1 {bad code name in on handler} -body {
try { list a b c } on err {} {}
} -returnCodes error -match glob -result {bad completion code "err": must be ok, error, return, break, continue*, or an integer}
test error-20.2 {bad code value in on handler} -body {
try { list a b c } on 34985723094872345 {} {}
} -returnCodes error -match glob -result {bad completion code "34985723094872345": must be ok, error, return, break, continue*, or an integer}
test error-21.1 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {string repeat x 10} on ok {} {}
}
} 0
test error-21.2 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {error [string repeat x 10]} on error {} {}
}
} 0
test error-21.3 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {throw FOO [string repeat x 10]} trap FOO {} {}
}
} 0
test error-21.4 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {string repeat x 10}
}
} 0
test error-21.5 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {string repeat x 10} on ok {} {} finally {string repeat y 10}
}
} 0
test error-21.6 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {
error [string repeat x 10]
} on error {} {} finally {
string repeat y 10
}
}
} 0
test error-21.7 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {
throw FOO [string repeat x 10]
} trap FOO {} {} finally {
string repeat y 10
}
}
} 0
test error-21.8 {memory leaks in try: Bug 2910044} memory {
leaktest {
try {string repeat x 10} finally {string repeat y 10}
}
} 0
test error-21.9 {Bug cee90e4e88} {
# Just don't panic.
apply {{} {try {} on ok {} - on return {} {}}}
} {}
# negative case try tests - bad "trap" handler
# what is the effect if we attempt to trap an errorcode that is not a list?
# nested try
# catch inside try
# no tests for bad varslist?
# -errorcode but code!=1 doesn't trap
# throw negative case tests (no args, too many args, etc)
}
namespace delete ::tcl::test::error
# cleanup
catch {rename p ""}
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End: