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