/* * 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.timing.core.server.impl; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.SimpleString; 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.impl.QueueImpl; import org.apache.activemq.artemis.tests.unit.core.server.impl.fakes.FakeConsumer; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.apache.activemq.artemis.utils.ActiveMQThreadFactory; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class QueueImplTest extends ActiveMQTestBase { private static final SimpleString queue1 = new SimpleString("queue1"); private static final long TIMEOUT = 10000; private ScheduledExecutorService scheduledExecutor; // private ExecutorService executor; @Override @Before public void setUp() throws Exception { super.setUp(); scheduledExecutor = new ScheduledThreadPoolExecutor(1); } @Override @After public void tearDown() throws Exception { scheduledExecutor.shutdownNow(); super.tearDown(); } // The tests ---------------------------------------------------------------- @Test public void testScheduledNoConsumer() throws Exception { QueueImpl queue = new QueueImpl(1, new SimpleString("address1"), new SimpleString("queue1"), null, null, false, true, false, scheduledExecutor, null, null, null, Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory()), null); // Send one scheduled long now = System.currentTimeMillis(); MessageReference ref1 = generateReference(queue, 1); ref1.setScheduledDeliveryTime(now + 7000); queue.addTail(ref1); // Send some non scheduled messages MessageReference ref2 = generateReference(queue, 2); queue.addTail(ref2); MessageReference ref3 = generateReference(queue, 3); queue.addTail(ref3); MessageReference ref4 = generateReference(queue, 4); queue.addTail(ref4); // Now send some more scheduled messages MessageReference ref5 = generateReference(queue, 5); ref5.setScheduledDeliveryTime(now + 5000); queue.addTail(ref5); MessageReference ref6 = generateReference(queue, 6); ref6.setScheduledDeliveryTime(now + 4000); queue.addTail(ref6); MessageReference ref7 = generateReference(queue, 7); ref7.setScheduledDeliveryTime(now + 3000); queue.addTail(ref7); MessageReference ref8 = generateReference(queue, 8); ref8.setScheduledDeliveryTime(now + 6000); queue.addTail(ref8); List<MessageReference> refs = new ArrayList<>(); // Scheduled refs are added back to *FRONT* of queue - otherwise if there were many messages in the queue // They may get stranded behind a big backlog refs.add(ref1); refs.add(ref8); refs.add(ref5); refs.add(ref6); refs.add(ref7); refs.add(ref2); refs.add(ref3); refs.add(ref4); Thread.sleep(7500); FakeConsumer consumer = new FakeConsumer(); queue.addConsumer(consumer); queue.deliverNow(); assertRefListsIdenticalRefs(refs, consumer.getReferences()); } @Test public void testScheduled() throws Exception { QueueImpl queue = new QueueImpl(1, new SimpleString("address1"), new SimpleString("queue1"), null, null, false, true, false, scheduledExecutor, null, null, null, Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory()), null); FakeConsumer consumer = null; // Send one scheduled long now = System.currentTimeMillis(); MessageReference ref1 = generateReference(queue, 1); ref1.setScheduledDeliveryTime(now + 7000); queue.addTail(ref1); // Send some non scheduled messages MessageReference ref2 = generateReference(queue, 2); queue.addTail(ref2); MessageReference ref3 = generateReference(queue, 3); queue.addTail(ref3); MessageReference ref4 = generateReference(queue, 4); queue.addTail(ref4); // Now send some more scheduled messages MessageReference ref5 = generateReference(queue, 5); ref5.setScheduledDeliveryTime(now + 5000); queue.addTail(ref5); MessageReference ref6 = generateReference(queue, 6); ref6.setScheduledDeliveryTime(now + 4000); queue.addTail(ref6); MessageReference ref7 = generateReference(queue, 7); ref7.setScheduledDeliveryTime(now + 3000); queue.addTail(ref7); MessageReference ref8 = generateReference(queue, 8); ref8.setScheduledDeliveryTime(now + 6000); queue.addTail(ref8); consumer = new FakeConsumer(); queue.addConsumer(consumer); queue.deliverNow(); List<MessageReference> refs = new ArrayList<>(); refs.add(ref2); refs.add(ref3); refs.add(ref4); assertRefListsIdenticalRefs(refs, consumer.getReferences()); refs.clear(); consumer.getReferences().clear(); MessageReference ref = consumer.waitForNextReference(QueueImplTest.TIMEOUT); Assert.assertEquals(ref7, ref); long now2 = System.currentTimeMillis(); Assert.assertTrue(now2 - now >= 3000); ref = consumer.waitForNextReference(QueueImplTest.TIMEOUT); Assert.assertEquals(ref6, ref); now2 = System.currentTimeMillis(); Assert.assertTrue(now2 - now >= 4000); ref = consumer.waitForNextReference(QueueImplTest.TIMEOUT); Assert.assertEquals(ref5, ref); now2 = System.currentTimeMillis(); Assert.assertTrue(now2 - now >= 5000); ref = consumer.waitForNextReference(QueueImplTest.TIMEOUT); Assert.assertEquals(ref8, ref); now2 = System.currentTimeMillis(); Assert.assertTrue(now2 - now >= 6000); ref = consumer.waitForNextReference(QueueImplTest.TIMEOUT); Assert.assertEquals(ref1, ref); now2 = System.currentTimeMillis(); Assert.assertTrue(now2 - now >= 7000); Assert.assertTrue(consumer.getReferences().isEmpty()); } @Test public void testDeliveryScheduled() throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); Consumer consumer = new FakeConsumer() { @Override public synchronized HandleStatus handle(final MessageReference reference) { countDownLatch.countDown(); return HandleStatus.HANDLED; } @Override public void disconnect() { } }; QueueImpl queue = new QueueImpl(1, new SimpleString("address1"), QueueImplTest.queue1, null, null, false, true, false, scheduledExecutor, null, null, null, Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory()), null); MessageReference messageReference = generateReference(queue, 1); queue.addConsumer(consumer); messageReference.setScheduledDeliveryTime(System.currentTimeMillis() + 2000); queue.addHead(messageReference, false); boolean gotLatch = countDownLatch.await(3000, TimeUnit.MILLISECONDS); Assert.assertTrue(gotLatch); } }