1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import java.io.IOException;
30 import java.net.SocketAddress;
31 import java.util.Collection;
32
33 import org.apache.mina.core.buffer.IoBuffer;
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.IdleStatus;
39 import org.apache.mina.core.session.IoSession;
40 import org.apache.mina.transport.socket.DatagramAcceptor;
41 import org.apache.mina.transport.socket.DatagramSessionConfig;
42 import org.apache.mina.transport.socket.SocketAcceptor;
43 import org.apache.mina.transport.socket.SocketSessionConfig;
44 import org.apache.mina.util.AvailablePortFinder;
45 import org.junit.After;
46 import org.junit.Assert;
47 import org.junit.Ignore;
48 import org.junit.Test;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52
53
54
55
56
57 public abstract class AbstractBindTest {
58 protected final IoAcceptor acceptor;
59
60 protected int port;
61
62 public AbstractBindTest(IoAcceptor acceptor) {
63 this.acceptor = acceptor;
64 }
65
66 protected abstract SocketAddress createSocketAddress(int port);
67
68 protected abstract int getPort(SocketAddress address);
69
70 protected abstract IoConnector newConnector();
71
72 protected void bind(boolean reuseAddress) throws IOException {
73 acceptor.setHandler(new EchoProtocolHandler());
74
75 setReuseAddress(reuseAddress);
76
77
78 boolean socketBound = false;
79
80
81
82
83 port = AvailablePortFinder.getNextAvailable();
84 socketBound = false;
85 try {
86 acceptor.setDefaultLocalAddress(createSocketAddress(port));
87 acceptor.bind();
88 socketBound = true;
89 } catch (IOException e) {
90
91 }
92
93
94 if (!socketBound) {
95 throw new IOException("Cannot bind any test port.");
96 }
97
98
99 }
100
101 private void setReuseAddress(boolean reuseAddress) {
102 if (acceptor instanceof DatagramAcceptor) {
103 ((DatagramSessionConfig) acceptor.getSessionConfig()).setReuseAddress(reuseAddress);
104 } else if (acceptor instanceof SocketAcceptor) {
105 ((SocketAcceptor) acceptor).setReuseAddress(reuseAddress);
106 }
107 }
108
109 @After
110 public void tearDown() {
111 try {
112 acceptor.dispose();
113 } catch (Exception e) {
114
115 }
116
117 acceptor.setDefaultLocalAddress(null);
118 }
119
120 @Test
121 public void testAnonymousBind() throws Exception {
122 acceptor.setHandler(new IoHandlerAdapter());
123 acceptor.setDefaultLocalAddress(null);
124 acceptor.bind();
125 assertNotNull(acceptor.getLocalAddress());
126 acceptor.unbind(acceptor.getLocalAddress());
127 assertNull(acceptor.getLocalAddress());
128 acceptor.setDefaultLocalAddress(createSocketAddress(0));
129 acceptor.bind();
130 assertNotNull(acceptor.getLocalAddress());
131 assertTrue(getPort(acceptor.getLocalAddress()) != 0);
132 acceptor.unbind(acceptor.getLocalAddress());
133 }
134
135 @Test
136 public void testDuplicateBind() throws IOException {
137 bind(false);
138
139 try {
140 acceptor.bind();
141 fail("Exception is not thrown");
142 } catch (Exception e) {
143
144 assertTrue(true);
145 }
146 }
147
148 @Test
149 public void testDuplicateUnbind() throws IOException {
150 bind(false);
151
152
153 acceptor.unbind();
154
155
156 acceptor.unbind();
157 }
158
159 @Test
160 public void testManyTimes() throws IOException, InterruptedException {
161 bind(true);
162
163 for (int i = 0; i < 1024; i++) {
164 Assert.assertTrue("Bound addresses is empty", acceptor.getLocalAddresses().size() > 0);
165 acceptor.unbind();
166 Thread.sleep(1);
167 Assert.assertTrue("Bound addresses is not empty", acceptor.getLocalAddresses().size() == 0);
168 acceptor.bind();
169 }
170
171 acceptor.unbind();
172 }
173
174 @Test
175 public void testUnbindDisconnectsClients() throws Exception {
176 bind(true);
177 IoConnector connector = newConnector();
178 IoSession[] sessions = new IoSession[5];
179 connector.setHandler(new IoHandlerAdapter());
180 for (int i = 0; i < sessions.length; i++) {
181 ConnectFuture future = connector.connect(createSocketAddress(port));
182 future.awaitUninterruptibly();
183 sessions[i] = future.getSession();
184 assertTrue(sessions[i].isConnected());
185 assertTrue(sessions[i].write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
186 }
187
188
189 Thread.sleep(500);
190
191 Collection<IoSession> managedSessions = acceptor.getManagedSessions().values();
192 assertEquals(5, managedSessions.size());
193
194 acceptor.unbind();
195
196
197 Thread.sleep(500);
198
199 assertEquals(0, managedSessions.size());
200 for (IoSession element : managedSessions) {
201 assertFalse(element.isConnected());
202 }
203 }
204
205 @Test
206 public void testUnbindResume() throws Exception {
207 bind(true);
208 IoConnector connector = newConnector();
209 IoSession session = null;
210 connector.setHandler(new IoHandlerAdapter());
211
212 ConnectFuture future = connector.connect(createSocketAddress(port));
213 future.awaitUninterruptibly();
214 session = future.getSession();
215 assertTrue(session.isConnected());
216 assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
217
218
219 Thread.sleep(500);
220
221 Collection<IoSession> managedSession = acceptor.getManagedSessions().values();
222 assertEquals(1, managedSession.size());
223
224 acceptor.unbind();
225
226
227 Thread.sleep(500);
228
229 assertEquals(0, managedSession.size());
230 for (IoSession element : managedSession) {
231 assertFalse(element.isConnected());
232 }
233
234
235 bind(true);
236
237
238 future = connector.connect(createSocketAddress(port));
239 future.awaitUninterruptibly();
240 session = future.getSession();
241 assertTrue(session.isConnected());
242 assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
243
244
245 Thread.sleep(500);
246
247 managedSession = acceptor.getManagedSessions().values();
248 assertEquals(1, managedSession.size());
249 }
250
251 @Test
252 @Ignore
253 public void testRegressively() throws IOException {
254 setReuseAddress(true);
255
256 SocketAddress addr = createSocketAddress(port);
257 EchoProtocolHandler handler = new EchoProtocolHandler();
258 acceptor.setDefaultLocalAddress(addr);
259 acceptor.setHandler(handler);
260 for (int i = 0; i < 1048576; i++) {
261 acceptor.bind();
262 acceptor.unbind();
263 }
264 bind(false);
265 }
266
267 private static class EchoProtocolHandler extends IoHandlerAdapter {
268 private static final Logger LOG = LoggerFactory.getLogger(EchoProtocolHandler.class);
269
270
271
272
273 public EchoProtocolHandler() {
274 super();
275 }
276
277 @Override
278 public void sessionCreated(IoSession session) {
279 if (session.getConfig() instanceof SocketSessionConfig) {
280 ((SocketSessionConfig) session.getConfig()).setReceiveBufferSize(2048);
281 }
282
283 session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
284 }
285
286 @Override
287 public void sessionIdle(IoSession session, IdleStatus status) {
288 LOG.info("*** IDLE #" + session.getIdleCount(IdleStatus.BOTH_IDLE) + " ***");
289 }
290
291 @Override
292 public void exceptionCaught(IoSession session, Throwable cause) {
293
294 session.closeNow();
295 }
296
297 @Override
298 public void messageReceived(IoSession session, Object message) throws Exception {
299 if (!(message instanceof IoBuffer)) {
300 return;
301 }
302
303 IoBuffer rb = (IoBuffer) message;
304
305 IoBuffer wb = rb.duplicate();
306 session.write(wb);
307 }
308 }
309 }