summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/chan.test9
-rw-r--r--tests/io.test277
-rw-r--r--tests/ioCmd.test3078
3 files changed, 3353 insertions, 11 deletions
diff --git a/tests/chan.test b/tests/chan.test
index dd2fea6..f2376a3 100644
--- a/tests/chan.test
+++ b/tests/chan.test
@@ -7,19 +7,24 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: chan.test,v 1.4 2005/06/07 21:31:53 dkf Exp $
+# RCS: @(#) $Id: chan.test,v 1.5 2005/08/24 17:56:24 andreas_kupries Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
+#
+# Note: The tests for the chan methods "create" and "postevent"
+# currently reside in the file "ioCmd.test".
+#
+
test chan-1.1 {chan command general syntax} -body {
chan
} -returnCodes error -result "wrong # args: should be \"chan subcommand ?argument ...?\""
test chan-1.2 {chan command general syntax} -body {
chan FOOBAR
-} -returnCodes error -result "unknown or ambiguous subcommand \"FOOBAR\": must be blocked, close, configure, copy, eof, event, flush, gets, names, puts, read, seek, tell, or truncate"
+} -returnCodes error -result "unknown or ambiguous subcommand \"FOOBAR\": must be blocked, close, configure, copy, create, eof, event, flush, gets, names, postevent, puts, read, seek, tell, or truncate"
test chan-2.1 {chan command: blocked subcommand} -body {
chan blocked foo bar
diff --git a/tests/io.test b/tests/io.test
index 9d724b8..4edb308 100644
--- a/tests/io.test
+++ b/tests/io.test
@@ -1,3 +1,4 @@
+# -*- tcl -*-
# Functionality covered: operation of all IO commands, and all procedures
# defined in generic/tclIO.c.
#
@@ -12,7 +13,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: io.test,v 1.68 2005/05/10 18:35:21 kennykb Exp $
+# RCS: @(#) $Id: io.test,v 1.69 2005/08/24 17:56:24 andreas_kupries Exp $
if {[catch {package require tcltest 2}]} {
puts stderr "Skipping tests in [info script]. tcltest 2 required."
@@ -28,14 +29,14 @@ namespace eval ::tcl::test::io {
namespace import ::tcltest::testConstraint
namespace import ::tcltest::viewFile
-testConstraint testchannel [llength [info commands testchannel]]
-testConstraint exec [llength [info commands exec]]
-testConstraint openpipe 1
-testConstraint fileevent [llength [info commands fileevent]]
-testConstraint fcopy [llength [info commands fcopy]]
-testConstraint testfevent [llength [info commands testfevent]]
+testConstraint testchannel [llength [info commands testchannel]]
+testConstraint exec [llength [info commands exec]]
+testConstraint openpipe 1
+testConstraint fileevent [llength [info commands fileevent]]
+testConstraint fcopy [llength [info commands fcopy]]
+testConstraint testfevent [llength [info commands testfevent]]
testConstraint testchannelevent [llength [info commands testchannelevent]]
-testConstraint testmainthread [llength [info commands testmainthread]]
+testConstraint testmainthread [llength [info commands testmainthread]]
# You need a *very* special environment to do some tests. In
# particular, many file systems do not support large-files...
@@ -7111,6 +7112,266 @@ test io-61.1 {Reset eof state after changing the eof char} -setup {
removeFile eofchar
} -result {77 = 23431}
+
+# Test the cutting and splicing of channels, this is incidentially the
+# attach/detach facility of package Thread, but __without any
+# safeguards__. It can also be used to emulate transfer of channels
+# between threads, and is used for that here.
+
+test io-70.0 {Cutting & Splicing channels} {testchannel} {
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res {}
+ lappend res [catch {seek $c 0 start}]
+ testchannel cut $c
+
+ lappend res [catch {seek $c 0 start}]
+ testchannel splice $c
+
+ lappend res [catch {seek $c 0 start}]
+ close $c
+
+ removeFile cutsplice
+
+ set res
+} {0 1 0}
+
+
+# Duplicate of code in "thread.test". Find a better way of doing this
+# without duplication. Maybe placement into a proc which transforms to
+# nop after the first call, and placement of its defintion in a
+# central location.
+
+testConstraint testthread [expr {[info commands testthread] != {}}]
+
+if {[testConstraint testthread]} {
+ testthread errorproc ThreadError
+
+ proc ThreadError {id info} {
+ global threadError
+ set threadError $info
+ }
+
+ proc ThreadNullError {id info} {
+ # ignore
+ }
+}
+
+test io-70.1 {Transfer channel} {testchannel testthread} {
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res {}
+ lappend res [catch {seek $c 0 start}]
+ testchannel cut $c
+ lappend res [catch {seek $c 0 start}]
+
+ set tid [testthread create]
+ testthread send $tid [list set c $c]
+ lappend res [testthread send $tid {
+ testchannel splice $c
+ set res [catch {seek $c 0 start}]
+ close $c
+ set res
+ }]
+
+ tcltest::threadReap
+ removeFile cutsplice
+
+ set res
+} {0 1 0}
+
+# ### ### ### ######### ######### #########
+
+foreach {n msg expected} {
+ 0 {} {}
+ 1 {{message only}} {{message only}}
+ 2 {-options x} {-options x}
+ 3 {-options {x y} {the message}} {-options {x y} {the message}}
+
+ 4 {-code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 5 {-code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 6 {-code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 7 {-code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 8 {-code error -level 0 -f ba snarf} {-code error -level 0 -f ba snarf}
+ 9 {-code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 10 {-code error -level 5 -f ba snarf} {-code error -level 0 -f ba snarf}
+ 11 {-code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 12 {-code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 13 {-code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 14 {-code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 15 {-code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 16 {-code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 17 {-code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 18 {-code error -level 0 -f ba} {-code error -level 0 -f ba}
+ 19 {-code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 20 {-code error -level 5 -f ba} {-code error -level 0 -f ba}
+ 21 {-code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 22 {-code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 23 {-code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 24 {-code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 25 {-code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 26 {-code error -level X -f ba snarf} {-code error -level 0 -f ba snarf}
+ 27 {-code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 28 {-code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 29 {-code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ 30 {-code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 31 {-code error -level X -f ba} {-code error -level 0 -f ba}
+ 32 {-code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 33 {-code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 34 {-code 1 -code 1 -level 0 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 35 {-code 1 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 36 {-code 1 -code 1 -level 5 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 37 {-code 1 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 38 {-code 1 -code error -level 0 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 39 {-code 1 -code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 40 {-code 1 -code error -level 5 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 41 {-code 1 -code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 42 {-code 1 -code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 43 {-code 1 -code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 44 {-code 1 -code 1 -level 0 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 45 {-code 1 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 46 {-code 1 -code 1 -level 5 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 47 {-code 1 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 48 {-code 1 -code error -level 0 -f ba} {-code 1 -code error -level 0 -f ba}
+ 49 {-code 1 -code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 50 {-code 1 -code error -level 5 -f ba} {-code 1 -code error -level 0 -f ba}
+ 51 {-code 1 -code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 52 {-code 1 -code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 53 {-code 1 -code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 54 {-code 1 -code 1 -level X -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 55 {-code 1 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 56 {-code 1 -code error -level X -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 57 {-code 1 -code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 58 {-code 1 -code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 59 {-code 1 -code 1 -level X -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 60 {-code 1 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 61 {-code 1 -code error -level X -f ba} {-code 1 -code error -level 0 -f ba}
+ 62 {-code 1 -code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 63 {-code 1 -code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 64 {-code 0 -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 65 {-code 0 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 66 {-code 0 -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 67 {-code 0 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 68 {-code 0 -code error -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 69 {-code 0 -code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 70 {-code 0 -code error -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 71 {-code 0 -code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 72 {-code 0 -code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 73 {-code 0 -code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 74 {-code 0 -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 75 {-code 0 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 76 {-code 0 -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 77 {-code 0 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 78 {-code 0 -code error -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 79 {-code 0 -code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 80 {-code 0 -code error -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 81 {-code 0 -code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 82 {-code 0 -code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 83 {-code 0 -code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 84 {-code 0 -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 85 {-code 0 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 86 {-code 0 -code error -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 87 {-code 0 -code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 88 {-code 0 -code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 89 {-code 0 -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ 90 {-code 0 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 91 {-code 0 -code error -level X -f ba} {-code 1 -level 0 -f ba}
+ 92 {-code 0 -code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 93 {-code 0 -code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 94 {-code 1 -code 1 -level 0 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 95 {-code 0 -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 96 {-code 1 -code 1 -level 5 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 97 {-code 0 -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 98 {-code error -code 1 -level 0 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ 99 {-code ok -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a0 {-code error -code 1 -level 5 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ a1 {-code ok -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a2 {-code boss -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a3 {-code boss -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a4 {-code 1 -code 1 -level 0 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ a5 {-code 0 -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ a6 {-code 1 -code 1 -level 5 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ a7 {-code 0 -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ a8 {-code error -code 1 -level 0 -f ba} {-code error -code 1 -level 0 -f ba}
+ a9 {-code ok -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ b0 {-code error -code 1 -level 5 -f ba} {-code error -code 1 -level 0 -f ba}
+ b1 {-code ok -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ b2 {-code boss -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ b3 {-code boss -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ b4 {-code 1 -code 1 -level X -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ b5 {-code 0 -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b6 {-code error -code 1 -level X -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ b7 {-code ok -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b8 {-code boss -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b9 {-code 1 -code 1 -level X -f ba} {-code 1 -code 1 -level 0 -f ba}
+ c0 {-code 0 -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ c1 {-code error -code 1 -level X -f ba} {-code error -code 1 -level 0 -f ba}
+ c2 {-code ok -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ c3 {-code boss -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+
+ c4 {-code 1 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c5 {-code 0 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c6 {-code 1 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c7 {-code 0 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c8 {-code error -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c9 {-code ok -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d0 {-code error -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d1 {-code ok -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d2 {-code boss -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d3 {-code boss -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d4 {-code 1 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d5 {-code 0 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d6 {-code 1 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ d7 {-code 0 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ d8 {-code error -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d9 {-code ok -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ e0 {-code error -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e1 {-code ok -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e2 {-code boss -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ e3 {-code boss -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e4 {-code 1 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e5 {-code 0 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e6 {-code error -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e7 {-code ok -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e8 {-code boss -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e9 {-code 1 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f0 {-code 0 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f1 {-code error -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f2 {-code ok -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f3 {-code boss -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+} {
+ test io-71.$n {Tcl_SetChannelError} {testchannel} {
+
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res [testchannel setchannelerror $c [lrange $msg 0 end]]
+ close $c
+ removeFile cutsplice
+
+ set res
+ } [lrange $expected 0 end]
+
+ test io-72.$n {Tcl_SetChannelErrorInterp} {testchannel} {
+
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res [testchannel setchannelerrorinterp $c [lrange $msg 0 end]]
+ close $c
+ removeFile cutsplice
+
+ set res
+ } [lrange $expected 0 end]
+}
+
+# ### ### ### ######### ######### #########
+
# cleanup
foreach file [list fooBar longfile script output test1 pipe my_script foo \
bar test2 test3 cat stdout kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
diff --git a/tests/ioCmd.test b/tests/ioCmd.test
index fd09bc7..2c95b13 100644
--- a/tests/ioCmd.test
+++ b/tests/ioCmd.test
@@ -1,3 +1,4 @@
+# -*- tcl -*-
# Commands covered: open, close, gets, read, puts, seek, tell, eof, flush,
# fblocked, fconfigure, open, channel, fcopy
#
@@ -12,7 +13,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: ioCmd.test,v 1.23 2005/05/10 18:35:22 kennykb Exp $
+# RCS: @(#) $Id: ioCmd.test,v 1.24 2005/08/24 17:56:24 andreas_kupries Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
@@ -572,6 +573,3081 @@ test iocmd-15.12 {Tcl_FcopyObjCmd} {fcopy} {
close $rfile
close $wfile
+# ### ### ### ######### ######### #########
+## Testing the reflected channel.
+
+test iocmd-20.0 {chan, wrong#args} {
+ catch {chan} msg
+ set msg
+} {wrong # args: should be "chan subcommand ?argument ...?"}
+
+test iocmd-20.1 {chan, unknown method} {
+ catch {chan foo} msg
+ set msg
+} {unknown or ambiguous subcommand "foo": must be blocked, close, configure, copy, create, eof, event, flush, gets, names, postevent, puts, read, seek, tell, or truncate}
+
+# --- --- --- --------- --------- ---------
+# chan create, and method "initalize"
+
+test iocmd-21.0 {chan create, wrong#args, not enough} {
+ catch {chan create} msg
+ set msg
+} {wrong # args: should be "chan create mode cmdprefix"}
+
+test iocmd-21.1 {chan create, wrong#args, too many} {
+ catch {chan create a b c} msg
+ set msg
+} {wrong # args: should be "chan create mode cmdprefix"}
+
+test iocmd-21.2 {chan create, invalid r/w mode, empty} {
+ proc foo {} {}
+ catch {chan create {} foo} msg
+ rename foo {}
+ set msg
+} {bad mode list: is empty}
+
+test iocmd-21.3 {chan create, invalid r/w mode, bad string} {
+ proc foo {} {}
+ catch {chan create {c} foo} msg
+ rename foo {}
+ set msg
+} {bad mode "c": must be read or write}
+
+test iocmd-21.4 {chan create, bad handler, not a list} {
+ catch {chan create {r w} "foo \{"} msg
+ set msg
+} {unmatched open brace in list}
+
+test iocmd-21.5 {chan create, bad handler, not a command} {
+ catch {chan create {r w} foo} msg
+ set msg
+} {Initialize failure: invalid command name "foo"}
+
+test iocmd-21.6 {chan create, initialize failed, bad signature} {
+ proc foo {} {}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: wrong # args: should be "foo"}
+
+test iocmd-21.7 {chan create, initialize failed, bad signature} {
+ proc foo {} {}
+ catch {chan create {r w} ::foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: wrong # args: should be "::foo"}
+
+test iocmd-21.8 {chan create, initialize failed, bad result, not a list} {
+ proc foo {args} {return "\{"}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: unmatched open brace in list}
+
+test iocmd-21.9 {chan create, initialize failed, bad result, not a list} {
+ proc foo {args} {return \{\{\}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: unmatched open brace in list}
+
+test iocmd-21.10 {chan create, initialize failed, bad result, empty list} {
+ proc foo {args} {}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: Not all required methods supported}
+
+test iocmd-21.11 {chan create, initialize failed, bad result, bogus method name} {
+ proc foo {args} {return 1}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: bad method "1": must be blocking, cget, cgetall, configure, finalize, initialize, read, seek, watch, or write}
+
+test iocmd-21.12 {chan create, initialize failed, bad result, ambiguous method name} {
+ proc foo {args} {return {a b c}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: ambiguous method "c": must be blocking, cget, cgetall, configure, finalize, initialize, read, seek, watch, or write}
+
+test iocmd-21.13 {chan create, initialize failed, bad result, required methods missing} {
+ proc foo {args} {return {initialize finalize}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: Not all required methods supported}
+
+test iocmd-21.14 {chan create, initialize failed, bad result, mode/handler mismatch} {
+ proc foo {args} {return {initialize finalize watch read}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: Writing not supported, but requested}
+
+test iocmd-21.15 {chan create, initialize failed, bad result, mode/handler mismatch} {
+ proc foo {args} {return {initialize finalize watch write}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: Reading not supported, but requested}
+
+test iocmd-21.16 {chan create, initialize failed, bad result, cget(all) mismatch} {
+ proc foo {args} {return {initialize finalize watch cget write read}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: 'cgetall' not supported, but should be, as 'cget' is}
+
+test iocmd-21.17 {chan create, initialize failed, bad result, cget(all) mismatch} {
+ proc foo {args} {return {initialize finalize watch cgetall read write}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {Initialize failure: 'cget' not supported, but should be, as 'cgetall' is}
+
+test iocmd-21.18 {chan create, initialize ok, creates channel} -match glob -body {
+ proc foo {args} {
+ global res
+ lappend res $args
+ if {[lindex $args 0] ne "initialize"} {return}
+ return {initialize finalize watch read write}
+ }
+ set res {}
+ lappend res [file channel rc*]
+ lappend res [chan create {r w} foo]
+ lappend res [close [lindex $res end]]
+ lappend res [file channel rc*]
+ rename foo {}
+ set res
+} -result {{} {initialize rc* {read write}} rc* {finalize rc*} {} {}}
+
+test iocmd-21.19 {chan create, init failure -> no channel, no finalize} -match glob -body {
+ proc foo {args} {
+ global res
+ lappend res $args
+ return {}
+ }
+ set res {}
+ lappend res [file channel rc*]
+ lappend res [catch {chan create {r w} foo} msg]
+ lappend res $msg
+ lappend res [file channel rc*]
+ rename foo {}
+ set res
+} -result {{} {initialize rc* {read write}} 1 {Initialize failure: Not all required methods supported} {}}
+
+# --- --- --- --------- --------- ---------
+# Helper commands to record the arguments to handler methods.
+
+proc note {item} {global res ; lappend res $item ; return}
+proc track {} {upvar args item ; note $item; return}
+proc notes {items} {foreach i $items {note $i}}
+
+# Helper command, canned result for 'initialize' method.
+# Gets the optional methods as arguments. Use return features
+# to post the result higher up.
+
+proc init {args} {
+ lappend args initialize finalize watch read write
+ return -code return $args
+}
+
+proc oninit {args} {
+ upvar args hargs
+ if {[lindex $hargs 0] ne "initialize"} {return}
+ lappend args initialize finalize watch read write
+ return -code return $args
+}
+
+proc onfinal {} {
+ upvar args hargs
+ if {[lindex $hargs 0] ne "finalize"} {return}
+ return -code return ""
+}
+
+# --- --- --- --------- --------- ---------
+# method finalize
+
+test iocmd-22.1 {chan finalize, handler destruction has no effect on channel} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit; return}
+ note [set c [chan create {r w} foo]]
+
+ rename foo {}
+
+ note [file channels rc*]
+ note [catch {close $c} msg] ; note $msg
+ note [file channels rc*]
+
+ set res
+} -result {{initialize rc* {read write}} rc* rc* 1 {invalid command name "foo"} {}}
+
+test iocmd-22.2 {chan finalize, for close} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return {}}
+ note [set c [chan create {r w} foo]]
+
+ close $c
+
+ # Close deleted the channel.
+ note [file channels rc*]
+
+ # Channel destruction does not kill handler command!
+ note [info command foo]
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} {} foo}
+
+test iocmd-22.3 {chan finalize, for close, error, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code error 5}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg] ; note $msg
+ # Channel is gone despite error.
+ note [file channels rc*]
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 5 {}}
+
+test iocmd-22.4 {chan finalize, for close, error, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; error FOO}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg] ; note $msg
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 FOO}
+
+test iocmd-22.5 {chan finalize, for close, arbitrary result, ignored} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return SOMETHING}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg]; note $msg
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 0 {}}
+
+test iocmd-22.6 {chan finalize, for close, break, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code 3}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg] ; note $msg
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 {}}
+
+test iocmd-22.7 {chan finalize, for close, continue, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code 4}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg] ; note $msg
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 {}}
+
+test iocmd-22.8 {chan finalize, for close, custom code, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg] ; note $msg
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 BANG}
+
+test iocmd-22.9 {chan finalize, for close, ignore level, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -level 5 -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+
+ note [catch {close $c} msg opt] ; note $msg ; note $opt
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+# --- === *** ###########################
+# method read
+
+test iocmd-23.1 {chan read, regular data return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return snarf
+ }
+ set c [chan create {r w} foo]
+
+ note [read $c 10]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}
+
+test iocmd-23.2 {chan read, bad data return, to much} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return [string repeat snarf 1000]
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 {read delivered more than requested}}
+
+test iocmd-23.3 {chan read, for non-readable channel} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ note MUST_NOT_HAPPEN
+ }
+ set c [chan create {w} foo]
+
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {1 {channel "rc*" wasn't opened for reading}}
+
+test iocmd-23.4 {chan read, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!}
+
+test iocmd-23.5 {chan read, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!}
+
+test iocmd-23.6 {chan read, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!}
+
+test iocmd-23.7 {chan read, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!}
+
+test iocmd-23.8 {chan read, level is squashed} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -level 55 -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg opt] ; note $msg ; note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM! {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BOOM!}}
+
+# --- === *** ###########################
+# method write
+
+test iocmd-24.1 {chan write, regular write} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal ; track
+ set written [string length [lindex $args 2]]
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+
+ puts -nonewline $c snarf ; flush $c
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarf} 5}
+
+test iocmd-24.2 {chan write, partial write is ok} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ set written [string length [lindex $args 2]]
+ if {$written > 10} {set written [expr {$written / 2}]}
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+
+ puts -nonewline $c snarfsnarfsnarf ; flush $c
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 7 {write rc* arfsnarf} 8}
+
+test iocmd-24.3 {chan write, failed write} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note -1 ; return -1}
+
+ set c [chan create {r w} foo]
+ puts -nonewline $c snarfsnarfsnarf ; flush $c
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} -1}
+
+test iocmd-24.4 {chan write, non-writable channel} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {1 {channel "rc*" wasn't opened for writing}}
+
+test iocmd-24.5 {chan write, bad result, more written than data} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return 10000}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarf ; flush $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarf} 1 {write wrote more than requested}}
+
+test iocmd-24.6 {chan write, bad result, zero-length write} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return 0}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarf ; flush $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarf} 1 {write wrote more than requested}}
+
+test iocmd-24.7 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code error BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+
+test iocmd-24.8 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; error BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+
+test iocmd-24.9 {chan write, failed write, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+
+test iocmd-24.10 {chan write, failed write, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+
+test iocmd-24.11 {chan write, failed write, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code 777 BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+
+test iocmd-24.12 {chan write, failed write, non-numeric return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return BANG}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 {expected integer but got "BANG"}}
+
+test iocmd-24.13 {chan write, failed write, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -level 55 -code 777 BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg opt]
+ note $msg
+ note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM! {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BOOM!}}
+
+# --- === *** ###########################
+# method cgetall
+
+test iocmd-25.1 {chan configure, cgetall, standard options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+
+test iocmd-25.2 {chan configure, cgetall, no options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall ; onfinal ; track ; return ""}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+
+test iocmd-25.3 {chan configure, cgetall, regular result} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return "-bar foo -snarf x"
+ }
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *} -bar foo -snarf x}}
+
+test iocmd-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return "-bar"
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 {Expected list with even number of elements, got 1 element instead}}
+
+test iocmd-25.5 {chan configure, cgetall, bad result, not a list} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return "\{"
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 {unmatched open brace in list}}
+
+test iocmd-25.6 {chan configure, cgetall, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!}
+
+test iocmd-25.7 {chan configure, cgetall, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!}
+
+test iocmd-25.8 {chan configure, cgetall, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!}
+
+test iocmd-25.9 {chan configure, cgetall, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!}
+
+test iocmd-25.10 {chan configure, cgetall, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -level 55 -code 777 BANG
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c} msg opt] ; note $msg ; note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+# --- === *** ###########################
+# method configure
+
+test iocmd-26.1 {chan configure, set standard option} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track ; note MUST_NOT_HAPPEN
+ return
+ }
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -translation lf]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{}}
+
+test iocmd-26.2 {chan configure, set option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+
+test iocmd-26.3 {chan configure, set option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit configure ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -rc-foo bar]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} {}}
+
+test iocmd-26.4 {chan configure, set option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+
+test iocmd-26.5 {chan configure, set option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+
+test iocmd-26.6 {chan configure, set option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code 444 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+
+test iocmd-26.7 {chan configure, set option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -level 55 -code 444 BANG
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo bar} msg opt] ; note $msg ; note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+# --- === *** ###########################
+# method cget
+
+test iocmd-27.1 {chan configure, get option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall ; onfinal ; track ; return foo}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -rc-foo]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} foo}
+
+test iocmd-27.2 {chan configure, get option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!}
+
+test iocmd-27.3 {chan configure, get option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!}
+
+test iocmd-27.4 {chan configure, get option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!}
+
+test iocmd-27.5 {chan configure, get option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code 333 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!}
+
+test iocmd-27.6 {chan configure, get option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -level 77 -code 333 BANG
+ }
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -rc-foo} msg opt] ; note $msg ; note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+# --- === *** ###########################
+# method seek
+
+test iocmd-28.1 {chan tell, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ note [tell $c]
+ close $c
+
+ rename foo {}
+ set res
+} -result {-1}
+
+test iocmd-28.2 {chan tell, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code error BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!}
+
+test iocmd-28.3 {chan tell, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!}
+
+test iocmd-28.4 {chan tell, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!}
+
+test iocmd-28.5 {chan tell, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code 222 BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!}
+
+test iocmd-28.6 {chan tell, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -level 11 -code 222 BANG}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg opt] ; note $msg ; note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+test iocmd-28.7 {chan tell, regular return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return 88}
+ set c [chan create {r w} foo]
+
+ note [tell $c]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 88}
+
+test iocmd-28.8 {chan tell, negative return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -1}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {Tried to seek before origin}}
+
+test iocmd-28.9 {chan tell, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return BOGUS}
+ set c [chan create {r w} foo]
+
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {expected integer but got "BOGUS"}}
+
+test iocmd-28.10 {chan seek, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {1 {error during seek on "rc*": invalid argument}}
+
+test iocmd-28.11 {chan seek, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code error BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!}
+
+test iocmd-28.12 {chan seek, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!}
+
+test iocmd-28.13 {chan seek, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!}
+
+test iocmd-28.14 {chan seek, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code 99 BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!}
+
+test iocmd-28.15 {chan seek, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -level 33 -code 99 BANG}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg opt] ; note $msg ; note $opt
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+test iocmd-28.16 {chan seek, bogus return, negative location} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -45}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {Tried to seek before origin}}
+
+test iocmd-28.17 {chan seek, bogus return, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return BOGUS}
+ set c [chan create {r w} foo]
+
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {expected integer but got "BOGUS"}}
+
+test iocmd-28.18 {chan seek, ok result} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return 23}
+ set c [chan create {r w} foo]
+
+ note [seek $c 0 current]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} {}}
+
+foreach {n code} {
+ 0 start
+ 1 current
+ 2 end
+} {
+ test iocmd-28.19.$n "chan seek, base conversion, $code" -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return 0}
+
+ set c [chan create {r w} foo]
+ note [seek $c 0 $code]
+ close $c
+
+ rename foo {}
+ set res
+ } -result [list [list seek rc* 0 $code] {}]
+}
+
+# --- === *** ###########################
+# method blocking
+
+test iocmd-29.1 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -blocking]
+ close $c
+
+ rename foo {}
+ set res
+} -result {1}
+
+test iocmd-29.2 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{} 0}
+
+test iocmd-29.3 {chan blocking, retrieval, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -blocking]
+ close $c
+
+ rename foo {}
+ set res
+} -result {1}
+
+test iocmd-29.4 {chan blocking, resetting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} {} 0}
+
+test iocmd-29.5 {chan blocking, setting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fconfigure $c -blocking 1]
+ note [fconfigure $c -blocking]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 1} {} 1}
+
+test iocmd-29.6 {chan blocking, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; error BOOM!}
+
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+
+ # Catch the close. It changes blocking mode internally, and runs into the error result.
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!}
+
+test iocmd-29.7 {chan blocking, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!}
+
+test iocmd-29.8 {chan blocking, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!}
+
+test iocmd-29.9 {chan blocking, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -code 44 BOOM!}
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!}
+
+test iocmd-29.10 {chan blocking, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -level 99 -code 44 BANG}
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -blocking 0} msg opt] ; note $msg ; note $opt
+
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}}
+
+test iocmd-29.11 {chan blocking, regular return ok, value ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return BOGUS}
+ set c [chan create {r w} foo]
+
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 0 {}}
+
+# --- === *** ###########################
+# method watch
+
+test iocmd-30.1 {chan watch, read interest, some return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return IGNORED}
+ set c [chan create {r w} foo]
+
+ note [fileevent $c readable {set tick $tick}]
+ close $c ;# 2nd watch, interest zero.
+
+ rename foo {}
+ set res
+} -result {{watch rc* read} {} {watch rc* {}}}
+
+test iocmd-30.2 {chan watch, write interest, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code error BOOM!_IGNORED}
+ set c [chan create {r w} foo]
+
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c writable {}]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} {watch rc* {}} {}}
+
+test iocmd-30.3 {chan watch, accumulated interests} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}]
+ note [fileevent $c writable {}]
+ note [fileevent $c readable {}]
+ close $c
+
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} {watch rc* {read write}} {} {watch rc* read} {} {watch rc* {}} {}}
+
+test iocmd-30.4 {chan watch, unchanged interest not forwarded} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}] ;# Script is changing,
+ note [fileevent $c readable {set tock $tock}] ;# interest does not.
+
+ close $c ;# 3rd and 4th watch, removing the event handlers.
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} {watch rc* {read write}} {} {} {watch rc* write} {watch rc* {}}}
+
+# --- === *** ###########################
+# chan postevent
+
+test iocmd-31.1 {chan postevent, restricted to reflected channels} -match glob -body {
+ set c [open [makeFile {} goo] r]
+
+ catch {chan postevent $c {r w}} msg
+
+ close $c
+ removeFile goo
+ set msg
+} -result {channel "file*" is not a reflected channel}
+
+test iocmd-31.2 {chan postevent, unwanted events} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ catch {chan postevent $c {r w}} msg ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{tried to post events channel "rc*" is not interested in}}
+
+test iocmd-31.3 {chan postevent, bad input, empty list} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ catch {chan postevent $c {}} msg ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{bad event list: is empty}}
+
+test iocmd-31.4 {chan postevent, bad input, illlegal keyword} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ catch {chan postevent $c goo} msg ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{bad event "goo": must be read or write}}
+
+test iocmd-31.5 {chan postevent, bad input, not a list} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ catch {chan postevent $c "\{"} msg ; note $msg
+ close $c
+
+ rename foo {}
+ set res
+} -result {{unmatched open brace in list}}
+
+test iocmd-31.6 {chan postevent, posted events do happen} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fileevent $c readable {note TOCK}]
+
+ set stop [after 10000 {note TIMEOUT}]
+ after 1000 {note [chan postevent $c r]}
+ vwait ::res
+ catch {after cancel $stop}
+ close $c
+
+ rename foo {}
+ set res
+} -result {{watch rc* read} {} TOCK {} {watch rc* {}}}
+
+test iocmd-31.7 {chan postevent, posted events do happen} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ note [fileevent $c writable {note TOCK}]
+
+ set stop [after 10000 {note TIMEOUT}]
+ after 1000 {note [chan postevent $c w]}
+ vwait ::res
+ catch {after cancel $stop}
+ close $c
+
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} TOCK {} {watch rc* {}}}
+
+# ### ### ### ######### ######### #########
+## Same tests as above, but exercising the code forwarding and
+## receiving driver operations to the originator thread.
+
+# -*- tcl -*-
+# ### ### ### ######### ######### #########
+## Testing the reflected channel (Thread forwarding).
+#
+## The id numbers refer to the original test without thread
+## forwarding, and gaps due to tests not applicable to forwarding are
+## left to keep this asociation.
+
+testConstraint testchannel [llength [info commands testchannel]]
+
+# Duplicate of code in "thread.test". Find a better way of doing this
+# without duplication. Maybe placement into a proc which transforms to
+# nop after the first call, and placement of its defintion in a
+# central location.
+
+testConstraint testthread [expr {[info commands testthread] != {}}]
+
+if {[testConstraint testthread]} {
+ testthread errorproc ThreadError
+
+ proc ThreadError {id info} {
+ global threadError
+ set threadError $info
+ }
+
+ proc ThreadNullError {id info} {
+ # ignore
+ }
+}
+
+# ### ### ### ######### ######### #########
+## Helper command. Runs a script in a separate thread and returns the
+## result. A channel is transfered into the thread as well, and list of
+## configuation variables
+
+proc inthread {chan script args} {
+
+ # Test thread.
+
+ set tid [testthread create]
+
+ # Init thread configuration.
+ # - Listed variables
+ # - Id of main thread
+ # - A number of helper commands
+
+ foreach v $args {
+ upvar 1 $v x
+ testthread send $tid [list set $v $x]
+ }
+ testthread send $tid [list set mid $tcltest::mainThread]
+ testthread send $tid {
+ proc note {item} {global notes ; lappend notes $item}
+ proc notes {} {global notes ; return $notes}
+ }
+ testthread send $tid [list proc s {} [list uplevel 1 $script]] ; # (*)
+
+ # Transfer channel (cut/splice aka detach/attach)
+
+ testchannel cut $chan
+ testthread send $tid [list testchannel splice $chan]
+
+ # Run test script, also run local event loop!
+ # The local event loop waits for the result to come back.
+ # It is also necessary for the execution of forwarded channel
+ # operations.
+
+ set ::tres ""
+ testthread send -async $tid {
+ after 500
+ catch {s} res ; # This runs the script, 's' was defined at (*)
+ testthread send -async $mid [list set ::tres $res]
+ }
+ vwait ::tres
+ # Remove test thread, and return the captured result.
+
+ tcltest::threadReap
+ return $::tres
+}
+
+# ### ### ### ######### ######### #########
+
+# ### ### ### ######### ######### #########
+
+test iocmd.tf-22.2 {chan finalize, for close} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return {}}
+ note [set c [chan create {r w} foo]]
+
+ note [inthread $c {
+ close $c
+ # Close the deleted the channel.
+ file channels rc*
+ } c]
+
+ # Channel destruction does not kill handler command!
+ note [info command foo]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} {} foo}
+
+test iocmd.tf-22.3 {chan finalize, for close, error, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code error 5}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg] ; note $msg
+ # Channel is gone despite error.
+ note [file channels rc*]
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 5 {}}
+
+test iocmd.tf-22.4 {chan finalize, for close, error, close errror} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; error FOO}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg] ; note $msg
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 FOO}
+
+test iocmd.tf-22.5 {chan finalize, for close, arbitrary result} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return SOMETHING}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} 0 {}}
+
+test iocmd.tf-22.6 {chan finalize, for close, break, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code 3}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg] ; note $msg
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 {}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-22.7 {chan finalize, for close, continue, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code 4}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg] ; note $msg
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 {}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-22.8 {chan finalize, for close, custom code, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg] ; note $msg
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 BANG} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-22.9 {chan finalize, for close, ignore level, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track ; oninit ; return -level 5 -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+
+ notes [inthread $c {
+ note [catch {close $c} msg opt] ; note $msg ; note $opt
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method read
+
+test iocmd.tf-23.1 {chan read, regular data return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return snarf
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [read $c 10]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}
+
+test iocmd.tf-23.2 {chan read, bad data return, to much} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return [string repeat snarf 1000]
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {[read $c 2]} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{read rc* 4096} 1 {read delivered more than requested}}
+
+test iocmd.tf-23.3 {chan read, for non-readable channel} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ note MUST_NOT_HAPPEN
+ }
+ set c [chan create {w} foo]
+ notes [inthread $c {
+ note [catch {[read $c 2]} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {1 {channel "rc*" wasn't opened for reading}}
+
+test iocmd.tf-23.4 {chan read, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-23.5 {chan read, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-23.6 {chan read, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-23.7 {chan read, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {read $c 2} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-23.8 {chan read, level is squashed} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ return -level 55 -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {read $c 2} msg opt] ; note $msg ; note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM! {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BOOM!}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method write
+
+test iocmd.tf-24.1 {chan write, regular write} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal ; track
+ set written [string length [lindex $args 2]]
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+
+ inthread $c {
+ puts -nonewline $c snarf ; flush $c
+ close $c
+ } c
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarf} 5}
+
+test iocmd.tf-24.2 {chan write, ack partial writes} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit ; onfinal ; track
+ set written [string length [lindex $args 2]]
+ if {$written > 10} {set written [expr {$written / 2}]}
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+
+ inthread $c {
+ puts -nonewline $c snarfsnarfsnarf ; flush $c
+ close $c
+ } c
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarfsnarfsnarf} 7 {write rc* arfsnarf} 8}
+
+test iocmd.tf-24.3 {chan write, failed write} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note -1 ; return -1}
+ set c [chan create {r w} foo]
+
+ inthread $c {
+ puts -nonewline $c snarfsnarfsnarf ; flush $c
+ close $c
+ } c
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarfsnarfsnarf} -1}
+
+test iocmd.tf-24.4 {chan write, non-writable channel} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {1 {channel "rc*" wasn't opened for writing}}
+
+test iocmd.tf-24.5 {chan write, bad result, more written than data} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return 10000}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarf ; flush $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarf} 1 {write wrote more than requested}}
+
+test iocmd.tf-24.6 {chan write, zero writes} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return 0}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarf ; flush $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarf} 1 {write wrote more than requested}}
+
+test iocmd.tf-24.7 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code error BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-24.8 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; error BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-24.9 {chan write, failed write, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-24.10 {chan write, failed write, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-24.11 {chan write, failed write, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code 777 BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-24.12 {chan write, failed write, non-numeric return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return BANG}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 {expected integer but got "BANG"}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-24.13 {chan write, failed write, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -level 55 -code 777 BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf ; flush $c} msg opt]
+ note $msg
+ note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM! {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BOOM!}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method cgetall
+
+test iocmd.tf-25.1 {chan configure, cgetall, standard options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+
+test iocmd.tf-25.2 {chan configure, cgetall, no options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall ; onfinal ; track ; return ""}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+
+test iocmd.tf-25.3 {chan configure, cgetall, regular result} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return "-bar foo -snarf x"
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *} -bar foo -snarf x}}
+
+test iocmd.tf-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return "-bar"
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cgetall rc*} 1 {Expected list with even number of elements, got 1 element instead}}
+
+test iocmd.tf-25.5 {chan configure, cgetall, bad result, not a list} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return "\{"
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cgetall rc*} 1 {unmatched open brace in list}}
+
+test iocmd.tf-25.6 {chan configure, cgetall, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cgetall rc*} 1 BOOM!}
+
+test iocmd.tf-25.7 {chan configure, cgetall, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-25.8 {chan configure, cgetall, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-25.9 {chan configure, cgetall, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-25.10 {chan configure, cgetall, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -level 55 -code 777 BANG
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg opt] ; note $msg ; note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method configure
+
+test iocmd.tf-26.1 {chan configure, set standard option} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track ; note MUST_NOT_HAPPEN
+ return
+ }
+
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -translation lf]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{}}
+
+test iocmd.tf-26.2 {chan configure, set option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+
+test iocmd.tf-26.3 {chan configure, set option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit configure ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -rc-foo bar]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{configure rc* -rc-foo bar} {}}
+
+test iocmd.tf-26.4 {chan configure, set option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-26.5 {chan configure, set option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-26.6 {chan configure, set option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -code 444 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-26.7 {chan configure, set option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure ; onfinal ; track
+ return -level 55 -code 444 BANG
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg opt] ; note $msg ; note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method cget
+
+test iocmd.tf-27.1 {chan configure, get option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall ; onfinal ; track ; return foo}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -rc-foo]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cget rc* -rc-foo} foo}
+
+test iocmd.tf-27.2 {chan configure, get option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cget rc* -rc-foo} 1 BOOM!}
+
+test iocmd.tf-27.3 {chan configure, get option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-27.4 {chan configure, get option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-27.5 {chan configure, get option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -code 333 BOOM!
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-27.6 {chan configure, get option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall ; onfinal ; track
+ return -level 77 -code 333 BANG
+ }
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg opt] ; note $msg ; note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method seek
+
+test iocmd.tf-28.1 {chan tell, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [tell $c]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {-1} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.2 {chan tell, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code error BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.3 {chan tell, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.4 {chan tell, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.5 {chan tell, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code 222 BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.6 {chan tell, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -level 11 -code 222 BANG}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg opt] ; note $msg ; note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.7 {chan tell, regular return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return 88}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [tell $c]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 88} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.8 {chan tell, negative return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -1}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {Tried to seek before origin}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.9 {chan tell, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return BOGUS}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {tell $c} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {expected integer but got "BOGUS"}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.10 {chan seek, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {1 {error during seek on "rc*": invalid argument}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.11 {chan seek, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code error BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.12 {chan seek, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.13 {chan seek, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.14 {chan seek, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -code 99 BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.15 {chan seek, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -level 33 -code 99 BANG}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg opt] ; note $msg ; note $opt
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.16 {chan seek, bogus return, negative location} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return -45}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {Tried to seek before origin}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.17 {chan seek, bogus return, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return BOGUS}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg] ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {expected integer but got "BOGUS"}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-28.18 {chan seek, ok result} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return 23}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [seek $c 0 current]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} {}} \
+ -constraints {testchannel testthread}
+
+foreach {n code} {
+ 0 start
+ 1 current
+ 2 end
+} {
+ test iocmd.tf-28.19.$n "chan seek, base conversion, $code" -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek ; onfinal ; track ; return 0}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [seek $c 0 $code]
+ close $c
+ notes
+ } c code]
+
+ rename foo {}
+ set res
+ } -result [list [list seek rc* 0 $code] {}] \
+ -constraints {testchannel testthread}
+}
+
+# --- === *** ###########################
+# method blocking
+
+test iocmd.tf-29.1 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {1} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.2 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{} 0} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.3 {chan blocking, retrieval, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; note MUST_NOT_HAPPEN ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {1} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.4 {chan blocking, resetting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} {} 0} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.5 {chan blocking, setting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fconfigure $c -blocking 1]
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 1} {} 1} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.6 {chan blocking, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; error BOOM!}
+
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+ # Catch the close. It changes blocking mode internally, and runs into the error result.
+ catch {close $c}
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.7 {chan blocking, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -code break BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+ catch {close $c}
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.8 {chan blocking, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+ catch {close $c}
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.9 {chan blocking, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -code 44 BOOM!}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+ catch {close $c}
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.10 {chan blocking, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return -level 99 -code 44 BANG}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg opt] ; note $msg ; note $opt
+ catch {close $c}
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BANG {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo BANG}} \
+ -constraints {testchannel testthread}
+
+test iocmd.tf-29.11 {chan blocking, regular return ok, value ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking ; onfinal ; track ; return BOGUS}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg] ; note $msg
+ catch {close $c}
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 0 {}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method watch
+
+test iocmd.tf-30.1 {chan watch, read interest, some return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return IGNORED}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fileevent $c readable {set tick $tick}]
+ close $c ;# 2nd watch, interest zero.
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{watch rc* read} {watch rc* {}} {}}
+
+test iocmd.tf-30.2 {chan watch, write interest, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return -code error BOOM!_IGNORED}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c writable {}]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{watch rc* write} {watch rc* {}} {} {}}
+
+test iocmd.tf-30.3 {chan watch, accumulated interests} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}]
+ note [fileevent $c writable {}]
+ note [fileevent $c readable {}]
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{watch rc* write} {watch rc* {read write}} {watch rc* read} {watch rc* {}} {} {} {} {}}
+
+test iocmd.tf-30.4 {chan watch, unchanged interest not forwarded} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}] ;# Script is changing,
+ note [fileevent $c readable {set tock $tock}] ;# interest does not.
+ close $c ;# 3rd and 4th watch, removing the event handlers.
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{watch rc* write} {watch rc* {read write}} {watch rc* write} {watch rc* {}} {} {} {}}
+
+# --- === *** ###########################
+# postevent
+# Not possible from a thread not containing the command handler.
+# Check that this is rejected.
+
+test iocmd.tf-31.8 {chan postevent, bad input} -match glob -body {
+ set res {}
+ proc foo {args} {oninit ; onfinal ; track ; return}
+ set c [chan create {r w} foo]
+
+ notes [inthread $c {
+ catch {chan postevent $c r} msg ; note $msg
+ close $c
+ notes
+ } c]
+
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{postevent for channel "rc*" called from outside interpreter}}
+
+
+# ### ### ### ######### ######### #########
+
+# ### ### ### ######### ######### #########
+
+rename track {}
# cleanup
foreach file [list test1 test2 test3 test4] {
removeFile $file