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