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