diff options
Diffstat (limited to 'qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java')
-rw-r--r-- | qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java new file mode 100644 index 0000000000..365353e734 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java @@ -0,0 +1,456 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.framing.abstraction.ContentChunk; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.subscription.SubscriptionFactory; +import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; +import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.mina.common.ByteBuffer; + +import javax.management.JMException; + +import java.util.ArrayList; + +/** + * Test class to test AMQQueueMBean attribtues and operations + */ +public class AMQQueueMBeanTest extends InternalBrokerBaseCase +{ + private static long MESSAGE_SIZE = 1000; + private AMQQueueMBean _queueMBean; + private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE; + + public void testMessageCountTransient() throws Exception + { + int messageCount = 10; + sendMessages(messageCount, false); + assertTrue(_queueMBean.getMessageCount() == messageCount); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + long queueDepth = (messageCount * MESSAGE_SIZE); + assertTrue(_queueMBean.getQueueDepth() == queueDepth); + + _queueMBean.deleteMessageFromTop(); + assertTrue(_queueMBean.getMessageCount() == (messageCount - 1)); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + + _queueMBean.clearQueue(); + assertEquals(0,(int)_queueMBean.getMessageCount()); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + + //Ensure that the data has been removed from the Store + verifyBrokerState(); + } + + public void testMessageCountPersistent() throws Exception + { + int messageCount = 10; + sendMessages(messageCount, true); + assertEquals("", messageCount, _queueMBean.getMessageCount().intValue()); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + long queueDepth = (messageCount * MESSAGE_SIZE); + assertTrue(_queueMBean.getQueueDepth() == queueDepth); + + _queueMBean.deleteMessageFromTop(); + assertTrue(_queueMBean.getMessageCount() == (messageCount - 1)); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + + _queueMBean.clearQueue(); + assertTrue(_queueMBean.getMessageCount() == 0); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + + //Ensure that the data has been removed from the Store + verifyBrokerState(); + } + + public void testDeleteMessages() throws Exception + { + int messageCount = 10; + sendMessages(messageCount, true); + assertEquals("", messageCount, _queueMBean.getMessageCount().intValue()); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + long queueDepth = (messageCount * MESSAGE_SIZE); + assertTrue(_queueMBean.getQueueDepth() == queueDepth); + + //delete first message + _queueMBean.deleteMessages(1L,1L); + assertTrue(_queueMBean.getMessageCount() == (messageCount - 1)); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + try + { + _queueMBean.viewMessageContent(1L); + fail("Message should no longer be on the queue"); + } + catch(Exception e) + { + + } + + //delete last message, leaving 2nd to 9th + _queueMBean.deleteMessages(10L,10L); + assertTrue(_queueMBean.getMessageCount() == (messageCount - 2)); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + try + { + _queueMBean.viewMessageContent(10L); + fail("Message should no longer be on the queue"); + } + catch(Exception e) + { + + } + + //delete remaining messages, leaving none + _queueMBean.deleteMessages(2L,9L); + assertTrue(_queueMBean.getMessageCount() == (0)); + assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); + + //Ensure that the data has been removed from the Store + verifyBrokerState(); + } + + // todo: collect to a general testing class -duplicated from Systest/MessageReturntest + private void verifyBrokerState() + { + + TestableMemoryMessageStore store = (TestableMemoryMessageStore) getVirtualHost().getMessageStore(); + + // Unlike MessageReturnTest there is no need for a delay as there this thread does the clean up. + + assertEquals("Store should have no messages:" + store.getMessageCount(), 0, store.getMessageCount()); + } + + public void testConsumerCount() throws AMQException + { + + assertTrue(getQueue().getActiveConsumerCount() == 0); + assertTrue(_queueMBean.getActiveConsumerCount() == 0); + + + InternalTestProtocolSession protocolSession = new InternalTestProtocolSession(getVirtualHost()); + + AMQChannel channel = new AMQChannel(protocolSession, 1, getMessageStore()); + protocolSession.addChannel(channel); + + Subscription subscription = + SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager()); + + getQueue().registerSubscription(subscription, false); + assertEquals(1,(int)_queueMBean.getActiveConsumerCount()); + + + SubscriptionFactory subscriptionFactory = SUBSCRIPTION_FACTORY; + Subscription s1 = subscriptionFactory.createSubscription(channel.getChannelId(), + protocolSession, + new AMQShortString("S1"), + false, + null, + true, + channel.getCreditManager()); + + Subscription s2 = subscriptionFactory.createSubscription(channel.getChannelId(), + protocolSession, + new AMQShortString("S2"), + false, + null, + true, + channel.getCreditManager()); + getQueue().registerSubscription(s1,false); + getQueue().registerSubscription(s2,false); + assertTrue(_queueMBean.getActiveConsumerCount() == 3); + assertTrue(_queueMBean.getConsumerCount() == 3); + + s1.close(); + assertEquals(2, (int) _queueMBean.getActiveConsumerCount()); + assertTrue(_queueMBean.getConsumerCount() == 3); + } + + public void testGeneralProperties() throws Exception + { + long maxQueueDepth = 1000; // in bytes + _queueMBean.setMaximumMessageCount(50000l); + _queueMBean.setMaximumMessageSize(2000l); + _queueMBean.setMaximumQueueDepth(maxQueueDepth); + + assertEquals("Max MessageCount not set",50000,_queueMBean.getMaximumMessageCount().longValue()); + assertEquals("Max MessageSize not set",2000, _queueMBean.getMaximumMessageSize().longValue()); + assertEquals("Max QueueDepth not set",maxQueueDepth, _queueMBean.getMaximumQueueDepth().longValue()); + + assertEquals("Queue Name does not match", new AMQShortString(getName()), _queueMBean.getName()); + assertFalse("AutoDelete should not be set.",_queueMBean.isAutoDelete()); + assertFalse("Queue should not be durable.",_queueMBean.isDurable()); + + //set+get exclusivity using the mbean, and also verify it is actually updated in the queue + _queueMBean.setExclusive(true); + assertTrue("Exclusive property should be true.",_queueMBean.isExclusive()); + assertTrue("Exclusive property should be true.", getQueue().isExclusive()); + _queueMBean.setExclusive(false); + assertFalse("Exclusive property should be false.",_queueMBean.isExclusive()); + assertFalse("Exclusive property should be false.", getQueue().isExclusive()); + } + + public void testExceptions() throws Exception + { + try + { + _queueMBean.viewMessages(0L, 3L); + fail(); + } + catch (JMException ex) + { + + } + + try + { + _queueMBean.viewMessages(2L, 1L); + fail(); + } + catch (JMException ex) + { + + } + + try + { + _queueMBean.viewMessages(-1L, 1L); + fail(); + } + catch (JMException ex) + { + + } + + try + { + long end = Integer.MAX_VALUE; + end+=2; + _queueMBean.viewMessages(1L, end); + fail("Expected Exception due to oversized(> 2^31) message range"); + } + catch (JMException ex) + { + + } + + IncomingMessage msg = message(false, false); + getQueue().clearQueue(); + ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); + qs.add(getQueue()); + msg.enqueue(qs); + MessageMetaData mmd = msg.headersReceived(); + msg.setStoredMessage(getMessageStore().addMessage(mmd)); + long id = msg.getMessageNumber(); + + msg.addContentBodyFrame(new ContentChunk() + { + ByteBuffer _data = ByteBuffer.allocate((int)MESSAGE_SIZE); + + { + _data.limit((int)MESSAGE_SIZE); + } + + public int getSize() + { + return (int) MESSAGE_SIZE; + } + + public ByteBuffer getData() + { + return _data; + } + + public void reduceToFit() + { + + } + }); + + AMQMessage m = new AMQMessage(msg.getStoredMessage()); + for(BaseQueue q : msg.getDestinationQueues()) + { + q.enqueue(m); + } +// _queue.process(_storeContext, new QueueEntry(_queue, msg), false); + _queueMBean.viewMessageContent(id); + try + { + _queueMBean.viewMessageContent(id + 1); + fail(); + } + catch (JMException ex) + { + + } + } + + public void testFlowControlProperties() throws Exception + { + assertTrue(_queueMBean.getCapacity() == 0); + assertTrue(_queueMBean.getFlowResumeCapacity() == 0); + assertFalse(_queueMBean.isFlowOverfull()); + + //capacity currently 0, try setting FlowResumeCapacity above this + try + { + _queueMBean.setFlowResumeCapacity(1L); + fail("Should have failed to allow setting FlowResumeCapacity above Capacity"); + } + catch (IllegalArgumentException ex) + { + //expected exception + assertTrue(_queueMBean.getFlowResumeCapacity() == 0); + } + + //add a message to the queue + sendMessages(1, true); + + //(FlowResume)Capacity currently 0, set both to 2 + _queueMBean.setCapacity(2L); + assertTrue(_queueMBean.getCapacity() == 2L); + _queueMBean.setFlowResumeCapacity(2L); + assertTrue(_queueMBean.getFlowResumeCapacity() == 2L); + + //Try setting Capacity below FlowResumeCapacity + try + { + _queueMBean.setCapacity(1L); + fail("Should have failed to allow setting Capacity below FlowResumeCapacity"); + } + catch (IllegalArgumentException ex) + { + //expected exception + assertTrue(_queueMBean.getCapacity() == 2); + } + + //create a channel and use it to exercise the capacity check mechanism + AMQChannel channel = new AMQChannel(getSession(), 1, getMessageStore()); + getQueue().checkCapacity(channel); + + assertTrue(_queueMBean.isFlowOverfull()); + assertTrue(channel.getBlocking()); + + //set FlowResumeCapacity to MESSAGE_SIZE and check queue is now underfull and channel unblocked + _queueMBean.setCapacity(MESSAGE_SIZE);//must increase capacity too + _queueMBean.setFlowResumeCapacity(MESSAGE_SIZE); + + assertFalse(_queueMBean.isFlowOverfull()); + assertFalse(channel.getBlocking()); + } + + private IncomingMessage message(final boolean immediate, boolean persistent) throws AMQException + { + MessagePublishInfo publish = new MessagePublishInfo() + { + + public AMQShortString getExchange() + { + return null; + } + + public void setExchange(AMQShortString exchange) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isImmediate() + { + return immediate; + } + + public boolean isMandatory() + { + return false; + } + + public AMQShortString getRoutingKey() + { + return null; + } + }; + + ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); + contentHeaderBody.bodySize = MESSAGE_SIZE; // in bytes + contentHeaderBody.setProperties(new BasicContentHeaderProperties()); + ((BasicContentHeaderProperties) contentHeaderBody.getProperties()).setDeliveryMode((byte) (persistent ? 2 : 1)); + IncomingMessage msg = new IncomingMessage(publish); + msg.setContentHeaderBody(contentHeaderBody); + return msg; + + } + + @Override + public void setUp() throws Exception + { + super.setUp(); + + _queueMBean = new AMQQueueMBean(getQueue()); + } + + public void tearDown() + { + ApplicationRegistry.remove(); + } + + private void sendMessages(int messageCount, boolean persistent) throws AMQException + { + for (int i = 0; i < messageCount; i++) + { + IncomingMessage currentMessage = message(false, persistent); + ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); + qs.add(getQueue()); + currentMessage.enqueue(qs); + + // route header + MessageMetaData mmd = currentMessage.headersReceived(); + currentMessage.setStoredMessage(getMessageStore().addMessage(mmd)); + + // Add the body so we have somthing to test later + currentMessage.addContentBodyFrame( + getSession().getMethodRegistry() + .getProtocolVersionMethodConverter() + .convertToContentChunk( + new ContentBody(ByteBuffer.allocate((int) MESSAGE_SIZE), + MESSAGE_SIZE))); + + AMQMessage m = new AMQMessage(currentMessage.getStoredMessage()); + for(BaseQueue q : currentMessage.getDestinationQueues()) + { + q.enqueue(m); + } + + + } + } +} |