os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/tests/socket.test
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
# Commands tested in this file: socket.
sl@0
     2
#
sl@0
     3
# This file contains a collection of tests for one or more of the Tcl
sl@0
     4
# built-in commands.  Sourcing this file into Tcl runs the tests and
sl@0
     5
# generates output for errors.  No output means no errors were found.
sl@0
     6
#
sl@0
     7
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
sl@0
     8
# Copyright (c) 1998-2000 Ajuba Solutions.
sl@0
     9
#
sl@0
    10
# See the file "license.terms" for information on usage and redistribution
sl@0
    11
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    12
#
sl@0
    13
# RCS: @(#) $Id: socket.test,v 1.26.2.6 2006/03/16 00:35:59 andreas_kupries Exp $
sl@0
    14
sl@0
    15
# Running socket tests with a remote server:
sl@0
    16
# ------------------------------------------
sl@0
    17
# 
sl@0
    18
# Some tests in socket.test depend on the existence of a remote server to
sl@0
    19
# which they connect. The remote server must be an instance of tcltest and it
sl@0
    20
# must run the script found in the file "remote.tcl" in this directory. You
sl@0
    21
# can start the remote server on any machine reachable from the machine on
sl@0
    22
# which you want to run the socket tests, by issuing:
sl@0
    23
# 
sl@0
    24
#     tcltest remote.tcl -port 2048	# Or choose another port number.
sl@0
    25
# 
sl@0
    26
# If the machine you are running the remote server on has several IP
sl@0
    27
# interfaces, you can choose which interface the server listens on for
sl@0
    28
# connections by specifying the -address command line flag, so:
sl@0
    29
# 
sl@0
    30
#     tcltest remote.tcl -address your.machine.com
sl@0
    31
# 
sl@0
    32
# These options can also be set by environment variables. On Unix, you can
sl@0
    33
# type these commands to the shell from which the remote server is started:
sl@0
    34
# 
sl@0
    35
#     shell% setenv serverPort 2048
sl@0
    36
#     shell% setenv serverAddress your.machine.com
sl@0
    37
# 
sl@0
    38
# and subsequently you can start the remote server with:
sl@0
    39
# 
sl@0
    40
#     tcltest remote.tcl
sl@0
    41
# 
sl@0
    42
# to have it listen on port 2048 on the interface your.machine.com.
sl@0
    43
#     
sl@0
    44
# When the server starts, it prints out a detailed message containing its
sl@0
    45
# configuration information, and it will block until killed with a Ctrl-C.
sl@0
    46
# Once the remote server exists, you can run the tests in socket.test with
sl@0
    47
# the server by setting two Tcl variables:
sl@0
    48
# 
sl@0
    49
#     % set remoteServerIP <name or address of machine on which server runs>
sl@0
    50
#     % set remoteServerPort 2048
sl@0
    51
# 
sl@0
    52
# These variables are also settable from the environment. On Unix, you can:
sl@0
    53
# 
sl@0
    54
#     shell% setenv remoteServerIP machine.where.server.runs
sl@0
    55
#     shell% senetv remoteServerPort 2048
sl@0
    56
# 
sl@0
    57
# The preamble of the socket.test file checks to see if the variables are set
sl@0
    58
# either in Tcl or in the environment; if they are, it attempts to connect to
sl@0
    59
# the server. If the connection is successful, the tests using the remote
sl@0
    60
# server will be performed; otherwise, it will attempt to start the remote
sl@0
    61
# server (via exec) on platforms that support this, on the local host,
sl@0
    62
# listening at port 2048. If all fails, a message is printed and the tests
sl@0
    63
# using the remote server are not performed.
sl@0
    64
sl@0
    65
package require tcltest 2
sl@0
    66
namespace import -force ::tcltest::*
sl@0
    67
sl@0
    68
# Some tests require the testthread and exec commands
sl@0
    69
testConstraint testthread [llength [info commands testthread]]
sl@0
    70
testConstraint exec [llength [info commands exec]]
sl@0
    71
sl@0
    72
# If remoteServerIP or remoteServerPort are not set, check in the
sl@0
    73
# environment variables for externally set values.
sl@0
    74
#
sl@0
    75
sl@0
    76
if {![info exists remoteServerIP]} {
sl@0
    77
    if {[info exists env(remoteServerIP)]} {
sl@0
    78
	set remoteServerIP $env(remoteServerIP)
sl@0
    79
    }
sl@0
    80
}
sl@0
    81
if {![info exists remoteServerPort]} {
sl@0
    82
    if {[info exists env(remoteServerIP)]} {
sl@0
    83
	set remoteServerPort $env(remoteServerPort)
sl@0
    84
    } else {
sl@0
    85
        if {[info exists remoteServerIP]} {
sl@0
    86
	    set remoteServerPort 2048
sl@0
    87
        }
sl@0
    88
    }
sl@0
    89
}
sl@0
    90
sl@0
    91
#
sl@0
    92
# Check if we're supposed to do tests against the remote server
sl@0
    93
#
sl@0
    94
sl@0
    95
set doTestsWithRemoteServer 1
sl@0
    96
if {![info exists remoteServerIP] && ($tcl_platform(platform) != "macintosh")} {
sl@0
    97
    set remoteServerIP 127.0.0.1
sl@0
    98
}
sl@0
    99
if {($doTestsWithRemoteServer == 1) && (![info exists remoteServerPort])} {
sl@0
   100
    set remoteServerPort 2048
sl@0
   101
}
sl@0
   102
sl@0
   103
# Attempt to connect to a remote server if one is already running. If it
sl@0
   104
# is not running or for some other reason the connect fails, attempt to
sl@0
   105
# start the remote server on the local host listening on port 2048. This
sl@0
   106
# is only done on platforms that support exec (i.e. not on the Mac). On
sl@0
   107
# platforms that do not support exec, the remote server must be started
sl@0
   108
# by the user before running the tests.
sl@0
   109
sl@0
   110
set remoteProcChan ""
sl@0
   111
set commandSocket ""
sl@0
   112
if {$doTestsWithRemoteServer} {
sl@0
   113
    catch {close $commandSocket}
sl@0
   114
    if {[catch {set commandSocket [socket $remoteServerIP \
sl@0
   115
						$remoteServerPort]}] != 0} {
sl@0
   116
	if {[info commands exec] == ""} {
sl@0
   117
	    set noRemoteTestReason "can't exec"
sl@0
   118
	    set doTestsWithRemoteServer 0
sl@0
   119
	} else {
sl@0
   120
	    set remoteServerIP 127.0.0.1
sl@0
   121
	    # Be *extra* careful in case this file is sourced from
sl@0
   122
	    # a directory other than the current one...
sl@0
   123
	    set remoteFile [file join [pwd] [file dirname [info script]] \
sl@0
   124
		    remote.tcl]
sl@0
   125
	    if {[catch {set remoteProcChan \
sl@0
   126
				[open "|[list [interpreter] $remoteFile \
sl@0
   127
					-serverIsSilent \
sl@0
   128
					-port $remoteServerPort \
sl@0
   129
					-address $remoteServerIP]" \
sl@0
   130
					w+]} \
sl@0
   131
		   msg] == 0} {
sl@0
   132
		after 1000
sl@0
   133
		if {[catch {set commandSocket [socket $remoteServerIP \
sl@0
   134
				$remoteServerPort]} msg] == 0} {
sl@0
   135
		    fconfigure $commandSocket -translation crlf -buffering line
sl@0
   136
		} else {
sl@0
   137
		    set noRemoteTestReason $msg
sl@0
   138
		    set doTestsWithRemoteServer 0
sl@0
   139
		}
sl@0
   140
	    } else {
sl@0
   141
		set noRemoteTestReason "$msg [interpreter]"
sl@0
   142
		set doTestsWithRemoteServer 0
sl@0
   143
	    }
sl@0
   144
	}
sl@0
   145
    } else {
sl@0
   146
	fconfigure $commandSocket -translation crlf -buffering line
sl@0
   147
    }
sl@0
   148
}
sl@0
   149
sl@0
   150
# Some tests are run only if we are doing testing against a remote server.
sl@0
   151
set ::tcltest::testConstraints(doTestsWithRemoteServer) $doTestsWithRemoteServer
sl@0
   152
if {$doTestsWithRemoteServer == 0} {
sl@0
   153
    if {[string first s $::tcltest::verbose] != -1} {
sl@0
   154
    	puts "Skipping tests with remote server. See tests/socket.test for"
sl@0
   155
	puts "information on how to run remote server."
sl@0
   156
	puts "Reason for not doing remote tests: $noRemoteTestReason"
sl@0
   157
    }
sl@0
   158
}
sl@0
   159
sl@0
   160
#
sl@0
   161
# If we do the tests, define a command to send a command to the
sl@0
   162
# remote server.
sl@0
   163
#
sl@0
   164
sl@0
   165
if {$doTestsWithRemoteServer == 1} {
sl@0
   166
    proc sendCommand {c} {
sl@0
   167
	global commandSocket
sl@0
   168
sl@0
   169
	if {[eof $commandSocket]} {
sl@0
   170
	    error "remote server disappeared"
sl@0
   171
	}
sl@0
   172
sl@0
   173
	if {[catch {puts $commandSocket $c} msg]} {
sl@0
   174
	    error "remote server disappaered: $msg"
sl@0
   175
	}
sl@0
   176
	if {[catch {puts $commandSocket "--Marker--Marker--Marker--"} msg]} {
sl@0
   177
	    error "remote server disappeared: $msg"
sl@0
   178
	}
sl@0
   179
sl@0
   180
	set resp ""
sl@0
   181
	while {1} {
sl@0
   182
	    set line [gets $commandSocket]
sl@0
   183
	    if {[eof $commandSocket]} {
sl@0
   184
		error "remote server disappaered"
sl@0
   185
	    }
sl@0
   186
	    if {[string compare $line "--Marker--Marker--Marker--"] == 0} {
sl@0
   187
		if {[string compare [lindex $resp 0] error] == 0} {
sl@0
   188
		    error [lindex $resp 1]
sl@0
   189
		} else {
sl@0
   190
		    return [lindex $resp 1]
sl@0
   191
		}
sl@0
   192
	    } else {
sl@0
   193
		append resp $line "\n"
sl@0
   194
	    }
sl@0
   195
	}
sl@0
   196
    }
sl@0
   197
}
sl@0
   198
sl@0
   199
test socket-1.1 {arg parsing for socket command} {socket} {
sl@0
   200
    list [catch {socket -server} msg] $msg
sl@0
   201
} {1 {no argument given for -server option}}
sl@0
   202
test socket-1.2 {arg parsing for socket command} {socket} {
sl@0
   203
    list [catch {socket -server foo} msg] $msg
sl@0
   204
} {1 {wrong # args: should be either:
sl@0
   205
socket ?-myaddr addr? ?-myport myport? ?-async? host port
sl@0
   206
socket -server command ?-myaddr addr? port}}
sl@0
   207
test socket-1.3 {arg parsing for socket command} {socket} {
sl@0
   208
    list [catch {socket -myaddr} msg] $msg
sl@0
   209
} {1 {no argument given for -myaddr option}}
sl@0
   210
test socket-1.4 {arg parsing for socket command} {socket} {
sl@0
   211
    list [catch {socket -myaddr 127.0.0.1} msg] $msg
sl@0
   212
} {1 {wrong # args: should be either:
sl@0
   213
socket ?-myaddr addr? ?-myport myport? ?-async? host port
sl@0
   214
socket -server command ?-myaddr addr? port}}
sl@0
   215
test socket-1.5 {arg parsing for socket command} {socket} {
sl@0
   216
    list [catch {socket -myport} msg] $msg
sl@0
   217
} {1 {no argument given for -myport option}}
sl@0
   218
test socket-1.6 {arg parsing for socket command} {socket} {
sl@0
   219
    list [catch {socket -myport xxxx} msg] $msg
sl@0
   220
} {1 {expected integer but got "xxxx"}}
sl@0
   221
test socket-1.7 {arg parsing for socket command} {socket} {
sl@0
   222
    list [catch {socket -myport 2522} msg] $msg
sl@0
   223
} {1 {wrong # args: should be either:
sl@0
   224
socket ?-myaddr addr? ?-myport myport? ?-async? host port
sl@0
   225
socket -server command ?-myaddr addr? port}}
sl@0
   226
test socket-1.8 {arg parsing for socket command} {socket} {
sl@0
   227
    list [catch {socket -froboz} msg] $msg
sl@0
   228
} {1 {bad option "-froboz": must be -async, -myaddr, -myport, or -server}}
sl@0
   229
test socket-1.9 {arg parsing for socket command} {socket} {
sl@0
   230
    list [catch {socket -server foo -myport 2521 3333} msg] $msg
sl@0
   231
} {1 {Option -myport is not valid for servers}}
sl@0
   232
test socket-1.10 {arg parsing for socket command} {socket} {
sl@0
   233
    list [catch {socket host 2528 -junk} msg] $msg
sl@0
   234
} {1 {wrong # args: should be either:
sl@0
   235
socket ?-myaddr addr? ?-myport myport? ?-async? host port
sl@0
   236
socket -server command ?-myaddr addr? port}}
sl@0
   237
test socket-1.11 {arg parsing for socket command} {socket} {
sl@0
   238
    list [catch {socket -server callback 2520 --} msg] $msg
sl@0
   239
} {1 {wrong # args: should be either:
sl@0
   240
socket ?-myaddr addr? ?-myport myport? ?-async? host port
sl@0
   241
socket -server command ?-myaddr addr? port}}
sl@0
   242
test socket-1.12 {arg parsing for socket command} {socket} {
sl@0
   243
    list [catch {socket foo badport} msg] $msg
sl@0
   244
} {1 {expected integer but got "badport"}}
sl@0
   245
test socket-1.13 {arg parsing for socket command} {socket} {
sl@0
   246
list [catch {socket -async -server} msg] $msg
sl@0
   247
} {1 {cannot set -async option for server sockets}}
sl@0
   248
test socket-1.14 {arg parsing for socket command} {socket} {
sl@0
   249
list [catch {socket -server foo -async} msg] $msg
sl@0
   250
} {1 {cannot set -async option for server sockets}}
sl@0
   251
sl@0
   252
set path(script) [makeFile {} script]
sl@0
   253
sl@0
   254
test socket-2.1 {tcp connection} {socket stdio} {
sl@0
   255
    file delete $path(script)
sl@0
   256
    set f [open $path(script) w]
sl@0
   257
    puts $f {
sl@0
   258
	set timer [after 10000 "set x timed_out"]
sl@0
   259
	set f [socket -server accept 0]
sl@0
   260
	proc accept {file addr port} {
sl@0
   261
	    global x
sl@0
   262
	    set x done
sl@0
   263
            close $file
sl@0
   264
	}
sl@0
   265
	puts ready
sl@0
   266
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   267
	vwait x
sl@0
   268
	after cancel $timer
sl@0
   269
	close $f
sl@0
   270
	puts $x
sl@0
   271
    }
sl@0
   272
    close $f
sl@0
   273
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   274
    gets $f x
sl@0
   275
    gets $f listen
sl@0
   276
    if {[catch {socket 127.0.0.1 $listen} msg]} {
sl@0
   277
        set x $msg
sl@0
   278
    } else {
sl@0
   279
        lappend x [gets $f]
sl@0
   280
        close $msg
sl@0
   281
    }
sl@0
   282
    lappend x [gets $f]
sl@0
   283
    close $f
sl@0
   284
    set x
sl@0
   285
} {ready done {}}
sl@0
   286
sl@0
   287
if [info exists port] {
sl@0
   288
    incr port
sl@0
   289
} else { 
sl@0
   290
    set port [expr 2048 + [pid]%1024]
sl@0
   291
}
sl@0
   292
test socket-2.2 {tcp connection with client port specified} {socket stdio} {
sl@0
   293
    file delete $path(script)
sl@0
   294
    set f [open $path(script) w]
sl@0
   295
    puts $f {
sl@0
   296
	set timer [after 10000 "set x timeout"]
sl@0
   297
        set f [socket -server accept 0]
sl@0
   298
	proc accept {file addr port} {
sl@0
   299
            global x
sl@0
   300
            puts "[gets $file] $port"
sl@0
   301
            close $file
sl@0
   302
            set x done
sl@0
   303
	}
sl@0
   304
	puts ready
sl@0
   305
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   306
	vwait x
sl@0
   307
	after cancel $timer
sl@0
   308
	close $f
sl@0
   309
    }
sl@0
   310
    close $f
sl@0
   311
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   312
    gets $f x
sl@0
   313
    gets $f listen
sl@0
   314
    global port
sl@0
   315
    if {[catch {socket -myport $port 127.0.0.1 $listen} sock]} {
sl@0
   316
        set x $sock
sl@0
   317
	close [socket 127.0.0.1 $listen]
sl@0
   318
	puts stderr $sock
sl@0
   319
    } else {
sl@0
   320
        puts $sock hello
sl@0
   321
	flush $sock
sl@0
   322
        lappend x [gets $f]
sl@0
   323
        close $sock
sl@0
   324
    }
sl@0
   325
    close $f
sl@0
   326
    set x
sl@0
   327
} [list ready "hello $port"]
sl@0
   328
test socket-2.3 {tcp connection with client interface specified} {socket stdio} {
sl@0
   329
    file delete $path(script)
sl@0
   330
    set f [open $path(script) w]
sl@0
   331
    puts $f {
sl@0
   332
	set timer [after 2000 "set x done"]
sl@0
   333
        set f [socket  -server accept 2830]
sl@0
   334
	proc accept {file addr port} {
sl@0
   335
            global x
sl@0
   336
            puts "[gets $file] $addr"
sl@0
   337
            close $file
sl@0
   338
            set x done
sl@0
   339
	}
sl@0
   340
	puts ready
sl@0
   341
	vwait x
sl@0
   342
	after cancel $timer
sl@0
   343
	close $f
sl@0
   344
    }
sl@0
   345
    close $f
sl@0
   346
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   347
    gets $f x
sl@0
   348
    if {[catch {socket -myaddr 127.0.0.1 127.0.0.1 2830} sock]} {
sl@0
   349
        set x $sock
sl@0
   350
    } else {
sl@0
   351
        puts $sock hello
sl@0
   352
	flush $sock
sl@0
   353
        lappend x [gets $f]
sl@0
   354
        close $sock
sl@0
   355
    }
sl@0
   356
    close $f
sl@0
   357
    set x
sl@0
   358
} {ready {hello 127.0.0.1}}
sl@0
   359
test socket-2.4 {tcp connection with server interface specified} {socket stdio} {
sl@0
   360
    file delete $path(script)
sl@0
   361
    set f [open $path(script) w]
sl@0
   362
    puts $f {
sl@0
   363
	set timer [after 2000 "set x done"]
sl@0
   364
        set f [socket -server accept -myaddr 127.0.0.1 0]
sl@0
   365
	proc accept {file addr port} {
sl@0
   366
            global x
sl@0
   367
            puts "[gets $file]"
sl@0
   368
            close $file
sl@0
   369
            set x done
sl@0
   370
	}
sl@0
   371
	puts ready
sl@0
   372
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   373
	vwait x
sl@0
   374
	after cancel $timer
sl@0
   375
	close $f
sl@0
   376
    }
sl@0
   377
    close $f
sl@0
   378
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   379
    gets $f x
sl@0
   380
    gets $f listen
sl@0
   381
    if {[catch {socket 127.0.0.1 $listen} sock]} {
sl@0
   382
        set x $sock
sl@0
   383
    } else {
sl@0
   384
        puts $sock hello
sl@0
   385
	flush $sock
sl@0
   386
        lappend x [gets $f]
sl@0
   387
        close $sock
sl@0
   388
    }
sl@0
   389
    close $f
sl@0
   390
    set x
sl@0
   391
} {ready hello}
sl@0
   392
test socket-2.5 {tcp connection with redundant server port} {socket stdio} {
sl@0
   393
    file delete $path(script)
sl@0
   394
    set f [open $path(script) w]
sl@0
   395
    puts $f {
sl@0
   396
	set timer [after 10000 "set x timeout"]
sl@0
   397
        set f [socket -server accept 0]
sl@0
   398
	proc accept {file addr port} {
sl@0
   399
            global x
sl@0
   400
            puts "[gets $file]"
sl@0
   401
            close $file
sl@0
   402
            set x done
sl@0
   403
	}
sl@0
   404
	puts ready
sl@0
   405
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   406
	vwait x
sl@0
   407
	after cancel $timer
sl@0
   408
	close $f
sl@0
   409
    }
sl@0
   410
    close $f
sl@0
   411
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   412
    gets $f x
sl@0
   413
    gets $f listen
sl@0
   414
    if {[catch {socket 127.0.0.1 $listen} sock]} {
sl@0
   415
        set x $sock
sl@0
   416
    } else {
sl@0
   417
        puts $sock hello
sl@0
   418
	flush $sock
sl@0
   419
        lappend x [gets $f]
sl@0
   420
        close $sock
sl@0
   421
    }
sl@0
   422
    close $f
sl@0
   423
    set x
sl@0
   424
} {ready hello}
sl@0
   425
test socket-2.6 {tcp connection} {socket} {
sl@0
   426
    set status ok
sl@0
   427
    if {![catch {set sock [socket 127.0.0.1 2833]}]} {
sl@0
   428
	if {![catch {gets $sock}]} {
sl@0
   429
	    set status broken
sl@0
   430
	}
sl@0
   431
	close $sock
sl@0
   432
    }
sl@0
   433
    set status
sl@0
   434
} ok
sl@0
   435
test socket-2.7 {echo server, one line} {socket stdio} {
sl@0
   436
    file delete $path(script)
sl@0
   437
    set f [open $path(script) w]
sl@0
   438
    puts $f {
sl@0
   439
	set timer [after 10000 "set x timeout"]
sl@0
   440
	set f [socket -server accept 0]
sl@0
   441
	proc accept {s a p} {
sl@0
   442
            fileevent $s readable [list echo $s]
sl@0
   443
	    fconfigure $s -translation lf -buffering line
sl@0
   444
        }
sl@0
   445
	proc echo {s} {
sl@0
   446
	     set l [gets $s]
sl@0
   447
             if {[eof $s]} {
sl@0
   448
                 global x
sl@0
   449
                 close $s
sl@0
   450
                 set x done
sl@0
   451
             } else {
sl@0
   452
                 puts $s $l
sl@0
   453
             }
sl@0
   454
	}
sl@0
   455
	puts ready
sl@0
   456
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   457
	vwait x
sl@0
   458
	after cancel $timer
sl@0
   459
	close $f
sl@0
   460
	puts $x
sl@0
   461
    }
sl@0
   462
    close $f
sl@0
   463
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   464
    gets $f
sl@0
   465
    gets $f listen
sl@0
   466
    set s [socket 127.0.0.1 $listen]
sl@0
   467
    fconfigure $s -buffering line -translation lf
sl@0
   468
    puts $s "hello abcdefghijklmnop"
sl@0
   469
    after 1000
sl@0
   470
    set x [gets $s]
sl@0
   471
    close $s
sl@0
   472
    set y [gets $f]
sl@0
   473
    close $f
sl@0
   474
    list $x $y
sl@0
   475
} {{hello abcdefghijklmnop} done}
sl@0
   476
removeFile script
sl@0
   477
test socket-2.8 {echo server, loop 50 times, single connection} -constraints {socket stdio} -setup {
sl@0
   478
    set path(script) [makeFile {
sl@0
   479
	set f [socket -server accept 0]
sl@0
   480
	proc accept {s a p} {
sl@0
   481
            fileevent $s readable [list echo $s]
sl@0
   482
            fconfigure $s -buffering line
sl@0
   483
        }
sl@0
   484
	proc echo {s} {
sl@0
   485
	     global i
sl@0
   486
             set l [gets $s]
sl@0
   487
             if {[eof $s]} {
sl@0
   488
                 global x
sl@0
   489
                 close $s
sl@0
   490
                 set x done
sl@0
   491
             } else { 
sl@0
   492
	         incr i
sl@0
   493
                 puts $s $l
sl@0
   494
             }
sl@0
   495
	}
sl@0
   496
	set i 0
sl@0
   497
	puts ready
sl@0
   498
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   499
	set timer [after 20000 "set x done"]
sl@0
   500
	vwait x
sl@0
   501
	after cancel $timer
sl@0
   502
	close $f
sl@0
   503
	puts "done $i"
sl@0
   504
    } script]
sl@0
   505
} -body {
sl@0
   506
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   507
    gets $f
sl@0
   508
    gets $f listen
sl@0
   509
    set s [socket 127.0.0.1 $listen]
sl@0
   510
    fconfigure $s -buffering line
sl@0
   511
    catch {
sl@0
   512
	for {set x 0} {$x < 50} {incr x} {
sl@0
   513
	    puts $s "hello abcdefghijklmnop"
sl@0
   514
	    gets $s
sl@0
   515
	}
sl@0
   516
    }
sl@0
   517
    close $s
sl@0
   518
    catch {set x [gets $f]}
sl@0
   519
    close $f
sl@0
   520
    set x
sl@0
   521
} -cleanup {
sl@0
   522
    removeFile script
sl@0
   523
} -result {done 50}
sl@0
   524
set path(script) [makeFile {} script]
sl@0
   525
test socket-2.9 {socket conflict} {socket stdio} {
sl@0
   526
    set s [socket -server accept 0]
sl@0
   527
    file delete $path(script)
sl@0
   528
    set f [open $path(script) w]
sl@0
   529
    puts -nonewline $f "socket -server accept [lindex [fconfigure $s -sockname] 2]"
sl@0
   530
    close $f
sl@0
   531
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   532
    gets $f
sl@0
   533
    after 100
sl@0
   534
    set x [list [catch {close $f} msg]]
sl@0
   535
    regsub "\n.*$" $msg {} msg ; # cut part of the error message containing the port number
sl@0
   536
    lappend x $msg
sl@0
   537
    close $s
sl@0
   538
    set x
sl@0
   539
} {1 {couldn't open socket: address already in use}}
sl@0
   540
test socket-2.10 {close on accept, accepted socket lives} {socket} {
sl@0
   541
    set done 0
sl@0
   542
    set timer [after 20000 "set done timed_out"]
sl@0
   543
    set ss [socket -server accept 0]
sl@0
   544
    proc accept {s a p} {
sl@0
   545
	global ss
sl@0
   546
	close $ss
sl@0
   547
	fileevent $s readable "readit $s"
sl@0
   548
	fconfigure $s -trans lf
sl@0
   549
    }
sl@0
   550
    proc readit {s} {
sl@0
   551
	global done
sl@0
   552
	gets $s
sl@0
   553
	close $s
sl@0
   554
	set done 1
sl@0
   555
    }
sl@0
   556
    set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]
sl@0
   557
    puts $cs hello
sl@0
   558
    close $cs
sl@0
   559
    vwait done
sl@0
   560
    after cancel $timer
sl@0
   561
    set done
sl@0
   562
} 1
sl@0
   563
test socket-2.11 {detecting new data} {socket} {
sl@0
   564
    proc accept {s a p} {
sl@0
   565
	global sock
sl@0
   566
	set sock $s
sl@0
   567
    }
sl@0
   568
sl@0
   569
    set s [socket -server accept 0]
sl@0
   570
    set sock ""
sl@0
   571
    set s2 [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
sl@0
   572
    vwait sock
sl@0
   573
    puts $s2 one
sl@0
   574
    flush $s2
sl@0
   575
    after 500
sl@0
   576
    fconfigure $sock -blocking 0
sl@0
   577
    set result a:[gets $sock]
sl@0
   578
    lappend result b:[gets $sock]
sl@0
   579
    fconfigure $sock -blocking 1
sl@0
   580
    puts $s2 two
sl@0
   581
    flush $s2
sl@0
   582
    fconfigure $sock -blocking 0
sl@0
   583
    lappend result c:[gets $sock]
sl@0
   584
    fconfigure $sock -blocking 1
sl@0
   585
    close $s2
sl@0
   586
    close $s
sl@0
   587
    close $sock
sl@0
   588
    set result
sl@0
   589
} {a:one b: c:two}
sl@0
   590
sl@0
   591
sl@0
   592
test socket-3.1 {socket conflict} {socket stdio} {
sl@0
   593
    file delete $path(script)
sl@0
   594
    set f [open $path(script) w]
sl@0
   595
    puts $f {
sl@0
   596
	set f [socket -server accept 0]
sl@0
   597
	puts ready
sl@0
   598
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
   599
	gets stdin
sl@0
   600
	close $f
sl@0
   601
    }
sl@0
   602
    close $f
sl@0
   603
    set f [open "|[list [interpreter] $path(script)]" r+]
sl@0
   604
    gets $f
sl@0
   605
    gets $f listen
sl@0
   606
    set x [list [catch {socket -server accept $listen} msg] \
sl@0
   607
		$msg]
sl@0
   608
    puts $f bye
sl@0
   609
    close $f
sl@0
   610
    set x
sl@0
   611
} {1 {couldn't open socket: address already in use}}
sl@0
   612
test socket-3.2 {server with several clients} {socket stdio} {
sl@0
   613
    file delete $path(script)
sl@0
   614
    set f [open $path(script) w]
sl@0
   615
    puts $f {
sl@0
   616
	set t1 [after 30000 "set x timed_out"]
sl@0
   617
	set t2 [after 31000 "set x timed_out"]
sl@0
   618
	set t3 [after 32000 "set x timed_out"]
sl@0
   619
	set counter 0
sl@0
   620
	set s [socket -server accept 0]
sl@0
   621
	proc accept {s a p} {
sl@0
   622
	    fileevent $s readable [list echo $s]
sl@0
   623
	    fconfigure $s -buffering line
sl@0
   624
	}
sl@0
   625
	proc echo {s} {
sl@0
   626
	     global x
sl@0
   627
             set l [gets $s]
sl@0
   628
             if {[eof $s]} {
sl@0
   629
                 close $s
sl@0
   630
                 set x done
sl@0
   631
             } else {
sl@0
   632
                 puts $s $l
sl@0
   633
             }
sl@0
   634
	}
sl@0
   635
	puts ready
sl@0
   636
	puts [lindex [fconfigure $s -sockname] 2]
sl@0
   637
	vwait x
sl@0
   638
	after cancel $t1
sl@0
   639
	vwait x
sl@0
   640
	after cancel $t2
sl@0
   641
	vwait x
sl@0
   642
	after cancel $t3
sl@0
   643
	close $s
sl@0
   644
	puts $x
sl@0
   645
    }
sl@0
   646
    close $f
sl@0
   647
    set f [open "|[list [interpreter] $path(script)]" r+]
sl@0
   648
    set x [gets $f]
sl@0
   649
    gets $f listen
sl@0
   650
    set s1 [socket 127.0.0.1 $listen]
sl@0
   651
    fconfigure $s1 -buffering line
sl@0
   652
    set s2 [socket 127.0.0.1 $listen]
sl@0
   653
    fconfigure $s2 -buffering line
sl@0
   654
    set s3 [socket 127.0.0.1 $listen]
sl@0
   655
    fconfigure $s3 -buffering line
sl@0
   656
    for {set i 0} {$i < 100} {incr i} {
sl@0
   657
	puts $s1 hello,s1
sl@0
   658
	gets $s1
sl@0
   659
	puts $s2 hello,s2
sl@0
   660
	gets $s2
sl@0
   661
	puts $s3 hello,s3
sl@0
   662
	gets $s3
sl@0
   663
    }
sl@0
   664
    close $s1
sl@0
   665
    close $s2
sl@0
   666
    close $s3
sl@0
   667
    lappend x [gets $f]
sl@0
   668
    close $f
sl@0
   669
    set x
sl@0
   670
} {ready done}
sl@0
   671
sl@0
   672
test socket-4.1 {server with several clients} {socket stdio} {
sl@0
   673
    file delete $path(script)
sl@0
   674
    set f [open $path(script) w]
sl@0
   675
    puts $f {
sl@0
   676
	set port [gets stdin]
sl@0
   677
	set s [socket 127.0.0.1 $port]
sl@0
   678
	fconfigure $s -buffering line
sl@0
   679
	for {set i 0} {$i < 100} {incr i} {
sl@0
   680
	    puts $s hello
sl@0
   681
	    gets $s
sl@0
   682
	}
sl@0
   683
	close $s
sl@0
   684
	puts bye
sl@0
   685
	gets stdin
sl@0
   686
    }
sl@0
   687
    close $f
sl@0
   688
    set p1 [open "|[list [interpreter] $path(script)]" r+]
sl@0
   689
    fconfigure $p1 -buffering line
sl@0
   690
    set p2 [open "|[list [interpreter] $path(script)]" r+]
sl@0
   691
    fconfigure $p2 -buffering line
sl@0
   692
    set p3 [open "|[list [interpreter] $path(script)]" r+]
sl@0
   693
    fconfigure $p3 -buffering line
sl@0
   694
    proc accept {s a p} {
sl@0
   695
	fconfigure $s -buffering line
sl@0
   696
	fileevent $s readable [list echo $s]
sl@0
   697
    }
sl@0
   698
    proc echo {s} {
sl@0
   699
	global x
sl@0
   700
        set l [gets $s]
sl@0
   701
        if {[eof $s]} {
sl@0
   702
            close $s
sl@0
   703
            set x done
sl@0
   704
        } else {
sl@0
   705
            puts $s $l
sl@0
   706
        }
sl@0
   707
    }
sl@0
   708
    set t1 [after 30000 "set x timed_out"]
sl@0
   709
    set t2 [after 31000 "set x timed_out"]
sl@0
   710
    set t3 [after 32000 "set x timed_out"]
sl@0
   711
    set s [socket -server accept 0]
sl@0
   712
    set listen [lindex [fconfigure $s -sockname] 2]
sl@0
   713
    puts $p1 $listen
sl@0
   714
    puts $p2 $listen
sl@0
   715
    puts $p3 $listen
sl@0
   716
    vwait x
sl@0
   717
    vwait x
sl@0
   718
    vwait x
sl@0
   719
    after cancel $t1
sl@0
   720
    after cancel $t2
sl@0
   721
    after cancel $t3
sl@0
   722
    close $s
sl@0
   723
    set l ""
sl@0
   724
    lappend l [list p1 [gets $p1] $x]
sl@0
   725
    lappend l [list p2 [gets $p2] $x]
sl@0
   726
    lappend l [list p3 [gets $p3] $x]
sl@0
   727
    puts $p1 bye
sl@0
   728
    puts $p2 bye
sl@0
   729
    puts $p3 bye
sl@0
   730
    close $p1
sl@0
   731
    close $p2
sl@0
   732
    close $p3
sl@0
   733
    set l
sl@0
   734
} {{p1 bye done} {p2 bye done} {p3 bye done}}
sl@0
   735
test socket-4.2 {byte order problems, socket numbers, htons} {socket} {
sl@0
   736
    set x ok
sl@0
   737
    if {[catch {socket -server dodo 0x3000} msg]} {
sl@0
   738
	set x $msg
sl@0
   739
    } else {
sl@0
   740
	close $msg
sl@0
   741
    }
sl@0
   742
    set x
sl@0
   743
} ok
sl@0
   744
sl@0
   745
test socket-5.1 {byte order problems, socket numbers, htons} \
sl@0
   746
	{socket unixOnly notRoot} {
sl@0
   747
    set x {couldn't open socket: not owner}
sl@0
   748
    if {![catch {socket -server dodo 0x1} msg]} {
sl@0
   749
        set x {htons problem, should be disallowed, are you running as SU?}
sl@0
   750
	close $msg
sl@0
   751
    }
sl@0
   752
    set x
sl@0
   753
} {couldn't open socket: not owner}
sl@0
   754
test socket-5.2 {byte order problems, socket numbers, htons} {socket} {
sl@0
   755
    set x {couldn't open socket: port number too high}
sl@0
   756
    if {![catch {socket -server dodo 0x10000} msg]} {
sl@0
   757
	set x {port resolution problem, should be disallowed}
sl@0
   758
	close $msg
sl@0
   759
    }
sl@0
   760
    set x
sl@0
   761
} {couldn't open socket: port number too high}
sl@0
   762
test socket-5.3 {byte order problems, socket numbers, htons} \
sl@0
   763
	{socket unixOnly notRoot} {
sl@0
   764
    set x {couldn't open socket: not owner}
sl@0
   765
    if {![catch {socket -server dodo 21} msg]} {
sl@0
   766
	set x {htons problem, should be disallowed, are you running as SU?}
sl@0
   767
	close $msg
sl@0
   768
    }
sl@0
   769
    set x
sl@0
   770
} {couldn't open socket: not owner}
sl@0
   771
sl@0
   772
test socket-6.1 {accept callback error} {socket stdio} {
sl@0
   773
    file delete $path(script)
sl@0
   774
    set f [open $path(script) w]
sl@0
   775
    puts $f {
sl@0
   776
	gets stdin port
sl@0
   777
	socket 127.0.0.1 $port
sl@0
   778
    }
sl@0
   779
    close $f
sl@0
   780
    set f [open "|[list [interpreter] $path(script)]" r+]
sl@0
   781
    proc bgerror args {
sl@0
   782
	global x
sl@0
   783
	set x $args
sl@0
   784
    }
sl@0
   785
    proc accept {s a p} {expr 10 / 0}
sl@0
   786
    set s [socket -server accept 0]
sl@0
   787
    puts $f [lindex [fconfigure $s -sockname] 2]
sl@0
   788
    close $f
sl@0
   789
    set timer [after 10000 "set x timed_out"]
sl@0
   790
    vwait x
sl@0
   791
    after cancel $timer
sl@0
   792
    close $s
sl@0
   793
    rename bgerror {}
sl@0
   794
    set x
sl@0
   795
} {{divide by zero}}
sl@0
   796
sl@0
   797
test socket-7.1 {testing socket specific options} {socket stdio} {
sl@0
   798
    file delete $path(script)
sl@0
   799
    set f [open $path(script) w]
sl@0
   800
    puts $f {
sl@0
   801
	set ss [socket -server accept 0]
sl@0
   802
	proc accept args {
sl@0
   803
	    global x
sl@0
   804
	    set x done
sl@0
   805
	}
sl@0
   806
	puts ready
sl@0
   807
	puts [lindex [fconfigure $ss -sockname] 2]
sl@0
   808
	set timer [after 10000 "set x timed_out"]
sl@0
   809
	vwait x
sl@0
   810
	after cancel $timer
sl@0
   811
    }
sl@0
   812
    close $f
sl@0
   813
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   814
    gets $f
sl@0
   815
    gets $f listen
sl@0
   816
    set s [socket 127.0.0.1 $listen]
sl@0
   817
    set p [fconfigure $s -peername]
sl@0
   818
    close $s
sl@0
   819
    close $f
sl@0
   820
    set l ""
sl@0
   821
    lappend l [string compare [lindex $p 0] 127.0.0.1]
sl@0
   822
    lappend l [string compare [lindex $p 2] $listen]
sl@0
   823
    lappend l [llength $p]
sl@0
   824
} {0 0 3}
sl@0
   825
test socket-7.2 {testing socket specific options} {socket stdio} {
sl@0
   826
    file delete $path(script)
sl@0
   827
    set f [open $path(script) w]
sl@0
   828
    puts $f {
sl@0
   829
	set ss [socket -server accept 2821]
sl@0
   830
	proc accept args {
sl@0
   831
	    global x
sl@0
   832
	    set x done
sl@0
   833
	}
sl@0
   834
	puts ready
sl@0
   835
	puts [lindex [fconfigure $ss -sockname] 2]
sl@0
   836
	set timer [after 10000 "set x timed_out"]
sl@0
   837
	vwait x
sl@0
   838
	after cancel $timer
sl@0
   839
    }
sl@0
   840
    close $f
sl@0
   841
    set f [open "|[list [interpreter] $path(script)]" r]
sl@0
   842
    gets $f
sl@0
   843
    gets $f listen
sl@0
   844
    set s [socket 127.0.0.1 $listen]
sl@0
   845
    set p [fconfigure $s -sockname]
sl@0
   846
    close $s
sl@0
   847
    close $f
sl@0
   848
    list [llength $p] \
sl@0
   849
	    [regexp {^(127\.0\.0\.1|0\.0\.0\.0)$} [lindex $p 0]] \
sl@0
   850
	    [expr {[lindex $p 2] == $listen}]
sl@0
   851
} {3 1 0}
sl@0
   852
test socket-7.3 {testing socket specific options} {socket} {
sl@0
   853
    set s [socket -server accept 0]
sl@0
   854
    set l [fconfigure $s]
sl@0
   855
    close $s
sl@0
   856
    update
sl@0
   857
    llength $l
sl@0
   858
} 14
sl@0
   859
test socket-7.4 {testing socket specific options} {socket} {
sl@0
   860
    set s [socket -server accept 0]
sl@0
   861
    proc accept {s a p} {
sl@0
   862
	global x
sl@0
   863
	set x [fconfigure $s -sockname]
sl@0
   864
	close $s
sl@0
   865
    }
sl@0
   866
    set listen [lindex [fconfigure $s -sockname] 2]
sl@0
   867
    set s1 [socket [info hostname] $listen]
sl@0
   868
    set timer [after 10000 "set x timed_out"]
sl@0
   869
    vwait x
sl@0
   870
    after cancel $timer
sl@0
   871
    close $s
sl@0
   872
    close $s1
sl@0
   873
    set l ""
sl@0
   874
    lappend l [expr {[lindex $x 2] == $listen}] [llength $x]
sl@0
   875
} {1 3}
sl@0
   876
test socket-7.5 {testing socket specific options} {socket unixOrPc} {
sl@0
   877
    set s [socket -server accept 0]
sl@0
   878
    proc accept {s a p} {
sl@0
   879
	global x
sl@0
   880
	set x [fconfigure $s -sockname]
sl@0
   881
	close $s
sl@0
   882
    }
sl@0
   883
    set listen [lindex [fconfigure $s -sockname] 2]
sl@0
   884
    set s1 [socket 127.0.0.1 $listen]
sl@0
   885
    set timer [after 10000 "set x timed_out"]
sl@0
   886
    vwait x
sl@0
   887
    after cancel $timer
sl@0
   888
    close $s
sl@0
   889
    close $s1
sl@0
   890
    set l ""
sl@0
   891
    lappend l [lindex $x 0] [expr {[lindex $x 2] == $listen}] [llength $x]
sl@0
   892
} {127.0.0.1 1 3}
sl@0
   893
sl@0
   894
test socket-8.1 {testing -async flag on sockets} {socket} {
sl@0
   895
    # NOTE: This test may fail on some Solaris 2.4 systems. If it does,
sl@0
   896
    # check that you have these patches installed (using showrev -p):
sl@0
   897
    #
sl@0
   898
    # 101907-05, 101925-02, 101945-14, 101959-03, 101969-05, 101973-03,
sl@0
   899
    # 101977-03, 101981-02, 101985-01, 102001-03, 102003-01, 102007-01,
sl@0
   900
    # 102011-02, 102024-01, 102039-01, 102044-01, 102048-01, 102062-03,
sl@0
   901
    # 102066-04, 102070-01, 102105-01, 102153-03, 102216-01, 102232-01,
sl@0
   902
    # 101878-03, 101879-01, 101880-03, 101933-01, 101950-01, 102030-01,
sl@0
   903
    # 102057-08, 102140-01, 101920-02, 101921-09, 101922-07, 101923-03
sl@0
   904
    #
sl@0
   905
    # If after installing these patches you are still experiencing a
sl@0
   906
    # problem, please email jyl@eng.sun.com. We have not observed this
sl@0
   907
    # failure on Solaris 2.5, so another option (instead of installing
sl@0
   908
    # these patches) is to upgrade to Solaris 2.5.
sl@0
   909
    set s [socket -server accept 0]
sl@0
   910
    proc accept {s a p} {
sl@0
   911
	global x
sl@0
   912
	puts $s bye
sl@0
   913
	close $s
sl@0
   914
	set x done
sl@0
   915
    }
sl@0
   916
    set s1 [socket -async [info hostname] [lindex [fconfigure $s -sockname] 2]]
sl@0
   917
    vwait x
sl@0
   918
    set z [gets $s1]
sl@0
   919
    close $s
sl@0
   920
    close $s1
sl@0
   921
    set z
sl@0
   922
} bye
sl@0
   923
sl@0
   924
test socket-9.1 {testing spurious events} {socket} {
sl@0
   925
    set len 0
sl@0
   926
    set spurious 0
sl@0
   927
    set done 0
sl@0
   928
    proc readlittle {s} {
sl@0
   929
	global spurious done len
sl@0
   930
	set l [read $s 1]
sl@0
   931
	if {[string length $l] == 0} {
sl@0
   932
	    if {![eof $s]} {
sl@0
   933
		incr spurious
sl@0
   934
	    } else {
sl@0
   935
		close $s
sl@0
   936
		set done 1
sl@0
   937
	    }
sl@0
   938
	} else {
sl@0
   939
	    incr len [string length $l]
sl@0
   940
	}
sl@0
   941
    }
sl@0
   942
    proc accept {s a p} {
sl@0
   943
	fconfigure $s -buffering none -blocking off
sl@0
   944
	fileevent $s readable [list readlittle $s]
sl@0
   945
    }
sl@0
   946
    set s [socket -server accept 0]
sl@0
   947
    set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]]
sl@0
   948
    puts -nonewline $c 01234567890123456789012345678901234567890123456789
sl@0
   949
    close $c
sl@0
   950
    set timer [after 10000 "set done timed_out"]
sl@0
   951
    vwait done
sl@0
   952
    after cancel $timer
sl@0
   953
    close $s
sl@0
   954
    list $spurious $len
sl@0
   955
} {0 50}
sl@0
   956
test socket-9.2 {testing async write, fileevents, flush on close} {socket} {
sl@0
   957
    set firstblock ""
sl@0
   958
    for {set i 0} {$i < 5} {incr i} {set firstblock "a$firstblock$firstblock"}
sl@0
   959
    set secondblock ""
sl@0
   960
    for {set i 0} {$i < 16} {incr i} {
sl@0
   961
	set secondblock "b$secondblock$secondblock"
sl@0
   962
    }
sl@0
   963
    set l [socket -server accept 0]
sl@0
   964
    proc accept {s a p} {
sl@0
   965
	fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
sl@0
   966
		-buffering line
sl@0
   967
	fileevent $s readable "readable $s"
sl@0
   968
    }
sl@0
   969
    proc readable {s} {
sl@0
   970
	set l [gets $s]
sl@0
   971
	fileevent $s readable {}
sl@0
   972
	after 1000 respond $s
sl@0
   973
    }
sl@0
   974
    proc respond {s} {
sl@0
   975
	global firstblock
sl@0
   976
	puts -nonewline $s $firstblock
sl@0
   977
	after 1000 writedata $s
sl@0
   978
    }
sl@0
   979
    proc writedata {s} {
sl@0
   980
	global secondblock
sl@0
   981
	puts -nonewline $s $secondblock
sl@0
   982
	close $s
sl@0
   983
    }
sl@0
   984
    set s [socket [info hostname] [lindex [fconfigure $l -sockname] 2]]
sl@0
   985
    fconfigure $s -blocking 0 -trans lf -buffering line
sl@0
   986
    set count 0
sl@0
   987
    puts $s hello
sl@0
   988
    proc readit {s} {
sl@0
   989
	global count done
sl@0
   990
	set l [read $s]
sl@0
   991
	incr count [string length $l]
sl@0
   992
	if {[eof $s]} {
sl@0
   993
	    close $s
sl@0
   994
	    set done 1
sl@0
   995
	}
sl@0
   996
    }
sl@0
   997
    fileevent $s readable "readit $s"
sl@0
   998
    set timer [after 10000 "set done timed_out"]
sl@0
   999
    vwait done
sl@0
  1000
    after cancel $timer
sl@0
  1001
    close $l
sl@0
  1002
    set count
sl@0
  1003
} 65566
sl@0
  1004
test socket-9.3 {testing EOF stickyness} {socket} {
sl@0
  1005
    proc count_to_eof {s} {
sl@0
  1006
	global count done timer
sl@0
  1007
	set l [gets $s]
sl@0
  1008
	if {[eof $s]} {
sl@0
  1009
	    incr count
sl@0
  1010
	    if {$count > 9} {
sl@0
  1011
		close $s
sl@0
  1012
		set done true
sl@0
  1013
		set count {eof is sticky}
sl@0
  1014
		after cancel $timer
sl@0
  1015
	    }
sl@0
  1016
	}
sl@0
  1017
    }
sl@0
  1018
    proc timerproc {} {
sl@0
  1019
	global done count c
sl@0
  1020
	set done true
sl@0
  1021
	set count {timer went off, eof is not sticky}
sl@0
  1022
	close $c
sl@0
  1023
    }	
sl@0
  1024
    set count 0
sl@0
  1025
    set done false
sl@0
  1026
    proc write_then_close {s} {
sl@0
  1027
	puts $s bye
sl@0
  1028
	close $s
sl@0
  1029
    }
sl@0
  1030
    proc accept {s a p} {
sl@0
  1031
	fconfigure $s -buffering line -translation lf
sl@0
  1032
	fileevent $s writable "write_then_close $s"
sl@0
  1033
    }
sl@0
  1034
    set s [socket -server accept 0]
sl@0
  1035
    set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]]
sl@0
  1036
    fconfigure $c -blocking off -buffering line -translation lf
sl@0
  1037
    fileevent $c readable "count_to_eof $c"
sl@0
  1038
    set timer [after 1000 timerproc]
sl@0
  1039
    vwait done
sl@0
  1040
    close $s
sl@0
  1041
    set count
sl@0
  1042
} {eof is sticky}
sl@0
  1043
sl@0
  1044
removeFile script
sl@0
  1045
sl@0
  1046
test socket-10.1 {testing socket accept callback error handling} {socket} {
sl@0
  1047
    set goterror 0
sl@0
  1048
    proc bgerror args {global goterror; set goterror 1}
sl@0
  1049
    set s [socket -server accept 0]
sl@0
  1050
    proc accept {s a p} {close $s; error}
sl@0
  1051
    set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
sl@0
  1052
    vwait goterror
sl@0
  1053
    close $s
sl@0
  1054
    close $c
sl@0
  1055
    set goterror
sl@0
  1056
} 1
sl@0
  1057
sl@0
  1058
test socket-11.1 {tcp connection} {socket doTestsWithRemoteServer} {
sl@0
  1059
    sendCommand {
sl@0
  1060
	set socket9_1_test_server [socket -server accept 2834]
sl@0
  1061
	proc accept {s a p} {
sl@0
  1062
	    puts $s done
sl@0
  1063
	    close $s
sl@0
  1064
	}
sl@0
  1065
    }
sl@0
  1066
    set s [socket $remoteServerIP 2834]
sl@0
  1067
    set r [gets $s]
sl@0
  1068
    close $s
sl@0
  1069
    sendCommand {close $socket9_1_test_server}
sl@0
  1070
    set r
sl@0
  1071
} done
sl@0
  1072
test socket-11.2 {client specifies its port} {socket doTestsWithRemoteServer} {
sl@0
  1073
    if {[info exists port]} {
sl@0
  1074
	incr port
sl@0
  1075
    } else {
sl@0
  1076
	set port [expr 2048 + [pid]%1024]
sl@0
  1077
    }
sl@0
  1078
    sendCommand {
sl@0
  1079
	set socket9_2_test_server [socket -server accept 2835]
sl@0
  1080
	proc accept {s a p} {
sl@0
  1081
	    puts $s $p
sl@0
  1082
	    close $s
sl@0
  1083
	}
sl@0
  1084
    }
sl@0
  1085
    set s [socket -myport $port $remoteServerIP 2835]
sl@0
  1086
    set r [gets $s]
sl@0
  1087
    close $s
sl@0
  1088
    sendCommand {close $socket9_2_test_server}
sl@0
  1089
    if {$r == $port} {
sl@0
  1090
	set result ok
sl@0
  1091
    } else {
sl@0
  1092
	set result broken
sl@0
  1093
    }
sl@0
  1094
    set result
sl@0
  1095
} ok
sl@0
  1096
test socket-11.3 {trying to connect, no server} {socket doTestsWithRemoteServer} {
sl@0
  1097
    set status ok
sl@0
  1098
    if {![catch {set s [socket $remoteServerIp 2836]}]} {
sl@0
  1099
	if {![catch {gets $s}]} {
sl@0
  1100
	    set status broken
sl@0
  1101
	}
sl@0
  1102
	close $s
sl@0
  1103
    }
sl@0
  1104
    set status
sl@0
  1105
} ok
sl@0
  1106
test socket-11.4 {remote echo, one line} {socket doTestsWithRemoteServer} {
sl@0
  1107
    sendCommand {
sl@0
  1108
	set socket10_6_test_server [socket -server accept 2836]
sl@0
  1109
	proc accept {s a p} {
sl@0
  1110
	    fileevent $s readable [list echo $s]
sl@0
  1111
	    fconfigure $s -buffering line -translation crlf
sl@0
  1112
	}
sl@0
  1113
	proc echo {s} {
sl@0
  1114
	    set l [gets $s]
sl@0
  1115
	    if {[eof $s]} {
sl@0
  1116
		close $s
sl@0
  1117
	    } else {
sl@0
  1118
		puts $s $l
sl@0
  1119
	    }
sl@0
  1120
	}
sl@0
  1121
    }
sl@0
  1122
    set f [socket $remoteServerIP 2836]
sl@0
  1123
    fconfigure $f -translation crlf -buffering line
sl@0
  1124
    puts $f hello
sl@0
  1125
    set r [gets $f]
sl@0
  1126
    close $f
sl@0
  1127
    sendCommand {close $socket10_6_test_server}
sl@0
  1128
    set r
sl@0
  1129
} hello
sl@0
  1130
test socket-11.5 {remote echo, 50 lines} {socket doTestsWithRemoteServer} {
sl@0
  1131
    sendCommand {
sl@0
  1132
	set socket10_7_test_server [socket -server accept 2836]
sl@0
  1133
	proc accept {s a p} {
sl@0
  1134
	    fileevent $s readable [list echo $s]
sl@0
  1135
	    fconfigure $s -buffering line -translation crlf
sl@0
  1136
	}
sl@0
  1137
	proc echo {s} {
sl@0
  1138
	    set l [gets $s]
sl@0
  1139
	    if {[eof $s]} {
sl@0
  1140
		close $s
sl@0
  1141
	    } else {
sl@0
  1142
		puts $s $l
sl@0
  1143
	    }
sl@0
  1144
	}
sl@0
  1145
    }
sl@0
  1146
    set f [socket $remoteServerIP 2836]
sl@0
  1147
    fconfigure $f -translation crlf -buffering line
sl@0
  1148
    for {set cnt 0} {$cnt < 50} {incr cnt} {
sl@0
  1149
	puts $f "hello, $cnt"
sl@0
  1150
	if {[string compare [gets $f] "hello, $cnt"] != 0} {
sl@0
  1151
	    break
sl@0
  1152
	}
sl@0
  1153
    }
sl@0
  1154
    close $f
sl@0
  1155
    sendCommand {close $socket10_7_test_server}
sl@0
  1156
    set cnt
sl@0
  1157
} 50
sl@0
  1158
# Macintosh sockets can have more than one server per port
sl@0
  1159
if {$tcl_platform(platform) == "macintosh"} {
sl@0
  1160
    set conflictResult {0 2836}
sl@0
  1161
} else {
sl@0
  1162
    set conflictResult {1 {couldn't open socket: address already in use}}
sl@0
  1163
}
sl@0
  1164
test socket-11.6 {socket conflict} {socket doTestsWithRemoteServer} {
sl@0
  1165
    set s1 [socket -server accept 2836]
sl@0
  1166
    if {[catch {set s2 [socket -server accept 2836]} msg]} {
sl@0
  1167
	set result [list 1 $msg]
sl@0
  1168
    } else {
sl@0
  1169
	set result [list 0 [lindex [fconfigure $s2 -sockname] 2]]
sl@0
  1170
	close $s2
sl@0
  1171
    }
sl@0
  1172
    close $s1
sl@0
  1173
    set result
sl@0
  1174
} $conflictResult
sl@0
  1175
test socket-11.7 {server with several clients} {socket doTestsWithRemoteServer} {
sl@0
  1176
    sendCommand {
sl@0
  1177
	set socket10_9_test_server [socket -server accept 2836]
sl@0
  1178
	proc accept {s a p} {
sl@0
  1179
	    fconfigure $s -buffering line
sl@0
  1180
	    fileevent $s readable [list echo $s]
sl@0
  1181
	}
sl@0
  1182
	proc echo {s} {
sl@0
  1183
	    set l [gets $s]
sl@0
  1184
	    if {[eof $s]} {
sl@0
  1185
		close $s
sl@0
  1186
	    } else {
sl@0
  1187
		puts $s $l
sl@0
  1188
	    }
sl@0
  1189
	}
sl@0
  1190
    }
sl@0
  1191
    set s1 [socket $remoteServerIP 2836]
sl@0
  1192
    fconfigure $s1 -buffering line
sl@0
  1193
    set s2 [socket $remoteServerIP 2836]
sl@0
  1194
    fconfigure $s2 -buffering line
sl@0
  1195
    set s3 [socket $remoteServerIP 2836]
sl@0
  1196
    fconfigure $s3 -buffering line
sl@0
  1197
    for {set i 0} {$i < 100} {incr i} {
sl@0
  1198
	puts $s1 hello,s1
sl@0
  1199
	gets $s1
sl@0
  1200
	puts $s2 hello,s2
sl@0
  1201
	gets $s2
sl@0
  1202
	puts $s3 hello,s3
sl@0
  1203
	gets $s3
sl@0
  1204
    }
sl@0
  1205
    close $s1
sl@0
  1206
    close $s2
sl@0
  1207
    close $s3
sl@0
  1208
    sendCommand {close $socket10_9_test_server}
sl@0
  1209
    set i
sl@0
  1210
} 100    
sl@0
  1211
test socket-11.8 {client with several servers} {socket doTestsWithRemoteServer} {
sl@0
  1212
    sendCommand {
sl@0
  1213
	set s1 [socket -server "accept 4003" 4003]
sl@0
  1214
	set s2 [socket -server "accept 4004" 4004]
sl@0
  1215
	set s3 [socket -server "accept 4005" 4005]
sl@0
  1216
	proc accept {mp s a p} {
sl@0
  1217
	    puts $s $mp
sl@0
  1218
	    close $s
sl@0
  1219
	}
sl@0
  1220
    }
sl@0
  1221
    set s1 [socket $remoteServerIP 4003]
sl@0
  1222
    set s2 [socket $remoteServerIP 4004]
sl@0
  1223
    set s3 [socket $remoteServerIP 4005]
sl@0
  1224
    set l ""
sl@0
  1225
    lappend l [gets $s1] [gets $s1] [eof $s1] [gets $s2] [gets $s2] [eof $s2] \
sl@0
  1226
	[gets $s3] [gets $s3] [eof $s3]
sl@0
  1227
    close $s1
sl@0
  1228
    close $s2
sl@0
  1229
    close $s3
sl@0
  1230
    sendCommand {
sl@0
  1231
	close $s1
sl@0
  1232
	close $s2
sl@0
  1233
	close $s3
sl@0
  1234
    }
sl@0
  1235
    set l
sl@0
  1236
} {4003 {} 1 4004 {} 1 4005 {} 1}
sl@0
  1237
test socket-11.9 {accept callback error} {socket doTestsWithRemoteServer} {
sl@0
  1238
    set s [socket -server accept 2836]
sl@0
  1239
    proc accept {s a p} {expr 10 / 0}
sl@0
  1240
    proc bgerror args {
sl@0
  1241
	global x
sl@0
  1242
	set x $args
sl@0
  1243
    }
sl@0
  1244
    if {[catch {sendCommand {
sl@0
  1245
	    set peername [fconfigure $callerSocket -peername]
sl@0
  1246
	    set s [socket [lindex $peername 0] 2836]
sl@0
  1247
	    close $s
sl@0
  1248
    	 }} msg]} {
sl@0
  1249
	close $s
sl@0
  1250
	error $msg
sl@0
  1251
    }
sl@0
  1252
    set timer [after 10000 "set x timed_out"]
sl@0
  1253
    vwait x
sl@0
  1254
    after cancel $timer
sl@0
  1255
    close $s
sl@0
  1256
    rename bgerror {}
sl@0
  1257
    set x
sl@0
  1258
} {{divide by zero}}
sl@0
  1259
test socket-11.10 {testing socket specific options} {socket doTestsWithRemoteServer} {
sl@0
  1260
    sendCommand {
sl@0
  1261
	set socket10_12_test_server [socket -server accept 2836]
sl@0
  1262
	proc accept {s a p} {close $s}
sl@0
  1263
    }
sl@0
  1264
    set s [socket $remoteServerIP 2836]
sl@0
  1265
    set p [fconfigure $s -peername]
sl@0
  1266
    set n [fconfigure $s -sockname]
sl@0
  1267
    set l ""
sl@0
  1268
    lappend l [lindex $p 2] [llength $p] [llength $p]
sl@0
  1269
    close $s
sl@0
  1270
    sendCommand {close $socket10_12_test_server}
sl@0
  1271
    set l
sl@0
  1272
} {2836 3 3}
sl@0
  1273
test socket-11.11 {testing spurious events} {socket doTestsWithRemoteServer} {
sl@0
  1274
    sendCommand {
sl@0
  1275
	set socket10_13_test_server [socket -server accept 2836]
sl@0
  1276
	proc accept {s a p} {
sl@0
  1277
	    fconfigure $s -translation "auto lf"
sl@0
  1278
	    after 100 writesome $s
sl@0
  1279
	}
sl@0
  1280
	proc writesome {s} {
sl@0
  1281
	    for {set i 0} {$i < 100} {incr i} {
sl@0
  1282
		puts $s "line $i from remote server"
sl@0
  1283
	    }
sl@0
  1284
	    close $s
sl@0
  1285
	}
sl@0
  1286
    }
sl@0
  1287
    set len 0
sl@0
  1288
    set spurious 0
sl@0
  1289
    set done 0
sl@0
  1290
    proc readlittle {s} {
sl@0
  1291
	global spurious done len
sl@0
  1292
	set l [read $s 1]
sl@0
  1293
	if {[string length $l] == 0} {
sl@0
  1294
	    if {![eof $s]} {
sl@0
  1295
		incr spurious
sl@0
  1296
	    } else {
sl@0
  1297
		close $s
sl@0
  1298
		set done 1
sl@0
  1299
	    }
sl@0
  1300
	} else {
sl@0
  1301
	    incr len [string length $l]
sl@0
  1302
	}
sl@0
  1303
    }
sl@0
  1304
    set c [socket $remoteServerIP 2836]
sl@0
  1305
    fileevent $c readable "readlittle $c"
sl@0
  1306
    set timer [after 40000 "set done timed_out"]
sl@0
  1307
    vwait done
sl@0
  1308
    after cancel $timer
sl@0
  1309
    sendCommand {close $socket10_13_test_server}
sl@0
  1310
    list $spurious $len $done
sl@0
  1311
} {0 2690 1}
sl@0
  1312
sl@0
  1313
test socket-11.12 {testing EOF stickyness} {socket doTestsWithRemoteServer} {
sl@0
  1314
    set counter 0
sl@0
  1315
    set done 0
sl@0
  1316
    proc count_up {s} {
sl@0
  1317
	global counter done after_id
sl@0
  1318
	set l [gets $s]
sl@0
  1319
	if {[eof $s]} {
sl@0
  1320
	    incr counter
sl@0
  1321
	    if {$counter > 9} {
sl@0
  1322
		set done {EOF is sticky}
sl@0
  1323
		after cancel $after_id
sl@0
  1324
		close $s
sl@0
  1325
	    }
sl@0
  1326
	}
sl@0
  1327
    }
sl@0
  1328
    proc timed_out {} {
sl@0
  1329
	global c done
sl@0
  1330
	set done {timed_out, EOF is not sticky}
sl@0
  1331
	close $c
sl@0
  1332
    }
sl@0
  1333
    sendCommand {
sl@0
  1334
	set socket10_14_test_server [socket -server accept 2836]
sl@0
  1335
	proc accept {s a p} {
sl@0
  1336
	    after 100 close $s
sl@0
  1337
	}
sl@0
  1338
    }
sl@0
  1339
    set c [socket $remoteServerIP 2836]
sl@0
  1340
    fileevent $c readable [list count_up $c]
sl@0
  1341
    set after_id [after 1000 timed_out]
sl@0
  1342
    vwait done
sl@0
  1343
    sendCommand {close $socket10_14_test_server}
sl@0
  1344
    set done
sl@0
  1345
} {EOF is sticky}
sl@0
  1346
sl@0
  1347
test socket-11.13 {testing async write, async flush, async close} \
sl@0
  1348
	{socket doTestsWithRemoteServer} {
sl@0
  1349
    proc readit {s} {
sl@0
  1350
	global count done
sl@0
  1351
	set l [read $s]
sl@0
  1352
	incr count [string length $l]
sl@0
  1353
	if {[eof $s]} {
sl@0
  1354
	    close $s
sl@0
  1355
	    set done 1
sl@0
  1356
	}
sl@0
  1357
    }
sl@0
  1358
    sendCommand {
sl@0
  1359
	set firstblock ""
sl@0
  1360
	for {set i 0} {$i < 5} {incr i} {
sl@0
  1361
		set firstblock "a$firstblock$firstblock"
sl@0
  1362
	}
sl@0
  1363
	set secondblock ""
sl@0
  1364
	for {set i 0} {$i < 16} {incr i} {
sl@0
  1365
	    set secondblock "b$secondblock$secondblock"
sl@0
  1366
	}
sl@0
  1367
	set l [socket -server accept 2845]
sl@0
  1368
	proc accept {s a p} {
sl@0
  1369
	    fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
sl@0
  1370
		-buffering line
sl@0
  1371
	    fileevent $s readable "readable $s"
sl@0
  1372
	}
sl@0
  1373
	proc readable {s} {
sl@0
  1374
	    set l [gets $s]
sl@0
  1375
	    fileevent $s readable {}
sl@0
  1376
	    after 1000 respond $s
sl@0
  1377
	}
sl@0
  1378
	proc respond {s} {
sl@0
  1379
	    global firstblock
sl@0
  1380
	    puts -nonewline $s $firstblock
sl@0
  1381
	    after 1000 writedata $s
sl@0
  1382
	}
sl@0
  1383
	proc writedata {s} {
sl@0
  1384
	    global secondblock
sl@0
  1385
	    puts -nonewline $s $secondblock
sl@0
  1386
	    close $s
sl@0
  1387
	}
sl@0
  1388
    }
sl@0
  1389
    set s [socket $remoteServerIP 2845]
sl@0
  1390
    fconfigure $s -blocking 0 -trans lf -buffering line
sl@0
  1391
    set count 0
sl@0
  1392
    puts $s hello
sl@0
  1393
    fileevent $s readable "readit $s"
sl@0
  1394
    set timer [after 10000 "set done timed_out"]
sl@0
  1395
    vwait done
sl@0
  1396
    after cancel $timer
sl@0
  1397
    sendCommand {close $l}
sl@0
  1398
    set count
sl@0
  1399
} 65566
sl@0
  1400
sl@0
  1401
set path(script1) [makeFile {} script1]
sl@0
  1402
set path(script2) [makeFile {} script2]
sl@0
  1403
sl@0
  1404
test socket-12.1 {testing inheritance of server sockets} {socket stdio exec} {
sl@0
  1405
    file delete $path(script1)
sl@0
  1406
    file delete $path(script2)
sl@0
  1407
sl@0
  1408
    # Script1 is just a 10 second delay.  If the server socket
sl@0
  1409
    # is inherited, it will be held open for 10 seconds
sl@0
  1410
sl@0
  1411
    set f [open $path(script1) w]
sl@0
  1412
    puts $f {
sl@0
  1413
	after 10000 exit
sl@0
  1414
	vwait forever
sl@0
  1415
    }
sl@0
  1416
    close $f
sl@0
  1417
sl@0
  1418
    # Script2 creates the server socket, launches script1,
sl@0
  1419
    # waits a second, and exits.  The server socket will now
sl@0
  1420
    # be closed unless script1 inherited it.
sl@0
  1421
sl@0
  1422
    set f [open $path(script2) w]
sl@0
  1423
    puts $f [list set tcltest [interpreter]]
sl@0
  1424
    puts -nonewline $f {
sl@0
  1425
	set f [socket -server accept 0]
sl@0
  1426
	puts [lindex [fconfigure $f -sockname] 2]
sl@0
  1427
	proc accept { file addr port } {
sl@0
  1428
	    close $file
sl@0
  1429
	}
sl@0
  1430
	exec $tcltest }
sl@0
  1431
    puts $f [list $path(script1) &]
sl@0
  1432
    puts $f {
sl@0
  1433
	close $f
sl@0
  1434
	after 1000 exit
sl@0
  1435
	vwait forever
sl@0
  1436
    }
sl@0
  1437
    close $f
sl@0
  1438
	
sl@0
  1439
    # Launch script2 and wait 5 seconds
sl@0
  1440
sl@0
  1441
    ### exec [interpreter] script2 &
sl@0
  1442
    set p [open "|[list [interpreter] $path(script2)]" r]
sl@0
  1443
    gets $p listen
sl@0
  1444
sl@0
  1445
    after 5000 { set ok_to_proceed 1 }
sl@0
  1446
    vwait ok_to_proceed
sl@0
  1447
sl@0
  1448
    # If we can still connect to the server, the socket got inherited.
sl@0
  1449
sl@0
  1450
    if {[catch {socket 127.0.0.1 $listen} msg]} {
sl@0
  1451
	set x {server socket was not inherited}
sl@0
  1452
    } else {
sl@0
  1453
	close $msg
sl@0
  1454
	set x {server socket was inherited}
sl@0
  1455
    }
sl@0
  1456
sl@0
  1457
    close $p
sl@0
  1458
    set x
sl@0
  1459
} {server socket was not inherited}
sl@0
  1460
test socket-12.2 {testing inheritance of client sockets} {socket stdio exec} {
sl@0
  1461
    file delete $path(script1)
sl@0
  1462
    file delete $path(script2)
sl@0
  1463
sl@0
  1464
    # Script1 is just a 20 second delay.  If the server socket
sl@0
  1465
    # is inherited, it will be held open for 10 seconds
sl@0
  1466
sl@0
  1467
    set f [open $path(script1) w]
sl@0
  1468
    puts $f {
sl@0
  1469
	after 20000 exit
sl@0
  1470
	vwait forever
sl@0
  1471
    }
sl@0
  1472
    close $f
sl@0
  1473
sl@0
  1474
    # Script2 opens the client socket and writes to it.  It then
sl@0
  1475
    # launches script1 and exits.  If the child process inherited the
sl@0
  1476
    # client socket, the socket will still be open.
sl@0
  1477
sl@0
  1478
    set f [open $path(script2) w]
sl@0
  1479
    puts $f [list set tcltest [interpreter]]
sl@0
  1480
    puts -nonewline $f {
sl@0
  1481
        gets stdin port
sl@0
  1482
	set f [socket 127.0.0.1 $port]
sl@0
  1483
        exec $tcltest }
sl@0
  1484
    puts $f [list $path(script1) &]
sl@0
  1485
    puts $f {
sl@0
  1486
	puts $f testing
sl@0
  1487
	flush $f
sl@0
  1488
	after 1000 exit
sl@0
  1489
	vwait forever
sl@0
  1490
    }
sl@0
  1491
    close $f
sl@0
  1492
sl@0
  1493
    # Create the server socket
sl@0
  1494
sl@0
  1495
    set server [socket -server accept 0]
sl@0
  1496
    proc accept { file host port } {
sl@0
  1497
	# When the client connects, establish the read handler
sl@0
  1498
	global server
sl@0
  1499
	close $server
sl@0
  1500
	fileevent $file readable [list getdata $file]
sl@0
  1501
	fconfigure $file -buffering line -blocking 0
sl@0
  1502
	return
sl@0
  1503
    }
sl@0
  1504
    proc getdata { file } {
sl@0
  1505
	# Read handler on the accepted socket.
sl@0
  1506
	global x
sl@0
  1507
	global failed
sl@0
  1508
	set status [catch {read $file} data]
sl@0
  1509
	if {$status != 0} {
sl@0
  1510
	    set x {read failed, error was $data}
sl@0
  1511
	    catch { close $file }
sl@0
  1512
	} elseif {[string compare {} $data]} {
sl@0
  1513
	} elseif {[fblocked $file]} {
sl@0
  1514
	} elseif {[eof $file]} {
sl@0
  1515
	    if {$failed} {
sl@0
  1516
		set x {client socket was inherited}
sl@0
  1517
	    } else {
sl@0
  1518
		set x {client socket was not inherited}
sl@0
  1519
	    }
sl@0
  1520
	    catch { close $file }
sl@0
  1521
	} else {
sl@0
  1522
	    set x {impossible case}
sl@0
  1523
	    catch { close $file }
sl@0
  1524
	}
sl@0
  1525
	return
sl@0
  1526
    }
sl@0
  1527
sl@0
  1528
    # If the socket doesn't hit end-of-file in 10 seconds, the
sl@0
  1529
    # script1 process must have inherited the client.
sl@0
  1530
sl@0
  1531
    set failed 0
sl@0
  1532
    after 10000 [list set failed 1]
sl@0
  1533
sl@0
  1534
    # Launch the script2 process
sl@0
  1535
    ### exec [interpreter] script2 &
sl@0
  1536
sl@0
  1537
    set p [open "|[list [interpreter] $path(script2)]" w]
sl@0
  1538
    puts $p [lindex [fconfigure $server -sockname] 2] ; flush $p
sl@0
  1539
sl@0
  1540
    vwait x
sl@0
  1541
    if {!$failed} {
sl@0
  1542
	vwait failed
sl@0
  1543
    }
sl@0
  1544
    close $p
sl@0
  1545
    set x
sl@0
  1546
} {client socket was not inherited}
sl@0
  1547
test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} {
sl@0
  1548
    file delete $path(script1)
sl@0
  1549
    file delete $path(script2)
sl@0
  1550
sl@0
  1551
    set f [open $path(script1) w]
sl@0
  1552
    puts $f {
sl@0
  1553
	after 10000 exit
sl@0
  1554
	vwait forever
sl@0
  1555
    }
sl@0
  1556
    close $f
sl@0
  1557
sl@0
  1558
    set f [open $path(script2) w]
sl@0
  1559
    puts $f [list set tcltest [interpreter]]
sl@0
  1560
    puts -nonewline $f {
sl@0
  1561
	set server [socket -server accept 0]
sl@0
  1562
	puts stdout [lindex [fconfigure $server -sockname] 2]
sl@0
  1563
	proc accept { file host port } }
sl@0
  1564
    puts $f \{
sl@0
  1565
    puts -nonewline $f {
sl@0
  1566
	    global tcltest
sl@0
  1567
	    puts $file {test data on socket}
sl@0
  1568
	    exec $tcltest }
sl@0
  1569
    puts $f [list $path(script1) &]
sl@0
  1570
    puts $f {
sl@0
  1571
	    after 1000 exit
sl@0
  1572
	}
sl@0
  1573
    puts $f \} 
sl@0
  1574
    puts $f {
sl@0
  1575
	vwait forever
sl@0
  1576
    }
sl@0
  1577
    close $f
sl@0
  1578
sl@0
  1579
    # Launch the script2 process and connect to it.  See how long
sl@0
  1580
    # the socket stays open
sl@0
  1581
sl@0
  1582
    ## exec [interpreter] script2 &
sl@0
  1583
    set p [open "|[list [interpreter] $path(script2)]" r]
sl@0
  1584
    gets $p listen
sl@0
  1585
sl@0
  1586
    after 1000 set ok_to_proceed 1
sl@0
  1587
    vwait ok_to_proceed
sl@0
  1588
sl@0
  1589
    set f [socket 127.0.0.1 $listen]
sl@0
  1590
    fconfigure $f -buffering full -blocking 0
sl@0
  1591
    fileevent $f readable [list getdata $f]
sl@0
  1592
sl@0
  1593
    # If the socket is still open after 5 seconds, the script1 process
sl@0
  1594
    # must have inherited the accepted socket.
sl@0
  1595
sl@0
  1596
    set failed 0
sl@0
  1597
    after 5000 set failed 1
sl@0
  1598
sl@0
  1599
    proc getdata { file } {
sl@0
  1600
	# Read handler on the client socket.
sl@0
  1601
	global x
sl@0
  1602
	global failed
sl@0
  1603
	set status [catch {read $file} data]
sl@0
  1604
	if {$status != 0} {
sl@0
  1605
	    set x {read failed, error was $data}
sl@0
  1606
	    catch { close $file }
sl@0
  1607
	} elseif {[string compare {} $data]} {
sl@0
  1608
	} elseif {[fblocked $file]} {
sl@0
  1609
	} elseif {[eof $file]} {
sl@0
  1610
	    if {$failed} {
sl@0
  1611
		set x {accepted socket was inherited}
sl@0
  1612
	    } else {
sl@0
  1613
		set x {accepted socket was not inherited}
sl@0
  1614
	    }
sl@0
  1615
	    catch { close $file }
sl@0
  1616
	} else {
sl@0
  1617
	    set x {impossible case}
sl@0
  1618
	    catch { close $file }
sl@0
  1619
	}
sl@0
  1620
	return
sl@0
  1621
    }
sl@0
  1622
    
sl@0
  1623
    vwait x
sl@0
  1624
sl@0
  1625
    close $p
sl@0
  1626
    set x
sl@0
  1627
} {accepted socket was not inherited}
sl@0
  1628
sl@0
  1629
test socket-13.1 {Testing use of shared socket between two threads} \
sl@0
  1630
	-constraints {socket testthread} -setup {
sl@0
  1631
sl@0
  1632
    threadReap
sl@0
  1633
sl@0
  1634
    set path(script) [makeFile {
sl@0
  1635
	set f [socket -server accept 0]
sl@0
  1636
	set listen [lindex [fconfigure $f -sockname] 2]
sl@0
  1637
	proc accept {s a p} {
sl@0
  1638
            fileevent $s readable [list echo $s]
sl@0
  1639
            fconfigure $s -buffering line
sl@0
  1640
        }
sl@0
  1641
	proc echo {s} {
sl@0
  1642
	     global i
sl@0
  1643
             set l [gets $s]
sl@0
  1644
             if {[eof $s]} {
sl@0
  1645
                 global x
sl@0
  1646
                 close $s
sl@0
  1647
                 set x done
sl@0
  1648
             } else { 
sl@0
  1649
	         incr i
sl@0
  1650
                 puts $s $l
sl@0
  1651
             }
sl@0
  1652
	}
sl@0
  1653
	set i 0
sl@0
  1654
	vwait x
sl@0
  1655
	close $f
sl@0
  1656
sl@0
  1657
	# thread cleans itself up.
sl@0
  1658
	testthread exit
sl@0
  1659
    } script]
sl@0
  1660
sl@0
  1661
} -body {
sl@0
  1662
    # create a thread
sl@0
  1663
    set serverthread [testthread create [list source $path(script) ] ]
sl@0
  1664
    update
sl@0
  1665
    set port [testthread send $serverthread {set listen}]
sl@0
  1666
    update
sl@0
  1667
sl@0
  1668
    after 1000
sl@0
  1669
    set s [socket 127.0.0.1 $port]
sl@0
  1670
    fconfigure $s -buffering line
sl@0
  1671
sl@0
  1672
    catch {
sl@0
  1673
	puts $s "hello"
sl@0
  1674
	gets $s result
sl@0
  1675
    }
sl@0
  1676
    close $s
sl@0
  1677
    update
sl@0
  1678
sl@0
  1679
    after 2000
sl@0
  1680
    lappend result [threadReap]
sl@0
  1681
} -cleanup {
sl@0
  1682
    removeFile script
sl@0
  1683
} -result {hello 1}
sl@0
  1684
sl@0
  1685
removeFile script1
sl@0
  1686
removeFile script2
sl@0
  1687
sl@0
  1688
# cleanup
sl@0
  1689
if {[string match sock* $commandSocket] == 1} {
sl@0
  1690
   puts $commandSocket exit
sl@0
  1691
   flush $commandSocket
sl@0
  1692
}
sl@0
  1693
catch {close $commandSocket}
sl@0
  1694
catch {close $remoteProcChan}
sl@0
  1695
::tcltest::cleanupTests
sl@0
  1696
flush stdout
sl@0
  1697
return