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.Mockito.verify;
30 import static org.mockito.Mockito.verifyNoMoreInteractions;
31 import static org.mockito.Mockito.when;
32
33 import java.io.IOException;
34 import java.net.URI;
35 import java.util.Date;
36 import java.util.HashMap;
37 import java.util.Map;
38
39 import org.apache.hc.client5.http.cache.HttpCacheEntry;
40 import org.apache.hc.client5.http.cache.HttpCacheStorage;
41 import org.apache.hc.client5.http.utils.DateUtils;
42 import org.apache.hc.core5.function.Resolver;
43 import org.apache.hc.core5.http.Header;
44 import org.apache.hc.core5.http.HttpHost;
45 import org.apache.hc.core5.http.HttpRequest;
46 import org.apache.hc.core5.http.HttpResponse;
47 import org.apache.hc.core5.http.HttpStatus;
48 import org.apache.hc.core5.http.message.BasicHeader;
49 import org.apache.hc.core5.http.message.BasicHttpRequest;
50 import org.apache.hc.core5.http.message.BasicHttpResponse;
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.ArgumentMatchers;
55 import org.mockito.Mock;
56 import org.mockito.invocation.InvocationOnMock;
57 import org.mockito.junit.MockitoJUnitRunner;
58 import org.mockito.stubbing.Answer;
59
60 @RunWith(MockitoJUnitRunner.class)
61 public class TestDefaultCacheInvalidator {
62
63 private DefaultCacheInvalidator impl;
64 private HttpHost host;
65 @Mock
66 private HttpCacheEntry mockEntry;
67 @Mock
68 private Resolver<URI, String> cacheKeyResolver;
69 @Mock
70 private HttpCacheStorage mockStorage;
71
72 private Date now;
73 private Date tenSecondsAgo;
74
75 @Before
76 public void setUp() {
77 now = new Date();
78 tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
79
80 when(cacheKeyResolver.resolve(ArgumentMatchers.<URI>any())).thenAnswer(new Answer<String>() {
81
82 @Override
83 public String answer(final InvocationOnMock invocation) throws Throwable {
84 final URI uri = invocation.getArgument(0);
85 return HttpCacheSupport.normalize(uri).toASCIIString();
86 }
87
88 });
89
90 host = new HttpHost("foo.example.com");
91 impl = new DefaultCacheInvalidator();
92 }
93
94
95 @Test
96 public void testInvalidatesRequestsThatArentGETorHEAD() throws Exception {
97 final HttpRequest request = new BasicHttpRequest("POST","/path");
98 final String key = "http://foo.example.com:80/path";
99 final Map<String,String> variantMap = new HashMap<>();
100 cacheEntryHasVariantMap(variantMap);
101
102 cacheReturnsEntryForUri(key);
103
104 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
105
106 verify(mockEntry).getVariantMap();
107 verify(mockStorage).getEntry(key);
108 verify(mockStorage).removeEntry(key);
109 }
110
111 @Test
112 public void testInvalidatesUrisInContentLocationHeadersOnPUTs() throws Exception {
113 final HttpRequest request = new BasicHttpRequest("PUT","/");
114 request.setHeader("Content-Length","128");
115
116 final String contentLocation = "http://foo.example.com/content";
117 request.setHeader("Content-Location", contentLocation);
118
119 final URI uri = new URI("http://foo.example.com:80/");
120 final String key = uri.toASCIIString();
121 cacheEntryHasVariantMap(new HashMap<String,String>());
122
123 cacheReturnsEntryForUri(key);
124
125 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
126
127 verify(mockEntry).getVariantMap();
128 verify(mockStorage).getEntry(key);
129 verify(mockStorage).removeEntry(key);
130 verify(mockStorage).removeEntry("http://foo.example.com:80/content");
131 }
132
133 @Test
134 public void testInvalidatesUrisInLocationHeadersOnPUTs() throws Exception {
135 final HttpRequest request = new BasicHttpRequest("PUT","/");
136 request.setHeader("Content-Length","128");
137
138 final String contentLocation = "http://foo.example.com/content";
139 request.setHeader("Location",contentLocation);
140
141 final URI uri = new URI("http://foo.example.com:80/");
142 final String key = uri.toASCIIString();
143 cacheEntryHasVariantMap(new HashMap<String,String>());
144
145 cacheReturnsEntryForUri(key);
146
147 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
148
149 verify(mockEntry).getVariantMap();
150 verify(mockStorage).getEntry(key);
151 verify(mockStorage).removeEntry(key);
152 verify(mockStorage).removeEntry("http://foo.example.com:80/content");
153 }
154
155 @Test
156 public void testInvalidatesRelativeUrisInContentLocationHeadersOnPUTs() throws Exception {
157 final HttpRequest request = new BasicHttpRequest("PUT","/");
158 request.setHeader("Content-Length","128");
159
160 final String relativePath = "/content";
161 request.setHeader("Content-Location",relativePath);
162
163 final URI uri = new URI("http://foo.example.com:80/");
164 final String key = uri.toASCIIString();
165 cacheEntryHasVariantMap(new HashMap<String,String>());
166
167 cacheReturnsEntryForUri(key);
168
169 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
170
171 verify(mockEntry).getVariantMap();
172 verify(mockStorage).getEntry(key);
173 verify(mockStorage).removeEntry(key);
174 verify(mockStorage).removeEntry("http://foo.example.com:80/content");
175 }
176
177 @Test
178 public void testDoesNotInvalidateUrisInContentLocationHeadersOnPUTsToDifferentHosts() throws Exception {
179 final HttpRequest request = new BasicHttpRequest("PUT","/");
180 request.setHeader("Content-Length","128");
181
182 final String contentLocation = "http://bar.example.com/content";
183 request.setHeader("Content-Location",contentLocation);
184
185 final URI uri = new URI("http://foo.example.com:80/");
186 final String key = uri.toASCIIString();
187 cacheEntryHasVariantMap(new HashMap<String,String>());
188
189 cacheReturnsEntryForUri(key);
190
191 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
192
193 verify(mockEntry).getVariantMap();
194 verify(mockStorage).getEntry(key);
195 verify(mockStorage).removeEntry(key);
196 }
197
198 @Test
199 public void testDoesNotInvalidateGETRequest() throws Exception {
200 final HttpRequest request = new BasicHttpRequest("GET","/");
201 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
202
203 verify(mockStorage).getEntry("http://foo.example.com:80/");
204 verifyNoMoreInteractions(mockStorage);
205 }
206
207 @Test
208 public void testDoesNotInvalidateHEADRequest() throws Exception {
209 final HttpRequest request = new BasicHttpRequest("HEAD","/");
210 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
211
212 verify(mockStorage).getEntry("http://foo.example.com:80/");
213 verifyNoMoreInteractions(mockStorage);
214 }
215
216 @Test
217 public void testInvalidatesHEADCacheEntryIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception {
218 final URI uri = new URI("http://foo.example.com:80/");
219 final String key = uri.toASCIIString();
220 final HttpRequest request = new BasicHttpRequest("GET", uri);
221
222 cacheEntryisForMethod("HEAD");
223 cacheEntryHasVariantMap(new HashMap<String, String>());
224 cacheReturnsEntryForUri(key);
225
226 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
227
228 verify(mockEntry).getRequestMethod();
229 verify(mockEntry).getVariantMap();
230 verify(mockStorage).getEntry(key);
231 verify(mockStorage).removeEntry(key);
232 }
233
234 @Test
235 public void testInvalidatesVariantHEADCacheEntriesIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception {
236 final URI uri = new URI("http://foo.example.com:80/");
237 final String key = uri.toASCIIString();
238 final HttpRequest request = new BasicHttpRequest("GET", uri);
239 final String theVariantKey = "{Accept-Encoding=gzip%2Cdeflate&User-Agent=Apache-HttpClient}";
240 final String theVariantURI = "{Accept-Encoding=gzip%2Cdeflate&User-Agent=Apache-HttpClient}http://foo.example.com:80/";
241 final Map<String, String> variants = HttpTestUtils.makeDefaultVariantMap(theVariantKey, theVariantURI);
242
243 cacheEntryisForMethod("HEAD");
244 cacheEntryHasVariantMap(variants);
245 cacheReturnsEntryForUri(key);
246
247 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
248
249 verify(mockEntry).getRequestMethod();
250 verify(mockEntry).getVariantMap();
251 verify(mockStorage).getEntry(key);
252 verify(mockStorage).removeEntry(key);
253 verify(mockStorage).removeEntry(theVariantURI);
254 }
255
256 @Test
257 public void testDoesNotInvalidateHEADCacheEntry() throws Exception {
258 final URI uri = new URI("http://foo.example.com:80/");
259 final String key = uri.toASCIIString();
260 final HttpRequest request = new BasicHttpRequest("HEAD", uri);
261
262 cacheReturnsEntryForUri(key);
263
264 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
265
266 verify(mockStorage).getEntry(key);
267 verifyNoMoreInteractions(mockStorage);
268 }
269
270 @Test
271 public void testDoesNotInvalidateHEADCacheEntryIfSubsequentHEADRequestsAreMadeToTheSameURI() throws Exception {
272 final URI uri = new URI("http://foo.example.com:80/");
273 final String key = uri.toASCIIString();
274 final HttpRequest request = new BasicHttpRequest("HEAD", uri);
275
276 cacheReturnsEntryForUri(key);
277
278 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
279
280 verify(mockStorage).getEntry(key);
281 verifyNoMoreInteractions(mockStorage);
282 }
283
284 @Test
285 public void testDoesNotInvalidateGETCacheEntryIfSubsequentGETRequestsAreMadeToTheSameURI() throws Exception {
286 final URI uri = new URI("http://foo.example.com:80/");
287 final String key = uri.toASCIIString();
288 final HttpRequest request = new BasicHttpRequest("GET", uri);
289
290 cacheEntryisForMethod("GET");
291 cacheReturnsEntryForUri(key);
292
293 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
294
295 verify(mockEntry).getRequestMethod();
296 verify(mockStorage).getEntry(key);
297 verifyNoMoreInteractions(mockStorage);
298 }
299
300 @Test
301 public void testDoesNotInvalidateRequestsWithClientCacheControlHeaders() throws Exception {
302 final HttpRequest request = new BasicHttpRequest("GET","/");
303 request.setHeader("Cache-Control","no-cache");
304
305 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
306
307 verify(mockStorage).getEntry("http://foo.example.com:80/");
308 verifyNoMoreInteractions(mockStorage);
309 }
310
311 @Test
312 public void testDoesNotInvalidateRequestsWithClientPragmaHeaders() throws Exception {
313 final HttpRequest request = new BasicHttpRequest("GET","/");
314 request.setHeader("Pragma","no-cache");
315
316 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
317
318 verify(mockStorage).getEntry("http://foo.example.com:80/");
319 verifyNoMoreInteractions(mockStorage);
320 }
321
322 @Test
323 public void testVariantURIsAreFlushedAlso() throws Exception {
324 final HttpRequest request = new BasicHttpRequest("POST","/");
325 final URI uri = new URI("http://foo.example.com:80/");
326 final String key = uri.toASCIIString();
327 final String variantUri = "theVariantURI";
328 final Map<String,String> mapOfURIs = HttpTestUtils.makeDefaultVariantMap(variantUri, variantUri);
329
330 cacheReturnsEntryForUri(key);
331 cacheEntryHasVariantMap(mapOfURIs);
332
333 impl.flushCacheEntriesInvalidatedByRequest(host, request, cacheKeyResolver, mockStorage);
334
335 verify(mockStorage).getEntry(key);
336 verify(mockEntry).getVariantMap();
337 verify(mockStorage).removeEntry(variantUri);
338 verify(mockStorage).removeEntry(key);
339 }
340
341 @Test
342 public void doesNotFlushForResponsesWithoutContentLocation() throws Exception {
343 final HttpRequest request = new BasicHttpRequest("POST","/");
344 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
345 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
346
347 verifyNoMoreInteractions(mockStorage);
348 }
349
350 @Test
351 public void flushesEntryIfFresherAndSpecifiedByContentLocation() throws Exception {
352 final HttpRequest request = new BasicHttpRequest("GET", "/");
353 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
354 response.setHeader("ETag","\"new-etag\"");
355 response.setHeader("Date", DateUtils.formatDate(now));
356 final String key = "http://foo.example.com:80/bar";
357 response.setHeader("Content-Location", key);
358
359 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
360 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
361 new BasicHeader("ETag", "\"old-etag\"")
362 });
363
364 when(mockStorage.getEntry(key)).thenReturn(entry);
365
366 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
367
368 verify(mockStorage).getEntry(key);
369 verify(mockStorage).removeEntry(key);
370 }
371
372 @Test
373 public void flushesEntryIfFresherAndSpecifiedByLocation() throws Exception {
374 final HttpRequest request = new BasicHttpRequest("GET", "/");
375 final HttpResponse response = new BasicHttpResponse(201);
376 response.setHeader("ETag","\"new-etag\"");
377 response.setHeader("Date", DateUtils.formatDate(now));
378 final String key = "http://foo.example.com:80/bar";
379 response.setHeader("Location", key);
380
381 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
382 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
383 new BasicHeader("ETag", "\"old-etag\"")
384 });
385
386 when(mockStorage.getEntry(key)).thenReturn(entry);
387
388 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
389
390 verify(mockStorage).getEntry(key);
391 verify(mockStorage).removeEntry(key);
392 }
393
394 @Test
395 public void doesNotFlushEntryForUnsuccessfulResponse() throws Exception {
396 final HttpRequest request = new BasicHttpRequest("GET", "/");
397 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_BAD_REQUEST, "Bad Request");
398 response.setHeader("ETag","\"new-etag\"");
399 response.setHeader("Date", DateUtils.formatDate(now));
400 final String key = "http://foo.example.com:80/bar";
401 response.setHeader("Content-Location", key);
402
403 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
404
405 verifyNoMoreInteractions(mockStorage);
406 }
407
408 @Test
409 public void flushesEntryIfFresherAndSpecifiedByNonCanonicalContentLocation() throws Exception {
410 final HttpRequest request = new BasicHttpRequest("GET", "/");
411 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
412 response.setHeader("ETag","\"new-etag\"");
413 response.setHeader("Date", DateUtils.formatDate(now));
414 final String cacheKey = "http://foo.example.com:80/bar";
415 response.setHeader("Content-Location", "http://foo.example.com/bar");
416
417 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
418 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
419 new BasicHeader("ETag", "\"old-etag\"")
420 });
421
422 when(mockStorage.getEntry(cacheKey)).thenReturn(entry);
423
424 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
425
426 verify(mockStorage).getEntry(cacheKey);
427 verify(mockStorage).removeEntry(cacheKey);
428 }
429
430 @Test
431 public void flushesEntryIfFresherAndSpecifiedByRelativeContentLocation() throws Exception {
432 final HttpRequest request = new BasicHttpRequest("GET", "/");
433 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
434 response.setHeader("ETag","\"new-etag\"");
435 response.setHeader("Date", DateUtils.formatDate(now));
436 final String cacheKey = "http://foo.example.com:80/bar";
437 response.setHeader("Content-Location", "/bar");
438
439 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
440 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
441 new BasicHeader("ETag", "\"old-etag\"")
442 });
443
444 when(mockStorage.getEntry(cacheKey)).thenReturn(entry);
445
446 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
447
448 verify(mockStorage).getEntry(cacheKey);
449 verify(mockStorage).removeEntry(cacheKey);
450 }
451
452 @Test
453 public void doesNotFlushEntryIfContentLocationFromDifferentHost() throws Exception {
454 final HttpRequest request = new BasicHttpRequest("GET", "/");
455 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
456 response.setHeader("ETag","\"new-etag\"");
457 response.setHeader("Date", DateUtils.formatDate(now));
458 final String cacheKey = "http://baz.example.com:80/bar";
459 response.setHeader("Content-Location", cacheKey);
460
461 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
462
463 verifyNoMoreInteractions(mockStorage);
464 }
465
466 @Test
467 public void doesNotFlushEntrySpecifiedByContentLocationIfEtagsMatch() throws Exception {
468 final HttpRequest request = new BasicHttpRequest("GET", "/");
469 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
470 response.setHeader("ETag","\"same-etag\"");
471 response.setHeader("Date", DateUtils.formatDate(now));
472 final String key = "http://foo.example.com:80/bar";
473 response.setHeader("Content-Location", key);
474
475 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
476 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
477 new BasicHeader("ETag", "\"same-etag\"")
478 });
479
480 when(mockStorage.getEntry(key)).thenReturn(entry);
481 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
482
483 verify(mockStorage).getEntry(key);
484 verifyNoMoreInteractions(mockStorage);
485 }
486
487 @Test
488 public void doesNotFlushEntrySpecifiedByContentLocationIfOlder() throws Exception {
489 final HttpRequest request = new BasicHttpRequest("GET", "/");
490 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
491 response.setHeader("ETag","\"new-etag\"");
492 response.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
493 final String key = "http://foo.example.com:80/bar";
494 response.setHeader("Content-Location", key);
495
496 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
497 new BasicHeader("Date", DateUtils.formatDate(now)),
498 new BasicHeader("ETag", "\"old-etag\"")
499 });
500
501 when(mockStorage.getEntry(key)).thenReturn(entry);
502
503 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
504
505 verify(mockStorage).getEntry(key);
506 verifyNoMoreInteractions(mockStorage);
507 }
508
509 @Test
510 public void doesNotFlushEntryIfNotInCache() throws Exception {
511 final HttpRequest request = new BasicHttpRequest("GET", "/");
512 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
513 response.setHeader("ETag","\"new-etag\"");
514 response.setHeader("Date", DateUtils.formatDate(now));
515 final String key = "http://foo.example.com:80/bar";
516 response.setHeader("Content-Location", key);
517
518 when(mockStorage.getEntry(key)).thenReturn(null);
519
520 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
521
522 verify(mockStorage).getEntry(key);
523 verifyNoMoreInteractions(mockStorage);
524 }
525
526 @Test
527 public void doesNotFlushEntrySpecifiedByContentLocationIfResponseHasNoEtag() throws Exception {
528 final HttpRequest request = new BasicHttpRequest("GET", "/");
529 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
530 response.removeHeaders("ETag");
531 response.setHeader("Date", DateUtils.formatDate(now));
532 final String key = "http://foo.example.com:80/bar";
533 response.setHeader("Content-Location", key);
534
535 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
536 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
537 new BasicHeader("ETag", "\"old-etag\"")
538 });
539
540 when(mockStorage.getEntry(key)).thenReturn(entry);
541
542 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
543
544 verify(mockStorage).getEntry(key);
545 verifyNoMoreInteractions(mockStorage);
546 }
547
548 @Test
549 public void doesNotFlushEntrySpecifiedByContentLocationIfEntryHasNoEtag() throws Exception {
550 final HttpRequest request = new BasicHttpRequest("GET", "/");
551 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
552 response.setHeader("ETag", "\"some-etag\"");
553 response.setHeader("Date", DateUtils.formatDate(now));
554 final String key = "http://foo.example.com:80/bar";
555 response.setHeader("Content-Location", key);
556
557 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
558 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
559 });
560
561 when(mockStorage.getEntry(key)).thenReturn(entry);
562
563 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
564
565 verify(mockStorage).getEntry(key);
566 verifyNoMoreInteractions(mockStorage);
567 }
568
569 @Test
570 public void flushesEntrySpecifiedByContentLocationIfResponseHasNoDate() throws Exception {
571 final HttpRequest request = new BasicHttpRequest("GET", "/");
572 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
573 response.setHeader("ETag", "\"new-etag\"");
574 response.removeHeaders("Date");
575 final String key = "http://foo.example.com:80/bar";
576 response.setHeader("Content-Location", key);
577
578 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
579 new BasicHeader("ETag", "\"old-etag\""),
580 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
581 });
582
583 when(mockStorage.getEntry(key)).thenReturn(entry);
584
585 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
586
587 verify(mockStorage).getEntry(key);
588 verify(mockStorage).removeEntry(key);
589 verifyNoMoreInteractions(mockStorage);
590 }
591
592 @Test
593 public void flushesEntrySpecifiedByContentLocationIfEntryHasNoDate() throws Exception {
594 final HttpRequest request = new BasicHttpRequest("GET", "/");
595 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
596 response.setHeader("ETag","\"new-etag\"");
597 response.setHeader("Date", DateUtils.formatDate(now));
598 final String key = "http://foo.example.com:80/bar";
599 response.setHeader("Content-Location", key);
600
601 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
602 new BasicHeader("ETag", "\"old-etag\"")
603 });
604
605 when(mockStorage.getEntry(key)).thenReturn(entry);
606
607 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
608
609 verify(mockStorage).getEntry(key);
610 verify(mockStorage).removeEntry(key);
611 verifyNoMoreInteractions(mockStorage);
612 }
613
614 @Test
615 public void flushesEntrySpecifiedByContentLocationIfResponseHasMalformedDate() throws Exception {
616 final HttpRequest request = new BasicHttpRequest("GET", "/");
617 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
618 response.setHeader("ETag","\"new-etag\"");
619 response.setHeader("Date", "blarg");
620 final String key = "http://foo.example.com:80/bar";
621 response.setHeader("Content-Location", key);
622
623 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
624 new BasicHeader("ETag", "\"old-etag\""),
625 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo))
626 });
627
628 when(mockStorage.getEntry(key)).thenReturn(entry);
629
630 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
631
632 verify(mockStorage).getEntry(key);
633 verify(mockStorage).removeEntry(key);
634 verifyNoMoreInteractions(mockStorage);
635 }
636
637 @Test
638 public void flushesEntrySpecifiedByContentLocationIfEntryHasMalformedDate() throws Exception {
639 final HttpRequest request = new BasicHttpRequest("GET", "/");
640 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
641 response.setHeader("ETag","\"new-etag\"");
642 response.setHeader("Date", DateUtils.formatDate(now));
643 final String key = "http://foo.example.com:80/bar";
644 response.setHeader("Content-Location", key);
645
646 final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
647 new BasicHeader("ETag", "\"old-etag\""),
648 new BasicHeader("Date", "foo")
649 });
650
651 when(mockStorage.getEntry(key)).thenReturn(entry);
652
653 impl.flushCacheEntriesInvalidatedByExchange(host, request, response, cacheKeyResolver, mockStorage);
654
655 verify(mockStorage).getEntry(key);
656 verify(mockStorage).removeEntry(key);
657 verifyNoMoreInteractions(mockStorage);
658 }
659
660
661
662 private void cacheEntryHasVariantMap(final Map<String,String> variantMap) {
663 when(mockEntry.getVariantMap()).thenReturn(variantMap);
664 }
665
666 private void cacheReturnsEntryForUri(final String key) throws IOException {
667 when(mockStorage.getEntry(key)).thenReturn(mockEntry);
668 }
669
670 private void cacheEntryisForMethod(final String httpMethod) {
671 when(mockEntry.getRequestMethod()).thenReturn(httpMethod);
672 }
673 }