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.compression;
021
022import static org.junit.Assert.assertTrue;
023
024import org.apache.mina.core.buffer.IoBuffer;
025import org.apache.mina.core.filterchain.IoFilterChain;
026import org.apache.mina.core.filterchain.IoFilter.NextFilter;
027import org.apache.mina.core.session.IoSession;
028import org.apache.mina.core.write.DefaultWriteRequest;
029import org.apache.mina.core.write.WriteRequest;
030import org.easymock.AbstractMatcher;
031import org.easymock.MockControl;
032import org.junit.Before;
033import org.junit.Test;
034
035/**
036 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
037 */
038public class CompressionFilterTest {
039    private MockControl mockSession;
040
041    private MockControl mockNextFilter;
042
043    private MockControl mockIoFilterChain;
044
045    private IoSession session;
046
047    private NextFilter nextFilter;
048
049    private IoFilterChain ioFilterChain;
050
051    private CompressionFilter filter;
052
053    private Zlib deflater;
054
055    private Zlib inflater;
056
057    private Zlib actualDeflater;
058
059    private Zlib actualInflater;
060
061    // the sample data to be used for testing
062    String strCompress = "The quick brown fox jumps over the lazy dog.  "
063            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
064            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
065            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
066            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
067            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
068            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
069            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
070            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
071            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
072            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
073            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  "
074            + "The quick brown fox jumps over the lazy dog.  " + "The quick brown fox jumps over the lazy dog.  ";
075
076    @Before
077    public void setUp() {
078        // create the necessary mock controls.
079        mockSession = MockControl.createControl(IoSession.class);
080        mockNextFilter = MockControl.createControl(NextFilter.class);
081        mockIoFilterChain = MockControl.createControl(IoFilterChain.class);
082
083        // set the default matcher
084        mockNextFilter.setDefaultMatcher(new DataMatcher());
085
086        session = (IoSession) mockSession.getMock();
087        nextFilter = (NextFilter) mockNextFilter.getMock();
088        ioFilterChain = (IoFilterChain) mockIoFilterChain.getMock();
089
090        // create an instance of the filter
091        filter = new CompressionFilter(CompressionFilter.COMPRESSION_MAX);
092
093        // deflater and inflater that will be used by the filter
094        deflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER);
095        inflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER);
096
097        // create instances of the deflater and inflater to help test the output
098        actualDeflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_DEFLATER);
099        actualInflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER);
100    }
101
102    @Test
103    public void testCompression() throws Exception {
104        // prepare the input data
105        IoBuffer buf = IoBuffer.wrap(strCompress.getBytes("UTF8"));
106        IoBuffer actualOutput = actualDeflater.deflate(buf);
107        WriteRequest writeRequest = new DefaultWriteRequest(buf);
108
109        // record all the mock calls
110        ioFilterChain.contains(CompressionFilter.class);
111        mockIoFilterChain.setReturnValue(false);
112
113        ioFilterChain.getSession();
114        mockIoFilterChain.setReturnValue(session);
115
116        session.setAttribute(CompressionFilter.class.getName() + ".Deflater", deflater);
117        mockSession.setDefaultMatcher(new DataMatcher());
118        mockSession.setReturnValue(null, MockControl.ONE);
119
120        session.setAttribute(CompressionFilter.class.getName() + ".Inflater", inflater);
121        mockSession.setReturnValue(null, MockControl.ONE);
122
123        session.containsAttribute(CompressionFilter.DISABLE_COMPRESSION_ONCE);
124        mockSession.setReturnValue(false);
125
126        session.getAttribute(CompressionFilter.class.getName() + ".Deflater");
127        mockSession.setReturnValue(deflater);
128
129        nextFilter.filterWrite(session, new DefaultWriteRequest(actualOutput));
130
131        // switch to playback mode
132        mockSession.replay();
133        mockIoFilterChain.replay();
134        mockNextFilter.replay();
135
136        // make the actual calls on the filter
137        filter.onPreAdd(ioFilterChain, "CompressionFilter", nextFilter);
138        filter.filterWrite(nextFilter, session, writeRequest);
139
140        // verify that all the calls happened as recorded
141        mockNextFilter.verify();
142
143        assertTrue(true);
144    }
145
146    @Test
147    public void testDecompression() throws Exception {
148        // prepare the input data
149        IoBuffer buf = IoBuffer.wrap(strCompress.getBytes("UTF8"));
150        IoBuffer byteInput = actualDeflater.deflate(buf);
151        IoBuffer actualOutput = actualInflater.inflate(byteInput);
152
153        // record all the mock calls
154        ioFilterChain.contains(CompressionFilter.class);
155        mockIoFilterChain.setReturnValue(false);
156
157        ioFilterChain.getSession();
158        mockIoFilterChain.setReturnValue(session);
159
160        session.setAttribute(CompressionFilter.class.getName() + ".Deflater", deflater);
161        mockSession.setDefaultMatcher(new DataMatcher());
162        mockSession.setReturnValue(null, MockControl.ONE);
163
164        session.setAttribute(CompressionFilter.class.getName() + ".Inflater", inflater);
165        mockSession.setReturnValue(null, MockControl.ONE);
166
167        session.getAttribute(CompressionFilter.class.getName() + ".Inflater");
168        mockSession.setReturnValue(inflater);
169
170        nextFilter.messageReceived(session, actualOutput);
171
172        // switch to playback mode
173        mockSession.replay();
174        mockIoFilterChain.replay();
175        mockNextFilter.replay();
176
177        // make the actual calls on the filter
178        filter.onPreAdd(ioFilterChain, "CompressionFilter", nextFilter);
179        filter.messageReceived(nextFilter, session, byteInput);
180
181        // verify that all the calls happened as recorded
182        mockNextFilter.verify();
183
184        assertTrue(true);
185    }
186
187    /**
188     * A matcher used to check if the actual and expected outputs matched
189     */
190    class DataMatcher extends AbstractMatcher {
191        @Override
192        protected boolean argumentMatches(Object arg0, Object arg1) {
193            // we need to only verify the ByteBuffer output
194            if (arg0 instanceof WriteRequest) {
195                WriteRequest expected = (WriteRequest) arg0;
196                WriteRequest actual = (WriteRequest) arg1;
197                IoBuffer bExpected = (IoBuffer) expected.getMessage();
198                IoBuffer bActual = (IoBuffer) actual.getMessage();
199                return bExpected.equals(bActual);
200            }
201            return true;
202        }
203    }
204}