[CalendarServer-changes] [8482] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jan 3 18:05:04 PST 2012
Revision: 8482
http://trac.macosforge.org/projects/calendarserver/changeset/8482
Author: glyph at apple.com
Date: 2012-01-03 18:05:03 -0800 (Tue, 03 Jan 2012)
Log Message:
-----------
Test (and fix) for the bug where getpeername() raises an exception due to the
connection already being closed.
Modified Paths:
--------------
CalendarServer/trunk/twext/internet/sendfdport.py
CalendarServer/trunk/twext/web2/metafd.py
Added Paths:
-----------
CalendarServer/trunk/twext/web2/test/test_metafd.py
Property Changed:
----------------
CalendarServer/trunk/
Modified: CalendarServer/trunk/twext/internet/sendfdport.py
===================================================================
--- CalendarServer/trunk/twext/internet/sendfdport.py 2012-01-03 23:24:11 UTC (rev 8481)
+++ CalendarServer/trunk/twext/internet/sendfdport.py 2012-01-04 02:05:03 UTC (rev 8482)
@@ -235,16 +235,16 @@
def __init__(self, fd, transportFactory, protocolFactory):
"""
@param fd: a file descriptor
-
@type fd: C{int}
-
- @param transportFactory: a 3-argument function that takes the socket
- object produced from the file descriptor, the (non-ancillary) data
- sent along with the incoming file descriptor, and the protocol
- built along with it, and returns an L{ITransport} provider. Note
- that this should NOT call C{makeConnection} on the protocol that it
- produces, as this class will do that.
+ @param transportFactory: a 4-argument function that takes the socket
+ object produced from the file descriptor, the peer address of that
+ socket, the (non-ancillary) data sent along with the incoming file
+ descriptor, and the protocol built along with it, and returns an
+ L{ITransport} provider. Note that this should NOT call
+ C{makeConnection} on the protocol that it produces, as this class
+ will do that.
+
@param protocolFactory: an L{IProtocolFactory}
"""
FileDescriptor.__init__(self)
@@ -283,7 +283,8 @@
except SocketError:
peeraddr = ('0.0.0.0', 0)
protocol = self.protocolFactory.buildProtocol(peeraddr)
- transport = self.transportFactory(skt, description, protocol)
+ transport = self.transportFactory(skt, peeraddr,
+ description, protocol)
protocol.makeConnection(transport)
except:
log.err()
@@ -312,4 +313,4 @@
"""
self.statusQueue.append(statusMessage)
self.startWriting()
-
+
Modified: CalendarServer/trunk/twext/web2/metafd.py
===================================================================
--- CalendarServer/trunk/twext/web2/metafd.py 2012-01-03 23:24:11 UTC (rev 8481)
+++ CalendarServer/trunk/twext/web2/metafd.py 2012-01-04 02:05:03 UTC (rev 8482)
@@ -1,4 +1,4 @@
-
+# -*- test-case-name: twext.web2.test.test_metafd -*-
##
# Copyright (c) 2010 Apple Inc. All rights reserved.
#
@@ -47,13 +47,11 @@
@ivar fd: the file descriptor of a UNIX socket being used to receive
connections from a master process calling accept()
-
@type fd: C{int}
@ivar contextFactory: A context factory for building SSL/TLS connections
for inbound connections tagged with the string 'SSL' as their
descriptive data, or None if SSL is not enabled for this server.
-
@type contextFactory: L{twisted.internet.ssl.ContextFactory} or C{NoneType}
"""
@@ -92,13 +90,12 @@
self.reportingFactory.inheritedPort.stopReading()
- def createTransport(self, skt, data, protocol):
+ def createTransport(self, skt, peer, data, protocol):
"""
Create a TCP transport, from a socket object passed by the parent.
"""
self._connectionCount += 1
- transport = Server(skt, protocol,
- skt.getpeername(), JustEnoughLikeAPort,
+ transport = Server(skt, protocol, peer, JustEnoughLikeAPort,
self._connectionCount, reactor)
if data == 'SSL':
transport.startTLS(self.contextFactory)
Added: CalendarServer/trunk/twext/web2/test/test_metafd.py
===================================================================
--- CalendarServer/trunk/twext/web2/test/test_metafd.py (rev 0)
+++ CalendarServer/trunk/twext/web2/test/test_metafd.py 2012-01-04 02:05:03 UTC (rev 8482)
@@ -0,0 +1,141 @@
+##
+# Copyright (c) 2011 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+
+"""
+Tests for twext.web2.metafd.
+"""
+
+from socket import error as SocketError
+from errno import ENOTCONN
+
+from twext.web2 import metafd
+from twext.web2.metafd import ReportingHTTPService
+from twext.web2.channel.http import HTTPChannel
+from twext.internet import sendfdport
+from twisted.internet.tcp import Server
+
+
+from twisted.trial.unittest import TestCase
+
+
+class FakeSocket(object):
+ """
+ A fake socket for testing.
+ """
+ def __init__(self, test):
+ self.test = test
+
+
+ def fileno(self):
+ return "not a socket"
+
+
+ def setblocking(self, blocking):
+ return
+
+
+ def getpeername(self):
+ if self.test.peerNameSucceed:
+ return ("4.3.2.1", 4321)
+ else:
+ raise SocketError(ENOTCONN, "Transport endpoint not connected")
+
+
+
+class InheritedPortForTesting(sendfdport.InheritedPort):
+ """
+ L{sendfdport.InheritedPort} subclass that prevents certain I/O operations
+ for better unit testing.
+ """
+
+ def startReading(self):
+ "Do nothing."
+
+
+ def stopReading(self):
+ "Do nothing."
+
+
+ def startWriting(self):
+ "Do nothing."
+
+
+ def stopWriting(self):
+ "Do nothing."
+
+
+
+class ServerTransportForTesting(Server):
+ """
+ tcp.Server replacement for testing purposes.
+ """
+
+ def startReading(self):
+ "Do nothing."
+
+ def stopReading(self):
+ "Do nothing."
+
+ def startWriting(self):
+ "Do nothing."
+
+ def stopWriting(self):
+ "Do nothing."
+
+ def __init__(self, *a, **kw):
+ super(ServerTransportForTesting, self).__init__(*a, **kw)
+ self.reactor = None
+
+
+
+class ReportingHTTPServiceTests(TestCase):
+ """
+ Tests for L{ReportingHTTPService}
+ """
+
+ peerNameSucceed = True
+
+ def setUp(self):
+ def fakefromfd(fd, addressFamily, socketType):
+ return FakeSocket(self)
+ def fakerecvfd(fd):
+ return "not an fd", "not a description"
+ def fakeclose(fd):
+ ""
+ self.patch(sendfdport, 'recvfd', fakerecvfd)
+ self.patch(sendfdport, 'fromfd', fakefromfd)
+ self.patch(sendfdport, 'close', fakeclose)
+ self.patch(metafd, 'InheritedPort', InheritedPortForTesting)
+ self.patch(metafd, 'Server', ServerTransportForTesting)
+ # This last stubbed out just to prevent dirty reactor warnings.
+ self.patch(HTTPChannel, "callLater", lambda *a, **k: None)
+ self.svc = ReportingHTTPService(None, None, None)
+ self.svc.startService()
+
+
+ def test_quickClosedSocket(self):
+ """
+ If a socket is closed very quickly after being {accept()}ed, requesting
+ its peer (or even host) address may fail with C{ENOTCONN}. If this
+ happens, its transport should be supplied with a dummy peer address.
+ """
+ self.peerNameSucceed = False
+ self.svc.reportingFactory.inheritedPort.doRead()
+ channels = self.svc.reportingFactory.connectedChannels
+ self.assertEqual(len(channels), 1)
+ self.assertEqual(list(channels)[0].transport.getPeer().host, "0.0.0.0")
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120103/edd4e3fb/attachment-0001.html>
More information about the calendarserver-changes
mailing list