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.impl.cache;
28  
29  import static org.mockito.ArgumentMatchers.isA;
30  import static org.mockito.ArgumentMatchers.same;
31  import static org.mockito.Mockito.mock;
32  import static org.mockito.Mockito.verify;
33  import static org.mockito.Mockito.when;
34  
35  import java.util.Date;
36  import java.util.HashMap;
37  
38  import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
39  import org.apache.hc.client5.http.cache.HttpCacheEntry;
40  import org.apache.hc.core5.http.ClassicHttpRequest;
41  import org.apache.hc.core5.http.Header;
42  import org.apache.hc.core5.http.message.BasicHeader;
43  import org.apache.hc.core5.util.TimeValue;
44  import org.junit.Assert;
45  import org.junit.Before;
46  import org.junit.Test;
47  
48  @SuppressWarnings({"boxing","static-access"}) // test code
49  public class TestCachedHttpResponseGenerator {
50  
51      private HttpCacheEntry entry;
52      private ClassicHttpRequest request;
53      private CacheValidityPolicy mockValidityPolicy;
54      private CachedHttpResponseGenerator impl;
55  
56      @Before
57      public void setUp() {
58          entry = HttpTestUtils.makeCacheEntry(new HashMap<String, String>());
59          request = HttpTestUtils.makeDefaultRequest();
60          mockValidityPolicy = mock(CacheValidityPolicy.class);
61          impl = new CachedHttpResponseGenerator(mockValidityPolicy);
62      }
63  
64      @Test
65      public void testResponseHasContentLength() throws Exception {
66          final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
67          final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(buf);
68  
69          final SimpleHttpResponse response = impl.generateResponse(request, entry1);
70  
71          final Header length = response.getFirstHeader("Content-Length");
72          Assert.assertNotNull("Content-Length Header is missing", length);
73  
74          Assert.assertEquals("Content-Length does not match buffer length", buf.length, Integer
75                  .parseInt(length.getValue()));
76      }
77  
78      @Test
79      public void testContentLengthIsNotAddedWhenTransferEncodingIsPresent() throws Exception {
80  
81          final Header[] hdrs = new Header[] { new BasicHeader("Transfer-Encoding", "chunked") };
82          final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
83          final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(hdrs, buf);
84  
85          final SimpleHttpResponse response = impl.generateResponse(request, entry1);
86  
87          final Header length = response.getFirstHeader("Content-Length");
88  
89          Assert.assertNull(length);
90      }
91  
92      @Test
93      public void testResponseMatchesCacheEntry() throws Exception {
94          final SimpleHttpResponse response = impl.generateResponse(request, entry);
95  
96          Assert.assertTrue(response.containsHeader("Content-Length"));
97  
98          Assert.assertSame("HTTP", response.getVersion().getProtocol());
99          Assert.assertEquals(1, response.getVersion().getMajor());
100         Assert.assertEquals(1, response.getVersion().getMinor());
101     }
102 
103     @Test
104     public void testResponseStatusCodeMatchesCacheEntry() throws Exception {
105         final SimpleHttpResponse response = impl.generateResponse(request, entry);
106 
107         Assert.assertEquals(entry.getStatus(), response.getCode());
108     }
109 
110     @Test
111     public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() throws Exception {
112         currentAge(TimeValue.ofSeconds(10L));
113 
114         final SimpleHttpResponse response = impl.generateResponse(request, entry);
115 
116         verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Date.class));
117 
118         final Header ageHdr = response.getFirstHeader("Age");
119         Assert.assertNotNull(ageHdr);
120         Assert.assertEquals(10L, Long.parseLong(ageHdr.getValue()));
121     }
122 
123     @Test
124     public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() throws Exception {
125         currentAge(TimeValue.ofSeconds(0L));
126 
127         final SimpleHttpResponse response = impl.generateResponse(request, entry);
128 
129         verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Date.class));
130 
131         final Header ageHdr = response.getFirstHeader("Age");
132         Assert.assertNull(ageHdr);
133     }
134 
135     @Test
136     public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() throws Exception {
137         currentAge(TimeValue.ofSeconds(CacheValidityPolicy.MAX_AGE.toSeconds() + 1L));
138 
139         final SimpleHttpResponse response = impl.generateResponse(request, entry);
140 
141         verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Date.class));
142 
143         final Header ageHdr = response.getFirstHeader("Age");
144         Assert.assertNotNull(ageHdr);
145         Assert.assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), Long.parseLong(ageHdr.getValue()));
146     }
147 
148     private void currentAge(final TimeValue age) {
149         when(
150                 mockValidityPolicy.getCurrentAge(same(entry),
151                         isA(Date.class))).thenReturn(age);
152     }
153 
154     @Test
155     public void testResponseContainsEntityToServeGETRequestIfEntryContainsResource() throws Exception {
156         final SimpleHttpResponse response = impl.generateResponse(request, entry);
157 
158         Assert.assertNotNull(response.getBody());
159     }
160 
161     @Test
162     public void testResponseDoesNotContainEntityToServeHEADRequestIfEntryContainsResource() throws Exception {
163         final ClassicHttpRequest headRequest = HttpTestUtils.makeDefaultHEADRequest();
164         final SimpleHttpResponse response = impl.generateResponse(headRequest, entry);
165 
166         Assert.assertNull(response.getBody());
167     }
168 
169 }