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 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 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.jupiter.api.Assertions;
45 import org.junit.jupiter.api.BeforeEach;
46 import org.junit.jupiter.api.Test;
47
48 @SuppressWarnings({"boxing","static-access"})
49 public class TestCachedHttpResponseGenerator {
50
51 private HttpCacheEntry entry;
52 private ClassicHttpRequest request;
53 private CacheValidityPolicy mockValidityPolicy;
54 private CachedHttpResponseGenerator impl;
55
56 @BeforeEach
57 public void setUp() {
58 entry = HttpTestUtils.makeCacheEntry(new HashMap<>());
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 Assertions.assertNotNull(length, "Content-Length Header is missing");
73
74 Assertions.assertEquals(buf.length, Integer.parseInt(length.getValue()), "Content-Length does not match buffer length");
75 }
76
77 @Test
78 public void testContentLengthIsNotAddedWhenTransferEncodingIsPresent() throws Exception {
79
80 final Header[] hdrs = new Header[] { new BasicHeader("Transfer-Encoding", "chunked") };
81 final byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
82 final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry(hdrs, buf);
83
84 final SimpleHttpResponse response = impl.generateResponse(request, entry1);
85
86 final Header length = response.getFirstHeader("Content-Length");
87
88 Assertions.assertNull(length);
89 }
90
91 @Test
92 public void testResponseMatchesCacheEntry() throws Exception {
93 final SimpleHttpResponse response = impl.generateResponse(request, entry);
94
95 Assertions.assertTrue(response.containsHeader("Content-Length"));
96
97 Assertions.assertSame("HTTP", response.getVersion().getProtocol());
98 Assertions.assertEquals(1, response.getVersion().getMajor());
99 Assertions.assertEquals(1, response.getVersion().getMinor());
100 }
101
102 @Test
103 public void testResponseStatusCodeMatchesCacheEntry() throws Exception {
104 final SimpleHttpResponse response = impl.generateResponse(request, entry);
105
106 Assertions.assertEquals(entry.getStatus(), response.getCode());
107 }
108
109 @Test
110 public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() throws Exception {
111 currentAge(TimeValue.ofSeconds(10L));
112
113 final SimpleHttpResponse response = impl.generateResponse(request, entry);
114
115 verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Instant.class));
116
117 final Header ageHdr = response.getFirstHeader("Age");
118 Assertions.assertNotNull(ageHdr);
119 Assertions.assertEquals(10L, Long.parseLong(ageHdr.getValue()));
120 }
121
122 @Test
123 public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() throws Exception {
124 currentAge(TimeValue.ofSeconds(0L));
125
126 final SimpleHttpResponse response = impl.generateResponse(request, entry);
127
128 verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Instant.class));
129
130 final Header ageHdr = response.getFirstHeader("Age");
131 Assertions.assertNull(ageHdr);
132 }
133
134 @Test
135 public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() throws Exception {
136 currentAge(TimeValue.ofSeconds(CacheValidityPolicy.MAX_AGE.toSeconds() + 1L));
137
138 final SimpleHttpResponse response = impl.generateResponse(request, entry);
139
140 verify(mockValidityPolicy).getCurrentAge(same(entry), isA(Instant.class));
141
142 final Header ageHdr = response.getFirstHeader("Age");
143 Assertions.assertNotNull(ageHdr);
144 Assertions.assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), Long.parseLong(ageHdr.getValue()));
145 }
146
147 private void currentAge(final TimeValue age) {
148 when(
149 mockValidityPolicy.getCurrentAge(same(entry),
150 isA(Instant.class))).thenReturn(age);
151 }
152
153 @Test
154 public void testResponseContainsEntityToServeGETRequestIfEntryContainsResource() throws Exception {
155 final SimpleHttpResponse response = impl.generateResponse(request, entry);
156
157 Assertions.assertNotNull(response.getBody());
158 }
159
160 @Test
161 public void testResponseDoesNotContainEntityToServeHEADRequestIfEntryContainsResource() throws Exception {
162 final ClassicHttpRequest headRequest = HttpTestUtils.makeDefaultHEADRequest();
163 final SimpleHttpResponse response = impl.generateResponse(headRequest, entry);
164
165 Assertions.assertNull(response.getBody());
166 }
167
168 }