Index: Lib/test/test_socket.py =================================================================== --- Lib/test/test_socket.py (revision 62182) +++ Lib/test/test_socket.py (working copy) @@ -15,8 +15,8 @@ from weakref import proxy import signal -PORT = 50007 -HOST = 'localhost' +PORT = None +HOST = None MSG = 'Michael Gilfix was here\n' class SocketTCPTest(unittest.TestCase): @@ -24,8 +24,8 @@ def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - global PORT - PORT = test_support.bind_port(self.serv, HOST, PORT) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(self.serv) self.serv.listen(1) def tearDown(self): @@ -37,8 +37,8 @@ def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - global PORT - PORT = test_support.bind_port(self.serv, HOST, PORT) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(self.serv) def tearDown(self): self.serv.close() @@ -461,16 +461,23 @@ # XXX The following don't test module-level functionality... def testSockName(self): - # Testing getsockname() + # Testing getsockname(). Use a temporary socket to elicit an unused + # ephemeral port that we can use later in the test. + tempsock = socket.socket() + tempsock.bind(("0.0.0.0", 0)) + (host, port) = tempsock.getsockname() + tempsock.close() + del tempsock + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.bind(("0.0.0.0", PORT+1)) + sock.bind(("0.0.0.0", port)) name = sock.getsockname() # XXX(nnorwitz): http://tinyurl.com/os5jz seems to indicate # it reasonable to get the host's addr in addition to 0.0.0.0. # At least for eCos. This is required for the S/390 to pass. my_ip_addr = socket.gethostbyname(socket.gethostname()) self.assert_(name[0] in ("0.0.0.0", my_ip_addr), '%s invalid' % name[0]) - self.assertEqual(name[1], PORT+1) + self.assertEqual(name[1], port) def testGetSockOpt(self): # Testing getsockopt() Index: Lib/test/test_httplib.py =================================================================== --- Lib/test/test_httplib.py (revision 62182) +++ Lib/test/test_httplib.py (working copy) @@ -196,16 +196,16 @@ def test_responses(self): self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found") -PORT = 50003 -HOST = "localhost" +PORT = None +HOST = None class TimeoutTest(TestCase): def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - global PORT - PORT = test_support.bind_port(self.serv, HOST, PORT) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(self.serv) self.serv.listen(5) def tearDown(self): Index: Lib/test/test_asynchat.py =================================================================== --- Lib/test/test_asynchat.py (revision 62182) +++ Lib/test/test_asynchat.py (working copy) @@ -6,8 +6,8 @@ import sys from test import test_support -HOST = "127.0.0.1" -PORT = 54322 +HOST = None +PORT = None SERVER_QUIT = 'QUIT\n' class echo_server(threading.Thread): @@ -22,8 +22,8 @@ def run(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - global PORT - PORT = test_support.bind_port(sock, HOST, PORT) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(sock) sock.listen(1) self.event.set() conn, client = sock.accept() Index: Lib/test/test_socket_ssl.py =================================================================== --- Lib/test/test_socket_ssl.py (revision 62182) +++ Lib/test/test_socket_ssl.py (working copy) @@ -20,6 +20,10 @@ # Optionally test SSL support, if we have it in the tested platform skip_expected = not hasattr(socket, "ssl") +HOST = None +PORT = None +SERVER_HOST = None +SERVER_PORT = None class ConnectedTests(unittest.TestCase): @@ -86,19 +90,17 @@ class BasicTests(unittest.TestCase): def testRudeShutdown(self): - # Some random port to connect to. - PORT = [9934] - listener_ready = threading.Event() listener_gone = threading.Event() - # `listener` runs in a thread. It opens a socket listening on - # PORT, and sits in an accept() until the main thread connects. - # Then it rudely closes the socket, and sets Event `listener_gone` - # to let the main thread know the socket is gone. + # `listener` runs in a thread. It opens a socket and sits in accept() + # until the main thread connects. Then it rudely closes the socket, + # and sets Event `listener_gone` to let the main thread know the socket + # is gone. def listener(): s = socket.socket() - PORT[0] = test_support.bind_port(s, '', PORT[0]) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(s) s.listen(5) listener_ready.set() s.accept() @@ -108,7 +110,7 @@ def connector(): listener_ready.wait() s = socket.socket() - s.connect(('localhost', PORT[0])) + s.connect((HOST, PORT)) listener_gone.wait() try: ssl_sock = socket.ssl(s) @@ -169,7 +171,7 @@ def testBasic(self): s = socket.socket() - s.connect(("localhost", 4433)) + s.connect((SERVER_HOST, SERVER_PORT)) ss = socket.ssl(s) ss.write("Foo\n") i = ss.read(4) @@ -183,7 +185,7 @@ info = "/C=PT/ST=Queensland/L=Lisboa/O=Neuronio, Lda./OU=Desenvolvimento/CN=brutus.neuronio.pt/emailAddress=sampo@iki.fi" s = socket.socket() - s.connect(("localhost", 4433)) + s.connect((SERVER_HOST, SERVER_PORT)) ss = socket.ssl(s) cert = ss.server() self.assertEqual(cert, info) @@ -210,8 +212,16 @@ if not os.access(key_file, os.F_OK): raise ValueError("No key file found! (tried %r)" % key_file) + # Obtain an unused host/port that we can pass to openssl. + tempsock = socket.socket() + global SERVER_HOST, SERVER_PORT + (SERVER_HOST, SERVER_PORT) = test_support.bind_port(tempsock) + tempsock.close() + del tempsock + try: - cmd = "openssl s_server -cert %s -key %s -quiet" % (cert_file, key_file) + args = (SERVER_PORT, cert_file, key_file) + cmd = "openssl s_server -accept %d -cert %s -key %s -quiet" % args self.s = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -222,7 +232,7 @@ # let's try if it is actually up try: s = socket.socket() - s.connect(("localhost", 4433)) + s.connect((SERVER_HOST, SERVER_PORT)) s.close() if self.s.stdout.readline() != "ERROR\n": raise ValueError Index: Lib/test/test_ftplib.py =================================================================== --- Lib/test/test_ftplib.py (revision 62182) +++ Lib/test/test_ftplib.py (working copy) @@ -6,18 +6,19 @@ from unittest import TestCase from test import test_support -server_port = None +HOST = None +PORT = None # This function sets the evt 3 times: # 1) when the connection is ready to be accepted. # 2) when it is safe for the caller to close the connection # 3) when we have closed the socket def server(evt): - global server_port serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serv.settimeout(3) serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - server_port = test_support.bind_port(serv, "", 9091) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(serv) serv.listen(5) # (1) Signal the caller that we are ready to accept the connection. evt.set() @@ -43,7 +44,7 @@ # Wait for the server to be ready. self.evt.wait() self.evt.clear() - ftplib.FTP.port = server_port + ftplib.FTP.port = PORT def tearDown(self): # Wait on the closing of the socket (this shouldn't be necessary). @@ -54,34 +55,34 @@ ftplib.FTP() # connects - ftp = ftplib.FTP("localhost") + ftp = ftplib.FTP(HOST) self.evt.wait() ftp.sock.close() def testTimeoutDefault(self): # default - ftp = ftplib.FTP("localhost") + ftp = ftplib.FTP(HOST) self.assertTrue(ftp.sock.gettimeout() is None) self.evt.wait() ftp.sock.close() def testTimeoutValue(self): # a value - ftp = ftplib.FTP("localhost", timeout=30) + ftp = ftplib.FTP(HOST, timeout=30) self.assertEqual(ftp.sock.gettimeout(), 30) self.evt.wait() ftp.sock.close() def testTimeoutConnect(self): ftp = ftplib.FTP() - ftp.connect("localhost", timeout=30) + ftp.connect(HOST, timeout=30) self.assertEqual(ftp.sock.gettimeout(), 30) self.evt.wait() ftp.sock.close() def testTimeoutDifferentOrder(self): ftp = ftplib.FTP(timeout=30) - ftp.connect("localhost") + ftp.connect(HOST) self.assertEqual(ftp.sock.gettimeout(), 30) self.evt.wait() ftp.sock.close() @@ -89,7 +90,7 @@ def testTimeoutDirectAccess(self): ftp = ftplib.FTP() ftp.timeout = 30 - ftp.connect("localhost") + ftp.connect(HOST) self.assertEqual(ftp.sock.gettimeout(), 30) self.evt.wait() ftp.sock.close() @@ -99,7 +100,7 @@ previous = socket.getdefaulttimeout() socket.setdefaulttimeout(30) try: - ftp = ftplib.FTP("localhost", timeout=None) + ftp = ftplib.FTP(HOST, timeout=None) finally: socket.setdefaulttimeout(previous) self.assertEqual(ftp.sock.gettimeout(), 30) Index: Lib/test/test_telnetlib.py =================================================================== --- Lib/test/test_telnetlib.py (revision 62182) +++ Lib/test/test_telnetlib.py (working copy) @@ -6,14 +6,15 @@ from unittest import TestCase from test import test_support -PORT = 9091 +HOST = None +PORT = None def server(evt): serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serv.settimeout(3) serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - global PORT - PORT = test_support.bind_port(serv, "", PORT) + global HOST, PORT + (HOST, PORT) = test_support.bind_port(serv) serv.listen(5) evt.set() try: @@ -38,24 +39,24 @@ def testBasic(self): # connects - telnet = telnetlib.Telnet("localhost", PORT) + telnet = telnetlib.Telnet(HOST, PORT) telnet.sock.close() def testTimeoutDefault(self): # default - telnet = telnetlib.Telnet("localhost", PORT) + telnet = telnetlib.Telnet(HOST, PORT) self.assertTrue(telnet.sock.gettimeout() is None) telnet.sock.close() def testTimeoutValue(self): # a value - telnet = telnetlib.Telnet("localhost", PORT, timeout=30) + telnet = telnetlib.Telnet(HOST, PORT, timeout=30) self.assertEqual(telnet.sock.gettimeout(), 30) telnet.sock.close() def testTimeoutDifferentOrder(self): telnet = telnetlib.Telnet(timeout=30) - telnet.open("localhost", PORT) + telnet.open(HOST, PORT) self.assertEqual(telnet.sock.gettimeout(), 30) telnet.sock.close() @@ -64,7 +65,7 @@ previous = socket.getdefaulttimeout() socket.setdefaulttimeout(30) try: - telnet = telnetlib.Telnet("localhost", PORT, timeout=None) + telnet = telnetlib.Telnet(HOST, PORT, timeout=None) finally: socket.setdefaulttimeout(previous) self.assertEqual(telnet.sock.gettimeout(), 30) Index: Lib/test/test_support.py =================================================================== --- Lib/test/test_support.py (revision 62182) +++ Lib/test/test_support.py (working copy) @@ -103,32 +103,24 @@ msg = "Use of the `%s' resource not enabled" % resource raise ResourceDenied(msg) -def bind_port(sock, host='', preferred_port=54321): - """Try to bind the sock to a port. If we are running multiple - tests and we don't try multiple ports, the test can fail. This - makes the test more robust.""" +def bind_port(sock): + """Bind the socket to a free port. Returns the results from getsockname() + after the socket has been bound, that is, a tuple containing the host and + port actually bound to. Relies on ephemeral ports in order to ensure we + are using an unbound port. This is important as many tests may be running + simultaneously, especially in a buildbot environment.""" - # Find some random ports that hopefully no one is listening on. - # Ideally each test would clean up after itself and not continue listening - # on any ports. However, this isn't the case. The last port (0) is - # a stop-gap that asks the O/S to assign a port. Whenever the warning - # message below is printed, the test that is listening on the port should - # be fixed to close the socket at the end of the test. - # Another reason why we can't use a port is another process (possibly - # another instance of the test suite) is using the same port. - for port in [preferred_port, 9907, 10243, 32999, 0]: - try: - sock.bind((host, port)) - if port == 0: - port = sock.getsockname()[1] - return port - except socket.error, (err, msg): - if err != errno.EADDRINUSE: - raise - print >>sys.__stderr__, \ - ' WARNING: failed to listen on port %d, trying another' % port - raise TestFailed('unable to find port to listen on') + # Use a temporary socket object to ensure we're not affected by any socket + # options that have already been set on the 'sock' object we're passed. + tempsock = socket.socket(sock.family, sock.type) + tempsock.bind(('127.0.0.1', 0)) + (host, port) = tempsock.getsockname() + tempsock.close() + del tempsock + sock.bind((host, port)) + return sock.getsockname() + FUZZ = 1e-6 def fcmp(x, y): # fuzzy comparison function