예제 #1
0
    def test_init_ignore(self):
        closer = utils.SocketCloser('sock', ignore=[TestException])

        self.assertEqual(closer.sock, 'sock')
        self.assertEqual(closer.err_thresh, 0)
        self.assertEqual(closer.errors, None)
        self.assertEqual(closer.ignore, frozenset([TestException]))
예제 #2
0
    def test_init_err_thresh(self):
        closer = utils.SocketCloser('sock', 10)

        self.assertEqual(closer.sock, 'sock')
        self.assertEqual(closer.err_thresh, 10)
        self.assertEqual(closer.errors, 0)
        self.assertEqual(closer.ignore, frozenset())
예제 #3
0
    def test_together_noerror(self):
        sock = mock.Mock()

        with utils.SocketCloser(sock):
            sock.make_call()

        sock.make_call.assert_called_once_with()
        self.assertFalse(sock.close.called)
예제 #4
0
    def test_exit_closeerror(self):
        sock = mock.Mock(**{'close.side_effect': socket.error()})
        closer = utils.SocketCloser(sock)

        result = closer.__exit__(TestException, TestException('foo'), [])

        self.assertEqual(result, None)
        sock.close.assert_called_once_with()
        self.assertEqual(closer.errors, None)
예제 #5
0
    def test_exit_ignore(self):
        sock = mock.Mock()
        closer = utils.SocketCloser(sock, ignore=[TestException])

        result = closer.__exit__(TestException, TestException('foo'), [])

        self.assertEqual(result, True)
        self.assertFalse(sock.close.called)
        self.assertEqual(closer.errors, None)
예제 #6
0
    def test_exit_noerror(self):
        sock = mock.Mock()
        closer = utils.SocketCloser(sock)

        result = closer.__exit__(None, None, None)

        self.assertEqual(result, None)
        self.assertFalse(sock.close.called)
        self.assertEqual(closer.errors, None)
예제 #7
0
    def test_together_closeerror(self):
        sock = mock.Mock(**{'close.side_effect': socket.error()})

        with self.assertRaises(TestException):
            with utils.SocketCloser(sock):
                sock.make_call()
                raise TestException('spam')

        sock.make_call.assert_called_once_with()
        sock.close.assert_called_once_with()
예제 #8
0
    def test_together_kill(self):
        sock = mock.Mock()

        with self.assertRaises(gevent.GreenletExit):
            with utils.SocketCloser(sock):
                sock.make_call()
                raise gevent.GreenletExit()

        sock.make_call.assert_called_once_with()
        sock.close.assert_called_once_with()
예제 #9
0
    def test_exit_kill_thresh(self):
        sock = mock.Mock()
        closer = utils.SocketCloser(sock, 10)

        result = closer.__exit__(gevent.GreenletExit, gevent.GreenletExit(),
                                 [])

        self.assertEqual(result, None)
        sock.close.assert_called_once_with()
        self.assertEqual(closer.errors, 0)
예제 #10
0
    def connect(self, target, acceptor, wrapper=None):
        """
        Initiate a connection from the tendril manager's endpoint.
        Once the connection is completed, a TCPTendril object will be
        created and passed to the given acceptor.

        :param target: The target of the connection attempt.
        :param acceptor: A callable which will initialize the state of
                         the new TCPTendril object.
        :param wrapper: A callable taking, as its first argument, a
                        socket.socket object.  The callable must
                        return a valid proxy for the socket.socket
                        object, which will subsequently be used to
                        communicate on the connection.

        For passing extra arguments to the acceptor or the wrapper,
        see the ``TendrilPartial`` class; for chaining together
        multiple wrappers, see the ``WrapperChain`` class.
        """

        # Call some common sanity-checks
        super(TCPTendrilManager, self).connect(target, acceptor, wrapper)

        # Set up the socket
        sock = socket.socket(self.addr_family, socket.SOCK_STREAM)

        with utils.SocketCloser(sock, ignore=[application.RejectConnection]):
            # Bind to our endpoint
            sock.bind(self.endpoint)

            # Connect to our target
            sock.connect(target)

            # Call any wrappers
            if wrapper:
                sock = wrapper(sock)

            # Now, construct a Tendril
            tend = TCPTendril(self, sock)

            # Finally, set up the application
            tend.application = acceptor(tend)

            # OK, let's track the tendril
            self._track_tendril(tend)

            # Start the tendril
            tend._start()

            # Might as well return the tendril, too
            return tend

        # The acceptor raised a RejectConnection exception, apparently
        sock.close()
        return None
예제 #11
0
    def test_together_noerror_thresh(self):
        sock = mock.Mock()
        closer = utils.SocketCloser(sock, 10)
        closer.errors = 5

        with closer:
            sock.make_call()

        sock.make_call.assert_called_once_with()
        self.assertFalse(sock.close.called)
        self.assertEqual(closer.errors, 4)
예제 #12
0
    def test_together_kill_thresh(self):
        sock = mock.Mock()
        closer = utils.SocketCloser(sock, 10)

        with self.assertRaises(gevent.GreenletExit):
            with closer:
                sock.make_call()
                raise gevent.GreenletExit()

        sock.make_call.assert_called_once_with()
        sock.close.assert_called_once_with()
        self.assertEqual(closer.errors, 0)
예제 #13
0
    def test_exit_error_thresh(self):
        sock = mock.Mock()
        closer = utils.SocketCloser(sock, 1)

        result = closer.__exit__(TestException, TestException('foo'), [])

        self.assertEqual(result, True)
        self.assertFalse(sock.close.called)
        self.assertEqual(closer.errors, 1)

        result = closer.__exit__(TestException, TestException('foo'), [])

        self.assertEqual(result, None)
        sock.close.assert_called_once_with()
        self.assertEqual(closer.errors, 1)
예제 #14
0
    def test_together_closeerror_thresh(self):
        sock = mock.Mock(**{'close.side_effect': socket.error()})
        closer = utils.SocketCloser(sock, 1)

        with closer:
            sock.make_call()
            raise TestException('spam')

        sock.make_call.assert_called_once_with()
        self.assertFalse(sock.close.called)
        self.assertEqual(closer.errors, 1)

        sock.reset_mock()

        with self.assertRaises(TestException):
            with closer:
                sock.make_call()
                raise TestException('spam')

        sock.make_call.assert_called_once_with()
        sock.close.assert_called_once_with()
        self.assertEqual(closer.errors, 1)
예제 #15
0
    def listener(self, acceptor, wrapper):
        """
        Listens for new connections to the manager's endpoint.  Once a
        new connection is received, a TCPTendril object is generated
        for it and it is passed to the acceptor, which must initialize
        the state of the connection.  If no acceptor is given, no new
        connections can be initialized.

        :param acceptor: If given, specifies a callable that will be
                         called with each newly received TCPTendril;
                         that callable is responsible for initial
                         acceptance of the connection and for setting
                         up the initial state of the connection.  If
                         not given, no new connections will be
                         accepted by the TCPTendrilManager.
        :param wrapper: A callable taking, as its first argument, a
                        socket.socket object.  The callable must
                        return a valid proxy for the socket.socket
                        object, which will subsequently be used to
                        communicate on the connection.
        """

        # If we have no acceptor, there's nothing for us to do here
        if not acceptor:
            # Not listening on anything
            self.local_addr = None

            # Just sleep in a loop
            while True:
                gevent.sleep(600)
            return  # Pragma: nocover

        # OK, set up the socket
        sock = socket.socket(self.addr_family, socket.SOCK_STREAM)

        with utils.SocketCloser(sock):
            # Set up SO_REUSEADDR
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

            # Bind to our endpoint
            sock.bind(self.endpoint)

            # Get the assigned port number
            self.local_addr = sock.getsockname()

            # Call any wrappers
            if wrapper:
                sock = wrapper(sock)

            # Initiate listening
            sock.listen(self.backlog)

        # OK, now go into an accept loop with an error threshold of 10
        closer = utils.SocketCloser(sock,
                                    10,
                                    ignore=[application.RejectConnection])
        while True:
            with closer:
                cli, addr = sock.accept()

                # OK, the connection has been accepted; construct a
                # Tendril for it
                tend = TCPTendril(self, cli, addr)

                # Set up the application
                with utils.SocketCloser(cli):
                    tend.application = acceptor(tend)

                    # Make sure we track the new tendril, but only if
                    # the acceptor doesn't throw any exceptions
                    self._track_tendril(tend)

                    # Start the tendril
                    tend._start()
예제 #16
0
    def test_enter(self):
        closer = utils.SocketCloser('sock')
        result = closer.__enter__()

        self.assertEqual(closer, result)