Package org.apache.mina.filter.stream

Source Code of org.apache.mina.filter.stream.AbstractStreamWriteFilterTest$DummyWriteFuture

/*
*  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.mina.filter.stream;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.MessageDigest;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import junit.framework.TestCase;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.filterchain.IoFilter.NextFilter;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.DummySession;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.write.DefaultWriteRequest;
import org.apache.mina.core.write.WriteRequest;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.apache.mina.util.AvailablePortFinder;
import org.easymock.IArgumentMatcher;
import org.easymock.classextension.EasyMock;

/**
* TODO Add documentation
*
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev: 713957 $, $Date: 2008-11-14 10:27:16 +0100 (Fri, 14 Nov 2008) $
*/
public abstract class AbstractStreamWriteFilterTest<M, U extends AbstractStreamWriteFilter<M>> extends TestCase {

    protected final IoSession session = new DummySession();

    abstract protected U createFilter();
   
    abstract protected M createMessage(byte[] data) throws Exception;
   
    public void testWriteEmptyFile() throws Exception {
        AbstractStreamWriteFilter<M> filter = createFilter();
        M message = createMessage(new byte[0]);

        WriteRequest writeRequest = new DefaultWriteRequest(message,
                new DummyWriteFuture());

        NextFilter nextFilter = EasyMock.createMock(NextFilter.class);
       /*
         * Record expectations
         */
        nextFilter.messageSent(session, writeRequest);

        /*
         * Replay.
         */
        EasyMock.replay(nextFilter);

        filter.filterWrite(nextFilter, session, writeRequest);

        /*
         * Verify.
         */
        EasyMock.verify(nextFilter);

        assertTrue(writeRequest.getFuture().isWritten());
    }

    /**
     * Tests that the filter just passes objects which aren't FileRegion's
     * through to the next filter.
     *
     * @throws Exception when something goes wrong
     */
    public void testWriteNonFileRegionMessage() throws Exception {
        AbstractStreamWriteFilter<M> filter = createFilter();

        Object message = new Object();
        WriteRequest writeRequest = new DefaultWriteRequest(message,
                new DummyWriteFuture());

        NextFilter nextFilter = EasyMock.createMock(NextFilter.class);
        /*
         * Record expectations
         */
        nextFilter.filterWrite(session, writeRequest);
        nextFilter.messageSent(session, writeRequest);

        /*
         * Replay.
         */
        EasyMock.replay(nextFilter);

        filter.filterWrite(nextFilter, session, writeRequest);
        filter.messageSent(nextFilter, session, writeRequest);

        /*
         * Verify.
         */
        EasyMock.verify(nextFilter);
    }

    /**
     * Tests when the contents of the file fits into one write buffer.
     *
     * @throws Exception when something goes wrong
     */
    public void testWriteSingleBufferFile() throws Exception {
        byte[] data = new byte[] { 1, 2, 3, 4 };

        AbstractStreamWriteFilter<M> filter = createFilter();
        M message = createMessage(data);

        WriteRequest writeRequest = new DefaultWriteRequest(message,
                new DummyWriteFuture());

        NextFilter nextFilter = EasyMock.createMock(NextFilter.class);
        /*
         * Record expectations
         */
        nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(new DefaultWriteRequest(IoBuffer
                .wrap(data))));
        nextFilter.messageSent(session, writeRequest);

        /*
         * Replay.
         */
        EasyMock.replay(nextFilter);

        filter.filterWrite(nextFilter, session, writeRequest);
        filter.messageSent(nextFilter, session, writeRequest);

        /*
         * Verify.
         */
        EasyMock.verify(nextFilter);

        assertTrue(writeRequest.getFuture().isWritten());
    }

    /**
     * Tests when the contents of the file doesn't fit into one write buffer.
     *
     * @throws Exception when something goes wrong
     */
    public void testWriteSeveralBuffersStream() throws Exception {
        AbstractStreamWriteFilter<M> filter = createFilter();
        filter.setWriteBufferSize(4);

        byte[] data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        byte[] chunk1 = new byte[] { 1, 2, 3, 4 };
        byte[] chunk2 = new byte[] { 5, 6, 7, 8 };
        byte[] chunk3 = new byte[] { 9, 10 };

        M message = createMessage(data);
        WriteRequest writeRequest = new DefaultWriteRequest(message,
                new DummyWriteFuture());

        WriteRequest chunk1Request = new DefaultWriteRequest(IoBuffer
                .wrap(chunk1));
        WriteRequest chunk2Request = new DefaultWriteRequest(IoBuffer
                .wrap(chunk2));
        WriteRequest chunk3Request = new DefaultWriteRequest(IoBuffer
                .wrap(chunk3));

        NextFilter nextFilter = EasyMock.createMock(NextFilter.class);
        /*
         * Record expectations
         */
        nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk1Request));
        nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk2Request));
        nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk3Request));
        nextFilter.messageSent(EasyMock.eq(session), eqWriteRequest(writeRequest));

        /*
         * Replay.
         */
        EasyMock.replay(nextFilter);

        filter.filterWrite(nextFilter, session, writeRequest);
        filter.messageSent(nextFilter, session, chunk1Request);
        filter.messageSent(nextFilter, session, chunk2Request);
        filter.messageSent(nextFilter, session, chunk3Request);

        /*
         * Verify.
         */
        EasyMock.verify(nextFilter);

        assertTrue(writeRequest.getFuture().isWritten());
    }

    public void testWriteWhileWriteInProgress() throws Exception {
        AbstractStreamWriteFilter<M> filter = createFilter();
        M message = createMessage(new byte[5]);

        Queue<WriteRequest> queue = new LinkedList<WriteRequest>();

        /*
         * Make up the situation.
         */
        session.setAttribute(filter.CURRENT_STREAM, message);
        session.setAttribute(filter.WRITE_REQUEST_QUEUE, queue);

        NextFilter nextFilter = EasyMock.createMock(NextFilter.class);
        /*
         * Replay.  (We recorded *nothing* because nothing should occur.)
         */
        EasyMock.replay(nextFilter);

        WriteRequest wr = new DefaultWriteRequest(new Object(),
                new DummyWriteFuture());
        filter.filterWrite(nextFilter, session, wr);
        assertEquals(1, queue.size());
        assertSame(wr, queue.poll());

        /*
         * Verify.
         */
        EasyMock.verify(nextFilter);

        session.removeAttribute(filter.CURRENT_STREAM);
        session.removeAttribute(filter.WRITE_REQUEST_QUEUE);
    }

    public void testWritesWriteRequestQueueWhenFinished() throws Exception {
        AbstractStreamWriteFilter<M> filter = createFilter();
        M message = createMessage(new byte[0]);
       
        WriteRequest wrs[] = new WriteRequest[] {
                new DefaultWriteRequest(new Object(), new DummyWriteFuture()),
                new DefaultWriteRequest(new Object(), new DummyWriteFuture()),
                new DefaultWriteRequest(new Object(), new DummyWriteFuture()) };
        Queue<WriteRequest> queue = new LinkedList<WriteRequest>();
        queue.add(wrs[0]);
        queue.add(wrs[1]);
        queue.add(wrs[2]);

        /*
         * Make up the situation.
         */
        session.setAttribute(filter.CURRENT_STREAM, message);
        session.setAttribute(filter.CURRENT_WRITE_REQUEST,
                new DefaultWriteRequest(message));
        session.setAttribute(filter.WRITE_REQUEST_QUEUE, queue);

        /*
         * Record expectations
         */
        NextFilter nextFilter = EasyMock.createMock(NextFilter.class);
        nextFilter.filterWrite(session, wrs[0]);
        nextFilter.filterWrite(session, wrs[1]);
        nextFilter.filterWrite(session, wrs[2]);
        nextFilter.messageSent(EasyMock.eq(session), eqWriteRequest(new DefaultWriteRequest(message)));

        /*
         * Replay.
         */
        EasyMock.replay(nextFilter);

        filter.messageSent(nextFilter, session, new DefaultWriteRequest(
                new Object()));
        assertEquals(0, queue.size());

        /*
         * Verify.
         */
        EasyMock.verify(nextFilter);
    }

    /**
     * Tests that {@link StreamWriteFilter#setWriteBufferSize(int)} checks the
     * specified size.
     */
    public void testSetWriteBufferSize() {
        AbstractStreamWriteFilter<M> filter = createFilter();

        try {
            filter.setWriteBufferSize(0);
            fail("0 writeBuferSize specified. IllegalArgumentException expected.");
        } catch (IllegalArgumentException iae) {
            // Pass, exception was thrown
        }

        try {
            filter.setWriteBufferSize(-100);
            fail("Negative writeBuferSize specified. IllegalArgumentException expected.");
        } catch (IllegalArgumentException iae) {
            // Pass, exception was thrown
        }

        filter.setWriteBufferSize(1);
        assertEquals(1, filter.getWriteBufferSize());
        filter.setWriteBufferSize(1024);
        assertEquals(1024, filter.getWriteBufferSize());
    }

    public void testWriteUsingSocketTransport() throws Exception {
        NioSocketAcceptor acceptor = new NioSocketAcceptor();
        acceptor.setReuseAddress(true);
        SocketAddress address = new InetSocketAddress("localhost",
                AvailablePortFinder.getNextAvailable());

        NioSocketConnector connector = new NioSocketConnector();

        // Generate 4MB of random data
        byte[] data = new byte[4 * 1024 * 1024];
        new Random().nextBytes(data);

        byte[] expectedMd5 = MessageDigest.getInstance("MD5").digest(data);

        M message = createMessage(data);
       
        SenderHandler sender = new SenderHandler(message);
        ReceiverHandler receiver = new ReceiverHandler(data.length);

        acceptor.setHandler(sender);
        connector.setHandler(receiver);
       
        acceptor.bind(address);
        connector.connect(address);
        sender.latch.await();
        receiver.latch.await();

        acceptor.dispose();

        assertEquals(data.length, receiver.bytesRead);
        byte[] actualMd5 = receiver.digest.digest();
        assertEquals(expectedMd5.length, actualMd5.length);
        for (int i = 0; i < expectedMd5.length; i++) {
            assertEquals(expectedMd5[i], actualMd5[i]);
        }
    }

    private class SenderHandler extends IoHandlerAdapter {
        final CountDownLatch latch = new CountDownLatch(1);

        private M message;

        StreamWriteFilter streamWriteFilter = new StreamWriteFilter();

        private SenderHandler(M message) {
            this.message = message;
        }

        @Override
        public void sessionCreated(IoSession session) throws Exception {
            super.sessionCreated(session);
            session.getFilterChain().addLast("codec", streamWriteFilter);
        }

        @Override
        public void sessionOpened(IoSession session) throws Exception {
            session.write(message);
        }

        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            latch.countDown();
        }

        @Override
        public void sessionClosed(IoSession session) throws Exception {
            latch.countDown();
        }

        @Override
        public void sessionIdle(IoSession session, IdleStatus status)
                throws Exception {
            latch.countDown();
        }

        @Override
        public void messageSent(IoSession session, Object message)
                throws Exception {
            if (message == this.message) {
                latch.countDown();
            }
        }
    }

    private static class ReceiverHandler extends IoHandlerAdapter {
        final CountDownLatch latch = new CountDownLatch(1);

        long bytesRead = 0;

        long size = 0;

        MessageDigest digest;

        private ReceiverHandler(long size) throws Exception {
            this.size = size;
            digest = MessageDigest.getInstance("MD5");
        }

        @Override
        public void sessionCreated(IoSession session) throws Exception {
            super.sessionCreated(session);

            session.getConfig().setIdleTime(IdleStatus.READER_IDLE, 5);
        }

        @Override
        public void sessionIdle(IoSession session, IdleStatus status)
                throws Exception {
            session.close(true);
        }

        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            latch.countDown();
        }

        @Override
        public void sessionClosed(IoSession session) throws Exception {
            latch.countDown();
        }

        @Override
        public void messageReceived(IoSession session, Object message)
                throws Exception {
            IoBuffer buf = (IoBuffer) message;
            while (buf.hasRemaining()) {
                digest.update(buf.get());
                bytesRead++;
            }
            if (bytesRead >= size) {
                session.close(true);
            }
        }
    }

    public static WriteRequest eqWriteRequest(WriteRequest expected) {
        EasyMock.reportMatcher(new WriteRequestMatcher(expected));
        return null;
    }
   
    public static class WriteRequestMatcher implements IArgumentMatcher {
       
        private final WriteRequest expected;
       
        public WriteRequestMatcher(WriteRequest expected) {
                this.expected = expected;
        }
       
        public boolean matches(Object actual) {
            if (actual instanceof WriteRequest) {
                WriteRequest w2 = (WriteRequest) actual;

                return expected.getMessage().equals(w2.getMessage())
                        && expected.getFuture().isWritten() == w2.getFuture()
                        .isWritten();
            }
            return false;
        }
        public void appendTo(StringBuffer buffer) {
                buffer.append("Expected a WriteRequest with the message '").append(expected.getMessage()).append("'");
        }
    }

    private static class DummyWriteFuture implements WriteFuture {
        private boolean written;

        public boolean isWritten() {
            return written;
        }

        public void setWritten() {
            this.written = true;
        }

        public IoSession getSession() {
            return null;
        }

        public Object getLock() {
            return this;
        }

        public void join() {
        }

        public boolean join(long timeoutInMillis) {
            return true;
        }

        public boolean isDone() {
            return true;
        }

        public WriteFuture addListener(IoFutureListener<?> listener) {
            return this;
        }

        public WriteFuture removeListener(IoFutureListener<?> listener) {
            return this;
        }

        public WriteFuture await() throws InterruptedException {
            return this;
        }

        public boolean await(long timeout, TimeUnit unit)
                throws InterruptedException {
            return true;
        }

        public boolean await(long timeoutMillis) throws InterruptedException {
            return true;
        }

        public WriteFuture awaitUninterruptibly() {
            return this;
        }

        public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
            return true;
        }

        public boolean awaitUninterruptibly(long timeoutMillis) {
            return true;
        }

        public Throwable getException() {
            return null;
        }

        public void setException(Throwable cause) {
            throw new IllegalStateException();
        }
    }

   
}
TOP

Related Classes of org.apache.mina.filter.stream.AbstractStreamWriteFilterTest$DummyWriteFuture

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.