// 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.functional; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; /** * 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 BindingLifecycle extends BindingLifecycleBase { /** * This tests that when you purge a queue, all of its messages go. */ @Test public void queuePurge() throws IOException { Binding binding = setupExchangeBindings(false); channel.basicPublish(binding.x, binding.k, null, payload); // Purge the queue, and test that we don't recieve a message channel.queuePurge(binding.q); GetResponse response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); deleteExchangeAndQueue(binding); } /** * See bug 21854: * "When Queue.Purge is called, sent-but-unacknowledged messages are no * longer purged, even if the channel they were sent down is not * (Tx-)transacted." */ @SuppressWarnings("deprecation") @Test public void unackedPurge() throws IOException { Binding binding = setupExchangeBindings(false); channel.basicPublish(binding.x, binding.k, null, payload); GetResponse response = channel.basicGet(binding.q, false); assertFalse(response.getEnvelope().isRedeliver()); assertNotNull("The response SHOULD NOT BE null", response); // If we purge the queue the unacked message should still be there on // recover. channel.queuePurge(binding.q); response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); channel.basicRecover(); response = channel.basicGet(binding.q, false); channel.basicRecover(); assertTrue(response.getEnvelope().isRedeliver()); assertNotNull("The response SHOULD NOT BE null", response); // If we recover then purge the message should go away channel.queuePurge(binding.q); response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); deleteExchangeAndQueue(binding); } /** * This tests whether when you delete an exchange, that any * bindings attached to it are deleted as well. */ @Test public void exchangeDelete() throws IOException { boolean durable = true; Binding binding = setupExchangeAndRouteMessage(true); // Nuke the exchange and repeat this test, this time you // expect nothing to get routed channel.exchangeDelete(binding.x); channel.exchangeDeclare(binding.x, "direct"); sendUnroutable(binding); channel.queueDelete(binding.q); } /** * This tests whether the server checks that an exchange is * actually being used when you try to delete it with the ifunused * flag. * * To test this, you try to delete an exchange with a queue still * bound to it and expect the delete operation to fail. */ @Test public void exchangeIfUnused() throws IOException { boolean durable = true; Binding binding = setupExchangeBindings(true); try { channel.exchangeDelete(binding.x, true); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); openChannel(); deleteExchangeAndQueue(binding); return; } fail("Exchange delete should have failed"); } /** * This tests whether the server checks that an auto_delete * exchange actually deletes the bindings attached to it when it * is deleted. * * To test this, you declare and auto_delete exchange and bind an * auto_delete queue to it. * * Start a consumer on this queue, send a message, let it get * consumed and then cancel the consumer * * The unsubscribe should cause the queue to auto_delete, which in * turn should cause the exchange to auto_delete. * * Then re-declare the queue again and try to rebind it to the same exhange. * * Because the exchange has been auto-deleted, the bind operation * should fail. */ @Test public void exchangeAutoDelete() throws IOException, TimeoutException { doAutoDelete(false, 1); } /** * Runs something similar to testExchangeAutoDelete, but adds * different queues with the same binding to the same exchange. * * The difference should be that the original exchange should not * get auto-deleted */ @Test public void exchangeAutoDeleteManyBindings() throws IOException, TimeoutException { doAutoDelete(false, 10); } /** * */ @Test public void exchangePassiveDeclare() throws IOException { channel.exchangeDeclare("testPassive", "direct"); channel.exchangeDeclarePassive("testPassive"); try { channel.exchangeDeclarePassive("unknown_exchange"); fail("Passive declare of an unknown exchange should fail"); } catch (IOException ioe) { checkShutdownSignal(AMQP.NOT_FOUND, ioe); } } /** * Test the behaviour of queue.unbind */ @Test public void unbind() throws Exception { for (String exchange: new String[]{"amq.fanout", "amq.direct", "amq.topic", "amq.headers"}) { testUnbind(exchange); } } public void testUnbind(String exchange) throws Exception { Binding b = new Binding(channel.queueDeclare().getQueue(), exchange, "quay"); // failure cases Binding[] tests = new Binding[] { new Binding("unknown_queue", b.x, b.k), new Binding(b.q, "unknown_exchange", b.k), new Binding("unknown_unknown", "exchange_queue", b.k), new Binding(b.q, b.x, "unknown_rk"), new Binding("unknown_queue", "unknown_exchange", "unknown_rk") }; for (int i = 0; i < tests.length; i++) { Binding test = tests[i]; // check we can unbind all sorts of things that don't exist channel.queueUnbind(test.q, test.x, test.k); } // success case channel.queueBind(b.q, b.x, b.k); sendRoutable(b); channel.queueUnbind(b.q, b.x, b.k); sendUnroutable(b); } }