def test_sendFileDescriptorSorting(self): """ Make sure InheritedSocketDispatcher.sendFileDescriptor sorts sockets with status None higher than those with int status values. """ self.patch(_SubprocessSocket, 'sendSocketToPeer', lambda x, y, z:None) dispatcher = InheritedSocketDispatcher(ConnectionLimiter(2, 20)) dispatcher.addSocket() dispatcher.addSocket() dispatcher.addSocket() sockets = dispatcher._subprocessSockets[:] # Check that 0 is preferred over None sockets[0].status = 0 sockets[1].status = 1 sockets[2].status = None dispatcher.sendFileDescriptor(None, "") self.assertEqual(sockets[0].status, 1) self.assertEqual(sockets[1].status, 1) self.assertEqual(sockets[2].status, None) dispatcher.sendFileDescriptor(None, "") self.assertEqual(sockets[0].status, 1) self.assertEqual(sockets[1].status, 1) self.assertEqual(sockets[2].status, 1) # Check that after going to 1 and back to 0 that is still preferred over None sockets[0].status = 0 sockets[1].status = 1 sockets[2].status = None dispatcher.sendFileDescriptor(None, "") self.assertEqual(sockets[0].status, 1) self.assertEqual(sockets[1].status, 1) self.assertEqual(sockets[2].status, None) sockets[1].status = 0 dispatcher.sendFileDescriptor(None, "") self.assertEqual(sockets[0].status, 1) self.assertEqual(sockets[1].status, 1) self.assertEqual(sockets[2].status, None)
class InheritedSocketDispatcherTests(TestCase): """ Inherited socket dispatcher tests. """ def setUp(self): self.dispatcher = InheritedSocketDispatcher(ConnectionLimiter(2, 20)) self.dispatcher.reactor = ReaderAdder() def test_closeSomeSockets(self): """ L{InheritedSocketDispatcher} determines how many sockets to close from L{IStatusWatcher.closeCountFromStatus}. """ self.dispatcher.statusWatcher = Watcher([]) class SocketForClosing(object): blocking = True closed = False def setblocking(self, b): self.blocking = b def fileno(self): return object() def close(self): self.closed = True one = SocketForClosing() two = SocketForClosing() three = SocketForClosing() skt = self.dispatcher.addSocket( lambda: (SocketForClosing(), SocketForClosing())) skt.restarted() self.dispatcher.sendFileDescriptor(one, "one") self.dispatcher.sendFileDescriptor(two, "two") self.dispatcher.sendFileDescriptor(three, "three") def sendfd(unixSocket, tcpSocket, description): pass # Put something into the socket-close queue. self.dispatcher._subprocessSockets[0].doWrite(sendfd) # Nothing closed yet. self.assertEquals(one.closed, False) self.assertEquals(two.closed, False) self.assertEquals(three.closed, False) def recvmsg(fileno): return 'data', 0, 0 self.dispatcher._subprocessSockets[0].doRead(recvmsg) # One socket closed. self.assertEquals(one.closed, True) self.assertEquals(two.closed, False) self.assertEquals(three.closed, False) def test_nonBlocking(self): """ Creating a L{_SubprocessSocket} via L{InheritedSocketDispatcher.addSocket} results in a non-blocking L{socket.socket} object being assigned to its C{skt} attribute, as well as a non-blocking L{socket.socket} object being returned. """ dispatcher = self.dispatcher dispatcher.startDispatching() inputSocket = dispatcher.addSocket() outputSocket = self.dispatcher.reactor.readers[-1] self.assertTrue(isNonBlocking(inputSocket), "Input is blocking.") self.assertTrue(isNonBlocking(outputSocket), "Output is blocking.") def test_addAfterStart(self): """ Adding a socket to an L{InheritedSocketDispatcher} after it has already been started results in it immediately starting reading. """ dispatcher = self.dispatcher dispatcher.startDispatching() dispatcher.addSocket() self.assertEquals(dispatcher.reactor.getReaders(), dispatcher._subprocessSockets) def test_statusesChangedOnNewConnection(self): """ L{InheritedSocketDispatcher.sendFileDescriptor} will update its C{statusWatcher} via C{statusesChanged}. """ q = [] dispatcher = self.dispatcher dispatcher.statusWatcher = Watcher(q) description = "whatever" # Need to have a socket that will accept the descriptors. skt = dispatcher.addSocket() skt.restarted() dispatcher.sendFileDescriptor(object(), description) dispatcher.sendFileDescriptor(object(), description) self.assertEquals(q, [[(0, True)], [(1, True)], [(2, True)]]) def test_statusesChangedOnStatusMessage(self): """ L{InheritedSocketDispatcher.sendFileDescriptor} will update its C{statusWatcher} will update its C{statusWatcher} via C{statusesChanged}. """ q = [] dispatcher = self.dispatcher dispatcher.statusWatcher = Watcher(q) message = "whatever" # Need to have a socket that will accept the descriptors. dispatcher.addSocket() subskt = dispatcher._subprocessSockets[0] dispatcher.statusMessage(subskt, message) dispatcher.statusMessage(subskt, message) self.assertEquals(q, [[(-1, False)], [(-2, False)]]) def test_statusesChangedOnStartRestartStop(self): """ L{_SubprocessSocket} will update its C{status} when state change. """ q = [] dispatcher = self.dispatcher dispatcher.statusWatcher = Watcher(q) message = "whatever" # Need to have a socket that will accept the descriptors. subskt = dispatcher.addSocket() subskt.start() subskt.restarted() dispatcher.sendFileDescriptor(subskt, message) subskt.stop() subskt.start() subskt.restarted() self.assertEquals(q, [ [(0, False)], [(0, True)], [(1, True)], [(0, False)], [(0, False)], [(0, True)], ])
class InheritedSocketDispatcherTests(TestCase): """ Inherited socket dispatcher tests. """ def setUp(self): self.dispatcher = InheritedSocketDispatcher(ConnectionLimiter(2, 20)) self.dispatcher.reactor = ReaderAdder() def test_closeSomeSockets(self): """ L{InheritedSocketDispatcher} determines how many sockets to close from L{IStatusWatcher.closeCountFromStatus}. """ self.dispatcher.statusWatcher = Watcher([]) class SocketForClosing(object): blocking = True closed = False def setblocking(self, b): self.blocking = b def fileno(self): return object() def close(self): self.closed = True one = SocketForClosing() two = SocketForClosing() three = SocketForClosing() skt = self.dispatcher.addSocket( lambda: (SocketForClosing(), SocketForClosing()) ) skt.restarted() self.dispatcher.sendFileDescriptor(one, "one") self.dispatcher.sendFileDescriptor(two, "two") self.dispatcher.sendFileDescriptor(three, "three") def sendfd(unixSocket, tcpSocket, description): pass # Put something into the socket-close queue. self.dispatcher._subprocessSockets[0].doWrite(sendfd) # Nothing closed yet. self.assertEquals(one.closed, False) self.assertEquals(two.closed, False) self.assertEquals(three.closed, False) def recvmsg(fileno): return 'data', 0, 0 self.dispatcher._subprocessSockets[0].doRead(recvmsg) # One socket closed. self.assertEquals(one.closed, True) self.assertEquals(two.closed, False) self.assertEquals(three.closed, False) def test_nonBlocking(self): """ Creating a L{_SubprocessSocket} via L{InheritedSocketDispatcher.addSocket} results in a non-blocking L{socket.socket} object being assigned to its C{skt} attribute, as well as a non-blocking L{socket.socket} object being returned. """ dispatcher = self.dispatcher dispatcher.startDispatching() inputSocket = dispatcher.addSocket() outputSocket = self.dispatcher.reactor.readers[-1] self.assertTrue(isNonBlocking(inputSocket), "Input is blocking.") self.assertTrue(isNonBlocking(outputSocket), "Output is blocking.") def test_addAfterStart(self): """ Adding a socket to an L{InheritedSocketDispatcher} after it has already been started results in it immediately starting reading. """ dispatcher = self.dispatcher dispatcher.startDispatching() dispatcher.addSocket() self.assertEquals(dispatcher.reactor.getReaders(), dispatcher._subprocessSockets) def test_statusesChangedOnNewConnection(self): """ L{InheritedSocketDispatcher.sendFileDescriptor} will update its C{statusWatcher} via C{statusesChanged}. """ q = [] dispatcher = self.dispatcher dispatcher.statusWatcher = Watcher(q) description = "whatever" # Need to have a socket that will accept the descriptors. skt = dispatcher.addSocket() skt.restarted() dispatcher.sendFileDescriptor(object(), description) dispatcher.sendFileDescriptor(object(), description) self.assertEquals(q, [[(0, True)], [(1, True)], [(2, True)]]) def test_statusesChangedOnStatusMessage(self): """ L{InheritedSocketDispatcher.sendFileDescriptor} will update its C{statusWatcher} will update its C{statusWatcher} via C{statusesChanged}. """ q = [] dispatcher = self.dispatcher dispatcher.statusWatcher = Watcher(q) message = "whatever" # Need to have a socket that will accept the descriptors. dispatcher.addSocket() subskt = dispatcher._subprocessSockets[0] dispatcher.statusMessage(subskt, message) dispatcher.statusMessage(subskt, message) self.assertEquals(q, [[(-1, False)], [(-2, False)]]) def test_statusesChangedOnStartRestartStop(self): """ L{_SubprocessSocket} will update its C{status} when state change. """ q = [] dispatcher = self.dispatcher dispatcher.statusWatcher = Watcher(q) message = "whatever" # Need to have a socket that will accept the descriptors. subskt = dispatcher.addSocket() subskt.start() subskt.restarted() dispatcher.sendFileDescriptor(subskt, message) subskt.stop() subskt.start() subskt.restarted() self.assertEquals( q, [ [(0, False)], [(0, True)], [(1, True)], [(0, False)], [(0, False)], [(0, True)], ] )