Diff
Bounty program for improvements to Tcl and certain Tcl packages.

Differences From Artifact [b3da26dcef]:

To Artifact [61c9f2ee71]:


1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20











-
+







# Commands tested in this file: socket.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions. 
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: tlsIO.test,v 1.18 2001/06/21 20:45:43 hobbs Exp $
# RCS: @(#) $Id: tlsIO.test,v 1.19 2002/02/04 22:45:11 hobbs Exp $

# Running socket tests with a remote server:
# ------------------------------------------
# 
# Some tests in socket.test depend on the existence of a remote server to
# which they connect. The remote server must be an instance of tcltest and it
# must run the script found in the file "remote.tcl" in this directory. You
65
66
67
68
69
70
71


72
73
74
75
76
77
78
79
80
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81






+
+

-







proc dputs {msg} { return ; puts stderr $msg ; flush stderr }

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# The build dir is added as the first element of $PATH
set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
# Load the tls package

package require tls 1.4

set tlsServerPort 8048

# Specify where the certificates are

set certsDir	[file join [file dirname [info script]] certs]
116
117
118
119
120
121
122
123

124
125
126
127

128
129
130
131
132
133
134
117
118
119
120
121
122
123

124
125
126
127

128
129
130
131
132
133
134
135






-
+



-
+







	dputs "handshake: eof"
	set ::do_handshake "eof"
    } elseif {[catch {tls::handshake $s} result]} {
	# Some errors are normal.
	dputs "handshake: $result"
    } elseif {$result == 1} {
	# Handshake complete
	if {[llength $args]} { eval fconfigure $s $args }
	if {[llength $args]} { eval [list fconfigure $s] $args }
	if {$cmd == ""} {
	    fileevent $s $type ""
	} else {
	    fileevent $s $type "$cmd $s"
	    fileevent $s $type "$cmd [list $s]"
	}
	dputs "handshake: complete"
	set ::do_handshake "complete"
    } else {
	dputs "handshake: in progress"
    }
}
300
301
302
303
304
305
306

307

308
309
310
311
312
313
314
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316






+
-
+







    list [catch {tls::socket foo badport} msg] $msg
} {1 {expected integer but got "badport"}}

test tlsIO-2.1 {tcp connection} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	package require tls
	set timer [after 2000 "set x timed_out"]
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8828 \]"
    puts $f {
	proc accept {file addr port} {
	    global x
	    set x done
341
342
343
344
345
346
347

348
349
350
351
352
353
354
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357






+







    set port [expr $tlsServerPort + [pid]%1024]
}

test tlsIO-2.2 {tcp connection with client port specified} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
	set timer [after 2000 "set x done"]
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8829 \]"
    puts $f {
	proc accept {sock addr port} {
            global x
380
381
382
383
384
385
386

387
388
389
390
391
392
393
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397






+







    set x
} [list ready "hello $port"]

test tlsIO-2.3 {tcp connection with client interface specified} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
	set timer [after 2000 "set x done"]
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8830 \]"
    puts $f {
	proc accept {sock addr port} {
            global x
417
418
419
420
421
422
423

424
425
426
427
428
429
430
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435






+







    set x
} {ready {hello 127.0.0.1}}

test tlsIO-2.4 {tcp connection with server interface specified} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
	set timer [after 2000 "set x done"]
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey -myaddr [info hostname] 8831 \]"
    puts $f {
	proc accept {sock addr port} {
            global x
453
454
455
456
457
458
459

460
461
462
463
464
465
466
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472






+







    set x
} {ready hello}

test tlsIO-2.5 {tcp connection with redundant server port} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
	set timer [after 2000 "set x done"]
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8832 \]"
    puts $f {
	proc accept {sock addr port} {
            global x
499
500
501
502
503
504
505

506
507
508
509
510
511
512
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519






+







    set status
} ok

test tlsIO-2.7 {echo server, one line} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
	set timer [after 2000 "set x done"]
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8834 \]"
    puts $f {
	proc accept {s a p} {
            fileevent $s readable [list echo $s]
542
543
544
545
546
547
548

549
550
551
552
553
554
555
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563






+







    close $f
    list $x $y
} {{hello abcdefghijklmnop} done}

test tlsIO-2.8 {echo server, loop 50 times, single connection} {socket stdio} {
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8835 \]"
    puts $f {
	proc accept {s a p} {
            fileevent $s readable [list echo $s]
            fconfigure $s -buffering line
592
593
594
595
596
597
598
599





600
601
602
603
604
605
606
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618






-
+
+
+
+
+







    set x
} {done 50}

test tlsIO-2.9 {socket conflict} {socket stdio} {
    set s [tls::socket -server accept 8828]
    removeFile script
    set f [open script w]
    puts -nonewline $f {package require tls; tls::socket -server accept 8828}
    puts -nonewline $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
	tls::socket -server accept 8828
    }
    close $f
    set f [open "|[list $::tcltest::tcltest script]" r]
    gets $f
    after 100
    set x [list [catch {close $f} msg] [string range $msg 0 43]]
    close $s
    set x
676
677
678
679
680
681
682

683

684
685
686
687
688
689
690
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703






+
-
+







test tlsIO-2.12 {tcp connection; no certificates specified} \
	{socket stdio unixOnly} {
    # There is a debug assertion on Windows/SSL that causes a crash when the
    # certificate isn't specified.
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	package require tls
	set timer [after 2000 "set x timed_out"]
	set f [tls::socket -server accept 8828]
	proc accept {file addr port} {
	    global x
	    set x done
            close $file
	}
708
709
710
711
712
713
714

715

716
717
718
719
720
721
722
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736






+
-
+







    set x
} {ready done {}}

test tlsIO-3.1 {socket conflict} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	package require tls
    }
    puts $f "set f \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8828 \]"
    puts $f {
	puts ready
	gets stdin
	close $f
    }
732
733
734
735
736
737
738

739

740
741
742
743
744
745
746
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761






+
-
+







    set x
} {1 {couldn't open socket: address already in use}}

test tlsIO-3.2 {server with several clients} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	package require tls
	set t1 [after 30000 "set x timed_out"]
	set t2 [after 31000 "set x timed_out"]
	set t3 [after 32000 "set x timed_out"]
	set counter 0
    }
    puts $f "set s \[tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8828 \]"
    puts $f {
800
801
802
803
804
805
806

807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

823
824
825
826
827
828
829
830






+
-
+







} {ready done}

test tlsIO-4.1 {server with several clients} {socket stdio} {
    # have seen intermittent hangs on Windows
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	package require tls
	gets stdin
    }
    puts $f "set s \[tls::socket -certfile $clientCert -cafile $caCert -keyfile $clientKey 127.0.0.1 8828 \]"
    puts $f {
	fconfigure $s -buffering line
	for {set i 0} {$i < 100} {incr i} {
	    puts $s hello
907
908
909
910
911
912
913

914
915
916
917
918
919
920
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937






+







test tlsIO-6.1 {accept callback error} {socket stdio} {
    # There is a debug assertion on Windows/SSL that causes a crash when the
    # certificate isn't specified.
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	gets stdin
    }
    puts $f [list tls::socket -cafile $caCert 127.0.0.1 8848]
    close $f
    set f [open "|[list $::tcltest::tcltest script]" r+]
    proc bgerror args {
934
935
936
937
938
939
940

941
942
943
944
945
946
947
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965






+







    set x
} {{divide by zero}}

test tlsIO-7.1 {testing socket specific options} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
    }
    puts $f [list tls::socket -server accept \
	    -certfile $serverCert -cafile $caCert -keyfile $serverKey 8820]
    puts $f {
	proc accept args {
	    global x
967
968
969
970
971
972
973

974
975
976
977
978
979
980
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999






+







    lappend l [llength $p]
} {0 0 3}

test tlsIO-7.2 {testing socket specific options} {socket stdio} {
    removeFile script
    set f [open script w]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
	package require tls
    }
    puts $f "tls::socket -server accept -certfile $serverCert -cafile $caCert -keyfile $serverKey 8821"
    puts $f {
	proc accept args {
	    global x
	    set x done
999
1000
1001
1002
1003
1004
1005
1006

1007
1008


1009
1010


1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029


1030
1031
1032
1033
1034
1035
1036
1037
1038






-
+


+
+
-
-
+
+







    lappend l [string equal [lindex $p 2] 8821]
} {3 127.0.0.1 0}

test tlsIO-7.3 {testing socket specific options} {socket} {
    set s [tls::socket \
	-certfile $serverCert -cafile $caCert -keyfile $serverKey \
    	-server accept 8822]
    set l [fconfigure $s]
    set l [llength [fconfigure $s]]
    close $s
    update
    # A bug fixed in fconfigure for 8.3.4+ make this return 14 normally,
    # but 12 in older versions.
    llength $l
} 12
    expr {$l >= 12 && (($l % 2) == 0)}
} 1

# bug report #5812 fconfigure doesn't return value for '-sockname'

test tlsIO-7.4 {testing socket specific options} {socket} {
    set s [tls::socket \
	-certfile $serverCert -cafile $caCert -keyfile $serverKey \
    	-server accept 8823]
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1305






-
+







    set r
} done

test tlsIO-11.2 {client specifies its port} {socket doTestsWithRemoteServer} {
    if {[info exists port]} {
	incr port
    } else {
	set port [expr $tlsServerPort + [pid]%1024]
	set port [expr {$tlsServerPort + [pid]%1024}]
    }
    sendCertValues
    sendCommand {
	set socket9_2_test_server [tls::socket -server accept \
		-certfile $serverCert -cafile $caCert -keyfile $serverKey 8835]
	proc accept {s a p} {
	    tls::handshake $s
1690
1691
1692
1693
1694
1695
1696
























1697
1698
1699
1700
1701
1702
1703
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    fileevent $s readable "readit $s"
    set timer [after 10000 "set done timed_out"]
    vwait done
    after cancel $timer
    sendCommand {close $l}
    set count
} 65566

proc getdata {type file} {
    # Read handler on the accepted socket.
    global x
    global failed
    set status [catch {read $file} data]
    if {$status != 0} {
	set x "read failed, error was $data"
	catch { close $file }
    } elseif {[string compare {} $data]} {
    } elseif {[fblocked $file]} {
    } elseif {[eof $file]} {
	if {$failed} {
	    set x "$type socket was inherited"
	} else {
	    set x "$type socket was not inherited"
	}
	catch { close $file }
    } else {
	set x {impossible case}
	catch { close $file }
    }
    return
}

test tlsIO-12.1 {testing inheritance of server sockets} {socket exec} {
    makeFile {} script1
    makeFile {} script2

    # Script1 is just a 10 second delay.  If the server socket
    # is inherited, it will be held open for 10 seconds
1711
1712
1713
1714
1715
1716
1717


1718


1719
1720
1721
1722
1723
1724
1725
1756
1757
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1772
1773






+
+
-
+
+







    # Script2 creates the server socket, launches script1,
    # waits a second, and exits.  The server socket will now
    # be closed unless script1 inherited it.

    set f [open script2 w]
    puts $f [list set tclsh $::tcltest::tcltest]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    puts $f {package require tls}
	package require tls
    }
    puts $f "set f \[tls::socket -server accept \
	    -certfile $serverCert -cafile $caCert -keyfile $serverKey 8828\]"
    puts $f {
	proc accept { file addr port } {
	    close $file
	}
	exec $tclsh script1 &
1765
1766
1767
1768
1769
1770
1771


1772


1773
1774
1775
1776
1777
1778
1779
1813
1814
1815
1816
1817
1818
1819
1820
1821

1822
1823
1824
1825
1826
1827
1828
1829
1830






+
+
-
+
+







    # Script2 opens the client socket and writes to it.  It then
    # launches script1 and exits.  If the child process inherited the
    # client socket, the socket will still be open.

    set f [open script2 w]
    puts $f [list set tclsh $::tcltest::tcltest]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    puts $f {package require tls}
	package require tls
    }
    puts $f "set f \[tls::socket -certfile $clientCert -cafile $caCert \
	    -keyfile $clientKey 127.0.0.1 8829\]"
    puts $f {
	exec $tclsh script1 &
	puts $f testing
	flush $f
	after 1000 exit
1787
1788
1789
1790
1791
1792
1793
1794
1795


1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1838
1839
1840
1841
1842
1843
1844


1845
1846























1847
1848
1849
1850
1851
1852
1853






-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	    -certfile $serverCert -cafile $caCert -keyfile $serverKey \
	    -server accept 8829]
    proc accept { file host port } {
	# When the client connects, establish the read handler
	global server
	close $server
	fconfigure $file -blocking 0
	fileevent $file readable [list do_handshake $file readable getdata \
		-buffering line]
	fileevent $file readable [list do_handshake $file readable \
		[list getdata client] -buffering line]
	return
    }
    proc getdata { file } {
	# Read handler on the accepted socket.
	global x
	global failed
	set status [catch {read $file} data]
	if {$status != 0} {
	    set x {read failed, error was $data}
	    catch { close $file }
	} elseif {[string compare {} $data]} {
	} elseif {[fblocked $file]} {
	} elseif {[eof $file]} {
	    if {$failed} {
		set x {client socket was inherited}
	    } else {
		set x {client socket was not inherited}
	    }
	    catch { close $file }
	} else {
	    set x {impossible case}
	    catch { close $file }
	}
	return
    }

    # If the socket doesn't hit end-of-file in 5 seconds, the
    # script1 process must have inherited the client.

    set failed 0
1846
1847
1848
1849
1850
1851
1852


1853


1854
1855
1856
1857
1858
1859
1860
1874
1875
1876
1877
1878
1879
1880
1881
1882

1883
1884
1885
1886
1887
1888
1889
1890
1891






+
+
-
+
+







	after 10000 exit
	vwait forever
    }
    close $f

    set f [open script2 w]
    puts $f [list set tclsh $::tcltest::tcltest]
    puts $f {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    puts $f {package require tls}
	package require tls
    }
    puts $f "set f \[tls::socket -server accept \
	    -certfile $serverCert -cafile $caCert -keyfile $serverKey 8930\]"
    puts $f {
	proc accept { file host port } {
	    global tclsh
	    fconfigure $file -buffering line
	    puts $file {test data on socket}
1876
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925

1926
1927
1928
1929
1930
1931
1932
1907
1908
1909
1910
1911
1912
1913

1914
1915
1916
1917
1918
1919
1920
1921
























1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940






-
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











+







    set f [tls::socket \
	    -certfile $clientCert -cafile $caCert -keyfile $clientKey \
	    127.0.0.1 8930]
    fconfigure $f -buffering full -blocking 0
    # We need to put a byte into the read queue, otherwise the
    # TLS handshake doesn't finish
    puts $f a; flush $f
    fileevent $f readable [list getdata $f]
    fileevent $f readable [list getdata accepted $f]

    # If the socket is still open after 5 seconds, the script1 process
    # must have inherited the accepted socket.

    set failed 0
    after 5000 set failed 1

    proc getdata { file } {
	# Read handler on the client socket.
	global x
	global failed
	set status [catch {read $file} data]
	if {$status != 0} {
	    set x "read failed, error was $data"
	    catch { close $file }
	} elseif {[string compare {} $data]} {
	} elseif {[fblocked $file]} {
	} elseif {[eof $file]} {
	    if {$failed} {
		set x {accepted socket was inherited}
	    } else {
		set x {accepted socket was not inherited}
	    }
	    catch { close $file }
	} else {
	    set x {impossible case}
	    catch { close $file }
	}
	return
    }
    
    vwait x
    set x
} {accepted socket was not inherited}

test tlsIO-13.1 {Testing use of shared socket between two threads} \
	{socket testthread} {
    # HOBBS: never tested
    removeFile script
    threadReap

    makeFile {
	set auto_path [linsert $auto_path 0 [lindex [split $env(PATH) ";:"] 0]]
    	package require tls
	set f [tls::socket -server accept 8828]
	proc accept {s a p} {
            fileevent $s readable [list echo $s]
            fconfigure $s -buffering line
        }
	proc echo {s} {