/* * Copyright 2002-2015 the original author or authors. * * Licensed 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.springframework.integration.channel; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.springframework.integration.selector.UnexpiredMessageSelector; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; /** * @author Mark Fisher * @author Artem Bilan * @author Gary Russell */ public class QueueChannelTests { @Test public void testSimpleSendAndReceive() throws Exception { final AtomicBoolean messageReceived = new AtomicBoolean(false); final CountDownLatch latch = new CountDownLatch(1); final QueueChannel channel = new QueueChannel(); new Thread(() -> { Message<?> message = channel.receive(); if (message != null) { messageReceived.set(true); latch.countDown(); } }).start(); assertFalse(messageReceived.get()); channel.send(new GenericMessage<String>("testing")); latch.await(1000, TimeUnit.MILLISECONDS); assertTrue(messageReceived.get()); } @Test public void testImmediateReceive() throws Exception { final AtomicBoolean messageReceived = new AtomicBoolean(false); final QueueChannel channel = new QueueChannel(); final CountDownLatch latch1 = new CountDownLatch(1); final CountDownLatch latch2 = new CountDownLatch(1); Executor singleThreadExecutor = Executors.newSingleThreadExecutor(); Runnable receiveTask1 = () -> { Message<?> message = channel.receive(0); if (message != null) { messageReceived.set(true); } latch1.countDown(); }; Runnable sendTask = () -> channel.send(new GenericMessage<String>("testing")); singleThreadExecutor.execute(receiveTask1); latch1.await(); singleThreadExecutor.execute(sendTask); assertFalse(messageReceived.get()); Runnable receiveTask2 = () -> { Message<?> message = channel.receive(0); if (message != null) { messageReceived.set(true); } latch2.countDown(); }; singleThreadExecutor.execute(receiveTask2); latch2.await(); assertTrue(messageReceived.get()); } @Test public void testBlockingReceiveWithNoTimeout() throws Exception { final QueueChannel channel = new QueueChannel(); final AtomicBoolean receiveInterrupted = new AtomicBoolean(false); final CountDownLatch latch = new CountDownLatch(1); Thread t = new Thread(() -> { Message<?> message = channel.receive(); receiveInterrupted.set(true); assertTrue(message == null); latch.countDown(); }); t.start(); assertFalse(receiveInterrupted.get()); t.interrupt(); latch.await(); assertTrue(receiveInterrupted.get()); } @Test public void testBlockingReceiveWithTimeout() throws Exception { final QueueChannel channel = new QueueChannel(); final AtomicBoolean receiveInterrupted = new AtomicBoolean(false); final CountDownLatch latch = new CountDownLatch(1); Thread t = new Thread(() -> { Message<?> message = channel.receive(10000); receiveInterrupted.set(true); assertTrue(message == null); latch.countDown(); }); t.start(); assertFalse(receiveInterrupted.get()); t.interrupt(); latch.await(); assertTrue(receiveInterrupted.get()); } @Test public void testImmediateSend() { QueueChannel channel = new QueueChannel(3); boolean result1 = channel.send(new GenericMessage<String>("test-1")); assertTrue(result1); boolean result2 = channel.send(new GenericMessage<String>("test-2"), 100); assertTrue(result2); boolean result3 = channel.send(new GenericMessage<String>("test-3"), 0); assertTrue(result3); boolean result4 = channel.send(new GenericMessage<String>("test-4"), 0); assertFalse(result4); } @Test public void testBlockingSendWithNoTimeout() throws Exception { final QueueChannel channel = new QueueChannel(1); boolean result1 = channel.send(new GenericMessage<String>("test-1")); assertTrue(result1); final AtomicBoolean sendInterrupted = new AtomicBoolean(false); final CountDownLatch latch = new CountDownLatch(1); Thread t = new Thread(() -> { channel.send(new GenericMessage<String>("test-2")); sendInterrupted.set(true); latch.countDown(); }); t.start(); assertFalse(sendInterrupted.get()); t.interrupt(); latch.await(); assertTrue(sendInterrupted.get()); } @Test public void testBlockingSendWithTimeout() throws Exception { final QueueChannel channel = new QueueChannel(1); boolean result1 = channel.send(new GenericMessage<String>("test-1")); assertTrue(result1); final AtomicBoolean sendInterrupted = new AtomicBoolean(false); final CountDownLatch latch = new CountDownLatch(1); Thread t = new Thread(() -> { channel.send(new GenericMessage<String>("test-2"), 10000); sendInterrupted.set(true); latch.countDown(); }); t.start(); assertFalse(sendInterrupted.get()); t.interrupt(); latch.await(); assertTrue(sendInterrupted.get()); } @Test public void testClear() { QueueChannel channel = new QueueChannel(2); GenericMessage<String> message1 = new GenericMessage<String>("test1"); GenericMessage<String> message2 = new GenericMessage<String>("test2"); GenericMessage<String> message3 = new GenericMessage<String>("test3"); assertTrue(channel.send(message1)); assertTrue(channel.send(message2)); assertFalse(channel.send(message3, 0)); List<Message<?>> clearedMessages = channel.clear(); assertNotNull(clearedMessages); assertEquals(2, clearedMessages.size()); assertTrue(channel.send(message3)); } @Test public void testClearEmptyChannel() { QueueChannel channel = new QueueChannel(); List<Message<?>> clearedMessages = channel.clear(); assertNotNull(clearedMessages); assertEquals(0, clearedMessages.size()); } @Test public void testPurge() { QueueChannel channel = new QueueChannel(2); long minute = 60 * 1000; long time = System.currentTimeMillis(); long past = time - minute; long future = time + minute; Message<String> expiredMessage = MessageBuilder.withPayload("test1") .setExpirationDate(past).build(); Message<String> unexpiredMessage = MessageBuilder.withPayload("test2") .setExpirationDate(future).build(); assertTrue(channel.send(expiredMessage, 0)); assertTrue(channel.send(unexpiredMessage, 0)); assertFalse(channel.send(new GenericMessage<String>("atCapacity"), 0)); List<Message<?>> purgedMessages = channel.purge(new UnexpiredMessageSelector()); assertNotNull(purgedMessages); assertEquals(1, purgedMessages.size()); assertTrue(channel.send(new GenericMessage<String>("roomAvailable"), 0)); } @Rule public final TemporaryFolder tempFolder = new TemporaryFolder(); /*TODO: No Reactor Chronicle artifact @Test public void testReactorPersistentQueue() throws InterruptedException, IOException { final AtomicBoolean messageReceived = new AtomicBoolean(false); final CountDownLatch latch = new CountDownLatch(1); PersistentQueue<Message<?>> queue = new PersistentQueueSpec<Message<?>>() .codec(new JavaSerializationCodec<Message<?>>()) .basePath(this.tempFolder.getRoot().getAbsolutePath()) .get(); final QueueChannel channel = new QueueChannel(queue); new Thread(new Runnable() { @Override public void run() { Message<?> message = channel.receive(); if (message != null) { messageReceived.set(true); latch.countDown(); } } }).start(); assertFalse(messageReceived.get()); channel.send(new GenericMessage<String>("testing")); latch.await(1000, TimeUnit.MILLISECONDS); assertTrue(messageReceived.get()); final CountDownLatch latch1 = new CountDownLatch(2); Thread thread = new Thread(new Runnable() { @Override public void run() { while (true) { Message<?> message = channel.receive(100); if (message != null) { latch1.countDown(); if (latch1.getCount() == 0) { break; } } } } }); thread.start(); Thread.sleep(200); channel.send(new GenericMessage<String>("testing")); channel.send(new GenericMessage<String>("testing")); assertTrue(latch1.await(1000, TimeUnit.MILLISECONDS)); final AtomicBoolean receiveInterrupted = new AtomicBoolean(false); final CountDownLatch latch2 = new CountDownLatch(1); Thread t = new Thread(new Runnable() { @Override public void run() { Message<?> message = channel.receive(10000); receiveInterrupted.set(true); assertTrue(message == null); latch2.countDown(); } }); t.start(); assertFalse(receiveInterrupted.get()); t.interrupt(); latch2.await(); assertTrue(receiveInterrupted.get()); receiveInterrupted.set(false); final CountDownLatch latch3 = new CountDownLatch(1); t = new Thread(new Runnable() { @Override public void run() { Message<?> message = channel.receive(); receiveInterrupted.set(true); assertTrue(message == null); latch3.countDown(); } }); t.start(); assertFalse(receiveInterrupted.get()); t.interrupt(); latch3.await(); assertTrue(receiveInterrupted.get()); GenericMessage<String> message1 = new GenericMessage<String>("test1"); GenericMessage<String> message2 = new GenericMessage<String>("test2"); assertTrue(channel.send(message1)); assertTrue(channel.send(message2)); List<Message<?>> clearedMessages = channel.clear(); assertNotNull(clearedMessages); assertEquals(2, clearedMessages.size()); clearedMessages = channel.clear(); assertNotNull(clearedMessages); assertEquals(0, clearedMessages.size()); // Test on artificial infinite wait // channel.receive(); // Distributed scenario final CountDownLatch latch4 = new CountDownLatch(1); new Thread(new Runnable() { @Override public void run() { Message<?> message = channel.receive(); if (message != null) { latch4.countDown(); } } }).start(); queue.add(new GenericMessage<String>("foo")); assertTrue(latch4.await(1000, TimeUnit.MILLISECONDS)); } */ }