1 # Commands tested in this file: socket.
3 # This file contains a collection of tests for one or more of the Tcl built-in
4 # commands. Sourcing this file into Tcl runs the tests and generates output
5 # for errors. No output means no errors were found.
7 # Copyright (c) 1994-1996 Sun Microsystems, Inc.
8 # Copyright (c) 1998-2000 Ajuba Solutions.
10 # See the file "license.terms" for information on usage and redistribution of
11 # this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 # Running socket tests with a remote server:
14 # ------------------------------------------
16 # Some tests in socket.test depend on the existence of a remote server to
17 # which they connect. The remote server must be an instance of tcltest and it
18 # must run the script found in the file "remote.tcl" in this directory. You
19 # can start the remote server on any machine reachable from the machine on
20 # which you want to run the socket tests, by issuing:
22 # tcltest remote.tcl -port 2048 # Or choose another port number.
24 # If the machine you are running the remote server on has several IP
25 # interfaces, you can choose which interface the server listens on for
26 # connections by specifying the -address command line flag, so:
28 # tcltest remote.tcl -address your.machine.com
30 # These options can also be set by environment variables. On Unix, you can
31 # type these commands to the shell from which the remote server is started:
33 # shell% setenv serverPort 2048
34 # shell% setenv serverAddress your.machine.com
36 # and subsequently you can start the remote server with:
40 # to have it listen on port 2048 on the interface your.machine.com.
42 # When the server starts, it prints out a detailed message containing its
43 # configuration information, and it will block until killed with a Ctrl-C.
44 # Once the remote server exists, you can run the tests in socket.test with the
45 # server by setting two Tcl variables:
47 # % set remoteServerIP <name or address of machine on which server runs>
48 # % set remoteServerPort 2048
50 # These variables are also settable from the environment. On Unix, you can:
52 # shell% setenv remoteServerIP machine.where.server.runs
53 # shell% senetv remoteServerPort 2048
55 # The preamble of the socket.test file checks to see if the variables are set
56 # either in Tcl or in the environment; if they are, it attempts to connect to
57 # the server. If the connection is successful, the tests using the remote
58 # server will be performed; otherwise, it will attempt to start the remote
59 # server (via exec) on platforms that support this, on the local host,
60 # listening at port 2048. If all fails, a message is printed and the tests
61 # using the remote server are not performed.
63 if {"::tcltest" ni [namespace children]} {
64 package require tcltest 2.5
65 namespace import -force ::tcltest::*
68 ::tcltest::loadTestedCommands
70 # A bad interaction between socket creation, macOS, and unattended CI
71 # environments make this whole file impractical to run; too many weird hangs.
72 if {[info exists ::env(MAC_CI)]} {
76 # Some tests require the Thread package or exec command
77 testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
78 testConstraint exec [llength [info commands exec]]
80 # Produce a random port number in the Dynamic/Private range
81 # from 49152 through 65535.
83 # firstly try dynamic port via server-socket(0):
86 set port [lindex [fconfigure [set s [socket -server {} 0]] -sockname] 2]
90 close [socket -server {} $port]
92 if {[incr i] > 1000} {return -code error "too many iterations to get free random port: $msg"}
94 set port [expr {int(rand()*16383+49152)}]
99 # Test the latency of tcp connections over the loopback interface. Some OSes
100 # (e.g. NetBSD) seem to use the Nagle algorithm and delayed ACKs, so it takes
101 # up to 200ms for a packet sent to localhost to arrive. We're measuring this
102 # here, so that OSes that don't have this problem can run the tests at full
104 set server [socket -server {apply {{s a p} {set ::s1 $s}}} 0]
105 set s2 [socket localhost [lindex [fconfigure $server -sockname] 2]]
106 vwait s1; close $server
107 fconfigure $s1 -buffering line
108 fconfigure $s2 -buffering line
109 set t1 [clock milliseconds]
110 puts $s2 test1; gets $s1
111 puts $s2 test2; gets $s1
113 set t2 [clock milliseconds]
114 set lat1 [expr {($t2-$t1)*2}]; # doubled as a safety margin
116 # Test the latency of failed connection attempts over the loopback
117 # interface. They can take more than a second under Windowos and requres
118 # additional [after]s in some tests that are not needed on systems that fail
120 set t1 [clock milliseconds]
121 catch {socket 127.0.0.1 [randport]}
122 set t2 [clock milliseconds]
123 set lat2 [expr {($t2-$t1)*3}]
125 # Use the maximum of the two latency calculations, but at least 200ms
126 set latency [expr {$lat1 > $lat2 ? $lat1 : $lat2}]
127 set latency [expr {$latency > 200 ? $latency : 200}]
128 unset t1 t2 s1 s2 lat1 lat2 server
130 # If remoteServerIP or remoteServerPort are not set, check in the environment
131 # variables for externally set values.
134 if {![info exists remoteServerIP]} {
135 if {[info exists env(remoteServerIP)]} {
136 set remoteServerIP $env(remoteServerIP)
139 if {![info exists remoteServerPort]} {
140 if {[info exists env(remoteServerPort)]} {
141 set remoteServerPort $env(remoteServerPort)
143 if {[info exists remoteServerIP]} {
144 set remoteServerPort 2048
150 # activate this to time the tests
152 set name [lindex $args 0]
153 puts "[lindex [time {uplevel [linsert $args 0 tcltest::test]}] 0] @@@ $name"
157 foreach {af localhost} {
161 # Check if the family is supported and set the constraint accordingly
162 testConstraint supported_$af [expr {![catch {socket -server foo -myaddr $localhost 0} sock]}]
166 set sock [socket -server foo -myaddr localhost 0]
167 set sockname [fconfigure $sock -sockname]
169 testConstraint localhost_v4 [expr {"127.0.0.1" in $sockname}]
170 testConstraint localhost_v6 [expr {"::1" in $sockname}]
173 foreach {af localhost} {
178 if {![testConstraint supported_$af]} {
181 set ::tcl::unsupported::socketAF $af
183 # Check if we're supposed to do tests against the remote server
186 set doTestsWithRemoteServer 1
187 if {![info exists remoteServerIP]} {
188 set remoteServerIP $localhost
190 if {($doTestsWithRemoteServer == 1) && (![info exists remoteServerPort])} {
191 set remoteServerPort [randport]
194 # Attempt to connect to a remote server if one is already running. If it is
195 # not running or for some other reason the connect fails, attempt to start the
196 # remote server on the local host listening on port 2048. This is only done on
197 # platforms that support exec (i.e. not on the Mac). On platforms that do not
198 # support exec, the remote server must be started by the user before running
201 set remoteProcChan ""
203 if {$doTestsWithRemoteServer} {
204 catch {close $commandSocket}
206 set commandSocket [socket $remoteServerIP $remoteServerPort]
208 fconfigure $commandSocket -translation crlf -buffering line
209 } elseif {![testConstraint exec]} {
210 set noRemoteTestReason "can't exec"
211 set doTestsWithRemoteServer 0
213 set remoteServerIP $localhost
214 # Be *extra* careful in case this file is sourced from
215 # a directory other than the current one...
216 set remoteFile [file join [pwd] [file dirname [info script]] \
219 set remoteProcChan [open "|[list \
220 [interpreter] $remoteFile -serverIsSilent \
221 -port $remoteServerPort -address $remoteServerIP]" w+]
225 set commandSocket [socket $remoteServerIP $remoteServerPort]
227 fconfigure $commandSocket -translation crlf -buffering line
229 set noRemoteTestReason $msg
230 set doTestsWithRemoteServer 0
233 set noRemoteTestReason "$msg [interpreter]"
234 set doTestsWithRemoteServer 0
239 # Some tests are run only if we are doing testing against a remote server.
240 testConstraint doTestsWithRemoteServer $doTestsWithRemoteServer
241 if {!$doTestsWithRemoteServer} {
242 if {[string first s $::tcltest::verbose] >= 0} {
243 puts "Skipping tests with remote server. See tests/socket.test for"
244 puts "information on how to run remote server."
245 puts "Reason for not doing remote tests: $noRemoteTestReason"
250 # If we do the tests, define a command to send a command to the remote server.
253 if {[testConstraint doTestsWithRemoteServer]} {
254 proc sendCommand {c} {
257 if {[eof $commandSocket]} {
258 error "remote server disappeared"
260 if {[catch {puts $commandSocket $c} msg]} {
261 error "remote server disappaered: $msg"
263 if {[catch {puts $commandSocket "--Marker--Marker--Marker--"} msg]} {
264 error "remote server disappeared: $msg"
268 set line [gets $commandSocket]
269 if {[eof $commandSocket]} {
270 error "remote server disappaered"
272 if {$line eq "--Marker--Marker--Marker--"} {
273 lassign $result code info value
274 return -code $code -errorinfo $info $value
276 append result $line "\n"
282 lindex [fconfigure $sock -sockname] 2
285 # Some tests in this file are known to hang *occasionally* on OSX; stop the
287 testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
288 # Here "Windows" means derived platforms as Cygwin or Msys2 too.
289 testConstraint notWindows [expr {![regexp {^(Windows|MSYS|CYGWIN)} $::tcl_platform(os)]}]
291 # ----------------------------------------------------------------------
293 test socket_$af-1.1 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
295 } -returnCodes error -result {no argument given for -server option}
296 test socket_$af-1.2 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
298 } -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
299 test socket_$af-1.3 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
301 } -returnCodes error -result {no argument given for -myaddr option}
302 test socket_$af-1.4 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
303 socket -myaddr $localhost
304 } -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
305 test socket_$af-1.5 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
307 } -returnCodes error -result {no argument given for -myport option}
308 test socket_$af-1.6 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
310 } -returnCodes error -result {expected integer but got "xxxx"}
311 test socket_$af-1.7 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
313 } -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
314 test socket_$af-1.8 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
316 } -returnCodes error -result {bad option "-froboz": must be -async, -myaddr, -myport, or -server}
317 test socket_$af-1.9 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
318 socket -server foo -myport 2521 3333
319 } -returnCodes error -result {option -myport is not valid for servers}
320 test socket_$af-1.10 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
321 socket host 2528 -junk
322 } -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
323 test socket_$af-1.11 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
324 socket -server callback 2520 --
325 } -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
326 test socket_$af-1.12 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
328 } -returnCodes error -result {expected integer but got "badport"}
329 test socket_$af-1.13 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
330 socket -async -server
331 } -returnCodes error -result {cannot set -async option for server sockets}
332 test socket_$af-1.14 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
333 socket -server foo -async
334 } -returnCodes error -result {cannot set -async option for server sockets}
336 set path(script) [makeFile {} script]
338 test socket_$af-2.1 {tcp connection} -constraints [list socket supported_$af stdio] -setup {
339 file delete $path(script)
340 set f [open $path(script) w]
342 set timer [after 10000 "set x timed_out"]
343 set f [socket -server accept 0]
344 proc accept {file addr port} {
350 puts [lindex [fconfigure $f -sockname] 2]
357 set f [open "|[list [interpreter] $path(script)]" r]
361 # $x == "ready" at this point
362 set sock [socket $localhost $listen]
368 } -result {ready done {}}
369 test socket_$af-2.2 {tcp connection with client port specified} -setup {
371 file delete $path(script)
372 set f [open $path(script) w]
374 set timer [after 10000 "set x timeout"]
375 set f [socket -server accept 0]
376 proc accept {file addr port} {
378 puts "[gets $file] $port"
383 puts [lindex [fconfigure $f -sockname] 2]
389 set f [open "|[list [interpreter] $path(script)]" r]
392 } -constraints [list socket supported_$af stdio] -body {
393 # $x == "ready" at this point
394 set sock [socket -myport $port $localhost $listen]
397 lappend x [expr {[gets $f] eq "hello $port"}]
401 catch {close [socket $localhost $listen]}
404 test socket_$af-2.3 {tcp connection with client interface specified} -setup {
405 file delete $path(script)
406 set f [open $path(script) w]
408 set timer [after 2000 "set x done"]
409 set f [socket -server accept 0]
410 proc accept {file addr port} {
412 puts "[gets $file] $addr"
416 puts [lindex [fconfigure $f -sockname] 2]
423 set f [open "|[list [interpreter] $path(script)]" r]
426 } -constraints [list socket supported_$af stdio] -body {
427 # $x == "ready" at this point
428 set sock [socket -myaddr $localhost $localhost $listen]
436 } -result [list ready [list hello $localhost]]
437 test socket_$af-2.4 {tcp connection with server interface specified} -setup {
438 file delete $path(script)
439 set f [open $path(script) w]
440 puts $f [list set localhost $localhost]
442 set timer [after 2000 "set x done"]
443 set f [socket -server accept -myaddr $localhost 0]
444 proc accept {file addr port} {
451 puts [lindex [fconfigure $f -sockname] 2]
457 set f [open "|[list [interpreter] $path(script)]" r]
460 } -constraints [list socket supported_$af stdio] -body {
461 # $x == "ready" at this point
462 set sock [socket $localhost $listen]
470 } -result {ready hello}
471 test socket_$af-2.5 {tcp connection with redundant server port} -setup {
472 file delete $path(script)
473 set f [open $path(script) w]
475 set timer [after 10000 "set x timeout"]
476 set f [socket -server accept 0]
477 proc accept {file addr port} {
484 puts [lindex [fconfigure $f -sockname] 2]
490 set f [open "|[list [interpreter] $path(script)]" r]
493 } -constraints [list socket supported_$af stdio] -body {
494 # $x == "ready" at this point
495 set sock [socket $localhost $listen]
503 } -result {ready hello}
504 test socket_$af-2.6 {tcp connection} -constraints [list socket supported_$af] -body {
506 if {![catch {set sock [socket $localhost [randport]]}]} {
507 if {![catch {gets $sock}]} {
514 test socket_$af-2.7 {echo server, one line} -constraints [list socket supported_$af stdio] -setup {
515 file delete $path(script)
516 set f [open $path(script) w]
518 set timer [after 10000 "set x timeout"]
519 set f [socket -server accept 0]
520 proc accept {s a p} {
521 fileevent $s readable [list echo $s]
522 fconfigure $s -translation lf -buffering line
535 puts [lindex [fconfigure $f -sockname] 2]
542 set f [open "|[list [interpreter] $path(script)]" r]
546 set s [socket $localhost $listen]
547 fconfigure $s -buffering line -translation lf
548 puts $s "hello abcdefghijklmnop"
554 } -result {{hello abcdefghijklmnop} done}
556 test socket_$af-2.8 {echo server, loop 50 times, single connection} -setup {
557 set path(script) [makeFile {
558 set f [socket -server accept 0]
559 proc accept {s a p} {
560 fileevent $s readable [list echo $s]
561 fconfigure $s -buffering line
577 puts [lindex [fconfigure $f -sockname] 2]
578 set timer [after 20000 "set x done"]
584 set f [open "|[list [interpreter] $path(script)]" r]
587 } -constraints [list socket supported_$af stdio] -body {
588 set s [socket $localhost $listen]
589 fconfigure $s -buffering line
591 for {set x 0} {$x < 50} {incr x} {
592 puts $s "hello abcdefghijklmnop"
597 catch {set x [gets $f]}
603 set path(script) [makeFile {} script]
604 test socket_$af-2.9 {socket conflict} -constraints [list socket supported_$af stdio] -body {
605 set s [socket -server accept 0]
606 file delete $path(script)
607 set f [open $path(script) w]
608 puts $f [list set ::tcl::unsupported::socketAF $::tcl::unsupported::socketAF]
609 puts $f "socket -server accept [lindex [fconfigure $s -sockname] 2]"
611 set f [open "|[list [interpreter] $path(script)]" r]
615 } -returnCodes error -cleanup {
617 } -match glob -result {couldn't open socket: address already in use*}
618 test socket_$af-2.10 {close on accept, accepted socket lives} -setup {
620 set timer [after 20000 "set done timed_out"]
621 } -constraints [list socket supported_$af] -body {
622 set ss [socket -server accept 0]
623 proc accept {s a p} {
626 fileevent $s readable "readit $s"
627 fconfigure $s -trans lf
635 set cs [socket $localhost [lindex [fconfigure $ss -sockname] 2]]
643 test socket_$af-2.11 {detecting new data} -constraints [list socket supported_$af] -setup {
644 proc accept {s a p} {
648 set s [socket -server accept 0]
651 set s2 [socket $localhost [lindex [fconfigure $s -sockname] 2]]
655 after $latency {set x 1}; # Spurious failures in Travis CI, if we do [after idle]
657 fconfigure $sock -blocking 0
658 set result a:[gets $sock]
659 lappend result b:[gets $sock]
660 fconfigure $sock -blocking 1
663 after $latency {set x 1}; # NetBSD fails here if we do [after idle]
665 fconfigure $sock -blocking 0
666 lappend result c:[gets $sock]
668 fconfigure $sock -blocking 1
672 } -result {a:one b: c:two}
673 test socket_$af-2.12 {} [list socket stdio supported_$af] {
674 file delete $path(script)
675 set f [open $path(script) w]
677 set server [socket -server accept_client 0]
678 puts [lindex [chan configure $server -sockname] 2]
679 proc accept_client { client host port } {
680 chan configure $client -blocking 0 -buffering line
683 proc write_line client {
684 if { [catch { chan puts $client [string repeat . 720000]}] } {
685 puts [catch {chan close $client}]
688 after 0 write_line $client
691 chan event stdin readable {set forever now}
696 set f [open "|[list [interpreter] $path(script)]" r+]
698 set sock [socket $localhost $port]
699 chan event $sock readable [list read_lines $sock $f]
700 proc read_lines { sock pipe } {
703 chan event $pipe readable [list readpipe $pipe]
705 proc readpipe {pipe} {
706 while {![string is integer [set ::done [gets $pipe]]]} {}
712 test socket_$af-2.13 {Bug 1758a0b603} {socket stdio} {
713 file delete $path(script)
714 set f [open $path(script) w]
716 set server [socket -server accept 0]
717 puts [lindex [chan configure $server -sockname] 2]
718 proc accept { client host port } {
719 chan configure $client -blocking 0 -buffering line -buffersize 1
720 puts $client [string repeat . 720000]
722 chan event $client writable [list setup $client]
725 chan event $client writable {set forever write}
726 after 5 {set forever timeout}
732 set pipe [open |[list [interpreter] $path(script)] r]
734 set sock [socket $localhost $port]
735 chan configure $sock -blocking 0 -buffering line
736 chan event $sock readable [list read_lines $sock $pipe ]
737 proc read_lines { sock pipe } {
740 after idle [list stop $sock $pipe]
741 chan event $sock readable {}
743 proc stop {sock pipe} {
746 set done [gets $pipe]
749 vwait [namespace which -variable done]
754 test socket_$af-3.1 {socket conflict} -constraints [list socket supported_$af stdio] -setup {
755 file delete $path(script)
756 set f [open $path(script) w]
757 puts $f [list set localhost $localhost]
759 set f [socket -server accept -myaddr $localhost 0]
761 puts [lindex [fconfigure $f -sockname] 2]
766 set f [open "|[list [interpreter] $path(script)]" r+]
770 socket -server accept -myaddr $localhost $listen
774 } -returnCodes error -result {couldn't open socket: address already in use}
775 test socket_$af-3.2 {server with several clients} -setup {
776 file delete $path(script)
777 set f [open $path(script) w]
778 puts $f [list set localhost $localhost]
780 set t1 [after 30000 "set x timed_out"]
781 set t2 [after 31000 "set x timed_out"]
782 set t3 [after 32000 "set x timed_out"]
784 set s [socket -server accept -myaddr $localhost 0]
785 proc accept {s a p} {
786 fileevent $s readable [list echo $s]
787 fconfigure $s -buffering line
800 puts [lindex [fconfigure $s -sockname] 2]
811 set f [open "|[list [interpreter] $path(script)]" r+]
814 } -constraints [list socket supported_$af stdio] -body {
816 set s1 [socket $localhost $listen]
817 fconfigure $s1 -buffering line
818 set s2 [socket $localhost $listen]
819 fconfigure $s2 -buffering line
820 set s3 [socket $localhost $listen]
821 fconfigure $s3 -buffering line
822 for {set i 0} {$i < 100} {incr i} {
836 } -result {ready done}
838 test socket_$af-4.1 {server with several clients} -setup {
839 file delete $path(script)
840 set f [open $path(script) w]
841 puts $f [list set localhost $localhost]
843 set port [gets stdin]
844 set s [socket $localhost $port]
845 fconfigure $s -buffering line
846 for {set i 0} {$i < 100} {incr i} {
855 set p1 [open "|[list [interpreter] $path(script)]" r+]
856 fconfigure $p1 -buffering line
857 set p2 [open "|[list [interpreter] $path(script)]" r+]
858 fconfigure $p2 -buffering line
859 set p3 [open "|[list [interpreter] $path(script)]" r+]
860 fconfigure $p3 -buffering line
861 } -constraints [list socket supported_$af stdio] -body {
862 proc accept {s a p} {
863 fconfigure $s -buffering line
864 fileevent $s readable [list echo $s]
876 set t1 [after 30000 "set x timed_out"]
877 set t2 [after 31000 "set x timed_out"]
878 set t3 [after 32000 "set x timed_out"]
879 set s [socket -server accept -myaddr $localhost 0]
880 set listen [lindex [fconfigure $s -sockname] 2]
892 lappend l [list p1 [gets $p1] $x]
893 lappend l [list p2 [gets $p2] $x]
894 lappend l [list p3 [gets $p3] $x]
902 } -result {{p1 bye done} {p2 bye done} {p3 bye done}}
903 test socket_$af-4.2 {byte order problems, socket numbers, htons} -body {
904 close [socket -server dodo -myaddr $localhost 0x3000]
906 } -constraints [list socket supported_$af] -result ok
908 test socket_$af-5.1 {byte order problems, socket numbers, htons} -body {
909 if {![catch {socket -server dodo 0x1} msg]} {
911 return {htons problem, should be disallowed, are you running as SU?}
913 return {couldn't open socket: not owner}
914 } -constraints [list socket supported_$af unix notRoot notOSX notWindows] -result {couldn't open socket: not owner}
915 test socket_$af-5.2 {byte order problems, socket numbers, htons} -body {
916 if {![catch {socket -server dodo 0x10000} msg]} {
918 return {port resolution problem, should be disallowed}
920 return {couldn't open socket: port number too high}
921 } -constraints [list socket supported_$af] -result {couldn't open socket: port number too high}
922 test socket_$af-5.3 {byte order problems, socket numbers, htons} -body {
923 if {![catch {socket -server dodo 21} msg]} {
925 return {htons problem, should be disallowed, are you running as SU?}
927 return {couldn't open socket: not owner}
928 } -constraints [list socket supported_$af unix notRoot notOSX notWindows] -result {couldn't open socket: not owner}
930 test socket_$af-6.1 {accept callback error} -constraints [list socket supported_$af stdio] -setup {
931 proc myHandler {msg options} {
934 set handler [interp bgerror {}]
935 interp bgerror {} [namespace which myHandler]
936 file delete $path(script)
938 set f [open $path(script) w]
939 puts $f [list set localhost $localhost]
942 socket $localhost $port
945 set f [open "|[list [interpreter] $path(script)]" r+]
946 proc accept {s a p} {expr {10 / 0}}
947 set s [socket -server accept -myaddr $localhost 0]
948 puts $f [lindex [fconfigure $s -sockname] 2]
950 set timer [after 10000 "set x timed_out"]
956 interp bgerror {} $handler
957 } -result {divide by zero}
959 test socket_$af-6.2 {
960 readable fileevent on server socket
962 set sock [socket -server dummy 0]
963 } -constraints [list socket supported_$af] -body {
964 fileevent $sock readable dummy
967 } -returnCodes 1 -result "channel is not readable"
969 test socket_$af-6.3 {writable fileevent on server socket} -setup {
970 set sock [socket -server dummy 0]
971 } -constraints [list socket supported_$af] -body {
972 fileevent $sock writable dummy
975 } -returnCodes 1 -result "channel is not writable"
977 test socket_$af-7.1 {testing socket specific options} -setup {
978 file delete $path(script)
979 set f [open $path(script) w]
981 set ss [socket -server accept 0]
987 puts [lindex [fconfigure $ss -sockname] 2]
988 set timer [after 10000 "set x timed_out"]
993 set f [open "|[list [interpreter] $path(script)]" r]
997 } -constraints [list socket supported_$af stdio] -body {
998 set s [socket $localhost $listen]
999 set p [fconfigure $s -peername]
1001 lappend l [string compare [lindex $p 0] $localhost]
1002 lappend l [string compare [lindex $p 2] $listen]
1003 lappend l [llength $p]
1007 test socket_$af-7.2 {testing socket specific options} -setup {
1008 file delete $path(script)
1009 set f [open $path(script) w]
1010 puts $f [list set ::tcl::unsupported::socketAF $::tcl::unsupported::socketAF]
1012 set ss [socket -server accept 0]
1018 puts [lindex [fconfigure $ss -sockname] 2]
1019 set timer [after 10000 "set x timed_out"]
1024 set f [open "|[list [interpreter] $path(script)]" r]
1027 } -constraints [list socket supported_$af stdio] -body {
1028 set s [socket $localhost $listen]
1029 set p [fconfigure $s -sockname]
1032 [regexp {^(127\.0\.0\.1|0\.0\.0\.0|::1)$} [lindex $p 0]] \
1033 [expr {[lindex $p 2] == $listen}]
1037 test socket_$af-7.3 {testing socket specific options} -constraints [list socket supported_$af] -body {
1038 set s [socket -server accept -myaddr $localhost 0]
1039 set l [fconfigure $s]
1044 test socket_$af-7.4 {testing socket specific options} -constraints [list socket supported_$af] -setup {
1045 set timer [after 10000 "set x timed_out"]
1048 set s [socket -server accept -myaddr $localhost 0]
1049 proc accept {s a p} {
1051 set x [fconfigure $s -sockname]
1054 set listen [lindex [fconfigure $s -sockname] 2]
1055 set s1 [socket $localhost $listen]
1057 lappend l [expr {[lindex $x 2] == $listen}] [llength $x]
1063 test socket_$af-7.5 {testing socket specific options} -setup {
1064 set timer [after 10000 "set x timed_out"]
1066 } -constraints [list socket supported_$af unixOrWin] -body {
1067 set s [socket -server accept 0]
1068 proc accept {s a p} {
1070 set x [fconfigure $s -sockname]
1073 set listen [lindex [fconfigure $s -sockname] 2]
1074 set s1 [socket $localhost $listen]
1076 lappend l [lindex $x 0] [expr {[lindex $x 2] == $listen}] [llength $x]
1081 } -result [list $localhost 1 3]
1083 test socket_$af-8.1 {testing -async flag on sockets} -constraints [list socket supported_$af] -body {
1084 # NOTE: This test may fail on some Solaris 2.4 systems. If it does, check
1085 # that you have these patches installed (using showrev -p):
1087 # 101907-05, 101925-02, 101945-14, 101959-03, 101969-05, 101973-03,
1088 # 101977-03, 101981-02, 101985-01, 102001-03, 102003-01, 102007-01,
1089 # 102011-02, 102024-01, 102039-01, 102044-01, 102048-01, 102062-03,
1090 # 102066-04, 102070-01, 102105-01, 102153-03, 102216-01, 102232-01,
1091 # 101878-03, 101879-01, 101880-03, 101933-01, 101950-01, 102030-01,
1092 # 102057-08, 102140-01, 101920-02, 101921-09, 101922-07, 101923-03
1094 # If after installing these patches you are still experiencing a problem,
1095 # please email jyl@eng.sun.com. We have not observed this failure on
1096 # Solaris 2.5, so another option (instead of installing these patches) is
1097 # to upgrade to Solaris 2.5.
1098 set s [socket -server accept -myaddr $localhost 0]
1099 proc accept {s a p} {
1105 set s1 [socket -async $localhost [lindex [fconfigure $s -sockname] 2]]
1113 test socket_$af-9.1 {testing spurious events} -constraints [list socket supported_$af] -setup {
1117 set timer [after 10000 "set done timed_out"]
1119 proc readlittle {s} {
1120 global spurious done len
1122 if {[string length $l] == 0} {
1130 incr len [string length $l]
1133 proc accept {s a p} {
1134 fconfigure $s -buffering none -blocking off
1135 fileevent $s readable [list readlittle $s]
1137 set s [socket -server accept -myaddr $localhost 0]
1138 set c [socket $localhost [lindex [fconfigure $s -sockname] 2]]
1139 puts -nonewline $c 01234567890123456789012345678901234567890123456789
1147 test socket_$af-9.2 {testing async write, fileevents, flush on close} -constraints [list socket supported_$af] -setup {
1149 for {set i 0} {$i < 5} {incr i} {set firstblock "a$firstblock$firstblock"}
1151 for {set i 0} {$i < 16} {incr i} {
1152 set secondblock "b$secondblock$secondblock"
1154 set timer [after 10000 "set done timed_out"]
1155 set l [socket -server accept -myaddr $localhost 0]
1156 proc accept {s a p} {
1157 fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
1159 fileevent $s readable "readable $s"
1163 fileevent $s readable {}
1164 after idle respond $s
1168 puts -nonewline $s $firstblock
1169 after idle writedata $s
1171 proc writedata {s} {
1173 puts -nonewline $s $secondblock
1177 set s [socket $localhost [lindex [fconfigure $l -sockname] 2]]
1178 fconfigure $s -blocking 0 -trans lf -buffering line
1184 incr count [string length $l]
1190 fileevent $s readable "readit $s"
1197 test socket_$af-9.3 {testing EOF stickyness} -constraints [list socket supported_$af] -setup {
1200 proc write_then_close {s} {
1204 proc accept {s a p} {
1205 fconfigure $s -buffering line -translation lf
1206 fileevent $s writable "write_then_close $s"
1208 set s [socket -server accept -myaddr $localhost 0]
1210 proc count_to_eof {s} {
1218 set count {eof is sticky}
1222 proc timerproc {s} {
1225 set count {timer went off, eof is not sticky}
1228 set c [socket $localhost [lindex [fconfigure $s -sockname] 2]]
1229 fconfigure $c -blocking off -buffering line -translation lf
1230 fileevent $c readable "count_to_eof $c"
1231 set timer [after 1000 timerproc $c]
1237 } -result {eof is sticky}
1241 test socket_$af-10.1 {testing socket accept callback error handling} \
1242 -constraints [list socket supported_$af] -setup {
1244 proc myHandler {msg options} {
1247 set handler [interp bgerror {}]
1248 interp bgerror {} [namespace which myHandler]
1250 set s [socket -server accept -myaddr $localhost 0]
1251 proc accept {s a p} {close $s; error}
1252 set c [socket $localhost [lindex [fconfigure $s -sockname] 2]]
1258 interp bgerror {} $handler
1261 test socket_$af-11.1 {tcp connection} -setup {
1262 set port [sendCommand {
1263 set server [socket -server accept 0]
1264 proc accept {s a p} {
1270 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1271 set s [socket $remoteServerIP $port]
1275 sendCommand {close $server}
1277 test socket_$af-11.2 {client specifies its port} -setup {
1278 set lport [randport]
1279 set rport [sendCommand {
1280 set server [socket -server accept 0]
1281 proc accept {s a p} {
1287 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1288 set s [socket -myport $lport $remoteServerIP $rport]
1290 expr {$r==$lport ? "ok" : "broken: $r != $port"}
1293 sendCommand {close $server}
1295 test socket_$af-11.3 {trying to connect, no server} -body {
1297 if {![catch {set s [socket $remoteServerIp [randport]]}]} {
1298 if {![catch {gets $s}]} {
1304 } -constraints [list socket supported_$af doTestsWithRemoteServer] -result ok
1305 test socket_$af-11.4 {remote echo, one line} -setup {
1306 set port [sendCommand {
1307 set server [socket -server accept 0]
1308 proc accept {s a p} {
1309 fileevent $s readable [list echo $s]
1310 fconfigure $s -buffering line -translation crlf
1322 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1323 set f [socket $remoteServerIP $port]
1324 fconfigure $f -translation crlf -buffering line
1329 sendCommand {close $server}
1331 test socket_$af-11.5 {remote echo, 50 lines} -setup {
1332 set port [sendCommand {
1333 set server [socket -server accept 0]
1334 proc accept {s a p} {
1335 fileevent $s readable [list echo $s]
1336 fconfigure $s -buffering line -translation crlf
1348 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1349 set f [socket $remoteServerIP $port]
1350 fconfigure $f -translation crlf -buffering line
1351 for {set cnt 0} {$cnt < 50} {incr cnt} {
1352 puts $f "hello, $cnt"
1353 if {[gets $f] != "hello, $cnt"} {
1360 sendCommand {close $server}
1362 test socket_$af-11.6 {socket conflict} -setup {
1363 set s1 [socket -server accept -myaddr $localhost 0]
1364 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1365 set s2 [socket -server accept -myaddr $localhost [getPort $s1]]
1366 list [getPort $s2] [close $s2]
1369 } -returnCodes error -result {couldn't open socket: address already in use}
1370 test socket_$af-11.7 {server with several clients} -setup {
1371 set port [sendCommand {
1372 set server [socket -server accept 0]
1373 proc accept {s a p} {
1374 fconfigure $s -buffering line
1375 fileevent $s readable [list echo $s]
1387 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1388 set s1 [socket $remoteServerIP $port]
1389 fconfigure $s1 -buffering line
1390 set s2 [socket $remoteServerIP $port]
1391 fconfigure $s2 -buffering line
1392 set s3 [socket $remoteServerIP $port]
1393 fconfigure $s3 -buffering line
1394 for {set i 0} {$i < 100} {incr i} {
1407 sendCommand {close $server}
1409 test socket_$af-11.8 {client with several servers} -setup {
1410 lassign [sendCommand {
1411 set s1 [socket -server "accept server1" 0]
1412 set s2 [socket -server "accept server2" 0]
1413 set s3 [socket -server "accept server3" 0]
1414 proc accept {mp s a p} {
1418 list [getPort $s1] [getPort $s2] [getPort $s3]
1420 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1421 set s1 [socket $remoteServerIP $p1]
1422 set s2 [socket $remoteServerIP $p2]
1423 set s3 [socket $remoteServerIP $p3]
1424 list [gets $s1] [gets $s1] [eof $s1] [gets $s2] [gets $s2] [eof $s2] \
1425 [gets $s3] [gets $s3] [eof $s3]
1435 } -result {server1 {} 1 server2 {} 1 server3 {} 1}
1436 test socket_$af-11.9 {accept callback error} -constraints [list socket supported_$af doTestsWithRemoteServer] -setup {
1437 proc myHandler {msg options} {
1440 set handler [interp bgerror {}]
1441 interp bgerror {} [namespace which myHandler]
1442 set timer [after 10000 "set x timed_out"]
1444 set s [socket -server accept 0]
1445 proc accept {s a p} {expr {10 / 0}}
1446 sendCommand "set port [getPort $s]"
1449 set peername [fconfigure $callerSocket -peername]
1450 set s [socket [lindex $peername 0] $port]
1462 interp bgerror {} $handler
1463 } -result {divide by zero}
1464 test socket_$af-11.10 {testing socket specific options} -setup {
1465 set port [sendCommand {
1466 set server [socket -server accept 0]
1467 proc accept {s a p} {close $s}
1470 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1471 set s [socket $remoteServerIP $port]
1472 set p [fconfigure $s -peername]
1473 set n [fconfigure $s -sockname]
1474 list [expr {[lindex $p 2] == $port}] [llength $p] [llength $n]
1477 sendCommand {close $server}
1479 test socket_$af-11.11 {testing spurious events} -setup {
1480 set port [sendCommand {
1481 set server [socket -server accept 0]
1482 proc accept {s a p} {
1483 fconfigure $s -translation "auto lf"
1484 after idle writesome $s
1486 proc writesome {s} {
1487 for {set i 0} {$i < 100} {incr i} {
1488 puts $s "line $i from remote server"
1497 set timer [after 40000 "set done timed_out"]
1498 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1499 proc readlittle {s} {
1500 global spurious done len
1502 if {[string length $l] == 0} {
1510 incr len [string length $l]
1513 set c [socket $remoteServerIP $port]
1514 fileevent $c readable "readlittle $c"
1516 list $spurious $len $done
1519 sendCommand {close $server}
1520 } -result {0 2690 1}
1521 test socket_$af-11.12 {testing EOF stickyness} -constraints [list socket supported_$af doTestsWithRemoteServer] -setup {
1524 set port [sendCommand {
1525 set server [socket -server accept 0]
1526 proc accept {s a p} {
1533 set done {timed_out, EOF is not sticky}
1536 set after_id [after 1000 timed_out]
1544 set done {EOF is sticky}
1549 set c [socket $remoteServerIP $port]
1550 fileevent $c readable [list count_up $c]
1554 after cancel $after_id
1555 sendCommand {close $server}
1556 } -result {EOF is sticky}
1557 test socket_$af-11.13 {testing async write, async flush, async close} -setup {
1558 set port [sendCommand {
1560 for {set i 0} {$i < 5} {incr i} {
1561 set firstblock "a$firstblock$firstblock"
1564 for {set i 0} {$i < 16} {incr i} {
1565 set secondblock "b$secondblock$secondblock"
1567 set l [socket -server accept 0]
1568 proc accept {s a p} {
1569 fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
1571 fileevent $s readable "readable $s"
1575 fileevent $s readable {}
1576 after idle respond $s
1580 puts -nonewline $s $firstblock
1581 after idle writedata $s
1583 proc writedata {s} {
1585 puts -nonewline $s $secondblock
1590 set timer [after 10000 "set done timed_out"]
1591 } -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
1595 incr count [string length $l]
1601 set s [socket $remoteServerIP $port]
1602 fconfigure $s -blocking 0 -trans lf -buffering line
1605 fileevent $s readable "readit $s"
1610 sendCommand {close $l}
1613 set path(script1) [makeFile {} script1]
1614 set path(script2) [makeFile {} script2]
1616 test socket_$af-12.1 {testing inheritance of server sockets} -setup {
1617 file delete $path(script1)
1618 file delete $path(script2)
1619 # Script1 is just a 10 second delay. If the server socket is inherited, it
1620 # will be held open for 10 seconds
1621 set f [open $path(script1) w]
1623 fileevent stdin readable exit
1628 # Script2 creates the server socket, launches script1, and exits.
1629 # The server socket will now be closed unless script1 inherited it.
1630 set f [open $path(script2) w]
1631 puts $f [list set tcltest [interpreter]]
1632 puts $f [list set delay $path(script1)]
1633 puts $f [list set localhost $localhost]
1635 set f [socket -server accept -myaddr $localhost 0]
1636 proc accept { file addr port } {
1639 exec $tcltest $delay &
1640 puts [lindex [fconfigure $f -sockname] 2]
1645 } -constraints [list socket supported_$af stdio exec] -body {
1646 # Launch script2 and wait 5 seconds
1647 ### exec [interpreter] script2 &
1648 set p [open "|[list [interpreter] $path(script2)]" r]
1649 # If we can still connect to the server, the socket got inherited.
1650 if {[catch {close [socket $localhost $listen]}]} {
1651 return {server socket was not inherited}
1653 return {server socket was inherited}
1657 } -result {server socket was not inherited}
1658 test socket_$af-12.2 {testing inheritance of client sockets} -setup {
1659 file delete $path(script1)
1660 file delete $path(script2)
1661 # Script1 is just a 20 second delay. If the server socket is inherited, it
1662 # will be held open for 20 seconds
1663 set f [open $path(script1) w]
1665 fileevent stdin readable exit
1670 # Script2 opens the client socket and writes to it. It then launches
1671 # script1 and exits. If the child process inherited the client socket, the
1672 # socket will still be open.
1673 set f [open $path(script2) w]
1674 puts $f [list set tcltest [interpreter]]
1675 puts $f [list set delay $path(script1)]
1676 puts $f [list set localhost $localhost]
1679 set f [socket $localhost $port]
1680 exec $tcltest $delay &
1686 # If the socket doesn't hit end-of-file in 10 seconds, the script1 process
1687 # must have inherited the client.
1689 set after [after 10000 {set x "client socket was inherited"}]
1690 } -constraints [list socket supported_$af stdio exec] -body {
1691 # Create the server socket
1692 set server [socket -server accept -myaddr $localhost 0]
1693 proc accept { file host port } {
1694 # When the client connects, establish the read handler
1697 fileevent $file readable [list getdata $file]
1698 fconfigure $file -buffering line -blocking 0
1701 proc getdata { file } {
1702 # Read handler on the accepted socket.
1704 set status [catch {read $file} data]
1706 set x "read failed, error was $data"
1707 } elseif {$data ne ""} {
1708 } elseif {[fblocked $file]} {
1709 } elseif {[eof $file]} {
1710 set x "client socket was not inherited"
1712 set x "impossible case"
1715 # Launch the script2 process
1716 ### exec [interpreter] script2 &
1717 set p [open "|[list [interpreter] $path(script2)]" w]
1718 puts $p [lindex [fconfigure $server -sockname] 2] ; flush $p
1722 fconfigure $f -blocking 1
1726 } -result {client socket was not inherited}
1727 test socket_$af-12.3 {testing inheritance of accepted sockets} -setup {
1728 file delete $path(script1)
1729 file delete $path(script2)
1730 set f [open $path(script1) w]
1732 fileevent stdin readable exit
1737 set f [open $path(script2) w]
1738 puts $f [list set tcltest [interpreter]]
1739 puts $f [list set delay $path(script1)]
1740 puts $f [list set localhost $localhost]
1742 set server [socket -server accept -myaddr $localhost 0]
1743 proc accept { file host port } {
1744 global tcltest delay
1745 puts $file {test data on socket}
1746 exec $tcltest $delay &
1749 puts stdout [lindex [fconfigure $server -sockname] 2]
1753 } -constraints [list socket supported_$af stdio exec] -body {
1754 # Launch the script2 process and connect to it. See how long the socket
1756 ## exec [interpreter] script2 &
1757 set p [open "|[list [interpreter] $path(script2)]" r]
1759 set f [socket $localhost $listen]
1760 fconfigure $f -buffering full -blocking 0
1761 fileevent $f readable [list getdata $f]
1762 # If the socket is still open after 5 seconds, the script1 process must
1763 # have inherited the accepted socket.
1765 set after [after 5000 [list set x "accepted socket was inherited"]]
1766 proc getdata { file } {
1767 # Read handler on the client socket.
1770 set status [catch {read $file} data]
1772 set x "read failed, error was $data"
1773 } elseif {[string compare {} $data]} {
1774 } elseif {[fblocked $file]} {
1775 } elseif {[eof $file]} {
1776 set x "accepted socket was not inherited"
1778 set x "impossible case"
1785 fconfigure $f -blocking 1
1789 } -result {accepted socket was not inherited}
1791 test socket_$af-13.1 {Testing use of shared socket between two threads} -body {
1793 set serverthread [thread::create -preserved [string map [list @localhost@ $localhost] {
1794 set f [socket -server accept -myaddr @localhost@ 0]
1795 set listen [lindex [fconfigure $f -sockname] 2]
1796 proc accept {s a p} {
1797 fileevent $s readable [list echo $s]
1798 fconfigure $s -buffering line
1816 set port [thread::send $serverthread {set listen}]
1817 set s [socket $localhost $port]
1818 fconfigure $s -buffering line
1824 thread::release $serverthread
1825 append result " " [llength [thread::names]]
1826 } -result {hello 1} -constraints [list socket supported_$af thread]
1828 proc transf_test {{testmode transfer} {maxIter 1000} {maxTime 10000}} {
1831 set ::testmode $testmode
1834 # if binding on port 0 is not possible (system related, blocked on ISPs etc):
1835 if {[catch {close [socket -async $::localhost $port]}]} {
1836 # simplest server on random port (immediatelly closing a connect):
1838 set srvsock [socket -server {apply {{ch args} {close $ch}}} -myaddr $::localhost $port]
1839 # socket on windows has some issues yet (e. g. bug [b6d0d8cc2c]), so we simply decrease iteration count (to 1/4):
1840 if {$::tcl_platform(platform) eq "windows" && $maxIter > 50} {
1841 set ::count [expr {$maxIter / 4 * 3 - 1}]; # bypass 3/4 iterations
1844 tcltest::DebugPuts 2 "== test \[$::localhost\]:$port $testmode =="
1845 set ::parent [thread::id]
1846 # helper thread creating async connection and initiating transfer (detach) to parent:
1847 set ::helper [thread::create]
1848 thread::send -async $::helper [list \
1849 lassign [list $::parent $::localhost $port $testmode] \
1850 ::parent ::localhost ::port ::testmode
1852 thread::send -async $::helper {
1853 set ::helper [thread::id]
1854 proc iteration {args} {
1855 set fd [socket -async $::localhost $::port]
1856 if {"helper-writable" in $::testmode} {;# to test both sides during connect
1857 fileevent $fd writable [list apply {{fd} {
1858 if {[thread::id] ne $::helper} {
1859 thread::send -async $::parent {set ::count "ERROR: invalid thread, $::helper is expecting"}
1866 thread::send -async $::parent [list transf_parent $fd {*}$args]
1870 # parent proc commiting transfer attempt (attach) and checking acquire was successful:
1871 proc transf_parent {fd args} {
1872 tcltest::DebugPuts 2 "** trma / $::count ** $args **"
1874 if {"parent-close" in $::testmode} {;# to test close during connect
1875 set ::count $::count
1879 fileevent $fd writable [list apply {{fd} {
1880 if {[thread::id] ne $::parent} {
1881 thread::send -async $::parent {set ::count "ERROR: invalid thread, $::parent is expecting"}
1885 set ::count $::count
1889 # repeat maxIter times (up to maxTime ms as timeout):
1890 set tout [after $maxTime {set ::count "TIMEOUT"}]
1893 if {![string is integer $::count]} {
1894 # if timeout just skip (test was successful until now):
1895 if {$::count eq "TIMEOUT"} {::tcltest::Skip "timing issue"}
1898 if {[incr ::count] >= $maxIter} break
1899 tcltest::DebugPuts 2 "** iter / $::count **"
1900 thread::send -async $::helper [list iteration nr $::count]
1905 catch {after cancel $tout}
1906 if {$srvsock ne {}} {close $srvsock}
1907 if {[info exists ::helper]} {thread::release -wait $::helper}
1908 tcltest::DebugPuts 2 "== stop / $::count =="
1909 unset -nocomplain ::count ::testmode ::parent ::helper
1912 test socket_$af-13.2.tr1 {Testing socket transfer between threads during async connect} -body {
1913 transf_test {transfer} 1000
1914 } -result 1000 -constraints [list socket supported_$af thread]
1915 test socket_$af-13.2.tr2 {Testing socket transfer between threads during async connect} -body {
1916 transf_test {transfer helper-writable} 100
1917 } -result 100 -constraints [list socket supported_$af thread]
1918 test socket_$af-13.2.cl1 {Testing socket transfer between threads during async connect} -body {
1919 transf_test {parent-close} 100
1920 } -result 100 -constraints [list socket supported_$af thread]
1921 test socket_$af-13.2.cl2 {Testing socket transfer between threads during async connect} -body {
1922 transf_test {parent-close helper-writable} 100
1923 } -result 100 -constraints [list socket supported_$af thread]
1924 catch {rename transf_parent {}}
1925 rename transf_test {}
1927 # ----------------------------------------------------------------------
1933 if {$remoteProcChan ne ""} {
1934 catch {sendCommand exit}
1936 catch {close $commandSocket}
1937 catch {close $remoteProcChan}
1939 unset ::tcl::unsupported::socketAF
1940 test socket-14.0.0 {[socket -async] when server only listens on IPv4} -setup {
1941 proc accept {s a p} {
1947 set server [socket -server accept -myaddr 127.0.0.1 0]
1948 set port [lindex [fconfigure $server -sockname] 2]
1949 } -constraints {socket supported_inet localhost_v4} -body {
1950 set client [socket -async localhost $port]
1951 set after [after $latency {set x [fconfigure $client -error]}]
1955 catch {after cancel $after}
1956 catch {close $server}
1957 catch {close $client}
1960 test socket-14.0.1 {[socket -async] when server only listens on IPv6} -setup {
1961 proc accept {s a p} {
1967 set server [socket -server accept -myaddr ::1 0]
1968 set port [lindex [fconfigure $server -sockname] 2]
1969 } -constraints {socket supported_inet6 localhost_v6} -body {
1970 set client [socket -async localhost $port]
1971 set after [after $latency {set x [fconfigure $client -error]}]
1975 catch {after cancel $after}
1976 catch {close $server}
1977 catch {close $client}
1980 test socket-14.1 {[socket -async] fileevent while still connecting} -setup {
1981 proc accept {s a p} {
1987 set server [socket -server accept -myaddr localhost 0]
1988 set port [lindex [fconfigure $server -sockname] 2]
1990 } -constraints socket -body {
1991 set client [socket -async localhost $port]
1992 fileevent $client writable {
1993 lappend x [fconfigure $client -error]
1994 fileevent $client writable {}
1996 set after [after $latency {lappend x timeout}]
1997 while {[llength $x] < 2 && "timeout" ni $x} {
2000 lsort $x; # we only want to see both events, the order doesn't matter
2002 catch {after cancel $after}
2003 catch {close $server}
2004 catch {close $client}
2007 test socket-14.2 {[socket -async] fileevent connection refused} -setup {
2008 set after [after $latency set x timeout]
2010 set client [socket -async localhost [randport]]
2011 fileevent $client writable {set x ok}
2013 lappend x [fconfigure $client -error]
2014 } -constraints socket -cleanup {
2015 catch {after cancel $after}
2016 catch {close $client}
2017 unset -nocomplain x after client
2018 } -result {ok {connection refused}}
2019 test socket-14.3 {[socket -async] when server only listens on IPv6} -setup {
2020 proc accept {s a p} {
2026 set server [socket -server accept -myaddr ::1 0]
2027 set port [lindex [fconfigure $server -sockname] 2]
2028 } -constraints {socket supported_inet6 localhost_v6} -body {
2029 set client [socket -async localhost $port]
2030 set after [after $latency {set x [fconfigure $client -error]}]
2034 catch {after cancel $after}
2035 catch {close $server}
2036 catch {close $client}
2039 test socket-14.4 {[socket -async] and both, readdable and writable fileevents} -setup {
2040 proc accept {s a p} {
2044 set server [socket -server accept -myaddr localhost 0]
2045 set port [lindex [fconfigure $server -sockname] 2]
2047 } -constraints socket -body {
2048 set client [socket -async localhost $port]
2049 fileevent $client writable {
2050 lappend x [fconfigure $client -error]
2051 fileevent $client writable {}
2053 fileevent $client readable {lappend x [gets $client]}
2054 set after [after $latency {lappend x timeout}]
2055 while {[llength $x] < 2 && "timeout" ni $x} {
2060 catch {after cancel $after}
2061 catch {close $client}
2062 catch {close $server}
2065 # FIXME: we should also have an IPv6 counterpart of this
2066 test socket-14.5 {[socket -async] which fails before any connect() can be made} -body {
2067 # address from rfc5737
2068 socket -async -myaddr 192.0.2.42 127.0.0.1 [randport]
2069 } -constraints {socket supported_inet notOSX} -returnCodes 1 \
2070 -result {couldn't open socket: cannot assign requested address}
2071 test socket-14.6.0 {[socket -async] with no event loop and server listening on IPv4} -setup {
2072 proc accept {s a p} {
2078 set server [socket -server accept -myaddr 127.0.0.1 0]
2079 set port [lindex [fconfigure $server -sockname] 2]
2081 } -constraints {socket supported_inet localhost_v4} -body {
2082 set client [socket -async localhost $port]
2083 for {set i 0} {$i < 50} {incr i } {
2086 lappend x [gets $client]
2093 catch {close $server}
2094 catch {close $client}
2097 test socket-14.6.1 {[socket -async] with no event loop and server listening on IPv6} -setup {
2098 proc accept {s a p} {
2104 set server [socket -server accept -myaddr ::1 0]
2105 set port [lindex [fconfigure $server -sockname] 2]
2107 } -constraints {socket supported_inet6 localhost_v6} -body {
2108 set client [socket -async localhost $port]
2109 for {set i 0} {$i < 50} {incr i } {
2112 lappend x [gets $client]
2119 catch {close $server}
2120 catch {close $client}
2123 test socket-14.7.0 {pending [socket -async] and blocking [gets], server is IPv4} -setup {
2125 fileevent stdin readable exit
2126 set server [socket -server accept -myaddr 127.0.0.1 0]
2127 proc accept {s h p} {puts $s ok; close $s; set ::x 1}
2128 puts [lindex [fconfigure $server -sockname] 2]
2132 set fd [open |[list [interpreter] script] RDWR]
2134 } -constraints {socket supported_inet localhost_v4 notOSX} -body {
2135 set sock [socket -async localhost $port]
2136 list [fconfigure $sock -error] [gets $sock] [fconfigure $sock -error]
2141 } -result {{} ok {}}
2142 test socket-14.7.1 {pending [socket -async] and blocking [gets], server is IPv6} -setup {
2144 fileevent stdin readable exit
2145 set server [socket -server accept -myaddr ::1 0]
2146 proc accept {s h p} {puts $s ok; close $s; set ::x 1}
2147 puts [lindex [fconfigure $server -sockname] 2]
2151 set fd [open |[list [interpreter] script] RDWR]
2153 } -constraints {socket supported_inet6 localhost_v6 notOSX} -body {
2154 set sock [socket -async localhost $port]
2155 list [fconfigure $sock -error] [gets $sock] [fconfigure $sock -error]
2160 } -result {{} ok {}}
2161 test socket-14.7.2 {pending [socket -async] and blocking [gets], no listener} -setup {
2162 set sock [socket -server error 0]
2163 set unusedPort [lindex [fconfigure $sock -sockname] 2]
2166 set sock [socket -async localhost $unusedPort]
2167 catch {gets $sock} x
2168 list $x [fconfigure $sock -error] [fconfigure $sock -error]
2169 } -constraints {socket notOSX} -cleanup {
2171 } -match glob -result {{error reading "sock*": socket is not connected} {connection refused} {}}
2172 test socket-14.8.0 {pending [socket -async] and nonblocking [gets], server is IPv4} -setup {
2174 fileevent stdin readable exit
2175 set server [socket -server accept -myaddr 127.0.0.1 0]
2176 proc accept {s h p} {puts $s ok; close $s; set ::x 1}
2177 puts [lindex [fconfigure $server -sockname] 2]
2181 set fd [open |[list [interpreter] script] RDWR]
2183 } -constraints {socket supported_inet localhost_v4} -body {
2184 set sock [socket -async localhost $port]
2185 fconfigure $sock -blocking 0
2186 for {set i 0} {$i < 50} {incr i } {
2187 if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
2196 test socket-14.8.1 {pending [socket -async] and nonblocking [gets], server is IPv6} -setup {
2198 fileevent stdin readable exit
2199 set server [socket -server accept -myaddr ::1 0]
2200 proc accept {s h p} {puts $s ok; close $s; set ::x 1}
2201 puts [lindex [fconfigure $server -sockname] 2]
2205 set fd [open |[list [interpreter] script] RDWR]
2207 } -constraints {socket supported_inet6 localhost_v6} -body {
2208 set sock [socket -async localhost $port]
2209 fconfigure $sock -blocking 0
2210 for {set i 0} {$i < 50} {incr i } {
2211 if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
2220 test socket-14.8.2 {pending [socket -async] and nonblocking [gets], no listener} -body {
2221 set sock [socket -async localhost [randport]]
2222 fconfigure $sock -blocking 0
2223 for {set i 0} {$i < 50} {incr i } {
2224 if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
2227 list $x [fconfigure $sock -error] [fconfigure $sock -error]
2228 } -constraints socket -cleanup {
2230 } -match glob -result {{error reading "sock*": socket is not connected} {connection refused} {}}
2231 test socket-14.9.0 {pending [socket -async] and blocking [puts], server is IPv4} -setup {
2233 fileevent stdin readable exit
2235 set server [socket -server accept -myaddr 127.0.0.1 0]
2236 proc accept {s h p} {set ::x $s}
2237 puts [lindex [fconfigure $server -sockname] 2]
2242 set fd [open |[list [interpreter] script] RDWR]
2244 } -constraints {socket supported_inet localhost_v4 notOSX} -body {
2245 set sock [socket -async localhost $port]
2248 list [fconfigure $sock -error] [gets $fd]
2254 test socket-14.9.1 {pending [socket -async] and blocking [puts], server is IPv6} -setup {
2256 fileevent stdin readable exit
2258 set server [socket -server accept -myaddr ::1 0]
2259 proc accept {s h p} {set ::x $s}
2260 puts [lindex [fconfigure $server -sockname] 2]
2265 set fd [open |[list [interpreter] script] RDWR]
2267 } -constraints {socket supported_inet6 localhost_v6 notOSX} -body {
2268 set sock [socket -async localhost $port]
2271 list [fconfigure $sock -error] [gets $fd]
2277 test socket-14.10.0 {pending [socket -async] and nonblocking [puts], server is IPv4} -setup {
2279 fileevent stdin readable exit
2280 set server [socket -server accept -myaddr 127.0.0.1 0]
2281 proc accept {s h p} {set ::x $s}
2282 puts [lindex [fconfigure $server -sockname] 2]
2287 set fd [open |[list [interpreter] script] RDWR]
2289 set after [after $latency set x timeout]
2290 } -constraints {socket supported_inet localhost_v4} -body {
2291 set sock [socket -async localhost $port]
2292 fconfigure $sock -blocking 0
2295 fileevent $fd readable {set x 1}
2297 list [fconfigure $sock -error] [gets $fd]
2304 test socket-14.10.1 {pending [socket -async] and nonblocking [puts], server is IPv6} -setup {
2306 fileevent stdin readable exit
2307 set server [socket -server accept -myaddr ::1 0]
2308 proc accept {s h p} {set ::x $s}
2309 puts [lindex [fconfigure $server -sockname] 2]
2314 set fd [open |[list [interpreter] script] RDWR]
2316 set after [after $latency set x timeout]
2317 } -constraints {socket supported_inet6 localhost_v6} -body {
2318 set sock [socket -async localhost $port]
2319 fconfigure $sock -blocking 0
2322 fileevent $fd readable {set x 1}
2324 list [fconfigure $sock -error] [gets $fd]
2331 test socket-14.11.0 {pending [socket -async] and nonblocking [puts], no listener, no flush} -setup {
2332 set after [after $latency set x timeout]
2334 set sock [socket -async localhost [randport]]
2335 fconfigure $sock -blocking 0
2337 fileevent $sock writable {set x 1}
2340 } -constraints socket -cleanup {
2344 } -result {socket is not connected} -returnCodes 1
2345 test socket-14.11.1 {pending [socket -async] and nonblocking [puts], no listener, flush} -setup {
2346 set after [after $latency set x timeout]
2348 set sock [socket -async localhost [randport]]
2349 fconfigure $sock -blocking 0
2352 fileevent $sock writable {set x 1}
2355 } -constraints {socket nonPortable} -cleanup {
2356 after cancel $timeout
2359 } -result {socket is not connected} -returnCodes 1
2360 test socket-14.12 {[socket -async] background progress triggered by [fconfigure -error]} -body {
2361 set s [socket -async localhost [randport]]
2362 for {set i 0} {$i < 50} {incr i} {
2363 set x [fconfigure $s -error]
2368 } -constraints socket -cleanup {
2370 unset -nocomplain x s
2371 } -result {connection refused}
2372 test socket-14.13 {testing writable event when quick failure} -body {
2373 # Test for bug 336441ed59 where a quick background fail was ignored
2375 # Test only for windows as socket -async 255.255.255.255 fails
2378 # The following connect should fail very quickly
2379 set a1 [after $latency {set x timeout}]
2380 set s [socket -async 255.255.255.255 43434]
2381 fileevent $s writable {set x writable}
2384 } -constraints {socket win supported_inet} -cleanup {
2388 test socket-14.14 {testing fileevent readable on failed async socket connect} -body {
2389 # Test for bug 581937ab1e
2390 set a1 [after $latency {set x timeout}]
2391 # This connect should fail
2392 set s [socket -async localhost [randport]]
2393 fileevent $s readable {set x readable}
2396 } -constraints socket -cleanup {
2400 test socket-14.15 {blocking read on async socket should not trigger event handlers} -setup {
2401 set subprocess [open "|[list [interpreter]]" r+]
2402 fconfigure $subprocess -blocking 0 -buffering none
2403 } -constraints socket -body {
2405 set s [socket -async localhost [randport]]
2407 fileevent $s writable {set x fail}
2413 set after [after $latency set x timeout]
2414 fileevent $subprocess readable [list gets $subprocess x]
2418 catch {after cancel $after}
2419 if {![testConstraint win]} {
2420 catch {exec kill [pid $subprocess]}
2422 catch {close $subprocess}
2425 # v4 and v6 is required to prevent that the async connect does not terminate
2426 # before the fconfigure command. There is always an additional ip to try.
2427 test socket-14.16 {empty -peername while [socket -async] connecting} -body {
2428 set client [socket -async localhost [randport]]
2429 fconfigure $client -peername
2430 } -constraints {socket localhost_v4 localhost_v6 notOSX} -cleanup {
2431 catch {close $client}
2433 # v4 and v6 is required to prevent that the async connect does not terminate
2434 # before the fconfigure command. There is always an additional ip to try.
2435 test socket-14.17 {empty -sockname while [socket -async] connecting} -body {
2436 set client [socket -async localhost [randport]]
2437 fconfigure $client -sockname
2438 } -constraints {socket localhost_v4 localhost_v6 notOSX} -cleanup {
2439 catch {close $client}
2441 # test for bug c6ed4acfd8: running async socket connect with other connect
2442 # established will block tcl as it goes in an infinite loop in vwait
2443 test socket-14.18 {bug c6ed4acfd8: running async socket connect made other connect block} -body {
2444 proc accept {channel address port} {}
2446 set ssock [socket -server accept $port]
2447 set csock1 [socket -async localhost [randport]]
2448 set csock2 [socket localhost $port]
2449 after 1000 {set done ok}
2451 } -constraints {socket notOSX} -cleanup {
2452 catch {close $ssock}
2453 catch {close $csock1}
2454 catch {close $csock2}
2459 set x {localhost {socket} 127.0.0.1 {supported_inet} ::1 {supported_inet6}}
2460 set resultok {-result "sock*" -match glob}
2462 -result {couldn't open socket: connection refused}
2465 foreach {servip sc} $x {
2466 foreach {cliip cc} $x {
2467 set constraints [list socket $sc $cc]
2468 set result $resulterr
2469 switch -- [lsort -unique [list $servip $cliip]] {
2470 localhost - 127.0.0.1 - ::1 {
2471 set result $resultok
2473 {127.0.0.1 localhost} {
2474 if {[testConstraint localhost_v4]} {
2475 set result $resultok
2479 if {[testConstraint localhost_v6]} {
2480 set result $resultok
2484 test socket-15.1.$num "Connect to $servip from $cliip" -setup {
2485 set server [socket -server accept -myaddr $servip 0]
2486 proc accept {s h p} { close $s }
2487 set port [lindex [fconfigure $server -sockname] 2]
2488 } -constraints $constraints -body {
2489 set s [socket $cliip $port]
2498 ::tcltest::cleanupTests