org.springframework.integration.channel.QueueChannelTests.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.channel.QueueChannelTests.java

Source

/*
 * 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 org.apache.commons.logging.Log;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.integration.selector.UnexpiredMessageSelector;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;
import reactor.io.codec.JavaSerializationCodec;
import reactor.io.queue.PersistentQueue;
import reactor.io.queue.spec.PersistentQueueSpec;

import java.io.IOException;
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 static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

/**
 * @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();
        Log logger = spy(TestUtils.getPropertyValue(channel, "logger", Log.class));
        when(logger.isDebugEnabled()).thenReturn(true);
        when(logger.isTraceEnabled()).thenReturn(true);
        new DirectFieldAccessor(channel).setPropertyValue("logger", logger);
        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());
        ArgumentCaptor<String> preCaptor = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<String> postCaptor = ArgumentCaptor.forClass(String.class);
        verify(logger).trace(preCaptor.capture());
        verify(logger, times(3)).debug(postCaptor.capture());
        assertThat(preCaptor.getValue(), startsWith("preReceive"));
        assertThat(postCaptor.getValue(), startsWith("postReceive"));
    }

    @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 = new Runnable() {
            @Override
            public void run() {
                Message<?> message = channel.receive(0);
                if (message != null) {
                    messageReceived.set(true);
                }
                latch1.countDown();
            }
        };
        Runnable sendTask = new Runnable() {
            @Override
            public void run() {
                channel.send(new GenericMessage<String>("testing"));
            }
        };
        singleThreadExecutor.execute(receiveTask1);
        latch1.await();
        singleThreadExecutor.execute(sendTask);
        assertFalse(messageReceived.get());
        Runnable receiveTask2 = new Runnable() {
            @Override
            public void run() {
                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(new Runnable() {
            @Override
            public void run() {
                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(new Runnable() {
            @Override
            public void run() {
                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(new Runnable() {
            @Override
            public void run() {
                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(new Runnable() {
            @Override
            public void run() {
                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();

    @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));
    }

}