1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
|
|
23 |
|
|
24 |
|
|
25 |
|
|
26 |
|
|
27 |
|
|
28 |
|
|
29 |
|
|
30 |
|
|
31 |
|
|
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 |
|
|
73 |
|
|
|
|
| 93.9% |
Uncovered Elements: 6 (98) |
Complexity: 12 |
Complexity Density: 0.14 |
|
74 |
|
public class GZipFilterTest extends MgnlTestCase { |
75 |
|
private static final String SOME_10CHARSLONG_CHAIN = "qwertzuiop"; |
76 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
77 |
4 |
@Override... |
78 |
|
@Before |
79 |
|
public void setUp() throws Exception { |
80 |
4 |
super.setUp(); |
81 |
4 |
ComponentsTestUtil.setImplementation(WebContainerResources.class, WebContainerResourcesImpl.class); |
82 |
|
} |
83 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (24) |
Complexity: 1 |
Complexity Density: 0.04 |
1PASS
|
|
84 |
1 |
@Test... |
85 |
|
public void testBufferIsFlushedProperlyWhenUsingWriterFurtherDownTheChainOfFilters() throws Exception { |
86 |
|
|
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 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
95 |
0 |
@Override... |
96 |
|
public boolean hasMoreElements() { |
97 |
0 |
return has; |
98 |
|
} |
99 |
|
|
|
|
| 0% |
Uncovered Elements: 2 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
100 |
0 |
@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"); |
110 |
|
|
111 |
|
|
112 |
1 |
final ByteArrayOutputStream finalOutput = new ByteArrayOutputStream(); |
113 |
1 |
final SimpleServletOutputStream servletOutput = new SimpleServletOutputStream(finalOutput); |
114 |
1 |
final HttpServletResponse testReponse = new HttpServletResponseWrapper(mockResponse) { |
115 |
|
|
|
|
| - |
Uncovered Elements: 0 (0) |
Complexity: 1 |
Complexity Density: - |
|
116 |
|
@Override... |
117 |
|
public ServletOutputStream getOutputStream() throws IOException { |
118 |
|
return servletOutput; |
119 |
|
} |
120 |
|
}; |
121 |
|
|
122 |
|
|
123 |
1 |
doAnswer(new Answer() { |
|
|
| 90% |
Uncovered Elements: 1 (10) |
Complexity: 3 |
Complexity Density: 0.38 |
|
124 |
1 |
@Override... |
125 |
|
public Object answer(InvocationOnMock invocation) { |
126 |
1 |
final Object[] args = invocation.getArguments(); |
127 |
1 |
final ServletResponse responseFutherDownTheChain = (ServletResponse) args[1]; |
128 |
|
|
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 |
|
|
142 |
1 |
final GZipFilter filter = new GZipFilter(); |
143 |
1 |
filter.doFilter(mockRequest, testReponse, chain); |
144 |
|
|
145 |
|
|
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 |
|
|
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()); |
156 |
1 |
assertEquals(expectedLength, uncompressed.length); |
157 |
|
} |
158 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (16) |
Complexity: 1 |
Complexity Density: 0.06 |
1PASS
|
|
159 |
1 |
@Test... |
160 |
|
public void testBufferIsFlushedAndGZipNotSetOnError() throws Exception { |
161 |
|
|
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 |
|
|
169 |
1 |
final ByteArrayOutputStream finalOutput = new ByteArrayOutputStream(); |
170 |
1 |
final SimpleServletOutputStream servletOutput = new SimpleServletOutputStream(finalOutput); |
171 |
1 |
final HttpServletResponse testReponse = new HttpServletResponseWrapper(mockResponse) { |
172 |
|
|
|
|
| - |
Uncovered Elements: 0 (0) |
Complexity: 1 |
Complexity Density: - |
|
173 |
|
@Override... |
174 |
|
public ServletOutputStream getOutputStream() throws IOException { |
175 |
|
return servletOutput; |
176 |
|
} |
177 |
|
}; |
178 |
|
|
179 |
|
|
180 |
1 |
doAnswer(new Answer() { |
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 1 |
Complexity Density: 0.17 |
|
181 |
1 |
@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 |
|
|
186 |
1 |
final PrintWriter out = responseFutherDownTheChain.getWriter(); |
187 |
1 |
out.println(SOME_10CHARSLONG_CHAIN); |
188 |
|
|
189 |
1 |
((HttpServletResponse) responseFutherDownTheChain).sendError(HttpServletResponse.SC_UNAUTHORIZED); |
190 |
1 |
return null; |
191 |
|
} |
192 |
|
}).when(chain).doFilter(same(mockRequest), isA(CacheResponseWrapper.class)); |
193 |
|
|
194 |
|
|
195 |
1 |
final GZipFilter filter = new GZipFilter(); |
196 |
1 |
filter.doFilter(mockRequest, testReponse, chain); |
197 |
|
|
198 |
|
|
199 |
1 |
verify(mockResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED); |
200 |
1 |
verify(mockResponse, times(2)).flushBuffer(); |
201 |
|
|
202 |
|
|
203 |
1 |
final byte[] uncompressed = finalOutput.toByteArray(); |
204 |
|
|
205 |
1 |
assertFalse("output should be gzipped", GZipUtil.isGZipped(uncompressed)); |
206 |
1 |
final int expectedLength = SOME_10CHARSLONG_CHAIN.length() + System.getProperty("line.separator").length(); |
207 |
1 |
assertEquals(expectedLength, uncompressed.length); |
208 |
|
} |
209 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (15) |
Complexity: 1 |
Complexity Density: 0.07 |
1PASS
|
|
210 |
1 |
@Test... |
211 |
|
public void testCacheHeadersAreAddedToTheResponse() throws Exception { |
212 |
|
|
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 |
|
|
227 |
1 |
wrapper.setHeader(CacheConstants.HEADER_CACHE_CONTROL, CacheConstants.HEADER_VALUE_MAX_AGE + ":525600"); |
228 |
1 |
wrapper.setHeader(CacheConstants.HEADER_EXPIRES, "someDate"); |
229 |
|
|
230 |
|
|
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 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (11) |
Complexity: 1 |
Complexity Density: 0.09 |
1PASS
|
|
236 |
1 |
@Test... |
237 |
|
public void testResponseIsGzippedWhenThresholdExceeded() throws IOException, ServletException { |
238 |
|
|
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() { |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
246 |
143623 |
@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 |
|
|
257 |
1 |
filter.doFilter(request, response, chain); |
258 |
|
|
259 |
|
|
260 |
1 |
assertTrue(GZipUtil.isGZipped(baos.toByteArray())); |
261 |
|
} |
262 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 1 |
|
263 |
|
private static class DummyFilterChain implements FilterChain { |
264 |
|
public ServletResponse response; |
265 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
266 |
1 |
@Override... |
267 |
|
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { |
268 |
1 |
this.response = response; |
269 |
|
} |
270 |
|
} |
271 |
|
|
|
|
| 71.4% |
Uncovered Elements: 2 (7) |
Complexity: 2 |
Complexity Density: 0.5 |
|
272 |
|
private static class DummyWritingFilterChain implements FilterChain { |
273 |
|
|
|
|
| 66.7% |
Uncovered Elements: 2 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
274 |
1 |
@Override... |
275 |
|
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { |
276 |
|
|
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 |
|
} |