[Checkins] SVN: zc.ngi/trunk/src/zc/ngi/ Fixed some bugs in
connector error handling.
Jim Fulton
jim at zope.com
Fri Sep 8 15:01:50 EDT 2006
Log message for revision 70076:
Fixed some bugs in connector error handling.
Changed:
U zc.ngi/trunk/src/zc/ngi/async.py
U zc.ngi/trunk/src/zc/ngi/testing.py
U zc.ngi/trunk/src/zc/ngi/tests.py
-=-
Modified: zc.ngi/trunk/src/zc/ngi/async.py
===================================================================
--- zc.ngi/trunk/src/zc/ngi/async.py 2006-09-08 19:01:47 UTC (rev 70075)
+++ zc.ngi/trunk/src/zc/ngi/async.py 2006-09-08 19:01:49 UTC (rev 70076)
@@ -169,7 +169,7 @@
self.__handler_lock.release()
def handle_expt(self):
- self.handle_close('expt')
+ self.handle_close('socket error')
class connector(dispatcher):
@@ -216,7 +216,7 @@
def writable(self):
return True
- def handle_close(reason):
+ def handle_close(self, reason=None):
if __debug__:
self.logger.debug('connector close %r', reason)
self.__handler.failed_connect(reason)
@@ -240,6 +240,15 @@
_Connection(self.socket, self.addr, self.logger))
return
+ def handle_error(self):
+ reason = sys.exc_info()[1]
+ self.logger.exception('connect error')
+ self.__handler.failed_connect(reason)
+ self.close()
+
+ def handle_expt(self):
+ self.handle_close('connection failed')
+
class listener(asyncore.dispatcher):
logger = logging.getLogger('zc.ngi.async.server')
Modified: zc.ngi/trunk/src/zc/ngi/testing.py
===================================================================
--- zc.ngi/trunk/src/zc/ngi/testing.py 2006-09-08 19:01:47 UTC (rev 70075)
+++ zc.ngi/trunk/src/zc/ngi/testing.py 2006-09-08 19:01:49 UTC (rev 70076)
@@ -147,3 +147,25 @@
else:
handler.connected(Connection(None, self.handler))
+# XXX This should move to zope.testing
+import random, socket
+def get_port():
+ """Return a port that is not in use.
+
+ Checks if a port is in use by trying to connect to it. Assumes it
+ is not in use if connect raises an exception.
+
+ Raises RuntimeError after 10 tries.
+ """
+ for i in range(10):
+ port = random.randrange(20000, 30000)
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ try:
+ s.connect(('localhost', port))
+ except socket.error:
+ # Perhaps we should check value of error too.
+ return port
+ finally:
+ s.close()
+ raise RuntimeError("Can't find port")
Modified: zc.ngi/trunk/src/zc/ngi/tests.py
===================================================================
--- zc.ngi/trunk/src/zc/ngi/tests.py 2006-09-08 19:01:47 UTC (rev 70075)
+++ zc.ngi/trunk/src/zc/ngi/tests.py 2006-09-08 19:01:49 UTC (rev 70076)
@@ -17,15 +17,49 @@
"""
import unittest
from zope.testing import doctest
+import zc.ngi.testing
import zc.ngi.async # start async thread before tests run
+def test_async_cannot_connect():
+ """Let's make sure that the connector handles connection failures correctly
+
+ >>> import threading
+ >>> lock = threading.Lock()
+ >>> _ = lock.acquire()
+
+ We define a simple handler that just notifies of failed connectioons.
+
+ >>> class Handler:
+ ... def failed_connect(connection, reason):
+ ... print 'failed', reason
+ ... lock.release()
+
+ >>> def connect(addr):
+ ... zc.ngi.async.connector(addr, Handler())
+ ... lock.acquire()
+
+ We find an unused port (so when we connect to it, the connection
+ will fail).
+
+ >>> port = zc.ngi.testing.get_port()
+
+ Now let's try to connect
+
+ >>> connect(('localhost', port))
+ failed connection failed
+
+ """
+
def test_suite():
- return doctest.DocFileSuite(
- 'README.txt',
- 'message.txt',
- 'async.txt',
- 'adapters.txt',
- )
+ return unittest.TestSuite([
+ doctest.DocFileSuite(
+ 'README.txt',
+ 'message.txt',
+ 'async.txt',
+ 'adapters.txt',
+ ),
+ doctest.DocTestSuite(),
+ ])
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
More information about the Checkins
mailing list