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.core;
21  
22  import org.apache.mina.core.filterchain.DefaultIoFilterChain;
23  import org.apache.mina.core.filterchain.IoFilter;
24  import org.apache.mina.core.filterchain.IoFilterAdapter;
25  import org.apache.mina.core.filterchain.IoFilterChain;
26  import org.apache.mina.core.filterchain.IoFilterChain.Entry;
27  import org.apache.mina.core.service.IoHandler;
28  import org.apache.mina.core.service.IoHandlerAdapter;
29  import org.apache.mina.core.session.DummySession;
30  import org.apache.mina.core.session.IdleStatus;
31  import org.apache.mina.core.session.IoSession;
32  import org.apache.mina.core.write.DefaultWriteRequest;
33  import org.apache.mina.core.write.WriteRequest;
34  import org.apache.mina.filter.util.NoopFilter;
35  import org.junit.After;
36  import org.junit.Before;
37  import org.junit.Test;
38  
39  import static org.junit.Assert.assertEquals;
40  import static org.junit.Assert.assertSame;
41  
42  /**
43   * Tests {@link DefaultIoFilterChain}.
44   *
45   * @author The Apache MINA Project (dev@mina.apache.org)
46   * @version $Rev: 751473 $, $Date: 2009-03-08 18:22:14 +0100 (Sun, 08 Mar 2009) $
47   */
48  public class IoFilterChainTest {
49      private DummySession session;
50      private IoFilterChain chain;
51      private String result;
52  
53      private final IoHandler handler = new IoHandlerAdapter() {
54          @Override
55          public void sessionCreated(IoSession session) {
56              result += "HS0";
57          }
58  
59          @Override
60          public void sessionOpened(IoSession session) {
61              result += "HSO";
62          }
63  
64          @Override
65          public void sessionClosed(IoSession session) {
66              result += "HSC";
67          }
68  
69          @Override
70          public void sessionIdle(IoSession session, IdleStatus status) {
71              result += "HSI";
72          }
73  
74          @Override
75          public void exceptionCaught(IoSession session, Throwable cause) {
76              result += "HEC";
77              if (cause.getClass() != Exception.class) {
78                  //cause.printStackTrace(System.out);
79              }
80          }
81  
82          @Override
83          public void messageReceived(IoSession session, Object message) {
84              result += "HMR";
85          }
86  
87          @Override
88          public void messageSent(IoSession session, Object message) {
89              result += "HMS";
90          }
91      };
92  
93      @Before
94      public void setUp() {
95          session = new DummySession();
96          session.setHandler(handler);
97          chain = session.getFilterChain();
98          result = "";
99      }
100 
101     @After
102     public void tearDown() {
103     }
104 
105     @Test
106     public void testAdd() throws Exception {
107         chain.addFirst("A", new EventOrderTestFilter('A'));
108         chain.addLast("B", new EventOrderTestFilter('A'));
109         chain.addFirst("C", new EventOrderTestFilter('A'));
110         chain.addLast("D", new EventOrderTestFilter('A'));
111         chain.addBefore("B", "E", new EventOrderTestFilter('A'));
112         chain.addBefore("C", "F", new EventOrderTestFilter('A'));
113         chain.addAfter("B", "G", new EventOrderTestFilter('A'));
114         chain.addAfter("D", "H", new EventOrderTestFilter('A'));
115 
116         String actual = "";
117         for (Entry e : chain.getAll()) {
118             actual += e.getName();
119         }
120 
121         assertEquals("FCAEBGDH", actual);
122     }
123 
124     @Test
125     public void testGet() throws Exception {
126         IoFilter filterA = new NoopFilter();
127         IoFilter filterB = new NoopFilter();
128         IoFilter filterC = new NoopFilter();
129         IoFilter filterD = new NoopFilter();
130 
131         chain.addFirst("A", filterA);
132         chain.addLast("B", filterB);
133         chain.addBefore("B", "C", filterC);
134         chain.addAfter("A", "D", filterD);
135 
136         assertSame(filterA, chain.get("A"));
137         assertSame(filterB, chain.get("B"));
138         assertSame(filterC, chain.get("C"));
139         assertSame(filterD, chain.get("D"));
140     }
141 
142     @Test
143     public void testRemove() throws Exception {
144         chain.addLast("A", new EventOrderTestFilter('A'));
145         chain.addLast("B", new EventOrderTestFilter('A'));
146         chain.addLast("C", new EventOrderTestFilter('A'));
147         chain.addLast("D", new EventOrderTestFilter('A'));
148         chain.addLast("E", new EventOrderTestFilter('A'));
149 
150         chain.remove("A");
151         chain.remove("E");
152         chain.remove("C");
153         chain.remove("B");
154         chain.remove("D");
155 
156         assertEquals(0, chain.getAll().size());
157     }
158 
159     @Test
160     public void testClear() throws Exception {
161         chain.addLast("A", new EventOrderTestFilter('A'));
162         chain.addLast("B", new EventOrderTestFilter('A'));
163         chain.addLast("C", new EventOrderTestFilter('A'));
164         chain.addLast("D", new EventOrderTestFilter('A'));
165         chain.addLast("E", new EventOrderTestFilter('A'));
166 
167         chain.clear();
168 
169         assertEquals(0, chain.getAll().size());
170     }
171 
172     @Test
173     public void testToString() throws Exception {
174         // When the chain is empty
175         assertEquals("{ empty }", chain.toString());
176 
177         // When there's one filter
178         chain.addLast("A", new IoFilterAdapter() {
179             @Override
180             public String toString() {
181                 return "B";
182             }
183         });
184         assertEquals("{ (A:B) }", chain.toString());
185 
186         // When there are two
187         chain.addLast("C", new IoFilterAdapter() {
188             @Override
189             public String toString() {
190                 return "D";
191             }
192         });
193         assertEquals("{ (A:B), (C:D) }", chain.toString());
194     }
195 
196     @Test
197     public void testDefault() {
198         run("HS0 HSO HMR HMS HSI HEC HSC");
199     }
200 
201     @Test
202     public void testChained() throws Exception {
203         chain.addLast("A", new EventOrderTestFilter('A'));
204         chain.addLast("B", new EventOrderTestFilter('B'));
205         run("AS0 BS0 HS0" + "ASO BSO HSO" + "AMR BMR HMR"
206                 + "BFW AFW AMS BMS HMS" + "ASI BSI HSI" + "AEC BEC HEC"
207                 + "ASC BSC HSC");
208     }
209 
210     @Test
211     public void testAddRemove() throws Exception {
212         IoFilter filter = new AddRemoveTestFilter();
213 
214         chain.addFirst("A", filter);
215         assertEquals("ADDED", result);
216 
217         chain.remove("A");
218         assertEquals("ADDEDREMOVED", result);
219     }
220 
221     private void run(String expectedResult) {
222         chain.fireSessionCreated();
223         chain.fireSessionOpened();
224         chain.fireMessageReceived(new Object());
225         chain.fireFilterWrite(new DefaultWriteRequest(new Object()));
226         chain.fireSessionIdle(IdleStatus.READER_IDLE);
227         chain.fireExceptionCaught(new Exception());
228         chain.fireSessionClosed();
229 
230         result = formatResult(result);
231         expectedResult = formatResult(expectedResult);
232 
233         //System.out.println("Expected: " + expectedResult);
234         //System.out.println("Actual:   " + result);
235         assertEquals(expectedResult, result);
236     }
237 
238     private String formatResult(String result) {
239         result = result.replaceAll("\\s", "");
240         StringBuilder buf = new StringBuilder(result.length() * 4 / 3);
241         for (int i = 0; i < result.length(); i++) {
242             buf.append(result.charAt(i));
243             if (i % 3 == 2) {
244                 buf.append(' ');
245             }
246         }
247 
248         return buf.toString();
249     }
250 
251     private class EventOrderTestFilter extends IoFilterAdapter {
252         private final char id;
253 
254         private EventOrderTestFilter(char id) {
255             this.id = id;
256         }
257 
258         @Override
259         public void sessionCreated(NextFilter nextFilter, IoSession session) {
260             result += id + "S0";
261             nextFilter.sessionCreated(session);
262         }
263 
264         @Override
265         public void sessionOpened(NextFilter nextFilter, IoSession session) {
266             result += id + "SO";
267             nextFilter.sessionOpened(session);
268         }
269 
270         @Override
271         public void sessionClosed(NextFilter nextFilter, IoSession session) {
272             result += id + "SC";
273             nextFilter.sessionClosed(session);
274         }
275 
276         @Override
277         public void sessionIdle(NextFilter nextFilter, IoSession session,
278                 IdleStatus status) {
279             result += id + "SI";
280             nextFilter.sessionIdle(session, status);
281         }
282 
283         @Override
284         public void exceptionCaught(NextFilter nextFilter, IoSession session,
285                 Throwable cause) {
286             result += id + "EC";
287             nextFilter.exceptionCaught(session, cause);
288         }
289 
290         @Override
291         public void filterWrite(NextFilter nextFilter, IoSession session,
292                 WriteRequest writeRequest) {
293             result += id + "FW";
294             nextFilter.filterWrite(session, writeRequest);
295         }
296 
297         @Override
298         public void messageReceived(NextFilter nextFilter, IoSession session,
299                 Object message) {
300             result += id + "MR";
301             nextFilter.messageReceived(session, message);
302         }
303 
304         @Override
305         public void messageSent(NextFilter nextFilter, IoSession session,
306                 WriteRequest writeRequest) {
307             result += id + "MS";
308             nextFilter.messageSent(session, writeRequest);
309         }
310 
311         @Override
312         public void filterClose(NextFilter nextFilter, IoSession session)
313                 throws Exception {
314             nextFilter.filterClose(session);
315         }
316     }
317 
318     private class AddRemoveTestFilter extends IoFilterAdapter {
319         @Override
320         public void onPostAdd(IoFilterChain parent, String name,
321                 NextFilter nextFilter) {
322             result += "ADDED";
323         }
324 
325         @Override
326         public void onPostRemove(IoFilterChain parent, String name,
327                 NextFilter nextFilter) {
328             result += "REMOVED";
329         }
330     }
331 }