Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/tests/chanio.test @ 47

Last change on this file since 47 was 25, checked in by landauf, 17 years ago

added tcl to libs

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