001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.filter.codec; 021 022import org.apache.mina.filter.codec.demux.MessageDecoderResult; 023import org.apache.mina.filter.codec.demux.MessageDecoderAdapter; 024import org.apache.mina.filter.codec.demux.DemuxingProtocolDecoder; 025import org.apache.mina.filter.codec.ProtocolDecoderOutput; 026import org.apache.mina.core.session.IoSession; 027import org.apache.mina.core.session.DummySession; 028import org.apache.mina.core.buffer.IoBuffer; 029import org.apache.mina.core.service.DefaultTransportMetadata; 030import org.apache.mina.core.file.FileRegion; 031import org.apache.mina.transport.socket.SocketSessionConfig; 032import org.easymock.EasyMock; 033import org.junit.Test; 034 035import java.net.InetSocketAddress; 036import java.nio.charset.Charset; 037 038/** 039 * Simple Unit Test showing that the DemuxingProtocolDecoder has 040 * inconsistent behavior if used with a non fragmented transport. 041 * 042 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 043*/ 044public class DemuxingProtocolDecoderBugTest { 045 046 private static void doTest(IoSession session) throws Exception { 047 ProtocolDecoderOutput mock = EasyMock.createMock(ProtocolDecoderOutput.class); 048 mock.write(Character.valueOf('A')); 049 mock.write(Character.valueOf('B')); 050 mock.write(Integer.valueOf(1)); 051 mock.write(Integer.valueOf(2)); 052 mock.write(Character.valueOf('C')); 053 EasyMock.replay(mock); 054 055 IoBuffer buffer = IoBuffer.allocate(1000); 056 buffer.putString("AB12C", Charset.defaultCharset().newEncoder()); 057 buffer.flip(); 058 059 DemuxingProtocolDecoder decoder = new DemuxingProtocolDecoder(); 060 decoder.addMessageDecoder(CharacterMessageDecoder.class); 061 decoder.addMessageDecoder(IntegerMessageDecoder.class); 062 063 decoder.decode(session, buffer, mock); 064 065 EasyMock.verify(mock); 066 } 067 068 public static class CharacterMessageDecoder extends MessageDecoderAdapter { 069 public MessageDecoderResult decodable(IoSession session, IoBuffer in) { 070 return Character.isDigit((char) in.get()) ? MessageDecoderResult.NOT_OK : MessageDecoderResult.OK; 071 } 072 073 public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { 074 out.write(Character.valueOf((char) in.get())); 075 return MessageDecoderResult.OK; 076 } 077 } 078 079 public static class IntegerMessageDecoder extends MessageDecoderAdapter { 080 public MessageDecoderResult decodable(IoSession session, IoBuffer in) { 081 return Character.isDigit((char) in.get()) ? MessageDecoderResult.OK : MessageDecoderResult.NOT_OK; 082 } 083 084 public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { 085 out.write(Integer.parseInt("" + (char) in.get())); 086 return MessageDecoderResult.OK; 087 } 088 } 089 090 private static class SessionStub extends DummySession { 091 public SessionStub(boolean fragmented) { 092 setTransportMetadata(new DefaultTransportMetadata("nio", "socket", false, fragmented, 093 InetSocketAddress.class, SocketSessionConfig.class, IoBuffer.class, FileRegion.class)); 094 } 095 } 096 097 /** 098 * Test a decoding with fragmentation 099 */ 100 @Test 101 public void testFragmentedTransport() throws Exception { 102 doTest(new SessionStub(true)); 103 } 104 105 /** 106 * Test a decoding without fragmentation 107 */ 108 @Test 109 public void testNonFragmentedTransport() throws Exception { 110 doTest(new SessionStub(false)); 111 } 112}