001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.filter.executor;
021
022import static org.junit.Assert.assertEquals;
023
024import java.util.concurrent.ExecutorService;
025import java.util.concurrent.TimeUnit;
026
027import org.apache.mina.core.filterchain.IoFilter.NextFilter;
028import org.apache.mina.core.session.DummySession;
029import org.apache.mina.core.session.IdleStatus;
030import org.apache.mina.core.session.IoSession;
031import org.apache.mina.core.write.WriteRequest;
032import org.junit.After;
033import org.junit.Before;
034import org.junit.Test;
035
036/**
037 * TODO Add documentation
038 * 
039 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
040 */
041public class ExecutorFilterRegressionTest {
042    private ExecutorFilter filter;
043
044    public ExecutorFilterRegressionTest() {
045        // Do nothing
046    }
047
048    @Before
049    public void setUp() throws Exception {
050        filter = new ExecutorFilter(8);
051    }
052
053    @After
054    public void tearDown() throws Exception {
055        ((ExecutorService) filter.getExecutor()).shutdown();
056        filter = null;
057    }
058
059    @Test
060    public void testEventOrder() throws Throwable {
061        final EventOrderChecker nextFilter = new EventOrderChecker();
062        final EventOrderCounter[] sessions = new EventOrderCounter[] { new EventOrderCounter(),
063                new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(),
064                new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(), new EventOrderCounter(),
065                new EventOrderCounter(), };
066        final int loop = 1000000;
067        final int end = sessions.length - 1;
068        final ExecutorFilter filter = this.filter;
069        ExecutorService executor = (ExecutorService) filter.getExecutor();
070        //executor.setKeepAliveTime(3, TimeUnit.SECONDS);
071
072        for (int i = 0; i < loop; i++) {
073            Integer objI = new Integer(i);
074
075            for (int j = end; j >= 0; j--) {
076                filter.messageReceived(nextFilter, sessions[j], objI);
077            }
078
079            if (nextFilter.throwable != null) {
080                throw nextFilter.throwable;
081            }
082        }
083
084        executor.shutdown();
085        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
086
087        for (int i = end; i >= 0; i--) {
088            assertEquals(loop - 1, sessions[i].lastCount.intValue());
089        }
090    }
091
092    private static class EventOrderCounter extends DummySession {
093        Integer lastCount = null;
094
095        /**
096         * Default constructor
097         */
098        public EventOrderCounter() {
099            super();
100        }
101
102        public synchronized void setLastCount(Integer newCount) {
103            if (lastCount != null) {
104                assertEquals(lastCount.intValue() + 1, newCount.intValue());
105            }
106
107            lastCount = newCount;
108        }
109    }
110
111    private static class EventOrderChecker implements NextFilter {
112        Throwable throwable;
113
114        /**
115         * Default constructor
116         */
117        public EventOrderChecker() {
118            super();
119        }
120
121        public void sessionOpened(IoSession session) {
122            // Do nothing
123        }
124
125        public void sessionClosed(IoSession session) {
126            // Do nothing
127        }
128
129        public void sessionIdle(IoSession session, IdleStatus status) {
130            // Do nothing
131        }
132
133        public void exceptionCaught(IoSession session, Throwable cause) {
134            // Do nothing
135        }
136
137        public void inputClosed(IoSession session) {
138            // Do nothing
139        }
140
141        public void messageReceived(IoSession session, Object message) {
142            try {
143                ((EventOrderCounter) session).setLastCount((Integer) message);
144            } catch (Exception e) {
145                if (this.throwable == null) {
146                    this.throwable = e;
147                }
148            }
149        }
150
151        public void messageSent(IoSession session, WriteRequest writeRequest) {
152            // Do nothing
153        }
154
155        public void filterWrite(IoSession session, WriteRequest writeRequest) {
156            // Do nothing
157        }
158
159        public void filterClose(IoSession session) {
160            // Do nothing
161        }
162
163        public void sessionCreated(IoSession session) {
164            // Do nothing
165        }
166    }
167}