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