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.filter.keepalive;
21  
22  import static org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler.EXCEPTION;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertNotNull;
25  
26  import java.net.InetAddress;
27  import java.net.InetSocketAddress;
28  import java.util.concurrent.atomic.AtomicBoolean;
29  
30  import org.apache.mina.core.buffer.IoBuffer;
31  import org.apache.mina.core.future.ConnectFuture;
32  import org.apache.mina.core.service.IoHandlerAdapter;
33  import org.apache.mina.core.session.IdleStatus;
34  import org.apache.mina.core.session.IoSession;
35  import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
36  import org.apache.mina.transport.socket.nio.NioSocketConnector;
37  import org.junit.After;
38  import org.junit.Before;
39  import org.junit.Test;
40  
41  /**
42   * Tests {@link KeepAliveFilter} used by the connector with different
43   * interested {@link IdleStatus}es.
44   *
45   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
46   */
47  public class KeepAliveFilterTest {
48      // Constants -----------------------------------------------------
49      static final IoBuffer PING = IoBuffer.wrap(new byte[] { 1 });
50  
51      static final IoBuffer PONG = IoBuffer.wrap(new byte[] { 2 });
52  
53      private static final int INTERVAL = 2;
54  
55      private static final int TIMEOUT = 1;
56  
57      private int port;
58  
59      private NioSocketAcceptor acceptor;
60  
61      @Before
62      public void setUp() throws Exception {
63          acceptor = new NioSocketAcceptor();
64          KeepAliveMessageFactory factory = new ServerFactory();
65          KeepAliveFilter filter = new KeepAliveFilter(factory, IdleStatus.BOTH_IDLE);
66          acceptor.getFilterChain().addLast("keep-alive", filter);
67          acceptor.setHandler(new IoHandlerAdapter());
68          acceptor.setDefaultLocalAddress(new InetSocketAddress(0));
69          acceptor.bind();
70          port = acceptor.getLocalAddress().getPort();
71      }
72  
73      @After
74      public void tearDown() throws Exception {
75          acceptor.unbind();
76          acceptor.dispose();
77      }
78  
79      @Test
80      public void testKeepAliveFilterForReaderIdle() throws Exception {
81          keepAliveFilterForIdleStatus(IdleStatus.READER_IDLE);
82      }
83  
84      @Test
85      public void testKeepAliveFilterForBothIdle() throws Exception {
86          keepAliveFilterForIdleStatus(IdleStatus.BOTH_IDLE);
87      }
88  
89      @Test
90      public void testKeepAliveFilterForWriterIdle() throws Exception {
91          keepAliveFilterForIdleStatus(IdleStatus.WRITER_IDLE);
92      }
93  
94      // Package protected ---------------------------------------------
95  
96      // Protected -----------------------------------------------------
97  
98      // Private -------------------------------------------------------
99  
100     private void keepAliveFilterForIdleStatus(IdleStatus status) throws Exception {
101         NioSocketConnector connector = new NioSocketConnector();
102         KeepAliveFilter filter = new KeepAliveFilter(new ClientFactory(), status, EXCEPTION, INTERVAL, TIMEOUT);
103         filter.setForwardEvent(true);
104         connector.getFilterChain().addLast("keep-alive", filter);
105 
106         final AtomicBoolean gotException = new AtomicBoolean(false);
107         connector.setHandler(new IoHandlerAdapter() {
108             @Override
109             public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
110                 //cause.printStackTrace();
111                 gotException.set(true);
112             }
113 
114             @Override
115             public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
116                 // Do nothing
117             }
118         });
119 
120         ConnectFuture future = connector.connect(new InetSocketAddress(InetAddress.getByName(null), port)).awaitUninterruptibly();
121         IoSession session = future.getSession();
122         assertNotNull(session);
123 
124         Thread.sleep((INTERVAL + TIMEOUT + 1) * 1000);
125 
126         assertFalse("got an exception on the client", gotException.get());
127 
128         session.closeNow();
129         connector.dispose();
130     }
131 
132     static boolean checkRequest(IoBuffer message) {
133         IoBuffer buff = message;
134         boolean check = buff.get() == 1;
135         buff.rewind();
136         return check;
137     }
138 
139     static boolean checkResponse(IoBuffer message) {
140         IoBuffer buff = message;
141         boolean check = buff.get() == 2;
142         buff.rewind();
143         return check;
144     }
145 
146     // Inner classes -------------------------------------------------
147     private final class ServerFactory implements KeepAliveMessageFactory {
148         /**
149          * Default constructor
150          */
151         public ServerFactory() {
152             super();
153         }
154 
155         public Object getRequest(IoSession session) {
156             return null;
157         }
158 
159         public Object getResponse(IoSession session, Object request) {
160             return PONG.duplicate();
161         }
162 
163         public boolean isRequest(IoSession session, Object message) {
164             if (message instanceof IoBuffer) {
165                 return checkRequest((IoBuffer) message);
166             }
167             return false;
168         }
169 
170         public boolean isResponse(IoSession session, Object message) {
171             if (message instanceof IoBuffer) {
172                 return checkResponse((IoBuffer) message);
173             }
174             return false;
175         }
176     }
177 
178     private final class ClientFactory implements KeepAliveMessageFactory {
179         /**
180          * Default constructor
181          */
182         public ClientFactory() {
183             super();
184         }
185 
186         public Object getRequest(IoSession session) {
187             return PING.duplicate();
188         }
189 
190         public Object getResponse(IoSession session, Object request) {
191             return null;
192         }
193 
194         public boolean isRequest(IoSession session, Object message) {
195             if (message instanceof IoBuffer) {
196                 return checkRequest((IoBuffer) message);
197             }
198             return false;
199         }
200 
201         public boolean isResponse(IoSession session, Object message) {
202             if (message instanceof IoBuffer) {
203                 return checkResponse((IoBuffer) message);
204             }
205             return false;
206         }
207     }
208 }