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
28 package org.apache.hc.client5.http.impl.cache;
29
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.nio.charset.StandardCharsets;
37 import java.util.Collections;
38 import java.util.Date;
39 import java.util.Map;
40
41 import org.apache.hc.client5.http.cache.HttpCacheEntry;
42 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
43 import org.apache.hc.client5.http.cache.HttpCacheStorageEntry;
44 import org.apache.hc.client5.http.cache.Resource;
45 import org.apache.hc.client5.http.cache.ResourceIOException;
46 import org.apache.hc.core5.http.Header;
47 import org.apache.hc.core5.http.message.BasicHeader;
48
49 import static org.junit.Assert.assertArrayEquals;
50 import static org.junit.Assert.assertEquals;
51 import static org.junit.Assert.assertNull;
52 import static org.junit.Assert.fail;
53
54 class HttpByteArrayCacheEntrySerializerTestUtils {
55 private final static String TEST_RESOURCE_DIR = "src/test/resources/";
56 static final String TEST_STORAGE_KEY = "xyzzy";
57
58
59
60
61 static class HttpCacheStorageEntryTestTemplate {
62 Resource resource;
63 Date requestDate;
64 Date responseDate;
65 int responseCode;
66 Header[] responseHeaders;
67 Map<String, String> variantMap;
68 String storageKey;
69
70
71
72
73
74
75 static HttpCacheStorageEntryTestTemplate makeDefault() {
76 return new HttpCacheStorageEntryTestTemplate(DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE);
77 }
78
79
80
81
82
83 HttpCacheStorageEntry toEntry() {
84 return new HttpCacheStorageEntry(storageKey,
85 new HttpCacheEntry(
86 requestDate,
87 responseDate,
88 responseCode,
89 responseHeaders,
90 resource,
91 variantMap));
92 }
93
94
95
96
97 private HttpCacheStorageEntryTestTemplate() {
98 }
99
100
101
102
103
104
105 private HttpCacheStorageEntryTestTemplate(final HttpCacheStorageEntryTestTemplate src) {
106 this.resource = src.resource;
107 this.requestDate = src.requestDate;
108 this.responseDate = src.responseDate;
109 this.responseCode = src.responseCode;
110 this.responseHeaders = src.responseHeaders;
111 this.variantMap = src.variantMap;
112 this.storageKey = src.storageKey;
113 }
114 }
115
116
117
118
119
120
121 private static final HttpCacheStorageEntryTestTemplate DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE = new HttpCacheStorageEntryTestTemplate();
122 static {
123 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.resource = new HeapResource("Hello World".getBytes(StandardCharsets.UTF_8));
124 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.requestDate = new Date(165214800000L);
125 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.responseDate = new Date(2611108800000L);
126 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.responseCode = 200;
127 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.responseHeaders = new Header[]{
128 new BasicHeader("Content-type", "text/html"),
129 new BasicHeader("Cache-control", "public, max-age=31536000"),
130 };
131 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.variantMap = Collections.emptyMap();
132 DEFAULT_HTTP_CACHE_STORAGE_ENTRY_TEST_TEMPLATE.storageKey = TEST_STORAGE_KEY;
133 }
134
135
136
137
138
139
140
141
142
143
144 static void testWithCache(final HttpCacheEntrySerializer<byte[]> serializer, final HttpCacheStorageEntry httpCacheStorageEntry) throws Exception {
145 final byte[] testBytes = serializer.serialize(httpCacheStorageEntry);
146 verifyHttpCacheEntryFromBytes(serializer, httpCacheStorageEntry, testBytes);
147 }
148
149
150
151
152
153
154
155
156
157 static void verifyHttpCacheEntryFromBytes(final HttpCacheEntrySerializer<byte[]> serializer, final HttpCacheStorageEntry httpCacheStorageEntry, final byte[] testBytes) throws Exception {
158 final HttpCacheStorageEntry testEntry = httpCacheStorageEntryFromBytes(serializer, testBytes);
159
160 assertCacheEntriesEqual(httpCacheStorageEntry, testEntry);
161 }
162
163
164
165
166
167
168
169
170
171
172 static void verifyHttpCacheEntryFromTestFile(final HttpCacheEntrySerializer<byte[]> serializer,
173 final HttpCacheStorageEntry httpCacheStorageEntry,
174 final String testFileName,
175 final boolean reserializeFiles) throws Exception {
176 if (reserializeFiles) {
177 final File toFile = makeTestFileObject(testFileName);
178 saveEntryToFile(serializer, httpCacheStorageEntry, toFile);
179 }
180
181 final byte[] bytes = readTestFileBytes(testFileName);
182
183 verifyHttpCacheEntryFromBytes(serializer, httpCacheStorageEntry, bytes);
184 }
185
186
187
188
189
190
191
192
193 static byte[] readTestFileBytes(final String testFileName) throws Exception {
194 final File testFile = makeTestFileObject(testFileName);
195 try(final FileInputStream testStream = new FileInputStream(testFile)) {
196 return readFullyStrict(testStream, testFile.length());
197 }
198 }
199
200
201
202
203
204
205
206
207 static HttpCacheStorageEntry httpCacheStorageEntryFromBytes(final HttpCacheEntrySerializer<byte[]> serializer, final byte[] testBytes) throws ResourceIOException {
208 return serializer.deserialize(testBytes);
209 }
210
211
212
213
214
215
216
217
218 static void assertCacheEntriesEqual(final HttpCacheStorageEntry expected, final HttpCacheStorageEntry actual) throws Exception {
219 assertEquals(expected.getKey(), actual.getKey());
220
221 final HttpCacheEntry expectedContent = expected.getContent();
222 final HttpCacheEntry actualContent = actual.getContent();
223
224 assertEquals(expectedContent.getRequestDate(), actualContent.getRequestDate());
225 assertEquals(expectedContent.getResponseDate(), actualContent.getResponseDate());
226 assertEquals(expectedContent.getStatus(), actualContent.getStatus());
227
228 assertArrayEquals(expectedContent.getVariantMap().keySet().toArray(), actualContent.getVariantMap().keySet().toArray());
229 for (final String key : expectedContent.getVariantMap().keySet()) {
230 assertEquals("Expected same variantMap values for key '" + key + "'",
231 expectedContent.getVariantMap().get(key), actualContent.getVariantMap().get(key));
232 }
233
234
235 for(final Header expectedHeader: expectedContent.getHeaders()) {
236 final Header actualHeader = actualContent.getFirstHeader(expectedHeader.getName());
237
238 if (actualHeader == null) {
239 if (expectedHeader.getName().equalsIgnoreCase("content-length")) {
240
241 } else {
242 fail("Expected header " + expectedHeader.getName() + " was not found");
243 }
244 } else {
245 assertEquals(expectedHeader.getName(), actualHeader.getName());
246 assertEquals(expectedHeader.getValue(), actualHeader.getValue());
247 }
248 }
249
250 if (expectedContent.getResource() == null) {
251 assertNull("Expected null resource", actualContent.getResource());
252 } else {
253 final byte[] expectedBytes = readFullyStrict(
254 expectedContent.getResource().getInputStream(),
255 (int) expectedContent.getResource().length()
256 );
257 final byte[] actualBytes = readFullyStrict(
258 actualContent.getResource().getInputStream(),
259 (int) actualContent.getResource().length()
260 );
261 assertArrayEquals(expectedBytes, actualBytes);
262 }
263 }
264
265
266
267
268
269
270
271 static File makeTestFileObject(final String testFileName) {
272 return new File(TEST_RESOURCE_DIR + testFileName);
273 }
274
275
276
277
278
279
280
281
282
283 static void saveEntryToFile(final HttpCacheEntrySerializer<byte[]> serializer, final HttpCacheStorageEntry httpCacheStorageEntry, final File outFile) throws Exception {
284 final byte[] bytes = serializer.serialize(httpCacheStorageEntry);
285
286 OutputStream out = null;
287 try {
288 out = new FileOutputStream(outFile);
289 out.write(bytes);
290 } finally {
291 if (out != null) {
292 out.close();
293 }
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306 private static int readFully(final InputStream src, final byte[] dest) throws IOException {
307 final int destPos = 0;
308 final int length = dest.length;
309 int totalBytesRead = 0;
310 int lastBytesRead;
311
312 while (totalBytesRead < length && (lastBytesRead = src.read(dest, destPos + totalBytesRead, length - totalBytesRead)) != -1) {
313 totalBytesRead += lastBytesRead;
314 }
315 return totalBytesRead;
316 }
317
318
319
320
321
322
323
324
325
326
327
328 static byte[] readFullyStrict(final InputStream src, final long length) throws IOException {
329 if (length > Integer.MAX_VALUE) {
330 throw new IllegalArgumentException(String.format("Length %d is too large to fit in an array", length));
331 }
332 final int intLength = (int) length;
333 final byte[] dest = new byte[intLength];
334 final int bytesRead = readFully(src, dest);
335
336 if (bytesRead == intLength) {
337 return dest;
338 } else {
339 throw new IOException(String.format("Expected to read %d bytes but only got %d", intLength, bytesRead));
340 }
341 }
342 }