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.transport.nio;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.io.IOException;
27  import java.net.Socket;
28  import java.nio.ByteBuffer;
29  import java.util.concurrent.CountDownLatch;
30  import java.util.concurrent.TimeUnit;
31  
32  import org.apache.mina.api.AbstractIoFilter;
33  import org.apache.mina.api.IoSession;
34  import org.apache.mina.filterchain.ReadFilterChainController;
35  import org.apache.mina.filterchain.WriteFilterChainController;
36  import org.apache.mina.session.WriteRequest;
37  import org.apache.mina.transport.nio.FixedSelectorLoopPool;
38  import org.apache.mina.transport.nio.NioTcpServer;
39  import org.apache.mina.transport.nio.SelectorLoopPool;
40  import org.junit.Test;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  /**
45   * This class test the event dispatching of {@link NioTcpServer}.
46   * 
47   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
48   */
49  public class NioTcpServerFilterEventTest {
50  
51      private static final Logger LOG = LoggerFactory.getLogger(NioTcpServerFilterEventTest.class);
52  
53      private static final int CLIENT_COUNT = 100;
54  
55      private static final int WAIT_TIME = 30000;
56  
57      private final CountDownLatch msgSentLatch = new CountDownLatch(CLIENT_COUNT);
58  
59      private final CountDownLatch msgReadLatch = new CountDownLatch(CLIENT_COUNT);
60  
61      private final CountDownLatch openLatch = new CountDownLatch(CLIENT_COUNT);
62  
63      private final CountDownLatch closedLatch = new CountDownLatch(CLIENT_COUNT);
64  
65      @Test
66      public void generate_all_kind_of_server_event() throws IOException, InterruptedException {
67          final NioTcpServer server = new NioTcpServer();
68          server.setFilters(new MyCodec(), new Handler());
69          server.bind(0);
70          // warm up
71          Thread.sleep(100);
72  
73          long t0 = System.currentTimeMillis();
74          final int port = server.getServerSocketChannel().socket().getLocalPort();
75  
76          final Socket[] clients = new Socket[CLIENT_COUNT];
77  
78          // connect some clients
79          for (int i = 0; i < CLIENT_COUNT; i++) {
80              // System.out.println("Creation client " + i);
81              try {
82                  clients[i] = new Socket("127.0.0.1", port);
83              } catch (Exception e) {
84                  e.printStackTrace();
85                  System.out.println("Creation client " + i + " failed");
86              }
87          }
88  
89          // does the session open message was fired ?
90          assertTrue(openLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
91  
92          // write some messages
93          for (int i = 0; i < CLIENT_COUNT; i++) {
94              clients[i].getOutputStream().write(("test:" + i).getBytes());
95              clients[i].getOutputStream().flush();
96          }
97  
98          // test is message was received by the server
99          assertTrue(msgReadLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
100 
101         // does response was wrote and sent ?
102         assertTrue(msgSentLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
103 
104         // read the echos
105         final byte[] buffer = new byte[1024];
106 
107         for (int i = 0; i < CLIENT_COUNT; i++) {
108             final int bytes = clients[i].getInputStream().read(buffer);
109             final String text = new String(buffer, 0, bytes);
110             assertEquals("test:" + i, text);
111         }
112 
113         // close the session
114         assertEquals(CLIENT_COUNT, closedLatch.getCount());
115         for (int i = 0; i < CLIENT_COUNT; i++) {
116             clients[i].close();
117         }
118 
119         // does the session close event was fired ?
120         assertTrue(closedLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
121 
122         long t1 = System.currentTimeMillis();
123 
124         System.out.println("Delta = " + (t1 - t0));
125 
126         server.unbind();
127     }
128 
129     /**
130      * A test that creates 50 clients, each one of them writing one message. We will check that for each client we
131      * correctly process the sessionOpened, messageReceived, messageSent and sessionClosed events. We use only one
132      * selector to process all the OP events.
133      */
134     @Test
135     public void generateAllKindOfServerEventOneSelector() throws IOException, InterruptedException {
136         SelectorLoopPool selectorLoopPool = new FixedSelectorLoopPool("Server", 1);
137         final NioTcpServer server = new NioTcpServer(selectorLoopPool.getSelectorLoop(), selectorLoopPool, null);
138         server.setFilters(new MyCodec(), new Handler());
139         server.bind(0);
140         // warm up
141         Thread.sleep(100);
142 
143         long t0 = System.currentTimeMillis();
144         final int port = server.getServerSocketChannel().socket().getLocalPort();
145 
146         final Socket[] clients = new Socket[CLIENT_COUNT];
147 
148         // connect some clients
149         for (int i = 0; i < CLIENT_COUNT; i++) {
150             // System.out.println("Creation client 2 " + i);
151             clients[i] = new Socket("127.0.0.1", port);
152         }
153 
154         // does the session open message was fired ?
155         assertTrue(openLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
156 
157         // write some messages
158         for (int i = 0; i < CLIENT_COUNT; i++) {
159             clients[i].getOutputStream().write(("test:" + i).getBytes());
160             clients[i].getOutputStream().flush();
161         }
162 
163         // test is message was received by the server
164         assertTrue(msgReadLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
165 
166         // does response was wrote and sent ?
167         assertTrue(msgSentLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
168 
169         // read the echos
170         final byte[] buffer = new byte[1024];
171 
172         for (int i = 0; i < CLIENT_COUNT; i++) {
173             final int bytes = clients[i].getInputStream().read(buffer);
174             final String text = new String(buffer, 0, bytes);
175             assertEquals("test:" + i, text);
176         }
177 
178         // close the session
179         assertEquals(CLIENT_COUNT, closedLatch.getCount());
180         for (int i = 0; i < CLIENT_COUNT; i++) {
181             clients[i].close();
182         }
183 
184         // does the session close event was fired ?
185         assertTrue(closedLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
186 
187         long t1 = System.currentTimeMillis();
188 
189         System.out.println("Delta = " + (t1 - t0));
190 
191         server.unbind();
192     }
193 
194     private class MyCodec extends AbstractIoFilter {
195 
196         @Override
197         public void messageReceived(final IoSession session, final Object message,
198                 final ReadFilterChainController controller) {
199             if (message instanceof ByteBuffer) {
200                 final ByteBuffer in = (ByteBuffer) message;
201                 final byte[] buffer = new byte[in.remaining()];
202                 in.get(buffer);
203                 controller.callReadNextFilter(new String(buffer));
204             } else {
205                 fail();
206             }
207         }
208 
209         @Override
210         public void messageWriting(IoSession session, WriteRequest writeRequest, WriteFilterChainController controller) {
211             writeRequest.setMessage(ByteBuffer.wrap(writeRequest.getMessage().toString().getBytes()));
212             controller.callWriteNextFilter(writeRequest);
213         }
214     }
215 
216     private class Handler extends AbstractIoFilter {
217 
218         @Override
219         public void sessionOpened(final IoSession session) {
220             LOG.info("** session open");
221             openLatch.countDown();
222         }
223 
224         @Override
225         public void sessionClosed(final IoSession session) {
226             LOG.info("** session closed");
227             closedLatch.countDown();
228         }
229 
230         @Override
231         public void messageReceived(final IoSession session, final Object message,
232                 final ReadFilterChainController controller) {
233             LOG.info("** message received {}", message);
234             msgReadLatch.countDown();
235             session.write(message.toString());
236         }
237 
238         @Override
239         public void messageSent(final IoSession session, final Object message) {
240             LOG.info("** message sent {}", message);
241             msgSentLatch.countDown();
242         }
243     }
244 }