diff options
Diffstat (limited to 'tests/socket.test')
| -rw-r--r-- | tests/socket.test | 772 |
1 files changed, 467 insertions, 305 deletions
diff --git a/tests/socket.test b/tests/socket.test index 2251bb5..b390627 100644 --- a/tests/socket.test +++ b/tests/socket.test @@ -9,51 +9,49 @@ # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: socket.test,v 1.16 2000/09/21 00:58:30 hobbs Exp $ # Running socket tests with a remote server: # ------------------------------------------ -# +# # Some tests in socket.test depend on the existence of a remote server to # which they connect. The remote server must be an instance of tcltest and it # must run the script found in the file "remote.tcl" in this directory. You # can start the remote server on any machine reachable from the machine on # which you want to run the socket tests, by issuing: -# +# # tcltest remote.tcl -port 2048 # Or choose another port number. -# +# # If the machine you are running the remote server on has several IP # interfaces, you can choose which interface the server listens on for # connections by specifying the -address command line flag, so: -# +# # tcltest remote.tcl -address your.machine.com -# +# # These options can also be set by environment variables. On Unix, you can # type these commands to the shell from which the remote server is started: -# +# # shell% setenv serverPort 2048 # shell% setenv serverAddress your.machine.com -# +# # and subsequently you can start the remote server with: -# +# # tcltest remote.tcl -# +# # to have it listen on port 2048 on the interface your.machine.com. -# +# # When the server starts, it prints out a detailed message containing its # configuration information, and it will block until killed with a Ctrl-C. # Once the remote server exists, you can run the tests in socket.test with # the server by setting two Tcl variables: -# +# # % set remoteServerIP <name or address of machine on which server runs> # % set remoteServerPort 2048 -# +# # These variables are also settable from the environment. On Unix, you can: -# +# # shell% setenv remoteServerIP machine.where.server.runs # shell% senetv remoteServerPort 2048 -# +# # The preamble of the socket.test file checks to see if the variables are set # either in Tcl or in the environment; if they are, it attempts to connect to # the server. If the connection is successful, the tests using the remote @@ -62,18 +60,17 @@ # listening at port 2048. If all fails, a message is printed and the tests # using the remote server are not performed. -if {[lsearch [namespace children] ::tcltest] == -1} { - package require tcltest - namespace import -force ::tcltest::* -} +package require tcltest 2 +namespace import -force ::tcltest::* # Some tests require the testthread and exec commands +testConstraint testthread [llength [info commands testthread]] +testConstraint exec [llength [info commands exec]] -set ::tcltest::testConstraints(testthread) \ - [expr {[info commands testthread] != {}}] -set ::tcltest::testConstraints(exec) [expr {[info commands exec] != {}}] +# Produce a random port number in the Dynamic/Private range +# from 49152 through 65535. +proc randport {} { expr {int(rand()*16383+49152)} } -# # If remoteServerIP or remoteServerPort are not set, check in the # environment variables for externally set values. # @@ -98,7 +95,7 @@ if {![info exists remoteServerPort]} { # set doTestsWithRemoteServer 1 -if {![info exists remoteServerIP] && ($tcl_platform(platform) != "macintosh")} { +if {![info exists remoteServerIP]} { set remoteServerIP 127.0.0.1 } if {($doTestsWithRemoteServer == 1) && (![info exists remoteServerPort])} { @@ -116,42 +113,43 @@ set remoteProcChan "" set commandSocket "" if {$doTestsWithRemoteServer} { catch {close $commandSocket} - if {[catch {set commandSocket [socket $remoteServerIP \ - $remoteServerPort]}] != 0} { - if {[info commands exec] == ""} { - set noRemoteTestReason "can't exec" - set doTestsWithRemoteServer 0 - } else { - set remoteServerIP 127.0.0.1 - set remoteFile [file join [pwd] remote.tcl] - if {[catch {set remoteProcChan \ - [open "|[list $::tcltest::tcltest $remoteFile \ - -serverIsSilent \ - -port $remoteServerPort \ - -address $remoteServerIP]" \ - w+]} \ - msg] == 0} { - after 1000 - if {[catch {set commandSocket [socket $remoteServerIP \ - $remoteServerPort]} msg] == 0} { - fconfigure $commandSocket -translation crlf -buffering line - } else { - set noRemoteTestReason $msg - set doTestsWithRemoteServer 0 - } + if {![catch { + set commandSocket [socket $remoteServerIP $remoteServerPort] + }]} then { + fconfigure $commandSocket -translation crlf -buffering line + } elseif {![testConstraint exec]} { + set noRemoteTestReason "can't exec" + set doTestsWithRemoteServer 0 + } else { + set remoteServerIP 127.0.0.1 + # Be *extra* careful in case this file is sourced from + # a directory other than the current one... + set remoteFile [file join [pwd] [file dirname [info script]] \ + remote.tcl] + if {![catch { + set remoteProcChan [open "|[list \ + [interpreter] $remoteFile -serverIsSilent \ + -port $remoteServerPort -address $remoteServerIP]" w+] + } msg]} then { + after 1000 + if {[catch { + set commandSocket [socket $remoteServerIP $remoteServerPort] + } msg] == 0} then { + fconfigure $commandSocket -translation crlf -buffering line } else { - set noRemoteTestReason "$msg $::tcltest::tcltest" + set noRemoteTestReason $msg set doTestsWithRemoteServer 0 } + } else { + set noRemoteTestReason "$msg [interpreter]" + set doTestsWithRemoteServer 0 } - } else { - fconfigure $commandSocket -translation crlf -buffering line } } # Some tests are run only if we are doing testing against a remote server. -set ::tcltest::testConstraints(doTestsWithRemoteServer) $doTestsWithRemoteServer -if {$doTestsWithRemoteServer == 0} { +testConstraint doTestsWithRemoteServer $doTestsWithRemoteServer +if {!$doTestsWithRemoteServer} { if {[string first s $::tcltest::verbose] != -1} { puts "Skipping tests with remote server. See tests/socket.test for" puts "information on how to run remote server." @@ -164,14 +162,13 @@ if {$doTestsWithRemoteServer == 0} { # remote server. # -if {$doTestsWithRemoteServer == 1} { +if {[testConstraint doTestsWithRemoteServer]} { proc sendCommand {c} { global commandSocket if {[eof $commandSocket]} { error "remote server disappeared" } - if {[catch {puts $commandSocket $c} msg]} { error "remote server disappaered: $msg" } @@ -203,17 +200,13 @@ test socket-1.1 {arg parsing for socket command} {socket} { } {1 {no argument given for -server option}} test socket-1.2 {arg parsing for socket command} {socket} { list [catch {socket -server foo} msg] $msg -} {1 {wrong # args: should be either: -socket ?-myaddr addr? ?-myport myport? ?-async? host port -socket -server command ?-myaddr addr? port}} +} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}} test socket-1.3 {arg parsing for socket command} {socket} { list [catch {socket -myaddr} msg] $msg } {1 {no argument given for -myaddr option}} test socket-1.4 {arg parsing for socket command} {socket} { list [catch {socket -myaddr 127.0.0.1} msg] $msg -} {1 {wrong # args: should be either: -socket ?-myaddr addr? ?-myport myport? ?-async? host port -socket -server command ?-myaddr addr? port}} +} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}} test socket-1.5 {arg parsing for socket command} {socket} { list [catch {socket -myport} msg] $msg } {1 {no argument given for -myport option}} @@ -222,50 +215,54 @@ test socket-1.6 {arg parsing for socket command} {socket} { } {1 {expected integer but got "xxxx"}} test socket-1.7 {arg parsing for socket command} {socket} { list [catch {socket -myport 2522} msg] $msg -} {1 {wrong # args: should be either: -socket ?-myaddr addr? ?-myport myport? ?-async? host port -socket -server command ?-myaddr addr? port}} +} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}} test socket-1.8 {arg parsing for socket command} {socket} { list [catch {socket -froboz} msg] $msg } {1 {bad option "-froboz": must be -async, -myaddr, -myport, or -server}} test socket-1.9 {arg parsing for socket command} {socket} { list [catch {socket -server foo -myport 2521 3333} msg] $msg -} {1 {Option -myport is not valid for servers}} +} {1 {option -myport is not valid for servers}} test socket-1.10 {arg parsing for socket command} {socket} { list [catch {socket host 2528 -junk} msg] $msg -} {1 {wrong # args: should be either: -socket ?-myaddr addr? ?-myport myport? ?-async? host port -socket -server command ?-myaddr addr? port}} +} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}} test socket-1.11 {arg parsing for socket command} {socket} { list [catch {socket -server callback 2520 --} msg] $msg -} {1 {wrong # args: should be either: -socket ?-myaddr addr? ?-myport myport? ?-async? host port -socket -server command ?-myaddr addr? port}} +} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}} test socket-1.12 {arg parsing for socket command} {socket} { list [catch {socket foo badport} msg] $msg } {1 {expected integer but got "badport"}} +test socket-1.13 {arg parsing for socket command} {socket} { +list [catch {socket -async -server} msg] $msg +} {1 {cannot set -async option for server sockets}} +test socket-1.14 {arg parsing for socket command} {socket} { +list [catch {socket -server foo -async} msg] $msg +} {1 {cannot set -async option for server sockets}} + +set path(script) [makeFile {} script] test socket-2.1 {tcp connection} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - set timer [after 2000 "set x timed_out"] - set f [socket -server accept 2828] + set timer [after 10000 "set x timed_out"] + set f [socket -server accept 0] proc accept {file addr port} { global x set x done close $file } puts ready + puts [lindex [fconfigure $f -sockname] 2] vwait x after cancel $timer close $f puts $x } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f x - if {[catch {socket 127.0.0.1 2828} msg]} { + gets $f listen + if {[catch {socket 127.0.0.1 $listen} msg]} { set x $msg } else { lappend x [gets $f] @@ -278,15 +275,15 @@ test socket-2.1 {tcp connection} {socket stdio} { if [info exists port] { incr port -} else { +} else { set port [expr 2048 + [pid]%1024] } test socket-2.2 {tcp connection with client port specified} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - set timer [after 2000 "set x done"] - set f [socket -server accept 2829] + set timer [after 10000 "set x timeout"] + set f [socket -server accept 0] proc accept {file addr port} { global x puts "[gets $file] $port" @@ -294,17 +291,19 @@ test socket-2.2 {tcp connection with client port specified} {socket stdio} { set x done } puts ready + puts [lindex [fconfigure $f -sockname] 2] vwait x after cancel $timer close $f } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f x + gets $f listen global port - if {[catch {socket -myport $port 127.0.0.1 2829} sock]} { + if {[catch {socket -myport $port 127.0.0.1 $listen} sock]} { set x $sock - close [socket 127.0.0.1 2829] + close [socket 127.0.0.1 $listen] puts stderr $sock } else { puts $sock hello @@ -316,8 +315,8 @@ test socket-2.2 {tcp connection with client port specified} {socket stdio} { set x } [list ready "hello $port"] test socket-2.3 {tcp connection with client interface specified} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { set timer [after 2000 "set x done"] set f [socket -server accept 2830] @@ -333,7 +332,7 @@ test socket-2.3 {tcp connection with client interface specified} {socket stdio} close $f } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f x if {[catch {socket -myaddr 127.0.0.1 127.0.0.1 2830} sock]} { set x $sock @@ -347,11 +346,11 @@ test socket-2.3 {tcp connection with client interface specified} {socket stdio} set x } {ready {hello 127.0.0.1}} test socket-2.4 {tcp connection with server interface specified} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { set timer [after 2000 "set x done"] - set f [socket -server accept -myaddr [info hostname] 2831] + set f [socket -server accept -myaddr 127.0.0.1 0] proc accept {file addr port} { global x puts "[gets $file]" @@ -359,14 +358,16 @@ test socket-2.4 {tcp connection with server interface specified} {socket stdio} set x done } puts ready + puts [lindex [fconfigure $f -sockname] 2] vwait x after cancel $timer close $f } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f x - if {[catch {socket [info hostname] 2831} sock]} { + gets $f listen + if {[catch {socket 127.0.0.1 $listen} sock]} { set x $sock } else { puts $sock hello @@ -378,11 +379,11 @@ test socket-2.4 {tcp connection with server interface specified} {socket stdio} set x } {ready hello} test socket-2.5 {tcp connection with redundant server port} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - set timer [after 2000 "set x done"] - set f [socket -server accept 2832] + set timer [after 10000 "set x timeout"] + set f [socket -server accept 0] proc accept {file addr port} { global x puts "[gets $file]" @@ -390,14 +391,16 @@ test socket-2.5 {tcp connection with redundant server port} {socket stdio} { set x done } puts ready + puts [lindex [fconfigure $f -sockname] 2] vwait x after cancel $timer close $f } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f x - if {[catch {socket 127.0.0.1 2832} sock]} { + gets $f listen + if {[catch {socket 127.0.0.1 $listen} sock]} { set x $sock } else { puts $sock hello @@ -419,11 +422,11 @@ test socket-2.6 {tcp connection} {socket} { set status } ok test socket-2.7 {echo server, one line} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - set timer [after 2000 "set x done"] - set f [socket -server accept 2834] + set timer [after 10000 "set x timeout"] + set f [socket -server accept 0] proc accept {s a p} { fileevent $s readable [list echo $s] fconfigure $s -translation lf -buffering line @@ -439,15 +442,17 @@ test socket-2.7 {echo server, one line} {socket stdio} { } } puts ready + puts [lindex [fconfigure $f -sockname] 2] vwait x after cancel $timer close $f - puts done + puts $x } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f - set s [socket 127.0.0.1 2834] + gets $f listen + set s [socket 127.0.0.1 $listen] fconfigure $s -buffering line -translation lf puts $s "hello abcdefghijklmnop" after 1000 @@ -457,9 +462,10 @@ test socket-2.7 {echo server, one line} {socket stdio} { close $f list $x $y } {{hello abcdefghijklmnop} done} -test socket-2.8 {echo server, loop 50 times, single connection} {socket stdio} { - makeFile { - set f [socket -server accept 2835] +removeFile script +test socket-2.8 {echo server, loop 50 times, single connection} -constraints {socket stdio} -setup { + set path(script) [makeFile { + set f [socket -server accept 0] proc accept {s a p} { fileevent $s readable [list echo $s] fconfigure $s -buffering line @@ -471,22 +477,25 @@ test socket-2.8 {echo server, loop 50 times, single connection} {socket stdio} { global x close $s set x done - } else { + } else { incr i puts $s $l } } set i 0 puts ready + puts [lindex [fconfigure $f -sockname] 2] set timer [after 20000 "set x done"] vwait x after cancel $timer close $f puts "done $i" - } script - set f [open "|[list $::tcltest::tcltest script]" r] + } script] +} -body { + set f [open "|[list [interpreter] $path(script)]" r] gets $f - set s [socket 127.0.0.1 2835] + gets $f listen + set s [socket 127.0.0.1 $listen] fconfigure $s -buffering line catch { for {set x 0} {$x < 50} {incr x} { @@ -498,27 +507,29 @@ test socket-2.8 {echo server, loop 50 times, single connection} {socket stdio} { catch {set x [gets $f]} close $f set x -} {done 50} -test socket-2.9 {socket conflict} {socket stdio} { - set s [socket -server accept 2828] +} -cleanup { removeFile script - set f [open script w] - puts -nonewline $f {socket -server accept 2828} +} -result {done 50} +set path(script) [makeFile {} script] +test socket-2.9 {socket conflict} {socket stdio} { + set s [socket -server accept 0] + file delete $path(script) + set f [open $path(script) w] + puts -nonewline $f "socket -server accept [lindex [fconfigure $s -sockname] 2]" close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f after 100 - set x [list [catch {close $f} msg] $msg] + set x [list [catch {close $f} msg]] + regsub "\n.*$" $msg {} msg ; # cut part of the error message containing the port number + lappend x $msg close $s set x -} {1 {couldn't open socket: address already in use - while executing -"socket -server accept 2828" - (file "script" line 1)}} +} {1 {couldn't open socket: address already in use}} test socket-2.10 {close on accept, accepted socket lives} {socket} { set done 0 set timer [after 20000 "set done timed_out"] - set ss [socket -server accept 2830] + set ss [socket -server accept 0] proc accept {s a p} { global ss close $ss @@ -531,7 +542,7 @@ test socket-2.10 {close on accept, accepted socket lives} {socket} { close $s set done 1 } - set cs [socket [info hostname] 2830] + set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]] puts $cs hello close $cs vwait done @@ -544,9 +555,9 @@ test socket-2.11 {detecting new data} {socket} { set sock $s } - set s [socket -server accept 2400] + set s [socket -server accept 0] set sock "" - set s2 [socket 127.0.0.1 2400] + set s2 [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] vwait sock puts $s2 one flush $s2 @@ -557,6 +568,7 @@ test socket-2.11 {detecting new data} {socket} { fconfigure $sock -blocking 1 puts $s2 two flush $s2 + after 500 fconfigure $sock -blocking 0 lappend result c:[gets $sock] fconfigure $sock -blocking 1 @@ -565,35 +577,116 @@ test socket-2.11 {detecting new data} {socket} { close $sock set result } {a:one b: c:two} - +test socket-2.12 {} {socket stdio} { + file delete $path(script) + set f [open $path(script) w] + puts $f { + set server [socket -server accept_client 0] + puts [lindex [chan configure $server -sockname] 2] + proc accept_client { client host port } { + chan configure $client -blocking 0 -buffering line + write_line $client + } + proc write_line client { + if { [catch { chan puts $client [string repeat . 720000]}] } { + puts [catch {chan close $client}] + } else { + puts signal1 + after 0 write_line $client + } + } + chan event stdin readable {set forever now} + vwait forever + exit + } + close $f + set f [open "|[list [interpreter] $path(script)]" r+] + gets $f port + set sock [socket 127.0.0.1 $port] + chan event $sock readable [list read_lines $sock $f] + proc read_lines { sock pipe } { + gets $pipe + chan close $sock + chan event $pipe readable [list readpipe $pipe] + } + proc readpipe {pipe} { + while {![string is integer [set ::done [gets $pipe]]]} {} + } + vwait ::done + close $f + set ::done +} 0 +test socket-2.13 {Bug 1758a0b603} {socket stdio} { + file delete $path(script) + set f [open $path(script) w] + puts $f { + set server [socket -server accept 0] + puts [lindex [chan configure $server -sockname] 2] + proc accept { client host port } { + chan configure $client -blocking 0 -buffering line -buffersize 1 + puts $client [string repeat . 720000] + puts ready + chan event $client writable [list setup $client] + } + proc setup client { + chan event $client writable {set forever write} + after 5 {set forever timeout} + } + vwait forever + puts $forever + } + close $f + set pipe [open |[list [interpreter] $path(script)] r] + gets $pipe port + set sock [socket localhost $port] + chan configure $sock -blocking 0 -buffering line + chan event $sock readable [list read_lines $sock $pipe ] + proc read_lines { sock pipe } { + gets $pipe + gets $sock line + after idle [list stop $sock $pipe] + chan event $sock readable {} + } + proc stop {sock pipe} { + variable done + close $sock + set done [gets $pipe] + } + variable done + vwait [namespace which -variable done] + close $pipe + set done +} write test socket-3.1 {socket conflict} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - set f [socket -server accept 2828] + set f [socket -server accept -myaddr 127.0.0.1 0] puts ready + puts [lindex [fconfigure $f -sockname] 2] gets stdin close $f } close $f - set f [open "|[list $::tcltest::tcltest script]" r+] + set f [open "|[list [interpreter] $path(script)]" r+] gets $f - set x [list [catch {socket -server accept 2828} msg] \ + gets $f listen + set x [list [catch {socket -server accept -myaddr 127.0.0.1 $listen} msg] \ $msg] puts $f bye close $f set x } {1 {couldn't open socket: address already in use}} test socket-3.2 {server with several clients} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { set t1 [after 30000 "set x timed_out"] set t2 [after 31000 "set x timed_out"] set t3 [after 32000 "set x timed_out"] set counter 0 - set s [socket -server accept 2828] + set s [socket -server accept -myaddr 127.0.0.1 0] proc accept {s a p} { fileevent $s readable [list echo $s] fconfigure $s -buffering line @@ -609,6 +702,7 @@ test socket-3.2 {server with several clients} {socket stdio} { } } puts ready + puts [lindex [fconfigure $s -sockname] 2] vwait x after cancel $t1 vwait x @@ -619,13 +713,14 @@ test socket-3.2 {server with several clients} {socket stdio} { puts $x } close $f - set f [open "|[list $::tcltest::tcltest script]" r+] + set f [open "|[list [interpreter] $path(script)]" r+] set x [gets $f] - set s1 [socket 127.0.0.1 2828] + gets $f listen + set s1 [socket 127.0.0.1 $listen] fconfigure $s1 -buffering line - set s2 [socket 127.0.0.1 2828] + set s2 [socket 127.0.0.1 $listen] fconfigure $s2 -buffering line - set s3 [socket 127.0.0.1 2828] + set s3 [socket 127.0.0.1 $listen] fconfigure $s3 -buffering line for {set i 0} {$i < 100} {incr i} { puts $s1 hello,s1 @@ -644,11 +739,11 @@ test socket-3.2 {server with several clients} {socket stdio} { } {ready done} test socket-4.1 {server with several clients} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - gets stdin - set s [socket 127.0.0.1 2828] + set port [gets stdin] + set s [socket 127.0.0.1 $port] fconfigure $s -buffering line for {set i 0} {$i < 100} {incr i} { puts $s hello @@ -659,11 +754,11 @@ test socket-4.1 {server with several clients} {socket stdio} { gets stdin } close $f - set p1 [open "|[list $::tcltest::tcltest script]" r+] + set p1 [open "|[list [interpreter] $path(script)]" r+] fconfigure $p1 -buffering line - set p2 [open "|[list $::tcltest::tcltest script]" r+] + set p2 [open "|[list [interpreter] $path(script)]" r+] fconfigure $p2 -buffering line - set p3 [open "|[list $::tcltest::tcltest script]" r+] + set p3 [open "|[list [interpreter] $path(script)]" r+] fconfigure $p3 -buffering line proc accept {s a p} { fconfigure $s -buffering line @@ -682,10 +777,11 @@ test socket-4.1 {server with several clients} {socket stdio} { set t1 [after 30000 "set x timed_out"] set t2 [after 31000 "set x timed_out"] set t3 [after 32000 "set x timed_out"] - set s [socket -server accept 2828] - puts $p1 open - puts $p2 open - puts $p3 open + set s [socket -server accept -myaddr 127.0.0.1 0] + set listen [lindex [fconfigure $s -sockname] 2] + puts $p1 $listen + puts $p2 $listen + puts $p3 $listen vwait x vwait x vwait x @@ -707,7 +803,7 @@ test socket-4.1 {server with several clients} {socket stdio} { } {{p1 bye done} {p2 bye done} {p3 bye done}} test socket-4.2 {byte order problems, socket numbers, htons} {socket} { set x ok - if {[catch {socket -server dodo 0x3000} msg]} { + if {[catch {socket -server dodo -myaddr 127.0.0.1 0x3000} msg]} { set x $msg } else { close $msg @@ -716,7 +812,7 @@ test socket-4.2 {byte order problems, socket numbers, htons} {socket} { } ok test socket-5.1 {byte order problems, socket numbers, htons} \ - {socket unixOnly notRoot} { + {socket unix notRoot} { set x {couldn't open socket: not owner} if {![catch {socket -server dodo 0x1} msg]} { set x {htons problem, should be disallowed, are you running as SU?} @@ -733,7 +829,7 @@ test socket-5.2 {byte order problems, socket numbers, htons} {socket} { set x } {couldn't open socket: port number too high} test socket-5.3 {byte order problems, socket numbers, htons} \ - {socket unixOnly notRoot} { + {socket unix notRoot} { set x {couldn't open socket: not owner} if {![catch {socket -server dodo 21} msg]} { set x {htons problem, should be disallowed, are you running as SU?} @@ -742,122 +838,130 @@ test socket-5.3 {byte order problems, socket numbers, htons} \ set x } {couldn't open socket: not owner} -test socket-6.1 {accept callback error} {socket stdio} { - removeFile script - set f [open script w] +test socket-6.1 {accept callback error} -constraints {socket stdio} -setup { + proc myHandler {msg options} { + variable x $msg + } + set handler [interp bgerror {}] + interp bgerror {} [namespace which myHandler] + file delete $path(script) +} -body { + set f [open $path(script) w] puts $f { - gets stdin - socket 127.0.0.1 2848 + gets stdin port + socket 127.0.0.1 $port } close $f - set f [open "|[list $::tcltest::tcltest script]" r+] - proc bgerror args { - global x - set x $args - } + set f [open "|[list [interpreter] $path(script)]" r+] proc accept {s a p} {expr 10 / 0} - set s [socket -server accept 2848] - puts $f hello + set s [socket -server accept -myaddr 127.0.0.1 0] + puts $f [lindex [fconfigure $s -sockname] 2] close $f set timer [after 10000 "set x timed_out"] vwait x after cancel $timer close $s - rename bgerror {} set x -} {{divide by zero}} +} -cleanup { + interp bgerror {} $handler +} -result {divide by zero} test socket-7.1 {testing socket specific options} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - socket -server accept 2820 + set ss [socket -server accept 0] proc accept args { global x set x done } puts ready + puts [lindex [fconfigure $ss -sockname] 2] set timer [after 10000 "set x timed_out"] vwait x after cancel $timer } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f - set s [socket 127.0.0.1 2820] + gets $f listen + set s [socket 127.0.0.1 $listen] set p [fconfigure $s -peername] close $s close $f set l "" lappend l [string compare [lindex $p 0] 127.0.0.1] - lappend l [string compare [lindex $p 2] 2820] + lappend l [string compare [lindex $p 2] $listen] lappend l [llength $p] } {0 0 3} test socket-7.2 {testing socket specific options} {socket stdio} { - removeFile script - set f [open script w] + file delete $path(script) + set f [open $path(script) w] puts $f { - socket -server accept 2821 + set ss [socket -server accept 2821] proc accept args { global x set x done } puts ready + puts [lindex [fconfigure $ss -sockname] 2] set timer [after 10000 "set x timed_out"] vwait x after cancel $timer } close $f - set f [open "|[list $::tcltest::tcltest script]" r] + set f [open "|[list [interpreter] $path(script)]" r] gets $f - set s [socket 127.0.0.1 2821] + gets $f listen + set s [socket 127.0.0.1 $listen] set p [fconfigure $s -sockname] close $s close $f - set l "" - lappend l [llength $p] - lappend l [lindex $p 0] - lappend l [expr [lindex $p 2] == 2821] -} {3 127.0.0.1 0} + list [llength $p] \ + [regexp {^(127\.0\.0\.1|0\.0\.0\.0)$} [lindex $p 0]] \ + [expr {[lindex $p 2] == $listen}] +} {3 1 0} test socket-7.3 {testing socket specific options} {socket} { - set s [socket -server accept 2822] + set s [socket -server accept -myaddr 127.0.0.1 0] set l [fconfigure $s] close $s update llength $l -} 12 +} 14 test socket-7.4 {testing socket specific options} {socket} { - set s [socket -server accept 2823] + set s [socket -server accept -myaddr 127.0.0.1 0] proc accept {s a p} { global x set x [fconfigure $s -sockname] close $s } - set s1 [socket [info hostname] 2823] + set listen [lindex [fconfigure $s -sockname] 2] + set s1 [socket 127.0.0.1 $listen] set timer [after 10000 "set x timed_out"] vwait x after cancel $timer close $s close $s1 set l "" - lappend l [lindex $x 2] [llength $x] -} {2823 3} + lappend l [expr {[lindex $x 2] == $listen}] [llength $x] +} {1 3} test socket-7.5 {testing socket specific options} {socket unixOrPc} { - set s [socket -server accept 2829] + set s [socket -server accept 0] proc accept {s a p} { global x set x [fconfigure $s -sockname] close $s } - set s1 [socket 127.0.0.1 2829] + set listen [lindex [fconfigure $s -sockname] 2] + set s1 [socket 127.0.0.1 $listen] set timer [after 10000 "set x timed_out"] vwait x after cancel $timer close $s close $s1 set l "" - lappend l [lindex $x 0] [lindex $x 2] [llength $x] -} {127.0.0.1 2829 3} + lappend l [lindex $x 0] [expr {[lindex $x 2] == $listen}] [llength $x] +} {127.0.0.1 1 3} test socket-8.1 {testing -async flag on sockets} {socket} { # NOTE: This test may fail on some Solaris 2.4 systems. If it does, @@ -874,14 +978,14 @@ test socket-8.1 {testing -async flag on sockets} {socket} { # problem, please email jyl@eng.sun.com. We have not observed this # failure on Solaris 2.5, so another option (instead of installing # these patches) is to upgrade to Solaris 2.5. - set s [socket -server accept 2830] + set s [socket -server accept -myaddr 127.0.0.1 0] proc accept {s a p} { global x puts $s bye close $s set x done } - set s1 [socket -async [info hostname] 2830] + set s1 [socket -async 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] vwait x set z [gets $s1] close $s @@ -911,8 +1015,8 @@ test socket-9.1 {testing spurious events} {socket} { fconfigure $s -buffering none -blocking off fileevent $s readable [list readlittle $s] } - set s [socket -server accept 2831] - set c [socket [info hostname] 2831] + set s [socket -server accept -myaddr 127.0.0.1 0] + set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] puts -nonewline $c 01234567890123456789012345678901234567890123456789 close $c set timer [after 10000 "set done timed_out"] @@ -928,7 +1032,7 @@ test socket-9.2 {testing async write, fileevents, flush on close} {socket} { for {set i 0} {$i < 16} {incr i} { set secondblock "b$secondblock$secondblock" } - set l [socket -server accept 2832] + set l [socket -server accept -myaddr 127.0.0.1 0] proc accept {s a p} { fconfigure $s -blocking 0 -translation lf -buffersize 16384 \ -buffering line @@ -949,7 +1053,7 @@ test socket-9.2 {testing async write, fileevents, flush on close} {socket} { puts -nonewline $s $secondblock close $s } - set s [socket [info hostname] 2832] + set s [socket 127.0.0.1 [lindex [fconfigure $l -sockname] 2]] fconfigure $s -blocking 0 -trans lf -buffering line set count 0 puts $s hello @@ -988,7 +1092,7 @@ test socket-9.3 {testing EOF stickyness} {socket} { set done true set count {timer went off, eof is not sticky} close $c - } + } set count 0 set done false proc write_then_close {s} { @@ -999,8 +1103,8 @@ test socket-9.3 {testing EOF stickyness} {socket} { fconfigure $s -buffering line -translation lf fileevent $s writable "write_then_close $s" } - set s [socket -server accept 2833] - set c [socket [info hostname] 2833] + set s [socket -server accept -myaddr 127.0.0.1 0] + set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] fconfigure $c -blocking off -buffering line -translation lf fileevent $c readable "count_to_eof $c" set timer [after 1000 timerproc] @@ -1011,17 +1115,26 @@ test socket-9.3 {testing EOF stickyness} {socket} { removeFile script -test socket-10.1 {testing socket accept callback error handling} {socket} { - set goterror 0 - proc bgerror args {global goterror; set goterror 1} - set s [socket -server accept 2898] +test socket-10.1 {testing socket accept callback error handling} -constraints { + socket +} -setup { + variable goterror 0 + proc myHandler {msg options} { + variable goterror 1 + } + set handler [interp bgerror {}] + interp bgerror {} [namespace which myHandler] +} -body { + set s [socket -server accept -myaddr 127.0.0.1 0] proc accept {s a p} {close $s; error} - set c [socket 127.0.0.1 2898] + set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] vwait goterror close $s close $c set goterror -} 1 +} -cleanup { + interp bgerror {} $handler +} -result 1 test socket-11.1 {tcp connection} {socket doTestsWithRemoteServer} { sendCommand { @@ -1123,15 +1236,9 @@ test socket-11.5 {remote echo, 50 lines} {socket doTestsWithRemoteServer} { sendCommand {close $socket10_7_test_server} set cnt } 50 -# Macintosh sockets can have more than one server per port -if {$tcl_platform(platform) == "macintosh"} { - set conflictResult {0 2836} -} else { - set conflictResult {1 {couldn't open socket: address already in use}} -} test socket-11.6 {socket conflict} {socket doTestsWithRemoteServer} { - set s1 [socket -server accept 2836] - if {[catch {set s2 [socket -server accept 2836]} msg]} { + set s1 [socket -server accept -myaddr 127.0.0.1 2836] + if {[catch {set s2 [socket -server accept -myaddr 127.0.0.1 2836]} msg]} { set result [list 1 $msg] } else { set result [list 0 [lindex [fconfigure $s2 -sockname] 2]] @@ -1139,7 +1246,7 @@ test socket-11.6 {socket conflict} {socket doTestsWithRemoteServer} { } close $s1 set result -} $conflictResult +} {1 {couldn't open socket: address already in use}} test socket-11.7 {server with several clients} {socket doTestsWithRemoteServer} { sendCommand { set socket10_9_test_server [socket -server accept 2836] @@ -1175,7 +1282,7 @@ test socket-11.7 {server with several clients} {socket doTestsWithRemoteServer} close $s3 sendCommand {close $socket10_9_test_server} set i -} 100 +} 100 test socket-11.8 {client with several servers} {socket doTestsWithRemoteServer} { sendCommand { set s1 [socket -server "accept 4003" 4003] @@ -1202,13 +1309,17 @@ test socket-11.8 {client with several servers} {socket doTestsWithRemoteServer} } set l } {4003 {} 1 4004 {} 1 4005 {} 1} -test socket-11.9 {accept callback error} {socket doTestsWithRemoteServer} { +test socket-11.9 {accept callback error} -constraints { + socket doTestsWithRemoteServer +} -setup { + proc myHandler {msg options} { + variable x $msg + } + set handler [interp bgerror {}] + interp bgerror {} [namespace which myHandler] +} -body { set s [socket -server accept 2836] proc accept {s a p} {expr 10 / 0} - proc bgerror args { - global x - set x $args - } if {[catch {sendCommand { set peername [fconfigure $callerSocket -peername] set s [socket [lindex $peername 0] 2836] @@ -1221,9 +1332,10 @@ test socket-11.9 {accept callback error} {socket doTestsWithRemoteServer} { vwait x after cancel $timer close $s - rename bgerror {} set x -} {{divide by zero}} +} -cleanup { + interp bgerror {} $handler +} -result {divide by zero} test socket-11.10 {testing socket specific options} {socket doTestsWithRemoteServer} { sendCommand { set socket10_12_test_server [socket -server accept 2836] @@ -1271,13 +1383,12 @@ test socket-11.11 {testing spurious events} {socket doTestsWithRemoteServer} { } set c [socket $remoteServerIP 2836] fileevent $c readable "readlittle $c" - set timer [after 10000 "set done timed_out"] + set timer [after 40000 "set done timed_out"] vwait done after cancel $timer sendCommand {close $socket10_13_test_server} - list $spurious $len -} {0 2690} - + list $spurious $len $done +} {0 2690 1} test socket-11.12 {testing EOF stickyness} {socket doTestsWithRemoteServer} { set counter 0 set done 0 @@ -1311,7 +1422,6 @@ test socket-11.12 {testing EOF stickyness} {socket doTestsWithRemoteServer} { sendCommand {close $socket10_14_test_server} set done } {EOF is sticky} - test socket-11.13 {testing async write, async flush, async close} \ {socket doTestsWithRemoteServer} { proc readit {s} { @@ -1366,14 +1476,17 @@ test socket-11.13 {testing async write, async flush, async close} \ set count } 65566 -test socket-12.1 {testing inheritance of server sockets} {socket exec} { - removeFile script1 - removeFile script2 +set path(script1) [makeFile {} script1] +set path(script2) [makeFile {} script2] + +test socket-12.1 {testing inheritance of server sockets} {socket stdio exec} { + file delete $path(script1) + file delete $path(script2) # Script1 is just a 10 second delay. If the server socket # is inherited, it will be held open for 10 seconds - set f [open script1 w] + set f [open $path(script1) w] puts $f { after 10000 exit vwait forever @@ -1384,49 +1497,54 @@ test socket-12.1 {testing inheritance of server sockets} {socket exec} { # waits a second, and exits. The server socket will now # be closed unless script1 inherited it. - set f [open script2 w] - puts $f [list set tcltest $::tcltest::tcltest] - puts $f { - set f [socket -server accept 2828] + set f [open $path(script2) w] + puts $f [list set tcltest [interpreter]] + puts -nonewline $f { + set f [socket -server accept -myaddr 127.0.0.1 0] + puts [lindex [fconfigure $f -sockname] 2] proc accept { file addr port } { close $file } - exec $tcltest script1 & + exec $tcltest } + puts $f [list $path(script1) &] + puts $f { close $f after 1000 exit vwait forever } close $f - + # Launch script2 and wait 5 seconds - exec $::tcltest::tcltest script2 & + ### exec [interpreter] script2 & + set p [open "|[list [interpreter] $path(script2)]" r] + gets $p listen + after 5000 { set ok_to_proceed 1 } vwait ok_to_proceed # If we can still connect to the server, the socket got inherited. - if {[catch {socket 127.0.0.1 2828} msg]} { + if {[catch {socket 127.0.0.1 $listen} msg]} { set x {server socket was not inherited} } else { close $msg set x {server socket was inherited} } - removeFile script1 - removeFile script2 + close $p set x } {server socket was not inherited} -test socket-12.2 {testing inheritance of client sockets} {socket exec} { - removeFile script1 - removeFile script2 +test socket-12.2 {testing inheritance of client sockets} {socket stdio exec} { + file delete $path(script1) + file delete $path(script2) - # Script1 is just a 10 second delay. If the server socket + # Script1 is just a 20 second delay. If the server socket # is inherited, it will be held open for 10 seconds - set f [open script1 w] + set f [open $path(script1) w] puts $f { - after 10000 exit + after 20000 exit vwait forever } close $f @@ -1435,11 +1553,14 @@ test socket-12.2 {testing inheritance of client sockets} {socket exec} { # launches script1 and exits. If the child process inherited the # client socket, the socket will still be open. - set f [open script2 w] - puts $f [list set tcltest $::tcltest::tcltest] + set f [open $path(script2) w] + puts $f [list set tcltest [interpreter]] + puts -nonewline $f { + gets stdin port + set f [socket 127.0.0.1 $port] + exec $tcltest } + puts $f [list $path(script1) &] puts $f { - set f [socket 127.0.0.1 2829] - exec $tcltest script1 & puts $f testing flush $f after 1000 exit @@ -1449,7 +1570,7 @@ test socket-12.2 {testing inheritance of client sockets} {socket exec} { # Create the server socket - set server [socket -server accept 2829] + set server [socket -server accept -myaddr 127.0.0.1 0] proc accept { file host port } { # When the client connects, establish the read handler global server @@ -1482,45 +1603,53 @@ test socket-12.2 {testing inheritance of client sockets} {socket exec} { return } - # If the socket doesn't hit end-of-file in 5 seconds, the + # If the socket doesn't hit end-of-file in 10 seconds, the # script1 process must have inherited the client. set failed 0 - after 5000 [list set failed 1] + after 10000 [list set failed 1] # Launch the script2 process + ### exec [interpreter] script2 & - exec $::tcltest::tcltest script2 & + set p [open "|[list [interpreter] $path(script2)]" w] + puts $p [lindex [fconfigure $server -sockname] 2] ; flush $p vwait x if {!$failed} { vwait failed } - removeFile script1 - removeFile script2 + close $p set x } {client socket was not inherited} -test socket-12.3 {testing inheritance of accepted sockets} {socket exec} { - removeFile script1 - removeFile script2 +test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} { + file delete $path(script1) + file delete $path(script2) - set f [open script1 w] + set f [open $path(script1) w] puts $f { after 10000 exit vwait forever } close $f - set f [open script2 w] - puts $f [list set tcltest $::tcltest::tcltest] - puts $f { - set server [socket -server accept 2930] - proc accept { file host port } { + set f [open $path(script2) w] + puts $f [list set tcltest [interpreter]] + puts -nonewline $f { + set server [socket -server accept -myaddr 127.0.0.1 0] + puts stdout [lindex [fconfigure $server -sockname] 2] + proc accept { file host port } } + puts $f \{ + puts -nonewline $f { global tcltest puts $file {test data on socket} - exec $tcltest script1 & + exec $tcltest } + puts $f [list $path(script1) &] + puts $f { after 1000 exit } + puts $f \} + puts $f { vwait forever } close $f @@ -1528,12 +1657,14 @@ test socket-12.3 {testing inheritance of accepted sockets} {socket exec} { # Launch the script2 process and connect to it. See how long # the socket stays open - exec $::tcltest::tcltest script2 & + ## exec [interpreter] script2 & + set p [open "|[list [interpreter] $path(script2)]" r] + gets $p listen after 1000 set ok_to_proceed 1 vwait ok_to_proceed - set f [socket 127.0.0.1 2930] + set f [socket 127.0.0.1 $listen] fconfigure $f -buffering full -blocking 0 fileevent $f readable [list getdata $f] @@ -1566,67 +1697,67 @@ test socket-12.3 {testing inheritance of accepted sockets} {socket exec} { } return } - + vwait x - removeFile script1 - removeFile script2 + close $p set x } {accepted socket was not inherited} test socket-13.1 {Testing use of shared socket between two threads} \ - {socket testthread} { - - removeFile script + -constraints {socket testthread} -setup { threadReap - - makeFile { - set f [socket -server accept 2828] - proc accept {s a p} { + set path(script) [makeFile { + set f [socket -server accept -myaddr 127.0.0.1 0] + set listen [lindex [fconfigure $f -sockname] 2] + proc accept {s a p} { fileevent $s readable [list echo $s] fconfigure $s -buffering line } - proc echo {s} { - global i + proc echo {s} { + global i set l [gets $s] if {[eof $s]} { global x close $s set x done - } else { - incr i + } else { + incr i puts $s $l } - } - set i 0 - vwait x - close $f - - # thread cleans itself up. - testthread exit - } script - + } + set i 0 + vwait x + close $f + # thread cleans itself up. + testthread exit + } script] +} -body { # create a thread - set serverthread [testthread create { source script } ] + set serverthread [testthread create [list source $path(script) ] ] update - + set port [testthread send $serverthread {set listen}] + update + after 1000 - set s [socket 127.0.0.1 2828] + set s [socket 127.0.0.1 $port] fconfigure $s -buffering line catch { - puts $s "hello" - gets $s result + puts $s "hello" + gets $s result } close $s update after 2000 lappend result [threadReap] - - set result +} -cleanup { + removeFile script +} -result {hello 1} -} {hello 1} +removeFile script1 +removeFile script2 # cleanup if {[string match sock* $commandSocket] == 1} { @@ -1635,6 +1766,37 @@ if {[string match sock* $commandSocket] == 1} { } catch {close $commandSocket} catch {close $remoteProcChan} +test socket-14.13 {testing writable event when quick failure} -constraints {socket win supported_inet} -body { + # Test for bug 336441ed59 where a quick background fail was ignored + + # Test only for windows as socket -async 255.255.255.255 fails + # directly on unix + + # The following connect should fail very quickly + set a1 [after 2000 {set x timeout}] + set s [socket -async 255.255.255.255 43434] + fileevent $s writable {set x writable} + vwait x + set x +} -cleanup { + catch {close $s} + after cancel $a1 +} -result writable + +test socket-14.14 {testing fileevent readable on failed async socket connect} -constraints [list socket] -body { + # Test for bug 581937ab1e + + set a1 [after 5000 {set x timeout}] + # This connect should fail + set s [socket -async localhost [randport]] + fileevent $s readable {set x readable} + vwait x + set x +} -cleanup { + catch {close $s} + after cancel $a1 +} -result readable + ::tcltest::cleanupTests flush stdout return |
