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): ...@@ -165,7 +165,7 @@ class CommonSetupTearDown(StorageTestBase):
self.addr.append(self._getAddr()) self.addr.append(self._getAddr())
def _getAddr(self): def _getAddr(self):
return 'localhost', forker.get_port() return 'localhost', forker.get_port(self)
def getConfig(self, path, create, read_only): def getConfig(self, path, create, read_only):
raise NotImplementedError raise NotImplementedError
......
...@@ -23,6 +23,7 @@ import logging ...@@ -23,6 +23,7 @@ import logging
import StringIO import StringIO
import tempfile import tempfile
import logging import logging
import zope.testing.setupstack
logger = logging.getLogger('ZEO.tests.forker') logger = logging.getLogger('ZEO.tests.forker')
...@@ -203,7 +204,7 @@ def shutdown_zeo_server(adminaddr): ...@@ -203,7 +204,7 @@ def shutdown_zeo_server(adminaddr):
logger.debug('shutdown_zeo_server(): acked: %s' % ack) logger.debug('shutdown_zeo_server(): acked: %s' % ack)
s.close() s.close()
def get_port(): def get_port(test=None):
"""Return a port that is not in use. """Return a port that is not in use.
Checks if a port is in use by trying to connect to it. Assumes it Checks if a port is in use by trying to connect to it. Assumes it
...@@ -213,6 +214,10 @@ def get_port(): ...@@ -213,6 +214,10 @@ def get_port():
Raises RuntimeError after 10 tries. Raises RuntimeError after 10 tries.
""" """
if test is not None:
return get_port2(test)
for i in range(10): for i in range(10):
port = random.randrange(20000, 30000) port = random.randrange(20000, 30000)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
...@@ -238,3 +243,37 @@ def get_port(): ...@@ -238,3 +243,37 @@ def get_port():
s.close() s.close()
s1.close() s1.close()
raise RuntimeError("Can't find port") 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( ...@@ -224,7 +224,7 @@ class GenericTests(
def setUp(self): def setUp(self):
StorageTestBase.StorageTestBase.setUp(self) StorageTestBase.StorageTestBase.setUp(self)
logger.info("setUp() %s", self.id()) logger.info("setUp() %s", self.id())
port = get_port() port = get_port(self)
zconf = forker.ZEOConfig(('', port)) zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(), zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
zconf, port) zconf, port)
...@@ -310,7 +310,7 @@ class FileStorageRecoveryTests(StorageTestBase.StorageTestBase, ...@@ -310,7 +310,7 @@ class FileStorageRecoveryTests(StorageTestBase.StorageTestBase,
""" % tempfile.mktemp(dir='.') """ % tempfile.mktemp(dir='.')
def _new_storage(self): def _new_storage(self):
port = get_port() port = get_port(self)
zconf = forker.ZEOConfig(('', port)) zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(), zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
zconf, port) zconf, port)
...@@ -571,7 +571,7 @@ class DemoStorageWrappedAroundClientStorage(DemoStorageWrappedBase): ...@@ -571,7 +571,7 @@ class DemoStorageWrappedAroundClientStorage(DemoStorageWrappedBase):
def _makeBaseStorage(self): def _makeBaseStorage(self):
logger.info("setUp() %s", self.id()) logger.info("setUp() %s", self.id())
port = get_port() port = get_port(self)
zconf = forker.ZEOConfig(('', port)) zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(), zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
zconf, port) zconf, port)
...@@ -1091,28 +1091,40 @@ def tpc_finish_error(): ...@@ -1091,28 +1091,40 @@ def tpc_finish_error():
connection closed connection closed
""" """
test_classes = [FileStorageTests, FileStorageRecoveryTests, slow_test_classes = [
MappingStorageTests, DemoStorageTests,
BlobAdaptedFileStorageTests, BlobWritableCacheTests, BlobAdaptedFileStorageTests, BlobWritableCacheTests,
ConfigurationTests, 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(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ZODB.tests.util.AAAA_Test_Runner_Hack))
suite.addTest(doctest.DocTestSuite( # Collect misc tests into their own layer to educe size of
setUp=zope.testing.setupstack.setUpDirectory, # unit test layer
tearDown=zope.testing.setupstack.tearDown)) zeo = unittest.TestSuite()
suite.addTest(doctest.DocFileSuite( zeo.addTest(unittest.makeSuite(ZODB.tests.util.AAAA_Test_Runner_Hack))
'registerDB.test' zeo.addTest(doctest.DocTestSuite(
)) setUp=setUp, tearDown=zope.testing.setupstack.tearDown))
suite.addTest( zeo.addTest(doctest.DocFileSuite('registerDB.test'))
doctest.DocFileSuite('zeo-fan-out.test', zeo.addTest(
setUp=zope.testing.setupstack.setUpDirectory, doctest.DocFileSuite(
tearDown=zope.testing.setupstack.tearDown, '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 = unittest.makeSuite(klass, "check")
sub.layer = ZODB.tests.util.MininalTestLayer(klass.__name__) sub.layer = ZODB.tests.util.MininalTestLayer(klass.__name__)
suite.addTest(sub) suite.addTest(sub)
......
...@@ -195,7 +195,8 @@ def main(): ...@@ -195,7 +195,8 @@ def main():
log(label, 'creating the test server, keep: %s', keep) log(label, 'creating the test server, keep: %s', keep)
t = ZEOTestServer(test_addr, server, keep) t = ZEOTestServer(test_addr, server, keep)
except socket.error, e: except socket.error, e:
if e[0] <> errno.EADDRINUSE: raise if e[0] != errno.EADDRINUSE:
raise
log(label, 'addr in use, closing and exiting') log(label, 'addr in use, closing and exiting')
storage.close() storage.close()
cleanup(storage) 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