def _queuemanager(self):
     """
 Returns the configured L{QueueManager} instance to use.
 Can be overridden by subclasses that wish to change out any queue mgr parameters.
 @rtype: L{QueueManager}
 """
     return QueueManager(
         store=MemoryQueue(),
         subscriber_scheduler=FavorReliableSubscriberScheduler(),
         queue_scheduler=RandomQueueScheduler())
예제 #2
0
def server_from_config(config=None, server_class=None, additional_kwargs=None):
    """
    Gets a configured L{coilmq.server.StompServer} from specified config.

    If `config` is None, global L{coilmq.config.config} var will be used instead.

    The `server_class` and `additional_kwargs` are primarily hooks for using this method
    from a testing environment.

    @param config: A C{ConfigParser.ConfigParser} instance with loaded config values.
    @type config: C{ConfigParser.ConfigParser}

    @param server_class: Which class to use for the server.  (This doesn't come from config currently.)
    @type server_class: C{class}

    @param additional_kwargs: Any additional args that should be passed to class.
    @type additional_kwargs: C{list}

    @return: The configured StompServer.
    @rtype: L{coilmq.server.StompServer}
    """
    global global_config
    if not config:
        config = global_config

    queue_store_factory = resolve_name(config.get('coilmq', 'qstore.factory'))
    subscriber_scheduler_factory = resolve_name(
        config.get('coilmq', 'scheduler.subscriber_priority_factory'))
    queue_scheduler_factory = resolve_name(
        config.get('coilmq', 'scheduler.queue_priority_factory'))

    if config.has_option('coilmq', 'auth.factory'):
        authenticator_factory = resolve_name(
            config.get('coilmq', 'auth.factory'))
        authenticator = authenticator_factory()
    else:
        authenticator = None

    server = ThreadedStompServer(
        (config.get('coilmq',
                    'listen_addr'), config.getint('coilmq', 'listen_port')),
        queue_manager=QueueManager(
            store=queue_store_factory(),
            subscriber_scheduler=subscriber_scheduler_factory(),
            queue_scheduler=queue_scheduler_factory()),
        topic_manager=TopicManager(),
        authenticator=authenticator,
        protocol=STOMP11)
    logger.info("Created server:%r" % server)
    return server
예제 #3
0
    def _queuemanager(self):
        """
        Returns the configured L{QueueManager} instance to use.
        """
        data_dir = os.path.join(os.getcwd(), 'data')
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
        configuration = {'qstore.sqlalchemy.url': 'sqlite:///data/coilmq.db'}
        engine = engine_from_config(configuration, 'qstore.sqlalchemy.')
        init_model(engine, drop=True)
        store = SAQueue()

        return QueueManager(store=store,
                            subscriber_scheduler=FavorReliableSubscriberScheduler(),
                            queue_scheduler=RandomQueueScheduler())
예제 #4
0
 def setUp(self):
     self.store = MemoryQueue()
     self.qm = QueueManager(self.store)
     self.conn = MockConnection()
예제 #5
0
class QueueManagerTest(unittest.TestCase):
    """ Test the QueueManager class. """
    def setUp(self):
        self.store = MemoryQueue()
        self.qm = QueueManager(self.store)
        self.conn = MockConnection()

    def test_subscribe(self):
        """ Test subscribing a connection to the queue. """
        dest = '/queue/dest'

        self.qm.subscribe(self.conn, dest)
        f = StompFrame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        print self.conn.frames
        assert len(self.conn.frames) == 1
        assert self.conn.frames[0] == f

    def test_unsubscribe(self):
        """ Test unsubscribing a connection from the queue. """
        dest = '/queue/dest'

        self.qm.subscribe(self.conn, dest)
        f = StompFrame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        print self.conn.frames
        assert len(self.conn.frames) == 1
        assert self.conn.frames[0] == f

        self.qm.unsubscribe(self.conn, dest)
        f = StompFrame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        assert len(self.conn.frames) == 1
        assert len(self.store.frames(dest)) == 1

    def send_simple(self):
        """ Test a basic send command. """
        dest = '/queue/dest'

        f = StompFrame('SEND', headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        assert len(self.store.frames(dest)) == 1

        # Assert some side-effects
        assert 'message-id' in f.headers
        assert f.cmd == 'MESSAGE'

    def test_send_err(self):
        """ Test sending a message when delivery results in error. """
        class ExcThrowingConn(object):
            reliable_subscriber = True

            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")

        dest = '/queue/dest'

        # This reliable subscriber will be chosen first
        conn = ExcThrowingConn()
        self.qm.subscribe(conn, dest)

        f = StompFrame('SEND', headers={'destination': dest}, body='Empty')
        try:
            self.qm.send(f)
            self.fail("Expected failure when there was an error sending.")
        except RuntimeError:
            pass

    def test_send_backlog_err_reliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        class ExcThrowingConn(object):
            reliable_subscriber = True

            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")

        dest = '/queue/dest'

        f = StompFrame('SEND', headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass

        # The message will have been requeued at this point, so add a valid
        # subscriber

        self.qm.subscribe(self.conn, dest)

        print "Frames: %r" % self.conn.frames

        assert len(self.conn.frames) == 1, "Expected frame to be delivered"
        assert self.conn.frames[0] == f

    def test_send_backlog_err_unreliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        class ExcThrowingConn(object):
            reliable_subscriber = False

            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")

        dest = '/queue/dest'

        f = StompFrame('SEND', headers={'destination': dest}, body='123')
        self.qm.send(f)

        f2 = StompFrame('SEND', headers={'destination': dest}, body='12345')
        self.qm.send(f2)

        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass

        # The message will have been requeued at this point, so add a valid
        # subscriber

        print "Queue state: %r" % (self.store._messages, )

        self.qm.subscribe(self.conn, dest)

        print "Frames: %r" % self.conn.frames

        assert len(self.conn.frames) == 2, "Expected frame to be delivered"
        assert self.conn.frames == [f2, f]

    def test_send_reliableFirst(self):
        """
        Test that messages are prioritized to reliable subscribers.
        
        This is actually a test of the underlying scheduler more than it is a test
        of the send message, per se.
        """

        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        conn2 = MockConnection()
        conn2.reliable_subscriber = False
        self.qm.subscribe(conn2, dest)

        f = StompFrame('MESSAGE',
                       headers={
                           'destination': dest,
                           'message-id': uuid.uuid4()
                       },
                       body='Empty')
        self.qm.send(f)

        print conn1.frames
        print conn2.frames
        assert len(conn1.frames) == 1
        assert len(conn2.frames) == 0

    def test_ack_basic(self):
        """ Test reliable client (ACK) behavior. """

        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        m1 = StompFrame('MESSAGE',
                        headers={'destination': dest},
                        body='Message body (1)')
        self.qm.send(m1)

        assert conn1.frames[0] == m1

        m2 = StompFrame('MESSAGE',
                        headers={'destination': dest},
                        body='Message body (2)')
        self.qm.send(m2)

        assert len(conn1.frames
                   ) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1

        ack = StompFrame('ACK',
                         headers={
                             'destination': dest,
                             'message-id': m1.message_id
                         })
        self.qm.ack(conn1, ack)

        print conn1.frames
        assert len(conn1.frames) == 2, "Expected 2 frames now, after ACK."
        assert conn1.frames[1] == m2

    def test_ack_transaction(self):
        """ Test the reliable client (ACK) behavior with transactions. """

        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        m1 = StompFrame('MESSAGE',
                        headers={
                            'destination': dest,
                        },
                        body='Message body (1)')
        self.qm.send(m1)

        assert conn1.frames[0] == m1

        m2 = StompFrame('MESSAGE',
                        headers={'destination': dest},
                        body='Message body (2)')
        self.qm.send(m2)

        assert len(conn1.frames
                   ) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1

        ack = StompFrame('ACK',
                         headers={
                             'destination': dest,
                             'transaction': 'abc',
                             'message-id': m1.message_id
                         })
        self.qm.ack(conn1, ack, transaction='abc')

        ack = StompFrame('ACK',
                         headers={
                             'destination': dest,
                             'transaction': 'abc',
                             'message-id': m2.message_id
                         })
        self.qm.ack(conn1, ack, transaction='abc')

        assert len(conn1.frames) == 2, "Expected 2 frames now, after ACK."
        assert conn1.frames[1] == m2

        self.qm.resend_transaction_frames(conn1, transaction='abc')

        assert len(conn1.frames) == 3, "Expected 3 frames after re-transmit."
        assert bool(self.qm._pending[conn1]
                    ) == True, "Expected 1 pending (waiting on ACK) frame." ""
예제 #6
0
 def setUp(self):
     self.store = MemoryQueue() 
     self.qm = QueueManager(self.store)
     self.conn = MockConnection()
예제 #7
0
class QueueManagerTest(unittest.TestCase):
    """ Test the QueueManager class. """
    
    def setUp(self):
        self.store = MemoryQueue() 
        self.qm = QueueManager(self.store)
        self.conn = MockConnection()
    
    def test_subscribe(self):
        """ Test subscribing a connection to the queue. """
        dest = '/queue/dest'
        
        self.qm.subscribe(self.conn, dest)
        f = StompFrame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        print self.conn.frames
        assert len(self.conn.frames) == 1
        assert self.conn.frames[0] == f
    
    def test_unsubscribe(self):
        """ Test unsubscribing a connection from the queue. """
        dest = '/queue/dest'
        
        self.qm.subscribe(self.conn, dest)
        f = StompFrame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        print self.conn.frames
        assert len(self.conn.frames) == 1
        assert self.conn.frames[0] == f
        
        self.qm.unsubscribe(self.conn, dest)
        f = StompFrame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        assert len(self.conn.frames) == 1
        assert len(self.store.frames(dest)) == 1
        
    def send_simple(self):
        """ Test a basic send command. """
        dest = '/queue/dest'
        
        f = StompFrame('SEND', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        assert len(self.store.frames(dest)) == 1
        
        # Assert some side-effects
        assert 'message-id' in f.headers
        assert f.cmd == 'MESSAGE'
        
    
    def test_send_err(self):
        """ Test sending a message when delivery results in error. """
        
        class ExcThrowingConn(object):
            reliable_subscriber = True
            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")
        
        dest = '/queue/dest'
        
        # This reliable subscriber will be chosen first
        conn = ExcThrowingConn()
        self.qm.subscribe(conn, dest)
        
        f = StompFrame('SEND', headers={'destination': dest}, body='Empty')
        try:
            self.qm.send(f)
            self.fail("Expected failure when there was an error sending.")
        except RuntimeError:
            pass
        
        
    def test_send_backlog_err_reliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        
        class ExcThrowingConn(object):
            reliable_subscriber = True
            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")
        
        dest = '/queue/dest'
        
        f = StompFrame('SEND', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass
        
        # The message will have been requeued at this point, so add a valid
        # subscriber
        
        self.qm.subscribe(self.conn, dest)
        
        print "Frames: %r" % self.conn.frames
        
        assert len(self.conn.frames) == 1, "Expected frame to be delivered"
        assert self.conn.frames[0] == f
        
    def test_send_backlog_err_unreliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        
        class ExcThrowingConn(object):
            reliable_subscriber = False
            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")
        
        dest = '/queue/dest'
        
        f = StompFrame('SEND', headers={'destination': dest}, body='123')
        self.qm.send(f)
        
        f2 = StompFrame('SEND', headers={'destination': dest}, body='12345')
        self.qm.send(f2)
        
        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass
        
        # The message will have been requeued at this point, so add a valid
        # subscriber
        
        print "Queue state: %r" % (self.store._messages,)
        
        self.qm.subscribe(self.conn, dest)
        
        print "Frames: %r" % self.conn.frames
        
        assert len(self.conn.frames) == 2, "Expected frame to be delivered"
        assert self.conn.frames == [f2,f]  
              
    def test_send_reliableFirst(self):
        """
        Test that messages are prioritized to reliable subscribers.
        
        This is actually a test of the underlying scheduler more than it is a test
        of the send message, per se.
        """
        
        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        conn2 = MockConnection()
        conn2.reliable_subscriber = False
        self.qm.subscribe(conn2, dest)
        
        f = StompFrame('MESSAGE', headers={'destination': dest, 'message-id': uuid.uuid4()}, body='Empty')
        self.qm.send(f)
            
        print conn1.frames
        print conn2.frames
        assert len(conn1.frames) == 1
        assert len(conn2.frames) == 0
    
    def test_ack_basic(self):
        """ Test reliable client (ACK) behavior. """
        
        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        m1 = StompFrame('MESSAGE', headers={'destination': dest}, body='Message body (1)')
        self.qm.send(m1)
        
        assert conn1.frames[0] == m1
        
        m2 = StompFrame('MESSAGE', headers={'destination': dest}, body='Message body (2)')
        self.qm.send(m2)
        
        assert len(conn1.frames) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1
        
        ack = StompFrame('ACK', headers={'destination': dest, 'message-id': m1.message_id})
        self.qm.ack(conn1, ack)
        
        print conn1.frames
        assert len(conn1.frames) == 2, "Expected 2 frames now, after ACK."
        assert conn1.frames[1] == m2
        
    def test_ack_transaction(self):
        """ Test the reliable client (ACK) behavior with transactions. """
                
        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        m1 = StompFrame('MESSAGE', headers={'destination': dest, }, body='Message body (1)')
        self.qm.send(m1)
        
        assert conn1.frames[0] == m1
        
        m2 = StompFrame('MESSAGE', headers={'destination': dest}, body='Message body (2)')
        self.qm.send(m2)
        
        assert len(conn1.frames) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1
        
        ack = StompFrame('ACK', headers={'destination': dest, 'transaction': 'abc', 'message-id': m1.message_id})
        self.qm.ack(conn1, ack, transaction='abc')
        
        ack = StompFrame('ACK', headers={'destination': dest, 'transaction': 'abc', 'message-id': m2.message_id})
        self.qm.ack(conn1, ack, transaction='abc')
        
        assert len(conn1.frames) == 2, "Expected 2 frames now, after ACK."
        assert conn1.frames[1] == m2
        
        self.qm.resend_transaction_frames(conn1, transaction='abc')
        
        assert len(conn1.frames) == 3, "Expected 3 frames after re-transmit."
        assert bool(self.qm._pending[conn1]) == True, "Expected 1 pending (waiting on ACK) frame.""" 
        
예제 #8
0
파일: test_queue.py 프로젝트: vallsv/coilmq
 def setUp(self):
     self.store = self._queuestore()
     self.qm = QueueManager(self.store)
     self.conn = MockConnection()
예제 #9
0
파일: test_queue.py 프로젝트: vallsv/coilmq
class QueueManagerTest(unittest.TestCase):
    """ Test the QueueManager class. """
    def _queuestore(self):
        """
        Returns the configured L{QueueStore} instance to use.

        Can be overridden by subclasses that wish to change out any queue store parameters.

        @rtype: L{QueueStore}
        """
        return MemoryQueue()

    def setUp(self):
        self.store = self._queuestore()
        self.qm = QueueManager(self.store)
        self.conn = MockConnection()

    def test_frames_iterator(self):
        dest = '/queue/dest'
        f = Frame(frames.SEND, headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        self.assertTrue(bool(self.store.frames(dest)))

    def test_subscribe(self):
        """ Test subscribing a connection to the queue. """
        dest = '/queue/dest'

        self.qm.subscribe(self.conn, dest)
        f = Frame(frames.MESSAGE, headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        self.assertEqual(len(self.conn.frames), 1)
        self.assertEqual(self.conn.frames[0], f)

    def test_unsubscribe(self):
        """ Test unsubscribing a connection from the queue. """
        dest = '/queue/dest'

        self.qm.subscribe(self.conn, dest)
        f = Frame(frames.MESSAGE, headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        self.assertEqual(len(self.conn.frames), 1)
        self.assertEqual(self.conn.frames[0], f)

        self.qm.unsubscribe(self.conn, dest)
        f = Frame(frames.MESSAGE, headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        self.assertEqual(len(self.conn.frames), 1)
        self.assertEqual(len(self.store.frames(dest)), 1)

    def send_simple(self):
        """ Test a basic send command. """
        dest = '/queue/dest'

        f = Frame(frames.SEND, headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        self.assertIn(dest, self.store.destinations())
        self.assertEqua(len(self.store.frames(dest)), 1)

        # Assert some side-effects
        self.assertIn('message-id', f.headers)
        self.assertEqual(f.command, frames.MESSAGE)

    def test_send_err(self):
        """ Test sending a message when delivery results in error. """
        class ExcThrowingConn(object):
            reliable_subscriber = True

            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")

        dest = '/queue/dest'

        # This reliable subscriber will be chosen first
        conn = ExcThrowingConn()
        self.qm.subscribe(conn, dest)

        f = Frame(frames.SEND, headers={'destination': dest}, body='Empty')
        try:
            self.qm.send(f)
            self.fail("Expected failure when there was an error sending.")
        except RuntimeError:
            pass

    def test_send_backlog_err_reliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        class ExcThrowingConn(object):
            reliable_subscriber = True

            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")

        dest = '/queue/send-backlog-err-reliable'

        f = Frame(frames.SEND, headers={'destination': dest}, body='Empty')
        self.qm.send(f)

        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass

        # The message will have been requeued at this point, so add a valid
        # subscriber

        self.qm.subscribe(self.conn, dest)

        self.assertEqual(len(self.conn.frames), 1,
                         "Expected frame to be delivered")
        self.assertEqual(self.conn.frames[0], f)

    def test_send_backlog_err_unreliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        class ExcThrowingConn(object):
            reliable_subscriber = False

            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")

        dest = '/queue/dest'

        f = Frame(frames.SEND, headers={'destination': dest}, body='123')
        self.qm.send(f)

        f2 = Frame(frames.SEND, headers={'destination': dest}, body='12345')
        self.qm.send(f2)

        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass

        # The message will have been requeued at this point, so add a valid
        # subscriber

        self.qm.subscribe(self.conn, dest)

        self.assertEqual(len(self.conn.frames), 2,
                         "Expected frame to be delivered")
        self.assertListEqual(list(self.conn.frames), [f2, f])

    def test_send_reliableFirst(self):
        """
        Test that messages are prioritized to reliable subscribers.

        This is actually a test of the underlying scheduler more than it is a test
        of the send message, per se.
        """

        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        conn2 = MockConnection()
        conn2.reliable_subscriber = False
        self.qm.subscribe(conn2, dest)

        f = Frame(frames.MESSAGE,
                  headers={
                      'destination': dest,
                      'message-id': uuid.uuid4()
                  },
                  body='Empty')
        self.qm.send(f)

        self.assertEqual(len(conn1.frames), 1)
        self.assertEqual(len(conn2.frames), 0)

    def test_clear_transaction_frames(self):
        """ Test the clearing of transaction ACK frames. """
        dest = '/queue/tx'

        f = Frame(frames.SEND,
                  headers={
                      'destination': dest,
                      'transaction': '1'
                  },
                  body='Body-A')
        self.qm.send(f)

        self.assertIn(dest, self.store.destinations())

        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        self.qm.subscribe(conn1, dest)

        self.assertEqual(len(conn1.frames), 1)

        self.qm.clear_transaction_frames(conn1, '1')

    def test_ack_basic(self):
        """ Test reliable client (ACK) behavior. """

        dest = '/queue/ack-basic'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        m1 = Frame(frames.MESSAGE,
                   headers={'destination': dest},
                   body='Message body (1)')
        self.qm.send(m1)

        self.assertEqual(conn1.frames[0], m1)

        m2 = Frame(frames.MESSAGE,
                   headers={'destination': dest},
                   body='Message body (2)')
        self.qm.send(m2)

        self.assertEqual(len(conn1.frames), 1)
        self.assertEqual(conn1.frames[0], m1)

        ack = Frame(frames.ACK,
                    headers={
                        'destination': dest,
                        'message-id': m1.headers['message-id']
                    })
        self.qm.ack(conn1, ack)

        self.assertEqual(len(conn1.frames), 2,
                         "Expected 2 frames now, after ACK.")
        self.assertEqual(conn1.frames[1], m2)

    def test_ack_transaction(self):
        """ Test the reliable client (ACK) behavior with transactions. """

        dest = '/queue/ack-transaction'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        m1 = Frame(frames.MESSAGE,
                   headers={
                       'destination': dest,
                   },
                   body='Message body (1)')
        self.qm.send(m1)

        assert conn1.frames[0] == m1

        m2 = Frame(frames.MESSAGE,
                   headers={'destination': dest},
                   body='Message body (2)')
        self.qm.send(m2)

        assert len(conn1.frames
                   ) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1

        ack = Frame(frames.ACK,
                    headers={
                        'destination': dest,
                        'transaction': 'abc',
                        'message-id': m1.headers.get('message-id')
                    })
        self.qm.ack(conn1, ack, transaction='abc')

        ack = Frame(frames.ACK,
                    headers={
                        'destination': dest,
                        'transaction': 'abc',
                        'message-id': m2.headers.get('message-id')
                    })
        self.qm.ack(conn1, ack, transaction='abc')

        self.assertEqual(len(conn1.frames), 2,
                         "Expected 2 frames now, after ACK.")
        self.assertEqual(conn1.frames[1], m2)

        self.qm.resend_transaction_frames(conn1, transaction='abc')

        self.assertEqual(len(conn1.frames), 3,
                         "Expected 3 frames after re-transmit.")
        self.assertTrue(self.qm._pending[conn1],
                        "Expected 1 pending (waiting on ACK) frame."
                        "")

    def test_disconnect_pending_frames(self):
        """ Test a queue disconnect when there are pending frames. """

        dest = '/queue/disconnect-pending-frames'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True

        self.qm.subscribe(conn1, dest)

        m1 = Frame(frames.MESSAGE,
                   headers={'destination': dest},
                   body='Message body (1)')
        self.qm.send(m1)

        self.assertEqual(conn1.frames[0], m1)

        self.qm.disconnect(conn1)

        # Now we need to ensure that the frame we sent is re-queued.
        self.assertEqual(len(self.store.frames(dest)), 1)
예제 #10
0
 def setUp(self):
     self.store = self._queuestore()
     self.qm = QueueManager(self.store)
     self.conn = MockConnection()
예제 #11
0
class QueueManagerTest(unittest.TestCase):
    """ Test the QueueManager class. """
    
    def _queuestore(self):
        """
        Returns the configured L{QueueStore} instance to use.
        
        Can be overridden by subclasses that wish to change out any queue store parameters.
        
        @rtype: L{QueueStore}
        """
        return MemoryQueue()
        
    def setUp(self):
        self.store = self._queuestore()
        self.qm = QueueManager(self.store)
        self.conn = MockConnection()
    
    def test_subscribe(self):
        """ Test subscribing a connection to the queue. """
        dest = '/queue/dest'
        
        self.qm.subscribe(self.conn, dest)
        f = Frame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        print self.conn.frames
        assert len(self.conn.frames) == 1
        assert self.conn.frames[0] == f
    
    def test_unsubscribe(self):
        """ Test unsubscribing a connection from the queue. """
        dest = '/queue/dest'
        
        self.qm.subscribe(self.conn, dest)
        f = Frame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        print self.conn.frames
        assert len(self.conn.frames) == 1
        assert self.conn.frames[0] == f
        
        self.qm.unsubscribe(self.conn, dest)
        f = Frame('MESSAGE', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        assert len(self.conn.frames) == 1
        assert len(self.store.frames(dest)) == 1
        
    def send_simple(self):
        """ Test a basic send command. """
        dest = '/queue/dest'
        
        f = Frame('SEND', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        assert dest in self.store.destinations()
        assert len(self.store.frames(dest)) == 1
        
        # Assert some side-effects
        assert 'message-id' in f.headers
        assert f.command == 'MESSAGE'
        
    
    def test_send_err(self):
        """ Test sending a message when delivery results in error. """
        
        class ExcThrowingConn(object):
            reliable_subscriber = True
            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")
        
        dest = '/queue/dest'
        
        # This reliable subscriber will be chosen first
        conn = ExcThrowingConn()
        self.qm.subscribe(conn, dest)
        
        f = Frame('SEND', headers={'destination': dest}, body='Empty')
        try:
            self.qm.send(f)
            self.fail("Expected failure when there was an error sending.")
        except RuntimeError:
            pass
        
        
    def test_send_backlog_err_reliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        
        class ExcThrowingConn(object):
            reliable_subscriber = True
            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")
        
        dest = '/queue/send-backlog-err-reliable'
        
        f = Frame('SEND', headers={'destination': dest}, body='Empty')
        self.qm.send(f)
        
        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass
        
        # The message will have been requeued at this point, so add a valid
        # subscriber
        
        self.qm.subscribe(self.conn, dest)
        
        print "Frames: %r" % self.conn.frames
        
        assert len(self.conn.frames) == 1, "Expected frame to be delivered"
        assert self.conn.frames[0] == f
        
    def test_send_backlog_err_unreliable(self):
        """ Test errors when sending backlog to reliable subscriber. """
        
        class ExcThrowingConn(object):
            reliable_subscriber = False
            def send_frame(self, frame):
                raise RuntimeError("Error sending data.")
        
        dest = '/queue/dest'
        
        f = Frame('SEND', headers={'destination': dest}, body='123')
        self.qm.send(f)
        
        f2 = Frame('SEND', headers={'destination': dest}, body='12345')
        self.qm.send(f2)
        
        conn = ExcThrowingConn()
        try:
            self.qm.subscribe(conn, dest)
            self.fail("Expected error when sending backlog.")
        except RuntimeError:
            pass
        
        # The message will have been requeued at this point, so add a valid
        # subscriber
        
        self.qm.subscribe(self.conn, dest)
        
        print "Frames: %r" % self.conn.frames
        
        assert len(self.conn.frames) == 2, "Expected frame to be delivered"
        assert self.conn.frames == [f2,f]  
              
    def test_send_reliableFirst(self):
        """
        Test that messages are prioritized to reliable subscribers.
        
        This is actually a test of the underlying scheduler more than it is a test
        of the send message, per se.
        """
        
        dest = '/queue/dest'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        conn2 = MockConnection()
        conn2.reliable_subscriber = False
        self.qm.subscribe(conn2, dest)
        
        f = Frame('MESSAGE', headers={'destination': dest, 'message-id': uuid.uuid4()}, body='Empty')
        self.qm.send(f)
            
        print conn1.frames
        print conn2.frames
        assert len(conn1.frames) == 1
        assert len(conn2.frames) == 0
    
    def test_clear_transaction_frames(self):
        """ Test the clearing of transaction ACK frames. """
        dest = '/queue/tx'
        
        f = Frame('SEND', headers={'destination': dest, 'transaction': '1'}, body='Body-A')
        self.qm.send(f)
        
        print self.store.destinations()
        assert dest in self.store.destinations()
        
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        self.qm.subscribe(conn1, dest)
        
        assert len(conn1.frames) == 1
        
        self.qm.clear_transaction_frames(conn1, '1')
        
    def test_ack_basic(self):
        """ Test reliable client (ACK) behavior. """
        
        dest = '/queue/ack-basic'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        m1 = Frame('MESSAGE', headers={'destination': dest}, body='Message body (1)')
        self.qm.send(m1)
        
        assert conn1.frames[0] == m1
        
        m2 = Frame('MESSAGE', headers={'destination': dest}, body='Message body (2)')
        self.qm.send(m2)
        
        assert len(conn1.frames) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1
        
        ack = Frame('ACK', headers={'destination': dest, 'message-id': m1.message_id})
        self.qm.ack(conn1, ack)
        
        print conn1.frames
        assert len(conn1.frames) == 2, "Expected 2 frames now, after ACK."
        assert conn1.frames[1] == m2
        
    def test_ack_transaction(self):
        """ Test the reliable client (ACK) behavior with transactions. """
                
        dest = '/queue/ack-transaction'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        m1 = Frame('MESSAGE', headers={'destination': dest, }, body='Message body (1)')
        self.qm.send(m1)
        
        assert conn1.frames[0] == m1
        
        m2 = Frame('MESSAGE', headers={'destination': dest}, body='Message body (2)')
        self.qm.send(m2)
        
        assert len(conn1.frames) == 1, "Expected connection to still only have 1 frame."
        assert conn1.frames[0] == m1
        
        ack = Frame('ACK', headers={'destination': dest, 'transaction': 'abc', 'message-id': m1.message_id})
        self.qm.ack(conn1, ack, transaction='abc')
        
        ack = Frame('ACK', headers={'destination': dest, 'transaction': 'abc', 'message-id': m2.message_id})
        self.qm.ack(conn1, ack, transaction='abc')
        
        assert len(conn1.frames) == 2, "Expected 2 frames now, after ACK."
        assert conn1.frames[1] == m2
        
        self.qm.resend_transaction_frames(conn1, transaction='abc')
        
        assert len(conn1.frames) == 3, "Expected 3 frames after re-transmit."
        assert bool(self.qm._pending[conn1]) == True, "Expected 1 pending (waiting on ACK) frame.""" 
    
    def test_disconnect_pending_frames(self):
        """ Test a queue disconnect when there are pending frames. """
        
        dest = '/queue/disconnect-pending-frames'
        conn1 = MockConnection()
        conn1.reliable_subscriber = True
        
        self.qm.subscribe(conn1, dest)
        
        m1 = Frame('MESSAGE', headers={'destination': dest}, body='Message body (1)')
        self.qm.send(m1)
        
        assert conn1.frames[0] == m1
        
        self.qm.disconnect(conn1)
        
        # Now we need to ensure that the frame we sent is re-queued.
        assert len(self.store.frames(dest)) == 1