1# -*- tcl -*-
2# Functionality covered: operation of all IO commands, and all procedures
3# defined in generic/tclIO.c.
4#
5# This file contains a collection of tests for one or more of the Tcl built-in
6# commands. Sourcing this file into Tcl runs the tests and generates output
7# for errors. No output means no errors were found.
8#
9# Copyright (c) 1991-1994 The Regents of the University of California.
10# Copyright (c) 1994-1997 Sun Microsystems, Inc.
11# Copyright (c) 1998-1999 by Scriptics Corporation.
12#
13# See the file "license.terms" for information on usage and redistribution of
14# this file, and for a DISCLAIMER OF ALL WARRANTIES.
15
16if {"::tcltest" ni [namespace children]} {
17    package require tcltest 2.5
18}
19
20namespace eval ::tcl::test::io {
21    namespace import ::tcltest::*
22
23    variable umaskValue
24    variable path
25    variable f
26    variable i
27    variable n
28    variable v
29    variable msg
30    variable expected
31
32    catch {
33	::tcltest::loadTestedCommands
34	package require -exact Tcltest [info patchlevel]
35	set ::tcltestlib [lindex [package ifneeded Tcltest [info patchlevel]] 1]
36    }
37    package require tcltests
38
39    testConstraint testbytestring   [llength [info commands testbytestring]]
40    testConstraint testchannel      [llength [info commands testchannel]]
41    testConstraint testfevent       [llength [info commands testfevent]]
42    testConstraint testchannelevent [llength [info commands testchannelevent]]
43    testConstraint testmainthread   [llength [info commands testmainthread]]
44    testConstraint testservicemode  [llength [info commands testservicemode]]
45    testConstraint notWinCI       [expr {
46	$::tcl_platform(platform) ne "windows" || ![info exists ::env(CI)]}]
47    testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
48
49    # You need a *very* special environment to do some tests.  In particular,
50    # many file systems do not support large-files...
51    testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]
52
53    # some tests can only be run is umask is 2 if "umask" cannot be run, the
54    # tests will be skipped.
55    set umaskValue 0
56    testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]
57
58    testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]
59
60    # set up a long data file for some of the following tests
61
62    set path(longfile) [makeFile {} longfile]
63    set f [open $path(longfile) w]
64    chan configure $f -eofchar {} -translation lf
65    for { set i 0 } { $i < 100 } { incr i} {
66	chan puts $f "#123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
67\#123456789abcdef01
68\#"
69    }
70    chan close $f
71
72    set path(cat) [makeFile {
73	set f stdin
74	if {$argv != ""} {
75	    set f [open [lindex $argv 0]]
76	}
77	chan configure $f -encoding binary -translation lf -blocking 0 -eofchar \x1a
78	chan configure stdout -encoding binary -translation lf -buffering none
79	chan event $f readable "foo $f"
80	proc foo {f} {
81	    set x [chan read $f]
82	    catch {chan puts -nonewline $x}
83	    if {[chan eof $f]} {
84		chan close $f
85		exit 0
86	    }
87	}
88	vwait forever
89    } cat]
90
91    set thisScript [file join [pwd] [info script]]
92
93    proc contents {file} {
94	set f [open $file]
95	chan configure $f -translation binary
96	set a [chan read $f]
97	chan close $f
98	return $a
99    }
100
101    # Wrapper round butt-ugly pipe syntax
102    proc openpipe {{mode r+} args} {
103	open "|[list [interpreter] {*}$args]" $mode
104    }
105
106test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
107    # no test, need to cause an async error.
108} {}
109set path(test1) [makeFile {} test1]
110test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
111    set f [open $path(test1) w]
112    chan configure $f -encoding binary
113    chan puts -nonewline $f "a\u4e4d\0"
114    chan close $f
115    contents $path(test1)
116} "a\x4d\x00"
117test chan-io-1.7 {Tcl_WriteChars: WriteChars} {
118    set f [open $path(test1) w]
119    chan configure $f -encoding shiftjis
120    chan puts -nonewline $f "a\u4e4d\0"
121    chan close $f
122    contents $path(test1)
123} "a\x93\xe1\x00"
124set path(test2) [makeFile {} test2]
125test chan-io-1.8 {Tcl_WriteChars: WriteChars} {
126    # This test written for SF bug #506297.
127    #
128    # Executing this test without the fix for the referenced bug applied to
129    # tcl will cause tcl, more specifically WriteChars, to go into an infinite
130    # loop.
131    set f [open $path(test2) w]
132    chan configure      $f -encoding iso2022-jp
133    chan puts -nonewline $f [format %s%c [string repeat " " 4] 12399]
134    chan close           $f
135    contents $path(test2)
136} "    \x1b\$B\$O\x1b(B"
137test chan-io-1.9 {Tcl_WriteChars: WriteChars} {
138    # When closing a channel with an encoding that appends escape bytes, check
139    # for the case where the escape bytes overflow the current IO buffer. The
140    # bytes should be moved into a new buffer.
141    set data "1234567890 [format %c 12399]"
142    set sizes [list]
143    # With default buffer size
144    set f [open $path(test2) w]
145    chan configure      $f -encoding iso2022-jp
146    chan puts -nonewline $f $data
147    chan close           $f
148    lappend sizes [file size $path(test2)]
149    # With buffer size equal to the length of the data, the escape bytes would
150    # go into the next buffer.
151    set f [open $path(test2) w]
152    chan configure      $f -encoding iso2022-jp -buffersize 16
153    chan puts -nonewline $f $data
154    chan close           $f
155    lappend sizes [file size $path(test2)]
156    # With buffer size that is large enough to hold 1 byte of escaped data,
157    # but not all 3. This should not write the escape bytes to the first
158    # buffer and then again to the second buffer.
159    set f [open $path(test2) w]
160    chan configure      $f -encoding iso2022-jp -buffersize 17
161    chan puts -nonewline $f $data
162    chan close           $f
163    lappend sizes [file size $path(test2)]
164    # With buffer size that can hold 2 out of 3 bytes of escaped data.
165    set f [open $path(test2) w]
166    chan configure      $f -encoding iso2022-jp -buffersize 18
167    chan puts -nonewline $f $data
168    chan close           $f
169    lappend sizes [file size $path(test2)]
170    # With buffer size that can hold all the data and escape bytes.
171    set f [open $path(test2) w]
172    chan configure      $f -encoding iso2022-jp -buffersize 19
173    chan puts -nonewline $f $data
174    chan close           $f
175    lappend sizes [file size $path(test2)]
176} {19 19 19 19 19}
177
178test chan-io-2.1 {WriteBytes} {
179    # loop until all bytes are written
180    set f [open $path(test1) w]
181    chan configure $f  -encoding binary -buffersize 16 -translation crlf
182    chan puts $f "abcdefghijklmnopqrstuvwxyz"
183    chan close $f
184    contents $path(test1)
185} "abcdefghijklmnopqrstuvwxyz\r\n"
186test chan-io-2.2 {WriteBytes: savedLF > 0} {
187    # After flushing buffer, there was a \n left over from the last
188    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.
189    set f [open $path(test1) w]
190    chan configure $f -encoding binary -buffersize 16 -translation crlf
191    chan puts -nonewline $f "123456789012345\n12"
192    set x [list [contents $path(test1)]]
193    chan close $f
194    lappend x [contents $path(test1)]
195} [list "123456789012345\r" "123456789012345\r\n12"]
196test chan-io-2.3 {WriteBytes: flush on line} -body {
197    # Tcl "line" buffering has weird behavior: if current buffer contains a
198    # \n, entire buffer gets flushed.  Logical behavior would be to flush only
199    # up to the \n.
200    set f [open $path(test1) w]
201    chan configure $f -encoding binary -buffering line -translation crlf
202    chan puts -nonewline $f "\n12"
203    contents $path(test1)
204} -cleanup {
205    chan close $f
206} -result "\r\n12"
207test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} {
208    set f [open $path(test1) w]
209     chan configure $f -encoding binary -buffering line -translation lf \
210	     -buffersize 16
211    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
212    set x [list [contents $path(test1)]]
213    chan close $f
214    lappend x [contents $path(test1)]
215} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
216
217test chan-io-3.1 {WriteChars: compatibility with WriteBytes} {
218    # loop until all bytes are written
219    set f [open $path(test1) w]
220    chan configure $f -encoding ascii -buffersize 16 -translation crlf
221    chan puts $f "abcdefghijklmnopqrstuvwxyz"
222    chan close $f
223    contents $path(test1)
224} "abcdefghijklmnopqrstuvwxyz\r\n"
225test chan-io-3.2 {WriteChars: compatibility with WriteBytes: savedLF > 0} {
226    # After flushing buffer, there was a \n left over from the last
227    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.
228    set f [open $path(test1) w]
229    chan configure $f -encoding ascii -buffersize 16 -translation crlf
230    chan puts -nonewline $f "123456789012345\n12"
231    set x [list [contents $path(test1)]]
232    chan close $f
233    lappend x [contents $path(test1)]
234} [list "123456789012345\r" "123456789012345\r\n12"]
235test chan-io-3.3 {WriteChars: compatibility with WriteBytes: flush on line} -body {
236    # Tcl "line" buffering has weird behavior: if current buffer contains a
237    # \n, entire buffer gets flushed.  Logical behavior would be to flush only
238    # up to the \n.
239    set f [open $path(test1) w]
240    chan configure $f -encoding ascii -buffering line -translation crlf
241    chan puts -nonewline $f "\n12"
242    contents $path(test1)
243} -cleanup {
244    chan close $f
245} -result "\r\n12"
246test chan-io-3.4 {WriteChars: loop over stage buffer} {
247    # stage buffer maps to more than can be queued at once.
248    set f [open $path(test1) w]
249    chan configure $f -encoding jis0208 -buffersize 16
250    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
251    set x [list [contents $path(test1)]]
252    chan close $f
253    lappend x [contents $path(test1)]
254} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
255test chan-io-3.5 {WriteChars: saved != 0} {
256    # Bytes produced by UtfToExternal from end of last channel buffer had to
257    # be moved to beginning of next channel buffer to preserve requested
258    # buffersize.
259    set f [open $path(test1) w]
260    chan configure $f -encoding jis0208 -buffersize 17
261    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
262    set x [list [contents $path(test1)]]
263    chan close $f
264    lappend x [contents $path(test1)]
265} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
266test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
267    # One incomplete UTF-8 character at end of staging buffer. Backup in src
268    # to the beginning of that UTF-8 character and try again.
269    #
270    # Translate the first 16 bytes, produce 14 bytes of output, 2 left over
271    # (first two bytes of \uff21 in UTF-8). Given those two bytes try
272    # translating them again, find that no bytes are read produced, and break
273    # to outer loop where those two bytes will have the remaining 4 bytes (the
274    # last byte of \uff21 plus the all of \uff22) appended.
275    set f [open $path(test1) w]
276    chan configure $f -encoding shiftjis -buffersize 16
277    chan puts -nonewline $f "12345678901234\uff21\uff22"
278    set x [list [contents $path(test1)]]
279    chan close $f
280    lappend x [contents $path(test1)]
281} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
282test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
283    # When translating UTF-8 to external, the produced bytes went past end of
284    # the channel buffer. This is done on purpose - we then truncate the bytes
285    # at the end of the partial character to preserve the requested blocksize
286    # on flush. The truncated bytes are moved to the beginning of the next
287    # channel buffer.
288    set f [open $path(test1) w]
289    chan configure $f -encoding jis0208 -buffersize 17
290    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
291    set x [list [contents $path(test1)]]
292    chan close $f
293    lappend x [contents $path(test1)]
294} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
295test chan-io-3.8 {WriteChars: reset sawLF after each buffer} {
296    set f [open $path(test1) w]
297    chan configure $f -encoding ascii -buffering line -translation lf \
298	     -buffersize 16
299    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
300    set x [list [contents $path(test1)]]
301    chan close $f
302    lappend x [contents $path(test1)]
303} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
304
305test chan-io-4.1 {TranslateOutputEOL: lf} {
306    # search for \n
307    set f [open $path(test1) w]
308    chan configure $f -buffering line -translation lf
309    chan puts $f "abcde"
310    set x [list [contents $path(test1)]]
311    chan close $f
312    lappend x [contents $path(test1)]
313} [list "abcde\n" "abcde\n"]
314test chan-io-4.2 {TranslateOutputEOL: cr} {
315    # search for \n, replace with \r
316    set f [open $path(test1) w]
317    chan configure $f -buffering line -translation cr
318    chan puts $f "abcde"
319    set x [list [contents $path(test1)]]
320    chan close $f
321    lappend x [contents $path(test1)]
322} [list "abcde\r" "abcde\r"]
323test chan-io-4.3 {TranslateOutputEOL: crlf} {
324    # simple case: search for \n, replace with \r
325    set f [open $path(test1) w]
326    chan configure $f -buffering line -translation crlf
327    chan puts $f "abcde"
328    set x [list [contents $path(test1)]]
329    chan close $f
330    lappend x [contents $path(test1)]
331} [list "abcde\r\n" "abcde\r\n"]
332test chan-io-4.4 {TranslateOutputEOL: crlf} {
333    # Keep storing more bytes in output buffer until output buffer is full. We
334    # have 13 bytes initially that would turn into 18 bytes. Fill dest buffer
335    # while (dstEnd < dstMax).
336    set f [open $path(test1) w]
337    chan configure $f -translation crlf -buffersize 16
338    chan puts -nonewline $f "1234567\n\n\n\n\nA"
339    set x [list [contents $path(test1)]]
340    chan close $f
341    lappend x [contents $path(test1)]
342} [list "1234567\r\n\r\n\r\n\r\n\r" "1234567\r\n\r\n\r\n\r\n\r\nA"]
343test chan-io-4.5 {TranslateOutputEOL: crlf} {
344    # Check for overflow of the destination buffer
345    set f [open $path(test1) w]
346    chan configure $f -translation crlf -buffersize 12
347    chan puts -nonewline $f "12345678901\n456789012345678901234"
348    chan close $f
349    set x [contents $path(test1)]
350} "12345678901\r\n456789012345678901234"
351
352test chan-io-5.1 {CheckFlush: not full} {
353    set f [open $path(test1) w]
354    chan configure $f
355    chan puts -nonewline $f "12345678901234567890"
356    set x [list [contents $path(test1)]]
357    chan close $f
358    lappend x [contents $path(test1)]
359} [list "" "12345678901234567890"]
360test chan-io-5.2 {CheckFlush: full} {
361    set f [open $path(test1) w]
362    chan configure $f -buffersize 16
363    chan puts -nonewline $f "12345678901234567890"
364    set x [list [contents $path(test1)]]
365    chan close $f
366    lappend x [contents $path(test1)]
367} [list "1234567890123456" "12345678901234567890"]
368test chan-io-5.3 {CheckFlush: not line} {
369    set f [open $path(test1) w]
370    chan configure $f -buffering line
371    chan puts -nonewline $f "12345678901234567890"
372    set x [list [contents $path(test1)]]
373    chan close $f
374    lappend x [contents $path(test1)]
375} [list "" "12345678901234567890"]
376test chan-io-5.4 {CheckFlush: line} {
377    set f [open $path(test1) w]
378    chan configure $f -buffering line -translation lf -encoding ascii
379    chan puts -nonewline $f "1234567890\n1234567890"
380    set x [list [contents $path(test1)]]
381    chan close $f
382    lappend x [contents $path(test1)]
383} [list "1234567890\n1234567890" "1234567890\n1234567890"]
384test chan-io-5.5 {CheckFlush: none} {
385    set f [open $path(test1) w]
386    chan configure $f -buffering none
387    chan puts -nonewline $f "1234567890"
388    set x [list [contents $path(test1)]]
389    chan close $f
390    lappend x [contents $path(test1)]
391} [list "1234567890" "1234567890"]
392
393test chan-io-6.1 {Tcl_GetsObj: working} -body {
394    set f [open $path(test1) w]
395    chan puts $f "foo\nboo"
396    chan close $f
397    set f [open $path(test1)]
398    chan gets $f
399} -cleanup {
400    chan close $f
401} -result {foo}
402test chan-io-6.2 {Tcl_GetsObj: CheckChannelErrors() != 0} emptyTest {
403    # no test, need to cause an async error.
404} {}
405test chan-io-6.3 {Tcl_GetsObj: how many have we used?} -body {
406    # if (bufPtr != NULL) {oldRemoved = bufPtr->nextRemoved}
407    set f [open $path(test1) w]
408    chan configure $f -translation crlf
409    chan puts $f "abc\ndefg"
410    chan close $f
411    set f [open $path(test1)]
412    list [chan tell $f] [chan gets $f line] [chan tell $f] [chan gets $f line] $line
413} -cleanup {
414    chan close $f
415} -result {0 3 5 4 defg}
416test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} -body {
417    set f [open $path(test1) w]
418    chan configure $f -translation binary
419    chan puts $f "\x81\u1234\0"
420    chan close $f
421    set f [open $path(test1)]
422    chan configure $f -translation binary
423    list [chan gets $f line] $line
424} -cleanup {
425    chan close $f
426} -result [list 3 "\x81\x34\x00"]
427test chan-io-6.5 {Tcl_GetsObj: encoding != NULL} -body {
428    set f [open $path(test1) w]
429    chan configure $f -translation binary
430    chan puts $f "\x88\xea\x92\x9a"
431    chan close $f
432    set f [open $path(test1)]
433    chan configure $f -encoding shiftjis
434    list [chan gets $f line] $line
435} -cleanup {
436    chan close $f
437} -result [list 2 "\u4e00\u4e01"]
438set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
439append a $a
440append a $a
441test chan-io-6.6 {Tcl_GetsObj: loop test} -body {
442    # if (dst >= dstEnd)
443    set f [open $path(test1) w]
444    chan puts $f $a
445    chan puts $f hi
446    chan close $f
447    set f [open $path(test1)]
448    list [chan gets $f line] $line
449} -cleanup {
450    chan close $f
451} -result [list 256 $a]
452test chan-io-6.7 {Tcl_GetsObj: error in input} -constraints stdio -body {
453    # if (FilterInputBytes(chanPtr, &gs) != 0)
454    set f [openpipe w+ $path(cat)]
455    chan puts -nonewline $f "hi\nwould"
456    chan flush $f
457    chan gets $f
458    chan configure $f -blocking 0
459    chan gets $f line
460} -cleanup {
461    chan close $f
462} -result {-1}
463test chan-io-6.8 {Tcl_GetsObj: remember if EOF is seen} -body {
464    set f [open $path(test1) w]
465    chan puts $f "abcdef\x1aghijk\nwombat"
466    chan close $f
467    set f [open $path(test1)]
468    chan configure $f -eofchar \x1a
469    list [chan gets $f line] $line [chan gets $f line] $line
470} -cleanup {
471    chan close $f
472} -result {6 abcdef -1 {}}
473test chan-io-6.9 {Tcl_GetsObj: remember if EOF is seen} -body {
474    set f [open $path(test1) w]
475    chan puts $f "abcdefghijk\nwom\u001abat"
476    chan close $f
477    set f [open $path(test1)]
478    chan configure $f -eofchar \x1a
479    list [chan gets $f line] $line [chan gets $f line] $line
480} -cleanup {
481    chan close $f
482} -result {11 abcdefghijk 3 wom}
483# Comprehensive tests
484test chan-io-6.10 {Tcl_GetsObj: lf mode: no chars} -body {
485    set f [open $path(test1) w]
486    chan close $f
487    set f [open $path(test1)]
488    chan configure $f -translation lf
489    list [chan gets $f line] $line
490} -cleanup {
491    chan close $f
492} -result {-1 {}}
493test chan-io-6.11 {Tcl_GetsObj: lf mode: lone \n} -body {
494    set f [open $path(test1) w]
495    chan configure $f -translation lf
496    chan puts -nonewline $f "\n"
497    chan close $f
498    set f [open $path(test1)]
499    chan configure $f -translation lf
500    list [chan gets $f line] $line [chan gets $f line] $line
501} -cleanup {
502    chan close $f
503} -result {0 {} -1 {}}
504test chan-io-6.12 {Tcl_GetsObj: lf mode: lone \r} -body {
505    set f [open $path(test1) w]
506    chan configure $f -translation lf
507    chan puts -nonewline $f "\r"
508    chan close $f
509    set f [open $path(test1)]
510    chan configure $f -translation lf
511    set x [list [chan gets $f line] $line [chan gets $f line] $line]
512} -cleanup {
513    chan close $f
514} -result [list 1 "\r" -1 ""]
515test chan-io-6.13 {Tcl_GetsObj: lf mode: 1 char} -body {
516    set f [open $path(test1) w]
517    chan configure $f -translation lf
518    chan puts -nonewline $f a
519    chan close $f
520    set f [open $path(test1)]
521    chan configure $f -translation lf
522    list [chan gets $f line] $line [chan gets $f line] $line
523} -cleanup {
524    chan close $f
525} -result {1 a -1 {}}
526test chan-io-6.14 {Tcl_GetsObj: lf mode: 1 char followed by EOL} -body {
527    set f [open $path(test1) w]
528    chan configure $f -translation lf
529    chan puts -nonewline $f "a\n"
530    chan close $f
531    set f [open $path(test1)]
532    chan configure $f -translation lf
533    list [chan gets $f line] $line [chan gets $f line] $line
534} -cleanup {
535    chan close $f
536} -result {1 a -1 {}}
537test chan-io-6.15 {Tcl_GetsObj: lf mode: several chars} -body {
538    set f [open $path(test1) w]
539    chan configure $f -translation lf
540    chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
541    chan close $f
542    set f [open $path(test1)]
543    chan configure $f -translation lf
544    list [chan gets $f line] $line [chan gets $f line] $line \
545	[chan gets $f line] $line [chan gets $f line] $line
546} -cleanup {
547    chan close $f
548} -result [list 4 "abcd" 10 "efgh\rijkl\r" 4 "mnop" -1 ""]
549test chan-io-6.16 {Tcl_GetsObj: cr mode: no chars} -body {
550    set f [open $path(test1) w]
551    chan close $f
552    set f [open $path(test1)]
553    chan configure $f -translation cr
554    list [chan gets $f line] $line
555} -cleanup {
556    chan close $f
557} -result {-1 {}}
558test chan-io-6.17 {Tcl_GetsObj: cr mode: lone \n} -body {
559    set f [open $path(test1) w]
560    chan configure $f -translation lf
561    chan puts -nonewline $f "\n"
562    chan close $f
563    set f [open $path(test1)]
564    chan configure $f -translation cr
565    list [chan gets $f line] $line [chan gets $f line] $line
566} -cleanup {
567    chan close $f
568} -result [list 1 "\n" -1 ""]
569test chan-io-6.18 {Tcl_GetsObj: cr mode: lone \r} -body {
570    set f [open $path(test1) w]
571    chan configure $f -translation lf
572    chan puts -nonewline $f "\r"
573    chan close $f
574    set f [open $path(test1)]
575    chan configure $f -translation cr
576    list [chan gets $f line] $line [chan gets $f line] $line
577} -cleanup {
578    chan close $f
579} -result {0 {} -1 {}}
580test chan-io-6.19 {Tcl_GetsObj: cr mode: 1 char} -body {
581    set f [open $path(test1) w]
582    chan configure $f -translation lf
583    chan puts -nonewline $f a
584    chan close $f
585    set f [open $path(test1)]
586    chan configure $f -translation cr
587    list [chan gets $f line] $line [chan gets $f line] $line
588} -cleanup {
589    chan close $f
590} -result {1 a -1 {}}
591test chan-io-6.20 {Tcl_GetsObj: cr mode: 1 char followed by EOL} -body {
592    set f [open $path(test1) w]
593    chan configure $f -translation lf
594    chan puts -nonewline $f "a\r"
595    chan close $f
596    set f [open $path(test1)]
597    chan configure $f -translation cr
598    list [chan gets $f line] $line [chan gets $f line] $line
599} -cleanup {
600    chan close $f
601} -result {1 a -1 {}}
602test chan-io-6.21 {Tcl_GetsObj: cr mode: several chars} -body {
603    set f [open $path(test1) w]
604    chan configure $f -translation lf
605    chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
606    chan close $f
607    set f [open $path(test1)]
608    chan configure $f -translation cr
609    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
610} -cleanup {
611    chan close $f
612} -result [list 9 "abcd\nefgh" 4 "ijkl" 5 "\nmnop" -1 ""]
613test chan-io-6.22 {Tcl_GetsObj: crlf mode: no chars} -body {
614    set f [open $path(test1) w]
615    chan close $f
616    set f [open $path(test1)]
617    chan configure $f -translation crlf
618    list [chan gets $f line] $line
619} -cleanup {
620    chan close $f
621} -result {-1 {}}
622test chan-io-6.23 {Tcl_GetsObj: crlf mode: lone \n} -body {
623    set f [open $path(test1) w]
624    chan configure $f -translation lf
625    chan puts -nonewline $f "\n"
626    chan close $f
627    set f [open $path(test1)]
628    chan configure $f -translation crlf
629    list [chan gets $f line] $line [chan gets $f line] $line
630} -cleanup {
631    chan close $f
632} -result [list 1 "\n" -1 ""]
633test chan-io-6.24 {Tcl_GetsObj: crlf mode: lone \r} -body {
634    set f [open $path(test1) w]
635    chan configure $f -translation lf
636    chan puts -nonewline $f "\r"
637    chan close $f
638    set f [open $path(test1)]
639    chan configure $f -translation crlf
640    list [chan gets $f line] $line [chan gets $f line] $line
641} -cleanup {
642    chan close $f
643} -result [list 1 "\r" -1 ""]
644test chan-io-6.25 {Tcl_GetsObj: crlf mode: \r\r} -body {
645    set f [open $path(test1) w]
646    chan configure $f -translation lf
647    chan puts -nonewline $f "\r\r"
648    chan close $f
649    set f [open $path(test1)]
650    chan configure $f -translation crlf
651    list [chan gets $f line] $line [chan gets $f line] $line
652} -cleanup {
653    chan close $f
654} -result [list 2 "\r\r" -1 ""]
655test chan-io-6.26 {Tcl_GetsObj: crlf mode: \r\n} -body {
656    set f [open $path(test1) w]
657    chan configure $f -translation lf
658    chan puts -nonewline $f "\r\n"
659    chan close $f
660    set f [open $path(test1)]
661    chan configure $f -translation crlf
662    list [chan gets $f line] $line [chan gets $f line] $line
663} -cleanup {
664    chan close $f
665} -result {0 {} -1 {}}
666test chan-io-6.27 {Tcl_GetsObj: crlf mode: 1 char} -body {
667    set f [open $path(test1) w]
668    chan configure $f -translation lf
669    chan puts -nonewline $f a
670    chan close $f
671    set f [open $path(test1)]
672    chan configure $f -translation crlf
673    list [chan gets $f line] $line [chan gets $f line] $line
674} -cleanup {
675    chan close $f
676} -result {1 a -1 {}}
677test chan-io-6.28 {Tcl_GetsObj: crlf mode: 1 char followed by EOL} -body {
678    set f [open $path(test1) w]
679    chan configure $f -translation lf
680    chan puts -nonewline $f "a\r\n"
681    chan close $f
682    set f [open $path(test1)]
683    chan configure $f -translation crlf
684    list [chan gets $f line] $line [chan gets $f line] $line
685} -cleanup {
686    chan close $f
687} -result {1 a -1 {}}
688test chan-io-6.29 {Tcl_GetsObj: crlf mode: several chars} -body {
689    set f [open $path(test1) w]
690    chan configure $f -translation lf
691    chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
692    chan close $f
693    set f [open $path(test1)]
694    chan configure $f -translation crlf
695    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
696} -cleanup {
697    chan close $f
698} -result [list 14 "abcd\nefgh\rijkl" 4 "mnop" -1 ""]
699test chan-io-6.30 {Tcl_GetsObj: crlf mode: buffer exhausted} -constraints {testchannel} -body {
700    # if (eol >= dstEnd)
701    set f [open $path(test1) w]
702    chan configure $f -translation lf
703    chan puts -nonewline $f "123456789012345\r\nabcdefghijklmnoprstuvwxyz"
704    chan close $f
705    set f [open $path(test1)]
706    chan configure $f -translation crlf -buffersize 16
707    list [chan gets $f line] $line [testchannel inputbuffered $f]
708} -cleanup {
709    chan close $f
710} -result [list 15 "123456789012345" 15]
711test chan-io-6.31 {Tcl_GetsObj: crlf mode: buffer exhausted, blocked} -setup {
712    set x ""
713} -constraints {stdio testchannel fileevent} -body {
714    # (FilterInputBytes() != 0)
715    set f [openpipe w+ $path(cat)]
716    chan configure $f -translation {crlf lf} -buffering none
717    chan puts -nonewline $f "bbbbbbbbbbbbbb\r\n123456789012345\r"
718    chan configure $f -buffersize 16
719    lappend x [chan gets $f]
720    chan configure $f -blocking 0
721    lappend x [chan gets $f line] $line [chan blocked $f] \
722	[testchannel inputbuffered $f]
723} -cleanup {
724    chan close $f
725} -result {bbbbbbbbbbbbbb -1 {} 1 16}
726test chan-io-6.32 {Tcl_GetsObj: crlf mode: buffer exhausted, more data} -constraints {testchannel} -body {
727    # not (FilterInputBytes() != 0)
728    set f [open $path(test1) w]
729    chan configure $f -translation lf
730    chan puts -nonewline $f "123456789012345\r\n123"
731    chan close $f
732    set f [open $path(test1)]
733    chan configure $f -translation crlf -buffersize 16
734    list [chan gets $f line] $line [chan tell $f] [testchannel inputbuffered $f]
735} -cleanup {
736    chan close $f
737} -result {15 123456789012345 17 3}
738test chan-io-6.33 {Tcl_GetsObj: crlf mode: buffer exhausted, at eof} -body {
739    # eol still equals dstEnd
740    set f [open $path(test1) w]
741    chan configure $f -translation lf
742    chan puts -nonewline $f "123456789012345\r"
743    chan close $f
744    set f [open $path(test1)]
745    chan configure $f -translation crlf -buffersize 16
746    list [chan gets $f line] $line [chan eof $f]
747} -cleanup {
748    chan close $f
749} -result [list 16 "123456789012345\r" 1]
750test chan-io-6.34 {Tcl_GetsObj: crlf mode: buffer exhausted, not followed by \n} -body {
751    # not (*eol == '\n')
752    set f [open $path(test1) w]
753    chan configure $f -translation lf
754    chan puts -nonewline $f "123456789012345\rabcd\r\nefg"
755    chan close $f
756    set f [open $path(test1)]
757    chan configure $f -translation crlf -buffersize 16
758    list [chan gets $f line] $line [chan tell $f]
759} -cleanup {
760    chan close $f
761} -result [list 20 "123456789012345\rabcd" 22]
762test chan-io-6.35 {Tcl_GetsObj: auto mode: no chars} -body {
763    set f [open $path(test1) w]
764    chan close $f
765    set f [open $path(test1)]
766    chan configure $f -translation auto
767    list [chan gets $f line] $line
768} -cleanup {
769    chan close $f
770} -result {-1 {}}
771test chan-io-6.36 {Tcl_GetsObj: auto mode: lone \n} -body {
772    set f [open $path(test1) w]
773    chan configure $f -translation lf
774    chan puts -nonewline $f "\n"
775    chan close $f
776    set f [open $path(test1)]
777    chan configure $f -translation auto
778    list [chan gets $f line] $line [chan gets $f line] $line
779} -cleanup {
780    chan close $f
781} -result {0 {} -1 {}}
782test chan-io-6.37 {Tcl_GetsObj: auto mode: lone \r} -body {
783    set f [open $path(test1) w]
784    chan configure $f -translation lf
785    chan puts -nonewline $f "\r"
786    chan close $f
787    set f [open $path(test1)]
788    chan configure $f -translation auto
789    list [chan gets $f line] $line [chan gets $f line] $line
790} -cleanup {
791    chan close $f
792} -result {0 {} -1 {}}
793test chan-io-6.38 {Tcl_GetsObj: auto mode: \r\r} -body {
794    set f [open $path(test1) w]
795    chan configure $f -translation lf
796    chan puts -nonewline $f "\r\r"
797    chan close $f
798    set f [open $path(test1)]
799    chan configure $f -translation auto
800    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
801} -cleanup {
802    chan close $f
803} -result {0 {} 0 {} -1 {}}
804test chan-io-6.39 {Tcl_GetsObj: auto mode: \r\n} -body {
805    set f [open $path(test1) w]
806    chan configure $f -translation lf
807    chan puts -nonewline $f "\r\n"
808    chan close $f
809    set f [open $path(test1)]
810    chan configure $f -translation auto
811    list [chan gets $f line] $line [chan gets $f line] $line
812} -cleanup {
813    chan close $f
814} -result {0 {} -1 {}}
815test chan-io-6.40 {Tcl_GetsObj: auto mode: 1 char} -body {
816    set f [open $path(test1) w]
817    chan configure $f -translation lf
818    chan puts -nonewline $f a
819    chan close $f
820    set f [open $path(test1)]
821    chan configure $f -translation auto
822    list [chan gets $f line] $line [chan gets $f line] $line
823} -cleanup {
824    chan close $f
825} -result {1 a -1 {}}
826test chan-io-6.41 {Tcl_GetsObj: auto mode: 1 char followed by EOL} -body {
827    set f [open $path(test1) w]
828    chan configure $f -translation lf
829    chan puts -nonewline $f "a\r\n"
830    chan close $f
831    set f [open $path(test1)]
832    chan configure $f -translation auto
833    list [chan gets $f line] $line [chan gets $f line] $line
834} -cleanup {
835    chan close $f
836} -result {1 a -1 {}}
837test chan-io-6.42 {Tcl_GetsObj: auto mode: several chars} -setup {
838    set x ""
839} -body {
840    set f [open $path(test1) w]
841    chan configure $f -translation lf
842    chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
843    chan close $f
844    set f [open $path(test1)]
845    chan configure $f -translation auto
846    lappend x [chan gets $f line] $line [chan gets $f line] $line
847    lappend x [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
848} -cleanup {
849    chan close $f
850} -result {4 abcd 4 efgh 4 ijkl 4 mnop -1 {}}
851test chan-io-6.43 {Tcl_GetsObj: input saw cr} -setup {
852    set x ""
853} -constraints {stdio testchannel fileevent} -body {
854    # if (chanPtr->flags & INPUT_SAW_CR)
855    set f [openpipe w+ $path(cat)]
856    chan configure $f -translation {auto lf} -buffering none
857    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
858    chan configure $f -buffersize 16
859    lappend x [chan gets $f]
860    chan configure $f -blocking 0
861    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
862    chan configure $f -blocking 1
863    chan puts -nonewline $f "\nabcd\refg\x1a"
864    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
865    lappend x [chan gets $f line] $line
866} -cleanup {
867    chan close $f
868} -result {bbbbbbbbbbbbbbb 15 123456789abcdef 1 4 abcd 0 3 efg}
869test chan-io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} -setup {
870    set x ""
871} -constraints {stdio testchannel fileevent} -body {
872    # not (*eol == '\n')
873    set f [openpipe w+ $path(cat)]
874    chan configure $f -translation {auto lf} -buffering none
875    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
876    chan configure $f -buffersize 16
877    lappend x [chan gets $f]
878    chan configure $f -blocking 0
879    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
880    chan configure $f -blocking 1
881    chan puts -nonewline $f "abcd\refg\x1a"
882    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
883    lappend x [chan gets $f line] $line
884} -cleanup {
885    chan close $f
886} -result {bbbbbbbbbbbbbbb 15 123456789abcdef 1 4 abcd 0 3 efg}
887test chan-io-6.45 {Tcl_GetsObj: input saw cr, skip right number of bytes} -setup {
888    set x ""
889} -constraints {stdio testchannel fileevent} -body {
890    # Tcl_ExternalToUtf()
891    set f [openpipe w+ $path(cat)]
892    chan configure $f -translation {auto lf} -buffering none
893    chan configure $f -encoding unicode
894    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
895    chan configure $f -buffersize 16
896    chan gets $f
897    chan configure $f -blocking 0
898    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
899    chan configure $f -blocking 1
900    chan puts -nonewline $f "\nabcd\refg"
901    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
902} -cleanup {
903    chan close $f
904} -result {15 123456789abcdef 1 4 abcd 0}
905test chan-io-6.46 {Tcl_GetsObj: input saw cr, followed by just \n should give eof} -setup {
906    set x ""
907} -constraints {stdio testchannel fileevent} -body {
908    # memmove()
909    set f [openpipe w+ $path(cat)]
910    chan configure $f -translation {auto lf} -buffering none
911    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
912    chan configure $f -buffersize 16
913    chan gets $f
914    chan configure $f -blocking 0
915    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
916    chan configure $f -blocking 1
917    chan puts -nonewline $f "\n\x1a"
918    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
919} -cleanup {
920    chan close $f
921} -result {15 123456789abcdef 1 -1 {} 0}
922test chan-io-6.47 {Tcl_GetsObj: auto mode: \r at end of buffer, peek for \n} -constraints {testchannel} -body {
923    # (eol == dstEnd)
924    set f [open $path(test1) w]
925    chan configure $f -translation lf
926    chan puts -nonewline $f "123456789012345\r\nabcdefghijklmnopq"
927    chan close $f
928    set f [open $path(test1)]
929    chan configure $f -translation auto -buffersize 16
930    list [chan gets $f] [testchannel inputbuffered $f]
931} -cleanup {
932    chan close $f
933} -result {123456789012345 15}
934test chan-io-6.48 {Tcl_GetsObj: auto mode: \r at end of buffer, no more avail} -constraints {testchannel} -body {
935    # PeekAhead() did not get any, so (eol >= dstEnd)
936    set f [open $path(test1) w]
937    chan configure $f -translation lf
938    chan puts -nonewline $f "123456789012345\r"
939    chan close $f
940    set f [open $path(test1)]
941    chan configure $f -translation auto -buffersize 16
942    list [chan gets $f] [testchannel queuedcr $f]
943} -cleanup {
944    chan close $f
945} -result {123456789012345 1}
946test chan-io-6.49 {Tcl_GetsObj: auto mode: \r followed by \n} -constraints {testchannel} -body {
947    # if (*eol == '\n') {skip++}
948    set f [open $path(test1) w]
949    chan configure $f -translation lf
950    chan puts -nonewline $f "123456\r\n78901"
951    chan close $f
952    set f [open $path(test1)]
953    list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]
954} -cleanup {
955    chan close $f
956} -result {123456 0 8 78901}
957test chan-io-6.50 {Tcl_GetsObj: auto mode: \r not followed by \n} -constraints {testchannel} -body {
958    # not (*eol == '\n')
959    set f [open $path(test1) w]
960    chan configure $f -translation lf
961    chan puts -nonewline $f "123456\r78901"
962    chan close $f
963    set f [open $path(test1)]
964    list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]
965} -cleanup {
966    chan close $f
967} -result {123456 0 7 78901}
968test chan-io-6.51 {Tcl_GetsObj: auto mode: \n} -body {
969    # else if (*eol == '\n') {goto gotoeol;}
970    set f [open $path(test1) w]
971    chan configure $f -translation lf
972    chan puts -nonewline $f "123456\n78901"
973    chan close $f
974    set f [open $path(test1)]
975    list [chan gets $f] [chan tell $f] [chan gets $f]
976} -cleanup {
977    chan close $f
978} -result {123456 7 78901}
979test chan-io-6.52 {Tcl_GetsObj: saw EOF character} -constraints {testchannel} -body {
980    # if (eof != NULL)
981    set f [open $path(test1) w]
982    chan configure $f -translation lf
983    chan puts -nonewline $f "123456\x1ak9012345\r"
984    chan close $f
985    set f [open $path(test1)]
986    chan configure $f -eofchar \x1a
987    list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]
988} -cleanup {
989    chan close $f
990} -result {123456 0 6 {}}
991test chan-io-6.53 {Tcl_GetsObj: device EOF} -body {
992    # didn't produce any bytes
993    set f [open $path(test1) w]
994    chan close $f
995    set f [open $path(test1)]
996    list [chan gets $f line] $line [chan eof $f]
997} -cleanup {
998    chan close $f
999} -result {-1 {} 1}
1000test chan-io-6.54 {Tcl_GetsObj: device EOF} -body {
1001    # got some bytes before EOF.
1002    set f [open $path(test1) w]
1003    chan puts -nonewline $f abc
1004    chan close $f
1005    set f [open $path(test1)]
1006    list [chan gets $f line] $line [chan eof $f]
1007} -cleanup {
1008    chan close $f
1009} -result {3 abc 1}
1010test chan-io-6.55 {Tcl_GetsObj: overconverted} -body {
1011    # Tcl_ExternalToUtf(), make sure state updated
1012    set f [open $path(test1) w]
1013    chan configure $f -encoding iso2022-jp
1014    chan puts $f "there\u4e00ok\n\u4e01more bytes\nhere"
1015    chan close $f
1016    set f [open $path(test1)]
1017    chan configure $f -encoding iso2022-jp
1018    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
1019} -cleanup {
1020    chan close $f
1021} -result [list 8 "there\u4e00ok" 11 "\u4e01more bytes" 4 "here"]
1022test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup {
1023    update
1024    variable x {}
1025} -constraints {stdio fileevent} -body {
1026    set f [openpipe w+ $path(cat)]
1027    chan configure $f -buffering none
1028    chan puts -nonewline $f "foobar"
1029    chan configure $f -blocking 0
1030    after 500 [namespace code {
1031	lappend x timeout
1032    }]
1033    chan event $f readable [namespace code {
1034	lappend x [chan gets $f]
1035    }]
1036    vwait [namespace which -variable x]
1037    vwait [namespace which -variable x]
1038    chan configure $f -blocking 1
1039    chan puts -nonewline $f "baz\n"
1040    after 500 [namespace code {
1041	lappend x timeout
1042    }]
1043    chan configure $f -blocking 0
1044    vwait [namespace which -variable x]
1045    vwait [namespace which -variable x]
1046    return $x
1047} -cleanup {
1048    chan close $f
1049} -result {{} timeout foobarbaz timeout}
1050
1051test chan-io-7.1 {FilterInputBytes: split up character at end of buffer} -body {
1052    # (result == TCL_CONVERT_MULTIBYTE)
1053    set f [open $path(test1) w]
1054    chan configure $f -encoding shiftjis
1055    chan puts $f "1234567890123\uff10\uff11\uff12\uff13\uff14\nend"
1056    chan close $f
1057    set f [open $path(test1)]
1058    chan configure $f -encoding shiftjis -buffersize 16
1059    chan gets $f
1060} -cleanup {
1061    chan close $f
1062} -result "1234567890123\uff10\uff11\uff12\uff13\uff14"
1063test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} -body {
1064    # (bufPtr->nextAdded < bufPtr->bufLength)
1065    set f [open $path(test1) w]
1066    chan configure $f -encoding binary
1067    chan puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
1068    chan close $f
1069    set f [open $path(test1)]
1070    chan configure $f -encoding shiftjis
1071    list [chan gets $f line] $line [chan eof $f]
1072} -cleanup {
1073    chan close $f
1074} -result {10 1234567890 0}
1075test chan-io-7.3 {FilterInputBytes: split up character at EOF} -setup {
1076    set x ""
1077} -constraints {testchannel} -body {
1078    set f [open $path(test1) w]
1079    chan configure $f -encoding binary
1080    chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
1081    chan close $f
1082    set f [open $path(test1)]
1083    chan configure $f -encoding shiftjis
1084    lappend x [chan gets $f line] $line
1085    lappend x [chan tell $f] [testchannel inputbuffered $f] [chan eof $f]
1086    lappend x [chan gets $f line] $line
1087} -cleanup {
1088    chan close $f
1089} -result [list 15 "1234567890123\uff10\uff11" 18 0 1 -1 ""]
1090test chan-io-7.4 {FilterInputBytes: recover from split up character} -setup {
1091    variable x ""
1092} -constraints {stdio fileevent} -body {
1093    set f [openpipe w+ $path(cat)]
1094    chan configure $f -encoding binary -buffering none
1095    chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
1096    chan configure $f -encoding shiftjis -blocking 0
1097    chan event $f read [namespace code {
1098	lappend x [chan gets $f line] $line [chan blocked $f]
1099    }]
1100    vwait [namespace which -variable x]
1101    chan configure $f -encoding binary -blocking 1
1102    chan puts $f "\x51\x82\x52"
1103    chan configure $f -encoding shiftjis
1104    vwait [namespace which -variable x]
1105    return $x
1106} -cleanup {
1107    chan close $f
1108} -result [list -1 "" 1 17 "1234567890123\uff10\uff11\uff12\uff13" 0]
1109
1110test chan-io-8.1 {PeekAhead: only go to device if no more cached data} -constraints {testchannel} -body {
1111    # (bufPtr->nextPtr == NULL)
1112    set f [open $path(test1) w]
1113    chan configure $f -encoding ascii -translation lf
1114    chan puts -nonewline $f "123456789012345\r\n2345678"
1115    chan close $f
1116    set f [open $path(test1)]
1117    chan configure $f -encoding ascii -translation auto -buffersize 16
1118    # here
1119    chan gets $f
1120    testchannel inputbuffered $f
1121} -cleanup {
1122    chan close $f
1123} -result 7
1124test chan-io-8.2 {PeekAhead: only go to device if no more cached data} -setup {
1125    variable x {}
1126} -constraints {stdio testchannel fileevent} -body {
1127    # not (bufPtr->nextPtr == NULL)
1128    set f [openpipe w+ $path(cat)]
1129    chan configure $f -translation lf -encoding ascii -buffering none
1130    chan puts -nonewline $f "123456789012345\r\nbcdefghijklmnopqrstuvwxyz"
1131    chan event $f read [namespace code {
1132	lappend x [chan gets $f line] $line [testchannel inputbuffered $f]
1133    }]
1134    chan configure $f -encoding unicode -buffersize 16 -blocking 0
1135    vwait [namespace which -variable x]
1136    chan configure $f -translation auto -encoding ascii -blocking 1
1137    # here
1138    vwait [namespace which -variable x]
1139    return $x
1140} -cleanup {
1141    chan close $f
1142} -result {-1 {} 42 15 123456789012345 25}
1143test chan-io-8.3 {PeekAhead: no cached data available} -constraints {stdio testchannel fileevent} -body {
1144    # (bytesLeft == 0)
1145    set f [openpipe w+ $path(cat)]
1146    chan configure $f -translation {auto binary}
1147    chan puts -nonewline $f "abcdefghijklmno\r"
1148    chan flush $f
1149    list [chan gets $f line] $line [testchannel queuedcr $f]
1150} -cleanup {
1151    chan close $f
1152} -result {15 abcdefghijklmno 1}
1153set a "123456789012345678901234567890"
1154append a "123456789012345678901234567890"
1155append a "1234567890123456789012345678901"
1156test chan-io-8.4 {PeekAhead: cached data available in this buffer} -body {
1157    # not (bytesLeft == 0)
1158    set f [open $path(test1) w+]
1159    chan configure $f -translation binary
1160    chan puts $f "${a}\r\nabcdef"
1161    chan close $f
1162    set f [open $path(test1)]
1163    chan configure $f -encoding binary -translation auto
1164    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE is
1165    # 30). To check if "\n" follows, calls PeekAhead and determines that
1166    # cached data is available in buffer w/o having to call driver.
1167    chan gets $f
1168} -cleanup {
1169    chan close $f
1170} -result $a
1171unset a
1172test chan-io-8.5 {PeekAhead: don't peek if last read was short} -constraints {stdio testchannel fileevent} -body {
1173    # (bufPtr->nextAdded < bufPtr->length)
1174    set f [openpipe w+ $path(cat)]
1175    chan configure $f -translation {auto binary}
1176    chan puts -nonewline $f "abcdefghijklmno\r"
1177    chan flush $f
1178    # here
1179    list [chan gets $f line] $line [testchannel queuedcr $f]
1180} -cleanup {
1181    chan close $f
1182} -result {15 abcdefghijklmno 1}
1183test chan-io-8.6 {PeekAhead: change to non-blocking mode} -constraints {stdio testchannel fileevent} -body {
1184    # ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0)
1185    set f [openpipe w+ $path(cat)]
1186    chan configure $f -translation {auto binary} -buffersize 16
1187    chan puts -nonewline $f "abcdefghijklmno\r"
1188    chan flush $f
1189    # here
1190    list [chan gets $f line] $line [testchannel queuedcr $f]
1191} -cleanup {
1192    chan close $f
1193} -result {15 abcdefghijklmno 1}
1194test chan-io-8.7 {PeekAhead: cleanup} -setup {
1195    set x ""
1196} -constraints {stdio testchannel fileevent} -body {
1197    # Make sure bytes are removed from buffer.
1198    set f [openpipe w+ $path(cat)]
1199    chan configure $f -translation {auto binary} -buffering none
1200    chan puts -nonewline $f "abcdefghijklmno\r"
1201    # here
1202    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
1203    chan puts -nonewline $f "\x1a"
1204    lappend x [chan gets $f line] $line
1205} -cleanup {
1206    chan close $f
1207} -result {15 abcdefghijklmno 1 -1 {}}
1208
1209test chan-io-9.1 {CommonGetsCleanup} emptyTest {
1210} {}
1211
1212test chan-io-10.1 {Tcl_ReadChars: CheckChannelErrors} emptyTest {
1213    # no test, need to cause an async error.
1214} {}
1215test chan-io-10.2 {Tcl_ReadChars: loop until enough copied} -body {
1216    # one time
1217    # for (copied = 0; (unsigned) toRead > 0; )
1218    set f [open $path(test1) w]
1219    chan puts $f abcdefghijklmnop
1220    chan close $f
1221    set f [open $path(test1)]
1222    chan read $f 5
1223} -cleanup {
1224    chan close $f
1225} -result {abcde}
1226test chan-io-10.3 {Tcl_ReadChars: loop until enough copied} -body {
1227    # multiple times
1228    # for (copied = 0; (unsigned) toRead > 0; )
1229    set f [open $path(test1) w]
1230    chan puts $f abcdefghijklmnopqrstuvwxyz
1231    chan close $f
1232    set f [open $path(test1)]
1233    chan configure $f -buffersize 16
1234    # here
1235    chan read $f 19
1236} -cleanup {
1237    chan close $f
1238} -result {abcdefghijklmnopqrs}
1239test chan-io-10.4 {Tcl_ReadChars: no more in channel buffer} -body {
1240    # (copiedNow < 0)
1241    set f [open $path(test1) w]
1242    chan puts -nonewline $f abcdefghijkl
1243    chan close $f
1244    set f [open $path(test1)]
1245    # here
1246    chan read $f 1000
1247} -cleanup {
1248    chan close $f
1249} -result {abcdefghijkl}
1250test chan-io-10.5 {Tcl_ReadChars: stop on EOF} -body {
1251    # (chanPtr->flags & CHANNEL_EOF)
1252    set f [open $path(test1) w]
1253    chan puts -nonewline $f abcdefghijkl
1254    chan close $f
1255    set f [open $path(test1)]
1256    # here
1257    chan read $f 1000
1258} -cleanup {
1259    chan close $f
1260} -result {abcdefghijkl}
1261
1262test chan-io-11.1 {ReadBytes: want to read a lot} -body {
1263    # ((unsigned) toRead > (unsigned) srcLen)
1264    set f [open $path(test1) w]
1265    chan puts -nonewline $f abcdefghijkl
1266    chan close $f
1267    set f [open $path(test1)]
1268    chan configure $f -encoding binary
1269    # here
1270    chan read $f 1000
1271} -cleanup {
1272    chan close $f
1273} -result {abcdefghijkl}
1274test chan-io-11.2 {ReadBytes: want to read all} -body {
1275    # ((unsigned) toRead > (unsigned) srcLen)
1276    set f [open $path(test1) w]
1277    chan puts -nonewline $f abcdefghijkl
1278    chan close $f
1279    set f [open $path(test1)]
1280    chan configure $f -encoding binary
1281    # here
1282    chan read $f
1283} -cleanup {
1284    chan close $f
1285} -result {abcdefghijkl}
1286test chan-io-11.3 {ReadBytes: allocate more space} -body {
1287    # (toRead > length - offset - 1)
1288    set f [open $path(test1) w]
1289    chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz
1290    chan close $f
1291    set f [open $path(test1)]
1292    chan configure $f -buffersize 16 -encoding binary
1293    # here
1294    chan read $f
1295} -cleanup {
1296    chan close $f
1297} -result {abcdefghijklmnopqrstuvwxyz}
1298test chan-io-11.4 {ReadBytes: EOF char found} -body {
1299    # (TranslateInputEOL() != 0)
1300    set f [open $path(test1) w]
1301    chan puts $f abcdefghijklmnopqrstuvwxyz
1302    chan close $f
1303    set f [open $path(test1)]
1304    chan configure $f -eofchar m -encoding binary
1305    # here
1306    list [chan read $f] [chan eof $f] [chan read $f] [chan eof $f]
1307} -cleanup {
1308    chan close $f
1309} -result {abcdefghijkl 1 {} 1}
1310
1311test chan-io-12.1 {ReadChars: want to read a lot} -body {
1312    # ((unsigned) toRead > (unsigned) srcLen)
1313    set f [open $path(test1) w]
1314    chan puts -nonewline $f abcdefghijkl
1315    chan close $f
1316    set f [open $path(test1)]
1317    # here
1318    chan read $f 1000
1319} -cleanup {
1320    chan close $f
1321} -result {abcdefghijkl}
1322test chan-io-12.2 {ReadChars: want to read all} -body {
1323    # ((unsigned) toRead > (unsigned) srcLen)
1324    set f [open $path(test1) w]
1325    chan puts -nonewline $f abcdefghijkl
1326    chan close $f
1327    set f [open $path(test1)]
1328    # here
1329    chan read $f
1330} -cleanup {
1331    chan close $f
1332} -result {abcdefghijkl}
1333test chan-io-12.3 {ReadChars: allocate more space} -body {
1334    # (toRead > length - offset - 1)
1335    set f [open $path(test1) w]
1336    chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz
1337    chan close $f
1338    set f [open $path(test1)]
1339    chan configure $f -buffersize 16
1340    # here
1341    chan read $f
1342} -cleanup {
1343    chan close $f
1344} -result {abcdefghijklmnopqrstuvwxyz}
1345test chan-io-12.4 {ReadChars: split-up char} -setup {
1346    variable x {}
1347} -constraints {stdio testchannel fileevent} -body {
1348    # (srcRead == 0)
1349    set f [openpipe w+ $path(cat)]
1350    chan configure $f -encoding binary -buffering none -buffersize 16
1351    chan puts -nonewline $f "123456789012345\x96"
1352    chan configure $f -encoding shiftjis -blocking 0
1353    chan event $f read [namespace code {
1354	lappend x [chan read $f] [testchannel inputbuffered $f]
1355    }]
1356    chan configure $f -encoding shiftjis
1357    vwait [namespace which -variable x]
1358    chan configure $f -encoding binary -blocking 1
1359    chan puts -nonewline $f "\x7b"
1360    after 500			;# Give the cat process time to catch up
1361    chan configure $f -encoding shiftjis -blocking 0
1362    vwait [namespace which -variable x]
1363    return $x
1364} -cleanup {
1365    chan close $f
1366} -result [list "123456789012345" 1 "\u672c" 0]
1367test chan-io-12.5 {ReadChars: chan events on partial characters} -setup {
1368    variable x {}
1369} -constraints {stdio fileevent} -body {
1370    set path(test1) [makeFile {
1371	chan configure stdout -encoding binary -buffering none
1372	chan gets stdin; chan puts -nonewline "\xe7"
1373	chan gets stdin; chan puts -nonewline "\x89"
1374	chan gets stdin; chan puts -nonewline "\xa6"
1375    } test1]
1376    set f [openpipe r+ $path(test1)]
1377    chan event $f readable [namespace code {
1378	lappend x [chan read $f]
1379	if {[chan eof $f]} {
1380	    lappend x eof
1381	}
1382    }]
1383    chan puts $f "go1"
1384    chan flush $f
1385    chan configure $f -blocking 0 -encoding utf-8
1386    vwait [namespace which -variable x]
1387    after 500 [namespace code { lappend x timeout }]
1388    vwait [namespace which -variable x]
1389    chan puts $f "go2"
1390    chan flush $f
1391    vwait [namespace which -variable x]
1392    after 500 [namespace code { lappend x timeout }]
1393    vwait [namespace which -variable x]
1394    chan puts $f "go3"
1395    chan flush $f
1396    vwait [namespace which -variable x]
1397    vwait [namespace which -variable x]
1398    lappend x [catch {chan close $f} msg] $msg
1399} -result "{} timeout {} timeout \u7266 {} eof 0 {}"
1400
1401test chan-io-13.1 {TranslateInputEOL: cr mode} -body {
1402    set f [open $path(test1) w]
1403    chan configure $f -translation lf
1404    chan puts -nonewline $f "abcd\rdef\r"
1405    chan close $f
1406    set f [open $path(test1)]
1407    chan configure $f -translation cr
1408    chan read $f
1409} -cleanup {
1410    chan close $f
1411} -result "abcd\ndef\n"
1412test chan-io-13.2 {TranslateInputEOL: crlf mode} -body {
1413    set f [open $path(test1) w]
1414    chan configure $f -translation lf
1415    chan puts -nonewline $f "abcd\r\ndef\r\n"
1416    chan close $f
1417    set f [open $path(test1)]
1418    chan configure $f -translation crlf
1419    chan read $f
1420} -cleanup {
1421    chan close $f
1422} -result "abcd\ndef\n"
1423test chan-io-13.3 {TranslateInputEOL: crlf mode: naked cr} -body {
1424    # (src >= srcMax)
1425    set f [open $path(test1) w]
1426    chan configure $f -translation lf
1427    chan puts -nonewline $f "abcd\r\ndef\r"
1428    chan close $f
1429    set f [open $path(test1)]
1430    chan configure $f -translation crlf
1431    chan read $f
1432} -cleanup {
1433    chan close $f
1434} -result "abcd\ndef\r"
1435test chan-io-13.4 {TranslateInputEOL: crlf mode: cr followed by not \n} -body {
1436    # (src >= srcMax)
1437    set f [open $path(test1) w]
1438    chan configure $f -translation lf
1439    chan puts -nonewline $f "abcd\r\ndef\rfgh"
1440    chan close $f
1441    set f [open $path(test1)]
1442    chan configure $f -translation crlf
1443    chan read $f
1444} -cleanup {
1445    chan close $f
1446} -result "abcd\ndef\rfgh"
1447test chan-io-13.5 {TranslateInputEOL: crlf mode: naked lf} -body {
1448    # (src >= srcMax)
1449    set f [open $path(test1) w]
1450    chan configure $f -translation lf
1451    chan puts -nonewline $f "abcd\r\ndef\nfgh"
1452    chan close $f
1453    set f [open $path(test1)]
1454    chan configure $f -translation crlf
1455    chan read $f
1456} -cleanup {
1457    chan close $f
1458} -result "abcd\ndef\nfgh"
1459test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} -setup {
1460    variable x {}
1461    variable y {}
1462} -constraints {stdio testchannel fileevent} -body {
1463    # (chanPtr->flags & INPUT_SAW_CR)
1464    # This test may fail on slower machines.
1465    set f [openpipe w+ $path(cat)]
1466    chan configure $f -blocking 0 -buffering none -translation {auto lf}
1467    chan event $f read [namespace code {
1468	lappend x [chan read $f] [testchannel queuedcr $f]
1469    }]
1470    chan puts -nonewline $f "abcdefghj\r"
1471    after 500 [namespace code {set y ok}]
1472    vwait [namespace which -variable y]
1473    chan puts -nonewline $f "\n01234"
1474    after 500 [namespace code {set y ok}]
1475    vwait [namespace which -variable y]
1476    return $x
1477} -cleanup {
1478    chan close $f
1479} -result [list "abcdefghj\n" 1 "01234" 0]
1480test chan-io-13.7 {TranslateInputEOL: auto mode: naked \r} -constraints testchannel -body {
1481    # (src >= srcMax)
1482    set f [open $path(test1) w]
1483    chan configure $f -translation lf
1484    chan puts -nonewline $f "abcd\r"
1485    chan close $f
1486    set f [open $path(test1)]
1487    chan configure $f -translation auto
1488    list [chan read $f] [testchannel queuedcr $f]
1489} -cleanup {
1490    chan close $f
1491} -result [list "abcd\n" 1]
1492test chan-io-13.8 {TranslateInputEOL: auto mode: \r\n} -body {
1493    # (*src == '\n')
1494    set f [open $path(test1) w]
1495    chan configure $f -translation lf
1496    chan puts -nonewline $f "abcd\r\ndef"
1497    chan close $f
1498    set f [open $path(test1)]
1499    chan configure $f -translation auto
1500    chan read $f
1501} -cleanup {
1502    chan close $f
1503} -result "abcd\ndef"
1504test chan-io-13.9 {TranslateInputEOL: auto mode: \r followed by not \n} -body {
1505    set f [open $path(test1) w]
1506    chan configure $f -translation lf
1507    chan puts -nonewline $f "abcd\rdef"
1508    chan close $f
1509    set f [open $path(test1)]
1510    chan configure $f -translation auto
1511    chan read $f
1512} -cleanup {
1513    chan close $f
1514} -result "abcd\ndef"
1515test chan-io-13.10 {TranslateInputEOL: auto mode: \n} -body {
1516    # not (*src == '\r')
1517    set f [open $path(test1) w]
1518    chan configure $f -translation lf
1519    chan puts -nonewline $f "abcd\ndef"
1520    chan close $f
1521    set f [open $path(test1)]
1522    chan configure $f -translation auto
1523    chan read $f
1524} -cleanup {
1525    chan close $f
1526} -result "abcd\ndef"
1527test chan-io-13.11 {TranslateInputEOL: EOF char} -body {
1528    # (*chanPtr->inEofChar != '\0')
1529    set f [open $path(test1) w]
1530    chan configure $f -translation lf
1531    chan puts -nonewline $f "abcd\ndefgh"
1532    chan close $f
1533    set f [open $path(test1)]
1534    chan configure $f -translation auto -eofchar e
1535    chan read $f
1536} -cleanup {
1537    chan close $f
1538} -result "abcd\nd"
1539test chan-io-13.12 {TranslateInputEOL: find EOF char in src} -body {
1540    # (*chanPtr->inEofChar != '\0')
1541    set f [open $path(test1) w]
1542    chan configure $f -translation lf
1543    chan puts -nonewline $f "\r\n\r\n\r\nab\r\n\r\ndef\r\n\r\n\r\n"
1544    chan close $f
1545    set f [open $path(test1)]
1546    chan configure $f -translation auto -eofchar e
1547    chan read $f
1548} -cleanup {
1549    chan close $f
1550} -result "\n\n\nab\n\nd"
1551
1552# Test standard handle management. The functions tested are Tcl_SetStdChannel
1553# and Tcl_GetStdChannel. Incidentally we are also testing channel table
1554# management.
1555
1556if {[testConstraint testchannel]} {
1557    set consoleFileNames [lsort [testchannel open]]
1558} else {
1559    # just to avoid an error
1560    set consoleFileNames [list]
1561}
1562
1563test chan-io-14.1 {Tcl_SetStdChannel and Tcl_GetStdChannel} {testchannel} {
1564    set result ""
1565    lappend result [chan configure stdin -buffering]
1566    lappend result [chan configure stdout -buffering]
1567    lappend result [chan configure stderr -buffering]
1568    lappend result [lsort [testchannel open]]
1569} [list line line none $consoleFileNames]
1570test chan-io-14.2 {Tcl_SetStdChannel and Tcl_GetStdChannel} -setup {
1571    interp create x
1572    set result ""
1573} -body {
1574    lappend result [x eval {chan configure stdin -buffering}]
1575    lappend result [x eval {chan configure stdout -buffering}]
1576    lappend result [x eval {chan configure stderr -buffering}]
1577} -cleanup {
1578    interp delete x
1579} -result {line line none}
1580set path(test3) [makeFile {} test3]
1581test chan-io-14.3 {Tcl_SetStdChannel & Tcl_GetStdChannel} -constraints exec -body {
1582    set f [open $path(test1) w]
1583    chan puts -nonewline $f {
1584	chan close stdin
1585	chan close stdout
1586	chan close stderr
1587	set f  [}
1588    chan puts $f [list open $path(test1) r]]
1589    chan puts $f "set f2 \[[list open $path(test2) w]]"
1590    chan puts $f "set f3 \[[list open $path(test3) w]]"
1591    chan puts $f {	chan puts stdout [chan gets stdin]
1592	chan puts stdout out
1593	chan puts stderr err
1594	chan close $f
1595	chan close $f2
1596	chan close $f3
1597    }
1598    chan close $f
1599    set result [exec [interpreter] $path(test1)]
1600    set f  [open $path(test2) r]
1601    set f2 [open $path(test3) r]
1602    lappend result [chan read $f] [chan read $f2]
1603} -cleanup {
1604    chan close $f
1605    chan close $f2
1606} -result {{
1607out
1608} {err
1609}}
1610# This test relies on the fact that stdout is used before stderr.
1611test chan-io-14.4 {Tcl_SetStdChannel & Tcl_GetStdChannel} -constraints {exec} -body {
1612    set f [open $path(test1) w]
1613    chan puts -nonewline $f { chan close stdin
1614	chan close stdout
1615	chan close stderr
1616	set f  [}
1617    chan puts $f [list open $path(test1) r]]
1618    chan puts $f "set f2 \[[list open $path(test2) w]]"
1619    chan puts $f "set f3 \[[list open $path(test3) w]]"
1620    chan puts $f {
1621	chan puts stdout [chan gets stdin]
1622	chan puts stdout $f2
1623	chan puts stderr $f3
1624	chan close $f
1625	chan close $f2
1626	chan close $f3
1627    }
1628    chan close $f
1629    set result [exec [interpreter] $path(test1)]
1630    set f  [open $path(test2) r]
1631    set f2 [open $path(test3) r]
1632    lappend result [chan read $f] [chan read $f2]
1633} -cleanup {
1634    chan close $f
1635    chan close $f2
1636} -result {{ chan close stdin
1637stdout
1638} {stderr
1639}}
1640catch {interp delete z}
1641test chan-io-14.5 {Tcl_GetChannel: stdio name translation} -setup {
1642    interp create z
1643} -body {
1644    chan eof stdin
1645    catch {z eval chan flush stdin} msg1
1646    catch {z eval chan close stdin} msg2
1647    catch {z eval chan flush stdin} msg3
1648    list $msg1 $msg2 $msg3
1649} -cleanup {
1650    interp delete z
1651} -result {{channel "stdin" wasn't opened for writing} {} {can not find channel named "stdin"}}
1652test chan-io-14.6 {Tcl_GetChannel: stdio name translation} -setup {
1653    interp create z
1654} -body {
1655    chan eof stdout
1656    catch {z eval chan flush stdout} msg1
1657    catch {z eval chan close stdout} msg2
1658    catch {z eval chan flush stdout} msg3
1659    list $msg1 $msg2 $msg3
1660} -cleanup {
1661    interp delete z
1662} -result {{} {} {can not find channel named "stdout"}}
1663test chan-io-14.7 {Tcl_GetChannel: stdio name translation} -setup {
1664    interp create z
1665} -body {
1666    chan eof stderr
1667    catch {z eval chan flush stderr} msg1
1668    catch {z eval chan close stderr} msg2
1669    catch {z eval chan flush stderr} msg3
1670    list $msg1 $msg2 $msg3
1671} -cleanup {
1672    interp delete z
1673} -result {{} {} {can not find channel named "stderr"}}
1674set path(script) [makeFile {} script]
1675test chan-io-14.8 {reuse of stdio special channels} -setup {
1676    file delete $path(script)
1677    file delete $path(test1)
1678} -constraints stdio -body {
1679    set f [open $path(script) w]
1680    chan puts -nonewline $f {
1681	chan close stderr
1682	set f [}
1683    chan puts $f [list open $path(test1) w]]
1684    chan puts -nonewline $f {
1685	chan puts stderr hello
1686	chan close $f
1687	set f [}
1688    chan puts $f [list open $path(test1) r]]
1689    chan puts $f {
1690	chan puts [chan gets $f]
1691    }
1692    chan close $f
1693    set f [openpipe r $path(script)]
1694    chan gets $f
1695} -cleanup {
1696    chan close $f
1697} -result hello
1698test chan-io-14.9 {reuse of stdio special channels} -setup {
1699    file delete $path(script)
1700    file delete $path(test1)
1701} -constraints {stdio fileevent} -body {
1702    set f [open $path(script) w]
1703    chan puts $f {
1704        array set path [lindex $argv 0]
1705	set f [open $path(test1) w]
1706	chan puts $f hello
1707	chan close $f
1708	chan close stderr
1709	set f [open "|[list [info nameofexecutable] $path(cat) $path(test1)]" r]
1710	chan puts [chan gets $f]
1711    }
1712    chan close $f
1713    set f [openpipe r $path(script) [array get path]]
1714    chan gets $f
1715} -cleanup {
1716    chan close $f
1717    # Added delay to give Windows time to stop the spawned process and clean
1718    # up its grip on the file test1. Added delete as proper test cleanup.
1719    # The failing tests were 18.1 and 18.2 as first re-users of file "test1".
1720    after [expr {[testConstraint win] ? 10000 : 500}]
1721    file delete $path(script)
1722    file delete $path(test1)
1723} -result hello
1724
1725test chan-io-15.1 {Tcl_CreateChan CloseHandler} emptyTest {
1726} {}
1727
1728test chan-io-16.1 {Tcl_DeleteChan CloseHandler} emptyTest {
1729} {}
1730
1731# Test channel table management. The functions tested are GetChannelTable,
1732# DeleteChannelTable, Tcl_RegisterChannel, Tcl_UnregisterChannel,
1733# Tcl_GetChannel and Tcl_CreateChannel.
1734#
1735# These functions use "eof stdin" to ensure that the standard channels are
1736# added to the channel table of the interpreter.
1737
1738test chan-io-17.1 {GetChannelTable, DeleteChannelTable on std handles} -setup {
1739    set l ""
1740} -constraints {testchannel} -body {
1741    set l1 [testchannel refcount stdin]
1742    chan eof stdin
1743    interp create x
1744    lappend l [expr {[testchannel refcount stdin] - $l1}]
1745    x eval {chan eof stdin}
1746    lappend l [expr {[testchannel refcount stdin] - $l1}]
1747    interp delete x
1748    lappend l [expr {[testchannel refcount stdin] - $l1}]
1749} -result {0 1 0}
1750test chan-io-17.2 {GetChannelTable, DeleteChannelTable on std handles} -setup  {
1751    set l ""
1752} -constraints {testchannel} -body {
1753    set l1 [testchannel refcount stdout]
1754    chan eof stdin
1755    interp create x
1756    lappend l [expr {[testchannel refcount stdout] - $l1}]
1757    x eval {chan eof stdout}
1758    lappend l [expr {[testchannel refcount stdout] - $l1}]
1759    interp delete x
1760    lappend l [expr {[testchannel refcount stdout] - $l1}]
1761} -result {0 1 0}
1762test chan-io-17.3 {GetChannelTable, DeleteChannelTable on std handles} -setup {
1763    set l ""
1764} -constraints {testchannel} -body {
1765    set l1 [testchannel refcount stderr]
1766    chan eof stdin
1767    interp create x
1768    lappend l [expr {[testchannel refcount stderr] - $l1}]
1769    x eval {chan eof stderr}
1770    lappend l [expr {[testchannel refcount stderr] - $l1}]
1771    interp delete x
1772    lappend l [expr {[testchannel refcount stderr] - $l1}]
1773} -result {0 1 0}
1774
1775test chan-io-18.1 {Tcl_RegisterChannel, Tcl_UnregisterChannel} -setup {
1776    file delete -force $path(test1)
1777    set l ""
1778} -constraints {testchannel} -body {
1779    set f [open $path(test1) w]
1780    lappend l [lindex [testchannel info $f] 15]
1781    chan close $f
1782    if {[catch {lindex [testchannel info $f] 15} msg]} {
1783	lappend l $msg
1784    } else {
1785	lappend l "very broken: $f found after being chan closed"
1786    }
1787    string equal $l [list 1 "can not find channel named \"$f\""]
1788} -result 1
1789test chan-io-18.2 {Tcl_RegisterChannel, Tcl_UnregisterChannel} -setup {
1790    file delete -force $path(test1)
1791    set l ""
1792} -constraints {testchannel} -body {
1793    set f [open $path(test1) w]
1794    lappend l [lindex [testchannel info $f] 15]
1795    interp create x
1796    interp share "" $f x
1797    lappend l [lindex [testchannel info $f] 15]
1798    x eval chan close $f
1799    lappend l [lindex [testchannel info $f] 15]
1800    interp delete x
1801    lappend l [lindex [testchannel info $f] 15]
1802    chan close $f
1803    if {[catch {lindex [testchannel info $f] 15} msg]} {
1804	lappend l $msg
1805    } else {
1806	lappend l "very broken: $f found after being chan closed"
1807    }
1808    string equal $l [list 1 2 1 1 "can not find channel named \"$f\""]
1809} -result 1
1810test chan-io-18.3 {Tcl_RegisterChannel, Tcl_UnregisterChannel} -setup {
1811    file delete $path(test1)
1812    set l ""
1813} -constraints {testchannel} -body {
1814    set f [open $path(test1) w]
1815    lappend l [lindex [testchannel info $f] 15]
1816    interp create x
1817    interp share "" $f x
1818    lappend l [lindex [testchannel info $f] 15]
1819    interp delete x
1820    lappend l [lindex [testchannel info $f] 15]
1821    chan close $f
1822    if {[catch {lindex [testchannel info $f] 15} msg]} {
1823	lappend l $msg
1824    } else {
1825	lappend l "very broken: $f found after being chan closed"
1826    }
1827    string equal $l [list 1 2 1 "can not find channel named \"$f\""]
1828} -result 1
1829
1830test chan-io-19.1 {Tcl_GetChannel->Tcl_GetStdChannel, standard handles} {
1831    chan eof stdin
1832} 0
1833test chan-io-19.2 {testing Tcl_GetChannel, user opened handle} -setup {
1834    file delete $path(test1)
1835} -body {
1836    set f [open $path(test1) w]
1837    chan eof $f
1838} -cleanup {
1839    chan close $f
1840} -result 0
1841test chan-io-19.3 {Tcl_GetChannel, channel not found} -body {
1842    chan eof file34
1843} -returnCodes error -result {can not find channel named "file34"}
1844test chan-io-19.4 {Tcl_CreateChannel, insertion into channel table} -setup {
1845    file delete $path(test1)
1846    set l ""
1847} -constraints {testchannel} -body {
1848    set f [open $path(test1) w]
1849    lappend l [chan eof $f]
1850    chan close $f
1851    if {[catch {lindex [testchannel info $f] 15} msg]} {
1852	lappend l $msg
1853    } else {
1854	lappend l "very broken: $f found after being chan closed"
1855    }
1856    string equal $l [list 0 "can not find channel named \"$f\""]
1857} -result 1
1858
1859test chan-io-20.1 {Tcl_CreateChannel: initial settings} -setup {
1860    set old [encoding system]
1861} -body {
1862    set a [open $path(test2) w]
1863    encoding system ascii
1864    set f [open $path(test1) w]
1865    chan configure $f -encoding
1866} -cleanup {
1867    encoding system $old
1868    chan close $f
1869    chan close $a
1870} -result {ascii}
1871test chan-io-20.2 {Tcl_CreateChannel: initial settings} -constraints {win} -body {
1872    set f [open $path(test1) w+]
1873    list [chan configure $f -eofchar] [chan configure $f -translation]
1874} -cleanup {
1875    chan close $f
1876} -result [list [list \x1a ""] {auto crlf}]
1877test chan-io-20.3 {Tcl_CreateChannel: initial settings} -constraints {unix} -body {
1878    set f [open $path(test1) w+]
1879    list [chan configure $f -eofchar] [chan configure $f -translation]
1880} -cleanup {
1881    chan close $f
1882} -result {{{} {}} {auto lf}}
1883test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} -setup {
1884    set path(stdout) [makeFile {} stdout]
1885} -constraints {stdio notWinCI} -body {
1886    set f [open $path(script) w]
1887    chan puts -nonewline $f {
1888	chan close stdout
1889	set f1 [}
1890    chan puts $f [list open $path(stdout) w]]
1891    chan puts $f {
1892	chan configure $f1 -buffersize 777
1893	chan puts stderr [chan configure stdout -buffersize]
1894    }
1895    chan close $f
1896    set f [openpipe r $path(script)]
1897    chan close $f
1898} -cleanup {
1899    removeFile $path(stdout)
1900} -returnCodes error -result {777}
1901
1902test chan-io-21.1 {Chan CloseChannelsOnExit} emptyTest {
1903} {}
1904
1905# Test management of attributes associated with a channel, such as its default
1906# translation, its name and type, etc. The functions tested in this group are
1907# Tcl_GetChannelName, Tcl_GetChannelType and Tcl_GetChannelFile.
1908# Tcl_GetChannelInstanceData not tested because files do not use the instance
1909# data.
1910
1911test chan-io-22.1 {Tcl_GetChannelMode} emptyTest {
1912    # Not used anywhere in Tcl.
1913} {}
1914
1915test chan-io-23.1 {Tcl_GetChannelName} -constraints {testchannel} -setup {
1916    file delete $path(test1)
1917} -body {
1918    set f [open $path(test1) w]
1919    set n [testchannel name $f]
1920    expr {$n eq $f ? "ok" : "$n != $f"}
1921} -cleanup {
1922    chan close $f
1923} -result ok
1924
1925test chan-io-24.1 {Tcl_GetChannelType} -constraints {testchannel} -setup {
1926    file delete $path(test1)
1927} -body {
1928    set f [open $path(test1) w]
1929    testchannel type $f
1930} -cleanup {
1931    chan close $f
1932} -result "file"
1933
1934test chan-io-25.1 {Tcl_GetChannelHandle, input} -setup {
1935    set l ""
1936} -constraints {testchannel} -body {
1937    set f [open $path(test1) w]
1938    chan configure $f -translation lf -eofchar {}
1939    chan puts $f "1234567890\n098765432"
1940    chan close $f
1941    set f [open $path(test1) r]
1942    chan gets $f
1943    lappend l [testchannel inputbuffered $f]
1944    lappend l [chan tell $f]
1945} -cleanup {
1946    chan close $f
1947} -result {10 11}
1948test chan-io-25.2 {Tcl_GetChannelHandle, output} -setup {
1949    file delete $path(test1)
1950    set l ""
1951} -constraints {testchannel} -body {
1952    set f [open $path(test1) w]
1953    chan configure $f -translation lf
1954    chan puts $f hello
1955    lappend l [testchannel outputbuffered $f]
1956    lappend l [chan tell $f]
1957    chan flush $f
1958    lappend l [testchannel outputbuffered $f]
1959    lappend l [chan tell $f]
1960} -cleanup {
1961    chan close $f
1962    file delete $path(test1)
1963} -result {6 6 0 6}
1964
1965test chan-io-26.1 {Tcl_GetChannelInstanceData} -body {
1966    # "pid" command uses Tcl_GetChannelInstanceData
1967    # Don't care what pid is (but must be a number), just want to exercise it.
1968    set f [openpipe r << exit]
1969    pid $f
1970} -constraints stdio -cleanup {
1971    chan close $f
1972} -match regexp -result {^\d+$}
1973
1974# Test flushing. The functions tested here are FlushChannel.
1975
1976test chan-io-27.1 {FlushChannel, no output buffered} -setup {
1977    file delete $path(test1)
1978} -body {
1979    set f [open $path(test1) w]
1980    chan flush $f
1981    file size $path(test1)
1982} -cleanup {
1983    chan close $f
1984} -result 0
1985test chan-io-27.2 {FlushChannel, some output buffered} -setup {
1986    file delete $path(test1)
1987    set l ""
1988} -body {
1989    set f [open $path(test1) w]
1990    chan configure $f -translation lf -eofchar {}
1991    chan puts $f hello
1992    lappend l [file size $path(test1)]
1993    chan flush $f
1994    lappend l [file size $path(test1)]
1995    chan close $f
1996    lappend l [file size $path(test1)]
1997} -result {0 6 6}
1998test chan-io-27.3 {FlushChannel, implicit flush on chan close} -setup {
1999    file delete $path(test1)
2000    set l ""
2001} -body {
2002    set f [open $path(test1) w]
2003    chan configure $f -translation lf -eofchar {}
2004    chan puts $f hello
2005    lappend l [file size $path(test1)]
2006    chan close $f
2007    lappend l [file size $path(test1)]
2008} -result {0 6}
2009test chan-io-27.4 {FlushChannel, implicit flush when buffer fills} -setup {
2010    file delete $path(test1)
2011    set l ""
2012} -body {
2013    set f [open $path(test1) w]
2014    chan configure $f -translation lf -eofchar {}
2015    chan configure $f -buffersize 60
2016    lappend l [file size $path(test1)]
2017    for {set i 0} {$i < 12} {incr i} {
2018	chan puts $f hello
2019    }
2020    lappend l [file size $path(test1)]
2021    chan flush $f
2022    lappend l [file size $path(test1)]
2023} -cleanup {
2024    chan close $f
2025} -result {0 60 72}
2026test chan-io-27.5 {FlushChannel, implicit flush when buffer fills and on chan close} -setup {
2027    file delete $path(test1)
2028    set l ""
2029} -constraints {unixOrWin} -body {
2030    set f [open $path(test1) w]
2031    chan configure $f -translation lf -buffersize 60 -eofchar {}
2032    lappend l [file size $path(test1)]
2033    for {set i 0} {$i < 12} {incr i} {
2034	chan puts $f hello
2035    }
2036    lappend l [file size $path(test1)]
2037    chan close $f
2038    lappend l [file size $path(test1)]
2039} -result {0 60 72}
2040set path(pipe)   [makeFile {} pipe]
2041set path(output) [makeFile {} output]
2042test chan-io-27.6 {FlushChannel, async flushing, async chan close} -setup {
2043    file delete $path(pipe)
2044    file delete $path(output)
2045} -constraints {stdio asyncPipeChan Close} -body {
2046    set f [open $path(pipe) w]
2047    chan puts $f "set f \[[list open $path(output) w]]"
2048    chan puts $f {
2049	chan configure $f -translation lf -buffering none -eofchar {}
2050	while {![chan eof stdin]} {
2051	    after 20
2052	    chan puts -nonewline $f [chan read stdin 1024]
2053	}
2054	chan close $f
2055    }
2056    chan close $f
2057    set x 01234567890123456789012345678901
2058    for {set i 0} {$i < 11} {incr i} {
2059        set x "$x$x"
2060    }
2061    set f [open $path(output) w]
2062    chan close $f
2063    set f [openpipe w $path(pipe)]
2064    chan configure $f -blocking off
2065    chan puts -nonewline $f $x
2066    chan close $f
2067    set counter 0
2068    while {([file size $path(output)] < 65536) && ($counter < 1000)} {
2069	after 20 [list incr [namespace which -variable counter]]
2070	vwait [namespace which -variable counter]
2071    }
2072    if {$counter == 1000} {
2073        set result "file size only [file size $path(output)]"
2074    } else {
2075        set result ok
2076    }
2077} -result ok
2078
2079# Tests closing a channel. The functions tested are Chan CloseChannel and
2080# Tcl_Chan Close.
2081
2082test chan-io-28.1 {Chan CloseChannel called when all references are dropped} -setup {
2083    file delete $path(test1)
2084    set l ""
2085} -constraints {testchannel} -body {
2086    set f [open $path(test1) w]
2087    interp create x
2088    interp share "" $f x
2089    lappend l [testchannel refcount $f]
2090    x eval chan close $f
2091    interp delete x
2092    lappend l [testchannel refcount $f]
2093} -cleanup {
2094    chan close $f
2095} -result {2 1}
2096test chan-io-28.2 {Chan CloseChannel called when all references are dropped} -setup {
2097    file delete $path(test1)
2098} -body {
2099    set f [open $path(test1) w]
2100    interp create x
2101    interp share "" $f x
2102    chan puts -nonewline $f abc
2103    chan close $f
2104    x eval chan puts $f def
2105    x eval chan close $f
2106    interp delete x
2107    set f [open $path(test1) r]
2108    chan gets $f
2109} -cleanup {
2110    chan close $f
2111} -result abcdef
2112test chan-io-28.3 {Chan CloseChannel, not called before output queue is empty} -setup {
2113    file delete $path(pipe)
2114    file delete $path(output)
2115} -constraints {stdio asyncPipeChan Close nonPortable} -body {
2116    set f [open $path(pipe) w]
2117    chan puts $f {
2118	# Need to not have eof char appended on chan close, because the other
2119	# side of the pipe already chan closed, so that writing would cause an
2120	# error "invalid file".
2121	chan configure stdout -eofchar {}
2122	chan configure stderr -eofchar {}
2123	set f [open $path(output) w]
2124	chan configure $f -translation lf -buffering none
2125	for {set x 0} {$x < 20} {incr x} {
2126	    after 20
2127	    chan puts -nonewline $f [chan read stdin 1024]
2128	}
2129	chan close $f
2130    }
2131    chan close $f
2132    set x 01234567890123456789012345678901
2133    for {set i 0} {$i < 11} {incr i} {
2134        set x "$x$x"
2135    }
2136    set f [open $path(output) w]
2137    chan close $f
2138    set f [openpipe r+ $path(pipe)]
2139    chan configure $f -blocking off -eofchar {}
2140    chan puts -nonewline $f $x
2141    chan close $f
2142    set counter 0
2143    while {([file size $path(output)] < 20480) && ($counter < 1000)} {
2144	after 20 [list incr [namespace which -variable counter]]
2145	vwait [namespace which -variable counter]
2146    }
2147    if {$counter == 1000} {
2148        set result probably_broken
2149    } else {
2150        set result ok
2151    }
2152} -result ok
2153test chan-io-28.4 {Tcl_Chan Close} -constraints {testchannel} -setup {
2154    file delete $path(test1)
2155    set l ""
2156} -body {
2157    lappend l [lsort [testchannel open]]
2158    set f [open $path(test1) w]
2159    lappend l [lsort [testchannel open]]
2160    chan close $f
2161    lappend l [lsort [testchannel open]]
2162    set x [list $consoleFileNames \
2163		[lsort [list {*}$consoleFileNames $f]] \
2164		$consoleFileNames]
2165    expr {$l eq $x ? "ok" : "{$l} != {$x}"}
2166} -result ok
2167test chan-io-28.5 {Tcl_Chan Close vs standard handles} -setup {
2168    file delete $path(script)
2169} -constraints {stdio unix testchannel} -body {
2170    set f [open $path(script) w]
2171    chan puts $f {
2172	chan close stdin
2173	chan puts [testchannel open]
2174    }
2175    chan close $f
2176    set f [openpipe r $path(script)]
2177    set l [chan gets $f]
2178    chan close $f
2179    lsort $l
2180} -result {file1 file2}
2181test chan-io-28.6 {Tcl_CloseEx (half-close) pipe} -setup {
2182    set cat [makeFile {
2183	fconfigure stdout -buffering line
2184	while {[gets stdin line] >= 0} {puts $line}
2185	puts DONE
2186	exit 0
2187    } cat.tcl]
2188    variable done
2189} -body {
2190    set ff [openpipe r+ $cat]
2191    puts $ff Hey
2192    close $ff w
2193    set timer [after 1000 [namespace code {set done Failed}]]
2194    set acc {}
2195    fileevent $ff readable [namespace code {
2196	if {[gets $ff line] < 0} {
2197	    set done Succeeded
2198	} else {
2199	    lappend acc $line
2200	}
2201    }]
2202    vwait [namespace which -variable done]
2203    after cancel $timer
2204    close $ff r
2205    list $done $acc
2206} -cleanup {
2207    removeFile cat.tcl
2208} -result {Succeeded {Hey DONE}}
2209test chan-io-28.7 {Tcl_CloseEx (half-close) socket} -setup {
2210    set echo [makeFile {
2211	proc accept {s args} {set ::sok $s}
2212	set s [socket -server accept 0]
2213	puts [lindex [fconfigure $s -sockname] 2]
2214	flush stdout
2215	vwait ::sok
2216	fconfigure $sok -buffering line
2217	while {[gets $sok line]>=0} {puts $sok $line}
2218	puts $sok DONE
2219	exit 0
2220    } echo.tcl]
2221    variable done
2222    unset -nocomplain done
2223    set done ""
2224    set timer ""
2225    set ff [openpipe r $echo]
2226    gets $ff port
2227} -body {
2228    set s [socket 127.0.0.1 $port]
2229    puts $s Hey
2230    close $s w
2231    set timer [after 1000 [namespace code {set done Failed}]]
2232    set acc {}
2233    fileevent $s readable [namespace code {
2234	if {[gets $s line]<0} {
2235	    set done Succeeded
2236	} else {
2237	    lappend acc $line
2238	}
2239    }]
2240    vwait [namespace which -variable done]
2241    list $done $acc
2242} -cleanup {
2243    catch {close $s}
2244    close $ff
2245    after cancel $timer
2246    removeFile echo.tcl
2247} -result {Succeeded {Hey DONE}}
2248
2249test chan-io-29.1 {Tcl_WriteChars, channel not writable} -body {
2250    chan puts stdin hello
2251} -returnCodes error -result {channel "stdin" wasn't opened for writing}
2252test chan-io-29.2 {Tcl_WriteChars, empty string} -setup {
2253    file delete $path(test1)
2254} -body {
2255    set f [open $path(test1) w]
2256    chan configure $f -eofchar {}
2257    chan puts -nonewline $f ""
2258    chan close $f
2259    file size $path(test1)
2260} -result 0
2261test chan-io-29.3 {Tcl_WriteChars, nonempty string} -setup {
2262    file delete $path(test1)
2263} -body {
2264    set f [open $path(test1) w]
2265    chan configure $f -eofchar {}
2266    chan puts -nonewline $f hello
2267    chan close $f
2268    file size $path(test1)
2269} -result 5
2270test chan-io-29.4 {Tcl_WriteChars, buffering in full buffering mode} -setup {
2271    file delete $path(test1)
2272    set l ""
2273} -constraints {testchannel} -body {
2274    set f [open $path(test1) w]
2275    chan configure $f -translation lf -buffering full -eofchar {}
2276    chan puts $f hello
2277    lappend l [testchannel outputbuffered $f]
2278    lappend l [file size $path(test1)]
2279    chan flush $f
2280    lappend l [testchannel outputbuffered $f]
2281    lappend l [file size $path(test1)]
2282} -cleanup {
2283    chan close $f
2284} -result {6 0 0 6}
2285test chan-io-29.5 {Tcl_WriteChars, buffering in line buffering mode} -setup {
2286    file delete $path(test1)
2287    set l ""
2288} -constraints {testchannel} -body {
2289    set f [open $path(test1) w]
2290    chan configure $f -translation lf -buffering line -eofchar {}
2291    chan puts -nonewline $f hello
2292    lappend l [testchannel outputbuffered $f]
2293    lappend l [file size $path(test1)]
2294    chan puts $f hello
2295    lappend l [testchannel outputbuffered $f]
2296    lappend l [file size $path(test1)]
2297} -cleanup {
2298    chan close $f
2299} -result {5 0 0 11}
2300test chan-io-29.6 {Tcl_WriteChars, buffering in no buffering mode} -setup {
2301    file delete $path(test1)
2302    set l ""
2303} -constraints {testchannel} -body {
2304    set f [open $path(test1) w]
2305    chan configure $f -translation lf -buffering none -eofchar {}
2306    chan puts -nonewline $f hello
2307    lappend l [testchannel outputbuffered $f]
2308    lappend l [file size $path(test1)]
2309    chan puts $f hello
2310    lappend l [testchannel outputbuffered $f]
2311    lappend l [file size $path(test1)]
2312} -cleanup {
2313    chan close $f
2314} -result {0 5 0 11}
2315test chan-io-29.7 {Tcl_Flush, full buffering} -setup {
2316    file delete $path(test1)
2317    set l ""
2318} -constraints {testchannel} -body {
2319    set f [open $path(test1) w]
2320    chan configure $f -translation lf -buffering full -eofchar {}
2321    chan puts -nonewline $f hello
2322    lappend l [testchannel outputbuffered $f]
2323    lappend l [file size $path(test1)]
2324    chan puts $f hello
2325    lappend l [testchannel outputbuffered $f]
2326    lappend l [file size $path(test1)]
2327    chan flush $f
2328    lappend l [testchannel outputbuffered $f]
2329    lappend l [file size $path(test1)]
2330} -cleanup {
2331    chan close $f
2332} -result {5 0 11 0 0 11}
2333test chan-io-29.8 {Tcl_Flush, full buffering} -setup {
2334    file delete $path(test1)
2335    set l ""
2336} -constraints {testchannel} -body {
2337    set f [open $path(test1) w]
2338    chan configure $f -translation lf -buffering line
2339    chan puts -nonewline $f hello
2340    lappend l [testchannel outputbuffered $f]
2341    lappend l [file size $path(test1)]
2342    chan flush $f
2343    lappend l [testchannel outputbuffered $f]
2344    lappend l [file size $path(test1)]
2345    chan puts $f hello
2346    lappend l [testchannel outputbuffered $f]
2347    lappend l [file size $path(test1)]
2348    chan flush $f
2349    lappend l [testchannel outputbuffered $f]
2350    lappend l [file size $path(test1)]
2351} -cleanup {
2352    chan close $f
2353} -result {5 0 0 5 0 11 0 11}
2354test chan-io-29.9 {Tcl_Flush, channel not writable} -body {
2355    chan flush stdin
2356} -returnCodes error -result {channel "stdin" wasn't opened for writing}
2357test chan-io-29.10 {Tcl_WriteChars, looping and buffering} -setup {
2358    file delete $path(test1)
2359} -body {
2360    set f1 [open $path(test1) w]
2361    chan configure $f1 -translation lf -eofchar {}
2362    set f2 [open $path(longfile) r]
2363    for {set x 0} {$x < 10} {incr x} {
2364	chan puts $f1 [chan gets $f2]
2365    }
2366    chan close $f2
2367    chan close $f1
2368    file size $path(test1)
2369} -result 387
2370test chan-io-29.11 {Tcl_WriteChars, no newline, implicit flush} -setup {
2371    file delete $path(test1)
2372} -body {
2373    set f1 [open $path(test1) w]
2374    chan configure $f1 -eofchar {}
2375    set f2 [open $path(longfile) r]
2376    for {set x 0} {$x < 10} {incr x} {
2377	chan puts -nonewline $f1 [chan gets $f2]
2378    }
2379    chan close $f1
2380    chan close $f2
2381    file size $path(test1)
2382} -result 377
2383test chan-io-29.12 {Tcl_WriteChars on a pipe} -setup {
2384    file delete $path(test1)
2385    file delete $path(pipe)
2386} -constraints stdio -body {
2387    set f1 [open $path(pipe) w]
2388    chan puts $f1 "set f1 \[[list open $path(longfile) r]]"
2389    chan puts $f1 {
2390	for {set x 0} {$x < 10} {incr x} {
2391	    chan puts [chan gets $f1]
2392	}
2393    }
2394    chan close $f1
2395    set f1 [openpipe r $path(pipe)]
2396    set f2 [open $path(longfile) r]
2397    set y ok
2398    for {set x 0} {$x < 10} {incr x} {
2399	set l1 [chan gets $f1]
2400	set l2 [chan gets $f2]
2401	if {$l1 ne $l2} {
2402	    set y broken:$x
2403	}
2404    }
2405    return $y
2406} -cleanup {
2407    chan close $f1
2408    chan close $f2
2409} -result ok
2410test chan-io-29.13 {Tcl_WriteChars to a pipe, line buffered} -setup {
2411    file delete $path(test1)
2412    file delete $path(pipe)
2413} -constraints stdio -body {
2414    set f1 [open $path(pipe) w]
2415    chan puts $f1 {
2416	chan puts [chan gets stdin]
2417	chan puts [chan gets stdin]
2418    }
2419    chan close $f1
2420    set y ok
2421    set f1 [openpipe r+ $path(pipe)]
2422    chan configure $f1 -buffering line
2423    set f2 [open $path(longfile) r]
2424    set line [chan gets $f2]
2425    chan puts $f1 $line
2426    set backline [chan gets $f1]
2427    if {$line ne $backline} {
2428	set y broken1
2429    }
2430    set line [chan gets $f2]
2431    chan puts $f1 $line
2432    set backline [chan gets $f1]
2433    if {$line ne $backline} {
2434	set y broken2
2435    }
2436    return $y
2437} -cleanup {
2438    chan close $f1
2439    chan close $f2
2440} -result ok
2441test chan-io-29.14 {Tcl_WriteChars, buffering and implicit flush at chan close} -setup {
2442    file delete $path(test3)
2443} -body {
2444    set f [open $path(test3) w]
2445    chan puts -nonewline $f "Text1"
2446    chan puts -nonewline $f " Text 2"
2447    chan puts $f " Text 3"
2448    chan close $f
2449    set f [open $path(test3) r]
2450    chan gets $f
2451} -cleanup {
2452    chan close $f
2453} -result {Text1 Text 2 Text 3}
2454test chan-io-29.15 {Tcl_Flush, channel not open for writing} -setup {
2455    file delete $path(test1)
2456    set fd [open $path(test1) w]
2457    chan close $fd
2458} -body {
2459    set fd [open $path(test1) r]
2460    chan flush $fd
2461} -returnCodes error -cleanup {
2462    catch {chan close $fd}
2463} -match glob -result {channel "*" wasn't opened for writing}
2464test chan-io-29.16 {Tcl_Flush on pipe opened only for reading} -setup {
2465    set fd [openpipe r cat longfile]
2466} -constraints stdio -body {
2467    chan flush $fd
2468} -returnCodes error -cleanup {
2469    catch {chan close $fd}
2470} -match glob -result {channel "*" wasn't opened for writing}
2471test chan-io-29.17 {Tcl_WriteChars buffers, then Tcl_Flush flushes} -setup {
2472    file delete $path(test1)
2473} -body {
2474    set f1 [open $path(test1) w]
2475    chan configure $f1 -translation lf
2476    chan puts $f1 hello
2477    chan puts $f1 hello
2478    chan puts $f1 hello
2479    chan flush $f1
2480    file size $path(test1)
2481} -cleanup {
2482    chan close $f1
2483} -result 18
2484test chan-io-29.18 {Tcl_WriteChars and Tcl_Flush intermixed} -setup {
2485    file delete $path(test1)
2486    set x ""
2487    set f1 [open $path(test1) w]
2488} -body {
2489    chan configure $f1 -translation lf
2490    chan puts $f1 hello
2491    chan puts $f1 hello
2492    chan puts $f1 hello
2493    chan flush $f1
2494    lappend x [file size $path(test1)]
2495    chan puts $f1 hello
2496    chan flush $f1
2497    lappend x [file size $path(test1)]
2498    chan puts $f1 hello
2499    chan flush $f1
2500    lappend x [file size $path(test1)]
2501} -cleanup {
2502    chan close $f1
2503} -result {18 24 30}
2504test chan-io-29.19 {Explicit and implicit flushes} -setup {
2505    file delete $path(test1)
2506} -body {
2507    set f1 [open $path(test1) w]
2508    chan configure $f1 -translation lf -eofchar {}
2509    set x ""
2510    chan puts $f1 hello
2511    chan puts $f1 hello
2512    chan puts $f1 hello
2513    chan flush $f1
2514    lappend x [file size $path(test1)]
2515    chan puts $f1 hello
2516    chan flush $f1
2517    lappend x [file size $path(test1)]
2518    chan puts $f1 hello
2519    chan close $f1
2520    lappend x [file size $path(test1)]
2521} -result {18 24 30}
2522test chan-io-29.20 {Implicit flush when buffer is full} -setup {
2523    file delete $path(test1)
2524} -body {
2525    set f1 [open $path(test1) w]
2526    chan configure $f1 -translation lf -eofchar {}
2527    set line "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
2528    for {set x 0} {$x < 100} {incr x} {
2529      chan puts $f1 $line
2530    }
2531    set z ""
2532    lappend z [file size $path(test1)]
2533    for {set x 0} {$x < 100} {incr x} {
2534	chan puts $f1 $line
2535    }
2536    lappend z [file size $path(test1)]
2537    chan close $f1
2538    lappend z [file size $path(test1)]
2539} -result {4096 12288 12600}
2540test chan-io-29.21 {Tcl_Flush to pipe} -setup {
2541    file delete $path(pipe)
2542} -constraints stdio -body {
2543    set f1 [open $path(pipe) w]
2544    chan puts $f1 {set x [chan read stdin 6]}
2545    chan puts $f1 {set cnt [string length $x]}
2546    chan puts $f1 {chan puts "read $cnt characters"}
2547    chan close $f1
2548    set f1 [openpipe r+ $path(pipe)]
2549    chan puts $f1 hello
2550    chan flush $f1
2551    chan gets $f1
2552} -cleanup {
2553    catch {chan close $f1}
2554} -result "read 6 characters"
2555test chan-io-29.22 {Tcl_Flush called at other end of pipe} -setup {
2556    file delete $path(pipe)
2557} -constraints stdio -body {
2558    set f1 [open $path(pipe) w]
2559    chan puts $f1 {
2560	chan configure stdout -buffering full
2561	chan puts hello
2562	chan puts hello
2563	chan flush stdout
2564	chan gets stdin
2565	chan puts bye
2566	chan flush stdout
2567    }
2568    chan close $f1
2569    set f1 [openpipe r+ $path(pipe)]
2570    set x ""
2571    lappend x [chan gets $f1]
2572    lappend x [chan gets $f1]
2573    chan puts $f1 hello
2574    chan flush $f1
2575    lappend x [chan gets $f1]
2576} -cleanup {
2577    chan close $f1
2578} -result {hello hello bye}
2579test chan-io-29.23 {Tcl_Flush and line buffering at end of pipe} -setup {
2580    file delete $path(pipe)
2581} -constraints stdio -body {
2582    set f1 [open $path(pipe) w]
2583    chan puts $f1 {
2584	chan puts hello
2585	chan puts hello
2586	chan gets stdin
2587	chan puts bye
2588    }
2589    chan close $f1
2590    set f1 [openpipe r+ $path(pipe)]
2591    set x ""
2592    lappend x [chan gets $f1]
2593    lappend x [chan gets $f1]
2594    chan puts $f1 hello
2595    chan flush $f1
2596    lappend x [chan gets $f1]
2597} -cleanup {
2598    chan close $f1
2599} -result {hello hello bye}
2600test chan-io-29.24 {Tcl_WriteChars and Tcl_Flush move end of file} -setup {
2601    variable x {}
2602} -body {
2603    set f [open $path(test3) w]
2604    chan puts $f "Line 1"
2605    chan puts $f "Line 2"
2606    set f2 [open $path(test3)]
2607    lappend x [chan read -nonewline $f2]
2608    chan close $f2
2609    chan flush $f
2610    set f2 [open $path(test3)]
2611    lappend x [chan read -nonewline $f2]
2612} -cleanup {
2613    chan close $f2
2614    chan close $f
2615} -result "{} {Line 1\nLine 2}"
2616test chan-io-29.25 {Implicit flush with Tcl_Flush to command pipelines} -setup {
2617    file delete $path(test3)
2618} -constraints {stdio fileevent} -body {
2619    set f [openpipe w $path(cat) | [interpreter] $path(cat) > $path(test3)]
2620    chan puts $f "Line 1"
2621    chan puts $f "Line 2"
2622    chan close $f
2623    after 100
2624    set f [open $path(test3) r]
2625    chan read $f
2626} -cleanup {
2627    chan close $f
2628} -result "Line 1\nLine 2\n"
2629test chan-io-29.26 {Tcl_Flush, Tcl_Write on bidirectional pipelines} -constraints {stdio unixExecs} -body {
2630    set f [open "|[list cat -u]" r+]
2631    chan puts $f "Line1"
2632    chan flush $f
2633    chan gets $f
2634} -cleanup {
2635    chan close $f
2636} -result {Line1}
2637test chan-io-29.27 {Tcl_Flush on chan closed pipeline} -setup {
2638    file delete $path(pipe)
2639    set f [open $path(pipe) w]
2640    chan puts $f {exit}
2641    chan close $f
2642} -constraints stdio -body {
2643    set f [openpipe r+ $path(pipe)]
2644    chan gets $f
2645    chan puts $f output
2646    after 50
2647    #
2648    # The flush below will get a SIGPIPE. This is an expected part of the test
2649    # and indicates that the test operates correctly. If you run this test
2650    # under a debugger, the signal will by intercepted unless you disable the
2651    # debugger's signal interception.
2652    #
2653    if {[catch {chan flush $f} msg]} {
2654	set x [list 1 $msg $::errorCode]
2655	catch {chan close $f}
2656    } elseif {[catch {chan close $f} msg]} {
2657	set x [list 1 $msg $::errorCode]
2658    } else {
2659	set x {this was supposed to fail and did not}
2660    }
2661    string tolower $x
2662} -match glob -result {1 {error flushing "*": broken pipe} {posix epipe {broken pipe}}}
2663test chan-io-29.28 {Tcl_WriteChars, lf mode} -setup {
2664    file delete $path(test1)
2665} -body {
2666    set f [open $path(test1) w]
2667    chan configure $f -translation lf -eofchar {}
2668    chan puts $f hello\nthere\nand\nhere
2669    chan flush $f
2670    file size $path(test1)
2671} -cleanup {
2672    chan close $f
2673} -result 21
2674test chan-io-29.29 {Tcl_WriteChars, cr mode} -setup {
2675    file delete $path(test1)
2676} -body {
2677    set f [open $path(test1) w]
2678    chan configure $f -translation cr -eofchar {}
2679    chan puts $f hello\nthere\nand\nhere
2680    chan close $f
2681    file size $path(test1)
2682} -result 21
2683test chan-io-29.30 {Tcl_WriteChars, crlf mode} -setup {
2684    file delete $path(test1)
2685} -body {
2686    set f [open $path(test1) w]
2687    chan configure $f -translation crlf -eofchar {}
2688    chan puts $f hello\nthere\nand\nhere
2689    chan close $f
2690    file size $path(test1)
2691} -result 25
2692test chan-io-29.31 {Tcl_WriteChars, background flush} -setup {
2693    file delete $path(pipe)
2694    file delete $path(output)
2695} -constraints stdio -body {
2696    set f [open $path(pipe) w]
2697    chan puts $f "set f \[[list open $path(output)  w]]"
2698    chan puts $f {chan configure $f -translation lf}
2699    set x [list while {![chan eof stdin]}]
2700    set x "$x {"
2701    chan puts $f $x
2702    chan puts $f {  chan puts -nonewline $f [chan read stdin 4096]}
2703    chan puts $f {  chan flush $f}
2704    chan puts $f "}"
2705    chan puts $f {chan close $f}
2706    chan close $f
2707    set x 01234567890123456789012345678901
2708    for {set i 0} {$i < 11} {incr i} {
2709	set x "$x$x"
2710    }
2711    set f [open $path(output) w]
2712    chan close $f
2713    set f [openpipe r+ $path(pipe)]
2714    chan configure $f -blocking off
2715    chan puts -nonewline $f $x
2716    chan close $f
2717    set counter 0
2718    while {([file size $path(output)] < 65536) && ($counter < 1000)} {
2719	after 10 [list incr [namespace which -variable counter]]
2720	vwait [namespace which -variable counter]
2721    }
2722    if {$counter == 1000} {
2723	set result "file size only [file size $path(output)]"
2724    } else {
2725	set result ok
2726    }
2727    # allow a little time for the background process to chan close.
2728    # otherwise, the following test fails on the [file delete $path(output)]
2729    # on Windows because a process still has the file open.
2730    after 100 set v 1; vwait v
2731    return $result
2732} -result ok
2733test chan-io-29.32 {Tcl_WriteChars, background flush to slow reader} -setup {
2734    file delete $path(pipe)
2735    file delete $path(output)
2736} -constraints {stdio asyncPipeChan Close} -body {
2737    set f [open $path(pipe) w]
2738    chan puts $f "set f \[[list open $path(output) w]]"
2739    chan puts $f {chan configure $f -translation lf}
2740    set x [list while {![chan eof stdin]}]
2741    set x "$x \{"
2742    chan puts $f $x
2743    chan puts $f {  after 20}
2744    chan puts $f {  chan puts -nonewline $f [chan read stdin 1024]}
2745    chan puts $f {  chan flush $f}
2746    chan puts $f "\}"
2747    chan puts $f {chan close $f}
2748    chan close $f
2749    set x 01234567890123456789012345678901
2750    for {set i 0} {$i < 11} {incr i} {
2751	set x "$x$x"
2752    }
2753    set f [open $path(output) w]
2754    chan close $f
2755    set f [openpipe r+ $path(pipe)]
2756    chan configure $f -blocking off
2757    chan puts -nonewline $f $x
2758    chan close $f
2759    set counter 0
2760    while {([file size $path(output)] < 65536) && ($counter < 1000)} {
2761	after 20 [list incr [namespace which -variable counter]]
2762	vwait [namespace which -variable counter]
2763    }
2764    if {$counter == 1000} {
2765	set result "file size only [file size $path(output)]"
2766    } else {
2767	set result ok
2768    }
2769} -result ok
2770test chan-io-29.33 {Tcl_Flush, implicit flush on exit} -setup {
2771    set f [open $path(script) w]
2772    chan puts $f "set f \[[list open $path(test1) w]]"
2773    chan puts $f {chan configure $f -translation lf
2774	chan puts $f hello
2775	chan puts $f bye
2776	chan puts $f strange
2777    }
2778    chan close $f
2779} -constraints exec -body {
2780    exec [interpreter] $path(script)
2781    set f [open $path(test1) r]
2782    chan read $f
2783} -cleanup {
2784    chan close $f
2785} -result "hello\nbye\nstrange\n"
2786test chan-io-29.34 {Tcl_Chan Close, async flush on chan close, using sockets} -setup {
2787    variable c 0
2788    variable x running
2789    set l abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
2790    proc writelots {s l} {
2791	for {set i 0} {$i < 2000} {incr i} {
2792	    chan puts $s $l
2793	}
2794    }
2795} -constraints {socket tempNotMac fileevent notWinCI} -body {
2796    proc accept {s a p} {
2797	variable x
2798	chan event $s readable [namespace code [list readit $s]]
2799	chan configure $s -blocking off
2800	set x accepted
2801    }
2802    proc readit {s} {
2803	variable c
2804	variable x
2805	set l [chan gets $s]
2806	if {[chan eof $s]} {
2807	    chan close $s
2808	    set x done
2809	} elseif {([string length $l] > 0) || ![chan blocked $s]} {
2810	    incr c
2811	}
2812    }
2813    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
2814    set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]
2815    vwait [namespace which -variable x]
2816    chan configure $cs -blocking off
2817    writelots $cs $l
2818    chan close $cs
2819    chan close $ss
2820    vwait [namespace which -variable x]
2821    set c
2822} -result 2000
2823test chan-io-29.35 {Tcl_Chan Close vs chan event vs multiple interpreters} -setup {
2824    catch {interp delete x}
2825    catch {interp delete y}
2826} -constraints {socket tempNotMac fileevent} -body {
2827    # On Mac, this test screws up sockets such that subsequent tests using
2828    # port 2828 either cause errors or panic().
2829    interp create x
2830    interp create y
2831    set s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
2832    proc accept {s a p} {
2833	chan puts $s hello
2834	chan close $s
2835    }
2836    set c [socket 127.0.0.1 [lindex [chan configure $s -sockname] 2]]
2837    interp share {} $c x
2838    interp share {} $c y
2839    chan close $c
2840    x eval {
2841	proc readit {s} {
2842	    chan gets $s
2843	    if {[chan eof $s]} {
2844		chan close $s
2845	    }
2846	}
2847    }
2848    y eval {
2849	proc readit {s} {
2850	    chan gets $s
2851	    if {[chan eof $s]} {
2852		chan close $s
2853	    }
2854	}
2855    }
2856    x eval "chan event $c readable \{readit $c\}"
2857    y eval "chan event $c readable \{readit $c\}"
2858    y eval [list chan close $c]
2859    update
2860} -cleanup {
2861    chan close $s
2862    interp delete x
2863    interp delete y
2864} -result ""
2865
2866# Test end of line translations. Procedures tested are Tcl_Write, Tcl_Read.
2867
2868test chan-io-30.1 {Tcl_Write lf, Tcl_Read lf} -setup {
2869    file delete $path(test1)
2870} -body {
2871    set f [open $path(test1) w]
2872    chan configure $f -translation lf
2873    chan puts $f hello\nthere\nand\nhere
2874    chan close $f
2875    set f [open $path(test1) r]
2876    chan configure $f -translation lf
2877    chan read $f
2878} -cleanup {
2879    chan close $f
2880} -result "hello\nthere\nand\nhere\n"
2881test chan-io-30.2 {Tcl_Write lf, Tcl_Read cr} -setup {
2882    file delete $path(test1)
2883} -body {
2884    set f [open $path(test1) w]
2885    chan configure $f -translation lf
2886    chan puts $f hello\nthere\nand\nhere
2887    chan close $f
2888    set f [open $path(test1) r]
2889    chan configure $f -translation cr
2890    chan read $f
2891} -cleanup {
2892    chan close $f
2893} -result "hello\nthere\nand\nhere\n"
2894test chan-io-30.3 {Tcl_Write lf, Tcl_Read crlf} -setup {
2895    file delete $path(test1)
2896} -body {
2897    set f [open $path(test1) w]
2898    chan configure $f -translation lf
2899    chan puts $f hello\nthere\nand\nhere
2900    chan close $f
2901    set f [open $path(test1) r]
2902    chan configure $f -translation crlf
2903    chan read $f
2904} -cleanup {
2905    chan close $f
2906} -result "hello\nthere\nand\nhere\n"
2907test chan-io-30.4 {Tcl_Write cr, Tcl_Read cr} -setup {
2908    file delete $path(test1)
2909} -body {
2910    set f [open $path(test1) w]
2911    chan configure $f -translation cr
2912    chan puts $f hello\nthere\nand\nhere
2913    chan close $f
2914    set f [open $path(test1) r]
2915    chan configure $f -translation cr
2916    chan read $f
2917} -cleanup {
2918    chan close $f
2919} -result "hello\nthere\nand\nhere\n"
2920test chan-io-30.5 {Tcl_Write cr, Tcl_Read lf} -setup {
2921    file delete $path(test1)
2922} -body {
2923    set f [open $path(test1) w]
2924    chan configure $f -translation cr
2925    chan puts $f hello\nthere\nand\nhere
2926    chan close $f
2927    set f [open $path(test1) r]
2928    chan configure $f -translation lf
2929    chan read $f
2930} -cleanup {
2931    chan close $f
2932} -result "hello\rthere\rand\rhere\r"
2933test chan-io-30.6 {Tcl_Write cr, Tcl_Read crlf} -setup {
2934    file delete $path(test1)
2935} -body {
2936    set f [open $path(test1) w]
2937    chan configure $f -translation cr
2938    chan puts $f hello\nthere\nand\nhere
2939    chan close $f
2940    set f [open $path(test1) r]
2941    chan configure $f -translation crlf
2942    chan read $f
2943} -cleanup {
2944    chan close $f
2945} -result "hello\rthere\rand\rhere\r"
2946test chan-io-30.7 {Tcl_Write crlf, Tcl_Read crlf} -setup {
2947    file delete $path(test1)
2948} -body {
2949    set f [open $path(test1) w]
2950    chan configure $f -translation crlf
2951    chan puts $f hello\nthere\nand\nhere
2952    chan close $f
2953    set f [open $path(test1) r]
2954    chan configure $f -translation crlf
2955    chan read $f
2956} -cleanup {
2957    chan close $f
2958} -result "hello\nthere\nand\nhere\n"
2959test chan-io-30.8 {Tcl_Write crlf, Tcl_Read lf} -setup {
2960    file delete $path(test1)
2961} -body {
2962    set f [open $path(test1) w]
2963    chan configure $f -translation crlf
2964    chan puts $f hello\nthere\nand\nhere
2965    chan close $f
2966    set f [open $path(test1) r]
2967    chan configure $f -translation lf
2968    chan read $f
2969} -cleanup {
2970    chan close $f
2971} -result "hello\r\nthere\r\nand\r\nhere\r\n"
2972test chan-io-30.9 {Tcl_Write crlf, Tcl_Read cr} -setup {
2973    file delete $path(test1)
2974} -body {
2975    set f [open $path(test1) w]
2976    chan configure $f -translation crlf
2977    chan puts $f hello\nthere\nand\nhere
2978    chan close $f
2979    set f [open $path(test1) r]
2980    chan configure $f -translation cr
2981    chan read $f
2982} -cleanup {
2983    chan close $f
2984} -result "hello\n\nthere\n\nand\n\nhere\n\n"
2985test chan-io-30.10 {Tcl_Write lf, Tcl_Read auto} -setup {
2986    file delete $path(test1)
2987} -body {
2988    set f [open $path(test1) w]
2989    chan configure $f -translation lf
2990    chan puts $f hello\nthere\nand\nhere
2991    chan close $f
2992    set f [open $path(test1) r]
2993    list [chan read $f] [chan configure $f -translation]
2994} -cleanup {
2995    chan close $f
2996} -result {{hello
2997there
2998and
2999here
3000} auto}
3001test chan-io-30.11 {Tcl_Write cr, Tcl_Read auto} -setup {
3002    file delete $path(test1)
3003} -body {
3004    set f [open $path(test1) w]
3005    chan configure $f -translation cr
3006    chan puts $f hello\nthere\nand\nhere
3007    chan close $f
3008    set f [open $path(test1) r]
3009    list [chan read $f] [chan configure $f -translation]
3010} -cleanup {
3011    chan close $f
3012} -result {{hello
3013there
3014and
3015here
3016} auto}
3017test chan-io-30.12 {Tcl_Write crlf, Tcl_Read auto} -setup {
3018    file delete $path(test1)
3019} -body {
3020    set f [open $path(test1) w]
3021    chan configure $f -translation crlf
3022    chan puts $f hello\nthere\nand\nhere
3023    chan close $f
3024    set f [open $path(test1) r]
3025    list [chan read $f] [chan configure $f -translation]
3026} -cleanup {
3027    chan close $f
3028} -result {{hello
3029there
3030and
3031here
3032} auto}
3033test chan-io-30.13 {Tcl_Write crlf on block boundary, Tcl_Read auto} -setup {
3034    file delete $path(test1)
3035} -body {
3036    set f [open $path(test1) w]
3037    chan configure $f -translation crlf
3038    set line "123456789ABCDE"	;# 14 char plus crlf
3039    chan puts -nonewline $f x	;# shift crlf across block boundary
3040    for {set i 0} {$i < 700} {incr i} {
3041	chan puts $f $line
3042    }
3043    chan close $f
3044    set f [open $path(test1) r]
3045    chan configure $f -translation auto
3046    string length [chan read $f]
3047} -cleanup {
3048    chan close $f
3049} -result [expr {700*15 + 1}]
3050test chan-io-30.14 {Tcl_Write crlf on block boundary, Tcl_Read crlf} -setup {
3051    file delete $path(test1)
3052} -body {
3053    set f [open $path(test1) w]
3054    chan configure $f -translation crlf
3055    set line "123456789ABCDE"	;# 14 char plus crlf
3056    chan puts -nonewline $f x	;# shift crlf across block boundary
3057    for {set i 0} {$i < 700} {incr i} {
3058	chan puts $f $line
3059    }
3060    chan close $f
3061    set f [open $path(test1) r]
3062    chan configure $f -translation crlf
3063    string length [chan read $f]
3064} -cleanup {
3065    chan close $f
3066} -result [expr {700*15 + 1}]
3067test chan-io-30.15 {Tcl_Write mixed, Tcl_Read auto} -setup {
3068    file delete $path(test1)
3069} -body {
3070    set f [open $path(test1) w]
3071    chan configure $f -translation lf
3072    chan puts $f hello\nthere\nand\rhere
3073    chan close $f
3074    set f [open $path(test1) r]
3075    chan configure $f -translation auto
3076    chan read $f
3077} -cleanup {
3078    chan close $f
3079} -result {hello
3080there
3081and
3082here
3083}
3084test chan-io-30.16 {Tcl_Write ^Z at end, Tcl_Read auto} -setup {
3085    file delete $path(test1)
3086} -body {
3087    set f [open $path(test1) w]
3088    chan configure $f -translation lf
3089    chan puts -nonewline $f hello\nthere\nand\rhere\n\x1a
3090    chan close $f
3091    set f [open $path(test1) r]
3092    chan configure $f -eofchar \x1a -translation auto
3093    chan read $f
3094} -cleanup {
3095    chan close $f
3096} -result {hello
3097there
3098and
3099here
3100}
3101test chan-io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} -setup {
3102    file delete $path(test1)
3103} -constraints {win} -body {
3104    set f [open $path(test1) w]
3105    chan configure $f -eofchar \x1a -translation lf
3106    chan puts $f hello\nthere\nand\rhere
3107    chan close $f
3108    set f [open $path(test1) r]
3109    chan configure $f -eofchar \x1a -translation auto
3110    chan read $f
3111} -cleanup {
3112    chan close $f
3113} -result {hello
3114there
3115and
3116here
3117}
3118test chan-io-30.18 {Tcl_Write, ^Z in middle, Tcl_Read auto} -setup {
3119    file delete $path(test1)
3120} -body {
3121    set f [open $path(test1) w]
3122    chan configure $f -translation lf
3123    set s [format "abc\ndef\n%cghi\nqrs" 26]
3124    chan puts $f $s
3125    chan close $f
3126    set f [open $path(test1) r]
3127    chan configure $f -eofchar \x1a -translation auto
3128    set l ""
3129    lappend l [chan gets $f]
3130    lappend l [chan gets $f]
3131    lappend l [chan eof $f]
3132    lappend l [chan gets $f]
3133    lappend l [chan eof $f]
3134    lappend l [chan gets $f]
3135    lappend l [chan eof $f]
3136} -cleanup {
3137    chan close $f
3138} -result {abc def 0 {} 1 {} 1}
3139test chan-io-30.19 {Tcl_Write, ^Z no newline in middle, Tcl_Read auto} -setup {
3140    file delete $path(test1)
3141} -body {
3142    set f [open $path(test1) w]
3143    chan configure $f -translation lf
3144    set s [format "abc\ndef\n%cghi\nqrs" 26]
3145    chan puts $f $s
3146    chan close $f
3147    set f [open $path(test1) r]
3148    chan configure $f -eofchar \x1a -translation auto
3149    set l ""
3150    lappend l [chan gets $f]
3151    lappend l [chan gets $f]
3152    lappend l [chan eof $f]
3153    lappend l [chan gets $f]
3154    lappend l [chan eof $f]
3155    lappend l [chan gets $f]
3156    lappend l [chan eof $f]
3157} -cleanup {
3158    chan close $f
3159} -result {abc def 0 {} 1 {} 1}
3160test chan-io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} -setup {
3161    file delete $path(test1)
3162    set l ""
3163} -body {
3164    set f [open $path(test1) w]
3165    chan configure $f -translation lf -eofchar {}
3166    chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
3167    chan close $f
3168    set f [open $path(test1) r]
3169    chan configure $f -translation lf -eofchar {}
3170    lappend l [chan gets $f]
3171    lappend l [chan gets $f]
3172    lappend l [chan eof $f]
3173    lappend l [chan gets $f]
3174    lappend l [chan eof $f]
3175    lappend l [chan gets $f]
3176    lappend l [chan eof $f]
3177    lappend l [chan gets $f]
3178    lappend l [chan eof $f]
3179} -cleanup {
3180    chan close $f
3181} -result "abc def 0 \x1aghi 0 qrs 0 {} 1"
3182test chan-io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} -setup {
3183    file delete $path(test1)
3184    set l ""
3185} -body {
3186    set f [open $path(test1) w]
3187    chan configure $f -translation lf -eofchar {}
3188    chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
3189    chan close $f
3190    set f [open $path(test1) r]
3191    chan configure $f -translation cr -eofchar {}
3192    set x [chan gets $f]
3193    lappend l [string equal $x "abc\ndef\n\x1aghi\nqrs\n"]
3194    lappend l [chan eof $f]
3195    lappend l [chan gets $f]
3196    lappend l [chan eof $f]
3197} -cleanup {
3198    chan close $f
3199} -result {1 1 {} 1}
3200test chan-io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} -setup {
3201    file delete $path(test1)
3202    set l ""
3203} -body {
3204    set f [open $path(test1) w]
3205    chan configure $f -translation lf -eofchar {}
3206    chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
3207    chan close $f
3208    set f [open $path(test1) r]
3209    chan configure $f -translation crlf -eofchar {}
3210    set x [chan gets $f]
3211    lappend l [string equal $x "abc\ndef\n\x1aghi\nqrs\n"]
3212    lappend l [chan eof $f]
3213    lappend l [chan gets $f]
3214    lappend l [chan eof $f]
3215} -cleanup {
3216    chan close $f
3217} -result {1 1 {} 1}
3218test chan-io-30.23 {Tcl_Write lf, ^Z in middle, Tcl_Read auto} -setup {
3219    file delete $path(test1)
3220} -body {
3221    set f [open $path(test1) w]
3222    chan configure $f -translation lf
3223    chan puts $f [format abc\ndef\n%cqrs\ntuv 26]
3224    chan close $f
3225    set f [open $path(test1) r]
3226    chan configure $f -translation auto -eofchar \x1a
3227    list [string length [chan read $f]] [chan eof $f]
3228} -cleanup {
3229    chan close $f
3230} -result {8 1}
3231test chan-io-30.24 {Tcl_Write lf, ^Z in middle, Tcl_Read lf} -setup {
3232    file delete $path(test1)
3233} -body {
3234    set f [open $path(test1) w]
3235    chan configure $f -translation lf
3236    set c [format abc\ndef\n%cqrs\ntuv 26]
3237    chan puts $f $c
3238    chan close $f
3239    set f [open $path(test1) r]
3240    chan configure $f -translation lf -eofchar \x1a
3241    list [string length [chan read $f]] [chan eof $f]
3242} -cleanup {
3243    chan close $f
3244} -result {8 1}
3245test chan-io-30.25 {Tcl_Write cr, ^Z in middle, Tcl_Read auto} -setup {
3246    file delete $path(test1)
3247} -body {
3248    set f [open $path(test1) w]
3249    chan configure $f -translation cr
3250    set c [format abc\ndef\n%cqrs\ntuv 26]
3251    chan puts $f $c
3252    chan close $f
3253    set f [open $path(test1) r]
3254    chan configure $f -translation auto -eofchar \x1a
3255    list [string length [chan read $f]] [chan eof $f]
3256} -cleanup {
3257    chan close $f
3258} -result {8 1}
3259test chan-io-30.26 {Tcl_Write cr, ^Z in middle, Tcl_Read cr} -setup {
3260    file delete $path(test1)
3261} -body {
3262    set f [open $path(test1) w]
3263    chan configure $f -translation cr
3264    set c [format abc\ndef\n%cqrs\ntuv 26]
3265    chan puts $f $c
3266    chan close $f
3267    set f [open $path(test1) r]
3268    chan configure $f -translation cr -eofchar \x1a
3269    list [string length [chan read $f]] [chan eof $f]
3270} -cleanup {
3271    chan close $f
3272} -result {8 1}
3273test chan-io-30.27 {Tcl_Write crlf, ^Z in middle, Tcl_Read auto} -setup {
3274    file delete $path(test1)
3275} -body {
3276    set f [open $path(test1) w]
3277    chan configure $f -translation crlf
3278    set c [format abc\ndef\n%cqrs\ntuv 26]
3279    chan puts $f $c
3280    chan close $f
3281    set f [open $path(test1) r]
3282    chan configure $f -translation auto -eofchar \x1a
3283    list [string length [chan read $f]] [chan eof $f]
3284} -cleanup {
3285    chan close $f
3286} -result {8 1}
3287test chan-io-30.28 {Tcl_Write crlf, ^Z in middle, Tcl_Read crlf} -setup {
3288    file delete $path(test1)
3289} -body {
3290    set f [open $path(test1) w]
3291    chan configure $f -translation crlf
3292    set c [format abc\ndef\n%cqrs\ntuv 26]
3293    chan puts $f $c
3294    chan close $f
3295    set f [open $path(test1) r]
3296    chan configure $f -translation crlf -eofchar \x1a
3297    list [string length [chan read $f]] [chan eof $f]
3298} -cleanup {
3299    chan close $f
3300} -result {8 1}
3301
3302# Test end of line translations. Functions tested are Tcl_Write and
3303# Tcl_Gets.
3304
3305test chan-io-31.1 {Tcl_Write lf, Tcl_Gets auto} -setup {
3306    file delete $path(test1)
3307    set l ""
3308} -body {
3309    set f [open $path(test1) w]
3310    chan configure $f -translation lf
3311    chan puts $f hello\nthere\nand\nhere
3312    chan close $f
3313    set f [open $path(test1) r]
3314    lappend l [chan gets $f]
3315    lappend l [chan tell $f]
3316    lappend l [chan configure $f -translation]
3317    lappend l [chan gets $f]
3318    lappend l [chan tell $f]
3319    lappend l [chan configure $f -translation]
3320} -cleanup {
3321    chan close $f
3322} -result {hello 6 auto there 12 auto}
3323test chan-io-31.2 {Tcl_Write cr, Tcl_Gets auto} -setup {
3324    file delete $path(test1)
3325    set l ""
3326} -body {
3327    set f [open $path(test1) w]
3328    chan configure $f -translation cr
3329    chan puts $f hello\nthere\nand\nhere
3330    chan close $f
3331    set f [open $path(test1) r]
3332    lappend l [chan gets $f]
3333    lappend l [chan tell $f]
3334    lappend l [chan configure $f -translation]
3335    lappend l [chan gets $f]
3336    lappend l [chan tell $f]
3337    lappend l [chan configure $f -translation]
3338} -cleanup {
3339    chan close $f
3340} -result {hello 6 auto there 12 auto}
3341test chan-io-31.3 {Tcl_Write crlf, Tcl_Gets auto} -setup {
3342    file delete $path(test1)
3343    set l ""
3344} -body {
3345    set f [open $path(test1) w]
3346    chan configure $f -translation crlf
3347    chan puts $f hello\nthere\nand\nhere
3348    chan close $f
3349    set f [open $path(test1) r]
3350    lappend l [chan gets $f]
3351    lappend l [chan tell $f]
3352    lappend l [chan configure $f -translation]
3353    lappend l [chan gets $f]
3354    lappend l [chan tell $f]
3355    lappend l [chan configure $f -translation]
3356} -cleanup {
3357    chan close $f
3358} -result {hello 7 auto there 14 auto}
3359test chan-io-31.4 {Tcl_Write lf, Tcl_Gets lf} -setup {
3360    file delete $path(test1)
3361    set l ""
3362} -body {
3363    set f [open $path(test1) w]
3364    chan configure $f -translation lf
3365    chan puts $f hello\nthere\nand\nhere
3366    chan close $f
3367    set f [open $path(test1) r]
3368    chan configure $f -translation lf
3369    lappend l [chan gets $f]
3370    lappend l [chan tell $f]
3371    lappend l [chan configure $f -translation]
3372    lappend l [chan gets $f]
3373    lappend l [chan tell $f]
3374    lappend l [chan configure $f -translation]
3375} -cleanup {
3376    chan close $f
3377} -result {hello 6 lf there 12 lf}
3378test chan-io-31.5 {Tcl_Write lf, Tcl_Gets cr} -setup {
3379    file delete $path(test1)
3380    set l ""
3381} -body {
3382    set f [open $path(test1) w]
3383    chan configure $f -translation lf
3384    chan puts $f hello\nthere\nand\nhere
3385    chan close $f
3386    set f [open $path(test1) r]
3387    chan configure $f -translation cr
3388    lappend l [string length [chan gets $f]]
3389    lappend l [chan tell $f]
3390    lappend l [chan configure $f -translation]
3391    lappend l [chan eof $f]
3392    lappend l [chan gets $f]
3393    lappend l [chan tell $f]
3394    lappend l [chan configure $f -translation]
3395    lappend l [chan eof $f]
3396} -cleanup {
3397    chan close $f
3398} -result {21 21 cr 1 {} 21 cr 1}
3399test chan-io-31.6 {Tcl_Write lf, Tcl_Gets crlf} -setup {
3400    file delete $path(test1)
3401    set l ""
3402} -body {
3403    set f [open $path(test1) w]
3404    chan configure $f -translation lf
3405    chan puts $f hello\nthere\nand\nhere
3406    chan close $f
3407    set f [open $path(test1) r]
3408    chan configure $f -translation crlf
3409    lappend l [string length [chan gets $f]]
3410    lappend l [chan tell $f]
3411    lappend l [chan configure $f -translation]
3412    lappend l [chan eof $f]
3413    lappend l [chan gets $f]
3414    lappend l [chan tell $f]
3415    lappend l [chan configure $f -translation]
3416    lappend l [chan eof $f]
3417} -cleanup {
3418    chan close $f
3419} -result {21 21 crlf 1 {} 21 crlf 1}
3420test chan-io-31.7 {Tcl_Write cr, Tcl_Gets cr} -setup {
3421    file delete $path(test1)
3422    set l ""
3423} -body {
3424    set f [open $path(test1) w]
3425    chan configure $f -translation cr
3426    chan puts $f hello\nthere\nand\nhere
3427    chan close $f
3428    set f [open $path(test1) r]
3429    chan configure $f -translation cr
3430    lappend l [chan gets $f]
3431    lappend l [chan tell $f]
3432    lappend l [chan configure $f -translation]
3433    lappend l [chan eof $f]
3434    lappend l [chan gets $f]
3435    lappend l [chan tell $f]
3436    lappend l [chan configure $f -translation]
3437    lappend l [chan eof $f]
3438} -cleanup {
3439    chan close $f
3440} -result {hello 6 cr 0 there 12 cr 0}
3441test chan-io-31.8 {Tcl_Write cr, Tcl_Gets lf} -setup {
3442    file delete $path(test1)
3443    set l ""
3444} -body {
3445    set f [open $path(test1) w]
3446    chan configure $f -translation cr
3447    chan puts $f hello\nthere\nand\nhere
3448    chan close $f
3449    set f [open $path(test1) r]
3450    chan configure $f -translation lf
3451    lappend l [string length [chan gets $f]]
3452    lappend l [chan tell $f]
3453    lappend l [chan configure $f -translation]
3454    lappend l [chan eof $f]
3455    lappend l [chan gets $f]
3456    lappend l [chan tell $f]
3457    lappend l [chan configure $f -translation]
3458    lappend l [chan eof $f]
3459} -cleanup {
3460    chan close $f
3461} -result {21 21 lf 1 {} 21 lf 1}
3462test chan-io-31.9 {Tcl_Write cr, Tcl_Gets crlf} -setup {
3463    file delete $path(test1)
3464    set l ""
3465} -body {
3466    set f [open $path(test1) w]
3467    chan configure $f -translation cr
3468    chan puts $f hello\nthere\nand\nhere
3469    chan close $f
3470    set f [open $path(test1) r]
3471    chan configure $f -translation crlf
3472    lappend l [string length [chan gets $f]]
3473    lappend l [chan tell $f]
3474    lappend l [chan configure $f -translation]
3475    lappend l [chan eof $f]
3476    lappend l [chan gets $f]
3477    lappend l [chan tell $f]
3478    lappend l [chan configure $f -translation]
3479    lappend l [chan eof $f]
3480} -cleanup {
3481    chan close $f
3482} -result {21 21 crlf 1 {} 21 crlf 1}
3483test chan-io-31.10 {Tcl_Write crlf, Tcl_Gets crlf} -setup {
3484    file delete $path(test1)
3485    set l ""
3486} -body {
3487    set f [open $path(test1) w]
3488    chan configure $f -translation crlf
3489    chan puts $f hello\nthere\nand\nhere
3490    chan close $f
3491    set f [open $path(test1) r]
3492    chan configure $f -translation crlf
3493    lappend l [chan gets $f]
3494    lappend l [chan tell $f]
3495    lappend l [chan configure $f -translation]
3496    lappend l [chan eof $f]
3497    lappend l [chan gets $f]
3498    lappend l [chan tell $f]
3499    lappend l [chan configure $f -translation]
3500    lappend l [chan eof $f]
3501} -cleanup {
3502    chan close $f
3503} -result {hello 7 crlf 0 there 14 crlf 0}
3504test chan-io-31.11 {Tcl_Write crlf, Tcl_Gets cr} -setup {
3505    file delete $path(test1)
3506    set l ""
3507} -body {
3508    set f [open $path(test1) w]
3509    chan configure $f -translation crlf
3510    chan puts $f hello\nthere\nand\nhere
3511    chan close $f
3512    set f [open $path(test1) r]
3513    chan configure $f -translation cr
3514    lappend l [chan gets $f]
3515    lappend l [chan tell $f]
3516    lappend l [chan configure $f -translation]
3517    lappend l [chan eof $f]
3518    lappend l [string length [chan gets $f]]
3519    lappend l [chan tell $f]
3520    lappend l [chan configure $f -translation]
3521    lappend l [chan eof $f]
3522} -cleanup {
3523    chan close $f
3524} -result {hello 6 cr 0 6 13 cr 0}
3525test chan-io-31.12 {Tcl_Write crlf, Tcl_Gets lf} -setup {
3526    file delete $path(test1)
3527    set l ""
3528} -body {
3529    set f [open $path(test1) w]
3530    chan configure $f -translation crlf
3531    chan puts $f hello\nthere\nand\nhere
3532    chan close $f
3533    set f [open $path(test1) r]
3534    chan configure $f -translation lf
3535    lappend l [string length [chan gets $f]]
3536    lappend l [chan tell $f]
3537    lappend l [chan configure $f -translation]
3538    lappend l [chan eof $f]
3539    lappend l [string length [chan gets $f]]
3540    lappend l [chan tell $f]
3541    lappend l [chan configure $f -translation]
3542    lappend l [chan eof $f]
3543} -cleanup {
3544    chan close $f
3545} -result {6 7 lf 0 6 14 lf 0}
3546test chan-io-31.13 {binary mode is synonym of lf mode} -setup {
3547    file delete $path(test1)
3548} -body {
3549    set f [open $path(test1) w]
3550    chan configure $f -translation binary
3551    chan configure $f -translation
3552} -cleanup {
3553    chan close $f
3554} -result lf
3555#
3556# Test chan-io-9.14 has been removed because "auto" output translation mode is
3557# not supoprted.
3558#
3559test chan-io-31.14 {Tcl_Write mixed, Tcl_Gets auto} -setup {
3560    file delete $path(test1)
3561    set l ""
3562} -body {
3563    set f [open $path(test1) w]
3564    chan configure $f -translation lf
3565    chan puts $f hello\nthere\rand\r\nhere
3566    chan close $f
3567    set f [open $path(test1) r]
3568    chan configure $f -translation auto
3569    lappend l [chan gets $f]
3570    lappend l [chan gets $f]
3571    lappend l [chan gets $f]
3572    lappend l [chan gets $f]
3573    lappend l [chan eof $f]
3574    lappend l [chan gets $f]
3575    lappend l [chan eof $f]
3576} -cleanup {
3577    chan close $f
3578} -result {hello there and here 0 {} 1}
3579test chan-io-31.15 {Tcl_Write mixed, Tcl_Gets auto} -setup {
3580    file delete $path(test1)
3581    set l ""
3582} -body {
3583    set f [open $path(test1) w]
3584    chan configure $f -translation lf
3585    chan puts -nonewline $f hello\nthere\rand\r\nhere\r
3586    chan close $f
3587    set f [open $path(test1) r]
3588    chan configure $f -translation auto
3589    lappend l [chan gets $f]
3590    lappend l [chan gets $f]
3591    lappend l [chan gets $f]
3592    lappend l [chan gets $f]
3593    lappend l [chan eof $f]
3594    lappend l [chan gets $f]
3595    lappend l [chan eof $f]
3596} -cleanup {
3597    chan close $f
3598} -result {hello there and here 0 {} 1}
3599test chan-io-31.16 {Tcl_Write mixed, Tcl_Gets auto} -setup {
3600    file delete $path(test1)
3601    set l ""
3602} -body {
3603    set f [open $path(test1) w]
3604    chan configure $f -translation lf
3605    chan puts -nonewline $f hello\nthere\rand\r\nhere\n
3606    chan close $f
3607    set f [open $path(test1) r]
3608    lappend l [chan gets $f]
3609    lappend l [chan gets $f]
3610    lappend l [chan gets $f]
3611    lappend l [chan gets $f]
3612    lappend l [chan eof $f]
3613    lappend l [chan gets $f]
3614    lappend l [chan eof $f]
3615} -cleanup {
3616    chan close $f
3617} -result {hello there and here 0 {} 1}
3618test chan-io-31.17 {Tcl_Write mixed, Tcl_Gets auto} -setup {
3619    file delete $path(test1)
3620    set l ""
3621} -body {
3622    set f [open $path(test1) w]
3623    chan configure $f -translation lf
3624    chan puts -nonewline $f hello\nthere\rand\r\nhere\r\n
3625    chan close $f
3626    set f [open $path(test1) r]
3627    chan configure $f -translation auto
3628    lappend l [chan gets $f]
3629    lappend l [chan gets $f]
3630    lappend l [chan gets $f]
3631    lappend l [chan gets $f]
3632    lappend l [chan eof $f]
3633    lappend l [chan gets $f]
3634    lappend l [chan eof $f]
3635} -cleanup {
3636    chan close $f
3637} -result {hello there and here 0 {} 1}
3638test chan-io-31.18 {Tcl_Write ^Z at end, Tcl_Gets auto} -setup {
3639    file delete $path(test1)
3640    set l ""
3641} -body {
3642    set f [open $path(test1) w]
3643    chan configure $f -translation lf
3644    chan puts $f [format "hello\nthere\nand\rhere\n\%c" 26]
3645    chan close $f
3646    set f [open $path(test1) r]
3647    chan configure $f -eofchar \x1a -translation auto
3648    lappend l [chan gets $f]
3649    lappend l [chan gets $f]
3650    lappend l [chan gets $f]
3651    lappend l [chan gets $f]
3652    lappend l [chan eof $f]
3653    lappend l [chan gets $f]
3654    lappend l [chan eof $f]
3655} -cleanup {
3656    chan close $f
3657} -result {hello there and here 0 {} 1}
3658test chan-io-31.19 {Tcl_Write, implicit ^Z at end, Tcl_Gets auto} -setup {
3659    file delete $path(test1)
3660    set l ""
3661} -body {
3662    set f [open $path(test1) w]
3663    chan configure $f -eofchar \x1a -translation lf
3664    chan puts $f hello\nthere\nand\rhere
3665    chan close $f
3666    set f [open $path(test1) r]
3667    chan configure $f -eofchar \x1a -translation auto
3668    lappend l [chan gets $f]
3669    lappend l [chan gets $f]
3670    lappend l [chan gets $f]
3671    lappend l [chan gets $f]
3672    lappend l [chan eof $f]
3673    lappend l [chan gets $f]
3674    lappend l [chan eof $f]
3675} -cleanup {
3676    chan close $f
3677} -result {hello there and here 0 {} 1}
3678test chan-io-31.20 {Tcl_Write, ^Z in middle, Tcl_Gets auto, eofChar} -setup {
3679    file delete $path(test1)
3680    set l ""
3681} -body {
3682    set f [open $path(test1) w]
3683    chan configure $f -translation lf
3684    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3685    chan close $f
3686    set f [open $path(test1) r]
3687    chan configure $f -eofchar \x1a
3688    chan configure $f -translation auto
3689    lappend l [chan gets $f]
3690    lappend l [chan gets $f]
3691    lappend l [chan eof $f]
3692    lappend l [chan gets $f]
3693    lappend l [chan eof $f]
3694} -cleanup {
3695    chan close $f
3696} -result {abc def 0 {} 1}
3697test chan-io-31.21 {Tcl_Write, no newline ^Z in middle, Tcl_Gets auto, eofChar} -setup {
3698    file delete $path(test1)
3699    set l ""
3700} -body {
3701    set f [open $path(test1) w]
3702    chan configure $f -translation lf
3703    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3704    chan close $f
3705    set f [open $path(test1) r]
3706    chan configure $f -eofchar \x1a -translation auto
3707    lappend l [chan gets $f]
3708    lappend l [chan gets $f]
3709    lappend l [chan eof $f]
3710    lappend l [chan gets $f]
3711    lappend l [chan eof $f]
3712} -cleanup {
3713    chan close $f
3714} -result {abc def 0 {} 1}
3715test chan-io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} -setup {
3716    file delete $path(test1)
3717    set l ""
3718} -body {
3719    set f [open $path(test1) w]
3720    chan configure $f -translation lf -eofchar {}
3721    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3722    chan close $f
3723    set f [open $path(test1) r]
3724    chan configure $f -translation lf -eofchar {}
3725    lappend l [chan gets $f]
3726    lappend l [chan gets $f]
3727    lappend l [chan eof $f]
3728    lappend l [chan gets $f]
3729    lappend l [chan eof $f]
3730    lappend l [chan gets $f]
3731    lappend l [chan eof $f]
3732    lappend l [chan gets $f]
3733    lappend l [chan eof $f]
3734} -cleanup {
3735    chan close $f
3736} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1"
3737test chan-io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} -setup {
3738    file delete $path(test1)
3739    set l ""
3740} -body {
3741    set f [open $path(test1) w]
3742    chan configure $f -translation cr -eofchar {}
3743    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3744    chan close $f
3745    set f [open $path(test1) r]
3746    chan configure $f -translation cr -eofchar {}
3747    lappend l [chan gets $f]
3748    lappend l [chan gets $f]
3749    lappend l [chan eof $f]
3750    lappend l [chan gets $f]
3751    lappend l [chan eof $f]
3752    lappend l [chan gets $f]
3753    lappend l [chan eof $f]
3754    lappend l [chan gets $f]
3755    lappend l [chan eof $f]
3756} -cleanup {
3757    chan close $f
3758} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1"
3759test chan-io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} -setup {
3760    file delete $path(test1)
3761    set l ""
3762} -body {
3763    set f [open $path(test1) w]
3764    chan configure $f -translation crlf -eofchar {}
3765    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3766    chan close $f
3767    set f [open $path(test1) r]
3768    chan configure $f -translation crlf -eofchar {}
3769    lappend l [chan gets $f]
3770    lappend l [chan gets $f]
3771    lappend l [chan eof $f]
3772    lappend l [chan gets $f]
3773    lappend l [chan eof $f]
3774    lappend l [chan gets $f]
3775    lappend l [chan eof $f]
3776    lappend l [chan gets $f]
3777    lappend l [chan eof $f]
3778} -cleanup {
3779    chan close $f
3780} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1"
3781test chan-io-31.25 {Tcl_Write lf, ^Z in middle, Tcl_Gets auto} -setup {
3782    file delete $path(test1)
3783    set l ""
3784} -body {
3785    set f [open $path(test1) w]
3786    chan configure $f -translation lf
3787    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3788    chan close $f
3789    set f [open $path(test1) r]
3790    chan configure $f -translation auto -eofchar \x1a
3791    lappend l [chan gets $f]
3792    lappend l [chan gets $f]
3793    lappend l [chan eof $f]
3794    lappend l [chan gets $f]
3795    lappend l [chan eof $f]
3796} -cleanup {
3797    chan close $f
3798} -result {abc def 0 {} 1}
3799test chan-io-31.26 {Tcl_Write lf, ^Z in middle, Tcl_Gets lf} -setup {
3800    file delete $path(test1)
3801    set l ""
3802} -body {
3803    set f [open $path(test1) w]
3804    chan configure $f -translation lf
3805    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3806    chan close $f
3807    set f [open $path(test1) r]
3808    chan configure $f -translation lf -eofchar \x1a
3809    lappend l [chan gets $f]
3810    lappend l [chan gets $f]
3811    lappend l [chan eof $f]
3812    lappend l [chan gets $f]
3813    lappend l [chan eof $f]
3814} -cleanup {
3815    chan close $f
3816} -result {abc def 0 {} 1}
3817test chan-io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} -setup {
3818    file delete $path(test1)
3819    set l ""
3820} -body {
3821    set f [open $path(test1) w]
3822    chan configure $f -translation cr -eofchar {}
3823    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3824    chan close $f
3825    set f [open $path(test1) r]
3826    chan configure $f -translation auto -eofchar \x1a
3827    lappend l [chan gets $f]
3828    lappend l [chan gets $f]
3829    lappend l [chan eof $f]
3830    lappend l [chan gets $f]
3831    lappend l [chan eof $f]
3832} -cleanup {
3833    chan close $f
3834} -result {abc def 0 {} 1}
3835test chan-io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} -setup {
3836    file delete $path(test1)
3837    set l ""
3838} -body {
3839    set f [open $path(test1) w]
3840    chan configure $f -translation cr -eofchar {}
3841    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3842    chan close $f
3843    set f [open $path(test1) r]
3844    chan configure $f -translation cr -eofchar \x1a
3845    lappend l [chan gets $f]
3846    lappend l [chan gets $f]
3847    lappend l [chan eof $f]
3848    lappend l [chan gets $f]
3849    lappend l [chan eof $f]
3850} -cleanup {
3851    chan close $f
3852} -result {abc def 0 {} 1}
3853test chan-io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} -setup {
3854    file delete $path(test1)
3855    set l ""
3856} -body {
3857    set f [open $path(test1) w]
3858    chan configure $f -translation crlf -eofchar {}
3859    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3860    chan close $f
3861    set f [open $path(test1) r]
3862    chan configure $f -translation auto -eofchar \x1a
3863    lappend l [chan gets $f]
3864    lappend l [chan gets $f]
3865    lappend l [chan eof $f]
3866    lappend l [chan gets $f]
3867    lappend l [chan eof $f]
3868} -cleanup {
3869    chan close $f
3870} -result {abc def 0 {} 1}
3871test chan-io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} -setup {
3872    file delete $path(test1)
3873    set l ""
3874} -body {
3875    set f [open $path(test1) w]
3876    chan configure $f -translation crlf -eofchar {}
3877    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3878    chan close $f
3879    set f [open $path(test1) r]
3880    chan configure $f -translation crlf -eofchar \x1a
3881    lappend l [chan gets $f]
3882    lappend l [chan gets $f]
3883    lappend l [chan eof $f]
3884    lappend l [chan gets $f]
3885    lappend l [chan eof $f]
3886} -cleanup {
3887    chan close $f
3888} -result {abc def 0 {} 1}
3889test chan-io-31.31 {Tcl_Write crlf on block boundary, Tcl_Gets crlf} -setup {
3890    file delete $path(test1)
3891    set c ""
3892} -body {
3893    set f [open $path(test1) w]
3894    chan configure $f -translation crlf
3895    set line "123456789ABCDE"	;# 14 char plus crlf
3896    chan puts -nonewline $f x	;# shift crlf across block boundary
3897    for {set i 0} {$i < 700} {incr i} {
3898	chan puts $f $line
3899    }
3900    chan close $f
3901    set f [open $path(test1) r]
3902    chan configure $f -translation crlf
3903    while {[chan gets $f line] >= 0} {
3904	append c $line\n
3905    }
3906    chan close $f
3907    string length $c
3908} -result [expr {700*15 + 1}]
3909test chan-io-31.32 {Tcl_Write crlf on block boundary, Tcl_Gets auto} -setup {
3910    file delete $path(test1)
3911    set c ""
3912} -body {
3913    set f [open $path(test1) w]
3914    chan configure $f -translation crlf
3915    set line "123456789ABCDE"	;# 14 char plus crlf
3916    chan puts -nonewline $f x	;# shift crlf across block boundary
3917    for {set i 0} {$i < 700} {incr i} {
3918	chan puts $f $line
3919    }
3920    chan close $f
3921    set f [open $path(test1) r]
3922    chan configure $f -translation auto
3923    while {[chan gets $f line] >= 0} {
3924	append c $line\n
3925    }
3926    chan close $f
3927    string length $c
3928} -result [expr {700*15 + 1}]
3929
3930# Test Tcl_Read and buffering.
3931
3932test chan-io-32.1 {Tcl_Read, channel not readable} -body {
3933    read stdout
3934} -returnCodes error -result {channel "stdout" wasn't opened for reading}
3935test chan-io-32.2 {Tcl_Read, zero byte count} {
3936    chan read stdin 0
3937} ""
3938test chan-io-32.3 {Tcl_Read, negative byte count} -setup {
3939    set f [open $path(longfile) r]
3940} -body {
3941    chan read $f -1
3942} -returnCodes error -cleanup {
3943    chan close $f
3944} -result {expected non-negative integer but got "-1"}
3945test chan-io-32.4 {Tcl_Read, positive byte count} -body {
3946    set f [open $path(longfile) r]
3947    string length [chan read $f 1024]
3948} -cleanup {
3949    chan close $f
3950} -result 1024
3951test chan-io-32.5 {Tcl_Read, multiple buffers} -body {
3952    set f [open $path(longfile) r]
3953    chan configure $f -buffersize 100
3954    string length [chan read $f 1024]
3955} -cleanup {
3956    chan close $f
3957} -result 1024
3958test chan-io-32.6 {Tcl_Read, very large read} {
3959    set f1 [open $path(longfile) r]
3960    set z [chan read $f1 1000000]
3961    chan close $f1
3962    set l [string length $z]
3963    set x ok
3964    set z [file size $path(longfile)]
3965    if {$z != $l} {
3966	set x "$z != $l"
3967    }
3968    set x
3969} ok
3970test chan-io-32.7 {Tcl_Read, nonblocking, file} {nonBlockFiles} {
3971    set f1 [open $path(longfile) r]
3972    chan configure $f1 -blocking off
3973    set z [chan read $f1 20]
3974    chan close $f1
3975    set l [string length $z]
3976    set x ok
3977    if {$l != 20} {
3978	set x "$l != 20"
3979    }
3980    set x
3981} ok
3982test chan-io-32.8 {Tcl_Read, nonblocking, file} {nonBlockFiles} {
3983    set f1 [open $path(longfile) r]
3984    chan configure $f1 -blocking off
3985    set z [chan read $f1 1000000]
3986    chan close $f1
3987    set x ok
3988    set l [string length $z]
3989    set z [file size $path(longfile)]
3990    if {$z != $l} {
3991	set x "$z != $l"
3992    }
3993    set x
3994} ok
3995test chan-io-32.9 {Tcl_Read, read to end of file} {
3996    set f1 [open $path(longfile) r]
3997    set z [chan read $f1]
3998    chan close $f1
3999    set l [string length $z]
4000    set x ok
4001    set z [file size $path(longfile)]
4002    if {$z != $l} {
4003	set x "$z != $l"
4004    }
4005    set x
4006} ok
4007test chan-io-32.10 {Tcl_Read from a pipe} -setup {
4008    file delete $path(pipe)
4009} -constraints stdio -body {
4010    set f1 [open $path(pipe) w]
4011    chan puts $f1 {chan puts [chan gets stdin]}
4012    chan close $f1
4013    set f1 [openpipe r+ $path(pipe)]
4014    chan puts $f1 hello
4015    chan flush $f1
4016    chan read $f1
4017} -cleanup {
4018    chan close $f1
4019} -result "hello\n"
4020test chan-io-32.11 {Tcl_Read from a pipe} -setup {
4021    file delete $path(pipe)
4022    set x ""
4023} -constraints stdio -body {
4024    set f1 [open $path(pipe) w]
4025    chan puts $f1 {chan puts [chan gets stdin]}
4026    chan puts $f1 {chan puts [chan gets stdin]}
4027    chan close $f1
4028    set f1 [openpipe r+ $path(pipe)]
4029    chan puts $f1 hello
4030    chan flush $f1
4031    lappend x [chan read $f1 6]
4032    chan puts $f1 hello
4033    chan flush $f1
4034    lappend x [chan read $f1]
4035} -cleanup {
4036    chan close $f1
4037} -result {{hello
4038} {hello
4039}}
4040test chan-io-32.12 {Tcl_Read, -nonewline} -setup {
4041    file delete $path(test1)
4042} -body {
4043    set f1 [open $path(test1) w]
4044    chan puts $f1 hello
4045    chan puts $f1 bye
4046    chan close $f1
4047    set f1 [open $path(test1) r]
4048    chan read -nonewline $f1
4049} -cleanup {
4050    chan close $f1
4051} -result {hello
4052bye}
4053test chan-io-32.13 {Tcl_Read, -nonewline} -setup {
4054    file delete $path(test1)
4055} -body {
4056    set f1 [open $path(test1) w]
4057    chan puts $f1 hello
4058    chan puts $f1 bye
4059    chan close $f1
4060    set f1 [open $path(test1) r]
4061    set c [chan read -nonewline $f1]
4062    list [string length $c] $c
4063} -cleanup {
4064    chan close $f1
4065} -result {9 {hello
4066bye}}
4067test chan-io-32.14 {Tcl_Read, reading in small chunks} -setup {
4068    file delete $path(test1)
4069} -body {
4070    set f [open $path(test1) w]
4071    chan puts $f "Two lines: this one"
4072    chan puts $f "and this one"
4073    chan close $f
4074    set f [open $path(test1)]
4075    list [chan read $f 1] [chan read $f 2] [chan read $f]
4076} -cleanup {
4077    chan close $f
4078} -result {T wo { lines: this one
4079and this one
4080}}
4081test chan-io-32.15 {Tcl_Read, asking for more input than available} -setup {
4082    file delete $path(test1)
4083} -body {
4084    set f [open $path(test1) w]
4085    chan puts $f "Two lines: this one"
4086    chan puts $f "and this one"
4087    chan close $f
4088    set f [open $path(test1)]
4089    chan read $f 100
4090} -cleanup {
4091    chan close $f
4092} -result {Two lines: this one
4093and this one
4094}
4095test chan-io-32.16 {Tcl_Read, read to end of file with -nonewline} -setup {
4096    file delete $path(test1)
4097} -body {
4098    set f [open $path(test1) w]
4099    chan puts $f "Two lines: this one"
4100    chan puts $f "and this one"
4101    chan close $f
4102    set f [open $path(test1)]
4103    chan read -nonewline $f
4104} -cleanup {
4105    chan close $f
4106} -result {Two lines: this one
4107and this one}
4108
4109# Test Tcl_Gets.
4110
4111test chan-io-33.1 {Tcl_Gets, reading what was written} -setup {
4112    file delete $path(test1)
4113} -body {
4114    set f1 [open $path(test1) w]
4115    chan puts $f1 "first line"
4116    chan close $f1
4117    set f1 [open $path(test1) r]
4118    chan gets $f1
4119} -cleanup {
4120    chan close $f1
4121} -result {first line}
4122test chan-io-33.2 {Tcl_Gets into variable} {
4123    set f1 [open $path(longfile) r]
4124    set c [chan gets $f1 x]
4125    set l [string length x]
4126    set z ok
4127    if {$l != $l} {
4128	set z broken
4129    }
4130    chan close $f1
4131    set z
4132} ok
4133test chan-io-33.3 {Tcl_Gets from pipe} -setup {
4134    file delete $path(pipe)
4135} -constraints stdio -body {
4136    set f1 [open $path(pipe) w]
4137    chan puts $f1 {chan puts [chan gets stdin]}
4138    chan close $f1
4139    set f1 [openpipe r+ $path(pipe)]
4140    chan puts $f1 hello
4141    chan flush $f1
4142    chan gets $f1
4143} -cleanup {
4144    chan close $f1
4145} -result hello
4146test chan-io-33.4 {Tcl_Gets with long line} -setup {
4147    file delete $path(test3)
4148} -body {
4149    set f [open $path(test3) w]
4150    chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4151    chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4152    chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4153    chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4154    chan puts $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4155    chan close $f
4156    set f [open $path(test3)]
4157    chan gets $f
4158} -cleanup {
4159    chan close $f
4160} -result {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
4161test chan-io-33.5 {Tcl_Gets with long line} -setup {
4162    set f [open $path(test3) w]
4163    puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4164    puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4165    puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4166    puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4167    puts $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4168    close $f
4169} -body {
4170    set f [open $path(test3)]
4171    set x [chan gets $f y]
4172    chan close $f
4173    list $x $y
4174} -result {260 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
4175test chan-io-33.6 {Tcl_Gets and end of file} -setup {
4176    file delete $path(test3)
4177    set x {}
4178} -body {
4179    set f [open $path(test3) w]
4180    chan puts -nonewline $f "Test1\nTest2"
4181    chan close $f
4182    set f [open $path(test3)]
4183    set y {}
4184    lappend x [chan gets $f y] $y
4185    set y {}
4186    lappend x [chan gets $f y] $y
4187    set y {}
4188    lappend x [chan gets $f y] $y
4189} -cleanup {
4190    chan close $f
4191} -result {5 Test1 5 Test2 -1 {}}
4192test chan-io-33.7 {Tcl_Gets and bad variable} -setup {
4193    set f [open $path(test3) w]
4194    chan puts $f "Line 1"
4195    chan puts $f "Line 2"
4196    chan close $f
4197    catch {unset x}
4198    set f [open $path(test3) r]
4199} -body {
4200    set x 24
4201    chan gets $f x(0)
4202} -returnCodes error -cleanup {
4203    chan close $f
4204} -result {can't set "x(0)": variable isn't array}
4205test chan-io-33.8 {Tcl_Gets, exercising double buffering} {
4206    set f [open $path(test3) w]
4207    chan configure $f -translation lf -eofchar {}
4208    set x ""
4209    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
4210    for {set y 0} {$y < 100} {incr y} {chan puts $f $x}
4211    chan close $f
4212    set f [open $path(test3) r]
4213    chan configure $f -translation lf
4214    for {set y 0} {$y < 100} {incr y} {chan gets $f}
4215    chan close $f
4216    set y
4217} 100
4218test chan-io-33.9 {Tcl_Gets, exercising double buffering} {
4219    set f [open $path(test3) w]
4220    chan configure $f -translation lf -eofchar {}
4221    set x ""
4222    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
4223    for {set y 0} {$y < 200} {incr y} {chan puts $f $x}
4224    chan close $f
4225    set f [open $path(test3) r]
4226    chan configure $f -translation lf
4227    for {set y 0} {$y < 200} {incr y} {chan gets $f}
4228    chan close $f
4229    set y
4230} 200
4231test chan-io-33.10 {Tcl_Gets, exercising double buffering} {
4232    set f [open $path(test3) w]
4233    chan configure $f -translation lf -eofchar {}
4234    set x ""
4235    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
4236    for {set y 0} {$y < 300} {incr y} {chan puts $f $x}
4237    chan close $f
4238    set f [open $path(test3) r]
4239    chan configure $f -translation lf
4240    for {set y 0} {$y < 300} {incr y} {chan gets $f}
4241    chan close $f
4242    set y
4243} 300
4244
4245# Test Tcl_Seek and Tcl_Tell.
4246
4247test chan-io-34.1 {Tcl_Seek to current position at start of file} -body {
4248    set f1 [open $path(longfile) r]
4249    chan seek $f1 0 current
4250    chan tell $f1
4251} -cleanup {
4252    chan close $f1
4253} -result 0
4254test chan-io-34.2 {Tcl_Seek to offset from start} -setup {
4255    file delete $path(test1)
4256} -body {
4257    set f1 [open $path(test1) w]
4258    chan configure $f1 -translation lf -eofchar {}
4259    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4260    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4261    chan close $f1
4262    set f1 [open $path(test1) r]
4263    chan seek $f1 10 start
4264    chan tell $f1
4265} -cleanup {
4266    chan close $f1
4267} -result 10
4268test chan-io-34.3 {Tcl_Seek to end of file} -setup {
4269    file delete $path(test1)
4270} -body {
4271    set f1 [open $path(test1) w]
4272    chan configure $f1 -translation lf -eofchar {}
4273    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4274    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4275    chan close $f1
4276    set f1 [open $path(test1) r]
4277    chan seek $f1 0 end
4278    chan tell $f1
4279} -cleanup {
4280    chan close $f1
4281} -result 54
4282test chan-io-34.4 {Tcl_Seek to offset from end of file} -setup {
4283    file delete $path(test1)
4284} -body {
4285    set f1 [open $path(test1) w]
4286    chan configure $f1 -translation lf -eofchar {}
4287    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4288    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4289    chan close $f1
4290    set f1 [open $path(test1) r]
4291    chan seek $f1 -10 end
4292    chan tell $f1
4293} -cleanup {
4294    chan close $f1
4295} -result 44
4296test chan-io-34.5 {Tcl_Seek to offset from current position} -setup {
4297    file delete $path(test1)
4298} -body {
4299    set f1 [open $path(test1) w]
4300    chan configure $f1 -translation lf -eofchar {}
4301    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4302    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4303    chan close $f1
4304    set f1 [open $path(test1) r]
4305    chan seek $f1 10 current
4306    chan seek $f1 10 current
4307    chan tell $f1
4308} -cleanup {
4309    chan close $f1
4310} -result 20
4311test chan-io-34.6 {Tcl_Seek to offset from end of file} -setup {
4312    file delete $path(test1)
4313} -body {
4314    set f1 [open $path(test1) w]
4315    chan configure $f1 -translation lf -eofchar {}
4316    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4317    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4318    chan close $f1
4319    set f1 [open $path(test1) r]
4320    chan seek $f1 -10 end
4321    list [chan tell $f1] [chan read $f1]
4322} -cleanup {
4323    chan close $f1
4324} -result {44 {rstuvwxyz
4325}}
4326test chan-io-34.7 {Tcl_Seek to offset from end of file, then to current position} -setup {
4327    file delete $path(test1)
4328} -body {
4329    set f1 [open $path(test1) w]
4330    chan configure $f1 -translation lf -eofchar {}
4331    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4332    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4333    chan close $f1
4334    set f1 [open $path(test1) r]
4335    chan seek $f1 -10 end
4336    set c1 [chan tell $f1]
4337    set r1 [chan read $f1 5]
4338    chan seek $f1 0 current
4339    list $c1 $r1 [chan tell $f1]
4340} -cleanup {
4341    chan close $f1
4342} -result {44 rstuv 49}
4343test chan-io-34.8 {Tcl_Seek on pipes: not supported} -setup {
4344    set pipe [openpipe]
4345} -constraints stdio -body {
4346    chan seek $pipe 0 current
4347} -returnCodes error -cleanup {
4348    chan close $pipe
4349} -match glob -result {error during seek on "*": invalid argument}
4350test chan-io-34.9 {Tcl_Seek, testing buffered input flushing} -setup {
4351    file delete $path(test3)
4352} -body {
4353    set f [open $path(test3) w]
4354    chan configure $f -eofchar {}
4355    chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4356    chan close $f
4357    set f [open $path(test3) RDWR]
4358    set x [chan read $f 1]
4359    chan seek $f 3
4360    lappend x [chan read $f 1]
4361    chan seek $f 0 start
4362    lappend x [chan read $f 1]
4363    chan seek $f 10 current
4364    lappend x [chan read $f 1]
4365    chan seek $f -2 end
4366    lappend x [chan read $f 1]
4367    chan seek $f 50 end
4368    lappend x [chan read $f 1]
4369    chan seek $f 1
4370    lappend x [chan read $f 1]
4371} -cleanup {
4372    chan close $f
4373} -result {a d a l Y {} b}
4374set path(test3) [makeFile {} test3]
4375test chan-io-34.10 {Tcl_Seek testing flushing of buffered input} {
4376    set f [open $path(test3) w]
4377    chan configure $f -translation lf
4378    chan puts $f xyz\n123
4379    chan close $f
4380    set f [open $path(test3) r+]
4381    chan configure $f -translation lf
4382    set x [chan gets $f]
4383    chan seek $f 0 current
4384    chan puts $f 456
4385    chan close $f
4386    list $x [viewFile test3]
4387} "xyz {xyz
4388456}"
4389test chan-io-34.11 {Tcl_Seek testing flushing of buffered output} {
4390    set f [open $path(test3) w]
4391    chan puts $f xyz\n123
4392    chan close $f
4393    set f [open $path(test3) w+]
4394    chan puts $f xyzzy
4395    chan seek $f 2
4396    set x [chan gets $f]
4397    chan close $f
4398    list $x [viewFile test3]
4399} "zzy xyzzy"
4400test chan-io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
4401    set f [open $path(test3) w]
4402    chan configure $f -translation lf -eofchar {}
4403    chan puts $f xyz\n123
4404    chan close $f
4405    set f [open $path(test3) a+]
4406    chan configure $f -translation lf -eofchar {}
4407    chan puts $f xyzzy
4408    chan flush $f
4409    set x [chan tell $f]
4410    chan seek $f -4 cur
4411    set y [chan gets $f]
4412    chan close $f
4413    list $x [viewFile test3] $y
4414} {14 {xyz
4415123
4416xyzzy} zzy}
4417test chan-io-34.13 {Tcl_Tell at start of file} -setup {
4418    file delete $path(test1)
4419} -body {
4420    set f1 [open $path(test1) w]
4421    chan tell $f1
4422} -cleanup {
4423    chan close $f1
4424} -result 0
4425test chan-io-34.14 {Tcl_Tell after seek to end of file} -setup {
4426    file delete $path(test1)
4427} -body {
4428    set f1 [open $path(test1) w]
4429    chan configure $f1 -translation lf -eofchar {}
4430    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4431    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4432    chan close $f1
4433    set f1 [open $path(test1) r]
4434    chan seek $f1 0 end
4435    chan tell $f1
4436} -cleanup {
4437    chan close $f1
4438} -result 54
4439test chan-io-34.15 {Tcl_Tell combined with seeking} -setup {
4440    file delete $path(test1)
4441} -body {
4442    set f1 [open $path(test1) w]
4443    chan configure $f1 -translation lf -eofchar {}
4444    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4445    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
4446    chan close $f1
4447    set f1 [open $path(test1) r]
4448    chan seek $f1 10 start
4449    set c1 [chan tell $f1]
4450    chan seek $f1 10 current
4451    list $c1 [chan tell $f1]
4452} -cleanup {
4453    chan close $f1
4454} -result {10 20}
4455test chan-io-34.16 {Tcl_Tell on pipe: always -1} -constraints stdio -body {
4456    set f1 [openpipe]
4457    chan tell $f1
4458} -cleanup {
4459    chan close $f1
4460} -result -1
4461test chan-io-34.17 {Tcl_Tell on pipe: always -1} stdio {
4462    set f1 [openpipe]
4463    chan puts $f1 {chan puts hello}
4464    chan flush $f1
4465    set c [chan tell $f1]
4466    chan gets $f1
4467    chan close $f1
4468    set c
4469} -1
4470test chan-io-34.18 {Tcl_Tell combined with seeking and reading} -setup {
4471    file delete $path(test2)
4472} -body {
4473    set f [open $path(test2) w]
4474    chan configure $f -translation lf -eofchar {}
4475    chan puts -nonewline $f "line1\nline2\nline3\nline4\nline5\n"
4476    chan close $f
4477    set f [open $path(test2)]
4478    chan configure $f -translation lf
4479    set x [chan tell $f]
4480    chan read $f 3
4481    lappend x [chan tell $f]
4482    chan seek $f 2
4483    lappend x [chan tell $f]
4484    chan seek $f 10 current
4485    lappend x [chan tell $f]
4486    chan seek $f 0 end
4487    lappend x [chan tell $f]
4488} -cleanup {
4489    chan close $f
4490} -result {0 3 2 12 30}
4491test chan-io-34.19 {Tcl_Tell combined with opening in append mode} -body {
4492    set f [open $path(test3) w]
4493    chan configure $f -translation lf -eofchar {}
4494    chan puts $f "abcdefghijklmnopqrstuvwxyz"
4495    chan puts $f "abcdefghijklmnopqrstuvwxyz"
4496    chan close $f
4497    set f [open $path(test3) a]
4498    chan tell $f
4499} -cleanup {
4500    chan close $f
4501} -result 54
4502test chan-io-34.20 {Tcl_Tell combined with writing} -setup {
4503    set l ""
4504} -body {
4505    set f [open $path(test3) w]
4506    chan seek $f 29 start
4507    lappend l [chan tell $f]
4508    chan puts -nonewline $f a
4509    chan seek $f 39 start
4510    lappend l [chan tell $f]
4511    chan puts -nonewline $f a
4512    lappend l [chan tell $f]
4513    chan seek $f 407 end
4514    lappend l [chan tell $f]
4515} -cleanup {
4516    chan close $f
4517} -result {29 39 40 447}
4518test chan-io-34.21 {Tcl_Seek and Tcl_Tell on large files} -setup {
4519    file delete $path(test3)
4520    set l ""
4521} -constraints {largefileSupport} -body {
4522    set f [open $path(test3) w]
4523    chan configure $f -encoding binary
4524    lappend l [chan tell $f]
4525    chan puts -nonewline $f abcdef
4526    lappend l [chan tell $f]
4527    chan flush $f
4528    lappend l [chan tell $f]
4529    # 4GB offset!
4530    chan seek $f 0x100000000
4531    lappend l [chan tell $f]
4532    chan puts -nonewline $f abcdef
4533    lappend l [chan tell $f]
4534    chan close $f
4535    lappend l [file size $path(test3)]
4536    # truncate...
4537    chan close [open $path(test3) w]
4538    lappend l [file size $path(test3)]
4539} -result {0 6 6 4294967296 4294967302 4294967302 0}
4540
4541# Test Tcl_Eof
4542
4543test chan-io-35.1 {Tcl_Eof} -setup {
4544    file delete $path(test1)
4545} -body {
4546    set f [open $path(test1) w]
4547    chan puts $f hello
4548    chan puts $f hello
4549    chan close $f
4550    set f [open $path(test1)]
4551    set x [chan eof $f]
4552    lappend x [chan eof $f]
4553    chan gets $f
4554    lappend x [chan eof $f]
4555    chan gets $f
4556    lappend x [chan eof $f]
4557    chan gets $f
4558    lappend x [chan eof $f]
4559    lappend x [chan eof $f]
4560} -cleanup {
4561    chan close $f
4562} -result {0 0 0 0 1 1}
4563test chan-io-35.2 {Tcl_Eof with pipe} -constraints stdio -setup {
4564    file delete $path(pipe)
4565} -body {
4566    set f1 [open $path(pipe) w]
4567    chan puts $f1 {chan gets stdin}
4568    chan puts $f1 {chan puts hello}
4569    chan close $f1
4570    set f1 [openpipe r+ $path(pipe)]
4571    chan puts $f1 hello
4572    set x [chan eof $f1]
4573    chan flush $f1
4574    lappend x [chan eof $f1]
4575    chan gets $f1
4576    lappend x [chan eof $f1]
4577    chan gets $f1
4578    lappend x [chan eof $f1]
4579} -cleanup {
4580    chan close $f1
4581} -result {0 0 0 1}
4582test chan-io-35.3 {Tcl_Eof with pipe} -constraints stdio -setup {
4583    file delete $path(pipe)
4584} -body {
4585    set f1 [open $path(pipe) w]
4586    chan puts $f1 {chan gets stdin}
4587    chan puts $f1 {chan puts hello}
4588    chan close $f1
4589    set f1 [openpipe r+ $path(pipe)]
4590    chan puts $f1 hello
4591    set x [chan eof $f1]
4592    chan flush $f1
4593    lappend x [chan eof $f1]
4594    chan gets $f1
4595    lappend x [chan eof $f1]
4596    chan gets $f1
4597    lappend x [chan eof $f1]
4598    chan gets $f1
4599    lappend x [chan eof $f1]
4600    chan gets $f1
4601    lappend x [chan eof $f1]
4602} -cleanup {
4603    chan close $f1
4604} -result {0 0 0 1 1 1}
4605test chan-io-35.4 {Tcl_Eof, eof detection on nonblocking file} -setup {
4606    file delete $path(test1)
4607    set l ""
4608} -constraints {nonBlockFiles} -body {
4609    chan close [open $path(test1) w]
4610    set f [open $path(test1) r]
4611    chan configure $f -blocking off
4612    lappend l [chan gets $f]
4613    lappend l [chan eof $f]
4614} -cleanup {
4615    chan close $f
4616} -result {{} 1}
4617test chan-io-35.5 {Tcl_Eof, eof detection on nonblocking pipe} -setup {
4618    file delete $path(pipe)
4619    set l ""
4620} -constraints stdio -body {
4621    set f [open $path(pipe) w]
4622    chan puts $f {
4623	exit
4624    }
4625    chan close $f
4626    set f [openpipe r $path(pipe)]
4627    lappend l [chan gets $f]
4628    lappend l [chan eof $f]
4629} -cleanup {
4630    chan close $f
4631} -result {{} 1}
4632test chan-io-35.6 {Tcl_Eof, eof char, lf write, auto read} -setup {
4633    file delete $path(test1)
4634} -body {
4635    set f [open $path(test1) w]
4636    chan configure $f -translation lf -eofchar \x1a
4637    chan puts $f abc\ndef
4638    chan close $f
4639    set s [file size $path(test1)]
4640    set f [open $path(test1) r]
4641    chan configure $f -translation auto -eofchar \x1a
4642    list $s [string length [chan read $f]] [chan eof $f]
4643} -cleanup {
4644    chan close $f
4645} -result {9 8 1}
4646test chan-io-35.7 {Tcl_Eof, eof char, lf write, lf read} -setup {
4647    file delete $path(test1)
4648} -body {
4649    set f [open $path(test1) w]
4650    chan configure $f -translation lf -eofchar \x1a
4651    chan puts $f abc\ndef
4652    chan close $f
4653    set s [file size $path(test1)]
4654    set f [open $path(test1) r]
4655    chan configure $f -translation lf -eofchar \x1a
4656    list $s [string length [chan read $f]] [chan eof $f]
4657} -cleanup {
4658    chan close $f
4659} -result {9 8 1}
4660test chan-io-35.8 {Tcl_Eof, eof char, cr write, auto read} -setup {
4661    file delete $path(test1)
4662} -body {
4663    set f [open $path(test1) w]
4664    chan configure $f -translation cr -eofchar \x1a
4665    chan puts $f abc\ndef
4666    chan close $f
4667    set s [file size $path(test1)]
4668    set f [open $path(test1) r]
4669    chan configure $f -translation auto -eofchar \x1a
4670    list $s [string length [chan read $f]] [chan eof $f]
4671} -cleanup {
4672    chan close $f
4673} -result {9 8 1}
4674test chan-io-35.9 {Tcl_Eof, eof char, cr write, cr read} -setup {
4675    file delete $path(test1)
4676} -body {
4677    set f [open $path(test1) w]
4678    chan configure $f -translation cr -eofchar \x1a
4679    chan puts $f abc\ndef
4680    chan close $f
4681    set s [file size $path(test1)]
4682    set f [open $path(test1) r]
4683    chan configure $f -translation cr -eofchar \x1a
4684    list $s [string length [chan read $f]] [chan eof $f]
4685} -cleanup {
4686    chan close $f
4687} -result {9 8 1}
4688test chan-io-35.10 {Tcl_Eof, eof char, crlf write, auto read} -setup {
4689    file delete $path(test1)
4690} -body {
4691    set f [open $path(test1) w]
4692    chan configure $f -translation crlf -eofchar \x1a
4693    chan puts $f abc\ndef
4694    chan close $f
4695    set s [file size $path(test1)]
4696    set f [open $path(test1) r]
4697    chan configure $f -translation auto -eofchar \x1a
4698    list $s [string length [chan read $f]] [chan eof $f]
4699} -cleanup {
4700    chan close $f
4701} -result {11 8 1}
4702test chan-io-35.11 {Tcl_Eof, eof char, crlf write, crlf read} -setup {
4703    file delete $path(test1)
4704} -body {
4705    set f [open $path(test1) w]
4706    chan configure $f -translation crlf -eofchar \x1a
4707    chan puts $f abc\ndef
4708    chan close $f
4709    set s [file size $path(test1)]
4710    set f [open $path(test1) r]
4711    chan configure $f -translation crlf -eofchar \x1a
4712    list $s [string length [chan read $f]] [chan eof $f]
4713} -cleanup {
4714    chan close $f
4715} -result {11 8 1}
4716test chan-io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} -setup {
4717    file delete $path(test1)
4718} -body {
4719    set f [open $path(test1) w]
4720    chan configure $f -translation lf -eofchar {}
4721    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
4722    chan close $f
4723    set c [file size $path(test1)]
4724    set f [open $path(test1) r]
4725    chan configure $f -translation auto -eofchar \x1a
4726    list $c [string length [chan read $f]] [chan eof $f]
4727} -cleanup {
4728    chan close $f
4729} -result {17 8 1}
4730test chan-io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} -setup {
4731    file delete $path(test1)
4732} -body {
4733    set f [open $path(test1) w]
4734    chan configure $f -translation lf -eofchar {}
4735    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
4736    chan close $f
4737    set c [file size $path(test1)]
4738    set f [open $path(test1) r]
4739    chan configure $f -translation lf -eofchar \x1a
4740    list $c [string length [chan read $f]] [chan eof $f]
4741} -cleanup {
4742    chan close $f
4743} -result {17 8 1}
4744test chan-io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} -setup {
4745    file delete $path(test1)
4746} -body {
4747    set f [open $path(test1) w]
4748    chan configure $f -translation cr -eofchar {}
4749    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
4750    chan close $f
4751    set c [file size $path(test1)]
4752    set f [open $path(test1) r]
4753    chan configure $f -translation auto -eofchar \x1a
4754    list $c [string length [chan read $f]] [chan eof $f]
4755} -cleanup {
4756    chan close $f
4757} -result {17 8 1}
4758test chan-io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} -setup {
4759    file delete $path(test1)
4760} -body {
4761    set f [open $path(test1) w]
4762    chan configure $f -translation cr -eofchar {}
4763    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
4764    chan close $f
4765    set c [file size $path(test1)]
4766    set f [open $path(test1) r]
4767    chan configure $f -translation cr -eofchar \x1a
4768    list $c [string length [chan read $f]] [chan eof $f]
4769} -cleanup {
4770    chan close $f
4771} -result {17 8 1}
4772test chan-io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} -setup {
4773    file delete $path(test1)
4774} -body {
4775    set f [open $path(test1) w]
4776    chan configure $f -translation crlf -eofchar {}
4777    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
4778    chan close $f
4779    set c [file size $path(test1)]
4780    set f [open $path(test1) r]
4781    chan configure $f -translation auto -eofchar \x1a
4782    list $c [string length [chan read $f]] [chan eof $f]
4783} -cleanup {
4784    chan close $f
4785} -result {21 8 1}
4786test chan-io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} -setup {
4787    file delete $path(test1)
4788} -body {
4789    set f [open $path(test1) w]
4790    chan configure $f -translation crlf -eofchar {}
4791    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
4792    chan close $f
4793    set c [file size $path(test1)]
4794    set f [open $path(test1) r]
4795    chan configure $f -translation crlf -eofchar \x1a
4796    list $c [string length [chan read $f]] [chan eof $f]
4797} -cleanup {
4798    chan close $f
4799} -result {21 8 1}
4800
4801# Test Tcl_InputBlocked
4802
4803test chan-io-36.1 {Tcl_InputBlocked on nonblocking pipe} -setup {
4804    set x ""
4805} -constraints stdio -body {
4806    set f1 [openpipe]
4807    chan puts $f1 {chan puts hello_from_pipe}
4808    chan flush $f1
4809    chan gets $f1
4810    chan configure $f1 -blocking off -buffering full
4811    chan puts $f1 {chan puts hello}
4812    lappend x [chan gets $f1]
4813    lappend x [chan blocked $f1]
4814    chan flush $f1
4815    after 200
4816    lappend x [chan gets $f1]
4817    lappend x [chan blocked $f1]
4818    lappend x [chan gets $f1]
4819    lappend x [chan blocked $f1]
4820} -cleanup {
4821    chan close $f1
4822} -result {{} 1 hello 0 {} 1}
4823test chan-io-36.2 {Tcl_InputBlocked on blocking pipe} -setup {
4824    set x ""
4825} -constraints stdio -body {
4826    set f1 [openpipe]
4827    chan configure $f1 -buffering line
4828    chan puts $f1 {chan puts hello_from_pipe}
4829    lappend x [chan gets $f1]
4830    lappend x [chan blocked $f1]
4831    chan puts $f1 {exit}
4832    lappend x [chan gets $f1]
4833    lappend x [chan blocked $f1]
4834    lappend x [chan eof $f1]
4835} -cleanup {
4836    chan close $f1
4837} -result {hello_from_pipe 0 {} 0 1}
4838test chan-io-36.3 {Tcl_InputBlocked vs files, short read} -setup {
4839    file delete $path(test1)
4840    set l ""
4841} -body {
4842    set f [open $path(test1) w]
4843    chan puts $f abcdefghijklmnop
4844    chan close $f
4845    set f [open $path(test1) r]
4846    lappend l [chan blocked $f]
4847    lappend l [chan read $f 3]
4848    lappend l [chan blocked $f]
4849    lappend l [chan read -nonewline $f]
4850    lappend l [chan blocked $f]
4851    lappend l [chan eof $f]
4852} -cleanup {
4853    chan close $f
4854} -result {0 abc 0 defghijklmnop 0 1}
4855test chan-io-36.4 {Tcl_InputBlocked vs files, event driven read} -setup {
4856    file delete $path(test1)
4857    set l ""
4858    variable x
4859} -constraints {fileevent} -body {
4860    set f [open $path(test1) w]
4861    chan puts $f abcdefghijklmnop
4862    chan close $f
4863    set f [open $path(test1) r]
4864    chan event $f readable [namespace code {
4865	lappend l [chan read $f 3]
4866	if {[chan eof $f]} {lappend l eof; chan close $f; set x done}
4867    }]
4868    vwait [namespace which -variable x]
4869    return $l
4870} -result {abc def ghi jkl mno {p
4871} eof}
4872test chan-io-36.5 {Tcl_InputBlocked vs files, short read, nonblocking} -setup {
4873    file delete $path(test1)
4874    set l ""
4875} -constraints {nonBlockFiles} -body {
4876    set f [open $path(test1) w]
4877    chan puts $f abcdefghijklmnop
4878    chan close $f
4879    set f [open $path(test1) r]
4880    chan configure $f -blocking off
4881    lappend l [chan blocked $f]
4882    lappend l [chan read $f 3]
4883    lappend l [chan blocked $f]
4884    lappend l [chan read -nonewline $f]
4885    lappend l [chan blocked $f]
4886    lappend l [chan eof $f]
4887} -cleanup {
4888    chan close $f
4889} -result {0 abc 0 defghijklmnop 0 1}
4890test chan-io-36.6 {Tcl_InputBlocked vs files, event driven read} -setup {
4891    file delete $path(test1)
4892    set l ""
4893    variable x
4894} -constraints {nonBlockFiles fileevent} -body {
4895    set f [open $path(test1) w]
4896    chan puts $f abcdefghijklmnop
4897    chan close $f
4898    set f [open $path(test1) r]
4899    chan configure $f -blocking off
4900    chan event $f readable [namespace code {
4901	lappend l [chan read $f 3]
4902	if {[chan eof $f]} {lappend l eof; chan close $f; set x done}
4903    }]
4904    vwait [namespace which -variable x]
4905    return $l
4906} -result {abc def ghi jkl mno {p
4907} eof}
4908
4909# Test Tcl_InputBuffered
4910
4911test chan-io-37.1 {Tcl_InputBuffered} -setup {
4912    set l ""
4913} -constraints {testchannel} -body {
4914    set f [open $path(longfile) r]
4915    chan configure $f -buffersize 4096
4916    chan read $f 3
4917    lappend l [testchannel inputbuffered $f]
4918    lappend l [chan tell $f]
4919} -cleanup {
4920    chan close $f
4921} -result {4093 3}
4922test chan-io-37.2 {Tcl_InputBuffered, test input flushing on seek} -setup {
4923    set l ""
4924} -constraints {testchannel} -body {
4925    set f [open $path(longfile) r]
4926    chan configure $f -buffersize 4096
4927    chan read $f 3
4928    lappend l [testchannel inputbuffered $f]
4929    lappend l [chan tell $f]
4930    chan seek $f 0 current
4931    lappend l [testchannel inputbuffered $f]
4932    lappend l [chan tell $f]
4933} -cleanup {
4934    chan close $f
4935} -result {4093 3 0 3}
4936
4937# Test Tcl_SetChannelBufferSize, Tcl_GetChannelBufferSize
4938
4939test chan-io-38.1 {Tcl_GetChannelBufferSize, default buffer size} -body {
4940    set f [open $path(longfile) r]
4941    chan configure $f -buffersize
4942} -cleanup {
4943    chan close $f
4944} -result 4096
4945test chan-io-38.2 {Tcl_SetChannelBufferSize, Tcl_GetChannelBufferSize} -setup {
4946    set l ""
4947} -body {
4948    set f [open $path(longfile) r]
4949    lappend l [chan configure $f -buffersize]
4950    chan configure $f -buffersize 10000
4951    lappend l [chan configure $f -buffersize]
4952    chan configure $f -buffersize 1
4953    lappend l [chan configure $f -buffersize]
4954    chan configure $f -buffersize -1
4955    lappend l [chan configure $f -buffersize]
4956    chan configure $f -buffersize 0
4957    lappend l [chan configure $f -buffersize]
4958    chan configure $f -buffersize 100000
4959    lappend l [chan configure $f -buffersize]
4960    chan configure $f -buffersize 10000000
4961    lappend l [chan configure $f -buffersize]
4962} -cleanup {
4963    chan close $f
4964} -result {4096 10000 1 1 1 100000 1048576}
4965test chan-io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
4966    # This test crashes the interp if Bug #427196 is not fixed
4967    set chan [open [info script] r]
4968    chan configure $chan -buffersize 10
4969    set var [chan read $chan 2]
4970    chan configure $chan -buffersize 32
4971    append var [chan read $chan]
4972    chan close $chan
4973} {}
4974
4975# Test Tcl_SetChannelOption, Tcl_GetChannelOption
4976
4977test chan-io-39.1 {Tcl_GetChannelOption} -setup {
4978    file delete $path(test1)
4979} -body {
4980    set f1 [open $path(test1) w]
4981    chan configure $f1 -blocking
4982} -cleanup {
4983    chan close $f1
4984} -result 1
4985#
4986# Test 17.2 was removed.
4987#
4988test chan-io-39.2 {Tcl_GetChannelOption} -setup {
4989    file delete $path(test1)
4990} -body {
4991    set f1 [open $path(test1) w]
4992    chan configure $f1 -buffering
4993} -cleanup {
4994    chan close $f1
4995} -result full
4996test chan-io-39.3 {Tcl_GetChannelOption} -setup {
4997    file delete $path(test1)
4998} -body {
4999    set f1 [open $path(test1) w]
5000    chan configure $f1 -buffering line
5001    chan configure $f1 -buffering
5002} -cleanup {
5003    chan close $f1
5004} -result line
5005test chan-io-39.4 {Tcl_GetChannelOption, Tcl_SetChannelOption} -setup {
5006    file delete $path(test1)
5007    set l ""
5008} -body {
5009    set f1 [open $path(test1) w]
5010    lappend l [chan configure $f1 -buffering]
5011    chan configure $f1 -buffering line
5012    lappend l [chan configure $f1 -buffering]
5013    chan configure $f1 -buffering none
5014    lappend l [chan configure $f1 -buffering]
5015    chan configure $f1 -buffering line
5016    lappend l [chan configure $f1 -buffering]
5017    chan configure $f1 -buffering full
5018    lappend l [chan configure $f1 -buffering]
5019} -cleanup {
5020    chan close $f1
5021} -result {full line none line full}
5022test chan-io-39.5 {Tcl_GetChannelOption, invariance} -setup {
5023    file delete $path(test1)
5024    set l ""
5025} -body {
5026    set f1 [open $path(test1) w]
5027    lappend l [chan configure $f1 -buffering]
5028    lappend l [list [catch {chan configure $f1 -buffering green} msg] $msg]
5029    lappend l [chan configure $f1 -buffering]
5030} -cleanup {
5031    chan close $f1
5032} -result {full {1 {bad value for -buffering: must be one of full, line, or none}} full}
5033test chan-io-39.6 {Tcl_SetChannelOption, multiple options} -setup {
5034    file delete $path(test1)
5035} -body {
5036    set f1 [open $path(test1) w]
5037    chan configure $f1 -translation lf -buffering line
5038    chan puts $f1 hello
5039    chan puts $f1 bye
5040    file size $path(test1)
5041} -cleanup {
5042    chan close $f1
5043} -result 10
5044test chan-io-39.7 {Tcl_SetChannelOption, buffering, translation} -setup {
5045    file delete $path(test1)
5046    set x ""
5047} -body {
5048    set f1 [open $path(test1) w]
5049    chan configure $f1 -translation lf
5050    chan puts $f1 hello
5051    chan puts $f1 bye
5052    chan configure $f1 -buffering line
5053    lappend x [file size $path(test1)]
5054    chan puts $f1 really_bye
5055    lappend x [file size $path(test1)]
5056} -cleanup {
5057    chan close $f1
5058} -result {0 21}
5059test chan-io-39.8 {Tcl_SetChannelOption, different buffering options} -setup {
5060    file delete $path(test1)
5061    set l ""
5062} -body {
5063    set f1 [open $path(test1) w]
5064    chan configure $f1 -translation lf -buffering none -eofchar {}
5065    chan puts -nonewline $f1 hello
5066    lappend l [file size $path(test1)]
5067    chan puts -nonewline $f1 hello
5068    lappend l [file size $path(test1)]
5069    chan configure $f1 -buffering full
5070    chan puts -nonewline $f1 hello
5071    lappend l [file size $path(test1)]
5072    chan configure $f1 -buffering none
5073    lappend l [file size $path(test1)]
5074    chan puts -nonewline $f1 hello
5075    lappend l [file size $path(test1)]
5076    chan close $f1
5077    lappend l [file size $path(test1)]
5078} -result {5 10 10 10 20 20}
5079test chan-io-39.9 {Tcl_SetChannelOption, blocking mode} -setup {
5080    file delete $path(test1)
5081    set x ""
5082} -constraints {nonBlockFiles} -body {
5083    set f1 [open $path(test1) w]
5084    chan close $f1
5085    set f1 [open $path(test1) r]
5086    lappend x [chan configure $f1 -blocking]
5087    chan configure $f1 -blocking off
5088    lappend x [chan configure $f1 -blocking]
5089    lappend x [chan gets $f1]
5090    lappend x [chan read $f1 1000]
5091    lappend x [chan blocked $f1]
5092    lappend x [chan eof $f1]
5093} -cleanup {
5094    chan close $f1
5095} -result {1 0 {} {} 0 1}
5096test chan-io-39.10 {Tcl_SetChannelOption, blocking mode} -setup {
5097    file delete $path(pipe)
5098    set x ""
5099} -constraints stdio -body {
5100    set f1 [open $path(pipe) w]
5101    chan puts $f1 {
5102	chan gets stdin
5103	after 100
5104	chan puts hi
5105	chan gets stdin
5106    }
5107    chan close $f1
5108    set f1 [openpipe r+ $path(pipe)]
5109    chan configure $f1 -blocking off -buffering line
5110    lappend x [chan configure $f1 -blocking]
5111    lappend x [chan gets $f1]
5112    lappend x [chan blocked $f1]
5113    chan configure $f1 -blocking on
5114    chan puts $f1 hello
5115    chan configure $f1 -blocking off
5116    lappend x [chan gets $f1]
5117    lappend x [chan blocked $f1]
5118    chan configure $f1 -blocking on
5119    chan puts $f1 bye
5120    chan configure $f1 -blocking off
5121    lappend x [chan gets $f1]
5122    lappend x [chan blocked $f1]
5123    chan configure $f1 -blocking on
5124    lappend x [chan configure $f1 -blocking]
5125    lappend x [chan gets $f1]
5126    lappend x [chan blocked $f1]
5127    lappend x [chan eof $f1]
5128    lappend x [chan gets $f1]
5129    lappend x [chan eof $f1]
5130} -cleanup {
5131    chan close $f1
5132} -result {0 {} 1 {} 1 {} 1 1 hi 0 0 {} 1}
5133test chan-io-39.11 {Tcl_SetChannelOption, Tcl_GetChannelOption, buffer size clipped to lower bound} -setup {
5134    file delete $path(test1)
5135} -body {
5136    set f [open $path(test1) w]
5137    chan configure $f -buffersize -10
5138    chan configure $f -buffersize
5139} -cleanup {
5140    chan close $f
5141} -result 1
5142test chan-io-39.12 {Tcl_SetChannelOption, Tcl_GetChannelOption buffer size clipped to upper bound} -setup {
5143    file delete $path(test1)
5144} -body {
5145    set f [open $path(test1) w]
5146    chan configure $f -buffersize 10000000
5147    chan configure $f -buffersize
5148} -cleanup {
5149    chan close $f
5150} -result 1048576
5151test chan-io-39.13 {Tcl_SetChannelOption, Tcl_GetChannelOption, buffer size} -setup {
5152    file delete $path(test1)
5153} -body {
5154    set f [open $path(test1) w]
5155    chan configure $f -buffersize 40000
5156    chan configure $f -buffersize
5157} -cleanup {
5158    chan close $f
5159} -result 40000
5160test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
5161    file delete $path(test1)
5162} -body {
5163    set f [open $path(test1) w]
5164    chan configure $f -encoding {}
5165    chan puts -nonewline $f \xe7\x89\xa6
5166    chan close $f
5167    set f [open $path(test1) r]
5168    chan configure $f -encoding utf-8
5169    chan read $f
5170} -cleanup {
5171    chan close $f
5172} -result \u7266
5173test chan-io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
5174    file delete $path(test1)
5175} -body {
5176    set f [open $path(test1) w]
5177    chan configure $f -encoding binary
5178    chan puts -nonewline $f \xe7\x89\xa6
5179    chan close $f
5180    set f [open $path(test1) r]
5181    chan configure $f -encoding utf-8
5182    chan read $f
5183} -cleanup {
5184    chan close $f
5185} -result \u7266
5186test chan-io-39.16 {Tcl_SetChannelOption: -encoding, errors} -setup {
5187    file delete $path(test1)
5188    set f [open $path(test1) w]
5189} -body {
5190    chan configure $f -encoding foobar
5191} -returnCodes error -cleanup {
5192    chan close $f
5193} -result {unknown encoding "foobar"}
5194test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} -setup {
5195    variable x {}
5196} -constraints {stdio fileevent} -body {
5197    set f [openpipe r+ $path(cat)]
5198    chan configure $f -encoding binary
5199    chan puts -nonewline $f "\xe7"
5200    chan flush $f
5201    chan configure $f -encoding utf-8 -blocking 0
5202    chan event $f readable [namespace code { lappend x [chan read $f] }]
5203    vwait [namespace which -variable x]
5204    after 300 [namespace code { lappend x timeout }]
5205    vwait [namespace which -variable x]
5206    chan configure $f -encoding utf-8
5207    vwait [namespace which -variable x]
5208    after 300 [namespace code { lappend x timeout }]
5209    vwait [namespace which -variable x]
5210    chan configure $f -encoding binary
5211    vwait [namespace which -variable x]
5212    after 300 [namespace code { lappend x timeout }]
5213    vwait [namespace which -variable x]
5214    return $x
5215} -cleanup {
5216    chan close $f
5217} -result "{} timeout {} timeout \xe7 timeout"
5218test chan-io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
5219	-constraints {socket} -body {
5220    proc accept {s a p} {chan close $s}
5221    set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
5222    set port [lindex [chan configure $s1 -sockname] 2]
5223    set s2 [socket 127.0.0.1 $port]
5224    update
5225    chan configure $s2 -translation {auto lf}
5226    chan configure $s2 -translation
5227} -cleanup {
5228    chan close $s1
5229    chan close $s2
5230} -result {auto lf}
5231test chan-io-39.19 {Tcl_SetChannelOption, setting read mode independently} \
5232	-constraints {socket} -body {
5233    proc accept {s a p} {chan close $s}
5234    set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
5235    set port [lindex [chan configure $s1 -sockname] 2]
5236    set s2 [socket 127.0.0.1 $port]
5237    update
5238    chan configure $s2 -translation {auto crlf}
5239    chan configure $s2 -translation
5240} -cleanup {
5241    chan close $s1
5242    chan close $s2
5243} -result {auto crlf}
5244test chan-io-39.20 {Tcl_SetChannelOption, setting read mode independently} \
5245	-constraints {socket} -body {
5246    proc accept {s a p} {chan close $s}
5247    set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
5248    set port [lindex [chan configure $s1 -sockname] 2]
5249    set s2 [socket 127.0.0.1 $port]
5250    update
5251    chan configure $s2 -translation {auto cr}
5252    chan configure $s2 -translation
5253} -cleanup {
5254    chan close $s1
5255    chan close $s2
5256} -result {auto cr}
5257test chan-io-39.21 {Tcl_SetChannelOption, setting read mode independently} \
5258	-constraints {socket} -body {
5259    proc accept {s a p} {chan close $s}
5260    set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
5261    set port [lindex [chan configure $s1 -sockname] 2]
5262    set s2 [socket 127.0.0.1 $port]
5263    update
5264    chan configure $s2 -translation {auto auto}
5265    chan configure $s2 -translation
5266} -cleanup {
5267    chan close $s1
5268    chan close $s2
5269} -result {auto crlf}
5270test chan-io-39.22 {Tcl_SetChannelOption, invariance} -setup {
5271    file delete $path(test1)
5272    set l ""
5273} -constraints {unix} -body {
5274    set f1 [open $path(test1) w+]
5275    lappend l [chan configure $f1 -eofchar]
5276    chan configure $f1 -eofchar {ON GO}
5277    lappend l [chan configure $f1 -eofchar]
5278    chan configure $f1 -eofchar D
5279    lappend l [chan configure $f1 -eofchar]
5280} -cleanup {
5281    chan close $f1
5282} -result {{{} {}} {O G} {D D}}
5283test chan-io-39.22a {Tcl_SetChannelOption, invariance} -setup {
5284    file delete $path(test1)
5285    set l [list]
5286} -body {
5287    set f1 [open $path(test1) w+]
5288    chan configure $f1 -eofchar {ON GO}
5289    lappend l [chan configure $f1 -eofchar]
5290    chan configure $f1 -eofchar D
5291    lappend l [chan configure $f1 -eofchar]
5292    lappend l [list [catch {chan configure $f1 -eofchar {1 2 3}} msg] $msg]
5293} -cleanup {
5294    chan close $f1
5295} -result {{O G} {D D} {1 {bad value for -eofchar: should be a list of zero, one, or two elements}}}
5296test chan-io-39.23 {Tcl_GetChannelOption, server socket is not readable or\
5297        writeable, it should still have valid -eofchar and -translation options} -setup {
5298    set l [list]
5299} -body {
5300    set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
5301    lappend l [chan configure $sock -eofchar] \
5302	[chan configure $sock -translation]
5303} -cleanup {
5304    chan close $sock
5305} -result {{{}} auto}
5306test chan-io-39.24 {Tcl_SetChannelOption, server socket is not readable or\
5307        writable so we can't change -eofchar or -translation} -setup {
5308    set l [list]
5309} -body {
5310    set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
5311    chan configure $sock -eofchar D -translation lf
5312    lappend l [chan configure $sock -eofchar] \
5313	[chan configure $sock -translation]
5314} -cleanup {
5315    chan close $sock
5316} -result {{{}} auto}
5317
5318test chan-io-40.1 {POSIX open access modes: RDWR} -setup {
5319    file delete $path(test3)
5320} -body {
5321    set f [open $path(test3) w]
5322    chan puts $f xyzzy
5323    chan close $f
5324    set f [open $path(test3) RDWR]
5325    chan puts -nonewline $f "ab"
5326    chan seek $f 0 current
5327    set x [chan gets $f]
5328    chan close $f
5329    set f [open $path(test3) r]
5330    lappend x [chan gets $f]
5331} -cleanup {
5332    chan close $f
5333} -result {zzy abzzy}
5334test chan-io-40.2 {POSIX open access modes: CREAT} -setup {
5335    file delete $path(test3)
5336} -constraints {unix} -body {
5337    set f [open $path(test3) {WRONLY CREAT} 0o600]
5338    file stat $path(test3) stats
5339    set x [format 0o%03o [expr {$stats(mode) & 0o777}]]
5340    chan puts $f "line 1"
5341    chan close $f
5342    set f [open $path(test3) r]
5343    lappend x [chan gets $f]
5344} -cleanup {
5345    chan close $f
5346} -result {0o600 {line 1}}
5347test chan-io-40.3 {POSIX open access modes: CREAT} -setup {
5348    file delete $path(test3)
5349} -constraints {unix umask} -body {
5350    # This test only works if your umask is 2, like ouster's.
5351    chan close [open $path(test3) {WRONLY CREAT}]
5352    file stat $path(test3) stats
5353    format "0o%03o" [expr {$stats(mode) & 0o777}]
5354} -result [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
5355test chan-io-40.4 {POSIX open access modes: CREAT} -setup {
5356    file delete $path(test3)
5357} -body {
5358    set f [open $path(test3) w]
5359    chan configure $f -eofchar {}
5360    chan puts $f xyzzy
5361    chan close $f
5362    set f [open $path(test3) {WRONLY CREAT}]
5363    chan configure $f -eofchar {}
5364    chan puts -nonewline $f "ab"
5365    chan close $f
5366    set f [open $path(test3) r]
5367    chan gets $f
5368} -cleanup {
5369    chan close $f
5370} -result abzzy
5371test chan-io-40.5 {POSIX open access modes: APPEND} -setup {
5372    file delete $path(test3)
5373    set x ""
5374} -body {
5375    set f [open $path(test3) w]
5376    chan configure $f -translation lf -eofchar {}
5377    chan puts $f xyzzy
5378    chan close $f
5379    set f [open $path(test3) {WRONLY APPEND}]
5380    chan configure $f -translation lf
5381    chan puts $f "new line"
5382    chan seek $f 0
5383    chan puts $f "abc"
5384    chan close $f
5385    set f [open $path(test3) r]
5386    chan configure $f -translation lf
5387    chan seek $f 6 current
5388    lappend x [chan gets $f]
5389    lappend x [chan gets $f]
5390} -cleanup {
5391    chan close $f
5392} -result {{new line} abc}
5393test chan-io-40.6 {POSIX open access modes: EXCL} -match regexp -setup {
5394    file delete $path(test3)
5395} -body {
5396    set f [open $path(test3) w]
5397    chan puts $f xyzzy
5398    chan close $f
5399    open $path(test3) {WRONLY CREAT EXCL}
5400} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
5401test chan-io-40.7 {POSIX open access modes: EXCL} -setup {
5402    file delete $path(test3)
5403} -body {
5404    set f [open $path(test3) {WRONLY CREAT EXCL}]
5405    chan configure $f -eofchar {}
5406    chan puts $f "A test line"
5407    chan close $f
5408    viewFile test3
5409} -result {A test line}
5410test chan-io-40.8 {POSIX open access modes: TRUNC} -setup {
5411    file delete $path(test3)
5412} -body {
5413    set f [open $path(test3) w]
5414    chan puts $f xyzzy
5415    chan close $f
5416    set f [open $path(test3) {WRONLY TRUNC}]
5417    chan puts $f abc
5418    chan close $f
5419    set f [open $path(test3) r]
5420    chan gets $f
5421} -cleanup {
5422    chan close $f
5423} -result abc
5424test chan-io-40.9 {POSIX open access modes: NONBLOCK} -setup {
5425    file delete $path(test3)
5426} -constraints {nonPortable unix} -body {
5427    set f [open $path(test3) {WRONLY NONBLOCK CREAT}]
5428    chan puts $f "NONBLOCK test"
5429    chan close $f
5430    set f [open $path(test3) r]
5431    chan gets $f
5432} -cleanup {
5433    chan close $f
5434} -result {NONBLOCK test}
5435test chan-io-40.10 {POSIX open access modes: RDONLY} -body {
5436    set f [open $path(test1) w]
5437    chan puts $f "two lines: this one"
5438    chan puts $f "and this"
5439    chan close $f
5440    set f [open $path(test1) RDONLY]
5441    list [chan gets $f] [catch {chan puts $f Test} msg] $msg
5442} -cleanup {
5443    chan close $f
5444} -match glob -result {{two lines: this one} 1 {channel "*" wasn't opened for writing}}
5445test chan-io-40.11 {POSIX open access modes: RDONLY} -match regexp -body {
5446    file delete $path(test3)
5447    open $path(test3) RDONLY
5448} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
5449test chan-io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
5450    file delete $path(test3)
5451    open $path(test3) WRONLY
5452} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
5453test chan-io-40.13 {POSIX open access modes: WRONLY} -body {
5454    makeFile xyzzy test3
5455    set f [open $path(test3) WRONLY]
5456    chan configure $f -eofchar {}
5457    chan puts -nonewline $f "ab"
5458    chan seek $f 0 current
5459    set x [list [catch {chan gets $f} msg] $msg]
5460    chan close $f
5461    lappend x [viewFile test3]
5462} -match glob -result {1 {channel "*" wasn't opened for reading} abzzy}
5463test chan-io-40.14 {POSIX open access modes: RDWR} -match regexp -body {
5464    file delete $path(test3)
5465    open $path(test3) RDWR
5466} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
5467test chan-io-40.15 {POSIX open access modes: RDWR} {
5468    makeFile xyzzy test3
5469    set f [open $path(test3) RDWR]
5470    chan puts -nonewline $f "ab"
5471    chan seek $f 0 current
5472    set x [chan gets $f]
5473    chan close $f
5474    lappend x [viewFile test3]
5475} {zzy abzzy}
5476test chan-io-40.16 {tilde substitution in open} -constraints makeFileInHome -setup {
5477    makeFile {Some text} _test_ ~
5478} -body {
5479    file exists [file join $::env(HOME) _test_]
5480} -cleanup {
5481    removeFile _test_ ~
5482} -result 1
5483test chan-io-40.17 {tilde substitution in open} -setup {
5484    set home $::env(HOME)
5485} -body {
5486    unset ::env(HOME)
5487    open ~/foo
5488} -returnCodes error -cleanup {
5489    set ::env(HOME) $home
5490} -result {couldn't find HOME environment variable to expand path}
5491
5492test chan-io-41.1 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
5493    chan event foo
5494} -returnCodes error -result {wrong # args: should be "chan event channelId event ?script?"}
5495test chan-io-41.2 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
5496    chan event foo bar baz q
5497} -returnCodes error -result {wrong # args: should be "chan event channelId event ?script?"}
5498test chan-io-41.3 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
5499    chan event gorp readable
5500} -returnCodes error -result {can not find channel named "gorp"}
5501test chan-io-41.4 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
5502    chan event gorp writable
5503} -returnCodes error -result {can not find channel named "gorp"}
5504test chan-io-41.5 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
5505    chan event gorp who-knows
5506} -returnCodes error -result {bad event name "who-knows": must be readable or writable}
5507
5508#
5509# Test chan event on a file
5510#
5511
5512set path(foo) [makeFile {} foo]
5513set f [open $path(foo) w+]
5514
5515test chan-io-42.1 {Tcl_FileeventCmd: creating, deleting, querying} {fileevent} {
5516    list [chan event $f readable] [chan event $f writable]
5517} {{} {}}
5518test chan-io-42.2 {Tcl_FileeventCmd: replacing} {fileevent} {
5519    set result {}
5520    chan event $f r "first script"
5521    lappend result [chan event $f readable]
5522    chan event $f r "new script"
5523    lappend result [chan event $f readable]
5524    chan event $f r "yet another"
5525    lappend result [chan event $f readable]
5526    chan event $f r ""
5527    lappend result [chan event $f readable]
5528} {{first script} {new script} {yet another} {}}
5529test chan-io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent} {
5530    set result {}
5531    chan event $f r "first scr\0ipt"
5532    lappend result [string length [chan event $f readable]]
5533    chan event $f r "new scr\0ipt"
5534    lappend result [string length [chan event $f readable]]
5535    chan event $f r "yet ano\0ther"
5536    lappend result [string length [chan event $f readable]]
5537    chan event $f r ""
5538    lappend result [chan event $f readable]
5539} {13 11 12 {}}
5540
5541test chan-io-43.1 {Tcl_FileeventCmd: creating, deleting, querying} {stdio unixExecs fileevent} {
5542    set result {}
5543    chan event $f readable "script 1"
5544    lappend result [chan event $f readable] [chan event $f writable]
5545    chan event $f writable "write script"
5546    lappend result [chan event $f readable] [chan event $f writable]
5547    chan event $f readable {}
5548    lappend result [chan event $f readable] [chan event $f writable]
5549    chan event $f writable {}
5550    lappend result [chan event $f readable] [chan event $f writable]
5551} {{script 1} {} {script 1} {write script} {} {write script} {} {}}
5552test chan-io-43.2 {Tcl_FileeventCmd: deleting when many present} -setup {
5553    set f2 [open "|[list cat -u]" r+]
5554    set f3 [open "|[list cat -u]" r+]
5555    set result {}
5556} -constraints {stdio unixExecs fileevent} -body {
5557    lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
5558    chan event $f r "chan read f"
5559    chan event $f2 r "chan read f2"
5560    chan event $f3 r "chan read f3"
5561    lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
5562    chan event $f2 r {}
5563    lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
5564    chan event $f3 r {}
5565    lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
5566    chan event $f r {}
5567    lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
5568} -cleanup {
5569    catch {chan close $f2}
5570    catch {chan close $f3}
5571} -result {{} {} {} {chan read f} {chan read f2} {chan read f3} {chan read f} {} {chan read f3} {chan read f} {} {} {} {} {}}
5572
5573test chan-io-44.1 {FileEventProc procedure: normal read event} -setup {
5574    set f2 [open "|[list cat -u]" r+]
5575    set f3 [open "|[list cat -u]" r+]
5576} -constraints {stdio unixExecs fileevent} -body {
5577    chan event $f2 readable [namespace code {
5578	set x [chan gets $f2]; chan event $f2 readable {}
5579    }]
5580    chan puts $f2 text; chan flush $f2
5581    variable x initial
5582    vwait [namespace which -variable x]
5583    return $x
5584} -cleanup {
5585    catch {chan close $f2}
5586    catch {chan close $f3}
5587} -result {text}
5588test chan-io-44.2 {FileEventProc procedure: error in read event} -setup {
5589    set f2 [open "|[list cat -u]" r+]
5590    set f3 [open "|[list cat -u]" r+]
5591    proc myHandler {msg options} {
5592	variable x $msg
5593    }
5594    set handler [interp bgerror {}]
5595    interp bgerror {} [namespace which myHandler]
5596} -constraints {stdio unixExecs fileevent} -body {
5597    chan event $f2 readable {error bogus}
5598    chan puts $f2 text; chan flush $f2
5599    variable x initial
5600    vwait [namespace which -variable x]
5601    list $x [chan event $f2 readable]
5602} -cleanup {
5603    interp bgerror {} $handler
5604    catch {chan close $f2}
5605    catch {chan close $f3}
5606} -result {bogus {}}
5607test chan-io-44.3 {FileEventProc procedure: normal write event} -setup {
5608    set f2 [open "|[list cat -u]" r+]
5609    set f3 [open "|[list cat -u]" r+]
5610} -constraints {stdio unixExecs fileevent} -body {
5611    chan event $f2 writable [namespace code {
5612	lappend x "triggered"
5613	incr count -1
5614	if {$count <= 0} {
5615	    chan event $f2 writable {}
5616	}
5617    }]
5618    variable x initial
5619    set count 3
5620    vwait [namespace which -variable x]
5621    vwait [namespace which -variable x]
5622    vwait [namespace which -variable x]
5623    return $x
5624} -cleanup {
5625    catch {chan close $f2}
5626    catch {chan close $f3}
5627} -result {initial triggered triggered triggered}
5628test chan-io-44.4 {FileEventProc procedure: eror in write event} -setup {
5629    set f2 [open "|[list cat -u]" r+]
5630    set f3 [open "|[list cat -u]" r+]
5631    proc myHandler {msg options} {
5632	variable x $msg
5633    }
5634    set handler [interp bgerror {}]
5635    interp bgerror {} [namespace which myHandler]
5636} -constraints {stdio unixExecs fileevent} -body {
5637    chan event $f2 writable {error bad-write}
5638    variable x initial
5639    vwait [namespace which -variable x]
5640    list $x [chan event $f2 writable]
5641} -cleanup {
5642    interp bgerror {} $handler
5643    catch {chan close $f2}
5644    catch {chan close $f3}
5645} -result {bad-write {}}
5646test chan-io-44.5 {FileEventProc procedure: end of file} -constraints {
5647    stdio unixExecs fileevent
5648} -body {
5649    set f4 [openpipe r $path(cat) << foo]
5650    chan event $f4 readable [namespace code {
5651	if {[chan gets $f4 line] < 0} {
5652	    lappend x eof
5653	    chan event $f4 readable {}
5654	} else {
5655	    lappend x $line
5656	}
5657    }]
5658    variable x initial
5659    vwait [namespace which -variable x]
5660    vwait [namespace which -variable x]
5661    set x
5662} -cleanup {
5663    chan close $f4
5664} -result {initial foo eof}
5665
5666chan close $f
5667makeFile "foo bar" foo
5668
5669test chan-io-45.1 {DeleteFileEvent, cleanup on chan close} {fileevent} {
5670    set f [open $path(foo) r]
5671    chan event $f readable [namespace code {
5672	lappend x "binding triggered: \"[chan gets $f]\""
5673	chan event $f readable {}
5674    }]
5675    chan close $f
5676    set x initial
5677    after 100 [namespace code {
5678	set y done
5679    }]
5680    variable y
5681    vwait [namespace which -variable y]
5682    set x
5683} {initial}
5684test chan-io-45.2 {DeleteFileEvent, cleanup on chan close} {fileevent} {
5685    set f  [open $path(foo) r]
5686    set f2 [open $path(foo) r]
5687    chan event $f readable [namespace code {
5688	lappend x "f triggered: \"[chan gets $f]\""
5689	chan event $f readable {}
5690    }]
5691    chan event $f2 readable [namespace code {
5692	lappend x "f2 triggered: \"[chan gets $f2]\""
5693	chan event $f2 readable {}
5694    }]
5695    chan close $f
5696    variable x initial
5697    vwait [namespace which -variable x]
5698    chan close $f2
5699    set x
5700} {initial {f2 triggered: "foo bar"}}
5701test chan-io-45.3 {DeleteFileEvent, cleanup on chan close} {fileevent} {
5702    set f  [open $path(foo) r]
5703    set f2 [open $path(foo) r]
5704    set f3 [open $path(foo) r]
5705    chan event $f readable {f script}
5706    chan event $f2 readable {f2 script}
5707    chan event $f3 readable {f3 script}
5708    set x {}
5709    chan close $f2
5710    lappend x [catch {chan event $f readable} msg] $msg \
5711	    [catch {chan event $f2 readable}] \
5712	    [catch {chan event $f3 readable} msg] $msg
5713    chan close $f3
5714    lappend x [catch {chan event $f readable} msg] $msg \
5715	    [catch {chan event $f2 readable}] \
5716	    [catch {chan event $f3 readable}]
5717    chan close $f
5718    lappend x [catch {chan event $f readable}] \
5719	    [catch {chan event $f2 readable}] \
5720	    [catch {chan event $f3 readable}]
5721} {0 {f script} 1 0 {f3 script} 0 {f script} 1 1 1 1 1}
5722
5723# Execute these tests only if the "testfevent" command is present.
5724
5725test chan-io-46.1 {Tcl event loop vs multiple interpreters} {testfevent fileevent notOSX} {
5726    testfevent create
5727    set script "set f \[[list open $path(foo) r]]\n"
5728    append script {
5729	set x "no event"
5730	chan event $f readable [namespace code {
5731	    set x "f triggered: [chan gets $f]"
5732	    chan event $f readable {}
5733	}]
5734    }
5735    set timer [after 10 lappend x timeout]
5736    testfevent cmd $script
5737    vwait x
5738    after cancel $timer
5739    testfevent cmd {chan close $f}
5740    list [testfevent cmd {set x}] [testfevent cmd {info commands after}]
5741} {{f triggered: foo bar} after}
5742test chan-io-46.2 {Tcl event loop vs multiple interpreters} testfevent {
5743    testfevent create
5744    testfevent cmd {
5745        variable x 0
5746        after 100 {set x triggered}
5747        vwait [namespace which -variable x]
5748        set x
5749    }
5750} {triggered}
5751test chan-io-46.3 {Tcl event loop vs multiple interpreters} testfevent {
5752    testfevent create
5753    testfevent cmd {
5754        set x 0
5755        after 10 {lappend x timer}
5756        after 30
5757        set result $x
5758        update idletasks
5759        lappend result $x
5760        update
5761        lappend result $x
5762    }
5763} {0 0 {0 timer}}
5764
5765test chan-io-47.1 {chan event vs multiple interpreters} -setup {
5766    set f  [open $path(foo) r]
5767    set f2 [open $path(foo) r]
5768    set f3 [open $path(foo) r]
5769    set x {}
5770} -constraints {testfevent fileevent} -body {
5771    chan event $f readable {script 1}
5772    testfevent create
5773    testfevent share $f2
5774    testfevent cmd "chan event $f2 readable {script 2}"
5775    chan event $f3 readable {sript 3}
5776    lappend x [chan event $f2 readable]
5777    testfevent delete
5778    lappend x [chan event $f readable] [chan event $f2 readable] \
5779        [chan event $f3 readable]
5780} -cleanup {
5781    chan close $f
5782    chan close $f2
5783    chan close $f3
5784} -result {{} {script 1} {} {sript 3}}
5785test chan-io-47.2 {deleting chan event on interpreter delete} -setup {
5786    set f  [open $path(foo) r]
5787    set f2 [open $path(foo) r]
5788    set f3 [open $path(foo) r]
5789    set f4 [open $path(foo) r]
5790} -constraints {testfevent fileevent} -body {
5791    chan event $f readable {script 1}
5792    testfevent create
5793    testfevent share $f2
5794    testfevent share $f3
5795    testfevent cmd "chan event $f2 readable {script 2}
5796        chan event $f3 readable {script 3}"
5797    chan event $f4 readable {script 4}
5798    testfevent delete
5799    list [chan event $f readable] [chan event $f2 readable] \
5800	[chan event $f3 readable] [chan event $f4 readable]
5801} -cleanup {
5802    chan close $f
5803    chan close $f2
5804    chan close $f3
5805    chan close $f4
5806} -result {{script 1} {} {} {script 4}}
5807test chan-io-47.3 {deleting chan event on interpreter delete} -setup {
5808    set f  [open $path(foo) r]
5809    set f2 [open $path(foo) r]
5810    set f3 [open $path(foo) r]
5811    set f4 [open $path(foo) r]
5812} -constraints {testfevent fileevent} -body {
5813    testfevent create
5814    testfevent share $f3
5815    testfevent share $f4
5816    chan event $f readable {script 1}
5817    chan event $f2 readable {script 2}
5818    testfevent cmd "chan event $f3 readable {script 3}
5819      chan event $f4 readable {script 4}"
5820    testfevent delete
5821    list [chan event $f readable] [chan event $f2 readable] \
5822	[chan event $f3 readable] [chan event $f4 readable]
5823} -cleanup {
5824    chan close $f
5825    chan close $f2
5826    chan close $f3
5827    chan close $f4
5828} -result {{script 1} {script 2} {} {}}
5829test chan-io-47.4 {file events on shared files and multiple interpreters} -setup {
5830    set f  [open $path(foo) r]
5831    set f2 [open $path(foo) r]
5832} -constraints {testfevent fileevent} -body {
5833    testfevent create
5834    testfevent share $f
5835    testfevent cmd "chan event $f readable {script 1}"
5836    chan event $f readable {script 2}
5837    chan event $f2 readable {script 3}
5838    list [chan event $f2 readable] [testfevent cmd "chan event $f readable"] \
5839	[chan event $f readable]
5840} -cleanup {
5841    testfevent delete
5842    chan close $f
5843    chan close $f2
5844} -result {{script 3} {script 1} {script 2}}
5845test chan-io-47.5 {file events on shared files, deleting file events} -setup {
5846    set f [open $path(foo) r]
5847} -body {
5848    testfevent create
5849    testfevent share $f
5850    testfevent cmd "chan event $f readable {script 1}"
5851    chan event $f readable {script 2}
5852    testfevent cmd "chan event $f readable {}"
5853    list [testfevent cmd "chan event $f readable"] [chan event $f readable]
5854} -constraints {testfevent fileevent} -cleanup {
5855    testfevent delete
5856    chan close $f
5857} -result {{} {script 2}}
5858test chan-io-47.6 {file events on shared files, deleting file events} -setup {
5859    set f [open $path(foo) r]
5860} -body {
5861    testfevent create
5862    testfevent share $f
5863    testfevent cmd "chan event $f readable {script 1}"
5864    chan event $f readable {script 2}
5865    chan event $f readable {}
5866    list [testfevent cmd "chan event $f readable"] [chan event $f readable]
5867} -constraints {testfevent fileevent} -cleanup {
5868    testfevent delete
5869    chan close $f
5870} -result {{script 1} {}}
5871unset path(foo)
5872removeFile foo
5873
5874set path(bar) [makeFile {} bar]
5875
5876test chan-io-48.1 {testing readability conditions} {fileevent} {
5877    set f [open $path(bar) w]
5878    chan puts $f abcdefg
5879    chan puts $f abcdefg
5880    chan puts $f abcdefg
5881    chan puts $f abcdefg
5882    chan puts $f abcdefg
5883    chan close $f
5884    set f [open $path(bar) r]
5885    chan event $f readable [namespace code {
5886	lappend l called
5887	if {[chan eof $f]} {
5888	    chan close $f
5889	    set x done
5890	} else {
5891	    chan gets $f
5892	}
5893    }]
5894    set l ""
5895    variable x not_done
5896    vwait [namespace which -variable x]
5897    list $x $l
5898} {done {called called called called called called called}}
5899test chan-io-48.2 {testing readability conditions} {nonBlockFiles fileevent} {
5900    set f [open $path(bar) w]
5901    chan puts $f abcdefg
5902    chan puts $f abcdefg
5903    chan puts $f abcdefg
5904    chan puts $f abcdefg
5905    chan puts $f abcdefg
5906    chan close $f
5907    set f [open $path(bar) r]
5908    chan event $f readable [namespace code {
5909	lappend l called
5910	if {[chan eof $f]} {
5911	    chan close $f
5912	    set x done
5913	} else {
5914	    chan gets $f
5915	}
5916    }]
5917    chan configure $f -blocking off
5918    set l ""
5919    variable x not_done
5920    vwait [namespace which -variable x]
5921    list $x $l
5922} {done {called called called called called called called}}
5923set path(my_script) [makeFile {} my_script]
5924test chan-io-48.3 {testing readability conditions} -setup {
5925    set l ""
5926} -constraints {stdio unix nonBlockFiles fileevent} -body {
5927    set f [open $path(bar) w]
5928    chan puts $f abcdefg
5929    chan puts $f abcdefg
5930    chan puts $f abcdefg
5931    chan puts $f abcdefg
5932    chan puts $f abcdefg
5933    chan close $f
5934    set f [open $path(my_script) w]
5935    chan puts $f {
5936	proc copy_slowly {f} {
5937	    while {![chan eof $f]} {
5938		chan puts [chan gets $f]
5939		after 200
5940	    }
5941	    chan close $f
5942	}
5943    }
5944    chan close $f
5945    set f [openpipe]
5946    chan event $f readable [namespace code {
5947	if {[chan eof $f]} {
5948	    set x done
5949	} else {
5950	    chan gets $f
5951	    lappend l [chan blocked $f]
5952	    chan gets $f
5953	    lappend l [chan blocked $f]
5954	}
5955    }]
5956    chan configure $f -buffering line
5957    chan configure $f -blocking off
5958    variable x not_done
5959    chan puts $f [list source $path(my_script)]
5960    chan puts $f "set f \[[list open $path(bar) r]]"
5961    chan puts $f {copy_slowly $f}
5962    chan puts $f {exit}
5963    vwait [namespace which -variable x]
5964    list $x $l
5965} -cleanup {
5966    chan close $f
5967} -result {done {0 1 0 1 0 1 0 1 0 1 0 1 0 0}}
5968unset path(bar)
5969removeFile bar
5970
5971test chan-io-48.4 {lf write, testing readability, ^Z termination, auto read mode} -setup {
5972    file delete $path(test1)
5973    set c 0
5974    set l ""
5975} -constraints {fileevent} -body {
5976    set f [open $path(test1) w]
5977    chan configure $f -translation lf
5978    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
5979    chan close $f
5980    set f [open $path(test1) r]
5981    chan configure $f -translation auto -eofchar \x1a
5982    chan event $f readable [namespace code {
5983	if {[chan eof $f]} {
5984	   set x done
5985	   chan close $f
5986	} else {
5987	   lappend l [chan gets $f]
5988	   incr c
5989	}
5990    }]
5991    variable x
5992    vwait [namespace which -variable x]
5993    list $c $l
5994} -result {3 {abc def {}}}
5995test chan-io-48.5 {lf write, testing readability, ^Z in middle, auto read mode} -setup {
5996    file delete $path(test1)
5997    set c 0
5998    set l ""
5999} -constraints {fileevent} -body {
6000    set f [open $path(test1) w]
6001    chan configure $f -translation lf
6002    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
6003    chan close $f
6004    set f [open $path(test1) r]
6005    chan configure $f -eofchar \x1a -translation auto
6006    chan event $f readable [namespace code {
6007	if {[chan eof $f]} {
6008	   set x done
6009	   chan close $f
6010	} else {
6011	   lappend l [chan gets $f]
6012	   incr c
6013	}
6014    }]
6015    variable x
6016    vwait [namespace which -variable x]
6017    list $c $l
6018} -result {3 {abc def {}}}
6019test chan-io-48.6 {cr write, testing readability, ^Z termination, auto read mode} -setup {
6020    file delete $path(test1)
6021    set c 0
6022    set l ""
6023} -constraints {fileevent} -body {
6024    set f [open $path(test1) w]
6025    chan configure $f -translation cr
6026    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
6027    chan close $f
6028    set f [open $path(test1) r]
6029    chan configure $f -translation auto -eofchar \x1a
6030    chan event $f readable [namespace code {
6031	if {[chan eof $f]} {
6032	   set x done
6033	   chan close $f
6034	} else {
6035	   lappend l [chan gets $f]
6036	   incr c
6037	}
6038    }]
6039    variable x
6040    vwait [namespace which -variable x]
6041    list $c $l
6042} -result {3 {abc def {}}}
6043test chan-io-48.7 {cr write, testing readability, ^Z in middle, auto read mode} -setup {
6044    file delete $path(test1)
6045    set c 0
6046    set l ""
6047} -constraints {fileevent} -body {
6048    set f [open $path(test1) w]
6049    chan configure $f -translation cr
6050    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
6051    chan close $f
6052    set f [open $path(test1) r]
6053    chan configure $f -eofchar \x1a -translation auto
6054    chan event $f readable [namespace code {
6055	if {[chan eof $f]} {
6056	   set x done
6057	   chan close $f
6058	} else {
6059	   lappend l [chan gets $f]
6060	   incr c
6061	}
6062    }]
6063    variable x
6064    vwait [namespace which -variable x]
6065    list $c $l
6066} -result {3 {abc def {}}}
6067test chan-io-48.8 {crlf write, testing readability, ^Z termination, auto read mode} -setup {
6068    file delete $path(test1)
6069    set c 0
6070    set l ""
6071} -constraints {fileevent} -body {
6072    set f [open $path(test1) w]
6073    chan configure $f -translation crlf
6074    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
6075    chan close $f
6076    set f [open $path(test1) r]
6077    chan configure $f -translation auto -eofchar \x1a
6078    chan event $f readable [namespace code {
6079	if {[chan eof $f]} {
6080	   set x done
6081	   chan close $f
6082	} else {
6083	   lappend l [chan gets $f]
6084	   incr c
6085	}
6086    }]
6087    variable x
6088    vwait [namespace which -variable x]
6089    list $c $l
6090} -result {3 {abc def {}}}
6091test chan-io-48.9 {crlf write, testing readability, ^Z in middle, auto read mode} -setup {
6092    file delete $path(test1)
6093    set c 0
6094    set l ""
6095} -constraints {fileevent} -body {
6096    set f [open $path(test1) w]
6097    chan configure $f -translation crlf
6098    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
6099    chan close $f
6100    set f [open $path(test1) r]
6101    chan configure $f -eofchar \x1a -translation auto
6102    chan event $f readable [namespace code {
6103	if {[chan eof $f]} {
6104	   set x done
6105	   chan close $f
6106	} else {
6107	   lappend l [chan gets $f]
6108	   incr c
6109	}
6110    }]
6111    variable x
6112    vwait [namespace which -variable x]
6113    list $c $l
6114} -result {3 {abc def {}}}
6115test chan-io-48.10 {lf write, testing readability, ^Z in middle, lf read mode} -setup {
6116    file delete $path(test1)
6117    set c 0
6118    set l ""
6119} -constraints {fileevent} -body {
6120    set f [open $path(test1) w]
6121    chan configure $f -translation lf
6122    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
6123    chan close $f
6124    set f [open $path(test1) r]
6125    chan configure $f -eofchar \x1a -translation lf
6126    chan event $f readable [namespace code {
6127	if {[chan eof $f]} {
6128	   set x done
6129	   chan close $f
6130	} else {
6131	   lappend l [chan gets $f]
6132	   incr c
6133	}
6134    }]
6135    variable x
6136    vwait [namespace which -variable x]
6137    list $c $l
6138} -result {3 {abc def {}}}
6139test chan-io-48.11 {lf write, testing readability, ^Z termination, lf read mode} -setup {
6140    file delete $path(test1)
6141    set c 0
6142    set l ""
6143} -constraints {fileevent} -body {
6144    set f [open $path(test1) w]
6145    chan configure $f -translation lf
6146    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
6147    chan close $f
6148    set f [open $path(test1) r]
6149    chan configure $f -translation lf -eofchar \x1a
6150    chan event $f readable [namespace code {
6151	if {[chan eof $f]} {
6152	   set x done
6153	   chan close $f
6154	} else {
6155	   lappend l [chan gets $f]
6156	   incr c
6157	}
6158    }]
6159    variable x
6160    vwait [namespace which -variable x]
6161    list $c $l
6162} -result {3 {abc def {}}}
6163test chan-io-48.12 {cr write, testing readability, ^Z in middle, cr read mode} -setup {
6164    file delete $path(test1)
6165    set c 0
6166    set l ""
6167} -constraints {fileevent} -body {
6168    set f [open $path(test1) w]
6169    chan configure $f -translation cr
6170    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
6171    chan close $f
6172    set f [open $path(test1) r]
6173    chan configure $f -eofchar \x1a -translation cr
6174    chan event $f readable [namespace code {
6175	if {[chan eof $f]} {
6176	   set x done
6177	   chan close $f
6178	} else {
6179	   lappend l [chan gets $f]
6180	   incr c
6181	}
6182    }]
6183    variable x
6184    vwait [namespace which -variable x]
6185    list $c $l
6186} -result {3 {abc def {}}}
6187test chan-io-48.13 {cr write, testing readability, ^Z termination, cr read mode} -setup {
6188    file delete $path(test1)
6189    set c 0
6190    set l ""
6191} -constraints {fileevent} -body {
6192    set f [open $path(test1) w]
6193    chan configure $f -translation cr
6194    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
6195    chan close $f
6196    set f [open $path(test1) r]
6197    chan configure $f -translation cr -eofchar \x1a
6198    chan event $f readable [namespace code {
6199	if {[chan eof $f]} {
6200	   set x done
6201	   chan close $f
6202	} else {
6203	   lappend l [chan gets $f]
6204	   incr c
6205	}
6206    }]
6207    variable x
6208    vwait [namespace which -variable x]
6209    list $c $l
6210} -result {3 {abc def {}}}
6211test chan-io-48.14 {crlf write, testing readability, ^Z in middle, crlf read mode} -setup {
6212    file delete $path(test1)
6213    set c 0
6214    set l ""
6215} -constraints {fileevent} -body {
6216    set f [open $path(test1) w]
6217    chan configure $f -translation crlf
6218    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
6219    chan close $f
6220    set f [open $path(test1) r]
6221    chan configure $f -eofchar \x1a -translation crlf
6222    chan event $f readable [namespace code {
6223	if {[chan eof $f]} {
6224	   set x done
6225	   chan close $f
6226	} else {
6227	   lappend l [chan gets $f]
6228	   incr c
6229	}
6230    }]
6231    variable x
6232    vwait [namespace which -variable x]
6233    list $c $l
6234} -result {3 {abc def {}}}
6235test chan-io-48.15 {crlf write, testing readability, ^Z termi, crlf read mode} -setup {
6236    file delete $path(test1)
6237    set c 0
6238    set l ""
6239} -constraints {fileevent} -body {
6240    set f [open $path(test1) w]
6241    chan configure $f -translation crlf
6242    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
6243    chan close $f
6244    set f [open $path(test1) r]
6245    chan configure $f -translation crlf -eofchar \x1a
6246    chan event $f readable [namespace code {
6247	if {[chan eof $f]} {
6248	   set x done
6249	   chan close $f
6250	} else {
6251	   lappend l [chan gets $f]
6252	   incr c
6253	}
6254    }]
6255    variable x
6256    vwait [namespace which -variable x]
6257    list $c $l
6258} -result {3 {abc def {}}}
6259
6260test chan-io-49.1 {testing crlf reading, leftover cr disgorgment} -setup {
6261    file delete $path(test1)
6262    set l ""
6263} -body {
6264    set f [open $path(test1) w]
6265    chan configure $f -translation lf
6266    chan puts -nonewline $f "a\rb\rc\r\n"
6267    chan close $f
6268    set f [open $path(test1) r]
6269    lappend l [file size $path(test1)]
6270    chan configure $f -translation crlf
6271    lappend l [chan read $f 1]
6272    lappend l [chan tell $f]
6273    lappend l [chan read $f 1]
6274    lappend l [chan tell $f]
6275    lappend l [chan read $f 1]
6276    lappend l [chan tell $f]
6277    lappend l [chan read $f 1]
6278    lappend l [chan tell $f]
6279    lappend l [chan read $f 1]
6280    lappend l [chan tell $f]
6281    lappend l [chan read $f 1]
6282    lappend l [chan tell $f]
6283    lappend l [chan eof $f]
6284    lappend l [chan read $f 1]
6285    lappend l [chan eof $f]
6286} -cleanup {
6287    chan close $f
6288} -result "7 a 1 [list \r] 2 b 3 [list \r] 4 c 5 {
6289} 7 0 {} 1"
6290test chan-io-49.2 {testing crlf reading, leftover cr disgorgment} -setup {
6291    file delete $path(test1)
6292    set l ""
6293} -body {
6294    set f [open $path(test1) w]
6295    chan configure $f -translation lf
6296    chan puts -nonewline $f "a\rb\rc\r\n"
6297    chan close $f
6298    set f [open $path(test1) r]
6299    lappend l [file size $path(test1)]
6300    chan configure $f -translation crlf
6301    lappend l [chan read $f 2]
6302    lappend l [chan tell $f]
6303    lappend l [chan read $f 2]
6304    lappend l [chan tell $f]
6305    lappend l [chan read $f 2]
6306    lappend l [chan tell $f]
6307    lappend l [chan eof $f]
6308    lappend l [chan read $f 2]
6309    lappend l [chan tell $f]
6310    lappend l [chan eof $f]
6311} -cleanup {
6312    chan close $f
6313} -result "7 [list a\r] 2 [list b\r] 4 [list c\n] 7 0 {} 7 1"
6314test chan-io-49.3 {testing crlf reading, leftover cr disgorgment} -setup {
6315    file delete $path(test1)
6316    set l ""
6317} -body {
6318    set f [open $path(test1) w]
6319    chan configure $f -translation lf
6320    chan puts -nonewline $f "a\rb\rc\r\n"
6321    chan close $f
6322    set f [open $path(test1) r]
6323    lappend l [file size $path(test1)]
6324    chan configure $f -translation crlf
6325    lappend l [chan read $f 3]
6326    lappend l [chan tell $f]
6327    lappend l [chan read $f 3]
6328    lappend l [chan tell $f]
6329    lappend l [chan eof $f]
6330    lappend l [chan read $f 3]
6331    lappend l [chan tell $f]
6332    lappend l [chan eof $f]
6333} -cleanup {
6334    chan close $f
6335} -result "7 [list a\rb] 3 [list \rc\n] 7 0 {} 7 1"
6336test chan-io-49.4 {testing crlf reading, leftover cr disgorgment} -setup {
6337    file delete $path(test1)
6338    set l ""
6339} -body {
6340    set f [open $path(test1) w]
6341    chan configure $f -translation lf
6342    chan puts -nonewline $f "a\rb\rc\r\n"
6343    chan close $f
6344    set f [open $path(test1) r]
6345    lappend l [file size $path(test1)]
6346    chan configure $f -translation crlf
6347    lappend l [chan read $f 3]
6348    lappend l [chan tell $f]
6349    lappend l [chan gets $f]
6350    lappend l [chan tell $f]
6351    lappend l [chan eof $f]
6352    lappend l [chan gets $f]
6353    lappend l [chan tell $f]
6354    lappend l [chan eof $f]
6355} -cleanup {
6356    chan close $f
6357} -result "7 [list a\rb] 3 [list \rc] 7 0 {} 7 1"
6358test chan-io-49.5 {testing crlf reading, leftover cr disgorgment} -setup {
6359    file delete $path(test1)
6360    set l ""
6361} -body {
6362    set f [open $path(test1) w]
6363    chan configure $f -translation lf
6364    chan puts -nonewline $f "a\rb\rc\r\n"
6365    chan close $f
6366    set f [open $path(test1) r]
6367    lappend l [file size $path(test1)]
6368    chan configure $f -translation crlf
6369    lappend l [set x [chan gets $f]]
6370    lappend l [chan tell $f]
6371    lappend l [chan gets $f]
6372    lappend l [chan tell $f]
6373    lappend l [chan eof $f]
6374} -cleanup {
6375    chan close $f
6376} -result [list 7 a\rb\rc 7 {} 7 1]
6377
6378test chan-io-50.1 {testing handler deletion} -setup {
6379    file delete $path(test1)
6380} -constraints testchannelevent -body {
6381    set f [open $path(test1) w]
6382    chan close $f
6383    set f [open $path(test1) r]
6384    variable z not_called
6385    set timer [after 50 lappend z timeout]
6386    testservicemode 0
6387    testchannelevent $f add readable [namespace code {
6388	variable z called
6389	testchannelevent $f delete 0
6390    }]
6391    testservicemode 1
6392    vwait z
6393    after cancel $timer
6394    set z
6395} -cleanup {
6396    chan close $f
6397} -result called
6398test chan-io-50.2 {testing handler deletion with multiple handlers} -setup {
6399    file delete $path(test1)
6400    chan close [open $path(test1) w]
6401    set z ""
6402} -constraints {testchannelevent testservicemode} -body {
6403    proc delhandler {f i} {
6404	variable z
6405	lappend z "called delhandler $f $i"
6406	testchannelevent $f delete 0
6407    }
6408    set z ""
6409    set timer [after 50 lappend z timeout]
6410    testservicemode 0
6411    set f [open $path(test1) r]
6412    testchannelevent $f add readable [namespace code [list delhandler $f 1]]
6413    testchannelevent $f add readable [namespace code [list delhandler $f 0]]
6414    testservicemode 1
6415    vwait z
6416    after cancel $timer
6417    string equal $z \
6418	[list [list called delhandler $f 0] [list called delhandler $f 1]]
6419} -cleanup {
6420    chan close $f
6421} -result 1
6422test chan-io-50.3 {testing handler deletion with multiple handlers} -setup {
6423    file delete $path(test1)
6424    chan close [open $path(test1) w]
6425} -constraints {testchannelevent testservicemode} -body {
6426    proc notcalled {f i} {
6427	variable z
6428	lappend z "notcalled was called!! $f $i"
6429    }
6430    proc delhandler {f i} {
6431	variable z
6432	testchannelevent $f delete 1
6433	lappend z "delhandler $f $i called"
6434	testchannelevent $f delete 0
6435	lappend z "delhandler $f $i deleted myself"
6436    }
6437    set z ""
6438    set timer [after 50 lappend z timeout]
6439    testservicemode 0
6440    set f [open $path(test1) r]
6441    testchannelevent $f add readable [namespace code [list notcalled $f 1]]
6442    testchannelevent $f add readable [namespace code [list delhandler $f 0]]
6443    testservicemode 1
6444    vwait z
6445    after cancel $timer
6446    string equal $z \
6447	[list [list delhandler $f 0 called] \
6448	      [list delhandler $f 0 deleted myself]]
6449} -cleanup {
6450    chan close $f
6451} -result 1
6452test chan-io-50.4 {testing handler deletion vs reentrant calls} -setup {
6453    file delete $path(test1)
6454    set f [open $path(test1) w]
6455    chan close $f
6456} -constraints testchannelevent -body {
6457    set f [open $path(test1) r]
6458    testchannelevent $f add readable [namespace code {
6459	if {$u eq "recursive"} {
6460	    testchannelevent $f delete 0
6461	    lappend z "delrecursive deleting recursive"
6462	} else {
6463	    lappend z "delrecursive calling recursive"
6464	    set u recursive
6465	    update
6466	}
6467    }]
6468    variable u toplevel
6469    variable z ""
6470    set timer [after 50 lappend z timeout]
6471    vwait z
6472    after cancel $timer
6473    set z
6474} -cleanup {
6475    chan close $f
6476    update
6477} -result {{delrecursive calling recursive} {delrecursive deleting recursive}}
6478test chan-io-50.5 {testing handler deletion vs reentrant calls} -setup {
6479    file delete $path(test1)
6480    set f [open $path(test1) w]
6481    chan close $f
6482    update
6483} -constraints {testchannelevent testservicemode notOSX} -body {
6484    proc notcalled {f} {
6485	variable z
6486	lappend z "notcalled was called!! $f"
6487    }
6488    proc del {f} {
6489	variable u
6490	variable z
6491	if {$u eq "recursive"} {
6492	    testchannelevent $f delete 1
6493	    testchannelevent $f delete 0
6494	    lappend z "del deleted notcalled"
6495	    lappend z "del deleted myself"
6496	} else {
6497	    set u recursive
6498	    lappend z "del calling recursive"
6499	    set timer [after 50 lappend z timeout]
6500	    set mode [testservicemode 1]
6501	    vwait z
6502	    after cancel $timer
6503	    testservicemode $mode
6504	    lappend z "del after update"
6505	}
6506    }
6507    set z ""
6508    set u toplevel
6509    set timer [after 50 lappend z timeout]
6510    testservicemode 0
6511    set f [open $path(test1) r]
6512    testchannelevent $f add readable [namespace code [list notcalled $f]]
6513    testchannelevent $f add readable [namespace code [list del $f]]
6514    testservicemode 1
6515    vwait z
6516    after cancel $timer
6517    set z
6518} -cleanup {
6519    chan close $f
6520    update
6521} -result [list {del calling recursive} {del deleted notcalled} \
6522	       {del deleted myself} {del after update}]
6523test chan-io-50.6 {testing handler deletion vs reentrant calls} -setup {
6524    file delete $path(test1)
6525    set f [open $path(test1) w]
6526    chan close $f
6527} -constraints {testchannelevent testservicemode} -body {
6528    proc first {f} {
6529	variable u
6530	variable z
6531	if {$u eq "toplevel"} {
6532	    lappend z "first called"
6533	    set mode [testservicemode 1]
6534	    set timer [after 50 lappend z timeout]
6535	    set u first
6536	    vwait z
6537	    after cancel $timer
6538	    testservicemode $mode
6539	    lappend z "first after update"
6540	} else {
6541	    lappend z "first called not toplevel"
6542	}
6543    }
6544    proc second {f} {
6545	variable u
6546	variable z
6547	if {$u eq "first"} {
6548	    lappend z "second called, first time"
6549	    set u second
6550	    testchannelevent $f delete 0
6551	} elseif {$u eq "second"} {
6552	    lappend z "second called, second time"
6553	    testchannelevent $f delete 0
6554	} else {
6555	    lappend z "second called, cannot happen!"
6556	    testchannelevent $f removeall
6557	}
6558    }
6559    set z ""
6560    set u toplevel
6561    set timer [after 50 lappend z timeout]
6562    testservicemode 0
6563    set f [open $path(test1) r]
6564    testchannelevent $f add readable [namespace code [list second $f]]
6565    testchannelevent $f add readable [namespace code [list first $f]]
6566    testservicemode 1
6567    vwait z
6568    after cancel $timer
6569    set z
6570} -cleanup {
6571    chan close $f
6572} -result [list {first called} {first called not toplevel} \
6573	       {second called, first time} {second called, second time} \
6574	       {first after update}]
6575
6576test chan-io-51.1 {Test old socket deletion on Macintosh} -setup {
6577    set x 0
6578    set result ""
6579    variable wait ""
6580} -constraints {socket} -body {
6581    proc accept {s a p} {
6582	variable x
6583	chan configure $s -blocking off
6584	chan puts $s "sock[incr x]"
6585	chan close $s
6586	variable wait done
6587    }
6588    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
6589    set port [lindex [chan configure $ss -sockname] 2]
6590    set cs [socket 127.0.0.1 $port]
6591    vwait [namespace which -variable wait]
6592    lappend result [chan gets $cs]
6593    chan close $cs
6594    set cs [socket 127.0.0.1 $port]
6595    vwait [namespace which -variable wait]
6596    lappend result [chan gets $cs]
6597    chan close $cs
6598    set cs [socket 127.0.0.1 $port]
6599    vwait [namespace which -variable wait]
6600    lappend result [chan gets $cs]
6601    chan close $cs
6602    set cs [socket 127.0.0.1 $port]
6603    vwait [namespace which -variable wait]
6604    lappend result [chan gets $cs]
6605} -cleanup {
6606    chan close $cs
6607    chan close $ss
6608} -result {sock1 sock2 sock3 sock4}
6609
6610test chan-io-52.1 {TclCopyChannel} -constraints {fcopy} -setup {
6611    file delete $path(test1)
6612} -body {
6613    set f1 [open $thisScript]
6614    set f2 [open $path(test1) w]
6615    chan copy $f1 $f2 -command " # "
6616    chan copy $f1 $f2
6617} -returnCodes error -cleanup {
6618    chan close $f1
6619    chan close $f2
6620} -match glob -result {channel "*" is busy}
6621test chan-io-52.2 {TclCopyChannel} -constraints {fcopy} -setup {
6622    file delete $path(test1)
6623} -body {
6624    set f1 [open $thisScript]
6625    set f2 [open $path(test1) w]
6626    set f3 [open $thisScript]
6627    chan copy $f1 $f2 -command " # "
6628    chan copy $f3 $f2
6629} -returnCodes error -cleanup {
6630    chan close $f1
6631    chan close $f2
6632    chan close $f3
6633} -match glob -result {channel "*" is busy}
6634test chan-io-52.3 {TclCopyChannel} -constraints {fcopy} -setup {
6635    file delete $path(test1)
6636} -body {
6637    set f1 [open $thisScript]
6638    set f2 [open $path(test1) w]
6639    chan configure $f1 -translation lf -blocking 0
6640    chan configure $f2 -translation cr -blocking 0
6641    set s0 [chan copy $f1 $f2]
6642    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6643    chan close $f1
6644    chan close $f2
6645    set s1 [file size $thisScript]
6646    set s2 [file size $path(test1)]
6647    if {($s1 == $s2) && ($s0 == $s1)} {
6648        lappend result ok
6649    }
6650    return $result
6651} -result {0 0 ok}
6652test chan-io-52.4 {TclCopyChannel} -constraints {fcopy} -setup {
6653    file delete $path(test1)
6654} -body {
6655    set f1 [open $thisScript]
6656    set f2 [open $path(test1) w]
6657    chan configure $f1 -translation lf -blocking 0
6658    chan configure $f2 -translation cr -blocking 0
6659    chan copy $f1 $f2 -size 40
6660    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6661    chan close $f1
6662    chan close $f2
6663    lappend result [file size $path(test1)]
6664} -result {0 0 40}
6665test chan-io-52.5 {TclCopyChannel, all} -constraints {fcopy} -setup {
6666    file delete $path(test1)
6667} -body {
6668    set f1 [open $thisScript]
6669    set f2 [open $path(test1) w]
6670    chan configure $f1 -translation lf -blocking 0
6671    chan configure $f2 -translation lf -blocking 0
6672    chan copy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
6673    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6674    chan close $f1
6675    chan close $f2
6676    if {[file size $thisScript] == [file size $path(test1)]} {
6677        lappend result ok
6678    }
6679    return $result
6680} -result {0 0 ok}
6681test chan-io-52.5a {TclCopyChannel, all, other negative value} -setup {
6682    file delete $path(test1)
6683} -constraints {fcopy} -body {
6684    set f1 [open $thisScript]
6685    set f2 [open $path(test1) w]
6686    chan configure $f1 -translation lf -blocking 0
6687    chan configure $f2 -translation lf -blocking 0
6688    chan copy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
6689    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6690    chan close $f1
6691    chan close $f2
6692    if {[file size $thisScript] == [file size $path(test1)]} {
6693        lappend result ok
6694    }
6695    return $result
6696} -result {0 0 ok}
6697test chan-io-52.5b {TclCopyChannel, all, wrap to negative value} -setup {
6698    file delete $path(test1)
6699} -constraints {fcopy} -body {
6700    set f1 [open $thisScript]
6701    set f2 [open $path(test1) w]
6702    chan configure $f1 -translation lf -blocking 0
6703    chan configure $f2 -translation lf -blocking 0
6704    chan copy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
6705    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6706    chan close $f1
6707    chan close $f2
6708    if {[file size $thisScript] ==  [file size $path(test1)]} {
6709        lappend result ok
6710    }
6711    return $result
6712} -result {0 0 ok}
6713test chan-io-52.6 {TclCopyChannel} -setup {
6714    file delete $path(test1)
6715} -constraints {fcopy} -body {
6716    set f1 [open $thisScript]
6717    set f2 [open $path(test1) w]
6718    chan configure $f1 -translation lf -blocking 0
6719    chan configure $f2 -translation lf -blocking 0
6720    set s0 [chan copy $f1 $f2 -size [expr {[file size $thisScript] + 5}]]
6721    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6722    chan close $f1
6723    chan close $f2
6724    set s1 [file size $thisScript]
6725    set s2 [file size $path(test1)]
6726    if {($s1 == $s2) && ($s0 == $s1)} {
6727        lappend result ok
6728    }
6729    return $result
6730} -result {0 0 ok}
6731test chan-io-52.7 {TclCopyChannel} -constraints {fcopy} -setup {
6732    file delete $path(test1)
6733} -body {
6734    set f1 [open $thisScript]
6735    set f2 [open $path(test1) w]
6736    chan configure $f1 -translation lf -blocking 0
6737    chan configure $f2 -translation lf -blocking 0
6738    chan copy $f1 $f2
6739    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6740    if {[file size $thisScript] == [file size $path(test1)]} {
6741        lappend result ok
6742    }
6743    return $result
6744} -cleanup {
6745    chan close $f1
6746    chan close $f2
6747} -result {0 0 ok}
6748test chan-io-52.8 {TclCopyChannel} -setup {
6749    file delete $path(test1)
6750    file delete $path(pipe)
6751} -constraints {stdio fcopy} -body {
6752    set f1 [open $path(pipe) w]
6753    chan configure $f1 -translation lf
6754    chan puts $f1 "
6755	chan puts ready
6756	chan gets stdin
6757	set f1 \[open [list $thisScript] r\]
6758	chan configure \$f1 -translation lf
6759	chan puts \[chan read \$f1 100\]
6760	chan close \$f1
6761    "
6762    chan close $f1
6763    set f1 [openpipe r+ $path(pipe)]
6764    chan configure $f1 -translation lf
6765    chan gets $f1
6766    chan puts $f1 ready
6767    chan flush $f1
6768    set f2 [open $path(test1) w]
6769    chan configure $f2 -translation lf
6770    set s0 [chan copy $f1 $f2 -size 40]
6771    catch {chan close $f1}
6772    chan close $f2
6773    list $s0 [file size $path(test1)]
6774} -result {40 40}
6775# Empty files, to register them with the test facility
6776set path(kyrillic.txt)   [makeFile {} kyrillic.txt]
6777set path(utf8-fcopy.txt) [makeFile {} utf8-fcopy.txt]
6778set path(utf8-rp.txt)    [makeFile {} utf8-rp.txt]
6779# Create kyrillic file, use lf translation to avoid os eol issues
6780set out [open $path(kyrillic.txt) w]
6781chan configure $out -encoding koi8-r -translation lf
6782chan puts       $out "\u0410\u0410"
6783chan close      $out
6784test chan-io-52.9 {TclCopyChannel & encodings} {fcopy} {
6785    # Copy kyrillic to UTF-8, using chan copy.
6786    set in  [open $path(kyrillic.txt) r]
6787    set out [open $path(utf8-fcopy.txt) w]
6788    chan configure $in  -encoding koi8-r -translation lf
6789    chan configure $out -encoding utf-8 -translation lf
6790    chan copy $in $out
6791    chan close $in
6792    chan close $out
6793    # Do the same again, but differently (read/chan puts).
6794    set in  [open $path(kyrillic.txt) r]
6795    set out [open $path(utf8-rp.txt) w]
6796    chan configure $in  -encoding koi8-r -translation lf
6797    chan configure $out -encoding utf-8 -translation lf
6798    chan puts -nonewline $out [chan read $in]
6799    chan close $in
6800    chan close $out
6801    list [file size $path(kyrillic.txt)] \
6802	    [file size $path(utf8-fcopy.txt)] \
6803	    [file size $path(utf8-rp.txt)]
6804} {3 5 5}
6805test chan-io-52.10 {TclCopyChannel & encodings} {fcopy} {
6806    # encoding to binary (=> implies that the internal utf-8 is written)
6807    set in  [open $path(kyrillic.txt) r]
6808    set out [open $path(utf8-fcopy.txt) w]
6809    chan configure $in  -encoding koi8-r -translation lf
6810    # -translation binary is also -encoding binary
6811    chan configure $out -translation binary
6812    chan copy $in $out
6813    chan close $in
6814    chan close $out
6815    file size $path(utf8-fcopy.txt)
6816} 5
6817test chan-io-52.11 {TclCopyChannel & encodings} -setup {
6818    set f [open $path(utf8-fcopy.txt) w]
6819    fconfigure $f -encoding utf-8 -translation lf
6820    puts $f "\u0410\u0410"
6821    close $f
6822} -constraints {fcopy} -body {
6823    # binary to encoding => the input has to be in utf-8 to make sense to the
6824    # encoder
6825    set in  [open $path(utf8-fcopy.txt) r]
6826    set out [open $path(kyrillic.txt) w]
6827    # -translation binary is also -encoding binary
6828    chan configure $in  -translation binary
6829    chan configure $out -encoding koi8-r -translation lf
6830    chan copy $in $out
6831    chan close $in
6832    chan close $out
6833    file size $path(kyrillic.txt)
6834} -result 3
6835
6836test chan-io-53.1 {CopyData} -setup {
6837    file delete $path(test1)
6838} -constraints {fcopy} -body {
6839    set f1 [open $thisScript]
6840    set f2 [open $path(test1) w]
6841    chan configure $f1 -translation lf -blocking 0
6842    chan configure $f2 -translation cr -blocking 0
6843    chan copy $f1 $f2 -size 0
6844    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6845    chan close $f1
6846    chan close $f2
6847    lappend result [file size $path(test1)]
6848} -result {0 0 0}
6849test chan-io-53.2 {CopyData} -setup {
6850    file delete $path(test1)
6851} -constraints {fcopy} -body {
6852    set f1 [open $thisScript]
6853    set f2 [open $path(test1) w]
6854    chan configure $f1 -translation lf -blocking 0
6855    chan configure $f2 -translation cr -blocking 0
6856    chan copy $f1 $f2 -command [namespace code {set s0}]
6857    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
6858    variable s0
6859    vwait [namespace which -variable s0]
6860    chan close $f1
6861    chan close $f2
6862    set s1 [file size $thisScript]
6863    set s2 [file size $path(test1)]
6864    if {($s1 == $s2) && ($s0 == $s1)} {
6865        lappend result ok
6866    }
6867    return $result
6868} -result {0 0 ok}
6869test chan-io-53.3 {CopyData: background read underflow} -setup {
6870    file delete $path(test1)
6871    file delete $path(pipe)
6872} -constraints {stdio unix fcopy} -body {
6873    set f1 [open $path(pipe) w]
6874    chan puts -nonewline $f1 {
6875	chan puts ready
6876	chan flush stdout			;# Don't assume line buffered!
6877	chan copy stdin stdout -command { set x }
6878	vwait x
6879	set f [}
6880    chan puts $f1 [list open $path(test1) w]]
6881    chan puts $f1 {
6882	chan configure $f -translation lf
6883	chan puts $f "done"
6884	chan close $f
6885    }
6886    chan close $f1
6887    set f1 [openpipe r+ $path(pipe)]
6888    set result [chan gets $f1]
6889    chan puts $f1 line1
6890    chan flush $f1
6891    lappend result [chan gets $f1]
6892    chan puts $f1 line2
6893    chan flush $f1
6894    lappend result [chan gets $f1]
6895    chan close $f1
6896    after 500
6897    set f [open $path(test1)]
6898    lappend result [chan read $f]
6899} -cleanup {
6900    chan close $f
6901} -result "ready line1 line2 {done\n}"
6902test chan-io-53.4 {CopyData: background write overflow} -setup {
6903    set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
6904    variable x
6905    for {set x 0} {$x < 12} {incr x} {
6906	append big $big
6907    }
6908    file delete $path(test1)
6909    file delete $path(pipe)
6910} -constraints {stdio unix fileevent fcopy} -body {
6911    set f1 [open $path(pipe) w]
6912    chan puts $f1 {
6913	chan puts ready
6914	chan copy stdin stdout -command { set x }
6915	vwait x
6916	set f [open $path(test1) w]
6917	chan configure $f -translation lf
6918	chan puts $f "done"
6919	chan close $f
6920    }
6921    chan close $f1
6922    set f1 [openpipe r+ $path(pipe)]
6923    set result [chan gets $f1]
6924    chan configure $f1 -blocking 0
6925    chan puts $f1 $big
6926    chan flush $f1
6927    after 500
6928    set result ""
6929    chan event $f1 read [namespace code {
6930	append result [chan read $f1 1024]
6931	if {[string length $result] >= [string length $big]} {
6932	    set x done
6933	}
6934    }]
6935    vwait [namespace which -variable x]
6936    return $x
6937} -cleanup {
6938    set big {}
6939    chan close $f1
6940} -result done
6941set result {}
6942proc FcopyTestAccept {sock args} {
6943    after 1000 "chan close $sock"
6944}
6945proc FcopyTestDone {bytes {error {}}} {
6946    variable fcopyTestDone
6947    if {[string length $error]} {
6948	set fcopyTestDone 1
6949    } else {
6950	set fcopyTestDone 0
6951    }
6952}
6953test chan-io-53.5 {CopyData: error during chan copy} {socket fcopy} {
6954    variable fcopyTestDone
6955    set listen [socket -server [namespace code FcopyTestAccept] -myaddr 127.0.0.1 0]
6956    set in [open $thisScript]	;# 126 K
6957    set out [socket 127.0.0.1 [lindex [chan configure $listen -sockname] 2]]
6958    catch {unset fcopyTestDone}
6959    chan close $listen	;# This means the socket open never really succeeds
6960    chan copy $in $out -command [namespace code FcopyTestDone]
6961    variable fcopyTestDone
6962    if {![info exists fcopyTestDone]} {
6963	vwait [namespace which -variable fcopyTestDone]		;# The error occurs here in the b.g.
6964    }
6965    chan close $in
6966    chan close $out
6967    set fcopyTestDone	;# 1 for error condition
6968} 1
6969test chan-io-53.6 {CopyData: error during chan copy} -setup {
6970    variable fcopyTestDone
6971    file delete $path(pipe)
6972    file delete $path(test1)
6973    catch {unset fcopyTestDone}
6974} -constraints {stdio fcopy} -body {
6975    set f1 [open $path(pipe) w]
6976    chan puts $f1 "exit 1"
6977    chan close $f1
6978    set in [openpipe r+ $path(pipe)]
6979    set out [open $path(test1) w]
6980    chan copy $in $out -command [namespace code FcopyTestDone]
6981    variable fcopyTestDone
6982    if {![info exists fcopyTestDone]} {
6983	vwait [namespace which -variable fcopyTestDone]
6984    }
6985    return $fcopyTestDone	;# 0 for plain end of file
6986} -cleanup {
6987    catch {chan close $in}
6988    chan close $out
6989} -result 0
6990proc doFcopy {in out {bytes 0} {error {}}} {
6991    variable fcopyTestDone
6992    variable fcopyTestCount
6993    incr fcopyTestCount $bytes
6994    if {[string length $error]} {
6995	set fcopyTestDone 1
6996    } elseif {[chan eof $in]} {
6997	set fcopyTestDone 0
6998    } else {
6999        # Delay next chan copy to wait for size>0 input bytes
7000        after 100 [list chan copy $in $out -size 1000 \
7001		-command [namespace code [list doFcopy $in $out]]]
7002    }
7003}
7004test chan-io-53.7 {CopyData: Flooding chan copy from pipe} -setup {
7005    variable fcopyTestDone
7006    file delete $path(pipe)
7007    catch {unset fcopyTestDone}
7008} -constraints {stdio fcopy} -body {
7009    set fcopyTestCount 0
7010    set f1 [open $path(pipe) w]
7011    chan puts $f1 {
7012	# Write  10 bytes / 10 msec
7013	proc Write {count} {
7014	    chan puts -nonewline "1234567890"
7015	    if {[incr count -1]} {
7016	        after 10 [list Write $count]
7017	    } else {
7018	        set ::ready 1
7019	    }
7020	}
7021	chan configure stdout -buffering none
7022	Write 345 ;# 3450 bytes ~3.45 sec
7023	vwait ready
7024	exit 0
7025    }
7026    chan close $f1
7027    set in [openpipe r+ $path(pipe) &]
7028    set out [open $path(test1) w]
7029    doFcopy $in $out
7030    variable fcopyTestDone
7031    if {![info exists fcopyTestDone]} {
7032	vwait [namespace which -variable fcopyTestDone]
7033    }
7034    # -1=error 0=script error N=number of bytes
7035    expr {($fcopyTestDone == 0) ? $fcopyTestCount : -1}
7036} -cleanup {
7037    catch {chan close $in}
7038    chan close $out
7039} -result {3450}
7040test chan-io-53.8 {CopyData: async callback and error handling, Bug 1932639} -setup {
7041    # copy progress callback. errors out intentionally
7042    proc cmd args {
7043	lappend ::RES "CMD $args"
7044	error !STOP
7045    }
7046    # capture callback error here
7047    proc ::bgerror args {
7048	lappend ::RES "bgerror/OK $args"
7049	set ::forever has-been-reached
7050	return
7051    }
7052    # Files we use for our channels
7053    set foo [makeFile ashgdfashdgfasdhgfasdhgf foo]
7054    set bar [makeFile {} bar]
7055    # Channels to copy between
7056    set f [open $foo r] ; fconfigure $f -translation binary
7057    set g [open $bar w] ; fconfigure $g -translation binary -buffering none
7058} -constraints {stdio fcopy} -body {
7059    # Record input size, so that result is always defined
7060    lappend ::RES [file size $bar]
7061    # Run the copy. Should not invoke -command now.
7062    chan copy $f $g -size 2 -command [namespace code cmd]
7063    # Check that -command was not called synchronously
7064    set sbs [file size $bar]
7065    lappend ::RES [expr {($sbs > 0) ? "sync/FAIL" : "sync/OK"}] $sbs
7066    # Now let the async part happen. Should capture the error in cmd via
7067    # bgerror. If not break the event loop via timer.
7068    set token [after 1000 {
7069	lappend ::RES {bgerror/FAIL timeout}
7070	set ::forever has-been-reached
7071    }]
7072    vwait ::forever
7073    catch {after cancel $token}
7074    # Report
7075    set ::RES
7076} -cleanup {
7077    chan close $f
7078    chan close $g
7079    catch {unset ::RES}
7080    catch {unset ::forever}
7081    rename ::bgerror {}
7082    removeFile foo
7083    removeFile bar
7084} -result {0 sync/OK 0 {CMD 2} {bgerror/OK !STOP}}
7085test chan-io-53.8a {CopyData: async callback and error handling, Bug 1932639, at eof} -setup {
7086    # copy progress callback.
7087    proc cmd args {
7088	lappend ::RES "CMD $args"
7089	set ::forever has-been-reached
7090	return
7091    }
7092    # Files we use for our channels
7093    set foo [makeFile ashgdfashdgfasdhgfasdhgf foo]
7094    set bar [makeFile {} bar]
7095    # Channels to copy between
7096    set f [open $foo r] ; chan configure $f -translation binary
7097    set g [open $bar w] ; chan configure $g -translation binary -buffering none
7098} -constraints {stdio fcopy} -body {
7099    # Initialize and force eof on the input.
7100    chan seek $f 0 end ; chan read $f 1
7101    set ::RES [chan eof $f]
7102    # Run the copy. Should not invoke -command now.
7103    chan copy $f $g -size 2 -command [namespace code cmd]
7104    # Check that -command was not called synchronously
7105    lappend ::RES [expr {([llength $::RES] > 1) ? "sync/FAIL" : "sync/OK"}]
7106    # Now let the async part happen. Should capture the eof in cmd
7107    # If not break the event loop via timer.
7108    set token [after 1000 {
7109	lappend ::RES {cmd/FAIL timeout}
7110	set ::forever has-been-reached
7111    }]
7112    vwait ::forever
7113    catch {after cancel $token}
7114    # Report
7115    return $::RES
7116} -cleanup {
7117    chan close $f
7118    chan close $g
7119    catch {unset ::RES}
7120    catch {unset ::forever}
7121    removeFile foo
7122    removeFile bar
7123} -result {1 sync/OK {CMD 0}}
7124test chan-io-53.9 {CopyData: -size and event interaction, Bug 780533} -setup {
7125    set out [makeFile {} out]
7126    set err [makeFile {} err]
7127    set pipe [open "|[list [info nameofexecutable] 2> $err]" r+]
7128    chan configure $pipe -translation binary -buffering line
7129    chan puts $pipe {
7130	chan configure stdout -translation binary -buffering line
7131	chan puts stderr Waiting...
7132	after 1000
7133	foreach x {a b c} {
7134	    chan puts stderr Looping...
7135	    chan puts $x
7136	    after 500
7137	}
7138	proc bye args {
7139	    if {[chan gets stdin line]<0} {
7140		chan puts stderr "CHILD: EOF detected, exiting"
7141		exit
7142	    } else {
7143		chan puts stderr "CHILD: ignoring line: $line"
7144	    }
7145	}
7146	chan puts stderr Now-sleeping-forever
7147	chan event stdin readable bye
7148	vwait forever
7149    }
7150    proc ::done args {
7151	set ::forever OK
7152	return
7153    }
7154    set ::forever {}
7155    set out [open $out w]
7156} -constraints {stdio fcopy} -body {
7157    chan copy $pipe $out -size 6 -command ::done
7158    set token [after 5000 {
7159	set ::forever {fcopy hangs}
7160    }]
7161    vwait ::forever
7162    catch {after cancel $token}
7163    set ::forever
7164} -cleanup {
7165    chan close $pipe
7166    rename ::done {}
7167    if {[testConstraint win]} {
7168	after 1000;		# Allow Windows time to figure out that the
7169                                # process is gone
7170    }
7171    catch {close $out}
7172    catch {removeFile out}
7173    catch {removeFile err}
7174    catch {unset ::forever}
7175} -result OK
7176test chan-io-53.10 {Bug 1350564, multi-directional fcopy} -setup {
7177    set err [makeFile {} err]
7178    set pipe [open "|[list [info nameofexecutable] 2> $err]" r+]
7179    chan configure $pipe -translation binary -buffering line
7180    chan puts $pipe {
7181	chan configure stderr -buffering line
7182	# Kill server when pipe closed by invoker.
7183	proc bye args {
7184	    if {![chan eof stdin]} { chan gets stdin ; return }
7185	    chan puts stderr BYE
7186	    exit
7187	}
7188	# Server code. Bi-directional copy between 2 sockets.
7189	proc geof {sok} {
7190	    chan puts stderr DONE/$sok
7191	    chan close $sok
7192	}
7193	proc new {sok args} {
7194	    chan puts stderr NEW/$sok
7195	    global l srv
7196	    chan configure $sok -translation binary -buffering none
7197	    lappend l $sok
7198	    if {[llength $l] == 2} {
7199		chan close $srv
7200		foreach {a b} $l break
7201		chan copy $a $b -command [list geof $a]
7202		chan copy $b $a -command [list geof $b]
7203		chan puts stderr 2COPY
7204	    }
7205	    chan puts stderr ...
7206	}
7207	chan puts stderr SRV
7208	set l {}
7209	set srv [socket -server new 9999]
7210	chan puts stderr WAITING
7211	chan event stdin readable bye
7212	chan puts OK
7213	vwait forever
7214    }
7215    # wait for OK from server.
7216    chan gets $pipe
7217    # Now the two clients.
7218    proc done {sock} {
7219	if {[chan eof $sock]} { chan close $sock ; return }
7220	lappend ::forever [chan gets $sock]
7221	return
7222    }
7223    set a [socket 127.0.0.1 9999]
7224    set b [socket 127.0.0.1 9999]
7225    chan configure $a -translation binary -buffering none
7226    chan configure $b -translation binary -buffering none
7227    chan event  $a readable [namespace code "done $a"]
7228    chan event  $b readable [namespace code "done $b"]
7229} -constraints {stdio fcopy} -body {
7230    # Now pass data through the server in both directions.
7231    set ::forever {}
7232    chan puts $a AB
7233    vwait ::forever
7234    chan puts $b BA
7235    vwait ::forever
7236    set ::forever
7237} -cleanup {
7238    catch {chan close $a}
7239    catch {chan close $b}
7240    chan close $pipe
7241    if {[testConstraint win]} {
7242	after 1000		;# Give Windows time to kill the process
7243    }
7244    removeFile err
7245    catch {unset ::forever}
7246} -result {AB BA}
7247
7248test chan-io-54.1 {Recursive channel events} {socket fileevent} {
7249    # This test checks to see if file events are delivered during recursive
7250    # event loops when there is buffered data on the channel.
7251    proc accept {s a p} {
7252	variable as
7253	chan configure $s -translation lf
7254	chan puts $s "line 1\nline2\nline3"
7255	chan flush $s
7256	set as $s
7257    }
7258    proc readit {s next} {
7259	variable x
7260	variable result
7261	lappend result $next
7262	if {$next == 1} {
7263	    chan event $s readable [namespace code [list readit $s 2]]
7264	    vwait [namespace which -variable x]
7265	}
7266	incr x
7267    }
7268    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
7269    # We need to delay on some systems until the creation of the server socket
7270    # completes.
7271    set done 0
7272    for {set i 0} {$i < 10} {incr i} {
7273	if {![catch {
7274	    set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]
7275	}]} {
7276	    set done 1
7277	    break
7278	}
7279	after 100
7280    }
7281    if {$done == 0} {
7282	chan close $ss
7283	error "failed to connect to server"
7284    }
7285    variable result {}
7286    variable x 0
7287    variable as
7288    vwait [namespace which -variable as]
7289    chan configure $cs -translation lf
7290    lappend result [chan gets $cs]
7291    chan configure $cs -blocking off
7292    chan event $cs readable [namespace code [list readit $cs 1]]
7293    set a [after 2000 [namespace code { set x failure }]]
7294    vwait [namespace which -variable x]
7295    after cancel $a
7296    chan close $as
7297    chan close $ss
7298    chan close $cs
7299    list $result $x
7300} {{{line 1} 1 2} 2}
7301test chan-io-54.2 {Testing for busy-wait in recursive channel events} -setup {
7302    set accept {}
7303    set after {}
7304    variable done 0
7305} -constraints {socket fileevent} -body {
7306    variable s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
7307    proc accept {s a p} {
7308	variable counter 0
7309	variable accept $s
7310	chan configure $s -blocking off -buffering line -translation lf
7311	chan event $s readable [namespace code "doit $s"]
7312    }
7313    proc doit {s} {
7314	variable counter
7315	variable after
7316	incr counter
7317	if {[chan gets $s] eq ""} {
7318	    chan event $s readable [namespace code "doit1 $s"]
7319	    set after [after 1000 [namespace code {
7320		chan puts $writer hello
7321		chan flush $writer
7322		set done 1
7323	    }]]
7324	}
7325    }
7326    proc doit1 {s} {
7327	variable counter
7328	variable accept
7329	incr counter
7330	chan gets $s
7331	chan close $s
7332	set accept {}
7333    }
7334    proc producer {} {
7335	variable s
7336	variable writer
7337	set writer [socket 127.0.0.1 [lindex [chan configure $s -sockname] 2]]
7338	chan configure $writer -buffering line
7339	chan puts -nonewline $writer hello
7340	chan flush $writer
7341    }
7342    producer
7343    vwait [namespace which -variable done]
7344    chan close $writer
7345    chan close $s
7346    after cancel $after
7347    set counter
7348} -cleanup {
7349    if {$accept ne {}} {chan close $accept}
7350} -result 1
7351
7352set path(fooBar) [makeFile {} fooBar]
7353
7354test chan-io-55.1 {ChannelEventScriptInvoker: deletion} -constraints {
7355    fileevent
7356} -setup {
7357    variable x
7358    proc eventScript {fd} {
7359	variable x
7360	chan close $fd
7361	error "planned error"
7362	set x whoops
7363    }
7364    proc myHandler args {
7365	variable x got_error
7366    }
7367    set handler [interp bgerror {}]
7368    interp bgerror {} [namespace which myHandler]
7369} -body {
7370    set f [open $path(fooBar) w]
7371    chan event $f writable [namespace code [list eventScript $f]]
7372    variable x not_done
7373    vwait [namespace which -variable x]
7374    set x
7375} -cleanup {
7376    interp bgerror {} $handler
7377} -result {got_error}
7378
7379test chan-io-56.1 {ChannelTimerProc} {testchannelevent} {
7380    set f [open $path(fooBar) w]
7381    chan puts $f "this is a test"
7382    chan close $f
7383    set f [open $path(fooBar) r]
7384    testchannelevent $f add readable [namespace code {
7385	chan read $f 1
7386	incr x
7387    }]
7388    variable x 0
7389    vwait [namespace which -variable x]
7390    vwait [namespace which -variable x]
7391    set result $x
7392    testchannelevent $f set 0 none
7393    after idle [namespace code {set y done}]
7394    variable y
7395    vwait [namespace which -variable y]
7396    chan close $f
7397    lappend result $y
7398} {2 done}
7399
7400test chan-io-57.1 {buffered data and file events, gets} -setup {
7401    variable s2
7402} -constraints {fileevent} -body {
7403    proc accept {sock args} {
7404	variable s2
7405	set s2 $sock
7406    }
7407    set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
7408    set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]
7409    vwait [namespace which -variable s2]
7410    update
7411    chan event $s2 readable [namespace code {lappend result readable}]
7412    chan puts $s "12\n34567890"
7413    chan flush $s
7414    variable result [chan gets $s2]
7415    after 1000 [namespace code {lappend result timer}]
7416    vwait [namespace which -variable result]
7417    lappend result [chan gets $s2]
7418    vwait [namespace which -variable result]
7419    set result
7420} -cleanup {
7421    chan close $s
7422    chan close $s2
7423    chan close $server
7424} -result {12 readable 34567890 timer}
7425test chan-io-57.2 {buffered data and file events, read} -setup {
7426    variable s2
7427} -constraints {fileevent} -body {
7428    proc accept {sock args} {
7429	variable s2
7430	set s2 $sock
7431    }
7432    set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
7433    set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]
7434    vwait [namespace which -variable s2]
7435    update
7436    chan event $s2 readable [namespace code {lappend result readable}]
7437    chan puts -nonewline $s "1234567890"
7438    chan flush $s
7439    variable result [chan read $s2 1]
7440    after 1000 [namespace code {lappend result timer}]
7441    vwait [namespace which -variable result]
7442    lappend result [chan read $s2 9]
7443    vwait [namespace which -variable result]
7444    set result
7445} -cleanup {
7446    chan close $s
7447    chan close $s2
7448    chan close $server
7449} -result {1 readable 234567890 timer}
7450
7451test chan-io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrWin fileevent} {
7452    set out [open $path(script) w]
7453    chan puts $out {
7454	chan puts "normal message from pipe"
7455	chan puts stderr "error message from pipe"
7456	exit 1
7457    }
7458    proc readit {pipe} {
7459	variable x
7460	variable result
7461	if {[chan eof $pipe]} {
7462	    set x [catch {chan close $pipe} line]
7463	    lappend result catch $line
7464	} else {
7465	    chan gets $pipe line
7466	    lappend result chan gets $line
7467	}
7468    }
7469    chan close $out
7470    set pipe [openpipe r $path(script)]
7471    chan event $pipe readable [namespace code [list readit $pipe]]
7472    variable x ""
7473    set result ""
7474    vwait [namespace which -variable x]
7475    list $x $result
7476} {1 {chan gets {normal message from pipe} chan gets {} catch {error message from pipe}}}
7477
7478test chan-io-59.1 {Thread reference of channels} {testmainthread testchannel} {
7479    # TIP #10
7480    # More complicated tests (like that the reference changes as a channel is
7481    # moved from thread to thread) can be done only in the extension which
7482    # fully implements the moving of channels between threads, i.e. 'Threads'.
7483    set f [open $path(longfile) r]
7484    set result [testchannel mthread $f]
7485    chan close $f
7486    string equal $result [testmainthread]
7487} {1}
7488
7489test chan-io-60.1 {writing illegal utf sequences} {fileevent testbytestring} {
7490    # This test will hang in older revisions of the core.
7491    set out [open $path(script) w]
7492    chan puts $out "catch {load $::tcltestlib Tcltest}"
7493    chan puts $out {
7494	chan puts [testbytestring \xe2]
7495	exit 1
7496    }
7497    proc readit {pipe} {
7498	variable x
7499	variable result
7500	if {[chan eof $pipe]} {
7501	    set x [catch {chan close $pipe} line]
7502	    lappend result catch $line
7503	} else {
7504	    chan gets $pipe line
7505	    lappend result gets $line
7506	}
7507    }
7508    chan close $out
7509    set pipe [openpipe r $path(script)]
7510    chan event $pipe readable [namespace code [list readit $pipe]]
7511    variable x ""
7512    set result ""
7513    vwait [namespace which -variable x]
7514    # cut of the remainder of the error stack, especially the filename
7515    set result [lreplace $result 3 3 [lindex [split [lindex $result 3] \n] 0]]
7516    list $x $result
7517} {1 {gets {} catch {error writing "stdout": invalid argument}}}
7518
7519test chan-io-61.1 {Reset eof state after changing the eof char} -setup {
7520    set datafile [makeFile {} eofchar]
7521    set f [open $datafile w]
7522    chan configure $f -translation binary
7523    chan puts -nonewline $f [string repeat "Ho hum\n" 11]
7524    chan puts $f =
7525    set line [string repeat "Ge gla " 4]
7526    chan puts -nonewline $f [string repeat [string trimright $line]\n 834]
7527    chan close $f
7528} -body {
7529    set f [open $datafile r]
7530    chan configure $f -eofchar =
7531    set res {}
7532    lappend res [chan read $f; chan tell $f]
7533    chan configure $f -eofchar {}
7534    lappend res [chan read $f 1]
7535    lappend res [chan read $f; chan tell $f]
7536    # Any seek zaps the internals into a good state.
7537    #chan seek $f 0 start
7538    #chan seek $f 0 current
7539    #lappend res [chan read $f; chan tell $f]
7540} -cleanup {
7541    chan close $f
7542    removeFile eofchar
7543} -result {77 = 23431}
7544
7545# Test the cutting and splicing of channels, this is incidentially the
7546# attach/detach facility of package Thread, but __without any safeguards__. It
7547# can also be used to emulate transfer of channels between threads, and is
7548# used for that here.
7549
7550test chan-io-70.0 {Cutting & Splicing channels} -setup {
7551    set f [makeFile {... dummy ...} cutsplice]
7552    set res {}
7553} -constraints {testchannel} -body {
7554    set c [open $f r]
7555    lappend res [catch {chan seek $c 0 start}]
7556    testchannel cut $c
7557    lappend res [catch {chan seek $c 0 start}]
7558    testchannel splice $c
7559    lappend res [catch {chan seek $c 0 start}]
7560} -cleanup {
7561    chan close $c
7562    removeFile cutsplice
7563} -result {0 1 0}
7564
7565test chan-io-70.1 {Transfer channel} -setup {
7566    set f [makeFile {... dummy ...} cutsplice]
7567    set res {}
7568} -constraints {testchannel thread} -body {
7569    set c [open $f r]
7570    lappend res [catch {chan seek $c 0 start}]
7571    testchannel cut $c
7572    lappend res [catch {chan seek $c 0 start}]
7573    set tid [thread::create -preserved]
7574    thread::send $tid [list set c $c]
7575    thread::send $tid {load {} Tcltest}
7576    lappend res [thread::send $tid {
7577	testchannel splice $c
7578	set res [catch {chan seek $c 0 start}]
7579	chan close $c
7580	set res
7581    }]
7582} -cleanup {
7583    thread::release $tid
7584    removeFile cutsplice
7585} -result {0 1 0}
7586
7587# ### ### ### ######### ######### #########
7588
7589foreach {n msg expected} {
7590     0 {}                                 {}
7591     1 {{message only}}                   {{message only}}
7592     2 {-options x}                       {-options x}
7593     3 {-options {x y} {the message}}     {-options {x y} {the message}}
7594
7595     4 {-code 1     -level 0 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7596     5 {-code 0     -level 0 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7597     6 {-code 1     -level 5 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7598     7 {-code 0     -level 5 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7599     8 {-code error -level 0 -f ba snarf} {-code error -level 0 -f ba snarf}
7600     9 {-code ok    -level 0 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7601    10 {-code error -level 5 -f ba snarf} {-code error -level 0 -f ba snarf}
7602    11 {-code ok    -level 5 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7603    12 {-code boss  -level 0 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7604    13 {-code boss  -level 5 -f ba snarf} {-code 1     -level 0 -f ba snarf}
7605    14 {-code 1     -level 0 -f ba}       {-code 1     -level 0 -f ba}
7606    15 {-code 0     -level 0 -f ba}       {-code 1     -level 0 -f ba}
7607    16 {-code 1     -level 5 -f ba}       {-code 1     -level 0 -f ba}
7608    17 {-code 0     -level 5 -f ba}       {-code 1     -level 0 -f ba}
7609    18 {-code error -level 0 -f ba}       {-code error -level 0 -f ba}
7610    19 {-code ok    -level 0 -f ba}       {-code 1     -level 0 -f ba}
7611    20 {-code error -level 5 -f ba}       {-code error -level 0 -f ba}
7612    21 {-code ok    -level 5 -f ba}       {-code 1     -level 0 -f ba}
7613    22 {-code boss  -level 0 -f ba}       {-code 1     -level 0 -f ba}
7614    23 {-code boss  -level 5 -f ba}       {-code 1     -level 0 -f ba}
7615    24 {-code 1     -level X -f ba snarf} {-code 1     -level 0 -f ba snarf}
7616    25 {-code 0     -level X -f ba snarf} {-code 1     -level 0 -f ba snarf}
7617    26 {-code error -level X -f ba snarf} {-code error -level 0 -f ba snarf}
7618    27 {-code ok    -level X -f ba snarf} {-code 1     -level 0 -f ba snarf}
7619    28 {-code boss  -level X -f ba snarf} {-code 1     -level 0 -f ba snarf}
7620    29 {-code 1     -level X -f ba}       {-code 1     -level 0 -f ba}
7621    30 {-code 0     -level X -f ba}       {-code 1     -level 0 -f ba}
7622    31 {-code error -level X -f ba}       {-code error -level 0 -f ba}
7623    32 {-code ok    -level X -f ba}       {-code 1     -level 0 -f ba}
7624    33 {-code boss  -level X -f ba}       {-code 1     -level 0 -f ba}
7625
7626    34 {-code 1 -code 1     -level 0 -f ba snarf} {-code 1 -code 1     -level 0 -f ba snarf}
7627    35 {-code 1 -code 0     -level 0 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7628    36 {-code 1 -code 1     -level 5 -f ba snarf} {-code 1 -code 1     -level 0 -f ba snarf}
7629    37 {-code 1 -code 0     -level 5 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7630    38 {-code 1 -code error -level 0 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
7631    39 {-code 1 -code ok    -level 0 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7632    40 {-code 1 -code error -level 5 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
7633    41 {-code 1 -code ok    -level 5 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7634    42 {-code 1 -code boss  -level 0 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7635    43 {-code 1 -code boss  -level 5 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7636    44 {-code 1 -code 1     -level 0 -f ba}       {-code 1 -code 1     -level 0 -f ba}
7637    45 {-code 1 -code 0     -level 0 -f ba}       {-code 1             -level 0 -f ba}
7638    46 {-code 1 -code 1     -level 5 -f ba}       {-code 1 -code 1     -level 0 -f ba}
7639    47 {-code 1 -code 0     -level 5 -f ba}       {-code 1             -level 0 -f ba}
7640    48 {-code 1 -code error -level 0 -f ba}       {-code 1 -code error -level 0 -f ba}
7641    49 {-code 1 -code ok    -level 0 -f ba}       {-code 1             -level 0 -f ba}
7642    50 {-code 1 -code error -level 5 -f ba}       {-code 1 -code error -level 0 -f ba}
7643    51 {-code 1 -code ok    -level 5 -f ba}       {-code 1             -level 0 -f ba}
7644    52 {-code 1 -code boss  -level 0 -f ba}       {-code 1             -level 0 -f ba}
7645    53 {-code 1 -code boss  -level 5 -f ba}       {-code 1             -level 0 -f ba}
7646    54 {-code 1 -code 1     -level X -f ba snarf} {-code 1 -code 1     -level 0 -f ba snarf}
7647    55 {-code 1 -code 0     -level X -f ba snarf} {-code 1             -level 0 -f ba snarf}
7648    56 {-code 1 -code error -level X -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
7649    57 {-code 1 -code ok    -level X -f ba snarf} {-code 1             -level 0 -f ba snarf}
7650    58 {-code 1 -code boss  -level X -f ba snarf} {-code 1             -level 0 -f ba snarf}
7651    59 {-code 1 -code 1     -level X -f ba}       {-code 1 -code 1     -level 0 -f ba}
7652    60 {-code 1 -code 0     -level X -f ba}       {-code 1             -level 0 -f ba}
7653    61 {-code 1 -code error -level X -f ba}       {-code 1 -code error -level 0 -f ba}
7654    62 {-code 1 -code ok    -level X -f ba}       {-code 1             -level 0 -f ba}
7655    63 {-code 1 -code boss  -level X -f ba}       {-code 1             -level 0 -f ba}
7656
7657    64 {-code 0 -code 1     -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7658    65 {-code 0 -code 0     -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7659    66 {-code 0 -code 1     -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7660    67 {-code 0 -code 0     -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7661    68 {-code 0 -code error -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7662    69 {-code 0 -code ok    -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7663    70 {-code 0 -code error -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7664    71 {-code 0 -code ok    -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7665    72 {-code 0 -code boss  -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7666    73 {-code 0 -code boss  -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7667    74 {-code 0 -code 1     -level 0 -f ba}       {-code 1 -level 0 -f ba}
7668    75 {-code 0 -code 0     -level 0 -f ba}       {-code 1 -level 0 -f ba}
7669    76 {-code 0 -code 1     -level 5 -f ba}       {-code 1 -level 0 -f ba}
7670    77 {-code 0 -code 0     -level 5 -f ba}       {-code 1 -level 0 -f ba}
7671    78 {-code 0 -code error -level 0 -f ba}       {-code 1 -level 0 -f ba}
7672    79 {-code 0 -code ok    -level 0 -f ba}       {-code 1 -level 0 -f ba}
7673    80 {-code 0 -code error -level 5 -f ba}       {-code 1 -level 0 -f ba}
7674    81 {-code 0 -code ok    -level 5 -f ba}       {-code 1 -level 0 -f ba}
7675    82 {-code 0 -code boss  -level 0 -f ba}       {-code 1 -level 0 -f ba}
7676    83 {-code 0 -code boss  -level 5 -f ba}       {-code 1 -level 0 -f ba}
7677    84 {-code 0 -code 1     -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7678    85 {-code 0 -code 0     -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7679    86 {-code 0 -code error -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7680    87 {-code 0 -code ok    -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7681    88 {-code 0 -code boss  -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7682    89 {-code 0 -code 1     -level X -f ba}       {-code 1 -level 0 -f ba}
7683    90 {-code 0 -code 0     -level X -f ba}       {-code 1 -level 0 -f ba}
7684    91 {-code 0 -code error -level X -f ba}       {-code 1 -level 0 -f ba}
7685    92 {-code 0 -code ok    -level X -f ba}       {-code 1 -level 0 -f ba}
7686    93 {-code 0 -code boss  -level X -f ba}       {-code 1 -level 0 -f ba}
7687
7688    94 {-code 1     -code 1 -level 0 -f ba snarf} {-code 1 -code 1     -level 0 -f ba snarf}
7689    95 {-code 0     -code 1 -level 0 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7690    96 {-code 1     -code 1 -level 5 -f ba snarf} {-code 1 -code 1     -level 0 -f ba snarf}
7691    97 {-code 0     -code 1 -level 5 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7692    98 {-code error -code 1 -level 0 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
7693    99 {-code ok    -code 1 -level 0 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7694    a0 {-code error -code 1 -level 5 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
7695    a1 {-code ok    -code 1 -level 5 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7696    a2 {-code boss  -code 1 -level 0 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7697    a3 {-code boss  -code 1 -level 5 -f ba snarf} {-code 1             -level 0 -f ba snarf}
7698    a4 {-code 1     -code 1 -level 0 -f ba}       {-code 1 -code 1     -level 0 -f ba}
7699    a5 {-code 0     -code 1 -level 0 -f ba}       {-code 1             -level 0 -f ba}
7700    a6 {-code 1     -code 1 -level 5 -f ba}       {-code 1 -code 1     -level 0 -f ba}
7701    a7 {-code 0     -code 1 -level 5 -f ba}       {-code 1             -level 0 -f ba}
7702    a8 {-code error -code 1 -level 0 -f ba}       {-code error -code 1 -level 0 -f ba}
7703    a9 {-code ok    -code 1 -level 0 -f ba}       {-code 1             -level 0 -f ba}
7704    b0 {-code error -code 1 -level 5 -f ba}       {-code error -code 1 -level 0 -f ba}
7705    b1 {-code ok    -code 1 -level 5 -f ba}       {-code 1             -level 0 -f ba}
7706    b2 {-code boss  -code 1 -level 0 -f ba}       {-code 1             -level 0 -f ba}
7707    b3 {-code boss  -code 1 -level 5 -f ba}       {-code 1             -level 0 -f ba}
7708    b4 {-code 1     -code 1 -level X -f ba snarf} {-code 1 -code 1     -level 0 -f ba snarf}
7709    b5 {-code 0     -code 1 -level X -f ba snarf} {-code 1             -level 0 -f ba snarf}
7710    b6 {-code error -code 1 -level X -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
7711    b7 {-code ok    -code 1 -level X -f ba snarf} {-code 1             -level 0 -f ba snarf}
7712    b8 {-code boss  -code 1 -level X -f ba snarf} {-code 1             -level 0 -f ba snarf}
7713    b9 {-code 1     -code 1 -level X -f ba}       {-code 1 -code 1     -level 0 -f ba}
7714    c0 {-code 0     -code 1 -level X -f ba}       {-code 1             -level 0 -f ba}
7715    c1 {-code error -code 1 -level X -f ba}       {-code error -code 1 -level 0 -f ba}
7716    c2 {-code ok    -code 1 -level X -f ba}       {-code 1             -level 0 -f ba}
7717    c3 {-code boss  -code 1 -level X -f ba}       {-code 1             -level 0 -f ba}
7718
7719    c4 {-code 1     -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7720    c5 {-code 0     -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7721    c6 {-code 1     -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7722    c7 {-code 0     -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7723    c8 {-code error -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7724    c9 {-code ok    -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7725    d0 {-code error -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7726    d1 {-code ok    -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7727    d2 {-code boss  -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7728    d3 {-code boss  -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
7729    d4 {-code 1     -code 0 -level 0 -f ba}       {-code 1 -level 0 -f ba}
7730    d5 {-code 0     -code 0 -level 0 -f ba}       {-code 1 -level 0 -f ba}
7731    d6 {-code 1     -code 0 -level 5 -f ba}       {-code 1 -level 0 -f ba}
7732    d7 {-code 0     -code 0 -level 5 -f ba}       {-code 1 -level 0 -f ba}
7733    d8 {-code error -code 0 -level 0 -f ba}       {-code 1 -level 0 -f ba}
7734    d9 {-code ok    -code 0 -level 0 -f ba}       {-code 1 -level 0 -f ba}
7735    e0 {-code error -code 0 -level 5 -f ba}       {-code 1 -level 0 -f ba}
7736    e1 {-code ok    -code 0 -level 5 -f ba}       {-code 1 -level 0 -f ba}
7737    e2 {-code boss  -code 0 -level 0 -f ba}       {-code 1 -level 0 -f ba}
7738    e3 {-code boss  -code 0 -level 5 -f ba}       {-code 1 -level 0 -f ba}
7739    e4 {-code 1     -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7740    e5 {-code 0     -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7741    e6 {-code error -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7742    e7 {-code ok    -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7743    e8 {-code boss  -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
7744    e9 {-code 1     -code 0 -level X -f ba}       {-code 1 -level 0 -f ba}
7745    f0 {-code 0     -code 0 -level X -f ba}       {-code 1 -level 0 -f ba}
7746    f1 {-code error -code 0 -level X -f ba}       {-code 1 -level 0 -f ba}
7747    f2 {-code ok    -code 0 -level X -f ba}       {-code 1 -level 0 -f ba}
7748    f3 {-code boss  -code 0 -level X -f ba}       {-code 1 -level 0 -f ba}
7749} {
7750    test chan-io-71.$n {Tcl_SetChannelError} -setup {
7751	set f [makeFile {... dummy ...} cutsplice]
7752    } -constraints {testchannel} -body {
7753	set c [open $f r]
7754	testchannel setchannelerror $c [lrange $msg 0 end]
7755    } -cleanup {
7756	chan close $c
7757	removeFile cutsplice
7758    } -result [lrange $expected 0 end]
7759    test chan-io-72.$n {Tcl_SetChannelErrorInterp} -setup {
7760	set f [makeFile {... dummy ...} cutsplice]
7761    } -constraints {testchannel} -body {
7762	set c [open $f r]
7763	testchannel setchannelerrorinterp $c [lrange $msg 0 end]
7764    } -cleanup {
7765	chan close $c
7766	removeFile cutsplice
7767    } -result [lrange $expected 0 end]
7768}
7769
7770test chan-io-73.1 {channel Tcl_Obj SetChannelFromAny} -body {
7771    # Test for Bug 1847044 - don't spoil type unless we have a valid channel
7772    chan close [lreplace [list a] 0 end]
7773} -returnCodes error -match glob -result *
7774
7775# ### ### ### ######### ######### #########
7776
7777# cleanup
7778foreach file [list fooBar longfile script output test1 pipe my_script \
7779	test2 test3 cat kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
7780    removeFile $file
7781}
7782cleanupTests
7783}
7784namespace delete ::tcl::test::io
7785