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.InetSocketAddress;
29  import java.util.concurrent.CountDownLatch;
30  import java.util.concurrent.TimeUnit;
31  import java.util.regex.Pattern;
32  
33  import org.apache.mina.core.RuntimeIoException;
34  import org.apache.mina.core.future.ConnectFuture;
35  import org.apache.mina.core.service.IoAcceptor;
36  import org.apache.mina.core.service.IoConnector;
37  import org.apache.mina.core.service.IoHandlerAdapter;
38  import org.apache.mina.core.session.IoSession;
39  import org.apache.mina.core.session.IoSessionInitializer;
40  import org.apache.mina.util.AvailablePortFinder;
41  import org.junit.Test;
42  
43  /**
44   * Tests a generic {@link IoConnector}.
45   *
46   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
47   */
48  public abstract class AbstractConnectorTest {
49  
50      protected abstract IoAcceptor createAcceptor();
51  
52      protected abstract IoConnector createConnector();
53  
54      @Test
55      public void testConnectFutureSuccessTiming() throws Exception {
56          int port = AvailablePortFinder.getNextAvailable(1025);
57          IoAcceptor acceptor = createAcceptor();
58          acceptor.setHandler(new IoHandlerAdapter());
59          acceptor.bind(new InetSocketAddress(port));
60  
61          try {
62              final StringBuffer buf = new StringBuffer();
63              IoConnector connector = createConnector();
64              connector.setHandler(new IoHandlerAdapter() {
65                  @Override
66                  public void sessionCreated(IoSession session) {
67                      buf.append("1");
68                  }
69  
70                  @Override
71                  public void sessionOpened(IoSession session) {
72                      buf.append("2");
73                  }
74  
75                  @Override
76                  public void exceptionCaught(IoSession session, Throwable cause) {
77                      buf.append("X");
78                  }
79              });
80              ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
81              future.awaitUninterruptibly();
82              buf.append("3");
83              future.getSession().close(true);
84              // sessionCreated() will fire before the connect future completes
85              // but sessionOpened() may not
86              assertTrue(Pattern.matches("12?32?", buf.toString()));
87          } finally {
88              acceptor.dispose();
89          }
90      }
91  
92      @Test
93      public void testConnectFutureFailureTiming() throws Exception {
94          int port = AvailablePortFinder.getNextAvailable(1025);
95          final StringBuffer buf = new StringBuffer();
96  
97          IoConnector connector = createConnector();
98          connector.setHandler(new IoHandlerAdapter() {
99              @Override
100             public void sessionCreated(IoSession session) {
101                 buf.append("X");
102             }
103 
104             @Override
105             public void sessionOpened(IoSession session) {
106                 buf.append("Y");
107             }
108 
109             @Override
110             public void exceptionCaught(IoSession session, Throwable cause) {
111                 buf.append("Z");
112             }
113         });
114 
115         try {
116             ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
117             future.awaitUninterruptibly();
118             buf.append("1");
119             try {
120                 future.getSession().close(true);
121                 fail();
122             } catch (RuntimeIoException e) {
123                 // Signifies a successful test execution
124                 assertTrue(true);
125             }
126             assertEquals("1", buf.toString());
127         } finally {
128             connector.dispose();
129         }
130     }
131 
132     /**
133      * Test to make sure the SessionCallback gets invoked before IoHandler.sessionCreated.
134      */
135     @Test
136     public void testSessionCallbackInvocation() throws Exception {
137         final int callbackInvoked = 0;
138         final int sessionCreatedInvoked = 1;
139         final int sessionCreatedInvokedBeforeCallback = 2;
140         final boolean[] assertions = { false, false, false };
141         final CountDownLatch latch = new CountDownLatch(2);
142         final ConnectFuture[] callbackFuture = new ConnectFuture[1];
143 
144         int port = AvailablePortFinder.getNextAvailable(1025);
145 
146         IoAcceptor acceptor = createAcceptor();
147         IoConnector connector = createConnector();
148 
149         try {
150             acceptor.setHandler(new IoHandlerAdapter());
151             InetSocketAddress address = new InetSocketAddress(port);
152             acceptor.bind(address);
153 
154             connector.setHandler(new IoHandlerAdapter() {
155                 @Override
156                 public void sessionCreated(IoSession session) throws Exception {
157                     assertions[sessionCreatedInvoked] = true;
158                     assertions[sessionCreatedInvokedBeforeCallback] = !assertions[callbackInvoked];
159                     latch.countDown();
160                 }
161             });
162 
163             ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", port),
164                     new IoSessionInitializer<ConnectFuture>() {
165                         public void initializeSession(IoSession session, ConnectFuture future) {
166                             assertions[callbackInvoked] = true;
167                             callbackFuture[0] = future;
168                             latch.countDown();
169                         }
170                     });
171 
172             assertTrue("Timed out waiting for callback and IoHandler.sessionCreated to be invoked",
173                     latch.await(5, TimeUnit.SECONDS));
174             assertTrue("Callback was not invoked", assertions[callbackInvoked]);
175             assertTrue("IoHandler.sessionCreated was not invoked", assertions[sessionCreatedInvoked]);
176             assertFalse("IoHandler.sessionCreated was invoked before session callback",
177                     assertions[sessionCreatedInvokedBeforeCallback]);
178             assertSame("Callback future should have been same future as returned by connect", future, callbackFuture[0]);
179         } finally {
180             try {
181                 connector.dispose();
182             } finally {
183                 acceptor.dispose();
184             }
185         }
186     }
187 }