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