示例#1
0
    def test_sync_checkpoint_timeout(self):
        """ Test a expected sync behavior with checkpoint_timeout param. """

        data_dir = tempfile.mkdtemp(prefix='coilmq-dbm-test')
        try:
            store = DbmQueue(data_dir, checkpoint_timeout=0.5)
            dest = '/queue/foo'

            frame = StompFrame('MESSAGE',
                               headers={'message-id': str(uuid.uuid4())},
                               body='some data -1')
            store.enqueue(dest, frame)

            time.sleep(0.5)

            frame = StompFrame('MESSAGE',
                               headers={'message-id': str(uuid.uuid4())},
                               body='some data -2')
            store.enqueue(dest, frame)

            print store.queue_metadata[dest]
            assert store.size(dest) == 2

            # No close()!

            store2 = DbmQueue(data_dir)
            print store2.queue_metadata[dest]
            assert store2.size(dest) == 2

        except:
            shutil.rmtree(data_dir, ignore_errors=True)
            raise
示例#2
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
示例#3
0
    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]
示例#4
0
    def test_dequeue_specific(self):
        """ Test that we only dequeue from the correct queue. """
        dest = '/queue/foo'
        notdest = '/queue/other'

        frame1 = StompFrame('MESSAGE',
                            headers={'message-id': str(uuid.uuid4())},
                            body='message-1')
        self.store.enqueue(dest, frame1)

        frame2 = StompFrame('MESSAGE',
                            headers={'message-id': str(uuid.uuid4())},
                            body='message-2')
        self.store.enqueue(notdest, frame2)

        frame3 = StompFrame('MESSAGE',
                            headers={'message-id': str(uuid.uuid4())},
                            body='message-3')
        self.store.enqueue(dest, frame3)

        assert self.store.has_frames(dest) == True
        assert self.store.size(dest) == 2

        rframe1 = self.store.dequeue(dest)
        assert frame1 == rframe1

        rframe2 = self.store.dequeue(dest)
        assert frame3 == rframe2

        assert self.store.has_frames(dest) == False
        assert self.store.size(dest) == 0
示例#5
0
    def test_dequeue_order(self):
        """ Test the order that frames are returned by dequeue() method. """
        dest = '/queue/foo'

        frame1 = StompFrame('MESSAGE',
                            headers={'message-id': str(uuid.uuid4())},
                            body='message-1')
        self.store.enqueue(dest, frame1)

        frame2 = StompFrame('MESSAGE',
                            headers={'message-id': str(uuid.uuid4())},
                            body='message-2')
        self.store.enqueue(dest, frame2)

        frame3 = StompFrame('MESSAGE',
                            headers={'message-id': str(uuid.uuid4())},
                            body='message-3')
        self.store.enqueue(dest, frame3)

        assert self.store.has_frames(dest) == True
        assert self.store.size(dest) == 3

        rframe1 = self.store.dequeue(dest)
        assert frame1 == rframe1

        rframe2 = self.store.dequeue(dest)
        assert frame2 == rframe2

        rframe3 = self.store.dequeue(dest)
        assert frame3 == rframe3

        assert self.store.has_frames(dest) == False
        assert self.store.size(dest) == 0
示例#6
0
 def test_dequeue_order(self):
     """ Test the order that frames are returned by dequeue() method. """
     dest = '/queue/foo'
     
     frame1 = StompFrame('MESSAGE', headers={'message-id': 'id-1'}, body='message-1') 
     self.store.enqueue(dest, frame1)
     
     frame2 = StompFrame('MESSAGE', headers={'message-id': 'id-2'}, body='message-2') 
     self.store.enqueue(dest, frame2)
     
     frame3 = StompFrame('MESSAGE', headers={'message-id': 'id-3'}, body='message-3') 
     self.store.enqueue(dest, frame3)
     
     assert self.store.has_frames(dest) == True
     assert self.store.size(dest) == 3
     
     # Perform some updates to change the expected order.
     
     sess = meta.Session()
     sess.execute(model.frames_table.update().where(model.frames_table.c.message_id=='id-1').values(queued=datetime.datetime(2010, 01, 01)))
     sess.execute(model.frames_table.update().where(model.frames_table.c.message_id=='id-2').values(queued=datetime.datetime(2009, 01, 01)))
     sess.execute(model.frames_table.update().where(model.frames_table.c.message_id=='id-3').values(queued=datetime.datetime(2004, 01, 01)))
     sess.commit()
     
     rframe1 = self.store.dequeue(dest)
     assert frame3 == rframe1
      
     rframe2 = self.store.dequeue(dest)
     assert frame2 == rframe2
     
     rframe3 = self.store.dequeue(dest)
     assert frame1 == rframe3
     
     assert self.store.has_frames(dest) == False
     assert self.store.size(dest) == 0
示例#7
0
 def test_subscribe_noack(self):
     """ Test subscribing to topics and queues w/ no ACK. """
     self._connect()
     self.engine.process_frame(StompFrame('SUBSCRIBE', headers={'destination': '/queue/bar'}))
     assert self.conn in self.qm.queues['/queue/bar']
     
     self.engine.process_frame(StompFrame('SUBSCRIBE', headers={'destination': '/foo/bar'}))
     assert self.conn in self.tm.topics['/foo/bar']
示例#8
0
 def test_connect_auth(self):
     """ Test the CONNECT command when auth is required. """
     self.engine.authenticator = self.auth
     
     assert self.engine.connected == False
     self.engine.process_frame(StompFrame('CONNECT'))
     self.assertErrorFrame(self.conn.frames[-1], 'Auth')
     assert self.engine.connected == False
     
     self.engine.process_frame(StompFrame('CONNECT', headers={'login': MockAuthenticator.LOGIN,
                                                             'passcode': MockAuthenticator.PASSCODE}))
     assert self.engine.connected == True
示例#9
0
    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." ""
示例#10
0
 def test_abort_invalid(self):
     """ Test invalid states for transaction ABORT. """
     self._connect()
      
     self.engine.process_frame(StompFrame('ABORT', headers={'transaction': 'abc'}))
     
     self.assertErrorFrame(self.conn.frames[-1], 'invalid transaction')
     
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': 'abc'}))
     self.engine.process_frame(StompFrame('ABORT', headers={'transaction': 'abc'}))
     
     self.engine.process_frame(StompFrame('ABORT', headers={'transaction': 'abc2'}))
     self.assertErrorFrame(self.conn.frames[-1], 'invalid transaction')
     
示例#11
0
 def test_send(self):
     """ Test sending to a topic and queue. """
     self._connect()
     
     msg = StompFrame('SEND', headers={'destination': '/queue/foo'}, body='QUEUEMSG-BODY')
     self.engine.process_frame(msg)        
     assert msg == self.qm.messages[-1]
     
     msg = StompFrame('SEND', headers={'destination': '/topic/foo'}, body='TOPICMSG-BODY')
     self.engine.process_frame(msg)
     assert msg == self.tm.messages[-1]
     
     msg = StompFrame('SEND', headers={}, body='TOPICMSG-BODY')
     self.engine.process_frame(msg)
     self.assertErrorFrame(self.conn.frames[-1], 'Missing destination')
示例#12
0
 def test_unsubscribe(self):
     """ Test the UNSUBSCRIBE command. """
     self._connect()
     self.engine.process_frame(StompFrame('SUBSCRIBE', headers={'destination': '/queue/bar'}))
     assert self.conn in self.qm.queues['/queue/bar']
     
     print self.conn.frames
     
     self.engine.process_frame(StompFrame('UNSUBSCRIBE', headers={'destination': '/queue/bar'}))
     assert self.conn not in self.qm.queues['/queue/bar']
     
     print self.conn.frames
     
     self.engine.process_frame(StompFrame('UNSUBSCRIBE', headers={'destination': '/invalid'}))
     print self.conn.frames[-1]
示例#13
0
 def test_subscribe_ack(self):
     """ Test subscribing to a queue with ack=true """
     self._connect()
     self.engine.process_frame(StompFrame('SUBSCRIBE', headers={'destination': '/queue/bar',
                                                               'ack': 'client'}))
     assert self.conn.reliable_subscriber == True
     assert self.conn in self.qm.queues['/queue/bar']
示例#14
0
 def test_begin(self):
     """ Test transaction BEGIN. """
     self._connect()
     
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': 'abc'}))
     assert 'abc' in self.engine.transactions
     assert len(self.engine.transactions['abc']) == 0
示例#15
0
    def test_sync_checkpoint_ops(self):
        """ Test a expected sync behavior with checkpoint_operations param. """

        data_dir = tempfile.mkdtemp(prefix='coilmq-dbm-test')
        max_ops = 5
        try:
            store = DbmQueue(data_dir, checkpoint_operations=max_ops)
            dest = '/queue/foo'

            for i in range(max_ops + 1):
                frame = StompFrame('MESSAGE',
                                   headers={'message-id': str(uuid.uuid4())},
                                   body='some data - %d' % i)
                store.enqueue(dest, frame)

            print store.queue_metadata[dest]
            assert store.size(dest) == max_ops + 1

            # No close()!

            store2 = DbmQueue(data_dir)
            print store2.queue_metadata[dest]
            assert store2.size(dest) == max_ops + 1

        except:
            shutil.rmtree(data_dir, ignore_errors=True)
            raise
示例#16
0
    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
示例#17
0
    def test_unsubscribe(self):
        """ Test unsubscribing a connection from the queue. """
        dest = '/topic/dest'

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

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

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

        assert len(self.conn.frames) == 1
示例#18
0
    def send_simple(self):
        """ Test a basic send command. """
        dest = '/topic/dest'

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

        # Assert some side-effects
        assert 'message-id' in f.headers
        assert f.cmd == 'MESSAGE'
示例#19
0
    def test_enqueue(self):
        """ Test the enqueue() method. """
        dest = '/queue/foo'
        frame = StompFrame('MESSAGE',
                           headers={'message-id': str(uuid.uuid4())},
                           body='some data')
        self.store.enqueue(dest, frame)

        assert self.store.has_frames(dest) == True
        assert self.store.size(dest) == 1
示例#20
0
    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
示例#21
0
    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'
示例#22
0
    def test_dequeue_identity(self):
        """ Test the dequeue() method. """
        dest = '/queue/foo'
        frame = StompFrame('MESSAGE',
                           headers={'message-id': str(uuid.uuid4())},
                           body='some data')
        self.store.enqueue(dest, frame)

        assert self.store.has_frames(dest) == True
        assert self.store.size(dest) == 1

        rframe = self.store.dequeue(dest)
        assert frame == rframe
        assert frame is not rframe

        assert self.store.has_frames(dest) == False
        assert self.store.size(dest) == 0
示例#23
0
    def test_dequeue(self):
        """ Test the dequeue() method. """
        dest = '/queue/foo'
        frame = StompFrame('MESSAGE',
                           headers={'message-id': str(uuid.uuid4())},
                           body='some data')
        self.store.enqueue(dest, frame)

        assert self.store.has_frames(dest) == True
        assert self.store.size(dest) == 1

        rframe = self.store.dequeue(dest)
        assert frame == rframe

        # We cannot generically assert whether or not frame and rframe are
        # the *same* object.

        assert self.store.has_frames(dest) == False
        assert self.store.size(dest) == 0
示例#24
0
    def test_sync_loss(self):
        """ Test metadata loss behavior. """

        data_dir = tempfile.mkdtemp(prefix='coilmq-dbm-test')
        try:
            store = DbmQueue(data_dir)
            dest = '/queue/foo'
            frame = StompFrame('MESSAGE',
                               headers={'message-id': str(uuid.uuid4())},
                               body='some data')
            store.enqueue(dest, frame)
            assert store.size(dest) == 1

            store2 = DbmQueue(data_dir)
            assert store2.size(dest) == 0

        except:
            shutil.rmtree(data_dir, ignore_errors=True)
            raise
示例#25
0
    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
示例#26
0
    def extract_message(self):
        """
        Pulls one complete frame off the buffer and returns it. 
        
        If there is no complete message in the buffer, returns None.

        Note that the buffer can contain more than once message. You
        should therefore call this method in a loop (or use iterator
        functionality exposed by class) until None returned.
        
        @return: The next complete frame in the buffer.
        @rtype: L{coilmq.frame.StompFrame}
        """
        (mbytes, hbytes) = self._find_message_bytes(self.buffer)
        if not mbytes:
            return None
        
        msgdata = self.buffer[:mbytes]
        self.buffer = self.buffer[mbytes:]
        hdata = msgdata[:hbytes]
        # Strip off any leading whitespace from headers; this is necessary, because
        # we do not (any longer) expect a trailing \n after the \x00 byte (which means
        # it will become a leading \n to the next frame).
        hdata = hdata.lstrip() 
        elems = hdata.split('\n')
        cmd = elems.pop(0)
        headers = {}
        
        for e in elems:
            try:
                (k,v) = e.split(':', 1) # header values may contain ':' so specify maxsplit
            except ValueError:
                continue
            headers[k.strip()] = v.strip()

        # hbytes points to the start of the '\n\n' at the end of the header,
        # so 2 bytes beyond this is the start of the body. The body EXCLUDES
        # the final byte, which is  '\x00'.
        body = msgdata[hbytes + 2:-1]
        return StompFrame(cmd, headers=headers, body=body)
示例#27
0
 def test_commit_invalid(self):
     """ Test invalid states for transaction COMMIT. """
     self._connect()
     
     # Send a message with invalid transaction 
     f = StompFrame('SEND', headers={'destination': '/dest', 'transaction': '123'}, body='ASDF')
     self.engine.process_frame(f)
     self.assertErrorFrame(self.conn.frames[-1], 'invalid transaction')
     
     # Attempt to commit invalid transaction
     self.engine.process_frame(StompFrame('COMMIT', headers={'transaction': 'abc'}))
     
     # Attempt to commit already-committed transaction
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': 'abc'}))
     self.engine.process_frame(StompFrame('SEND', headers={'destination': '/dest', 'transaction': 'abc'}, body='FOO'))
     self.engine.process_frame(StompFrame('COMMIT', headers={'transaction': 'abc'}))
     
     self.engine.process_frame(StompFrame('COMMIT', headers={'transaction': 'abc'}))
     self.assertErrorFrame(self.conn.frames[-1], 'invalid transaction')
示例#28
0
 def test_abort(self):
     """ Test transaction ABORT. """
     self._connect()
      
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': 'abc'}))
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': '123'}))
     
     f1 = StompFrame('SEND', headers={'destination': '/dest', 'transaction': 'abc'}, body='ASDF')
     self.engine.process_frame(f1)
     f2 = StompFrame('SEND', headers={'destination': '/dest', 'transaction': 'abc'}, body='ASDF')
     self.engine.process_frame(f2)
     f3 = StompFrame('SEND', headers={'destination': '/dest', 'transaction': '123'}, body='ASDF')
     self.engine.process_frame(f3)
     
     assert len(self.tm.messages) == 0
     
     self.engine.process_frame(StompFrame('ABORT', headers={'transaction': 'abc'}))
     assert len(self.tm.messages) == 0
     
     assert len(self.engine.transactions) == 1
示例#29
0
 def test_commit(self):
     """ Test transaction COMMIT. """
     self._connect()
      
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': 'abc'}))
     self.engine.process_frame(StompFrame('BEGIN', headers={'transaction': '123'}))
     self.engine.process_frame(StompFrame('SEND', headers={'destination': '/dest', 'transaction': 'abc'}, body='ASDF'))
     self.engine.process_frame(StompFrame('SEND', headers={'destination': '/dest', 'transaction': 'abc'}, body='ASDF'))
     self.engine.process_frame(StompFrame('SEND', headers={'destination': '/dest', 'transaction': '123'}, body='ASDF'))
     
     assert len(self.tm.messages) == 0
     
     self.engine.process_frame(StompFrame('COMMIT', headers={'transaction': 'abc'}))
     
     print self.conn.frames
     
     assert len(self.tm.messages) == 2
     
     assert len(self.engine.transactions) == 1
     
     self.engine.process_frame(StompFrame('COMMIT', headers={'transaction': '123'}))
     assert len(self.tm.messages) == 3
     
     assert len(self.engine.transactions) == 0
示例#30
0
 def disconnect(self):
     self.send_frame(StompFrame('DISCONNECT'))