Commit e0c862f8 authored by Jim Fulton's avatar Jim Fulton

Improved the get_port function to address a race condition. This

requires passing a test object.

With this, it appears that I can run tests in parallel without getting
extra spurious errors.
parent 40954c7e
......@@ -165,7 +165,7 @@ class CommonSetupTearDown(StorageTestBase):
self.addr.append(self._getAddr())
def _getAddr(self):
return 'localhost', forker.get_port()
return 'localhost', forker.get_port(self)
def getConfig(self, path, create, read_only):
raise NotImplementedError
......
......@@ -23,6 +23,7 @@ import logging
import StringIO
import tempfile
import logging
import zope.testing.setupstack
logger = logging.getLogger('ZEO.tests.forker')
......@@ -203,7 +204,7 @@ def shutdown_zeo_server(adminaddr):
logger.debug('shutdown_zeo_server(): acked: %s' % ack)
s.close()
def get_port():
def get_port(test=None):
"""Return a port that is not in use.
Checks if a port is in use by trying to connect to it. Assumes it
......@@ -213,6 +214,10 @@ def get_port():
Raises RuntimeError after 10 tries.
"""
if test is not None:
return get_port2(test)
for i in range(10):
port = random.randrange(20000, 30000)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
......@@ -238,3 +243,37 @@ def get_port():
s.close()
s1.close()
raise RuntimeError("Can't find port")
def get_port2(test):
for i in range(10):
while 1:
port = random.randrange(20000, 30000)
if port%3 == 0:
break
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind(('localhost', port+2))
except socket.error, e:
if e[0] != errno.EADDRINUSE:
raise
continue
if not (can_connect(port) or can_connect(port+1)):
zope.testing.setupstack.register(test, s.close)
return port
s.close()
raise RuntimeError("Can't find port")
def can_connect(port):
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
c.connect(('localhost', port))
except socket.error:
return False # Perhaps we should check value of error too.
else:
c.close()
return True
......@@ -224,7 +224,7 @@ class GenericTests(
def setUp(self):
StorageTestBase.StorageTestBase.setUp(self)
logger.info("setUp() %s", self.id())
port = get_port()
port = get_port(self)
zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
zconf, port)
......@@ -310,7 +310,7 @@ class FileStorageRecoveryTests(StorageTestBase.StorageTestBase,
""" % tempfile.mktemp(dir='.')
def _new_storage(self):
port = get_port()
port = get_port(self)
zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
zconf, port)
......@@ -571,7 +571,7 @@ class DemoStorageWrappedAroundClientStorage(DemoStorageWrappedBase):
def _makeBaseStorage(self):
logger.info("setUp() %s", self.id())
port = get_port()
port = get_port(self)
zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
zconf, port)
......@@ -1091,28 +1091,40 @@ def tpc_finish_error():
connection closed
"""
test_classes = [FileStorageTests, FileStorageRecoveryTests,
MappingStorageTests, DemoStorageTests,
BlobAdaptedFileStorageTests, BlobWritableCacheTests,
ConfigurationTests,
]
slow_test_classes = [
BlobAdaptedFileStorageTests, BlobWritableCacheTests,
DemoStorageTests, FileStorageTests, MappingStorageTests,
]
quick_test_classes = [FileStorageRecoveryTests, ConfigurationTests]
def setUp(test):
ZODB.tests.util.setUp(test)
test.globs['get_port'] = lambda : get_port(test)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ZODB.tests.util.AAAA_Test_Runner_Hack))
suite.addTest(doctest.DocTestSuite(
setUp=zope.testing.setupstack.setUpDirectory,
tearDown=zope.testing.setupstack.tearDown))
suite.addTest(doctest.DocFileSuite(
'registerDB.test'
))
suite.addTest(
doctest.DocFileSuite('zeo-fan-out.test',
setUp=zope.testing.setupstack.setUpDirectory,
tearDown=zope.testing.setupstack.tearDown,
),
# Collect misc tests into their own layer to educe size of
# unit test layer
zeo = unittest.TestSuite()
zeo.addTest(unittest.makeSuite(ZODB.tests.util.AAAA_Test_Runner_Hack))
zeo.addTest(doctest.DocTestSuite(
setUp=setUp, tearDown=zope.testing.setupstack.tearDown))
zeo.addTest(doctest.DocFileSuite('registerDB.test'))
zeo.addTest(
doctest.DocFileSuite(
'zeo-fan-out.test',
setUp=setUp, tearDown=zope.testing.setupstack.tearDown,
),
)
for klass in test_classes:
for klass in quick_test_classes:
zeo.addTest(unittest.makeSuite(klass, "check"))
zeo.layer = ZODB.tests.util.MininalTestLayer('testZeo-misc')
suite.addTest(zeo)
# Put the heavyweights in their own layers
for klass in slow_test_classes:
sub = unittest.makeSuite(klass, "check")
sub.layer = ZODB.tests.util.MininalTestLayer(klass.__name__)
suite.addTest(sub)
......
......@@ -195,7 +195,8 @@ def main():
log(label, 'creating the test server, keep: %s', keep)
t = ZEOTestServer(test_addr, server, keep)
except socket.error, e:
if e[0] <> errno.EADDRINUSE: raise
if e[0] != errno.EADDRINUSE:
raise
log(label, 'addr in use, closing and exiting')
storage.close()
cleanup(storage)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment