Clover icon

Magnolia Module Cache 5.5.9

  1. Project Clover database Mon Nov 25 2019 16:46:50 CET
  2. Package info.magnolia.module.cache.filter

File GZipFilterTest.java

 

Code metrics

4
91
12
3
284
186
15
0.16
7.58
4
1.25
3.6% of code in this file is excluded from these metrics.

Classes

Class Line # Actions
GZipFilterTest 74 86 3.9% 12 6
0.9387755493.9%
GZipFilterTest.DummyFilterChain 263 1 0% 1 0
1.0100%
GZipFilterTest.DummyWritingFilterChain 272 4 0% 2 2
0.7142857371.4%
 

Contributing tests

This file is covered by 4 tests. .

Source view

1    /**
2    * This file Copyright (c) 2008-2018 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.module.cache.filter;
35   
36    import static org.junit.Assert.*;
37    import static org.mockito.Matchers.any;
38    import static org.mockito.Matchers.isA;
39    import static org.mockito.Matchers.same;
40    import static org.mockito.Mockito.*;
41   
42    import info.magnolia.cms.cache.CacheConstants;
43    import info.magnolia.cms.filters.WebContainerResources;
44    import info.magnolia.cms.filters.WebContainerResourcesImpl;
45    import info.magnolia.module.cache.util.GZipUtil;
46    import info.magnolia.test.ComponentsTestUtil;
47    import info.magnolia.test.MgnlTestCase;
48   
49    import java.io.ByteArrayOutputStream;
50    import java.io.IOException;
51    import java.io.InputStream;
52    import java.io.PrintWriter;
53    import java.util.Enumeration;
54    import java.util.List;
55   
56    import javax.servlet.FilterChain;
57    import javax.servlet.ServletException;
58    import javax.servlet.ServletOutputStream;
59    import javax.servlet.ServletRequest;
60    import javax.servlet.ServletResponse;
61    import javax.servlet.http.HttpServletRequest;
62    import javax.servlet.http.HttpServletResponse;
63    import javax.servlet.http.HttpServletResponseWrapper;
64   
65    import org.apache.commons.collections4.MultiMap;
66    import org.junit.Before;
67    import org.junit.Test;
68    import org.mockito.invocation.InvocationOnMock;
69    import org.mockito.stubbing.Answer;
70   
71    /**
72    * Basic tests for gzip filter.
73    */
 
74    public class GZipFilterTest extends MgnlTestCase {
75    private static final String SOME_10CHARSLONG_CHAIN = "qwertzuiop";
76   
 
77  4 toggle @Override
78    @Before
79    public void setUp() throws Exception {
80  4 super.setUp();
81  4 ComponentsTestUtil.setImplementation(WebContainerResources.class, WebContainerResourcesImpl.class);
82    }
83   
 
84  1 toggle @Test
85    public void testBufferIsFlushedProperlyWhenUsingWriterFurtherDownTheChainOfFilters() throws Exception {
86    // GIVEN
87  1 final int iterations = 5000;
88   
89  1 final FilterChain chain = mock(FilterChain.class);
90  1 final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
91  1 when(mockRequest.getAttribute(any(String.class))).thenReturn(null);
92  1 when(mockRequest.getHeaders("Accept-Encoding")).thenReturn(new Enumeration() {
93    private boolean has = true;
94   
 
95  0 toggle @Override
96    public boolean hasMoreElements() {
97  0 return has;
98    }
99   
 
100  0 toggle @Override
101    public Object nextElement() {
102  0 has = false;
103  0 return "gzip";
104    }
105    });
106  1 final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
107  1 when(mockResponse.containsHeader("Content-Encoding")).thenReturn(true);
108  1 when(mockResponse.containsHeader("Vary")).thenReturn(true);
109  1 when(mockResponse.getCharacterEncoding()).thenReturn("ISO-8859-1"); // called when creating the writer in CacheResponseWriter
110   
111    // we need to wrap the mock response to be able to get the written output
112  1 final ByteArrayOutputStream finalOutput = new ByteArrayOutputStream();
113  1 final SimpleServletOutputStream servletOutput = new SimpleServletOutputStream(finalOutput);
114  1 final HttpServletResponse testReponse = new HttpServletResponseWrapper(mockResponse) {
115    // and we know GZipFilter will only call getOutputStream() on it.
 
116    toggle @Override
117    public ServletOutputStream getOutputStream() throws IOException {
118    return servletOutput;
119    }
120    };
121   
122    // fake some chained filter:
123  1 doAnswer(new Answer() {
 
124  1 toggle @Override
125    public Object answer(InvocationOnMock invocation) {
126  1 final Object[] args = invocation.getArguments();
127  1 final ServletResponse responseFutherDownTheChain = (ServletResponse) args[1];
128    // let's pretend we're some filter writing some content
129  1 try {
130  1 final PrintWriter out = responseFutherDownTheChain.getWriter();
131  5001 for (int i = 0; i < iterations; i++) {
132  5000 out.println(SOME_10CHARSLONG_CHAIN);
133    }
134    } catch (IOException ex) {
135  0 ex.printStackTrace();
136    }
137  1 return null;
138    }
139    }).when(chain).doFilter(same(mockRequest), isA(CacheResponseWrapper.class));
140   
141    // WHEN
142  1 final GZipFilter filter = new GZipFilter();
143  1 filter.doFilter(mockRequest, testReponse, chain);
144   
145    // THEN
146  1 verify(mockResponse).addHeader("Content-Encoding", "gzip");
147  1 verify(mockResponse).addHeader("Vary", "Accept-Encoding");
148  1 verify(mockResponse).setContentLength(finalOutput.toByteArray().length);
149  1 verify(mockResponse).flushBuffer();
150   
151    // now assert GZipFilter has written the expected amount of characters in the original response
152  1 final byte[] compressedBytes = finalOutput.toByteArray();
153  1 assertTrue("output should be gzipped", GZipUtil.isGZipped(compressedBytes));
154  1 final byte[] uncompressed = GZipUtil.ungzip(compressedBytes);
155  1 final int expectedLength = iterations * (SOME_10CHARSLONG_CHAIN.length() + System.getProperty("line.separator").length()); // n chars + newline
156  1 assertEquals(expectedLength, uncompressed.length);
157    }
158   
 
159  1 toggle @Test
160    public void testBufferIsFlushedAndGZipNotSetOnError() throws Exception {
161    // GIVEN
162  1 final FilterChain chain = mock(FilterChain.class);
163  1 final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
164   
165  1 final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
166  1 when(mockResponse.getCharacterEncoding()).thenReturn("ISO-8859-1");
167   
168    // we need to wrap the mock response to be able to get the written output
169  1 final ByteArrayOutputStream finalOutput = new ByteArrayOutputStream();
170  1 final SimpleServletOutputStream servletOutput = new SimpleServletOutputStream(finalOutput);
171  1 final HttpServletResponse testReponse = new HttpServletResponseWrapper(mockResponse) {
172    // and we know GZipFilter will only call getOutputStream() on it.
 
173    toggle @Override
174    public ServletOutputStream getOutputStream() throws IOException {
175    return servletOutput;
176    }
177    };
178   
179    // fake some chained filter:
180  1 doAnswer(new Answer() {
 
181  1 toggle @Override
182    public Object answer(InvocationOnMock invocation) throws Throwable {
183  1 final Object[] args = invocation.getArguments();
184  1 final ServletResponse responseFutherDownTheChain = (ServletResponse) args[1];
185    // let's pretend we're some filter writing some content
186  1 final PrintWriter out = responseFutherDownTheChain.getWriter();
187  1 out.println(SOME_10CHARSLONG_CHAIN);
188    // fake the content denied
189  1 ((HttpServletResponse) responseFutherDownTheChain).sendError(HttpServletResponse.SC_UNAUTHORIZED);
190  1 return null;
191    }
192    }).when(chain).doFilter(same(mockRequest), isA(CacheResponseWrapper.class));
193   
194    // WHEN
195  1 final GZipFilter filter = new GZipFilter();
196  1 filter.doFilter(mockRequest, testReponse, chain);
197   
198    // THEN
199  1 verify(mockResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED);
200  1 verify(mockResponse, times(2)).flushBuffer();
201   
202    // now assert GZipFilter has written the expected amount of characters in the original response
203  1 final byte[] uncompressed = finalOutput.toByteArray();
204    // errors should be uncompressed
205  1 assertFalse("output should be gzipped", GZipUtil.isGZipped(uncompressed));
206  1 final int expectedLength = SOME_10CHARSLONG_CHAIN.length() + System.getProperty("line.separator").length(); // n chars + newline
207  1 assertEquals(expectedLength, uncompressed.length);
208    }
209   
 
210  1 toggle @Test
211    public void testCacheHeadersAreAddedToTheResponse() throws Exception {
212    // GIVEN
213  1 final HttpServletRequest request = mock(HttpServletRequest.class);
214  1 final HttpServletResponse response = mock(HttpServletResponse.class);
215  1 final DummyFilterChain chain = new DummyFilterChain();
216  1 final GZipFilter filter = new GZipFilter();
217  1 final ServletOutputStream stream = mock(ServletOutputStream.class);
218   
219  1 when(response.containsHeader("Content-Encoding")).thenReturn(true);
220  1 when(response.containsHeader("Vary")).thenReturn(true);
221  1 when(response.getOutputStream()).thenReturn(stream);
222   
223  1 filter.doFilter(request, response, chain);
224  1 final CacheResponseWrapper wrapper = (CacheResponseWrapper) chain.response;
225   
226    // WHEN
227  1 wrapper.setHeader(CacheConstants.HEADER_CACHE_CONTROL, CacheConstants.HEADER_VALUE_MAX_AGE + ":525600");
228  1 wrapper.setHeader(CacheConstants.HEADER_EXPIRES, "someDate");
229   
230    // THEN
231  1 MultiMap map = ((CacheResponseWrapper) chain.response).getHeaders();
232  1 assertEquals("max-age:525600", ((List<String>) map.get(CacheConstants.HEADER_CACHE_CONTROL)).get(0));
233  1 assertEquals("someDate", ((List<String>) map.get(CacheConstants.HEADER_EXPIRES)).get(0));
234    }
235   
 
236  1 toggle @Test
237    public void testResponseIsGzippedWhenThresholdExceeded() throws IOException, ServletException {
238    // GIVEN
239  1 final HttpServletRequest request = mock(HttpServletRequest.class);
240  1 final HttpServletResponse response = mock(HttpServletResponse.class);
241  1 final DummyWritingFilterChain chain = new DummyWritingFilterChain();
242  1 final GZipFilter filter = new GZipFilter();
243  1 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
244   
245  1 final ServletOutputStream sos = new ServletOutputStream() {
 
246  143623 toggle @Override
247    public void write(int b) throws IOException {
248  143623 baos.write(b);
249    }
250    };
251   
252  1 when(response.containsHeader("Content-Encoding")).thenReturn(true);
253  1 when(response.containsHeader("Vary")).thenReturn(true);
254  1 when(response.getOutputStream()).thenReturn(sos);
255   
256    // WHEN
257  1 filter.doFilter(request, response, chain);
258   
259    // THEN
260  1 assertTrue(GZipUtil.isGZipped(baos.toByteArray()));
261    }
262   
 
263    private static class DummyFilterChain implements FilterChain {
264    public ServletResponse response;
265   
 
266  1 toggle @Override
267    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
268  1 this.response = response;
269    }
270    }
271   
 
272    private static class DummyWritingFilterChain implements FilterChain {
273   
 
274  1 toggle @Override
275    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
276    // styles.css have ~ 1mb size -> threshold will be exceeded
277  1 final InputStream fis = this.getClass().getClassLoader().getResourceAsStream("styles.css");
278  1 int i = 0;
279  ? while ((i = fis.read()) != -1) {
280  1016217 response.getOutputStream().write(i);
281    }
282    }
283    }
284    }