View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client.cache;
28  
29  import java.io.IOException;
30  import java.lang.reflect.Proxy;
31  import java.util.concurrent.atomic.AtomicBoolean;
32  
33  import org.apache.http.HttpEntity;
34  import org.apache.http.HttpRequest;
35  import org.apache.http.HttpResponse;
36  import org.apache.http.HttpStatus;
37  import org.apache.http.HttpVersion;
38  import org.apache.http.client.methods.CloseableHttpResponse;
39  import org.apache.http.client.methods.HttpGet;
40  import org.apache.http.entity.ByteArrayEntity;
41  import org.apache.http.entity.StringEntity;
42  import org.apache.http.message.BasicHttpResponse;
43  import org.apache.http.util.EntityUtils;
44  import org.junit.Assert;
45  import org.junit.Before;
46  import org.junit.Test;
47  
48  public class TestSizeLimitedResponseReader {
49  
50      private static final long MAX_SIZE = 4;
51  
52      private HttpRequest request;
53      private SizeLimitedResponseReader impl;
54  
55      @Before
56      public void setUp() {
57          request = new HttpGet("http://foo.example.com/bar");
58      }
59  
60      @Test
61      public void testLargeResponseIsTooLarge() throws Exception {
62          final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
63          final CloseableHttpResponse response = make200Response(buf);
64  
65          impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
66  
67          impl.readResponse();
68          final boolean tooLarge = impl.isLimitReached();
69          final HttpResponse result = impl.getReconstructedResponse();
70          final byte[] body = EntityUtils.toByteArray(result.getEntity());
71  
72          Assert.assertTrue(tooLarge);
73          Assert.assertArrayEquals(buf, body);
74      }
75  
76      @Test
77      public void testExactSizeResponseIsNotTooLarge() throws Exception {
78          final byte[] buf = new byte[] { 1, 2, 3, 4 };
79          final CloseableHttpResponse response = make200Response(buf);
80  
81          impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
82  
83          impl.readResponse();
84          final boolean tooLarge = impl.isLimitReached();
85          final HttpResponse reconstructed = impl.getReconstructedResponse();
86          final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
87  
88          Assert.assertFalse(tooLarge);
89          Assert.assertArrayEquals(buf, result);
90      }
91  
92      @Test
93      public void testSmallResponseIsNotTooLarge() throws Exception {
94          final byte[] buf = new byte[] { 1, 2, 3 };
95          final CloseableHttpResponse response = make200Response(buf);
96  
97          impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
98  
99          impl.readResponse();
100         final boolean tooLarge = impl.isLimitReached();
101         final HttpResponse reconstructed = impl.getReconstructedResponse();
102         final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
103 
104         Assert.assertFalse(tooLarge);
105         Assert.assertArrayEquals(buf, result);
106     }
107 
108     @Test
109     public void testResponseWithNoEntityIsNotTooLarge() throws Exception {
110         final CloseableHttpResponse response = make200Response();
111 
112         impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
113 
114         impl.readResponse();
115         final boolean tooLarge = impl.isLimitReached();
116 
117         Assert.assertFalse(tooLarge);
118     }
119 
120     @Test
121     public void testTooLargeEntityHasOriginalContentTypes() throws Exception {
122         final CloseableHttpResponse response = make200Response();
123         final StringEntity entity = new StringEntity("large entity content");
124         response.setEntity(entity);
125 
126         impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
127 
128         impl.readResponse();
129         final boolean tooLarge = impl.isLimitReached();
130         final HttpResponse result = impl.getReconstructedResponse();
131         final HttpEntity reconstructedEntity = result.getEntity();
132         Assert.assertEquals(entity.getContentEncoding(), reconstructedEntity.getContentEncoding());
133         Assert.assertEquals(entity.getContentType(), reconstructedEntity.getContentType());
134 
135         final String content = EntityUtils.toString(reconstructedEntity);
136 
137         Assert.assertTrue(tooLarge);
138         Assert.assertEquals("large entity content", content);
139     }
140 
141     @Test
142     public void testTooLargeResponseCombinedClosed() throws Exception {
143         final AtomicBoolean closed = new AtomicBoolean(false);
144         final CloseableHttpResponse response = (CloseableHttpResponse) Proxy
145                 .newProxyInstance(ResponseProxyHandler.class.getClassLoader(),
146                         new Class<?>[] { CloseableHttpResponse.class },
147                         new ResponseProxyHandler(new BasicHttpResponse(
148                                 HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK")) {
149                             @Override
150                             public void close() throws IOException {
151                                 closed.set(true);
152                             }
153                         });
154         final StringEntity entity = new StringEntity("large entity content");
155         response.setEntity(entity);
156 
157         impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
158 
159         impl.readResponse();
160         final boolean tooLarge = impl.isLimitReached();
161         final CloseableHttpResponse result = impl.getReconstructedResponse();
162         try {
163             final HttpEntity reconstructedEntity = result.getEntity();
164             Assert.assertEquals(entity.getContentEncoding(), reconstructedEntity.getContentEncoding());
165             Assert.assertEquals(entity.getContentType(), reconstructedEntity.getContentType());
166 
167             Assert.assertFalse(closed.get());
168             final String content = EntityUtils.toString(reconstructedEntity);
169 
170             Assert.assertTrue(tooLarge);
171             Assert.assertEquals("large entity content", content);
172         } finally {
173             result.close();
174         }
175         Assert.assertTrue(closed.get());
176     }
177 
178     @Test
179     public void testResponseCopiesAllOriginalHeaders() throws Exception {
180         final byte[] buf = new byte[] { 1, 2, 3 };
181         final CloseableHttpResponse response = make200Response(buf);
182         response.setHeader("Content-Encoding", "gzip");
183 
184         impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
185 
186         impl.readResponse();
187         final boolean tooLarge = impl.isLimitReached();
188         final HttpResponse reconstructed = impl.getReconstructedResponse();
189         final byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
190 
191         Assert.assertFalse(tooLarge);
192         Assert.assertArrayEquals(buf, result);
193         Assert.assertEquals("gzip", reconstructed.getFirstHeader("Content-Encoding").getValue());
194     }
195 
196     private CloseableHttpResponse make200Response() {
197         return Proxies.enhanceResponse(new BasicHttpResponse(
198                 HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"));
199     }
200 
201     private CloseableHttpResponse make200Response(final byte[] buf) {
202         final HttpResponse response = new BasicHttpResponse(
203                 HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
204         response.setEntity(new ByteArrayEntity(buf));
205         return Proxies.enhanceResponse(response);
206     }
207 
208 }