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.*;
23  
24  import java.io.IOException;
25  import java.net.InetSocketAddress;
26  import java.net.ServerSocket;
27  import java.net.Socket;
28  import java.nio.ByteBuffer;
29  import java.util.ArrayList;
30  import java.util.List;
31  import java.util.concurrent.CountDownLatch;
32  import java.util.concurrent.ExecutionException;
33  import java.util.concurrent.TimeUnit;
34  
35  import org.apache.mina.api.AbstractIoFilter;
36  import org.apache.mina.api.IoFuture;
37  import org.apache.mina.api.IoSession;
38  import org.apache.mina.filterchain.ReadFilterChainController;
39  import org.apache.mina.filterchain.WriteFilterChainController;
40  import org.apache.mina.session.WriteRequest;
41  import org.apache.mina.transport.nio.NioTcpClient;
42  import org.junit.Test;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  /**
47   * This class test the event dispatching of {@link NioTcpClient}.
48   * 
49   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
50   */
51  public class NioTcpClientFilterEventTest {
52  
53      private static final Logger LOG = LoggerFactory.getLogger(NioTcpClientFilterEventTest.class);
54  
55      private static final int CLIENT_COUNT = 10;
56  
57      private static final int WAIT_TIME = 30000;
58  
59      private final CountDownLatch msgSentLatch = new CountDownLatch(CLIENT_COUNT);
60  
61      private final CountDownLatch msgReadLatch = new CountDownLatch(CLIENT_COUNT);
62  
63      private final CountDownLatch openLatch = new CountDownLatch(CLIENT_COUNT);
64  
65      private final CountDownLatch closedLatch = new CountDownLatch(CLIENT_COUNT);
66  
67      /**
68       * Create an old IO server and use a bunch of MINA client on it. Test if the events occurs correctly in the
69       * different IoFilters.
70       */
71      @Test
72      public void generate_all_kind_of_client_event() throws IOException, InterruptedException, ExecutionException {
73          NioTcpClient client = new NioTcpClient();
74          client.setFilters(new MyCodec(), new Handler());
75  
76          ServerSocket serverSocket = new ServerSocket();
77          serverSocket.bind(null);
78          int port = serverSocket.getLocalPort();
79  
80          // warm up
81          Thread.sleep(100);
82          final long t0 = System.currentTimeMillis();
83  
84          // now connect the clients
85  
86          List<IoFuture<IoSession>> cf = new ArrayList<IoFuture<IoSession>>();
87          for (int i = 0; i < CLIENT_COUNT; i++) {
88              cf.add(client.connect(new InetSocketAddress("localhost", port)));
89          }
90  
91          Socket[] clientSockets = new Socket[CLIENT_COUNT];
92          for (int i = 0; i < CLIENT_COUNT; i++) {
93              clientSockets[i] = serverSocket.accept();
94          }
95  
96          // does the session open message was fired ?
97          assertTrue(openLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
98  
99          // gather sessions from futures
100         IoSession[] sessions = new IoSession[CLIENT_COUNT];
101         for (int i = 0; i < CLIENT_COUNT; i++) {
102             sessions[i] = cf.get(i).get();
103             assertNotNull(sessions[i]);
104         }
105 
106         // write some messages
107         for (int i = 0; i < CLIENT_COUNT; i++) {
108             clientSockets[i].getOutputStream().write(("test:" + i).getBytes());
109             clientSockets[i].getOutputStream().flush();
110         }
111 
112         // test is message was received by the server
113         assertTrue(msgReadLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
114 
115         // does response was wrote and sent ?
116         assertTrue(msgSentLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
117 
118         // read the echos
119         final byte[] buffer = new byte[1024];
120 
121         for (int i = 0; i < CLIENT_COUNT; i++) {
122             final int bytes = clientSockets[i].getInputStream().read(buffer);
123             final String text = new String(buffer, 0, bytes);
124             assertEquals("test:" + i, text);
125         }
126 
127         // close the session
128         assertEquals(CLIENT_COUNT, closedLatch.getCount());
129         for (int i = 0; i < CLIENT_COUNT; i++) {
130             clientSockets[i].close();
131         }
132 
133         // does the session close event was fired ?
134         assertTrue(closedLatch.await(WAIT_TIME, TimeUnit.MILLISECONDS));
135 
136         long t1 = System.currentTimeMillis();
137 
138         System.out.println("Delta = " + (t1 - t0));
139 
140         serverSocket.close();
141     }
142 
143     private class MyCodec extends AbstractIoFilter {
144 
145         @Override
146         public void messageReceived(final IoSession session, final Object message,
147                 final ReadFilterChainController controller) {
148             if (message instanceof ByteBuffer) {
149                 final ByteBuffer in = (ByteBuffer) message;
150                 final byte[] buffer = new byte[in.remaining()];
151                 in.get(buffer);
152                 controller.callReadNextFilter(new String(buffer));
153             } else {
154                 fail();
155             }
156         }
157 
158         @Override
159         public void messageWriting(IoSession session, WriteRequest writeRequest, WriteFilterChainController controller) {
160             writeRequest.setMessage(ByteBuffer.wrap(writeRequest.getMessage().toString().getBytes()));
161             controller.callWriteNextFilter(writeRequest);
162         }
163     }
164 
165     private class Handler extends AbstractIoFilter {
166 
167         @Override
168         public void sessionOpened(final IoSession session) {
169             LOG.info("** session open");
170             openLatch.countDown();
171         }
172 
173         @Override
174         public void sessionClosed(final IoSession session) {
175             LOG.info("** session closed");
176             closedLatch.countDown();
177         }
178 
179         @Override
180         public void messageReceived(final IoSession session, final Object message,
181                 final ReadFilterChainController controller) {
182             LOG.info("** message received {}", message);
183             msgReadLatch.countDown();
184             session.write(message.toString());
185         }
186 
187         @Override
188         public void messageSent(final IoSession session, final Object message) {
189             LOG.info("** message sent {}", message);
190             msgSentLatch.countDown();
191         }
192     }
193 }