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