// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.functional.BindingLifecycleBase; import com.rabbitmq.tools.Host; /** * This tests whether bindings are created and nuked properly. * * The tests attempt to declare durable queues on a secondary node, if * present, and that node is restarted as part of the tests while the * primary node is still running. That way we exercise any node-down * handler code in the server. * */ public class DurableBindingLifecycle extends BindingLifecycleBase { @Override protected void restart() throws IOException, TimeoutException { if (clusteredConnection != null) { clusteredConnection.abort(); clusteredConnection = null; clusteredChannel = null; alternateConnection = null; alternateChannel = null; Host.invokeMakeTarget( "stop-node" + " start-background-broker" + " RABBITMQ_NODENAME=\'" + Host.nodenameB() + "\'" + " RABBITMQ_NODE_PORT=" + Host.node_portB() + " RABBITMQ_CONFIG_FILE=\'" + Host.config_fileB() + "\'" ); } restartPrimary(); } private void restartPrimary() throws IOException, TimeoutException { tearDown(); bareRestart(); setUp(); } /** * Tests whether durable bindings are correctly recovered. */ @Test public void durableBindingRecovery() throws IOException, TimeoutException { declareDurableTopicExchange(X); declareAndBindDurableQueue(Q, X, K); restart(); for (int i = 0; i < N; i++) { basicPublishVolatile(X, K); } assertDelivered(Q, N); deleteQueue(Q); deleteExchange(X); } /** * This tests whether the bindings attached to a durable exchange * are correctly blown away when the exhange is nuked. * * This complements a unit test for testing non-durable exhanges. * In that case, an exchange is deleted and you expect any * bindings hanging to it to be deleted as well. To verify this, * the exchange is deleted and then recreated. * * After the recreation, the old bindings should no longer exist * and hence any messages published to that exchange get routed to * /dev/null * * This test exercises the durable variable of that test, so the * main difference is that the broker has to be restarted to * verify that the durable routes have been turfed. */ @Test public void durableBindingsDeletion() throws IOException, TimeoutException { declareDurableTopicExchange(X); declareAndBindDurableQueue(Q, X, K); deleteExchange(X); restart(); declareDurableTopicExchange(X); for (int i = 0; i < N; i++) { basicPublishVolatile(X, K); } GetResponse response = channel.basicGet(Q, true); assertNull("The initial response SHOULD BE null", response); deleteQueue(Q); deleteExchange(X); } /** * This tests whether the default bindings for durable queues * are recovered properly. * * The idea is to create a durable queue, nuke the server and then * publish a message to it using the queue name as a routing key */ @Test public void defaultBindingRecovery() throws IOException, TimeoutException { declareDurableQueue(Q); restart(); basicPublishVolatile("", Q); GetResponse response = channel.basicGet(Q, true); assertNotNull("The initial response SHOULD NOT be null", response); deleteQueue(Q); } /** * Test that when we have a transient exchange bound to a durable * queue and the durable queue is on a cluster node that restarts, * we do not lose the binding. See bug 24009. */ @Test public void transientExchangeDurableQueue() throws IOException, TimeoutException { // This test depends on the second node in the cluster to keep // the transient X alive if (clusteredConnection != null) { channel.exchangeDeclare("transientX", "fanout", false); channel.queueDeclare("durableQ", true, false, false, null); channel.queueBind("durableQ", "transientX", ""); restartPrimary(); basicPublishVolatile("transientX", ""); assertDelivered("durableQ", 1); deleteExchange("transientX"); deleteQueue("durableQ"); } } }