View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.transport;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertSame;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.net.InetAddress;
29  import java.net.InetSocketAddress;
30  import java.util.concurrent.CountDownLatch;
31  import java.util.concurrent.TimeUnit;
32  import java.util.regex.Pattern;
33  
34  import org.apache.mina.core.RuntimeIoException;
35  import org.apache.mina.core.future.ConnectFuture;
36  import org.apache.mina.core.service.IoAcceptor;
37  import org.apache.mina.core.service.IoConnector;
38  import org.apache.mina.core.service.IoHandlerAdapter;
39  import org.apache.mina.core.session.IoSession;
40  import org.apache.mina.core.session.IoSessionInitializer;
41  import org.apache.mina.util.AvailablePortFinder;
42  import org.junit.Test;
43  
44  /**
45   * Tests a generic {@link IoConnector}.
46   *
47   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
48   */
49  public abstract class AbstractConnectorTest {
50  
51      protected abstract IoAcceptor createAcceptor();
52  
53      protected abstract IoConnector createConnector();
54  
55      @Test
56      public void testConnectFutureSuccessTiming() throws Exception {
57          int port = AvailablePortFinder.getNextAvailable(1025);
58          IoAcceptor acceptor = createAcceptor();
59          acceptor.setHandler(new IoHandlerAdapter());
60          acceptor.bind(new InetSocketAddress(port));
61  
62          try {
63              final StringBuffer buf = new StringBuffer();
64              IoConnector connector = createConnector();
65              connector.setHandler(new IoHandlerAdapter() {
66                  @Override
67                  public void sessionCreated(IoSession session) {
68                      buf.append("1");
69                  }
70  
71                  @Override
72                  public void sessionOpened(IoSession session) {
73                      buf.append("2");
74                  }
75  
76                  @Override
77                  public void exceptionCaught(IoSession session, Throwable cause) {
78                      buf.append("X");
79                  }
80              });
81              ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
82              future.awaitUninterruptibly();
83              buf.append("3");
84              future.getSession().closeNow();
85              // sessionCreated() will fire before the connect future completes
86              // but sessionOpened() may not
87              assertTrue(Pattern.matches("12?32?", buf.toString()));
88          } finally {
89              acceptor.dispose();
90          }
91      }
92  
93      @Test
94      public void testConnectFutureFailureTiming() throws Exception {
95          int port = AvailablePortFinder.getNextAvailable(1025);
96          final StringBuffer buf = new StringBuffer();
97  
98          IoConnector connector = createConnector();
99          connector.setHandler(new IoHandlerAdapter() {
100             @Override
101             public void sessionCreated(IoSession session) {
102                 buf.append("X");
103             }
104 
105             @Override
106             public void sessionOpened(IoSession session) {
107                 buf.append("Y");
108             }
109 
110             @Override
111             public void exceptionCaught(IoSession session, Throwable cause) {
112                 buf.append("Z");
113             }
114         });
115 
116         try {
117             ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
118             future.awaitUninterruptibly();
119             buf.append("1");
120             try {
121                 future.getSession().closeNow();
122                 fail();
123             } catch (RuntimeIoException e) {
124                 // Signifies a successful test execution
125                 assertTrue(true);
126             }
127             assertEquals("1", buf.toString());
128         } finally {
129             connector.dispose();
130         }
131     }
132 
133     /**
134      * Test to make sure the SessionCallback gets invoked before IoHandler.sessionCreated.
135      * 
136      * @throws Exception is the test failed
137      */
138     @Test
139     public void testSessionCallbackInvocation() throws Exception {
140         final int callbackInvoked = 0;
141         final int sessionCreatedInvoked = 1;
142         final int sessionCreatedInvokedBeforeCallback = 2;
143         final boolean[] assertions = { false, false, false };
144         final CountDownLatch latch = new CountDownLatch(2);
145         final ConnectFuture[] callbackFuture = new ConnectFuture[1];
146 
147         int port = AvailablePortFinder.getNextAvailable(1025);
148 
149         IoAcceptor acceptor = createAcceptor();
150         IoConnector connector = createConnector();
151 
152         try {
153             acceptor.setHandler(new IoHandlerAdapter());
154             InetSocketAddress address = new InetSocketAddress(port);
155             acceptor.bind(address);
156 
157             connector.setHandler(new IoHandlerAdapter() {
158                 @Override
159                 public void sessionCreated(IoSession session) throws Exception {
160                     assertions[sessionCreatedInvoked] = true;
161                     assertions[sessionCreatedInvokedBeforeCallback] = !assertions[callbackInvoked];
162                     latch.countDown();
163                 }
164             });
165 
166             ConnectFuture future = connector.connect(new InetSocketAddress(InetAddress.getByName(null), port),
167                     new IoSessionInitializer<ConnectFuture>() {
168                         public void initializeSession(IoSession session, ConnectFuture future) {
169                             assertions[callbackInvoked] = true;
170                             callbackFuture[0] = future;
171                             latch.countDown();
172                         }
173                     });
174 
175             assertTrue("Timed out waiting for callback and IoHandler.sessionCreated to be invoked",
176                     latch.await(5, TimeUnit.SECONDS));
177             assertTrue("Callback was not invoked", assertions[callbackInvoked]);
178             assertTrue("IoHandler.sessionCreated was not invoked", assertions[sessionCreatedInvoked]);
179             assertFalse("IoHandler.sessionCreated was invoked before session callback",
180                     assertions[sessionCreatedInvokedBeforeCallback]);
181             assertSame("Callback future should have been same future as returned by connect", future, callbackFuture[0]);
182         } finally {
183             try {
184                 connector.dispose();
185             } finally {
186                 acceptor.dispose();
187             }
188         }
189     }
190 }