/*
* 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.integration.client;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
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.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MessagePriorityTest extends ActiveMQTestBase {
// Constants -----------------------------------------------------
private static final IntegrationTestLogger log = IntegrationTestLogger.LOGGER;
// Attributes ----------------------------------------------------
private ActiveMQServer server;
private ClientSession session;
private ClientSessionFactory sf;
private ServerLocator locator;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
// Public --------------------------------------------------------
@Test
public void testMessagePriority() throws Exception {
SimpleString queue = RandomUtil.randomSimpleString();
SimpleString address = RandomUtil.randomSimpleString();
session.createQueue(address, queue, false);
ClientProducer producer = session.createProducer(address);
for (int i = 0; i < 10; i++) {
ClientMessage m = createTextMessage(session, Integer.toString(i));
m.setPriority((byte) i);
producer.send(m);
}
ClientConsumer consumer = session.createConsumer(queue);
session.start();
// expect to consumer message with higher priority first
for (int i = 9; i >= 0; i--) {
ClientMessage m = consumer.receive(500);
Assert.assertNotNull(m);
Assert.assertEquals(i, m.getPriority());
}
consumer.close();
session.deleteQueue(queue);
}
/**
* in this tests, the session is started and the consumer created *before* the messages are sent.
* each message which is sent will be received by the consumer in its buffer and the priority won't be taken
* into account.
* We need to implement client-side message priority to handle this case: https://jira.jboss.org/jira/browse/JBMESSAGING-1560
*/
@Test
public void testMessagePriorityWithClientSidePrioritization() throws Exception {
SimpleString queue = RandomUtil.randomSimpleString();
SimpleString address = RandomUtil.randomSimpleString();
session.createQueue(address, queue, false);
session.start();
ClientProducer producer = session.createProducer(address);
ClientConsumer consumer = session.createConsumer(queue);
for (int i = 0; i < 10; i++) {
ClientMessage m = createTextMessage(session, Integer.toString(i));
m.setPriority((byte) i);
producer.send(m);
}
//Wait for msgs to reach client side
Thread.sleep(1000);
// expect to consume message with higher priority first
for (int i = 9; i >= 0; i--) {
ClientMessage m = consumer.receive(500);
log.info("received msg " + m.getPriority());
Assert.assertNotNull(m);
Assert.assertEquals(i, m.getPriority());
}
consumer.close();
session.deleteQueue(queue);
}
@Test
public void testMessageOrderWithSamePriority() throws Exception {
SimpleString queue = RandomUtil.randomSimpleString();
SimpleString address = RandomUtil.randomSimpleString();
session.createQueue(address, queue, false);
ClientProducer producer = session.createProducer(address);
ClientMessage[] messages = new ClientMessage[10];
// send 3 messages with priority 0
// 3 7
// 3 3
// 1 9
messages[0] = createTextMessage(session, "a");
messages[0].setPriority((byte) 0);
messages[1] = createTextMessage(session, "b");
messages[1].setPriority((byte) 0);
messages[2] = createTextMessage(session, "c");
messages[2].setPriority((byte) 0);
messages[3] = createTextMessage(session, "d");
messages[3].setPriority((byte) 7);
messages[4] = createTextMessage(session, "e");
messages[4].setPriority((byte) 7);
messages[5] = createTextMessage(session, "f");
messages[5].setPriority((byte) 7);
messages[6] = createTextMessage(session, "g");
messages[6].setPriority((byte) 3);
messages[7] = createTextMessage(session, "h");
messages[7].setPriority((byte) 3);
messages[8] = createTextMessage(session, "i");
messages[8].setPriority((byte) 3);
messages[9] = createTextMessage(session, "j");
messages[9].setPriority((byte) 9);
for (int i = 0; i < 10; i++) {
producer.send(messages[i]);
}
ClientConsumer consumer = session.createConsumer(queue);
session.start();
// 1 message with priority 9
MessagePriorityTest.expectMessage((byte) 9, "j", consumer);
// 3 messages with priority 7
MessagePriorityTest.expectMessage((byte) 7, "d", consumer);
MessagePriorityTest.expectMessage((byte) 7, "e", consumer);
MessagePriorityTest.expectMessage((byte) 7, "f", consumer);
// 3 messages with priority 3
MessagePriorityTest.expectMessage((byte) 3, "g", consumer);
MessagePriorityTest.expectMessage((byte) 3, "h", consumer);
MessagePriorityTest.expectMessage((byte) 3, "i", consumer);
// 3 messages with priority 0
MessagePriorityTest.expectMessage((byte) 0, "a", consumer);
MessagePriorityTest.expectMessage((byte) 0, "b", consumer);
MessagePriorityTest.expectMessage((byte) 0, "c", consumer);
consumer.close();
session.deleteQueue(queue);
}
// https://jira.jboss.org/jira/browse/HORNETQ-275
@Test
public void testOutOfOrderAcknowledgement() throws Exception {
SimpleString queue = RandomUtil.randomSimpleString();
SimpleString address = RandomUtil.randomSimpleString();
session.createQueue(address, queue, false);
ClientProducer producer = session.createProducer(address);
ClientConsumer consumer = session.createConsumer(queue);
session.start();
for (int i = 0; i < 10; i++) {
ClientMessage m = createTextMessage(session, Integer.toString(i));
m.setPriority((byte) i);
producer.send(m);
}
Thread.sleep(500);
// Now we wait a little bit to make sure the messages are in the client side buffer
// They should have been added to the delivering list in the ServerConsumerImpl in the order
// they were sent, not priority order
//We receive one of the messages
ClientMessage m = consumer.receive(500);
Assert.assertNotNull(m);
Assert.assertEquals(9, m.getPriority());
//Ack it
m.acknowledge();
consumer.close();
//Close and try and receive the other ones
consumer = session.createConsumer(queue);
// Other messages should be received now
// Previously there was a bug whereby if deliveries were stored on server side in send order
// then if received in priority order, and acked
// the ack would ack all messages up to the one received - resulting in acking
// messages that hadn't been delivered yet
for (int i = 8; i >= 0; i--) {
m = consumer.receive(500);
Assert.assertNotNull(m);
Assert.assertEquals(i, m.getPriority());
m.acknowledge();
}
consumer.close();
session.deleteQueue(queue);
}
@Test
public void testManyMessages() throws Exception {
SimpleString queue = RandomUtil.randomSimpleString();
SimpleString address = RandomUtil.randomSimpleString();
session.createQueue(address, queue, false);
ClientProducer producer = session.createProducer(address);
for (int i = 0; i < 777; i++) {
ClientMessage msg = session.createMessage(true);
msg.setPriority((byte) 5);
msg.putBooleanProperty("fast", false);
producer.send(msg);
}
for (int i = 0; i < 333; i++) {
ClientMessage msg = session.createMessage(true);
msg.setPriority((byte) 6);
msg.putBooleanProperty("fast", true);
producer.send(msg);
}
ClientConsumer consumer = session.createConsumer(queue);
session.start();
for (int i = 0; i < 333; i++) {
ClientMessage msg = consumer.receive(5000);
assertNotNull(msg);
msg.acknowledge();
assertTrue(msg.getBooleanProperty("fast"));
}
for (int i = 0; i < 777; i++) {
ClientMessage msg = consumer.receive(5000);
assertNotNull(msg);
msg.acknowledge();
assertFalse(msg.getBooleanProperty("fast"));
}
consumer.close();
session.deleteQueue(queue);
session.close();
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
@Override
@Before
public void setUp() throws Exception {
super.setUp();
Configuration config = createDefaultInVMConfig();
server = addServer(ActiveMQServers.newActiveMQServer(config, false));
server.start();
locator = createInVMNonHALocator().setBlockOnNonDurableSend(true).setBlockOnDurableSend(true);
sf = createSessionFactory(locator);
session = addClientSession(sf.createSession(false, true, true));
}
// Private -------------------------------------------------------
private static void expectMessage(final byte expectedPriority,
final String expectedStringInBody,
final ClientConsumer consumer) throws Exception {
ClientMessage m = consumer.receive(500);
Assert.assertNotNull(m);
Assert.assertEquals(expectedPriority, m.getPriority());
Assert.assertEquals(expectedStringInBody, m.getBodyBuffer().readString());
}
// Inner classes -------------------------------------------------
}