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