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      protected abstract IoConnector createConnector();
52  
53      @Test
54      public void testConnectFutureSuccessTiming() throws Exception {
55          int port = AvailablePortFinder.getNextAvailable(1025);
56          IoAcceptor acceptor = createAcceptor();
57          acceptor.setHandler(new IoHandlerAdapter());
58          acceptor.bind(new InetSocketAddress(port));
59  
60          try {
61              final StringBuffer buf = new StringBuffer();
62              IoConnector connector = createConnector();
63              connector.setHandler(new IoHandlerAdapter() {
64                  @Override
65                  public void sessionCreated(IoSession session) {
66                      buf.append("1");
67                  }
68  
69                  @Override
70                  public void sessionOpened(IoSession session) {
71                      buf.append("2");
72                  }
73  
74                  @Override
75                  public void exceptionCaught(IoSession session, Throwable cause) {
76                      buf.append("X");
77                  }
78              });
79              ConnectFuture future = connector.connect(new InetSocketAddress(
80                      "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(
117                     "localhost", port));
118             future.awaitUninterruptibly();
119             buf.append("1");
120             try {
121                 future.getSession().close(true);
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     @Test
137     public void testSessionCallbackInvocation() throws Exception {
138         final int callbackInvoked = 0;
139         final int sessionCreatedInvoked = 1;
140         final int sessionCreatedInvokedBeforeCallback = 2;
141         final boolean[] assertions = {false, false, false};
142         final CountDownLatch latch = new CountDownLatch(2);
143         final ConnectFuture[] callbackFuture = new ConnectFuture[1];
144         
145         int port = AvailablePortFinder.getNextAvailable(1025);
146 
147         IoAcceptor acceptor = createAcceptor();
148         IoConnector connector = createConnector();
149 
150         try {
151             acceptor.setHandler(new IoHandlerAdapter());
152             InetSocketAddress address = new InetSocketAddress(port);
153             acceptor.bind(address);
154     
155             connector.setHandler(new IoHandlerAdapter() {
156                @Override
157                 public void sessionCreated(IoSession session) throws Exception {
158                        assertions[sessionCreatedInvoked] = true;
159                        assertions[sessionCreatedInvokedBeforeCallback] = !assertions[callbackInvoked];
160                        latch.countDown();
161                 } 
162             });
163         
164             ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", port), 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", latch.await(5, TimeUnit.SECONDS));
173             assertTrue("Callback was not invoked", assertions[callbackInvoked]);
174             assertTrue("IoHandler.sessionCreated was not invoked", assertions[sessionCreatedInvoked]);
175             assertFalse("IoHandler.sessionCreated was invoked before session callback", assertions[sessionCreatedInvokedBeforeCallback]);
176             assertSame("Callback future should have been same future as returned by connect", future, callbackFuture[0]);
177         } finally {
178             try {
179                 connector.dispose();
180             } finally {
181                 acceptor.dispose();
182             }
183         }
184     }
185 }