sl@0: # Commands tested in this file: socket. sl@0: # sl@0: # This file contains a collection of tests for one or more of the Tcl sl@0: # built-in commands. Sourcing this file into Tcl runs the tests and sl@0: # generates output for errors. No output means no errors were found. sl@0: # sl@0: # Copyright (c) 1994-1996 Sun Microsystems, Inc. sl@0: # Copyright (c) 1998-2000 Ajuba Solutions. sl@0: # sl@0: # See the file "license.terms" for information on usage and redistribution sl@0: # of this file, and for a DISCLAIMER OF ALL WARRANTIES. sl@0: # sl@0: # RCS: @(#) $Id: socket.test,v 1.26.2.6 2006/03/16 00:35:59 andreas_kupries Exp $ sl@0: sl@0: # Running socket tests with a remote server: sl@0: # ------------------------------------------ sl@0: # sl@0: # Some tests in socket.test depend on the existence of a remote server to sl@0: # which they connect. The remote server must be an instance of tcltest and it sl@0: # must run the script found in the file "remote.tcl" in this directory. You sl@0: # can start the remote server on any machine reachable from the machine on sl@0: # which you want to run the socket tests, by issuing: sl@0: # sl@0: # tcltest remote.tcl -port 2048 # Or choose another port number. sl@0: # sl@0: # If the machine you are running the remote server on has several IP sl@0: # interfaces, you can choose which interface the server listens on for sl@0: # connections by specifying the -address command line flag, so: sl@0: # sl@0: # tcltest remote.tcl -address your.machine.com sl@0: # sl@0: # These options can also be set by environment variables. On Unix, you can sl@0: # type these commands to the shell from which the remote server is started: sl@0: # sl@0: # shell% setenv serverPort 2048 sl@0: # shell% setenv serverAddress your.machine.com sl@0: # sl@0: # and subsequently you can start the remote server with: sl@0: # sl@0: # tcltest remote.tcl sl@0: # sl@0: # to have it listen on port 2048 on the interface your.machine.com. sl@0: # sl@0: # When the server starts, it prints out a detailed message containing its sl@0: # configuration information, and it will block until killed with a Ctrl-C. sl@0: # Once the remote server exists, you can run the tests in socket.test with sl@0: # the server by setting two Tcl variables: sl@0: # sl@0: # % set remoteServerIP sl@0: # % set remoteServerPort 2048 sl@0: # sl@0: # These variables are also settable from the environment. On Unix, you can: sl@0: # sl@0: # shell% setenv remoteServerIP machine.where.server.runs sl@0: # shell% senetv remoteServerPort 2048 sl@0: # sl@0: # The preamble of the socket.test file checks to see if the variables are set sl@0: # either in Tcl or in the environment; if they are, it attempts to connect to sl@0: # the server. If the connection is successful, the tests using the remote sl@0: # server will be performed; otherwise, it will attempt to start the remote sl@0: # server (via exec) on platforms that support this, on the local host, sl@0: # listening at port 2048. If all fails, a message is printed and the tests sl@0: # using the remote server are not performed. sl@0: sl@0: package require tcltest 2 sl@0: namespace import -force ::tcltest::* sl@0: sl@0: # Some tests require the testthread and exec commands sl@0: testConstraint testthread [llength [info commands testthread]] sl@0: testConstraint exec [llength [info commands exec]] sl@0: sl@0: # If remoteServerIP or remoteServerPort are not set, check in the sl@0: # environment variables for externally set values. sl@0: # sl@0: sl@0: if {![info exists remoteServerIP]} { sl@0: if {[info exists env(remoteServerIP)]} { sl@0: set remoteServerIP $env(remoteServerIP) sl@0: } sl@0: } sl@0: if {![info exists remoteServerPort]} { sl@0: if {[info exists env(remoteServerIP)]} { sl@0: set remoteServerPort $env(remoteServerPort) sl@0: } else { sl@0: if {[info exists remoteServerIP]} { sl@0: set remoteServerPort 2048 sl@0: } sl@0: } sl@0: } sl@0: sl@0: # sl@0: # Check if we're supposed to do tests against the remote server sl@0: # sl@0: sl@0: set doTestsWithRemoteServer 1 sl@0: if {![info exists remoteServerIP] && ($tcl_platform(platform) != "macintosh")} { sl@0: set remoteServerIP 127.0.0.1 sl@0: } sl@0: if {($doTestsWithRemoteServer == 1) && (![info exists remoteServerPort])} { sl@0: set remoteServerPort 2048 sl@0: } sl@0: sl@0: # Attempt to connect to a remote server if one is already running. If it sl@0: # is not running or for some other reason the connect fails, attempt to sl@0: # start the remote server on the local host listening on port 2048. This sl@0: # is only done on platforms that support exec (i.e. not on the Mac). On sl@0: # platforms that do not support exec, the remote server must be started sl@0: # by the user before running the tests. sl@0: sl@0: set remoteProcChan "" sl@0: set commandSocket "" sl@0: if {$doTestsWithRemoteServer} { sl@0: catch {close $commandSocket} sl@0: if {[catch {set commandSocket [socket $remoteServerIP \ sl@0: $remoteServerPort]}] != 0} { sl@0: if {[info commands exec] == ""} { sl@0: set noRemoteTestReason "can't exec" sl@0: set doTestsWithRemoteServer 0 sl@0: } else { sl@0: set remoteServerIP 127.0.0.1 sl@0: # Be *extra* careful in case this file is sourced from sl@0: # a directory other than the current one... sl@0: set remoteFile [file join [pwd] [file dirname [info script]] \ sl@0: remote.tcl] sl@0: if {[catch {set remoteProcChan \ sl@0: [open "|[list [interpreter] $remoteFile \ sl@0: -serverIsSilent \ sl@0: -port $remoteServerPort \ sl@0: -address $remoteServerIP]" \ sl@0: w+]} \ sl@0: msg] == 0} { sl@0: after 1000 sl@0: if {[catch {set commandSocket [socket $remoteServerIP \ sl@0: $remoteServerPort]} msg] == 0} { sl@0: fconfigure $commandSocket -translation crlf -buffering line sl@0: } else { sl@0: set noRemoteTestReason $msg sl@0: set doTestsWithRemoteServer 0 sl@0: } sl@0: } else { sl@0: set noRemoteTestReason "$msg [interpreter]" sl@0: set doTestsWithRemoteServer 0 sl@0: } sl@0: } sl@0: } else { sl@0: fconfigure $commandSocket -translation crlf -buffering line sl@0: } sl@0: } sl@0: sl@0: # Some tests are run only if we are doing testing against a remote server. sl@0: set ::tcltest::testConstraints(doTestsWithRemoteServer) $doTestsWithRemoteServer sl@0: if {$doTestsWithRemoteServer == 0} { sl@0: if {[string first s $::tcltest::verbose] != -1} { sl@0: puts "Skipping tests with remote server. See tests/socket.test for" sl@0: puts "information on how to run remote server." sl@0: puts "Reason for not doing remote tests: $noRemoteTestReason" sl@0: } sl@0: } sl@0: sl@0: # sl@0: # If we do the tests, define a command to send a command to the sl@0: # remote server. sl@0: # sl@0: sl@0: if {$doTestsWithRemoteServer == 1} { sl@0: proc sendCommand {c} { sl@0: global commandSocket sl@0: sl@0: if {[eof $commandSocket]} { sl@0: error "remote server disappeared" sl@0: } sl@0: sl@0: if {[catch {puts $commandSocket $c} msg]} { sl@0: error "remote server disappaered: $msg" sl@0: } sl@0: if {[catch {puts $commandSocket "--Marker--Marker--Marker--"} msg]} { sl@0: error "remote server disappeared: $msg" sl@0: } sl@0: sl@0: set resp "" sl@0: while {1} { sl@0: set line [gets $commandSocket] sl@0: if {[eof $commandSocket]} { sl@0: error "remote server disappaered" sl@0: } sl@0: if {[string compare $line "--Marker--Marker--Marker--"] == 0} { sl@0: if {[string compare [lindex $resp 0] error] == 0} { sl@0: error [lindex $resp 1] sl@0: } else { sl@0: return [lindex $resp 1] sl@0: } sl@0: } else { sl@0: append resp $line "\n" sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: test socket-1.1 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -server} msg] $msg sl@0: } {1 {no argument given for -server option}} sl@0: test socket-1.2 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -server foo} msg] $msg sl@0: } {1 {wrong # args: should be either: sl@0: socket ?-myaddr addr? ?-myport myport? ?-async? host port sl@0: socket -server command ?-myaddr addr? port}} sl@0: test socket-1.3 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -myaddr} msg] $msg sl@0: } {1 {no argument given for -myaddr option}} sl@0: test socket-1.4 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -myaddr 127.0.0.1} msg] $msg sl@0: } {1 {wrong # args: should be either: sl@0: socket ?-myaddr addr? ?-myport myport? ?-async? host port sl@0: socket -server command ?-myaddr addr? port}} sl@0: test socket-1.5 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -myport} msg] $msg sl@0: } {1 {no argument given for -myport option}} sl@0: test socket-1.6 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -myport xxxx} msg] $msg sl@0: } {1 {expected integer but got "xxxx"}} sl@0: test socket-1.7 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -myport 2522} msg] $msg sl@0: } {1 {wrong # args: should be either: sl@0: socket ?-myaddr addr? ?-myport myport? ?-async? host port sl@0: socket -server command ?-myaddr addr? port}} sl@0: test socket-1.8 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -froboz} msg] $msg sl@0: } {1 {bad option "-froboz": must be -async, -myaddr, -myport, or -server}} sl@0: test socket-1.9 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -server foo -myport 2521 3333} msg] $msg sl@0: } {1 {Option -myport is not valid for servers}} sl@0: test socket-1.10 {arg parsing for socket command} {socket} { sl@0: list [catch {socket host 2528 -junk} msg] $msg sl@0: } {1 {wrong # args: should be either: sl@0: socket ?-myaddr addr? ?-myport myport? ?-async? host port sl@0: socket -server command ?-myaddr addr? port}} sl@0: test socket-1.11 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -server callback 2520 --} msg] $msg sl@0: } {1 {wrong # args: should be either: sl@0: socket ?-myaddr addr? ?-myport myport? ?-async? host port sl@0: socket -server command ?-myaddr addr? port}} sl@0: test socket-1.12 {arg parsing for socket command} {socket} { sl@0: list [catch {socket foo badport} msg] $msg sl@0: } {1 {expected integer but got "badport"}} sl@0: test socket-1.13 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -async -server} msg] $msg sl@0: } {1 {cannot set -async option for server sockets}} sl@0: test socket-1.14 {arg parsing for socket command} {socket} { sl@0: list [catch {socket -server foo -async} msg] $msg sl@0: } {1 {cannot set -async option for server sockets}} sl@0: sl@0: set path(script) [makeFile {} script] sl@0: sl@0: test socket-2.1 {tcp connection} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set timer [after 10000 "set x timed_out"] sl@0: set f [socket -server accept 0] sl@0: proc accept {file addr port} { sl@0: global x sl@0: set x done sl@0: close $file sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: puts $x sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f x sl@0: gets $f listen sl@0: if {[catch {socket 127.0.0.1 $listen} msg]} { sl@0: set x $msg sl@0: } else { sl@0: lappend x [gets $f] sl@0: close $msg sl@0: } sl@0: lappend x [gets $f] sl@0: close $f sl@0: set x sl@0: } {ready done {}} sl@0: sl@0: if [info exists port] { sl@0: incr port sl@0: } else { sl@0: set port [expr 2048 + [pid]%1024] sl@0: } sl@0: test socket-2.2 {tcp connection with client port specified} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set timer [after 10000 "set x timeout"] sl@0: set f [socket -server accept 0] sl@0: proc accept {file addr port} { sl@0: global x sl@0: puts "[gets $file] $port" sl@0: close $file sl@0: set x done sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f x sl@0: gets $f listen sl@0: global port sl@0: if {[catch {socket -myport $port 127.0.0.1 $listen} sock]} { sl@0: set x $sock sl@0: close [socket 127.0.0.1 $listen] sl@0: puts stderr $sock sl@0: } else { sl@0: puts $sock hello sl@0: flush $sock sl@0: lappend x [gets $f] sl@0: close $sock sl@0: } sl@0: close $f sl@0: set x sl@0: } [list ready "hello $port"] sl@0: test socket-2.3 {tcp connection with client interface specified} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set timer [after 2000 "set x done"] sl@0: set f [socket -server accept 2830] sl@0: proc accept {file addr port} { sl@0: global x sl@0: puts "[gets $file] $addr" sl@0: close $file sl@0: set x done sl@0: } sl@0: puts ready sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f x sl@0: if {[catch {socket -myaddr 127.0.0.1 127.0.0.1 2830} sock]} { sl@0: set x $sock sl@0: } else { sl@0: puts $sock hello sl@0: flush $sock sl@0: lappend x [gets $f] sl@0: close $sock sl@0: } sl@0: close $f sl@0: set x sl@0: } {ready {hello 127.0.0.1}} sl@0: test socket-2.4 {tcp connection with server interface specified} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set timer [after 2000 "set x done"] sl@0: set f [socket -server accept -myaddr 127.0.0.1 0] sl@0: proc accept {file addr port} { sl@0: global x sl@0: puts "[gets $file]" sl@0: close $file sl@0: set x done sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f x sl@0: gets $f listen sl@0: if {[catch {socket 127.0.0.1 $listen} sock]} { sl@0: set x $sock sl@0: } else { sl@0: puts $sock hello sl@0: flush $sock sl@0: lappend x [gets $f] sl@0: close $sock sl@0: } sl@0: close $f sl@0: set x sl@0: } {ready hello} sl@0: test socket-2.5 {tcp connection with redundant server port} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set timer [after 10000 "set x timeout"] sl@0: set f [socket -server accept 0] sl@0: proc accept {file addr port} { sl@0: global x sl@0: puts "[gets $file]" sl@0: close $file sl@0: set x done sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f x sl@0: gets $f listen sl@0: if {[catch {socket 127.0.0.1 $listen} sock]} { sl@0: set x $sock sl@0: } else { sl@0: puts $sock hello sl@0: flush $sock sl@0: lappend x [gets $f] sl@0: close $sock sl@0: } sl@0: close $f sl@0: set x sl@0: } {ready hello} sl@0: test socket-2.6 {tcp connection} {socket} { sl@0: set status ok sl@0: if {![catch {set sock [socket 127.0.0.1 2833]}]} { sl@0: if {![catch {gets $sock}]} { sl@0: set status broken sl@0: } sl@0: close $sock sl@0: } sl@0: set status sl@0: } ok sl@0: test socket-2.7 {echo server, one line} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set timer [after 10000 "set x timeout"] sl@0: set f [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: fileevent $s readable [list echo $s] sl@0: fconfigure $s -translation lf -buffering line sl@0: } sl@0: proc echo {s} { sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: global x sl@0: close $s sl@0: set x done sl@0: } else { sl@0: puts $s $l sl@0: } sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: puts $x sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f sl@0: gets $f listen sl@0: set s [socket 127.0.0.1 $listen] sl@0: fconfigure $s -buffering line -translation lf sl@0: puts $s "hello abcdefghijklmnop" sl@0: after 1000 sl@0: set x [gets $s] sl@0: close $s sl@0: set y [gets $f] sl@0: close $f sl@0: list $x $y sl@0: } {{hello abcdefghijklmnop} done} sl@0: removeFile script sl@0: test socket-2.8 {echo server, loop 50 times, single connection} -constraints {socket stdio} -setup { sl@0: set path(script) [makeFile { sl@0: set f [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: fileevent $s readable [list echo $s] sl@0: fconfigure $s -buffering line sl@0: } sl@0: proc echo {s} { sl@0: global i sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: global x sl@0: close $s sl@0: set x done sl@0: } else { sl@0: incr i sl@0: puts $s $l sl@0: } sl@0: } sl@0: set i 0 sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: set timer [after 20000 "set x done"] sl@0: vwait x sl@0: after cancel $timer sl@0: close $f sl@0: puts "done $i" sl@0: } script] sl@0: } -body { sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f sl@0: gets $f listen sl@0: set s [socket 127.0.0.1 $listen] sl@0: fconfigure $s -buffering line sl@0: catch { sl@0: for {set x 0} {$x < 50} {incr x} { sl@0: puts $s "hello abcdefghijklmnop" sl@0: gets $s sl@0: } sl@0: } sl@0: close $s sl@0: catch {set x [gets $f]} sl@0: close $f sl@0: set x sl@0: } -cleanup { sl@0: removeFile script sl@0: } -result {done 50} sl@0: set path(script) [makeFile {} script] sl@0: test socket-2.9 {socket conflict} {socket stdio} { sl@0: set s [socket -server accept 0] sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts -nonewline $f "socket -server accept [lindex [fconfigure $s -sockname] 2]" sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f sl@0: after 100 sl@0: set x [list [catch {close $f} msg]] sl@0: regsub "\n.*$" $msg {} msg ; # cut part of the error message containing the port number sl@0: lappend x $msg sl@0: close $s sl@0: set x sl@0: } {1 {couldn't open socket: address already in use}} sl@0: test socket-2.10 {close on accept, accepted socket lives} {socket} { sl@0: set done 0 sl@0: set timer [after 20000 "set done timed_out"] sl@0: set ss [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: global ss sl@0: close $ss sl@0: fileevent $s readable "readit $s" sl@0: fconfigure $s -trans lf sl@0: } sl@0: proc readit {s} { sl@0: global done sl@0: gets $s sl@0: close $s sl@0: set done 1 sl@0: } sl@0: set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]] sl@0: puts $cs hello sl@0: close $cs sl@0: vwait done sl@0: after cancel $timer sl@0: set done sl@0: } 1 sl@0: test socket-2.11 {detecting new data} {socket} { sl@0: proc accept {s a p} { sl@0: global sock sl@0: set sock $s sl@0: } sl@0: sl@0: set s [socket -server accept 0] sl@0: set sock "" sl@0: set s2 [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] sl@0: vwait sock sl@0: puts $s2 one sl@0: flush $s2 sl@0: after 500 sl@0: fconfigure $sock -blocking 0 sl@0: set result a:[gets $sock] sl@0: lappend result b:[gets $sock] sl@0: fconfigure $sock -blocking 1 sl@0: puts $s2 two sl@0: flush $s2 sl@0: fconfigure $sock -blocking 0 sl@0: lappend result c:[gets $sock] sl@0: fconfigure $sock -blocking 1 sl@0: close $s2 sl@0: close $s sl@0: close $sock sl@0: set result sl@0: } {a:one b: c:two} sl@0: sl@0: sl@0: test socket-3.1 {socket conflict} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set f [socket -server accept 0] sl@0: puts ready sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: gets stdin sl@0: close $f sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r+] sl@0: gets $f sl@0: gets $f listen sl@0: set x [list [catch {socket -server accept $listen} msg] \ sl@0: $msg] sl@0: puts $f bye sl@0: close $f sl@0: set x sl@0: } {1 {couldn't open socket: address already in use}} sl@0: test socket-3.2 {server with several clients} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set t1 [after 30000 "set x timed_out"] sl@0: set t2 [after 31000 "set x timed_out"] sl@0: set t3 [after 32000 "set x timed_out"] sl@0: set counter 0 sl@0: set s [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: fileevent $s readable [list echo $s] sl@0: fconfigure $s -buffering line sl@0: } sl@0: proc echo {s} { sl@0: global x sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: close $s sl@0: set x done sl@0: } else { sl@0: puts $s $l sl@0: } sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $s -sockname] 2] sl@0: vwait x sl@0: after cancel $t1 sl@0: vwait x sl@0: after cancel $t2 sl@0: vwait x sl@0: after cancel $t3 sl@0: close $s sl@0: puts $x sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r+] sl@0: set x [gets $f] sl@0: gets $f listen sl@0: set s1 [socket 127.0.0.1 $listen] sl@0: fconfigure $s1 -buffering line sl@0: set s2 [socket 127.0.0.1 $listen] sl@0: fconfigure $s2 -buffering line sl@0: set s3 [socket 127.0.0.1 $listen] sl@0: fconfigure $s3 -buffering line sl@0: for {set i 0} {$i < 100} {incr i} { sl@0: puts $s1 hello,s1 sl@0: gets $s1 sl@0: puts $s2 hello,s2 sl@0: gets $s2 sl@0: puts $s3 hello,s3 sl@0: gets $s3 sl@0: } sl@0: close $s1 sl@0: close $s2 sl@0: close $s3 sl@0: lappend x [gets $f] sl@0: close $f sl@0: set x sl@0: } {ready done} sl@0: sl@0: test socket-4.1 {server with several clients} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set port [gets stdin] sl@0: set s [socket 127.0.0.1 $port] sl@0: fconfigure $s -buffering line sl@0: for {set i 0} {$i < 100} {incr i} { sl@0: puts $s hello sl@0: gets $s sl@0: } sl@0: close $s sl@0: puts bye sl@0: gets stdin sl@0: } sl@0: close $f sl@0: set p1 [open "|[list [interpreter] $path(script)]" r+] sl@0: fconfigure $p1 -buffering line sl@0: set p2 [open "|[list [interpreter] $path(script)]" r+] sl@0: fconfigure $p2 -buffering line sl@0: set p3 [open "|[list [interpreter] $path(script)]" r+] sl@0: fconfigure $p3 -buffering line sl@0: proc accept {s a p} { sl@0: fconfigure $s -buffering line sl@0: fileevent $s readable [list echo $s] sl@0: } sl@0: proc echo {s} { sl@0: global x sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: close $s sl@0: set x done sl@0: } else { sl@0: puts $s $l sl@0: } sl@0: } sl@0: set t1 [after 30000 "set x timed_out"] sl@0: set t2 [after 31000 "set x timed_out"] sl@0: set t3 [after 32000 "set x timed_out"] sl@0: set s [socket -server accept 0] sl@0: set listen [lindex [fconfigure $s -sockname] 2] sl@0: puts $p1 $listen sl@0: puts $p2 $listen sl@0: puts $p3 $listen sl@0: vwait x sl@0: vwait x sl@0: vwait x sl@0: after cancel $t1 sl@0: after cancel $t2 sl@0: after cancel $t3 sl@0: close $s sl@0: set l "" sl@0: lappend l [list p1 [gets $p1] $x] sl@0: lappend l [list p2 [gets $p2] $x] sl@0: lappend l [list p3 [gets $p3] $x] sl@0: puts $p1 bye sl@0: puts $p2 bye sl@0: puts $p3 bye sl@0: close $p1 sl@0: close $p2 sl@0: close $p3 sl@0: set l sl@0: } {{p1 bye done} {p2 bye done} {p3 bye done}} sl@0: test socket-4.2 {byte order problems, socket numbers, htons} {socket} { sl@0: set x ok sl@0: if {[catch {socket -server dodo 0x3000} msg]} { sl@0: set x $msg sl@0: } else { sl@0: close $msg sl@0: } sl@0: set x sl@0: } ok sl@0: sl@0: test socket-5.1 {byte order problems, socket numbers, htons} \ sl@0: {socket unixOnly notRoot} { sl@0: set x {couldn't open socket: not owner} sl@0: if {![catch {socket -server dodo 0x1} msg]} { sl@0: set x {htons problem, should be disallowed, are you running as SU?} sl@0: close $msg sl@0: } sl@0: set x sl@0: } {couldn't open socket: not owner} sl@0: test socket-5.2 {byte order problems, socket numbers, htons} {socket} { sl@0: set x {couldn't open socket: port number too high} sl@0: if {![catch {socket -server dodo 0x10000} msg]} { sl@0: set x {port resolution problem, should be disallowed} sl@0: close $msg sl@0: } sl@0: set x sl@0: } {couldn't open socket: port number too high} sl@0: test socket-5.3 {byte order problems, socket numbers, htons} \ sl@0: {socket unixOnly notRoot} { sl@0: set x {couldn't open socket: not owner} sl@0: if {![catch {socket -server dodo 21} msg]} { sl@0: set x {htons problem, should be disallowed, are you running as SU?} sl@0: close $msg sl@0: } sl@0: set x sl@0: } {couldn't open socket: not owner} sl@0: sl@0: test socket-6.1 {accept callback error} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: gets stdin port sl@0: socket 127.0.0.1 $port sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r+] sl@0: proc bgerror args { sl@0: global x sl@0: set x $args sl@0: } sl@0: proc accept {s a p} {expr 10 / 0} sl@0: set s [socket -server accept 0] sl@0: puts $f [lindex [fconfigure $s -sockname] 2] sl@0: close $f sl@0: set timer [after 10000 "set x timed_out"] sl@0: vwait x sl@0: after cancel $timer sl@0: close $s sl@0: rename bgerror {} sl@0: set x sl@0: } {{divide by zero}} sl@0: sl@0: test socket-7.1 {testing socket specific options} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set ss [socket -server accept 0] sl@0: proc accept args { sl@0: global x sl@0: set x done sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $ss -sockname] 2] sl@0: set timer [after 10000 "set x timed_out"] sl@0: vwait x sl@0: after cancel $timer sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f sl@0: gets $f listen sl@0: set s [socket 127.0.0.1 $listen] sl@0: set p [fconfigure $s -peername] sl@0: close $s sl@0: close $f sl@0: set l "" sl@0: lappend l [string compare [lindex $p 0] 127.0.0.1] sl@0: lappend l [string compare [lindex $p 2] $listen] sl@0: lappend l [llength $p] sl@0: } {0 0 3} sl@0: test socket-7.2 {testing socket specific options} {socket stdio} { sl@0: file delete $path(script) sl@0: set f [open $path(script) w] sl@0: puts $f { sl@0: set ss [socket -server accept 2821] sl@0: proc accept args { sl@0: global x sl@0: set x done sl@0: } sl@0: puts ready sl@0: puts [lindex [fconfigure $ss -sockname] 2] sl@0: set timer [after 10000 "set x timed_out"] sl@0: vwait x sl@0: after cancel $timer sl@0: } sl@0: close $f sl@0: set f [open "|[list [interpreter] $path(script)]" r] sl@0: gets $f sl@0: gets $f listen sl@0: set s [socket 127.0.0.1 $listen] sl@0: set p [fconfigure $s -sockname] sl@0: close $s sl@0: close $f sl@0: list [llength $p] \ sl@0: [regexp {^(127\.0\.0\.1|0\.0\.0\.0)$} [lindex $p 0]] \ sl@0: [expr {[lindex $p 2] == $listen}] sl@0: } {3 1 0} sl@0: test socket-7.3 {testing socket specific options} {socket} { sl@0: set s [socket -server accept 0] sl@0: set l [fconfigure $s] sl@0: close $s sl@0: update sl@0: llength $l sl@0: } 14 sl@0: test socket-7.4 {testing socket specific options} {socket} { sl@0: set s [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: global x sl@0: set x [fconfigure $s -sockname] sl@0: close $s sl@0: } sl@0: set listen [lindex [fconfigure $s -sockname] 2] sl@0: set s1 [socket [info hostname] $listen] sl@0: set timer [after 10000 "set x timed_out"] sl@0: vwait x sl@0: after cancel $timer sl@0: close $s sl@0: close $s1 sl@0: set l "" sl@0: lappend l [expr {[lindex $x 2] == $listen}] [llength $x] sl@0: } {1 3} sl@0: test socket-7.5 {testing socket specific options} {socket unixOrPc} { sl@0: set s [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: global x sl@0: set x [fconfigure $s -sockname] sl@0: close $s sl@0: } sl@0: set listen [lindex [fconfigure $s -sockname] 2] sl@0: set s1 [socket 127.0.0.1 $listen] sl@0: set timer [after 10000 "set x timed_out"] sl@0: vwait x sl@0: after cancel $timer sl@0: close $s sl@0: close $s1 sl@0: set l "" sl@0: lappend l [lindex $x 0] [expr {[lindex $x 2] == $listen}] [llength $x] sl@0: } {127.0.0.1 1 3} sl@0: sl@0: test socket-8.1 {testing -async flag on sockets} {socket} { sl@0: # NOTE: This test may fail on some Solaris 2.4 systems. If it does, sl@0: # check that you have these patches installed (using showrev -p): sl@0: # sl@0: # 101907-05, 101925-02, 101945-14, 101959-03, 101969-05, 101973-03, sl@0: # 101977-03, 101981-02, 101985-01, 102001-03, 102003-01, 102007-01, sl@0: # 102011-02, 102024-01, 102039-01, 102044-01, 102048-01, 102062-03, sl@0: # 102066-04, 102070-01, 102105-01, 102153-03, 102216-01, 102232-01, sl@0: # 101878-03, 101879-01, 101880-03, 101933-01, 101950-01, 102030-01, sl@0: # 102057-08, 102140-01, 101920-02, 101921-09, 101922-07, 101923-03 sl@0: # sl@0: # If after installing these patches you are still experiencing a sl@0: # problem, please email jyl@eng.sun.com. We have not observed this sl@0: # failure on Solaris 2.5, so another option (instead of installing sl@0: # these patches) is to upgrade to Solaris 2.5. sl@0: set s [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: global x sl@0: puts $s bye sl@0: close $s sl@0: set x done sl@0: } sl@0: set s1 [socket -async [info hostname] [lindex [fconfigure $s -sockname] 2]] sl@0: vwait x sl@0: set z [gets $s1] sl@0: close $s sl@0: close $s1 sl@0: set z sl@0: } bye sl@0: sl@0: test socket-9.1 {testing spurious events} {socket} { sl@0: set len 0 sl@0: set spurious 0 sl@0: set done 0 sl@0: proc readlittle {s} { sl@0: global spurious done len sl@0: set l [read $s 1] sl@0: if {[string length $l] == 0} { sl@0: if {![eof $s]} { sl@0: incr spurious sl@0: } else { sl@0: close $s sl@0: set done 1 sl@0: } sl@0: } else { sl@0: incr len [string length $l] sl@0: } sl@0: } sl@0: proc accept {s a p} { sl@0: fconfigure $s -buffering none -blocking off sl@0: fileevent $s readable [list readlittle $s] sl@0: } sl@0: set s [socket -server accept 0] sl@0: set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]] sl@0: puts -nonewline $c 01234567890123456789012345678901234567890123456789 sl@0: close $c sl@0: set timer [after 10000 "set done timed_out"] sl@0: vwait done sl@0: after cancel $timer sl@0: close $s sl@0: list $spurious $len sl@0: } {0 50} sl@0: test socket-9.2 {testing async write, fileevents, flush on close} {socket} { sl@0: set firstblock "" sl@0: for {set i 0} {$i < 5} {incr i} {set firstblock "a$firstblock$firstblock"} sl@0: set secondblock "" sl@0: for {set i 0} {$i < 16} {incr i} { sl@0: set secondblock "b$secondblock$secondblock" sl@0: } sl@0: set l [socket -server accept 0] sl@0: proc accept {s a p} { sl@0: fconfigure $s -blocking 0 -translation lf -buffersize 16384 \ sl@0: -buffering line sl@0: fileevent $s readable "readable $s" sl@0: } sl@0: proc readable {s} { sl@0: set l [gets $s] sl@0: fileevent $s readable {} sl@0: after 1000 respond $s sl@0: } sl@0: proc respond {s} { sl@0: global firstblock sl@0: puts -nonewline $s $firstblock sl@0: after 1000 writedata $s sl@0: } sl@0: proc writedata {s} { sl@0: global secondblock sl@0: puts -nonewline $s $secondblock sl@0: close $s sl@0: } sl@0: set s [socket [info hostname] [lindex [fconfigure $l -sockname] 2]] sl@0: fconfigure $s -blocking 0 -trans lf -buffering line sl@0: set count 0 sl@0: puts $s hello sl@0: proc readit {s} { sl@0: global count done sl@0: set l [read $s] sl@0: incr count [string length $l] sl@0: if {[eof $s]} { sl@0: close $s sl@0: set done 1 sl@0: } sl@0: } sl@0: fileevent $s readable "readit $s" sl@0: set timer [after 10000 "set done timed_out"] sl@0: vwait done sl@0: after cancel $timer sl@0: close $l sl@0: set count sl@0: } 65566 sl@0: test socket-9.3 {testing EOF stickyness} {socket} { sl@0: proc count_to_eof {s} { sl@0: global count done timer sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: incr count sl@0: if {$count > 9} { sl@0: close $s sl@0: set done true sl@0: set count {eof is sticky} sl@0: after cancel $timer sl@0: } sl@0: } sl@0: } sl@0: proc timerproc {} { sl@0: global done count c sl@0: set done true sl@0: set count {timer went off, eof is not sticky} sl@0: close $c sl@0: } sl@0: set count 0 sl@0: set done false sl@0: proc write_then_close {s} { sl@0: puts $s bye sl@0: close $s sl@0: } sl@0: proc accept {s a p} { sl@0: fconfigure $s -buffering line -translation lf sl@0: fileevent $s writable "write_then_close $s" sl@0: } sl@0: set s [socket -server accept 0] sl@0: set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]] sl@0: fconfigure $c -blocking off -buffering line -translation lf sl@0: fileevent $c readable "count_to_eof $c" sl@0: set timer [after 1000 timerproc] sl@0: vwait done sl@0: close $s sl@0: set count sl@0: } {eof is sticky} sl@0: sl@0: removeFile script sl@0: sl@0: test socket-10.1 {testing socket accept callback error handling} {socket} { sl@0: set goterror 0 sl@0: proc bgerror args {global goterror; set goterror 1} sl@0: set s [socket -server accept 0] sl@0: proc accept {s a p} {close $s; error} sl@0: set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]] sl@0: vwait goterror sl@0: close $s sl@0: close $c sl@0: set goterror sl@0: } 1 sl@0: sl@0: test socket-11.1 {tcp connection} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set socket9_1_test_server [socket -server accept 2834] sl@0: proc accept {s a p} { sl@0: puts $s done sl@0: close $s sl@0: } sl@0: } sl@0: set s [socket $remoteServerIP 2834] sl@0: set r [gets $s] sl@0: close $s sl@0: sendCommand {close $socket9_1_test_server} sl@0: set r sl@0: } done sl@0: test socket-11.2 {client specifies its port} {socket doTestsWithRemoteServer} { sl@0: if {[info exists port]} { sl@0: incr port sl@0: } else { sl@0: set port [expr 2048 + [pid]%1024] sl@0: } sl@0: sendCommand { sl@0: set socket9_2_test_server [socket -server accept 2835] sl@0: proc accept {s a p} { sl@0: puts $s $p sl@0: close $s sl@0: } sl@0: } sl@0: set s [socket -myport $port $remoteServerIP 2835] sl@0: set r [gets $s] sl@0: close $s sl@0: sendCommand {close $socket9_2_test_server} sl@0: if {$r == $port} { sl@0: set result ok sl@0: } else { sl@0: set result broken sl@0: } sl@0: set result sl@0: } ok sl@0: test socket-11.3 {trying to connect, no server} {socket doTestsWithRemoteServer} { sl@0: set status ok sl@0: if {![catch {set s [socket $remoteServerIp 2836]}]} { sl@0: if {![catch {gets $s}]} { sl@0: set status broken sl@0: } sl@0: close $s sl@0: } sl@0: set status sl@0: } ok sl@0: test socket-11.4 {remote echo, one line} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set socket10_6_test_server [socket -server accept 2836] sl@0: proc accept {s a p} { sl@0: fileevent $s readable [list echo $s] sl@0: fconfigure $s -buffering line -translation crlf sl@0: } sl@0: proc echo {s} { sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: close $s sl@0: } else { sl@0: puts $s $l sl@0: } sl@0: } sl@0: } sl@0: set f [socket $remoteServerIP 2836] sl@0: fconfigure $f -translation crlf -buffering line sl@0: puts $f hello sl@0: set r [gets $f] sl@0: close $f sl@0: sendCommand {close $socket10_6_test_server} sl@0: set r sl@0: } hello sl@0: test socket-11.5 {remote echo, 50 lines} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set socket10_7_test_server [socket -server accept 2836] sl@0: proc accept {s a p} { sl@0: fileevent $s readable [list echo $s] sl@0: fconfigure $s -buffering line -translation crlf sl@0: } sl@0: proc echo {s} { sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: close $s sl@0: } else { sl@0: puts $s $l sl@0: } sl@0: } sl@0: } sl@0: set f [socket $remoteServerIP 2836] sl@0: fconfigure $f -translation crlf -buffering line sl@0: for {set cnt 0} {$cnt < 50} {incr cnt} { sl@0: puts $f "hello, $cnt" sl@0: if {[string compare [gets $f] "hello, $cnt"] != 0} { sl@0: break sl@0: } sl@0: } sl@0: close $f sl@0: sendCommand {close $socket10_7_test_server} sl@0: set cnt sl@0: } 50 sl@0: # Macintosh sockets can have more than one server per port sl@0: if {$tcl_platform(platform) == "macintosh"} { sl@0: set conflictResult {0 2836} sl@0: } else { sl@0: set conflictResult {1 {couldn't open socket: address already in use}} sl@0: } sl@0: test socket-11.6 {socket conflict} {socket doTestsWithRemoteServer} { sl@0: set s1 [socket -server accept 2836] sl@0: if {[catch {set s2 [socket -server accept 2836]} msg]} { sl@0: set result [list 1 $msg] sl@0: } else { sl@0: set result [list 0 [lindex [fconfigure $s2 -sockname] 2]] sl@0: close $s2 sl@0: } sl@0: close $s1 sl@0: set result sl@0: } $conflictResult sl@0: test socket-11.7 {server with several clients} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set socket10_9_test_server [socket -server accept 2836] sl@0: proc accept {s a p} { sl@0: fconfigure $s -buffering line sl@0: fileevent $s readable [list echo $s] sl@0: } sl@0: proc echo {s} { sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: close $s sl@0: } else { sl@0: puts $s $l sl@0: } sl@0: } sl@0: } sl@0: set s1 [socket $remoteServerIP 2836] sl@0: fconfigure $s1 -buffering line sl@0: set s2 [socket $remoteServerIP 2836] sl@0: fconfigure $s2 -buffering line sl@0: set s3 [socket $remoteServerIP 2836] sl@0: fconfigure $s3 -buffering line sl@0: for {set i 0} {$i < 100} {incr i} { sl@0: puts $s1 hello,s1 sl@0: gets $s1 sl@0: puts $s2 hello,s2 sl@0: gets $s2 sl@0: puts $s3 hello,s3 sl@0: gets $s3 sl@0: } sl@0: close $s1 sl@0: close $s2 sl@0: close $s3 sl@0: sendCommand {close $socket10_9_test_server} sl@0: set i sl@0: } 100 sl@0: test socket-11.8 {client with several servers} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set s1 [socket -server "accept 4003" 4003] sl@0: set s2 [socket -server "accept 4004" 4004] sl@0: set s3 [socket -server "accept 4005" 4005] sl@0: proc accept {mp s a p} { sl@0: puts $s $mp sl@0: close $s sl@0: } sl@0: } sl@0: set s1 [socket $remoteServerIP 4003] sl@0: set s2 [socket $remoteServerIP 4004] sl@0: set s3 [socket $remoteServerIP 4005] sl@0: set l "" sl@0: lappend l [gets $s1] [gets $s1] [eof $s1] [gets $s2] [gets $s2] [eof $s2] \ sl@0: [gets $s3] [gets $s3] [eof $s3] sl@0: close $s1 sl@0: close $s2 sl@0: close $s3 sl@0: sendCommand { sl@0: close $s1 sl@0: close $s2 sl@0: close $s3 sl@0: } sl@0: set l sl@0: } {4003 {} 1 4004 {} 1 4005 {} 1} sl@0: test socket-11.9 {accept callback error} {socket doTestsWithRemoteServer} { sl@0: set s [socket -server accept 2836] sl@0: proc accept {s a p} {expr 10 / 0} sl@0: proc bgerror args { sl@0: global x sl@0: set x $args sl@0: } sl@0: if {[catch {sendCommand { sl@0: set peername [fconfigure $callerSocket -peername] sl@0: set s [socket [lindex $peername 0] 2836] sl@0: close $s sl@0: }} msg]} { sl@0: close $s sl@0: error $msg sl@0: } sl@0: set timer [after 10000 "set x timed_out"] sl@0: vwait x sl@0: after cancel $timer sl@0: close $s sl@0: rename bgerror {} sl@0: set x sl@0: } {{divide by zero}} sl@0: test socket-11.10 {testing socket specific options} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set socket10_12_test_server [socket -server accept 2836] sl@0: proc accept {s a p} {close $s} sl@0: } sl@0: set s [socket $remoteServerIP 2836] sl@0: set p [fconfigure $s -peername] sl@0: set n [fconfigure $s -sockname] sl@0: set l "" sl@0: lappend l [lindex $p 2] [llength $p] [llength $p] sl@0: close $s sl@0: sendCommand {close $socket10_12_test_server} sl@0: set l sl@0: } {2836 3 3} sl@0: test socket-11.11 {testing spurious events} {socket doTestsWithRemoteServer} { sl@0: sendCommand { sl@0: set socket10_13_test_server [socket -server accept 2836] sl@0: proc accept {s a p} { sl@0: fconfigure $s -translation "auto lf" sl@0: after 100 writesome $s sl@0: } sl@0: proc writesome {s} { sl@0: for {set i 0} {$i < 100} {incr i} { sl@0: puts $s "line $i from remote server" sl@0: } sl@0: close $s sl@0: } sl@0: } sl@0: set len 0 sl@0: set spurious 0 sl@0: set done 0 sl@0: proc readlittle {s} { sl@0: global spurious done len sl@0: set l [read $s 1] sl@0: if {[string length $l] == 0} { sl@0: if {![eof $s]} { sl@0: incr spurious sl@0: } else { sl@0: close $s sl@0: set done 1 sl@0: } sl@0: } else { sl@0: incr len [string length $l] sl@0: } sl@0: } sl@0: set c [socket $remoteServerIP 2836] sl@0: fileevent $c readable "readlittle $c" sl@0: set timer [after 40000 "set done timed_out"] sl@0: vwait done sl@0: after cancel $timer sl@0: sendCommand {close $socket10_13_test_server} sl@0: list $spurious $len $done sl@0: } {0 2690 1} sl@0: sl@0: test socket-11.12 {testing EOF stickyness} {socket doTestsWithRemoteServer} { sl@0: set counter 0 sl@0: set done 0 sl@0: proc count_up {s} { sl@0: global counter done after_id sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: incr counter sl@0: if {$counter > 9} { sl@0: set done {EOF is sticky} sl@0: after cancel $after_id sl@0: close $s sl@0: } sl@0: } sl@0: } sl@0: proc timed_out {} { sl@0: global c done sl@0: set done {timed_out, EOF is not sticky} sl@0: close $c sl@0: } sl@0: sendCommand { sl@0: set socket10_14_test_server [socket -server accept 2836] sl@0: proc accept {s a p} { sl@0: after 100 close $s sl@0: } sl@0: } sl@0: set c [socket $remoteServerIP 2836] sl@0: fileevent $c readable [list count_up $c] sl@0: set after_id [after 1000 timed_out] sl@0: vwait done sl@0: sendCommand {close $socket10_14_test_server} sl@0: set done sl@0: } {EOF is sticky} sl@0: sl@0: test socket-11.13 {testing async write, async flush, async close} \ sl@0: {socket doTestsWithRemoteServer} { sl@0: proc readit {s} { sl@0: global count done sl@0: set l [read $s] sl@0: incr count [string length $l] sl@0: if {[eof $s]} { sl@0: close $s sl@0: set done 1 sl@0: } sl@0: } sl@0: sendCommand { sl@0: set firstblock "" sl@0: for {set i 0} {$i < 5} {incr i} { sl@0: set firstblock "a$firstblock$firstblock" sl@0: } sl@0: set secondblock "" sl@0: for {set i 0} {$i < 16} {incr i} { sl@0: set secondblock "b$secondblock$secondblock" sl@0: } sl@0: set l [socket -server accept 2845] sl@0: proc accept {s a p} { sl@0: fconfigure $s -blocking 0 -translation lf -buffersize 16384 \ sl@0: -buffering line sl@0: fileevent $s readable "readable $s" sl@0: } sl@0: proc readable {s} { sl@0: set l [gets $s] sl@0: fileevent $s readable {} sl@0: after 1000 respond $s sl@0: } sl@0: proc respond {s} { sl@0: global firstblock sl@0: puts -nonewline $s $firstblock sl@0: after 1000 writedata $s sl@0: } sl@0: proc writedata {s} { sl@0: global secondblock sl@0: puts -nonewline $s $secondblock sl@0: close $s sl@0: } sl@0: } sl@0: set s [socket $remoteServerIP 2845] sl@0: fconfigure $s -blocking 0 -trans lf -buffering line sl@0: set count 0 sl@0: puts $s hello sl@0: fileevent $s readable "readit $s" sl@0: set timer [after 10000 "set done timed_out"] sl@0: vwait done sl@0: after cancel $timer sl@0: sendCommand {close $l} sl@0: set count sl@0: } 65566 sl@0: sl@0: set path(script1) [makeFile {} script1] sl@0: set path(script2) [makeFile {} script2] sl@0: sl@0: test socket-12.1 {testing inheritance of server sockets} {socket stdio exec} { sl@0: file delete $path(script1) sl@0: file delete $path(script2) sl@0: sl@0: # Script1 is just a 10 second delay. If the server socket sl@0: # is inherited, it will be held open for 10 seconds sl@0: sl@0: set f [open $path(script1) w] sl@0: puts $f { sl@0: after 10000 exit sl@0: vwait forever sl@0: } sl@0: close $f sl@0: sl@0: # Script2 creates the server socket, launches script1, sl@0: # waits a second, and exits. The server socket will now sl@0: # be closed unless script1 inherited it. sl@0: sl@0: set f [open $path(script2) w] sl@0: puts $f [list set tcltest [interpreter]] sl@0: puts -nonewline $f { sl@0: set f [socket -server accept 0] sl@0: puts [lindex [fconfigure $f -sockname] 2] sl@0: proc accept { file addr port } { sl@0: close $file sl@0: } sl@0: exec $tcltest } sl@0: puts $f [list $path(script1) &] sl@0: puts $f { sl@0: close $f sl@0: after 1000 exit sl@0: vwait forever sl@0: } sl@0: close $f sl@0: sl@0: # Launch script2 and wait 5 seconds sl@0: sl@0: ### exec [interpreter] script2 & sl@0: set p [open "|[list [interpreter] $path(script2)]" r] sl@0: gets $p listen sl@0: sl@0: after 5000 { set ok_to_proceed 1 } sl@0: vwait ok_to_proceed sl@0: sl@0: # If we can still connect to the server, the socket got inherited. sl@0: sl@0: if {[catch {socket 127.0.0.1 $listen} msg]} { sl@0: set x {server socket was not inherited} sl@0: } else { sl@0: close $msg sl@0: set x {server socket was inherited} sl@0: } sl@0: sl@0: close $p sl@0: set x sl@0: } {server socket was not inherited} sl@0: test socket-12.2 {testing inheritance of client sockets} {socket stdio exec} { sl@0: file delete $path(script1) sl@0: file delete $path(script2) sl@0: sl@0: # Script1 is just a 20 second delay. If the server socket sl@0: # is inherited, it will be held open for 10 seconds sl@0: sl@0: set f [open $path(script1) w] sl@0: puts $f { sl@0: after 20000 exit sl@0: vwait forever sl@0: } sl@0: close $f sl@0: sl@0: # Script2 opens the client socket and writes to it. It then sl@0: # launches script1 and exits. If the child process inherited the sl@0: # client socket, the socket will still be open. sl@0: sl@0: set f [open $path(script2) w] sl@0: puts $f [list set tcltest [interpreter]] sl@0: puts -nonewline $f { sl@0: gets stdin port sl@0: set f [socket 127.0.0.1 $port] sl@0: exec $tcltest } sl@0: puts $f [list $path(script1) &] sl@0: puts $f { sl@0: puts $f testing sl@0: flush $f sl@0: after 1000 exit sl@0: vwait forever sl@0: } sl@0: close $f sl@0: sl@0: # Create the server socket sl@0: sl@0: set server [socket -server accept 0] sl@0: proc accept { file host port } { sl@0: # When the client connects, establish the read handler sl@0: global server sl@0: close $server sl@0: fileevent $file readable [list getdata $file] sl@0: fconfigure $file -buffering line -blocking 0 sl@0: return sl@0: } sl@0: proc getdata { file } { sl@0: # Read handler on the accepted socket. sl@0: global x sl@0: global failed sl@0: set status [catch {read $file} data] sl@0: if {$status != 0} { sl@0: set x {read failed, error was $data} sl@0: catch { close $file } sl@0: } elseif {[string compare {} $data]} { sl@0: } elseif {[fblocked $file]} { sl@0: } elseif {[eof $file]} { sl@0: if {$failed} { sl@0: set x {client socket was inherited} sl@0: } else { sl@0: set x {client socket was not inherited} sl@0: } sl@0: catch { close $file } sl@0: } else { sl@0: set x {impossible case} sl@0: catch { close $file } sl@0: } sl@0: return sl@0: } sl@0: sl@0: # If the socket doesn't hit end-of-file in 10 seconds, the sl@0: # script1 process must have inherited the client. sl@0: sl@0: set failed 0 sl@0: after 10000 [list set failed 1] sl@0: sl@0: # Launch the script2 process sl@0: ### exec [interpreter] script2 & sl@0: sl@0: set p [open "|[list [interpreter] $path(script2)]" w] sl@0: puts $p [lindex [fconfigure $server -sockname] 2] ; flush $p sl@0: sl@0: vwait x sl@0: if {!$failed} { sl@0: vwait failed sl@0: } sl@0: close $p sl@0: set x sl@0: } {client socket was not inherited} sl@0: test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} { sl@0: file delete $path(script1) sl@0: file delete $path(script2) sl@0: sl@0: set f [open $path(script1) w] sl@0: puts $f { sl@0: after 10000 exit sl@0: vwait forever sl@0: } sl@0: close $f sl@0: sl@0: set f [open $path(script2) w] sl@0: puts $f [list set tcltest [interpreter]] sl@0: puts -nonewline $f { sl@0: set server [socket -server accept 0] sl@0: puts stdout [lindex [fconfigure $server -sockname] 2] sl@0: proc accept { file host port } } sl@0: puts $f \{ sl@0: puts -nonewline $f { sl@0: global tcltest sl@0: puts $file {test data on socket} sl@0: exec $tcltest } sl@0: puts $f [list $path(script1) &] sl@0: puts $f { sl@0: after 1000 exit sl@0: } sl@0: puts $f \} sl@0: puts $f { sl@0: vwait forever sl@0: } sl@0: close $f sl@0: sl@0: # Launch the script2 process and connect to it. See how long sl@0: # the socket stays open sl@0: sl@0: ## exec [interpreter] script2 & sl@0: set p [open "|[list [interpreter] $path(script2)]" r] sl@0: gets $p listen sl@0: sl@0: after 1000 set ok_to_proceed 1 sl@0: vwait ok_to_proceed sl@0: sl@0: set f [socket 127.0.0.1 $listen] sl@0: fconfigure $f -buffering full -blocking 0 sl@0: fileevent $f readable [list getdata $f] sl@0: sl@0: # If the socket is still open after 5 seconds, the script1 process sl@0: # must have inherited the accepted socket. sl@0: sl@0: set failed 0 sl@0: after 5000 set failed 1 sl@0: sl@0: proc getdata { file } { sl@0: # Read handler on the client socket. sl@0: global x sl@0: global failed sl@0: set status [catch {read $file} data] sl@0: if {$status != 0} { sl@0: set x {read failed, error was $data} sl@0: catch { close $file } sl@0: } elseif {[string compare {} $data]} { sl@0: } elseif {[fblocked $file]} { sl@0: } elseif {[eof $file]} { sl@0: if {$failed} { sl@0: set x {accepted socket was inherited} sl@0: } else { sl@0: set x {accepted socket was not inherited} sl@0: } sl@0: catch { close $file } sl@0: } else { sl@0: set x {impossible case} sl@0: catch { close $file } sl@0: } sl@0: return sl@0: } sl@0: sl@0: vwait x sl@0: sl@0: close $p sl@0: set x sl@0: } {accepted socket was not inherited} sl@0: sl@0: test socket-13.1 {Testing use of shared socket between two threads} \ sl@0: -constraints {socket testthread} -setup { sl@0: sl@0: threadReap sl@0: sl@0: set path(script) [makeFile { sl@0: set f [socket -server accept 0] sl@0: set listen [lindex [fconfigure $f -sockname] 2] sl@0: proc accept {s a p} { sl@0: fileevent $s readable [list echo $s] sl@0: fconfigure $s -buffering line sl@0: } sl@0: proc echo {s} { sl@0: global i sl@0: set l [gets $s] sl@0: if {[eof $s]} { sl@0: global x sl@0: close $s sl@0: set x done sl@0: } else { sl@0: incr i sl@0: puts $s $l sl@0: } sl@0: } sl@0: set i 0 sl@0: vwait x sl@0: close $f sl@0: sl@0: # thread cleans itself up. sl@0: testthread exit sl@0: } script] sl@0: sl@0: } -body { sl@0: # create a thread sl@0: set serverthread [testthread create [list source $path(script) ] ] sl@0: update sl@0: set port [testthread send $serverthread {set listen}] sl@0: update sl@0: sl@0: after 1000 sl@0: set s [socket 127.0.0.1 $port] sl@0: fconfigure $s -buffering line sl@0: sl@0: catch { sl@0: puts $s "hello" sl@0: gets $s result sl@0: } sl@0: close $s sl@0: update sl@0: sl@0: after 2000 sl@0: lappend result [threadReap] sl@0: } -cleanup { sl@0: removeFile script sl@0: } -result {hello 1} sl@0: sl@0: removeFile script1 sl@0: removeFile script2 sl@0: sl@0: # cleanup sl@0: if {[string match sock* $commandSocket] == 1} { sl@0: puts $commandSocket exit sl@0: flush $commandSocket sl@0: } sl@0: catch {close $commandSocket} sl@0: catch {close $remoteProcChan} sl@0: ::tcltest::cleanupTests sl@0: flush stdout sl@0: return