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.time.Instant;
36  
37  import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
38  import org.apache.hc.client5.http.cache.HttpCacheEntry;
39  import org.apache.hc.core5.http.ClassicHttpRequest;
40  import org.apache.hc.core5.http.Header;
41  import org.apache.hc.core5.util.TimeValue;
42  import org.junit.jupiter.api.Assertions;
43  import org.junit.jupiter.api.BeforeEach;
44  import org.junit.jupiter.api.Test;
45  
46  @SuppressWarnings({"boxing","static-access"}) // test code
47  public class TestCachedHttpResponseGenerator {
48  
49      private HttpCacheEntry entry;
50      private ClassicHttpRequest request;
51      private CacheValidityPolicy mockValidityPolicy;
52      private CachedHttpResponseGenerator impl;
53  
54      @BeforeEach
55      public void setUp() {
56          entry = HttpTestUtils.makeCacheEntry();
57          request = HttpTestUtils.makeDefaultRequest();
58          mockValidityPolicy = mock(CacheValidityPolicy.class);
59          impl = new CachedHttpResponseGenerator(mockValidityPolicy);
60      }
61  
62      @Test
63      public void testResponseHasContentLength() throws Exception {
64          final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
65          final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(buf);
66  
67          final SimpleHttpResponse response = impl.generateResponse(request, entry1);
68  
69          final Header length = response.getFirstHeader("Content-Length");
70          Assertions.assertNotNull(length, "Content-Length Header is missing");
71  
72          Assertions.assertEquals(buf.length, Integer.parseInt(length.getValue()), "Content-Length does not match buffer length");
73      }
74  
75      @Test
76      public void testResponseStatusCodeMatchesCacheEntry() throws Exception {
77          final SimpleHttpResponse response = impl.generateResponse(request, entry);
78  
79          Assertions.assertEquals(entry.getStatus(), response.getCode());
80      }
81  
82      @Test
83      public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() throws Exception {
84          currentAge(TimeValue.ofSeconds(10L));
85  
86          final SimpleHttpResponse response = impl.generateResponse(request, entry);
87  
88          verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Instant.class));
89  
90          final Header ageHdr = response.getFirstHeader("Age");
91          Assertions.assertNotNull(ageHdr);
92          Assertions.assertEquals(10L, Long.parseLong(ageHdr.getValue()));
93      }
94  
95      @Test
96      public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() throws Exception {
97          currentAge(TimeValue.ofSeconds(0L));
98  
99          final SimpleHttpResponse response = impl.generateResponse(request, entry);
100 
101         verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Instant.class));
102 
103         final Header ageHdr = response.getFirstHeader("Age");
104         Assertions.assertNull(ageHdr);
105     }
106 
107     @Test
108     public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() throws Exception {
109         currentAge(TimeValue.ofSeconds(CacheSupport.MAX_AGE.toSeconds() + 1L));
110 
111         final SimpleHttpResponse response = impl.generateResponse(request, entry);
112 
113         verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Instant.class));
114 
115         final Header ageHdr = response.getFirstHeader("Age");
116         Assertions.assertNotNull(ageHdr);
117         Assertions.assertEquals(CacheSupport.MAX_AGE.toSeconds(), Long.parseLong(ageHdr.getValue()));
118     }
119 
120     private void currentAge(final TimeValue age) {
121         when(
122                 mockValidityPolicy.getCurrentAge(same(entry),
123                         isA(Instant.class))).thenReturn(age);
124     }
125 
126     @Test
127     public void testResponseContainsEntityToServeGETRequestIfEntryContainsResource() throws Exception {
128         final SimpleHttpResponse response = impl.generateResponse(request, entry);
129 
130         Assertions.assertNotNull(response.getBody());
131     }
132 
133     @Test
134     public void testResponseDoesNotContainEntityToServeHEADRequestIfEntryContainsResource() throws Exception {
135         final ClassicHttpRequest headRequest = HttpTestUtils.makeDefaultHEADRequest();
136         final SimpleHttpResponse response = impl.generateResponse(headRequest, entry);
137 
138         Assertions.assertNull(response.getBody());
139     }
140 
141 }