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.filter.codec;
21  
22  import java.net.SocketAddress;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import junit.framework.Assert;
27  import junit.framework.TestCase;
28  
29  import org.apache.mina.core.buffer.IoBuffer;
30  import org.apache.mina.core.service.DefaultTransportMetadata;
31  import org.apache.mina.core.session.IoSession;
32  import org.apache.mina.core.session.IoSessionConfig;
33  
34  /**
35   * Tests {@link CumulativeProtocolDecoder}.
36   *
37   * @author The Apache MINA Project (dev@mina.apache.org)
38   * @version $Rev: 671827 $, $Date: 2008-06-26 10:49:48 +0200 (jeu, 26 jun 2008) $
39   */
40  public class CumulativeProtocolDecoderTest extends TestCase {
41      private final ProtocolCodecSession session = new ProtocolCodecSession();
42  
43      private IoBuffer buf;
44      private IntegerDecoder decoder;
45  
46      public static void main(String[] args) {
47          junit.textui.TestRunner.run(CumulativeProtocolDecoderTest.class);
48      }
49  
50      @Override
51      protected void setUp() throws Exception {
52          buf = IoBuffer.allocate(16);
53          decoder = new IntegerDecoder();
54          session.setTransportMetadata(
55                  new DefaultTransportMetadata(
56                          "mina", "dummy", false, true, SocketAddress.class,
57                          IoSessionConfig.class, IoBuffer.class));
58      }
59  
60      @Override
61      protected void tearDown() throws Exception {
62          decoder.dispose(session);
63      }
64  
65      public void testCumulation() throws Exception {
66          buf.put((byte) 0);
67          buf.flip();
68  
69          decoder.decode(session, buf, session.getDecoderOutput());
70          Assert.assertEquals(0, session.getDecoderOutputQueue().size());
71          Assert.assertEquals(buf.limit(), buf.position());
72  
73          buf.clear();
74          buf.put((byte) 0);
75          buf.put((byte) 0);
76          buf.put((byte) 1);
77          buf.flip();
78  
79          decoder.decode(session, buf, session.getDecoderOutput());
80          Assert.assertEquals(1, session.getDecoderOutputQueue().size());
81          Assert.assertEquals(new Integer(1), session.getDecoderOutputQueue().poll());
82          Assert.assertEquals(buf.limit(), buf.position());
83      }
84  
85      public void testRepeatitiveDecode() throws Exception {
86          for (int i = 0; i < 4; i++) {
87              buf.putInt(i);
88          }
89          buf.flip();
90  
91          decoder.decode(session, buf, session.getDecoderOutput());
92          Assert.assertEquals(4, session.getDecoderOutputQueue().size());
93          Assert.assertEquals(buf.limit(), buf.position());
94  
95          List<Object> expected = new ArrayList<Object>();
96          for (int i = 0; i < 4; i++) {
97              expected.add(new Integer(i));
98          }
99          Assert.assertEquals(expected, session.getDecoderOutputQueue());
100     }
101 
102     public void testWrongImplementationDetection() throws Exception {
103         try {
104             new WrongDecoder().decode(session, buf, session.getDecoderOutput());
105             Assert.fail();
106         } catch (IllegalStateException e) {
107             // OK
108         }
109     }
110     
111     public void testBufferDerivation() throws Exception {
112         decoder = new DuplicatingIntegerDecoder();
113         
114         buf.putInt(1);
115         
116         // Put some extra byte to make the decoder create an internal buffer.
117         buf.put((byte) 0);
118         buf.flip();
119 
120         decoder.decode(session, buf, session.getDecoderOutput());
121         Assert.assertEquals(1, session.getDecoderOutputQueue().size());
122         Assert.assertEquals(1, session.getDecoderOutputQueue().poll());
123         Assert.assertEquals(buf.limit(), buf.position());
124 
125         // Keep appending to the internal buffer.
126         // DuplicatingIntegerDecoder will keep duplicating the internal
127         // buffer to disable auto-expansion, and CumulativeProtocolDecoder
128         // should detect that user derived its internal buffer.
129         // Consequently, CumulativeProtocolDecoder will perform 
130         // reallocation to avoid putting incoming data into
131         // the internal buffer with auto-expansion disabled.
132         for (int i = 2; i < 10; i ++) {
133             buf.clear();
134             buf.putInt(i);
135             // Put some extra byte to make the decoder keep the internal buffer.
136             buf.put((byte) 0);
137             buf.flip();
138             buf.position(1);
139     
140             decoder.decode(session, buf, session.getDecoderOutput());
141             Assert.assertEquals(1, session.getDecoderOutputQueue().size());
142             Assert.assertEquals(i, session.getDecoderOutputQueue().poll());
143             Assert.assertEquals(buf.limit(), buf.position());
144         }
145     }
146 
147     private static class IntegerDecoder extends CumulativeProtocolDecoder {
148 
149         @Override
150         protected boolean doDecode(IoSession session, IoBuffer in,
151                 ProtocolDecoderOutput out) throws Exception {
152             Assert.assertTrue(in.hasRemaining());
153             if (in.remaining() < 4) {
154                 return false;
155             }
156 
157             out.write(new Integer(in.getInt()));
158             return true;
159         }
160 
161         public void dispose() throws Exception {
162         }
163     }
164     
165     private static class WrongDecoder extends CumulativeProtocolDecoder {
166         @Override
167         protected boolean doDecode(IoSession session, IoBuffer in,
168                 ProtocolDecoderOutput out) throws Exception {
169             return true;
170         }
171 
172         public void dispose() throws Exception {
173         }
174     }
175 
176     private static class DuplicatingIntegerDecoder extends IntegerDecoder {
177         @Override
178         protected boolean doDecode(IoSession session, IoBuffer in,
179                 ProtocolDecoderOutput out) throws Exception {
180             in.duplicate(); // Will disable auto-expansion.
181             Assert.assertFalse(in.isAutoExpand());
182             return super.doDecode(session, in, out);
183         }
184 
185         public void dispose() throws Exception {
186         }
187     }
188 
189 }