Fix the socket tests so they can be run concurrently. Backport candidate
This commit is contained in:
parent
b9845e72f9
commit
909eb12c95
|
@ -21,7 +21,8 @@ class SocketTCPTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
self.serv.bind((HOST, PORT))
|
global PORT
|
||||||
|
PORT = test_support.bind_port(self.serv, HOST, PORT)
|
||||||
self.serv.listen(1)
|
self.serv.listen(1)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
@ -33,7 +34,8 @@ class SocketUDPTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
self.serv.bind((HOST, PORT))
|
global PORT
|
||||||
|
PORT = test_support.bind_port(self.serv, HOST, PORT)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.serv.close()
|
self.serv.close()
|
||||||
|
|
|
@ -71,7 +71,7 @@ def test_rude_shutdown():
|
||||||
return
|
return
|
||||||
|
|
||||||
# Some random port to connect to.
|
# Some random port to connect to.
|
||||||
PORT = 9934
|
PORT = [9934]
|
||||||
|
|
||||||
listener_ready = threading.Event()
|
listener_ready = threading.Event()
|
||||||
listener_gone = threading.Event()
|
listener_gone = threading.Event()
|
||||||
|
@ -82,7 +82,7 @@ def test_rude_shutdown():
|
||||||
# know the socket is gone.
|
# know the socket is gone.
|
||||||
def listener():
|
def listener():
|
||||||
s = socket.socket()
|
s = socket.socket()
|
||||||
s.bind(('', PORT))
|
PORT[0] = test_support.bind_port(s, '', PORT[0])
|
||||||
s.listen(5)
|
s.listen(5)
|
||||||
listener_ready.set()
|
listener_ready.set()
|
||||||
s.accept()
|
s.accept()
|
||||||
|
@ -92,7 +92,7 @@ def test_rude_shutdown():
|
||||||
def connector():
|
def connector():
|
||||||
listener_ready.wait()
|
listener_ready.wait()
|
||||||
s = socket.socket()
|
s = socket.socket()
|
||||||
s.connect(('localhost', PORT))
|
s.connect(('localhost', PORT[0]))
|
||||||
listener_gone.wait()
|
listener_gone.wait()
|
||||||
try:
|
try:
|
||||||
ssl_sock = socket.ssl(s)
|
ssl_sock = socket.ssl(s)
|
||||||
|
|
|
@ -6,6 +6,7 @@ test_support.requires('network')
|
||||||
|
|
||||||
from SocketServer import *
|
from SocketServer import *
|
||||||
import socket
|
import socket
|
||||||
|
import errno
|
||||||
import select
|
import select
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
@ -77,6 +78,11 @@ class ServerThread(threading.Thread):
|
||||||
pass
|
pass
|
||||||
if verbose: print "thread: creating server"
|
if verbose: print "thread: creating server"
|
||||||
svr = svrcls(self.__addr, self.__hdlrcls)
|
svr = svrcls(self.__addr, self.__hdlrcls)
|
||||||
|
# pull the address out of the server in case it changed
|
||||||
|
# this can happen if another process is using the port
|
||||||
|
addr = getattr(svr, 'server_address')
|
||||||
|
if addr:
|
||||||
|
self.__addr = addr
|
||||||
if verbose: print "thread: serving three times"
|
if verbose: print "thread: serving three times"
|
||||||
svr.serve_a_few()
|
svr.serve_a_few()
|
||||||
if verbose: print "thread: done"
|
if verbose: print "thread: done"
|
||||||
|
@ -136,7 +142,25 @@ def testloop(proto, servers, hdlrcls, testfunc):
|
||||||
t.join()
|
t.join()
|
||||||
if verbose: print "done"
|
if verbose: print "done"
|
||||||
|
|
||||||
tcpservers = [TCPServer, ThreadingTCPServer]
|
class ForgivingTCPServer(TCPServer):
|
||||||
|
# prevent errors if another process is using the port we want
|
||||||
|
def server_bind(self):
|
||||||
|
host, default_port = self.server_address
|
||||||
|
# this code shamelessly stolen from test.test_support
|
||||||
|
# the ports were changed to protect the innocent
|
||||||
|
import sys
|
||||||
|
for port in [default_port, 3434, 8798, 23833]:
|
||||||
|
try:
|
||||||
|
self.server_address = host, port
|
||||||
|
TCPServer.server_bind(self)
|
||||||
|
break
|
||||||
|
except socket.error, (err, msg):
|
||||||
|
if err != errno.EADDRINUSE:
|
||||||
|
raise
|
||||||
|
print >>sys.__stderr__, \
|
||||||
|
' WARNING: failed to listen on port %d, trying another' % port
|
||||||
|
|
||||||
|
tcpservers = [ForgivingTCPServer, ThreadingTCPServer]
|
||||||
if hasattr(os, 'fork') and os.name not in ('os2',):
|
if hasattr(os, 'fork') and os.name not in ('os2',):
|
||||||
tcpservers.append(ForkingTCPServer)
|
tcpservers.append(ForkingTCPServer)
|
||||||
udpservers = [UDPServer, ThreadingUDPServer]
|
udpservers = [UDPServer, ThreadingUDPServer]
|
||||||
|
|
|
@ -89,6 +89,24 @@ def requires(resource, msg=None):
|
||||||
msg = "Use of the `%s' resource not enabled" % resource
|
msg = "Use of the `%s' resource not enabled" % resource
|
||||||
raise ResourceDenied(msg)
|
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 fails. This
|
||||||
|
makes the test more robust."""
|
||||||
|
|
||||||
|
import socket, errno
|
||||||
|
# some random ports that hopefully no one is listening on.
|
||||||
|
for port in [preferred_port, 9907, 10243, 32999]:
|
||||||
|
try:
|
||||||
|
sock.bind((host, port))
|
||||||
|
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'
|
||||||
|
|
||||||
FUZZ = 1e-6
|
FUZZ = 1e-6
|
||||||
|
|
||||||
def fcmp(x, y): # fuzzy comparison function
|
def fcmp(x, y): # fuzzy comparison function
|
||||||
|
|
|
@ -12,6 +12,8 @@ What's New in Python 2.5 beta 1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Fix the socket tests so they can be run concurrently.
|
||||||
|
|
||||||
- Removed 5 integers from C frame objects (PyFrameObject).
|
- Removed 5 integers from C frame objects (PyFrameObject).
|
||||||
f_nlocals, f_ncells, f_nfreevars, f_stack_size, f_restricted.
|
f_nlocals, f_ncells, f_nfreevars, f_stack_size, f_restricted.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue