Package com.rabbitmq.client.test.functional

Source Code of com.rabbitmq.client.test.functional.PerQueueTTL

//  The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (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.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
//  the License for the specific language governing rights and
//  limitations under the License.
//
//  The Original Code is RabbitMQ.
//
//  The Initial Developer of the Original Code is VMware, Inc.
//  Copyright (c) 2007-2012 VMware, Inc.  All rights reserved.
//


package com.rabbitmq.client.test.functional;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.GetResponse;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.QueueingConsumer.Delivery;
import com.rabbitmq.client.test.BrokerTestCase;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

/**
*
*/
public class PerQueueTTL extends BrokerTestCase {

    private static final String TTL_EXCHANGE           = "ttl.exchange";
    private static final String TTL_ARG                = "x-message-ttl";
    private static final String TTL_QUEUE_NAME         = "queue.ttl";
    private static final String TTL_INVALID_QUEUE_NAME = "invalid.queue.ttl";

    private static final String[] MSG = {"one", "two", "three"};

    @Override
    protected void createResources() throws IOException {
        this.channel.exchangeDeclare(TTL_EXCHANGE, "direct");
    }

    @Override
    protected void releaseResources() throws IOException {
        this.channel.exchangeDelete(TTL_EXCHANGE);
    }

    public void testCreateQueueTTLTypes() throws IOException {
        Object[] args = { (byte)200, (short)200, 200, 200L };
        for (Object ttl : args) {
            try {
                declareQueue(ttl);
            } catch(IOException ex) {
                fail("Should be able to use " + ttl.getClass().getName() +
                     " for x-message-ttl");
            }
        }
    }

    public void testTTLAllowZero() throws Exception {
        try {
            declareQueue(0);
        } catch (IOException e) {
            fail("Should be able to declare a queue with zero for x-message-ttl");
        }
    }

    public void testCreateQueueWithInvalidTTL() throws Exception {
        try {
            declareQueue(TTL_INVALID_QUEUE_NAME, "foobar");
            fail("Should not be able to declare a queue with a non-long value for x-message-ttl");
        } catch (IOException e) {
            checkShutdownSignal(AMQP.PRECONDITION_FAILED, e);
        }
    }

    public void testTTLMustBePositive() throws Exception {
        try {
            declareQueue(TTL_INVALID_QUEUE_NAME, -10);
            fail("Should not be able to declare a queue with negative value for x-message-ttl");
        } catch (IOException e) {
            checkShutdownSignal(AMQP.PRECONDITION_FAILED, e);
        }
    }

    public void testQueueRedeclareEquivalence() throws Exception {
        declareQueue(10);
        try {
            declareQueue(20);
            fail("Should not be able to redeclare with different x-message-ttl");
        } catch(IOException ex) {
            checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex);
        }
    }

    public void testQueueRedeclareSemanticEquivalence() throws Exception {
        declareQueue((byte)10);
        declareQueue(10);
        declareQueue((short)10);
        declareQueue(10L);
    }

    public void testQueueRedeclareSemanticNonEquivalence() throws Exception {
        declareQueue(10);
        try {
            declareQueue(10.0);
            fail("Should not be able to redeclare with x-message-ttl argument of different type");
        } catch(IOException ex) {
            checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex);
        }
    }

    /*
     * Test messages expire when using basic get.
     */
    public void testPublishAndGetWithExpiry() throws Exception {
        declareAndBindQueue(200);

        publish(MSG[0]);
        Thread.sleep(150);

        publish(MSG[1]);
        Thread.sleep(100);

        publish(MSG[2]);

        assertEquals(MSG[1], get());
        assertEquals(MSG[2], get());
    }

    /*
     * Test get expiry for messages sent under a transaction
     */
    public void testTransactionalPublishWithGet() throws Exception {
        declareAndBindQueue(100);

        this.channel.txSelect();

        publish(MSG[0]);
        Thread.sleep(150);

        publish(MSG[1]);
        this.channel.txCommit();
        Thread.sleep(50);

        assertEquals(MSG[0], get());
        Thread.sleep(80);

        assertNull(get());
    }

    /*
     * Test expiry of requeued messages
     */
    public void testExpiryWithRequeue() throws Exception {
        declareAndBindQueue(100);

        publish(MSG[0]);
        Thread.sleep(50);
        publish(MSG[1]);
        publish(MSG[2]);

        expectBodyAndRemainingMessages(MSG[0], 2);
        expectBodyAndRemainingMessages(MSG[1], 1);

        closeChannel();
        openChannel();

        Thread.sleep(60);
        expectBodyAndRemainingMessages(MSG[1], 1);
        expectBodyAndRemainingMessages(MSG[2], 0);
    }

    /*
     * Test expiry of requeued messages after being consumed instantly
     */
    public void testExpiryWithRequeueAfterConsume() throws Exception {
        declareAndBindQueue(100);
        QueueingConsumer c = new QueueingConsumer(channel);
        channel.basicConsume(TTL_QUEUE_NAME, c);

        publish(MSG[0]);
        assertNotNull(c.nextDelivery(100));

        closeChannel();
        Thread.sleep(150);
        openChannel();

        assertNull("Requeued message not expired", get());
    }

    public void testZeroTTLDelivery() throws Exception {
        declareAndBindQueue(0);

        // when there is no consumer, message should expire
        publish(MSG[0]);
        assertNull(get());

        // when there is a consumer, message should be delivered
        QueueingConsumer c = new QueueingConsumer(channel);
        channel.basicConsume(TTL_QUEUE_NAME, c);
        publish(MSG[0]);
        Delivery d = c.nextDelivery(100);
        assertNotNull(d);

        // requeued messages should expire
        channel.basicReject(d.getEnvelope().getDeliveryTag(), true);
        assertNull(c.nextDelivery(100));
    }

    private String get() throws IOException {
        GetResponse response = basicGet(TTL_QUEUE_NAME);
        return response == null ? null : new String(response.getBody());
    }

    private void publish(String msg) throws IOException {
        basicPublishVolatile(msg.getBytes(), TTL_EXCHANGE, TTL_QUEUE_NAME);
    }

    private void declareAndBindQueue(Object ttlValue) throws IOException {
        declareQueue(ttlValue);
        this.channel.queueBind(TTL_QUEUE_NAME, TTL_EXCHANGE, TTL_QUEUE_NAME);
    }

    private AMQP.Queue.DeclareOk declareQueue(Object ttlValue) throws IOException {
        return declareQueue(TTL_QUEUE_NAME, ttlValue);
    }

    private AMQP.Queue.DeclareOk declareQueue(String name, Object ttlValue) throws IOException {
        Map<String, Object> argMap = Collections.singletonMap(TTL_ARG, ttlValue);
        return this.channel.queueDeclare(name, false, true, false, argMap);
    }

    private void expectBodyAndRemainingMessages(String body, int messagesLeft) throws IOException {
        GetResponse response = channel.basicGet(TTL_QUEUE_NAME, false);
        assertEquals(body, new String(response.getBody()));
        assertEquals(messagesLeft,  response.getMessageCount());
    }

}
TOP

Related Classes of com.rabbitmq.client.test.functional.PerQueueTTL

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.