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.hc.client5.http.cache;
28  
29  import static org.junit.Assert.assertEquals;
30  import static org.junit.Assert.assertFalse;
31  import static org.junit.Assert.assertNotNull;
32  import static org.junit.Assert.assertNull;
33  import static org.junit.Assert.assertSame;
34  import static org.junit.Assert.assertTrue;
35  import static org.junit.Assert.fail;
36  import static org.mockito.Mockito.mock;
37  
38  import java.util.Date;
39  import java.util.HashMap;
40  import java.util.Map;
41  
42  import org.apache.hc.client5.http.utils.DateUtils;
43  import org.apache.hc.core5.http.Header;
44  import org.apache.hc.core5.http.HttpStatus;
45  import org.apache.hc.core5.http.message.BasicHeader;
46  import org.junit.Before;
47  import org.junit.Test;
48  
49  public class TestHttpCacheEntry {
50  
51      private Date now;
52      private Date elevenSecondsAgo;
53      private Date nineSecondsAgo;
54      private Resource mockResource;
55      private HttpCacheEntry entry;
56  
57      @Before
58      public void setUp() {
59          now = new Date();
60          elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
61          nineSecondsAgo = new Date(now.getTime() - 9 * 1000L);
62          mockResource = mock(Resource.class);
63      }
64  
65      private HttpCacheEntry makeEntry(final Header[] headers) {
66          return new HttpCacheEntry(elevenSecondsAgo, nineSecondsAgo, HttpStatus.SC_OK, headers, mockResource);
67      }
68  
69      @Test
70      public void testGetHeadersReturnsCorrectHeaders() {
71          final Header[] headers = { new BasicHeader("foo", "fooValue"),
72                  new BasicHeader("bar", "barValue1"),
73                  new BasicHeader("bar", "barValue2")
74          };
75          entry = makeEntry(headers);
76          assertEquals(2, entry.getHeaders("bar").length);
77      }
78  
79      @Test
80      public void testGetFirstHeaderReturnsCorrectHeader() {
81          final Header[] headers = { new BasicHeader("foo", "fooValue"),
82                  new BasicHeader("bar", "barValue1"),
83                  new BasicHeader("bar", "barValue2")
84          };
85          entry = makeEntry(headers);
86          assertEquals("barValue1", entry.getFirstHeader("bar").getValue());
87      }
88  
89      @Test
90      public void testGetHeadersReturnsEmptyArrayIfNoneMatch() {
91          final Header[] headers = { new BasicHeader("foo", "fooValue"),
92                  new BasicHeader("bar", "barValue1"),
93                  new BasicHeader("bar", "barValue2")
94          };
95          entry = makeEntry(headers);
96          assertEquals(0, entry.getHeaders("baz").length);
97      }
98  
99      @Test
100     public void testGetFirstHeaderReturnsNullIfNoneMatch() {
101         final Header[] headers = { new BasicHeader("foo", "fooValue"),
102                 new BasicHeader("bar", "barValue1"),
103                 new BasicHeader("bar", "barValue2")
104         };
105         entry = makeEntry(headers);
106         assertEquals(null, entry.getFirstHeader("quux"));
107     }
108 
109     @Test
110     public void testCacheEntryWithNoVaryHeaderDoesNotHaveVariants() {
111         final Header[] headers = new Header[0];
112         entry = makeEntry(headers);
113         assertFalse(entry.hasVariants());
114     }
115 
116     @Test
117     public void testCacheEntryWithOneVaryHeaderHasVariants() {
118         final Header[] headers = { new BasicHeader("Vary", "User-Agent") };
119         entry = makeEntry(headers);
120         assertTrue(entry.hasVariants());
121     }
122 
123     @Test
124     public void testCacheEntryWithMultipleVaryHeadersHasVariants() {
125         final Header[] headers = { new BasicHeader("Vary", "User-Agent"),
126                 new BasicHeader("Vary", "Accept-Encoding")
127         };
128         entry = makeEntry(headers);
129         assertTrue(entry.hasVariants());
130     }
131 
132     @Test
133     public void testCacheEntryWithVaryStarHasVariants(){
134         final Header[] headers = { new BasicHeader("Vary", "*") };
135         entry = makeEntry(headers);
136         assertTrue(entry.hasVariants());
137     }
138 
139     @SuppressWarnings("unused")
140     @Test
141     public void mustProvideRequestDate() {
142         try {
143             new HttpCacheEntry(null, new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
144             fail("Should have thrown exception");
145         } catch (final NullPointerException expected) {
146         }
147     }
148 
149     @SuppressWarnings("unused")
150     @Test
151     public void mustProvideResponseDate() {
152         try {
153             new HttpCacheEntry(new Date(), null, HttpStatus.SC_OK, new Header[]{}, mockResource);
154             fail("Should have thrown exception");
155         } catch (final NullPointerException expected) {
156         }
157     }
158 
159     @SuppressWarnings("unused")
160     @Test
161     public void mustProvideResponseHeaders() {
162         try {
163             new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, null, mockResource);
164             fail("Should have thrown exception");
165         } catch (final NullPointerException expected) {
166         }
167     }
168 
169     @Test
170     public void statusCodeComesFromOriginalStatusLine() {
171         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
172         assertEquals(HttpStatus.SC_OK, entry.getStatus());
173     }
174 
175     @Test
176     public void canGetOriginalRequestDate() {
177         final Date requestDate = new Date();
178         entry = new HttpCacheEntry(requestDate, new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
179         assertSame(requestDate, entry.getRequestDate());
180     }
181 
182     @Test
183     public void canGetOriginalResponseDate() {
184         final Date responseDate = new Date();
185         entry = new HttpCacheEntry(new Date(), responseDate, HttpStatus.SC_OK, new Header[]{}, mockResource);
186         assertSame(responseDate, entry.getResponseDate());
187     }
188 
189     @Test
190     public void canGetOriginalResource() {
191         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
192         assertSame(mockResource, entry.getResource());
193     }
194 
195     @Test
196     public void canGetOriginalHeaders() {
197         final Header[] headers = {
198                 new BasicHeader("Server", "MockServer/1.0"),
199                 new BasicHeader("Date", DateUtils.formatDate(now))
200         };
201         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, headers, mockResource);
202         final Header[] result = entry.getHeaders();
203         assertEquals(headers.length, result.length);
204         for(int i=0; i<headers.length; i++) {
205             assertEquals(headers[i], result[i]);
206         }
207     }
208 
209     @SuppressWarnings("unused")
210     @Test
211     public void canConstructWithoutVariants() {
212         new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK, new Header[]{}, mockResource);
213     }
214 
215     @SuppressWarnings("unused")
216     @Test
217     public void canProvideVariantMap() {
218         new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
219                 new Header[]{}, mockResource,
220                 new HashMap<String,String>());
221     }
222 
223     @Test
224     public void canRetrieveOriginalVariantMap() {
225         final Map<String,String> variantMap = new HashMap<>();
226         variantMap.put("A","B");
227         variantMap.put("C","D");
228         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
229                 new Header[]{}, mockResource,
230                 variantMap);
231         final Map<String,String> result = entry.getVariantMap();
232         assertEquals(2, result.size());
233         assertEquals("B", result.get("A"));
234         assertEquals("D", result.get("C"));
235     }
236 
237     @Test
238     public void retrievedVariantMapIsNotModifiable() {
239         final Map<String,String> variantMap = new HashMap<>();
240         variantMap.put("A","B");
241         variantMap.put("C","D");
242         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
243                 new Header[]{}, mockResource,
244                 variantMap);
245         final Map<String,String> result = entry.getVariantMap();
246         try {
247             result.remove("A");
248             fail("Should have thrown exception");
249         } catch (final UnsupportedOperationException expected) {
250         }
251         try {
252             result.put("E","F");
253             fail("Should have thrown exception");
254         } catch (final UnsupportedOperationException expected) {
255         }
256     }
257 
258     @Test
259     public void canConvertToString() {
260         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
261                 new Header[]{}, mockResource);
262         assertNotNull(entry.toString());
263         assertFalse("".equals(entry.toString()));
264     }
265 
266     @Test
267     public void testMissingDateHeaderIsIgnored() {
268         final Header[] headers = new Header[] {};
269         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
270                                    headers, mockResource);
271         assertNull(entry.getDate());
272     }
273 
274     @Test
275     public void testMalformedDateHeaderIsIgnored() {
276         final Header[] headers = new Header[] { new BasicHeader("Date", "asdf") };
277         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
278                                    headers, mockResource);
279         assertNull(entry.getDate());
280     }
281 
282     @Test
283     public void testValidDateHeaderIsParsed() {
284         final long nowMs = System.currentTimeMillis();
285         // round down to nearest second to make comparison easier
286         final Date date = new Date(nowMs - (nowMs % 1000L));
287         final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils.formatDate(date)) };
288         entry = new HttpCacheEntry(new Date(), new Date(), HttpStatus.SC_OK,
289                                    headers, mockResource);
290         final Date dateHeaderValue = entry.getDate();
291         assertNotNull(dateHeaderValue);
292         assertEquals(date.getTime(), dateHeaderValue.getTime());
293     }
294 
295     @Test
296     public void testGetMethodReturnsCorrectRequestMethod() {
297         final Header[] headers = { new BasicHeader("foo", "fooValue"),
298                 new BasicHeader("bar", "barValue1"),
299                 new BasicHeader("bar", "barValue2")
300         };
301         entry = makeEntry(headers);
302         assertEquals(HeaderConstants.GET_METHOD, entry.getRequestMethod());
303     }
304 }