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.core;
021
022import java.io.IOException;
023
024import org.apache.mina.core.future.DefaultCloseFuture;
025import org.apache.mina.core.future.DefaultConnectFuture;
026import org.apache.mina.core.future.DefaultWriteFuture;
027import org.apache.mina.core.future.IoFuture;
028import org.apache.mina.core.future.IoFutureListener;
029import org.apache.mina.core.session.DummySession;
030import org.apache.mina.core.session.IoSession;
031import org.junit.Test;
032
033import static org.junit.Assert.assertFalse;
034import static org.junit.Assert.assertTrue;
035import static org.junit.Assert.assertNull;
036import static org.junit.Assert.assertEquals;
037import static org.junit.Assert.assertSame;
038import static org.junit.Assert.fail;
039
040/**
041 * Tests {@link IoFuture} implementations.
042 *
043 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
044 */
045public class FutureTest {
046
047    @Test
048    public void testCloseFuture() throws Exception {
049        DefaultCloseFuture future = new DefaultCloseFuture(null);
050        assertFalse(future.isDone());
051        assertFalse(future.isClosed());
052
053        TestThread thread = new TestThread(future);
054        thread.start();
055
056        future.setClosed();
057        thread.join();
058
059        assertTrue(thread.success);
060        assertTrue(future.isDone());
061        assertTrue(future.isClosed());
062    }
063
064    @Test
065    public void testConnectFuture() throws Exception {
066        DefaultConnectFuture future = new DefaultConnectFuture();
067        assertFalse(future.isDone());
068        assertFalse(future.isConnected());
069        assertNull(future.getSession());
070        assertNull(future.getException());
071
072        TestThread thread = new TestThread(future);
073        thread.start();
074
075        IoSession session = new DummySession();
076
077        future.setSession(session);
078        thread.join();
079
080        assertTrue(thread.success);
081        assertTrue(future.isDone());
082        assertTrue(future.isConnected());
083        assertEquals(session, future.getSession());
084        assertNull(future.getException());
085
086        future = new DefaultConnectFuture();
087        thread = new TestThread(future);
088        thread.start();
089        future.setException(new IOException());
090        thread.join();
091
092        assertTrue(thread.success);
093        assertTrue(future.isDone());
094        assertFalse(future.isConnected());
095        assertTrue(future.getException() instanceof IOException);
096
097        try {
098            future.getSession();
099            fail("IOException should be thrown.");
100        } catch (Exception e) {
101            // Signifies a successful test execution
102            assertTrue(true);
103        }
104    }
105
106    @Test
107    public void testWriteFuture() throws Exception {
108        DefaultWriteFuture future = new DefaultWriteFuture(null);
109        assertFalse(future.isDone());
110        assertFalse(future.isWritten());
111
112        TestThread thread = new TestThread(future);
113        thread.start();
114
115        future.setWritten();
116        thread.join();
117
118        assertTrue(thread.success);
119        assertTrue(future.isDone());
120        assertTrue(future.isWritten());
121
122        future = new DefaultWriteFuture(null);
123        thread = new TestThread(future);
124        thread.start();
125
126        future.setException(new Exception());
127        thread.join();
128
129        assertTrue(thread.success);
130        assertTrue(future.isDone());
131        assertFalse(future.isWritten());
132        assertTrue(future.getException().getClass() == Exception.class);
133    }
134
135    @Test
136    public void testAddListener() throws Exception {
137        DefaultCloseFuture future = new DefaultCloseFuture(null);
138        assertFalse(future.isDone());
139        assertFalse(future.isClosed());
140
141        TestListener listener1 = new TestListener();
142        TestListener listener2 = new TestListener();
143        future.addListener(listener1);
144        future.addListener(listener2);
145
146        TestThread thread = new TestThread(future);
147        thread.start();
148
149        future.setClosed();
150        thread.join();
151
152        assertTrue(thread.success);
153        assertTrue(future.isDone());
154        assertTrue(future.isClosed());
155
156        assertSame(future, listener1.notifiedFuture);
157        assertSame(future, listener2.notifiedFuture);
158    }
159
160    @Test
161    public void testLateAddListener() throws Exception {
162        DefaultCloseFuture future = new DefaultCloseFuture(null);
163        assertFalse(future.isDone());
164        assertFalse(future.isClosed());
165
166        TestThread thread = new TestThread(future);
167        thread.start();
168
169        future.setClosed();
170        thread.join();
171
172        assertTrue(thread.success);
173        assertTrue(future.isDone());
174        assertTrue(future.isClosed());
175
176        TestListener listener = new TestListener();
177        future.addListener(listener);
178        assertSame(future, listener.notifiedFuture);
179    }
180
181    @Test
182    public void testRemoveListener1() throws Exception {
183        DefaultCloseFuture future = new DefaultCloseFuture(null);
184        assertFalse(future.isDone());
185        assertFalse(future.isClosed());
186
187        TestListener listener1 = new TestListener();
188        TestListener listener2 = new TestListener();
189        future.addListener(listener1);
190        future.addListener(listener2);
191        future.removeListener(listener1);
192
193        TestThread thread = new TestThread(future);
194        thread.start();
195
196        future.setClosed();
197        thread.join();
198
199        assertTrue(thread.success);
200        assertTrue(future.isDone());
201        assertTrue(future.isClosed());
202
203        assertSame(null, listener1.notifiedFuture);
204        assertSame(future, listener2.notifiedFuture);
205    }
206
207    @Test
208    public void testRemoveListener2() throws Exception {
209        DefaultCloseFuture future = new DefaultCloseFuture(null);
210        assertFalse(future.isDone());
211        assertFalse(future.isClosed());
212
213        TestListener listener1 = new TestListener();
214        TestListener listener2 = new TestListener();
215        future.addListener(listener1);
216        future.addListener(listener2);
217        future.removeListener(listener2);
218
219        TestThread thread = new TestThread(future);
220        thread.start();
221
222        future.setClosed();
223        thread.join();
224
225        assertTrue(thread.success);
226        assertTrue(future.isDone());
227        assertTrue(future.isClosed());
228
229        assertSame(future, listener1.notifiedFuture);
230        assertSame(null, listener2.notifiedFuture);
231    }
232
233    private static class TestThread extends Thread {
234        private final IoFuture future;
235
236        boolean success;
237
238        public TestThread(IoFuture future) {
239            this.future = future;
240        }
241
242        @Override
243        public void run() {
244            success = future.awaitUninterruptibly(10000);
245        }
246    }
247
248    private static class TestListener implements IoFutureListener<IoFuture> {
249        IoFuture notifiedFuture;
250
251        /**
252         * Default constructor
253         */
254        public TestListener() {
255            super();
256        }
257
258        public void operationComplete(IoFuture future) {
259            this.notifiedFuture = future;
260        }
261    }
262}