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.Mockito.mock;
31 import static org.mockito.Mockito.reset;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.when;
34
35 import java.io.File;
36 import java.time.Instant;
37
38 import org.apache.hc.client5.http.HttpRoute;
39 import org.apache.hc.client5.http.cache.CacheResponseStatus;
40 import org.apache.hc.client5.http.cache.HttpCacheContext;
41 import org.apache.hc.client5.http.cache.HttpCacheStorage;
42 import org.apache.hc.client5.http.cache.ResourceFactory;
43 import org.apache.hc.client5.http.classic.ExecChain;
44 import org.apache.hc.client5.http.classic.ExecChainHandler;
45 import org.apache.hc.client5.http.classic.ExecRuntime;
46 import org.apache.hc.client5.http.classic.methods.HttpGet;
47 import org.apache.hc.client5.http.utils.DateUtils;
48 import org.apache.hc.core5.http.ClassicHttpRequest;
49 import org.apache.hc.core5.http.ClassicHttpResponse;
50 import org.apache.hc.core5.http.HttpHost;
51 import org.apache.hc.core5.http.io.entity.EntityUtils;
52 import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
53 import org.junit.jupiter.api.AfterEach;
54 import org.junit.jupiter.api.Assertions;
55 import org.junit.jupiter.api.BeforeEach;
56 import org.junit.jupiter.api.Test;
57 import org.mockito.Mockito;
58
59 class TestHttpCacheJiraNumber1147 {
60
61 private File cacheDir;
62
63 private void removeCache() {
64 if (this.cacheDir != null) {
65 final File[] files = this.cacheDir.listFiles();
66 for (final File cacheFile : files) {
67 cacheFile.delete();
68 }
69 this.cacheDir.delete();
70 this.cacheDir = null;
71 }
72 }
73
74 @BeforeEach
75 void setUp() throws Exception {
76 cacheDir = File.createTempFile("cachedir", "");
77 if (cacheDir.exists()) {
78 cacheDir.delete();
79 }
80 cacheDir.mkdir();
81 }
82
83 @AfterEach
84 void cleanUp() {
85 removeCache();
86 }
87
88 @Test
89 void testIssue1147() throws Exception {
90 final CacheConfig cacheConfig = CacheConfig.custom()
91 .setSharedCache(true)
92 .setMaxObjectSize(262144)
93 .build();
94
95 final ResourceFactory resourceFactory = new FileResourceFactory(cacheDir);
96 final HttpCacheStorage httpCacheStorage = new ManagedHttpCacheStorage(cacheConfig);
97
98 final ExecChain mockExecChain = mock(ExecChain.class);
99 final ExecRuntime mockEndpoint = mock(ExecRuntime.class);
100 final HttpHost target = new HttpHost("somehost", 80);
101 final HttpRoute route = new HttpRoute(target);
102 final ClassicHttpRequest get = new HttpGet("http://somehost/");
103 final HttpCacheContext context = HttpCacheContext.create();
104
105 final Instant now = Instant.now();
106 final Instant tenSecondsAgo = now.minusSeconds(10);
107
108 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
109 response.setEntity(HttpTestUtils.makeBody(128));
110 response.setHeader("Content-Length", "128");
111 response.setHeader("ETag", "\"etag\"");
112 response.setHeader("Cache-Control", "public, max-age=3600");
113 response.setHeader("Last-Modified", DateUtils.formatStandardDate(tenSecondsAgo));
114
115 when(mockExecChain.proceed(
116 isA(ClassicHttpRequest.class),
117 isA(ExecChain.Scope.class))).thenReturn(response);
118
119 final BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage);
120 final ExecChainHandler t = createCachingExecChain(cache, cacheConfig);
121
122 final ExecChain.Scope scope = new ExecChain.Scope("teset", route, get, mockEndpoint, context);
123 final ClassicHttpResponse response1 = t.execute(get, scope, mockExecChain);
124 Assertions.assertEquals(200, response1.getCode());
125 EntityUtils.consume(response1.getEntity());
126
127 verify(mockExecChain).proceed(isA(ClassicHttpRequest.class), isA(ExecChain.Scope.class));
128
129 removeCache();
130
131 reset(mockExecChain);
132 when(mockExecChain.proceed(isA(ClassicHttpRequest.class), isA(ExecChain.Scope.class))).thenReturn(response);
133
134 final ClassicHttpResponse response2 = t.execute(get, scope, mockExecChain);
135 Assertions.assertEquals(200, response2.getCode());
136 EntityUtils.consume(response2.getEntity());
137
138 verify(mockExecChain, Mockito.times(1)).proceed(
139 isA(ClassicHttpRequest.class),
140 isA(ExecChain.Scope.class));
141 Assertions.assertEquals(CacheResponseStatus.FAILURE, context.getCacheResponseStatus());
142 }
143
144 protected ExecChainHandler createCachingExecChain(final BasicHttpCache cache, final CacheConfig config) {
145 return new CachingExec(cache, null, config);
146 }
147
148 }