# Commands tested in this file: socket.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 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
# server will be performed; otherwise, it will attempt to start the remote
# server (via exec) on platforms that support this, on the local host,
# listening at port 2048. If all fails, a message is printed and the tests
# using the remote server are not performed.
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]]
# Produce a random port number in the Dynamic/Private range
# from 49152 through 65535.
proc randport {} { expr {int(rand()*16383+49152)} }
# Test the latency of tcp connections over the loopback interface. Some OSes
# (e.g. NetBSD) seem to use the Nagle algorithm and delayed ACKs, so it takes
# up to 200ms for a packet sent to localhost to arrive. We're measuring this
# here, so that OSes that don't have this problem can run the tests at full
# speed.
set server [socket -server {apply {{s a p} {set ::s1 $s}}} 0]
set s2 [socket localhost [lindex [fconfigure $server -sockname] 2]]
vwait s1; close $server
fconfigure $s1 -buffering line
fconfigure $s2 -buffering line
set t1 [clock milliseconds]
puts $s2 test1; gets $s1
puts $s2 test2; gets $s1
close $s1; close $s2
set t2 [clock milliseconds]
set latency [expr {($t2-$t1)*2}]; # doubled as a safety margin
unset t1 t2 s1 s2 server
# If remoteServerIP or remoteServerPort are not set, check in the environment
# variables for externally set values.
#
if {![info exists remoteServerIP]} {
if {[info exists env(remoteServerIP)]} {
set remoteServerIP $env(remoteServerIP)
}
}
if {![info exists remoteServerPort]} {
if {[info exists env(remoteServerPort)]} {
set remoteServerPort $env(remoteServerPort)
} else {
if {[info exists remoteServerIP]} {
set remoteServerPort 2048
}
}
}
if 0 {
# activate this to time the tests
proc test {args} {
set name [lindex $args 0]
puts "[lindex [time {uplevel [linsert $args 0 tcltest::test]}] 0] @@@ $name"
}
}
foreach {af localhost} {
any 127.0.0.1
inet 127.0.0.1
inet6 ::1
} {
set ::tcl::unsupported::socketAF $af
# Check if the family is supported and set the constraint accordingly
testConstraint supported_$af [expr {![catch {socket -server foo 0} sock]}]
catch {close $sock}
#
# Check if we're supposed to do tests against the remote server
#
set doTestsWithRemoteServer 1
if {![info exists remoteServerIP]} {
set remoteServerIP $localhost
}
if {($doTestsWithRemoteServer == 1) && (![info exists remoteServerPort])} {
set remoteServerPort [randport]
}
# Attempt to connect to a remote server if one is already running. If it is
# not running or for some other reason the connect fails, attempt to start the
# remote server on the local host listening on port 2048. This is only done on
# platforms that support exec (i.e. not on the Mac). On platforms that do not
# support exec, the remote server must be started by the user before running
# the tests.
set remoteProcChan ""
set commandSocket ""
if {$doTestsWithRemoteServer} {
catch {close $commandSocket}
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 $localhost
# 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 {
gets $remoteProcChan
if {[catch {
set commandSocket [socket $remoteServerIP $remoteServerPort]
} msg] == 0} then {
fconfigure $commandSocket -translation crlf -buffering line
} else {
set noRemoteTestReason $msg
set doTestsWithRemoteServer 0
}
} else {
set noRemoteTestReason "$msg [interpreter]"
set doTestsWithRemoteServer 0
}
}
}
# Some tests are run only if we are doing testing against a remote server.
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."
puts "Reason for not doing remote tests: $noRemoteTestReason"
}
}
#
# If we do the tests, define a command to send a command to the remote server.
#
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"
}
if {[catch {puts $commandSocket "--Marker--Marker--Marker--"} msg]} {
error "remote server disappeared: $msg"
}
while {1} {
set line [gets $commandSocket]
if {[eof $commandSocket]} {
error "remote server disappaered"
}
if {$line eq "--Marker--Marker--Marker--"} {
lassign $result code info value
return -code $code -errorinfo $info $value
}
append result $line "\n"
}
}
}
proc getPort sock {
lindex [fconfigure $sock -sockname] 2
}
# ----------------------------------------------------------------------
test socket_$af-1.1 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -server
} -returnCodes error -result {no argument given for -server option}
test socket_$af-1.2 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -server foo
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
test socket_$af-1.3 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -myaddr
} -returnCodes error -result {no argument given for -myaddr option}
test socket_$af-1.4 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -myaddr $localhost
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
test socket_$af-1.5 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -myport
} -returnCodes error -result {no argument given for -myport option}
test socket_$af-1.6 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -myport xxxx
} -returnCodes error -result {expected integer but got "xxxx"}
test socket_$af-1.7 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -myport 2522
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
test socket_$af-1.8 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -froboz
} -returnCodes error -result {bad option "-froboz": must be -async, -myaddr, -myport, or -server}
test socket_$af-1.9 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -server foo -myport 2521 3333
} -returnCodes error -result {option -myport is not valid for servers}
test socket_$af-1.10 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket host 2528 -junk
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
test socket_$af-1.11 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -server callback 2520 --
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}
test socket_$af-1.12 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket foo badport
} -returnCodes error -result {expected integer but got "badport"}
test socket_$af-1.13 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -async -server
} -returnCodes error -result {cannot set -async option for server sockets}
test socket_$af-1.14 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
socket -server foo -async
} -returnCodes error -result {cannot set -async option for server sockets}
set path(script) [makeFile {} script]
test socket_$af-2.1 {tcp connection} -constraints [list socket supported_$af stdio] -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f {
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 [interpreter] $path(script)]" r]
gets $f x
gets $f listen
} -body {
# $x == "ready" at this point
set sock [socket $localhost $listen]
lappend x [gets $f]
close $sock
lappend x [gets $f]
} -cleanup {
close $f
} -result {ready done {}}
test socket_$af-2.2 {tcp connection with client port specified} -setup {
set port [randport]
file delete $path(script)
set f [open $path(script) w]
puts $f {
set timer [after 10000 "set x timeout"]
set f [socket -server accept 0]
proc accept {file addr port} {
global x
puts "[gets $file] $port"
close $file
set x done
}
puts ready
puts [lindex [fconfigure $f -sockname] 2]
vwait x
after cancel $timer
close $f
}
close $f
set f [open "|[list [interpreter] $path(script)]" r]
gets $f x
gets $f listen
} -constraints [list socket supported_$af stdio] -body {
# $x == "ready" at this point
set sock [socket -myport $port $localhost $listen]
puts $sock hello
flush $sock
lappend x [expr {[gets $f] eq "hello $port"}]
close $sock
return $x
} -cleanup {
catch {close [socket $localhost $listen]}
close $f
} -result {ready 1}
test socket_$af-2.3 {tcp connection with client interface specified} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f {
set timer [after 2000 "set x done"]
set f [socket -server accept 0]
proc accept {file addr port} {
global x
puts "[gets $file] $addr"
close $file
set x done
}
puts [lindex [fconfigure $f -sockname] 2]
puts ready
vwait x
after cancel $timer
close $f
}
close $f
set f [open "|[list [interpreter] $path(script)]" r]
gets $f listen
gets $f x
} -constraints [list socket supported_$af stdio] -body {
# $x == "ready" at this point
set sock [socket -myaddr $localhost $localhost $listen]
puts $sock hello
flush $sock
lappend x [gets $f]
close $sock
return $x
} -cleanup {
close $f
} -result [list ready [list hello $localhost]]
test socket_$af-2.4 {tcp connection with server interface specified} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f [list set localhost $localhost]
puts $f {
set timer [after 2000 "set x done"]
set f [socket -server accept -myaddr $localhost 0]
proc accept {file addr port} {
global x
puts "[gets $file]"
close $file
set x done
}
puts ready
puts [lindex [fconfigure $f -sockname] 2]
vwait x
after cancel $timer
close $f
}
close $f
set f [open "|[list [interpreter] $path(script)]" r]
gets $f x
gets $f listen
} -constraints [list socket supported_$af stdio] -body {
# $x == "ready" at this point
set sock [socket $localhost $listen]
puts $sock hello
flush $sock
lappend x [gets $f]
close $sock
return $x
} -cleanup {
close $f
} -result {ready hello}
test socket_$af-2.5 {tcp connection with redundant server port} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f {
set timer [after 10000 "set x timeout"]
set f [socket -server accept 0]
proc accept {file addr port} {
global x
puts "[gets $file]"
close $file
set x done
}
puts ready
puts [lindex [fconfigure $f -sockname] 2]
vwait x
after cancel $timer
close $f
}
close $f
set f [open "|[list [interpreter] $path(script)]" r]
gets $f x
gets $f listen
} -constraints [list socket supported_$af stdio] -body {
# $x == "ready" at this point
set sock [socket $localhost $listen]
puts $sock hello
flush $sock
lappend x [gets $f]
close $sock
return $x
} -cleanup {
close $f
} -result {ready hello}
test socket_$af-2.6 {tcp connection} -constraints [list socket supported_$af] -body {
set status ok
if {![catch {set sock [socket $localhost [randport]]}]} {
if {![catch {gets $sock}]} {
set status broken
}
close $sock
}
set status
} -result ok
test socket_$af-2.7 {echo server, one line} -constraints [list socket supported_$af stdio] -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f {
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
}
proc echo {s} {
set l [gets $s]
if {[eof $s]} {
global x
close $s
set x done
} else {
puts $s $l
}
}
puts ready
puts [lindex [fconfigure $f -sockname] 2]
vwait x
after cancel $timer
close $f
puts $x
}
close $f
set f [open "|[list [interpreter] $path(script)]" r]
gets $f
gets $f listen
} -body {
set s [socket $localhost $listen]
fconfigure $s -buffering line -translation lf
puts $s "hello abcdefghijklmnop"
set x [gets $s]
close $s
list $x [gets $f]
} -cleanup {
close $f
} -result {{hello abcdefghijklmnop} done}
removeFile script
test socket_$af-2.8 {echo server, loop 50 times, single connection} -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
}
proc echo {s} {
global i
set l [gets $s]
if {[eof $s]} {
global x
close $s
set x done
} 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 [interpreter] $path(script)]" r]
gets $f
gets $f listen
} -constraints [list socket supported_$af stdio] -body {
set s [socket $localhost $listen]
fconfigure $s -buffering line
catch {
for {set x 0} {$x < 50} {incr x} {
puts $s "hello abcdefghijklmnop"
gets $s
}
}
close $s
catch {set x [gets $f]}
return $x
} -cleanup {
close $f
removeFile script
} -result {done 50}
set path(script) [makeFile {} script]
test socket_$af-2.9 {socket conflict} -constraints [list socket supported_$af stdio] -body {
set s [socket -server accept 0]
file delete $path(script)
set f [open $path(script) w]
puts $f [list set ::tcl::unsupported::socketAF $::tcl::unsupported::socketAF]
puts $f "socket -server accept [lindex [fconfigure $s -sockname] 2]"
close $f
set f [open "|[list [interpreter] $path(script)]" r]
gets $f
after 100
close $f
} -returnCodes error -cleanup {
close $s
} -match glob -result {couldn't open socket: address already in use*}
test socket_$af-2.10 {close on accept, accepted socket lives} -setup {
set done 0
set timer [after 20000 "set done timed_out"]
} -constraints [list socket supported_$af] -body {
set ss [socket -server accept 0]
proc accept {s a p} {
global ss
close $ss
fileevent $s readable "readit $s"
fconfigure $s -trans lf
}
proc readit {s} {
global done
gets $s
close $s
set done 1
}
set cs [socket $localhost [lindex [fconfigure $ss -sockname] 2]]
puts $cs hello
close $cs
vwait done
return $done
} -cleanup {
after cancel $timer
} -result 1
test socket_$af-2.11 {detecting new data} -constraints [list socket supported_$af] -setup {
proc accept {s a p} {
global sock
set sock $s
}
set s [socket -server accept 0]
set sock ""
} -body {
set s2 [socket $localhost [lindex [fconfigure $s -sockname] 2]]
vwait sock
puts $s2 one
flush $s2
after idle {set x 1}
vwait x
fconfigure $sock -blocking 0
set result a:[gets $sock]
lappend result b:[gets $sock]
fconfigure $sock -blocking 1
puts $s2 two
flush $s2
after $latency {set x 1}; # NetBSD fails here if we do [after idle]
vwait x
fconfigure $sock -blocking 0
lappend result c:[gets $sock]
} -cleanup {
fconfigure $sock -blocking 1
close $s2
close $s
close $sock
} -result {a:one b: c:two}
test socket_$af-3.1 {socket conflict} -constraints [list socket supported_$af stdio] -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f [list set localhost $localhost]
puts $f {
set f [socket -server accept -myaddr $localhost 0]
puts ready
puts [lindex [fconfigure $f -sockname] 2]
gets stdin
close $f
}
close $f
set f [open "|[list [interpreter] $path(script)]" r+]
gets $f
gets $f listen
} -body {
socket -server accept -myaddr $localhost $listen
} -cleanup {
puts $f bye
close $f
} -returnCodes error -result {couldn't open socket: address already in use}
test socket_$af-3.2 {server with several clients} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f [list set localhost $localhost]
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 -myaddr $localhost 0]
proc accept {s a p} {
fileevent $s readable [list echo $s]
fconfigure $s -buffering line
}
proc echo {s} {
global x
set l [gets $s]
if {[eof $s]} {
close $s
set x done
} else {
puts $s $l
}
}
puts ready
puts [lindex [fconfigure $s -sockname] 2]
vwait x
after cancel $t1
vwait x
after cancel $t2
vwait x
after cancel $t3
close $s
puts $x
}
close $f
set f [open "|[list [interpreter] $path(script)]" r+]
set x [gets $f]
gets $f listen
} -constraints [list socket supported_$af stdio] -body {
# $x == "ready" here
set s1 [socket $localhost $listen]
fconfigure $s1 -buffering line
set s2 [socket $localhost $listen]
fconfigure $s2 -buffering line
set s3 [socket $localhost $listen]
fconfigure $s3 -buffering line
for {set i 0} {$i < 100} {incr i} {
puts $s1 hello,s1
gets $s1
puts $s2 hello,s2
gets $s2
puts $s3 hello,s3
gets $s3
}
close $s1
close $s2
close $s3
lappend x [gets $f]
} -cleanup {
close $f
} -result {ready done}
test socket_$af-4.1 {server with several clients} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f [list set localhost $localhost]
puts $f {
set port [gets stdin]
set s [socket $localhost $port]
fconfigure $s -buffering line
for {set i 0} {$i < 100} {incr i} {
puts $s hello
gets $s
}
close $s
puts bye
gets stdin
}
close $f
set p1 [open "|[list [interpreter] $path(script)]" r+]
fconfigure $p1 -buffering line
set p2 [open "|[list [interpreter] $path(script)]" r+]
fconfigure $p2 -buffering line
set p3 [open "|[list [interpreter] $path(script)]" r+]
fconfigure $p3 -buffering line
} -constraints [list socket supported_$af stdio] -body {
proc accept {s a p} {
fconfigure $s -buffering line
fileevent $s readable [list echo $s]
}
proc echo {s} {
global x
set l [gets $s]
if {[eof $s]} {
close $s
set x done
} else {
puts $s $l
}
}
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 -myaddr $localhost 0]
set listen [lindex [fconfigure $s -sockname] 2]
puts $p1 $listen
puts $p2 $listen
puts $p3 $listen
vwait x
vwait x
vwait x
after cancel $t1
after cancel $t2
after cancel $t3
close $s
set l ""
lappend l [list p1 [gets $p1] $x]
lappend l [list p2 [gets $p2] $x]
lappend l [list p3 [gets $p3] $x]
} -cleanup {
puts $p1 bye
puts $p2 bye
puts $p3 bye
close $p1
close $p2
close $p3
} -result {{p1 bye done} {p2 bye done} {p3 bye done}}
test socket_$af-4.2 {byte order problems, socket numbers, htons} -body {
close [socket -server dodo -myaddr $localhost 0x3000]
return ok
} -constraints [list socket supported_$af] -result ok
test socket_$af-5.1 {byte order problems, socket numbers, htons} -body {
if {![catch {socket -server dodo 0x1} msg]} {
close $msg
return {htons problem, should be disallowed, are you running as SU?}
}
return {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot] -result {couldn't open socket: not owner}
test socket_$af-5.2 {byte order problems, socket numbers, htons} -body {
if {![catch {socket -server dodo 0x10000} msg]} {
close $msg
return {port resolution problem, should be disallowed}
}
return {couldn't open socket: port number too high}
} -constraints [list socket supported_$af] -result {couldn't open socket: port number too high}
test socket_$af-5.3 {byte order problems, socket numbers, htons} -body {
if {![catch {socket -server dodo 21} msg]} {
close $msg
return {htons problem, should be disallowed, are you running as SU?}
}
return {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot] -result {couldn't open socket: not owner}
test socket_$af-6.1 {accept callback error} -constraints [list socket supported_$af 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 [list set localhost $localhost]
puts $f {
gets stdin port
socket $localhost $port
}
close $f
set f [open "|[list [interpreter] $path(script)]" r+]
proc accept {s a p} {expr 10 / 0}
set s [socket -server accept -myaddr $localhost 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
return $x
} -cleanup {
interp bgerror {} $handler
} -result {divide by zero}
test socket_$af-6.2 {
readable fileevent on server socket
} -setup {
set sock [socket -server dummy 0]
} -body {
fileevent $sock readable dummy
} -cleanup {
close $sock
} -returnCodes 1 -result "channel is not readable"
test socket_$af-6.3 {writable fileevent on server socket} -setup {
set sock [socket -server dummy 0]
} -body {
fileevent $sock writable dummy
} -cleanup {
close $sock
} -returnCodes 1 -result "channel is not writable"
test socket_$af-7.1 {testing socket specific options} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f {
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 [interpreter] $path(script)]" r]
gets $f
gets $f listen
set l ""
} -constraints [list socket supported_$af stdio] -body {
set s [socket $localhost $listen]
set p [fconfigure $s -peername]
close $s
lappend l [string compare [lindex $p 0] $localhost]
lappend l [string compare [lindex $p 2] $listen]
lappend l [llength $p]
} -cleanup {
close $f
} -result {0 0 3}
test socket_$af-7.2 {testing socket specific options} -setup {
file delete $path(script)
set f [open $path(script) w]
puts $f [list set ::tcl::unsupported::socketAF $::tcl::unsupported::socketAF]
puts $f {
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 [interpreter] $path(script)]" r]
gets $f
gets $f listen
} -constraints [list socket supported_$af stdio] -body {
set s [socket $localhost $listen]
set p [fconfigure $s -sockname]
close $s
list [llength $p] \
[regexp {^(127\.0\.0\.1|0\.0\.0\.0|::1)$} [lindex $p 0]] \
[expr {[lindex $p 2] == $listen}]
} -cleanup {
close $f
} -result {3 1 0}
test socket_$af-7.3 {testing socket specific options} -constraints [list socket supported_$af] -body {
set s [socket -server accept -myaddr $localhost 0]
set l [fconfigure $s]
close $s
update
llength $l
} -result 14
test socket_$af-7.4 {testing socket specific options} -constraints [list socket supported_$af] -setup {
set timer [after 10000 "set x timed_out"]
set l ""
} -body {
set s [socket -server accept -myaddr $localhost 0]
proc accept {s a p} {
global x
set x [fconfigure $s -sockname]
close $s
}
set listen [lindex [fconfigure $s -sockname] 2]
set s1 [socket $localhost $listen]
vwait x
lappend l [expr {[lindex $x 2] == $listen}] [llength $x]
} -cleanup {
after cancel $timer
close $s
close $s1
} -result {1 3}
test socket_$af-7.5 {testing socket specific options} -setup {
set timer [after 10000 "set x timed_out"]
set l ""
} -constraints [list socket supported_$af unixOrPc] -body {
set s [socket -server accept 0]
proc accept {s a p} {
global x
set x [fconfigure $s -sockname]
close $s
}
set listen [lindex [fconfigure $s -sockname] 2]
set s1 [socket $localhost $listen]
vwait x
lappend l [lindex $x 0] [expr {[lindex $x 2] == $listen}] [llength $x]
} -cleanup {
after cancel $timer
close $s
close $s1
} -result [list $localhost 1 3]
test socket_$af-8.1 {testing -async flag on sockets} -constraints [list socket supported_$af] -body {
# NOTE: This test may fail on some Solaris 2.4 systems. If it does, check
# that you have these patches installed (using showrev -p):
#
# 101907-05, 101925-02, 101945-14, 101959-03, 101969-05, 101973-03,
# 101977-03, 101981-02, 101985-01, 102001-03, 102003-01, 102007-01,
# 102011-02, 102024-01, 102039-01, 102044-01, 102048-01, 102062-03,
# 102066-04, 102070-01, 102105-01, 102153-03, 102216-01, 102232-01,
# 101878-03, 101879-01, 101880-03, 101933-01, 101950-01, 102030-01,
# 102057-08, 102140-01, 101920-02, 101921-09, 101922-07, 101923-03
#
# If after installing these patches you are still experiencing a 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 -myaddr $localhost 0]
proc accept {s a p} {
global x
puts $s bye
close $s
set x done
}
set s1 [socket -async $localhost [lindex [fconfigure $s -sockname] 2]]
vwait x
gets $s1
} -cleanup {
close $s
close $s1
} -result bye
test socket_$af-9.1 {testing spurious events} -constraints [list socket supported_$af] -setup {
set len 0
set spurious 0
set done 0
set timer [after 10000 "set done timed_out"]
} -body {
proc readlittle {s} {
global spurious done len
set l [read $s 1]
if {[string length $l] == 0} {
if {![eof $s]} {
incr spurious
} else {
close $s
set done 1
}
} else {
incr len [string length $l]
}
}
proc accept {s a p} {
fconfigure $s -buffering none -blocking off
fileevent $s readable [list readlittle $s]
}
set s [socket -server accept -myaddr $localhost 0]
set c [socket $localhost [lindex [fconfigure $s -sockname] 2]]
puts -nonewline $c 01234567890123456789012345678901234567890123456789
close $c
vwait done
close $s
list $spurious $len
} -cleanup {
after cancel $timer
} -result {0 50}
test socket_$af-9.2 {testing async write, fileevents, flush on close} -constraints [list socket supported_$af] -setup {
set firstblock ""
for {set i 0} {$i < 5} {incr i} {set firstblock "a$firstblock$firstblock"}
set secondblock ""
for {set i 0} {$i < 16} {incr i} {
set secondblock "b$secondblock$secondblock"
}
set timer [after 10000 "set done timed_out"]
set l [socket -server accept -myaddr $localhost 0]
proc accept {s a p} {
fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
-buffering line
fileevent $s readable "readable $s"
}
proc readable {s} {
set l [gets $s]
fileevent $s readable {}
after idle respond $s
}
proc respond {s} {
global firstblock
puts -nonewline $s $firstblock
after idle writedata $s
}
proc writedata {s} {
global secondblock
puts -nonewline $s $secondblock
close $s
}
} -body {
set s [socket $localhost [lindex [fconfigure $l -sockname] 2]]
fconfigure $s -blocking 0 -trans lf -buffering line
set count 0
puts $s hello
proc readit {s} {
global count done
set l [read $s]
incr count [string length $l]
if {[eof $s]} {
close $s
set done 1
}
}
fileevent $s readable "readit $s"
vwait done
return $count
} -cleanup {
close $l
after cancel $timer
} -result 65566
test socket_$af-9.3 {testing EOF stickyness} -constraints [list socket supported_$af] -setup {
set count 0
set done false
proc write_then_close {s} {
puts $s bye
close $s
}
proc accept {s a p} {
fconfigure $s -buffering line -translation lf
fileevent $s writable "write_then_close $s"
}
set s [socket -server accept -myaddr $localhost 0]
} -body {
proc count_to_eof {s} {
global count done
set l [gets $s]
if {[eof $s]} {
incr count
if {$count > 9} {
close $s
set done true
set count {eof is sticky}
}
}
}
proc timerproc {s} {
global done count
set done true
set count {timer went off, eof is not sticky}
close $s
}
set c [socket $localhost [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 $c]
vwait done
return $count
} -cleanup {
close $s
after cancel $timer
} -result {eof is sticky}
removeFile script
test socket_$af-10.1 {testing socket accept callback error handling} \
-constraints [list socket supported_$af] -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 $localhost 0]
proc accept {s a p} {close $s; error}
set c [socket $localhost [lindex [fconfigure $s -sockname] 2]]
vwait goterror
close $s
close $c
return $goterror
} -cleanup {
interp bgerror {} $handler
} -result 1
test socket_$af-11.1 {tcp connection} -setup {
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
puts $s done
close $s
}
getPort $server
}]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set s [socket $remoteServerIP $port]
gets $s
} -cleanup {
close $s
sendCommand {close $server}
} -result done
test socket_$af-11.2 {client specifies its port} -setup {
set lport [randport]
set rport [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
puts $s $p
close $s
}
getPort $server
}]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set s [socket -myport $lport $remoteServerIP $rport]
set r [gets $s]
expr {$r==$lport ? "ok" : "broken: $r != $port"}
} -cleanup {
close $s
sendCommand {close $server}
} -result ok
test socket_$af-11.3 {trying to connect, no server} -body {
set status ok
if {![catch {set s [socket $remoteServerIp [randport]]}]} {
if {![catch {gets $s}]} {
set status broken
}
close $s
}
return $status
} -constraints [list socket supported_$af doTestsWithRemoteServer] -result ok
test socket_$af-11.4 {remote echo, one line} -setup {
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
fileevent $s readable [list echo $s]
fconfigure $s -buffering line -translation crlf
}
proc echo {s} {
set l [gets $s]
if {[eof $s]} {
close $s
} else {
puts $s $l
}
}
getPort $server
}]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set f [socket $remoteServerIP $port]
fconfigure $f -translation crlf -buffering line
puts $f hello
gets $f
} -cleanup {
catch {close $f}
sendCommand {close $server}
} -result hello
test socket_$af-11.5 {remote echo, 50 lines} -setup {
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
fileevent $s readable [list echo $s]
fconfigure $s -buffering line -translation crlf
}
proc echo {s} {
set l [gets $s]
if {[eof $s]} {
close $s
} else {
puts $s $l
}
}
getPort $server
}]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set f [socket $remoteServerIP $port]
fconfigure $f -translation crlf -buffering line
for {set cnt 0} {$cnt < 50} {incr cnt} {
puts $f "hello, $cnt"
if {[gets $f] != "hello, $cnt"} {
break
}
}
return $cnt
} -cleanup {
close $f
sendCommand {close $server}
} -result 50
test socket_$af-11.6 {socket conflict} -setup {
set s1 [socket -server accept -myaddr $localhost 0]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set s2 [socket -server accept -myaddr $localhost [getPort $s1]]
list [getPort $s2] [close $s2]
} -cleanup {
close $s1
} -returnCodes error -result {couldn't open socket: address already in use}
test socket_$af-11.7 {server with several clients} -setup {
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
fconfigure $s -buffering line
fileevent $s readable [list echo $s]
}
proc echo {s} {
set l [gets $s]
if {[eof $s]} {
close $s
} else {
puts $s $l
}
}
getPort $server
}]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set s1 [socket $remoteServerIP $port]
fconfigure $s1 -buffering line
set s2 [socket $remoteServerIP $port]
fconfigure $s2 -buffering line
set s3 [socket $remoteServerIP $port]
fconfigure $s3 -buffering line
for {set i 0} {$i < 100} {incr i} {
puts $s1 hello,s1
gets $s1
puts $s2 hello,s2
gets $s2
puts $s3 hello,s3
gets $s3
}
return $i
} -cleanup {
close $s1
close $s2
close $s3
sendCommand {close $server}
} -result 100
test socket_$af-11.8 {client with several servers} -setup {
lassign [sendCommand {
set s1 [socket -server "accept server1" 0]
set s2 [socket -server "accept server2" 0]
set s3 [socket -server "accept server3" 0]
proc accept {mp s a p} {
puts $s $mp
close $s
}
list [getPort $s1] [getPort $s2] [getPort $s3]
}] p1 p2 p3
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set s1 [socket $remoteServerIP $p1]
set s2 [socket $remoteServerIP $p2]
set s3 [socket $remoteServerIP $p3]
list [gets $s1] [gets $s1] [eof $s1] [gets $s2] [gets $s2] [eof $s2] \
[gets $s3] [gets $s3] [eof $s3]
} -cleanup {
close $s1
close $s2
close $s3
sendCommand {
close $s1
close $s2
close $s3
}
} -result {server1 {} 1 server2 {} 1 server3 {} 1}
test socket_$af-11.9 {accept callback error} -constraints [list socket supported_$af doTestsWithRemoteServer] -setup {
proc myHandler {msg options} {
variable x $msg
}
set handler [interp bgerror {}]
interp bgerror {} [namespace which myHandler]
set timer [after 10000 "set x timed_out"]
} -body {
set s [socket -server accept 0]
proc accept {s a p} {expr {10 / 0}}
sendCommand "set port [getPort $s]"
if {[catch {
sendCommand {
set peername [fconfigure $callerSocket -peername]
set s [socket [lindex $peername 0] $port]
close $s
}
} msg]} then {
close $s
error $msg
}
vwait x
return $x
} -cleanup {
close $s
after cancel $timer
interp bgerror {} $handler
} -result {divide by zero}
test socket_$af-11.10 {testing socket specific options} -setup {
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {close $s}
getPort $server
}]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
set s [socket $remoteServerIP $port]
set p [fconfigure $s -peername]
set n [fconfigure $s -sockname]
list [expr {[lindex $p 2] == $port}] [llength $p] [llength $n]
} -cleanup {
close $s
sendCommand {close $server}
} -result {1 3 3}
test socket_$af-11.11 {testing spurious events} -setup {
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
fconfigure $s -translation "auto lf"
after idle writesome $s
}
proc writesome {s} {
for {set i 0} {$i < 100} {incr i} {
puts $s "line $i from remote server"
}
close $s
}
getPort $server
}]
set len 0
set spurious 0
set done 0
set timer [after 40000 "set done timed_out"]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
proc readlittle {s} {
global spurious done len
set l [read $s 1]
if {[string length $l] == 0} {
if {![eof $s]} {
incr spurious
} else {
close $s
set done 1
}
} else {
incr len [string length $l]
}
}
set c [socket $remoteServerIP $port]
fileevent $c readable "readlittle $c"
vwait done
list $spurious $len $done
} -cleanup {
after cancel $timer
sendCommand {close $server}
} -result {0 2690 1}
test socket_$af-11.12 {testing EOF stickyness} -constraints [list socket supported_$af doTestsWithRemoteServer] -setup {
set counter 0
set done 0
set port [sendCommand {
set server [socket -server accept 0]
proc accept {s a p} {
after idle close $s
}
getPort $server
}]
proc timed_out {} {
global c done
set done {timed_out, EOF is not sticky}
close $c
}
set after_id [after 1000 timed_out]
} -body {
proc count_up {s} {
global counter done
set l [gets $s]
if {[eof $s]} {
incr counter
if {$counter > 9} {
set done {EOF is sticky}
close $s
}
}
}
set c [socket $remoteServerIP $port]
fileevent $c readable [list count_up $c]
vwait done
return $done
} -cleanup {
after cancel $after_id
sendCommand {close $server}
} -result {EOF is sticky}
test socket_$af-11.13 {testing async write, async flush, async close} -setup {
set port [sendCommand {
set firstblock ""
for {set i 0} {$i < 5} {incr i} {
set firstblock "a$firstblock$firstblock"
}
set secondblock ""
for {set i 0} {$i < 16} {incr i} {
set secondblock "b$secondblock$secondblock"
}
set l [socket -server accept 0]
proc accept {s a p} {
fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
-buffering line
fileevent $s readable "readable $s"
}
proc readable {s} {
set l [gets $s]
fileevent $s readable {}
after idle respond $s
}
proc respond {s} {
global firstblock
puts -nonewline $s $firstblock
after idle writedata $s
}
proc writedata {s} {
global secondblock
puts -nonewline $s $secondblock
close $s
}
getPort $l
}]
set timer [after 10000 "set done timed_out"]
} -constraints [list socket supported_$af doTestsWithRemoteServer] -body {
proc readit {s} {
global count done
set l [read $s]
incr count [string length $l]
if {[eof $s]} {
close $s
set done 1
}
}
set s [socket $remoteServerIP $port]
fconfigure $s -blocking 0 -trans lf -buffering line
set count 0
puts $s hello
fileevent $s readable "readit $s"
vwait done
return $count
} -cleanup {
after cancel $timer
sendCommand {close $l}
} -result 65566
set path(script1) [makeFile {} script1]
set path(script2) [makeFile {} script2]
test socket_$af-12.1 {testing inheritance of server sockets} -setup {
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 $path(script1) w]
puts $f {
fileevent stdin readable exit
after 10000 exit
vwait forever
}
close $f
# Script2 creates the server socket, launches script1, and exits.
# The server socket will now be closed unless script1 inherited it.
set f [open $path(script2) w]
puts $f [list set tcltest [interpreter]]
puts $f [list set delay $path(script1)]
puts $f [list set localhost $localhost]
puts $f {
set f [socket -server accept -myaddr $localhost 0]
proc accept { file addr port } {
close $file
}
exec $tcltest $delay &
puts [lindex [fconfigure $f -sockname] 2]
close $f
exit
}
close $f
} -constraints [list socket supported_$af stdio exec] -body {
# Launch script2 and wait 5 seconds
### exec [interpreter] script2 &
set p [open "|[list [interpreter] $path(script2)]" r]
# If we can still connect to the server, the socket got inherited.
if {[catch {close [socket $localhost $listen]}]} {
return {server socket was not inherited}
} else {
return {server socket was inherited}
}
} -cleanup {
catch {close $p}
} -result {server socket was not inherited}
test socket_$af-12.2 {testing inheritance of client sockets} -setup {
file delete $path(script1)
file delete $path(script2)
# Script1 is just a 20 second delay. If the server socket is inherited, it
# will be held open for 20 seconds
set f [open $path(script1) w]
puts $f {
fileevent stdin readable exit
after 20000 exit
vwait forever
}
close $f
# Script2 opens the client socket and writes to it. It then launches
# script1 and exits. If the child process inherited the client socket, the
# socket will still be open.
set f [open $path(script2) w]
puts $f [list set tcltest [interpreter]]
puts $f [list set delay $path(script1)]
puts $f [list set localhost $localhost]
puts $f {
gets stdin port
set f [socket $localhost $port]
exec $tcltest $delay &
puts $f testing
flush $f
exit
}
close $f
# If the socket doesn't hit end-of-file in 10 seconds, the script1 process
# must have inherited the client.
set failed 0
set after [after 10000 [list set failed 1]]
} -constraints [list socket supported_$af stdio exec] -body {
# Create the server socket
set server [socket -server accept -myaddr $localhost 0]
proc accept { file host port } {
# When the client connects, establish the read handler
global server
close $server
fileevent $file readable [list getdata $file]
fconfigure $file -buffering line -blocking 0
}
proc getdata { file } {
# Read handler on the accepted socket.
global x failed
set status [catch {read $file} data]
if {$status != 0} {
set x {read failed, error was $data}
catch { close $file }
} elseif {$data ne ""} {
} elseif {[fblocked $file]} {
} elseif {[eof $file]} {
if {$failed} {
set x {client socket was inherited}
} else {
set x {client socket was not inherited}
}
catch { close $file }
} else {
set x {impossible case}
catch { close $file }
}
}
# Launch the script2 process
### exec [interpreter] script2 &
set p [open "|[list [interpreter] $path(script2)]" w]
puts $p [lindex [fconfigure $server -sockname] 2] ; flush $p
vwait x
return $x
} -cleanup {
after cancel $after
close $p
} -result {client socket was not inherited}
test socket_$af-12.3 {testing inheritance of accepted sockets} -setup {
file delete $path(script1)
file delete $path(script2)
set f [open $path(script1) w]
puts $f {
fileevent stdin readable exit
after 10000 exit
vwait forever
}
close $f
set f [open $path(script2) w]
puts $f [list set tcltest [interpreter]]
puts $f [list set delay $path(script1)]
puts $f [list set localhost $localhost]
puts $f {
set server [socket -server accept -myaddr $localhost 0]
proc accept { file host port } {
global tcltest delay
puts $file {test data on socket}
exec $tcltest $delay &
after idle exit
}
puts stdout [lindex [fconfigure $server -sockname] 2]
vwait forever
}
close $f
} -constraints [list socket supported_$af stdio exec] -body {
# Launch the script2 process and connect to it. See how long the socket
# stays open
## exec [interpreter] script2 &
set p [open "|[list [interpreter] $path(script2)]" r]
gets $p listen
set f [socket $localhost $listen]
fconfigure $f -buffering full -blocking 0
fileevent $f readable [list getdata $f]
# If the socket is still open after 5 seconds, the script1 process must
# have inherited the accepted socket.
set failed 0
set after [after 5000 [list set failed 1]]
proc getdata { file } {
# Read handler on the client socket.
global x
global failed
set status [catch {read $file} data]
if {$status != 0} {
set x {read failed, error was $data}
catch { close $file }
} elseif {[string compare {} $data]} {
} elseif {[fblocked $file]} {
} elseif {[eof $file]} {
if {$failed} {
set x {accepted socket was inherited}
} else {
set x {accepted socket was not inherited}
}
catch { close $file }
} else {
set x {impossible case}
catch { close $file }
}
return
}
vwait x
return $x
} -cleanup {
after cancel $after
catch {close $p}
} -result {accepted socket was not inherited}
test socket_$af-13.1 {Testing use of shared socket between two threads} -setup {
threadReap
set path(script) [makeFile [string map [list @localhost@ $localhost] {
set f [socket -server accept -myaddr @localhost@ 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
set l [gets $s]
if {[eof $s]} {
global x
close $s
set x done
} else {
incr i
puts $s $l
}
}
set i 0
vwait x
close $f
# thread cleans itself up.
testthread exit
}] script]
} -constraints [list socket supported_$af testthread] -body {
# create a thread
set serverthread [testthread create [list source $path(script) ] ]
update
set port [testthread send $serverthread {set listen}]
update
set s [socket $localhost $port]
fconfigure $s -buffering line
catch {
puts $s "hello"
gets $s result
}
close $s
update
append result " " [threadReap]
} -cleanup {
removeFile script
} -result {hello 1}
# ----------------------------------------------------------------------
removeFile script1
removeFile script2
# cleanup
if {$remoteProcChan ne ""} {
catch {sendCommand exit}
}
catch {close $commandSocket}
catch {close $remoteProcChan}
}
unset ::tcl::unsupported::socketAF
test socket-14.0 {[socket -async] when server only listens on one address family} \
-constraints [list socket supported_any] \
-setup {
proc accept {s a p} {
global x
puts $s bye
close $s
set x ok
}
set server [socket -server accept -myaddr 127.0.0.1 0]
set port [lindex [fconfigure $server -sockname] 2]
} -body {
set client [socket -async localhost $port]
set after [after 1000 {set x [fconfigure $client -error]}]
vwait x
set x
} -cleanup {
after cancel $after
close $server
close $client
unset x
} -result ok
test socket-14.1 {[socket -async] fileevent while still connecting} \
-constraints [list socket supported_any] \
-setup {
proc accept {s a p} {
global x
puts $s bye
close $s
lappend x ok
}
set server [socket -server accept -myaddr 127.0.0.1 0]
set port [lindex [fconfigure $server -sockname] 2]
} -body {
set client [socket -async localhost $port]
fileevent $client writable {
lappend x [expr {[fconfigure $client -error] eq ""}]
}
set after [after 1000 {set x timeout}]
vwait x
vwait x
set x
} -cleanup {
after cancel $after
close $server
close $client
unset x
} -result {ok 1}
test socket-14.2 {[socket -async] fileevent connection refused} \
-constraints [list socket supported_any] \
-body {
set client [socket -async localhost [randport]]
fileevent $client writable {set x [fconfigure $client -error]}
set after [after 1000 {set x timeout}]
vwait x
if {$x eq "timeout"} {
append x ": [fconfigure $client -error]"
}
set x
} -cleanup {
after cancel $after
close $client
unset x
} -result "connection refused"
::tcltest::cleanupTests
flush stdout
return
# Local Variables:
# mode: tcl
# fill-column: 78
# End: