/*
* 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.activemq.artemis.tests.unit.core.server.impl;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.filter.impl.FilterImpl;
import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.core.server.Consumer;
import org.apache.activemq.artemis.core.server.HandleStatus;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.impl.QueueImpl;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.unit.core.server.impl.fakes.FakeConsumer;
import org.apache.activemq.artemis.tests.unit.core.server.impl.fakes.FakeFilter;
import org.apache.activemq.artemis.tests.unit.core.server.impl.fakes.FakePostOffice;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.FutureLatch;
import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class QueueImplTest extends ActiveMQTestBase {
// The tests ----------------------------------------------------------------
private ScheduledExecutorService scheduledExecutor;
private ExecutorService executor;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
scheduledExecutor = Executors.newSingleThreadScheduledExecutor(ActiveMQThreadFactory.defaultThreadFactory());
executor = Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory());
}
@Override
@After
public void tearDown() throws Exception {
scheduledExecutor.shutdownNow();
executor.shutdownNow();
super.tearDown();
}
private static final SimpleString queue1 = new SimpleString("queue1");
private static final SimpleString address1 = new SimpleString("address1");
@Test
public void testName() {
final SimpleString name = new SimpleString("oobblle");
QueueImpl queue = getNamedQueue(name);
Assert.assertEquals(name, queue.getName());
}
@Test
public void testDurable() {
QueueImpl queue = getNonDurableQueue();
Assert.assertFalse(queue.isDurable());
queue = getDurableQueue();
Assert.assertTrue(queue.isDurable());
}
@Test
public void testAddRemoveConsumer() throws Exception {
Consumer cons1 = new FakeConsumer();
Consumer cons2 = new FakeConsumer();
Consumer cons3 = new FakeConsumer();
QueueImpl queue = getTemporaryQueue();
Assert.assertEquals(0, queue.getConsumerCount());
queue.addConsumer(cons1);
Assert.assertEquals(1, queue.getConsumerCount());
queue.removeConsumer(cons1);
Assert.assertEquals(0, queue.getConsumerCount());
queue.addConsumer(cons1);
queue.addConsumer(cons2);
queue.addConsumer(cons3);
Assert.assertEquals(3, queue.getConsumerCount());
queue.removeConsumer(new FakeConsumer());
Assert.assertEquals(3, queue.getConsumerCount());
queue.removeConsumer(cons1);
Assert.assertEquals(2, queue.getConsumerCount());
queue.removeConsumer(cons2);
Assert.assertEquals(1, queue.getConsumerCount());
queue.removeConsumer(cons3);
Assert.assertEquals(0, queue.getConsumerCount());
queue.removeConsumer(cons3);
}
@Test
public void testGetFilter() {
QueueImpl queue = getTemporaryQueue();
Assert.assertNull(queue.getFilter());
Filter filter = new Filter() {
@Override
public boolean match(final Message message) {
return false;
}
@Override
public SimpleString getFilterString() {
return null;
}
};
queue = getFilteredQueue(filter);
Assert.assertEquals(filter, queue.getFilter());
}
@Test
public void testSimpleadd() {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
queue.addTail(ref);
}
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
}
@Test
public void testRate() throws InterruptedException {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
queue.addTail(ref);
}
Thread.sleep(1000);
float rate = queue.getRate();
Assert.assertTrue(rate <= 10.0f);
System.out.println("Rate: " + rate);
}
@Test
public void testSimpleNonDirectDelivery() throws Exception {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
// Now add a consumer
FakeConsumer consumer = new FakeConsumer();
queue.addConsumer(consumer);
Assert.assertTrue(consumer.getReferences().isEmpty());
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
queue.deliverNow();
assertRefListsIdenticalRefs(refs, consumer.getReferences());
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages, queue.getDeliveringCount());
}
@Test
public void testBusyConsumer() throws Exception {
QueueImpl queue = getTemporaryQueue();
FakeConsumer consumer = new FakeConsumer();
consumer.setStatusImmediate(HandleStatus.BUSY);
queue.addConsumer(consumer);
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
queue.deliverNow();
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
Assert.assertTrue(consumer.getReferences().isEmpty());
consumer.setStatusImmediate(HandleStatus.HANDLED);
queue.deliverNow();
assertRefListsIdenticalRefs(refs, consumer.getReferences());
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(10, queue.getDeliveringCount());
}
@Test
public void testBusyConsumerThenAddMoreMessages() throws Exception {
QueueImpl queue = getTemporaryQueue();
FakeConsumer consumer = new FakeConsumer();
consumer.setStatusImmediate(HandleStatus.BUSY);
queue.addConsumer(consumer);
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
queue.deliverNow();
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
Assert.assertTrue(consumer.getReferences().isEmpty());
for (int i = numMessages; i < numMessages * 2; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(20, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
Assert.assertTrue(consumer.getReferences().isEmpty());
consumer.setStatusImmediate(HandleStatus.HANDLED);
for (int i = numMessages * 2; i < numMessages * 3; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
assertRefListsIdenticalRefs(refs, consumer.getReferences());
Assert.assertEquals(30, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(30, queue.getDeliveringCount());
}
@Test
public void testaddHeadadd() throws Exception {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
List<MessageReference> refs1 = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs1.add(ref);
queue.addTail(ref);
}
LinkedList<MessageReference> refs2 = new LinkedList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i + numMessages);
refs2.addFirst(ref);
queue.addHead(ref, false);
}
List<MessageReference> refs3 = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i + 2 * numMessages);
refs3.add(ref);
queue.addTail(ref);
}
FakeConsumer consumer = new FakeConsumer();
queue.addConsumer(consumer);
queue.deliverNow();
List<MessageReference> allRefs = new ArrayList<>();
allRefs.addAll(refs2);
allRefs.addAll(refs1);
allRefs.addAll(refs3);
assertRefListsIdenticalRefs(allRefs, consumer.getReferences());
}
@Test
public void testChangeConsumersAndDeliver() throws Exception {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
FakeConsumer cons1 = new FakeConsumer();
queue.addConsumer(cons1);
queue.deliverNow();
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages, queue.getDeliveringCount());
assertRefListsIdenticalRefs(refs, cons1.getReferences());
FakeConsumer cons2 = new FakeConsumer();
queue.addConsumer(cons2);
Assert.assertEquals(2, queue.getConsumerCount());
cons1.getReferences().clear();
for (MessageReference ref : refs) {
queue.acknowledge(ref);
}
refs.clear();
for (int i = 0; i < 2 * numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
Assert.assertEquals(numMessages * 2, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages * 2, queue.getDeliveringCount());
Assert.assertEquals(numMessages, cons1.getReferences().size());
Assert.assertEquals(numMessages, cons2.getReferences().size());
cons1.getReferences().clear();
cons2.getReferences().clear();
for (MessageReference ref : refs) {
queue.acknowledge(ref);
}
refs.clear();
FakeConsumer cons3 = new FakeConsumer();
queue.addConsumer(cons3);
Assert.assertEquals(3, queue.getConsumerCount());
for (int i = 0; i < 3 * numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
Assert.assertEquals(numMessages * 3, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages * 3, queue.getDeliveringCount());
Assert.assertEquals(numMessages, cons1.getReferences().size());
Assert.assertEquals(numMessages, cons2.getReferences().size());
Assert.assertEquals(numMessages, cons3.getReferences().size());
queue.removeConsumer(cons1);
cons3.getReferences().clear();
cons2.getReferences().clear();
for (MessageReference ref : refs) {
queue.acknowledge(ref);
}
refs.clear();
for (int i = 0; i < 2 * numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
Assert.assertEquals(numMessages * 2, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages * 2, queue.getDeliveringCount());
Assert.assertEquals(numMessages, cons2.getReferences().size());
Assert.assertEquals(numMessages, cons3.getReferences().size());
queue.removeConsumer(cons3);
cons2.getReferences().clear();
for (MessageReference ref : refs) {
queue.acknowledge(ref);
}
refs.clear();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages, queue.getDeliveringCount());
Assert.assertEquals(numMessages, cons2.getReferences().size());
}
@Test
public void testRoundRobinWithQueueing() throws Exception {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
queue.pause();
// Test first with queueing
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
FakeConsumer cons1 = new FakeConsumer();
FakeConsumer cons2 = new FakeConsumer();
queue.addConsumer(cons1);
queue.addConsumer(cons2);
queue.resume();
// Need to make sure the consumers will receive the messages before we do these assertions
long timeout = System.currentTimeMillis() + 5000;
while (cons1.getReferences().size() != numMessages / 2 && timeout > System.currentTimeMillis()) {
Thread.sleep(1);
}
while (cons2.getReferences().size() != numMessages / 2 && timeout > System.currentTimeMillis()) {
Thread.sleep(1);
}
Assert.assertEquals(numMessages / 2, cons1.getReferences().size());
Assert.assertEquals(numMessages / 2, cons2.getReferences().size());
for (int i = 0; i < numMessages; i++) {
MessageReference ref;
ref = i % 2 == 0 ? cons1.getReferences().get(i / 2) : cons2.getReferences().get(i / 2);
Assert.assertEquals(refs.get(i), ref);
}
}
@Test
public void testWithPriorities() throws Exception {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
ref.getMessage().setPriority((byte) i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
FakeConsumer consumer = new FakeConsumer();
queue.addConsumer(consumer);
queue.deliverNow();
List<MessageReference> receivedRefs = consumer.getReferences();
// Should be in reverse order
Assert.assertEquals(refs.size(), receivedRefs.size());
for (int i = 0; i < numMessages; i++) {
Assert.assertEquals(refs.get(i), receivedRefs.get(9 - i));
}
}
@Test
public void testConsumerWithFiltersDirect() throws Exception {
testConsumerWithFilters(true);
}
@Test
public void testConsumerWithFiltersQueueing() throws Exception {
testConsumerWithFilters(false);
}
@Test
public void testConsumerWithFilterAddAndRemove() {
QueueImpl queue = getTemporaryQueue();
Filter filter = new FakeFilter("fruit", "orange");
FakeConsumer consumer = new FakeConsumer(filter);
}
@Test
public void testIterator() {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 20;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
queue.addTail(ref);
refs.add(ref);
}
Assert.assertEquals(numMessages, getMessageCount(queue));
Iterator<MessageReference> iterator = queue.iterator();
List<MessageReference> list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
assertRefListsIdenticalRefs(refs, list);
}
private void awaitExecution() {
FutureLatch future = new FutureLatch();
executor.execute(future);
future.await(10000);
}
@Test
public void testConsumeWithFiltersAddAndRemoveConsumer() throws Exception {
QueueImpl queue = getTemporaryQueue();
Filter filter = new FakeFilter("fruit", "orange");
FakeConsumer consumer = new FakeConsumer(filter);
queue.addConsumer(consumer);
List<MessageReference> refs = new ArrayList<>();
MessageReference ref1 = generateReference(queue, 1);
ref1.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("banana"));
queue.addTail(ref1);
MessageReference ref2 = generateReference(queue, 2);
ref2.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("orange"));
queue.addTail(ref2);
refs.add(ref2);
Assert.assertEquals(2, getMessageCount(queue));
awaitExecution();
Assert.assertEquals(1, consumer.getReferences().size());
Assert.assertEquals(1, queue.getDeliveringCount());
assertRefListsIdenticalRefs(refs, consumer.getReferences());
queue.acknowledge(ref2);
queue.removeConsumer(consumer);
queue.addConsumer(consumer);
queue.deliverNow();
refs.clear();
consumer.clearReferences();
MessageReference ref3 = generateReference(queue, 3);
ref3.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("banana"));
queue.addTail(ref3);
MessageReference ref4 = generateReference(queue, 4);
ref4.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("orange"));
queue.addTail(ref4);
refs.add(ref4);
Assert.assertEquals(3, getMessageCount(queue));
awaitExecution();
Assert.assertEquals(1, consumer.getReferences().size());
Assert.assertEquals(1, queue.getDeliveringCount());
assertRefListsIdenticalRefs(refs, consumer.getReferences());
}
@Test
public void testBusyConsumerWithFilterFirstCallBusy() throws Exception {
QueueImpl queue = getTemporaryQueue();
FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'"));
consumer.setStatusImmediate(HandleStatus.BUSY);
queue.addConsumer(consumer);
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
ref.getMessage().putStringProperty("color", "green");
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
queue.deliverNow();
consumer.setStatusImmediate(null);
queue.deliverNow();
List<MessageReference> receeivedRefs = consumer.getReferences();
int currId = 0;
for (MessageReference receeivedRef : receeivedRefs) {
Assert.assertEquals("messages received out of order", receeivedRef.getMessage().getMessageID(), currId++);
}
}
@Test
public void testBusyConsumerWithFilterThenAddMoreMessages() throws Exception {
QueueImpl queue = getTemporaryQueue();
FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'"));
consumer.setStatusImmediate(HandleStatus.BUSY);
queue.addConsumer(consumer);
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
ref.getMessage().putStringProperty("color", "red");
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
queue.deliverNow();
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
Assert.assertTrue(consumer.getReferences().isEmpty());
for (int i = numMessages; i < numMessages * 2; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
ref.getMessage().putStringProperty("color", "green");
queue.addTail(ref);
}
Assert.assertEquals(20, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
Assert.assertTrue(consumer.getReferences().isEmpty());
consumer.setStatusImmediate(null);
for (int i = numMessages * 2; i < numMessages * 3; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
queue.deliverNow();
Assert.assertEquals(numMessages, consumer.getReferences().size());
Assert.assertEquals(30, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(10, queue.getDeliveringCount());
List<MessageReference> receeivedRefs = consumer.getReferences();
int currId = 10;
for (MessageReference receeivedRef : receeivedRefs) {
Assert.assertEquals("messages received out of order", receeivedRef.getMessage().getMessageID(), currId++);
}
}
@Test
public void testConsumerWithFilterThenAddMoreMessages() throws Exception {
QueueImpl queue = getTemporaryQueue();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
ref.getMessage().putStringProperty("color", "red");
refs.add(ref);
queue.addTail(ref);
}
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
queue.deliverNow();
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
for (int i = numMessages; i < numMessages * 2; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
ref.getMessage().putStringProperty("color", "green");
queue.addTail(ref);
}
FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'"));
queue.addConsumer(consumer);
queue.deliverNow();
Assert.assertEquals(20, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(10, queue.getDeliveringCount());
for (int i = numMessages * 2; i < numMessages * 3; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
ref.getMessage().putStringProperty("color", "green");
queue.addTail(ref);
}
queue.deliverNow();
Assert.assertEquals(20, consumer.getReferences().size());
Assert.assertEquals(30, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(20, queue.getDeliveringCount());
}
// Private ------------------------------------------------------------------------------
private void testConsumerWithFilters(final boolean direct) throws Exception {
QueueImpl queue = getTemporaryQueue();
Filter filter = new FakeFilter("fruit", "orange");
FakeConsumer consumer = new FakeConsumer(filter);
if (direct) {
queue.addConsumer(consumer);
}
List<MessageReference> refs = new ArrayList<>();
MessageReference ref1 = generateReference(queue, 1);
ref1.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("banana"));
queue.addTail(ref1);
MessageReference ref2 = generateReference(queue, 2);
ref2.getMessage().putStringProperty(new SimpleString("cheese"), new SimpleString("stilton"));
queue.addTail(ref2);
MessageReference ref3 = generateReference(queue, 3);
ref3.getMessage().putStringProperty(new SimpleString("cake"), new SimpleString("sponge"));
queue.addTail(ref3);
MessageReference ref4 = generateReference(queue, 4);
ref4.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("orange"));
refs.add(ref4);
queue.addTail(ref4);
MessageReference ref5 = generateReference(queue, 5);
ref5.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("apple"));
queue.addTail(ref5);
MessageReference ref6 = generateReference(queue, 6);
ref6.getMessage().putStringProperty(new SimpleString("fruit"), new SimpleString("orange"));
refs.add(ref6);
queue.addTail(ref6);
if (!direct) {
queue.addConsumer(consumer);
queue.deliverNow();
}
Assert.assertEquals(6, getMessageCount(queue));
awaitExecution();
Assert.assertEquals(2, consumer.getReferences().size());
Assert.assertEquals(2, queue.getDeliveringCount());
assertRefListsIdenticalRefs(refs, consumer.getReferences());
queue.acknowledge(ref5);
queue.acknowledge(ref6);
queue.removeConsumer(consumer);
consumer = new FakeConsumer();
queue.addConsumer(consumer);
queue.deliverNow();
Assert.assertEquals(4, getMessageCount(queue));
Assert.assertEquals(4, consumer.getReferences().size());
Assert.assertEquals(4, queue.getDeliveringCount());
}
@Test
public void testMessageOrder() throws Exception {
FakeConsumer consumer = new FakeConsumer();
QueueImpl queue = getTemporaryQueue();
MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3);
queue.addHead(messageReference, false);
queue.addTail(messageReference2);
queue.addHead(messageReference3, false);
Assert.assertEquals(0, consumer.getReferences().size());
queue.addConsumer(consumer);
queue.deliverNow();
Assert.assertEquals(3, consumer.getReferences().size());
Assert.assertEquals(messageReference3, consumer.getReferences().get(0));
Assert.assertEquals(messageReference, consumer.getReferences().get(1));
Assert.assertEquals(messageReference2, consumer.getReferences().get(2));
}
@Test
public void testMessagesAdded() throws Exception {
QueueImpl queue = getTemporaryQueue();
MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3);
queue.addTail(messageReference);
queue.addTail(messageReference2);
queue.addTail(messageReference3);
Assert.assertEquals(getMessagesAdded(queue), 3);
}
@Test
public void testGetReference() throws Exception {
QueueImpl queue = getTemporaryQueue();
MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3);
queue.addHead(messageReference, false);
queue.addHead(messageReference2, false);
queue.addHead(messageReference3, false);
Assert.assertEquals(queue.getReference(2), messageReference2);
}
@Test
public void testGetNonExistentReference() throws Exception {
QueueImpl queue = getTemporaryQueue();
MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3);
queue.addHead(messageReference, false);
queue.addHead(messageReference2, false);
queue.addHead(messageReference3, false);
Assert.assertNull(queue.getReference(5));
}
/**
* Test the paused and resumed states with async deliveries.
*
* @throws Exception
*/
@Test
public void testPauseAndResumeWithAsync() throws Exception {
QueueImpl queue = getTemporaryQueue();
// pauses the queue
queue.pause();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
// even as this queue is paused, it will receive the messages anyway
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
// Now add a consumer
FakeConsumer consumer = new FakeConsumer();
queue.addConsumer(consumer);
Assert.assertTrue(consumer.getReferences().isEmpty());
Assert.assertEquals(10, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
// explicit order of delivery
queue.deliverNow();
// As the queue is paused, even an explicit order of delivery will not work.
Assert.assertEquals(0, consumer.getReferences().size());
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
// resuming work
queue.resume();
awaitExecution();
// after resuming the delivery begins.
assertRefListsIdenticalRefs(refs, consumer.getReferences());
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(numMessages, queue.getDeliveringCount());
}
/**
* Test the paused and resumed states with direct deliveries.
*
* @throws Exception
*/
@Test
public void testPauseAndResumeWithDirect() throws Exception {
QueueImpl queue = getTemporaryQueue();
// Now add a consumer
FakeConsumer consumer = new FakeConsumer();
queue.addConsumer(consumer);
// brings to queue to paused state
queue.pause();
final int numMessages = 10;
List<MessageReference> refs = new ArrayList<>();
for (int i = 0; i < numMessages; i++) {
MessageReference ref = generateReference(queue, i);
refs.add(ref);
queue.addTail(ref);
}
// the queue even if it's paused will receive the message but won't forward
// directly to the consumer until resumed.
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(0, queue.getScheduledCount());
Assert.assertEquals(0, queue.getDeliveringCount());
Assert.assertTrue(consumer.getReferences().isEmpty());
// brings the queue to resumed state.
queue.resume();
awaitExecution();
// resuming delivery of messages
assertRefListsIdenticalRefs(refs, consumer.getReferences());
Assert.assertEquals(numMessages, getMessageCount(queue));
Assert.assertEquals(numMessages, queue.getDeliveringCount());
}
@Test
public void testResetMessagesAdded() throws Exception {
QueueImpl queue = getTemporaryQueue();
MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2);
queue.addTail(messageReference);
queue.addTail(messageReference2);
Assert.assertEquals(2, getMessagesAdded(queue));
queue.resetMessagesAdded();
Assert.assertEquals(0, getMessagesAdded(queue));
}
class AddtoQueueRunner implements Runnable {
QueueImpl queue;
MessageReference messageReference;
boolean added = false;
CountDownLatch countDownLatch;
boolean first;
AddtoQueueRunner(final boolean first,
final QueueImpl queue,
final MessageReference messageReference,
final CountDownLatch countDownLatch) {
this.queue = queue;
this.messageReference = messageReference;
this.countDownLatch = countDownLatch;
this.first = first;
}
@Override
public void run() {
if (first) {
queue.addHead(messageReference, false);
} else {
queue.addTail(messageReference);
}
added = true;
countDownLatch.countDown();
}
}
@Test
public void testTotalIteratorOrder() throws Exception {
final String MY_ADDRESS = "myAddress";
final String MY_QUEUE = "myQueue";
ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(createDefaultInVMConfig(), true));
AddressSettings defaultSetting = new AddressSettings().setPageSizeBytes(10 * 1024).setMaxSizeBytes(20 * 1024);
server.getAddressSettingsRepository().addMatch("#", defaultSetting);
server.start();
ServerLocator locator = createInVMNonHALocator().setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true);
ClientSessionFactory factory = createSessionFactory(locator);
ClientSession session = addClientSession(factory.createSession(false, true, true));
session.createQueue(MY_ADDRESS, MY_QUEUE, true);
ClientProducer producer = addClientProducer(session.createProducer(MY_ADDRESS));
for (int i = 0; i < 50; i++) {
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeBytes(new byte[1024]);
message.putIntProperty("order", i);
producer.send(message);
}
producer.close();
session.close();
factory.close();
locator.close();
Queue queue = ((LocalQueueBinding) server.getPostOffice().getBinding(new SimpleString(MY_QUEUE))).getQueue();
LinkedListIterator<MessageReference> totalIterator = queue.browserIterator();
try {
int i = 0;
while (totalIterator.hasNext()) {
MessageReference ref = totalIterator.next();
Assert.assertEquals(i++, ref.getMessage().getIntProperty("order").intValue());
}
} finally {
totalIterator.close();
server.stop();
}
}
private QueueImpl getNonDurableQueue() {
return getQueue(QueueImplTest.queue1, false, false, null);
}
private QueueImpl getDurableQueue() {
return getQueue(QueueImplTest.queue1, true, false, null);
}
private QueueImpl getNamedQueue(SimpleString name) {
return getQueue(name, false, true, null);
}
private QueueImpl getFilteredQueue(Filter filter) {
return getQueue(QueueImplTest.queue1, false, true, filter);
}
private QueueImpl getTemporaryQueue() {
return getQueue(QueueImplTest.queue1, false, true, null);
}
private QueueImpl getQueue(SimpleString name, boolean durable, boolean temporary, Filter filter) {
return new QueueImpl(1, QueueImplTest.address1, name, filter, null, durable, temporary, false, scheduledExecutor,
new FakePostOffice(), null, null, executor, null);
}
}