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.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.util.Date;
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.After;
54  import org.junit.Assert;
55  import org.junit.Before;
56  import org.junit.Test;
57  import org.mockito.Mockito;
58  
59  public 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      @Before
75      public void setUp() throws Exception {
76          cacheDir = File.createTempFile("cachedir", "");
77          if (cacheDir.exists()) {
78              cacheDir.delete();
79          }
80          cacheDir.mkdir();
81      }
82  
83      @After
84      public void cleanUp() {
85          removeCache();
86      }
87  
88      @Test
89      public void testIssue1147() throws Exception {
90          final CacheConfig cacheConfig = CacheConfig.custom()
91              .setSharedCache(true)
92              .setMaxObjectSize(262144) //256kb
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 Date now = new Date();
106         final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
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.formatDate(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         Assert.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         Assert.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         Assert.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 }