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.handler.demux;
21  
22  import junit.framework.TestCase;
23  
24  import org.apache.mina.common.IoSession;
25  import org.apache.mina.handler.demux.DemuxingIoHandler;
26  import org.apache.mina.handler.demux.MessageHandler;
27  import org.easymock.MockControl;
28  
29  /**
30   * Tests {@link org.apache.mina.handler.demux.DemuxingIoHandler}.
31   *
32   * @author The Apache Directory Project (mina-dev@directory.apache.org)
33   * @version $Rev$, $Date$
34   */
35  public class DemuxingIoHandlerTest extends TestCase {
36      MockControl mockHandler1;
37  
38      MockControl mockHandler2;
39  
40      MockControl mockHandler3;
41  
42      MessageHandler handler1;
43  
44      MessageHandler handler2;
45  
46      MessageHandler handler3;
47  
48      IoSession session;
49  
50      Object[] msg;
51  
52      @SuppressWarnings("unchecked")
53      protected void setUp() throws Exception {
54          super.setUp();
55  
56          /*
57           * Create the messages.
58           */
59          msg = new Object[9];
60          msg[0] = new C1();
61          msg[1] = new C2();
62          msg[2] = new C3();
63          msg[3] = new C1();
64          msg[4] = new C2();
65          msg[5] = new C3();
66          msg[6] = new C1();
67          msg[7] = new C2();
68          msg[8] = new C3();
69  
70          /*
71           * Create mocks.
72           */
73          mockHandler1 = MockControl.createControl(MessageHandler.class);
74          mockHandler2 = MockControl.createControl(MessageHandler.class);
75          mockHandler3 = MockControl.createControl(MessageHandler.class);
76  
77          handler1 = (MessageHandler) mockHandler1.getMock();
78          handler2 = (MessageHandler) mockHandler2.getMock();
79          handler3 = (MessageHandler) mockHandler3.getMock();
80  
81          session = (IoSession) MockControl.createControl(IoSession.class)
82                  .getMock();
83      }
84  
85      @SuppressWarnings("unchecked")
86      public void testFindHandlerByClass() throws Exception {
87          /*
88           * Record expectations.
89           */
90          handler1.messageReceived(session, msg[0]);
91          handler1.messageReceived(session, msg[1]);
92          handler1.messageReceived(session, msg[2]);
93          handler1.messageReceived(session, msg[3]);
94          handler2.messageReceived(session, msg[4]);
95          handler2.messageReceived(session, msg[5]);
96          handler1.messageReceived(session, msg[6]);
97          handler2.messageReceived(session, msg[7]);
98          handler3.messageReceived(session, msg[8]);
99  
100         /*
101          * Replay.
102          */
103         mockHandler1.replay();
104         mockHandler2.replay();
105         mockHandler3.replay();
106 
107         DemuxingIoHandler ioHandler = new DemuxingIoHandler();
108 
109         /*
110          * First round. All messages should be handled by handler1
111          */
112         ioHandler.addMessageHandler(C1.class, (MessageHandler) mockHandler1
113                 .getMock());
114         ioHandler.messageReceived(session, msg[0]);
115         ioHandler.messageReceived(session, msg[1]);
116         ioHandler.messageReceived(session, msg[2]);
117 
118         /*
119          * Second round. C1 messages should be handled by handler1. C2 and C3
120          * messages should be handled by handler2.
121          */
122         ioHandler.addMessageHandler(C2.class, (MessageHandler) mockHandler2
123                 .getMock());
124         ioHandler.messageReceived(session, msg[3]);
125         ioHandler.messageReceived(session, msg[4]);
126         ioHandler.messageReceived(session, msg[5]);
127 
128         /*
129          * Third round. C1 messages should be handled by handler1, C2 by 
130          * handler2 and C3 by handler3.
131          */
132         ioHandler.addMessageHandler(C3.class, (MessageHandler) mockHandler3
133                 .getMock());
134         ioHandler.messageReceived(session, msg[6]);
135         ioHandler.messageReceived(session, msg[7]);
136         ioHandler.messageReceived(session, msg[8]);
137 
138         /*
139          * Verify.
140          */
141         mockHandler1.verify();
142         mockHandler2.verify();
143         mockHandler3.verify();
144     }
145 
146     @SuppressWarnings("unchecked")
147     public void testFindHandlerByInterface() throws Exception {
148         /*
149          * Record expectations.
150          */
151         handler1.messageReceived(session, msg[0]);
152         handler1.messageReceived(session, msg[1]);
153         handler1.messageReceived(session, msg[2]);
154         handler1.messageReceived(session, msg[3]);
155         handler2.messageReceived(session, msg[4]);
156         handler1.messageReceived(session, msg[5]);
157         handler3.messageReceived(session, msg[6]);
158         handler2.messageReceived(session, msg[7]);
159         handler3.messageReceived(session, msg[8]);
160 
161         /*
162          * Replay.
163          */
164         mockHandler1.replay();
165         mockHandler2.replay();
166         mockHandler3.replay();
167 
168         DemuxingIoHandler ioHandler = new DemuxingIoHandler();
169 
170         /*
171          * First round. All messages should be handled by handler1
172          */
173         ioHandler.addMessageHandler(I4.class, (MessageHandler) mockHandler1
174                 .getMock());
175         ioHandler.messageReceived(session, msg[0]);
176         ioHandler.messageReceived(session, msg[1]);
177         ioHandler.messageReceived(session, msg[2]);
178 
179         /*
180          * Second round. C1 and C3 messages should be handled by handler1. C2
181          * messages should be handled by handler2.
182          */
183         ioHandler.addMessageHandler(I6.class, (MessageHandler) mockHandler2
184                 .getMock());
185         ioHandler.messageReceived(session, msg[3]);
186         ioHandler.messageReceived(session, msg[4]);
187         ioHandler.messageReceived(session, msg[5]);
188 
189         /*
190          * Third round. C1 and C3 messages should be handled by handler3. C2
191          * messages should be handled by handler2.
192          */
193         ioHandler.addMessageHandler(I3.class, (MessageHandler) mockHandler3
194                 .getMock());
195         ioHandler.messageReceived(session, msg[6]);
196         ioHandler.messageReceived(session, msg[7]);
197         ioHandler.messageReceived(session, msg[8]);
198 
199         /*
200          * Verify.
201          */
202         mockHandler1.verify();
203         mockHandler2.verify();
204         mockHandler3.verify();
205     }
206 
207     /*
208      * Define some interfaces and classes used when testing the findHandler
209      * method. This is what the hierarchy looks like:
210      * 
211      * C3 - I7 - I9
212      *  |    |   /\
213      *  |   I8  I3 I4
214      *  |
215      * C2 - I5 - I6
216      *  |
217      * C1 - I1 - I2 - I4
218      *            |
219      *           I3
220      */
221 
222     public interface I1 {
223     }
224 
225     public interface I2 extends I3 {
226     }
227 
228     public interface I3 {
229     }
230 
231     public interface I4 {
232     }
233 
234     public static class C1 implements I1, I2, I4 {
235     }
236 
237     public interface I5 {
238     }
239 
240     public interface I6 {
241     }
242 
243     public static class C2 extends C1 implements I5, I6 {
244     }
245 
246     public interface I7 extends I8 {
247     }
248 
249     public interface I8 {
250     }
251 
252     public interface I9 extends I3, I4 {
253     }
254 
255     public static class C3 extends C2 implements I7, I9 {
256     }
257 }