From 594f24cf0512a2ed6dafdd0912bbb63b703cefb3 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 19 Jun 2013 19:50:02 +0000 Subject: [PATCH] HTTPASYNC-46: HttpClient cache test cases can be shared with HttpAsyncClient Contributed by James Leigh git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1494755 13f79535-47bb-0310-9956-ffa450edef68 --- httpclient-cache/pom.xml | 12 + .../client/cache/AbstractProtocolTest.java | 22 +- .../http/impl/client/cache/HttpTestUtils.java | 6 + .../impl/client/cache/ResponseEquivalent.java | 54 + .../impl/client/cache/TestCachingExec.java | 1612 +--------------- .../client/cache/TestCachingExecChain.java | 1703 +++++++++++++++++ .../cache/TestHttpCacheJiraNumber1147.java | 7 +- .../cache/TestProtocolAllowedBehavior.java | 8 +- .../client/cache/TestProtocolDeviations.java | 27 +- .../cache/TestProtocolRecommendations.java | 157 +- .../cache/TestProtocolRequirements.java | 500 ++--- .../client/cache/TestRFC5861Compliance.java | 56 +- 12 files changed, 2210 insertions(+), 1954 deletions(-) create mode 100644 httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ResponseEquivalent.java create mode 100644 httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 145058d63..568e03973 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -112,6 +112,18 @@ maven-surefire-plugin + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + test-jar + + + + diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java index 0305dd06b..d66236e81 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java @@ -33,6 +33,7 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; +import org.apache.http.client.cache.HttpCacheContext; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; @@ -55,9 +56,10 @@ public abstract class AbstractProtocolTest { protected ClientExecChain mockBackend; protected HttpCache mockCache; protected HttpRequestWrapper request; + protected HttpCacheContext context; protected CloseableHttpResponse originResponse; protected CacheConfig config; - protected CachingExec impl; + protected ClientExecChain impl; protected HttpCache cache; public static HttpRequestWrapper eqRequest(final HttpRequestWrapper in) { @@ -65,6 +67,11 @@ public abstract class AbstractProtocolTest { return null; } + public static HttpResponse eqResponse(final HttpResponse in) { + EasyMock.reportMatcher(new ResponseEquivalent(in)); + return null; + } + @Before public void setUp() { host = new HttpHost("foo.example.com"); @@ -75,6 +82,8 @@ public abstract class AbstractProtocolTest { request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1)); + context = HttpCacheContext.create(); + originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response()); config = CacheConfig.custom() @@ -85,7 +94,16 @@ public abstract class AbstractProtocolTest { cache = new BasicHttpCache(config); mockBackend = EasyMock.createNiceMock(ClientExecChain.class); mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = new CachingExec(mockBackend, cache, config); + impl = createCachingExecChain(mockBackend, cache, config); + } + + protected ClientExecChain createCachingExecChain(final ClientExecChain backend, + final HttpCache cache, final CacheConfig config) { + return new CachingExec(backend, cache, config); + } + + protected boolean supportsRangeAndContentRangeHeaders(final ClientExecChain impl) { + return impl instanceof CachingExec && ((CachingExec) impl).supportsRangeAndContentRangeHeaders(); } protected void replayMocks() { diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java index 764ed52b6..7da22f83d 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java @@ -244,6 +244,12 @@ public class HttpTestUtils { r2)); } + /* Assert.asserts that two requests are morally equivalent. */ + public static boolean equivalent(final HttpResponse r1, final HttpResponse r2) { + return (equivalent(r1.getStatusLine(), r2.getStatusLine()) && isEndToEndHeaderSubset(r1, + r2)); + } + public static byte[] getRandomBytes(final int nbytes) { final byte[] bytes = new byte[nbytes]; (new Random()).nextBytes(bytes); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ResponseEquivalent.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ResponseEquivalent.java new file mode 100644 index 000000000..b57126bf8 --- /dev/null +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ResponseEquivalent.java @@ -0,0 +1,54 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client.cache; + +import org.apache.http.HttpResponse; +import org.easymock.IArgumentMatcher; + +public class ResponseEquivalent implements IArgumentMatcher { + + private final HttpResponse expected; + + public ResponseEquivalent(final HttpResponse expected) { + this.expected = expected; + } + + public boolean matches(final Object actual) { + if (!(actual instanceof HttpResponse)) { + return false; + } + final HttpResponse other = (HttpResponse) actual; + return HttpTestUtils.equivalent(expected, other); + } + + public void appendTo(final StringBuffer buf) { + buf.append("eqRequest("); + buf.append(expected); + buf.append(")"); + } + +} diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java index 0f36e0a94..a29d52d53 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java @@ -29,7 +29,6 @@ package org.apache.http.impl.client.cache; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.isNull; import static org.easymock.EasyMock.same; @@ -37,58 +36,33 @@ import static org.easymock.classextension.EasyMock.createMockBuilder; import static org.easymock.classextension.EasyMock.createNiceMock; import static org.easymock.classextension.EasyMock.replay; import static org.easymock.classextension.EasyMock.verify; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; import java.io.IOException; -import java.io.InputStream; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; -import java.util.List; import java.util.Map; -import junit.framework.AssertionFailedError; - -import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.StatusLine; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.cache.CacheResponseStatus; -import org.apache.http.client.cache.HttpCacheContext; import org.apache.http.client.cache.HttpCacheEntry; -import org.apache.http.client.cache.HttpCacheStorage; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; -import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestWrapper; -import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.client.utils.DateUtils; import org.apache.http.conn.routing.HttpRoute; -import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.execchain.ClientExecChain; -import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.util.EntityUtils; -import org.easymock.Capture; import org.easymock.IExpectationSetters; import org.easymock.classextension.EasyMock; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -public class TestCachingExec { +public class TestCachingExec extends TestCachingExecChain { private static final String GET_CURRENT_DATE = "getCurrentDate"; @@ -101,68 +75,33 @@ public class TestCachingExec { private CachingExec impl; private boolean mockedImpl; - private CacheValidityPolicy mockValidityPolicy; - private CacheableRequestPolicy mockRequestPolicy; - private ClientExecChain mockBackend; - private HttpCache mockCache; - private HttpCacheStorage mockStorage; - private CachedResponseSuitabilityChecker mockSuitabilityChecker; - private ResponseCachingPolicy mockResponsePolicy; private CloseableHttpResponse mockBackendResponse; - private HttpCacheEntry mockCacheEntry; - private CachedHttpResponseGenerator mockResponseGenerator; - private ResponseHandler mockHandler; - private HttpUriRequest mockUriRequest; - private CloseableHttpResponse mockCachedResponse; - private ConditionalRequestBuilder mockConditionalRequestBuilder; - private HttpRequest mockConditionalRequest; - private StatusLine mockStatusLine; - private ResponseProtocolCompliance mockResponseProtocolCompliance; - private RequestProtocolCompliance mockRequestProtocolCompliance; - private CacheConfig config; - private AsynchronousValidator asyncValidator; private Date requestDate; private Date responseDate; - private HttpRoute route; - private HttpHost host; - private HttpRequestWrapper request; - private HttpCacheContext context; - private HttpCacheEntry entry; - @SuppressWarnings("unchecked") @Before public void setUp() { - mockRequestPolicy = createNiceMock(CacheableRequestPolicy.class); - mockValidityPolicy = createNiceMock(CacheValidityPolicy.class); - mockBackend = createNiceMock(ClientExecChain.class); - mockCache = createNiceMock(HttpCache.class); - mockSuitabilityChecker = createNiceMock(CachedResponseSuitabilityChecker.class); - mockResponsePolicy = createNiceMock(ResponseCachingPolicy.class); - mockHandler = createNiceMock(ResponseHandler.class); + super.setUp(); + mockBackendResponse = createNiceMock(CloseableHttpResponse.class); - mockUriRequest = createNiceMock(HttpUriRequest.class); - mockCacheEntry = createNiceMock(HttpCacheEntry.class); - mockResponseGenerator = createNiceMock(CachedHttpResponseGenerator.class); - mockCachedResponse = createNiceMock(CloseableHttpResponse.class); - mockConditionalRequestBuilder = createNiceMock(ConditionalRequestBuilder.class); - mockConditionalRequest = createNiceMock(HttpRequest.class); - mockStatusLine = createNiceMock(StatusLine.class); - mockResponseProtocolCompliance = createNiceMock(ResponseProtocolCompliance.class); - mockRequestProtocolCompliance = createNiceMock(RequestProtocolCompliance.class); - mockStorage = createNiceMock(HttpCacheStorage.class); - config = CacheConfig.DEFAULT; - asyncValidator = new AsynchronousValidator(config); requestDate = new Date(System.currentTimeMillis() - 1000); responseDate = new Date(); - host = new HttpHost("foo.example.com"); - route = new HttpRoute(host); - request = HttpRequestWrapper.wrap( - new BasicHttpRequest("GET", "/stuff", HttpVersion.HTTP_1_1)); - context = HttpCacheContext.create(); - entry = HttpTestUtils.makeCacheEntry(); - impl = new CachingExec( + } + + @Override + public ClientExecChain createCachingExecChain(final ClientExecChain mockBackend, + final HttpCache mockCache, final CacheValidityPolicy mockValidityPolicy, + final ResponseCachingPolicy mockResponsePolicy, + final CachedHttpResponseGenerator mockResponseGenerator, + final CacheableRequestPolicy mockRequestPolicy, + final CachedResponseSuitabilityChecker mockSuitabilityChecker, + final ConditionalRequestBuilder mockConditionalRequestBuilder, + final ResponseProtocolCompliance mockResponseProtocolCompliance, + final RequestProtocolCompliance mockRequestProtocolCompliance, + final CacheConfig config, final AsynchronousValidator asyncValidator) { + return impl = new CachingExec( mockBackend, mockCache, mockValidityPolicy, @@ -177,140 +116,28 @@ public class TestCachingExec { asyncValidator); } - private void replayMocks() { - replay(mockRequestPolicy); - replay(mockValidityPolicy); - replay(mockSuitabilityChecker); - replay(mockResponsePolicy); - replay(mockCacheEntry); - replay(mockResponseGenerator); - replay(mockBackend); - replay(mockCache); - replay(mockHandler); + @Override + public ClientExecChain createCachingExecChain(final ClientExecChain backend, + final HttpCache cache, final CacheConfig config) { + return impl = new CachingExec(backend, cache, config); + } + + protected void replayMocks() { + super.replayMocks(); replay(mockBackendResponse); - replay(mockUriRequest); - replay(mockCachedResponse); - replay(mockConditionalRequestBuilder); - replay(mockConditionalRequest); - replay(mockStatusLine); - replay(mockResponseProtocolCompliance); - replay(mockRequestProtocolCompliance); - replay(mockStorage); if (mockedImpl) { replay(impl); } } - private void verifyMocks() { - verify(mockRequestPolicy); - verify(mockValidityPolicy); - verify(mockSuitabilityChecker); - verify(mockResponsePolicy); - verify(mockCacheEntry); - verify(mockResponseGenerator); - verify(mockBackend); - verify(mockCache); - verify(mockHandler); + protected void verifyMocks() { + super.verifyMocks(); verify(mockBackendResponse); - verify(mockUriRequest); - verify(mockCachedResponse); - verify(mockConditionalRequestBuilder); - verify(mockConditionalRequest); - verify(mockStatusLine); - verify(mockResponseProtocolCompliance); - verify(mockRequestProtocolCompliance); - verify(mockStorage); if (mockedImpl) { verify(impl); } } - @Test - public void testCacheableResponsesGoIntoCache() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - final HttpResponse resp1 = HttpTestUtils.make200Response(); - resp1.setHeader("Cache-Control","max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - verifyMocks(); - } - - @Test - public void testOlderCacheableResponsesDoNotGoIntoCache() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - final Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - final HttpResponse resp1 = HttpTestUtils.make200Response(); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Cache-Control", "max-age=3600"); - resp1.setHeader("Etag", "\"new-etag\""); - - backendExpectsAnyRequestAndReturn(resp1); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - req2.setHeader("Cache-Control","no-cache"); - final HttpResponse resp2 = HttpTestUtils.make200Response(); - resp2.setHeader("ETag", "\"old-etag\""); - resp2.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); - resp2.setHeader("Cache-Control","max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp2); - - final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); - verifyMocks(); - - assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); - } - - @Test - public void testNewerCacheableResponsesReplaceExistingCacheEntry() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - final Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - final HttpResponse resp1 = HttpTestUtils.make200Response(); - resp1.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); - resp1.setHeader("Cache-Control", "max-age=3600"); - resp1.setHeader("Etag", "\"old-etag\""); - - backendExpectsAnyRequestAndReturn(resp1); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - req2.setHeader("Cache-Control","max-age=0"); - final HttpResponse resp2 = HttpTestUtils.make200Response(); - resp2.setHeader("ETag", "\"new-etag\""); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Cache-Control","max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp2); - - final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); - verifyMocks(); - - assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); - } - @Test public void testRequestThatCannotBeServedFromCacheCausesBackendRequest() throws Exception { @@ -328,16 +155,6 @@ public class TestCachingExec { Assert.assertSame(mockBackendResponse, result); } - private void requestIsFatallyNonCompliant(final RequestProtocolError error) { - final List errors = new ArrayList(); - if (error != null) { - errors.add(error); - } - expect( - mockRequestProtocolCompliance.requestIsFatallyNonCompliant(request)).andReturn( - errors); - } - @Test public void testCacheMissCausesBackendRequest() throws Exception { mockImplMethods(CALL_BACKEND); @@ -477,23 +294,6 @@ public class TestCachingExec { verifyMocks(); } - @Test - public void testSuitableCacheEntryDoesNotCauseBackendRequest() throws Exception { - cacheInvalidatorWasCalled(); - requestPolicyAllowsCaching(true); - getCacheEntryReturns(mockCacheEntry); - cacheEntrySuitable(true); - responseIsGeneratedFromCache(); - requestIsFatallyNonCompliant(null); - entryHasStaleness(0L); - - replayMocks(); - final HttpResponse result = impl.execute(route, request, context); - verifyMocks(); - - Assert.assertSame(mockCachedResponse, result); - } - @Test public void testCallBackendMakesBackEndRequestAndHandlesResponse() throws Exception { mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); @@ -510,1268 +310,6 @@ public class TestCachingExec { verifyMocks(); } - @Test - public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception { - final CacheConfig config = CacheConfig.DEFAULT; - impl = new CachingExec(mockBackend, - new BasicHttpCache(new HeapResourceFactory(), mockStorage, config), - config); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); - final HttpResponse resp1 = HttpTestUtils.make200Response(); - resp1.setHeader("Cache-Control","no-cache"); - - expect(mockStorage.getEntry(isA(String.class))).andReturn(null).anyTimes(); - mockStorage.removeEntry(isA(String.class)); - expectLastCall().anyTimes(); - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - final HttpResponse result = impl.execute(route, req1); - verifyMocks(); - - assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); - } - - @Test - public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception { - - requestIsFatallyNonCompliant(null); - cacheInvalidatorWasCalled(); - requestPolicyAllowsCaching(true); - cacheEntrySuitable(true); - getCacheEntryReturns(mockCacheEntry); - responseIsGeneratedFromCache(); - entryHasStaleness(0L); - - replayMocks(); - impl.execute(route, request, context); - verifyMocks(); - } - - @Test - public void testNonCompliantRequestWrapsAndReThrowsProtocolException() throws Exception { - - final ClientProtocolException expected = new ClientProtocolException("ouch"); - - requestIsFatallyNonCompliant(null); - mockRequestProtocolCompliance.makeRequestCompliant((HttpRequestWrapper)anyObject()); - expectLastCall().andThrow(expected); - - boolean gotException = false; - replayMocks(); - try { - impl.execute(route, request, context); - } catch (final ClientProtocolException ex) { - Assert.assertSame(expected, ex); - gotException = true; - } - verifyMocks(); - Assert.assertTrue(gotException); - } - - @Test - public void testSetsModuleGeneratedResponseContextForCacheOptionsResponse() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS","*",HttpVersion.HTTP_1_1)); - req.setHeader("Max-Forwards","0"); - - impl.execute(route, req, context); - Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, - context.getCacheResponseStatus()); - } - - @Test - public void testSetsModuleGeneratedResponseContextForFatallyNoncompliantRequest() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req.setHeader("Range","bytes=0-50"); - req.setHeader("If-Range","W/\"weak-etag\""); - - impl.execute(route, req, context); - Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, - context.getCacheResponseStatus()); - } - - @Test - public void testRecordsClientProtocolInViaHeaderIfRequestNotServableFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req = HttpRequestWrapper.wrap( - new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0)); - req.setHeader("Cache-Control","no-cache"); - final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - final Capture cap = new Capture(); - - backendCaptureRequestAndReturn(cap, resp); - - replayMocks(); - impl.execute(route, req, context); - verifyMocks(); - - final HttpRequest captured = cap.getValue(); - final String via = captured.getFirstHeader("Via").getValue(); - final String proto = via.split("\\s+")[0]; - Assert.assertTrue("http/1.0".equalsIgnoreCase(proto) || - "1.0".equalsIgnoreCase(proto)); - } - - @Test - public void testSetsCacheMissContextIfRequestNotServableFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req.setHeader("Cache-Control","no-cache"); - final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - - backendExpectsAnyRequestAndReturn(resp); - - replayMocks(); - impl.execute(route, req, context); - verifyMocks(); - Assert.assertEquals(CacheResponseStatus.CACHE_MISS, - context.getCacheResponseStatus()); - } - - @Test - public void testSetsViaHeaderOnResponseIfRequestNotServableFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req.setHeader("Cache-Control","no-cache"); - final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - - backendExpectsAnyRequestAndReturn(resp); - - replayMocks(); - final HttpResponse result = impl.execute(route, req); - verifyMocks(); - Assert.assertNotNull(result.getFirstHeader("Via")); - } - - @Test - public void testSetsViaHeaderOnResponseForCacheMiss() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control","public, max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - final HttpResponse result = impl.execute(route, req1); - verifyMocks(); - Assert.assertNotNull(result.getFirstHeader("Via")); - } - - @Test - public void testSetsCacheHitContextIfRequestServedFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control","public, max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2, context); - verifyMocks(); - Assert.assertEquals(CacheResponseStatus.CACHE_HIT, - context.getCacheResponseStatus()); - } - - @Test - public void testSetsViaHeaderOnResponseIfRequestServedFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control","public, max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertNotNull(result.getFirstHeader("Via")); - } - - @Test - public void testReturns304ForIfModifiedSinceHeaderIfRequestServedFromCache() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testReturns304ForIfModifiedSinceHeaderIf304ResponseInCache() throws Exception { - final Date now = new Date(); - final Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L); - final Date inTenMinutes = new Date(now.getTime() + 600 * 1000L); - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req1.addHeader("If-Modified-Since", DateUtils.formatDate(oneHourAgo)); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req2.addHeader("If-Modified-Since", DateUtils.formatDate(oneHourAgo)); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Cache-control", "max-age=600"); - resp1.setHeader("Expires", DateUtils.formatDate(inTenMinutes)); - - expect(mockBackend.execute( - same(route), - isA(HttpRequestWrapper.class), - isA(HttpClientContext.class), - (HttpExecutionAware) isNull())).andReturn(Proxies.enhanceResponse(resp1)).once(); - - expect(mockBackend.execute( - same(route), - isA(HttpRequestWrapper.class), - isA(HttpClientContext.class), - (HttpExecutionAware) isNull())).andThrow( - new AssertionFailedError("Should have reused cached 304 response")).anyTimes(); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - Assert.assertFalse(result.containsHeader("Last-Modified")); - } - - @Test - public void testReturns200ForIfModifiedSinceDateIsLess() throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - resp1.setHeader("Last-Modified", DateUtils.formatDate(new Date())); - - // The variant has been modified since this date - req2.addHeader("If-Modified-Since", DateUtils - .formatDate(tenSecondsAgo)); - - final HttpResponse resp2 = HttpTestUtils.make200Response(); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testReturns200ForIfModifiedSinceDateIsInvalid() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAfter = new Date(now.getTime() + 10 * 1000L); - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - resp1.setHeader("Last-Modified", DateUtils.formatDate(new Date())); - - // invalid date (date in the future) - req2.addHeader("If-Modified-Since", DateUtils - .formatDate(tenSecondsAfter)); - - backendExpectsAnyRequestAndReturn(resp1).times(2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testReturns304ForIfNoneMatchHeaderIfRequestServedFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req2.addHeader("If-None-Match", "*"); - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testReturns200ForIfNoneMatchHeaderFails() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - - req2.addHeader("If-None-Match", "\"abc\""); - - final HttpResponse resp2 = HttpTestUtils.make200Response(); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(200, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testReturns304ForIfNoneMatchHeaderAndIfModifiedSinceIfRequestServedFromCache() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - resp1.setHeader("Last-Modified", DateUtils.formatDate(new Date())); - - req2.addHeader("If-None-Match", "*"); - req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testReturns200ForIfNoneMatchHeaderFailsIfModifiedSinceIgnored() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req2.addHeader("If-None-Match", "\"abc\""); - req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - Assert.assertEquals(200, result.getStatusLine().getStatusCode()); - - } - - @Test - public void testSetsValidatedContextIfRequestWasSuccessfullyValidated() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control","public, max-age=5"); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - resp2.setHeader("Content-Length","128"); - resp2.setHeader("ETag","\"etag\""); - resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp2.setHeader("Cache-Control","public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2, context); - verifyMocks(); - Assert.assertEquals(CacheResponseStatus.VALIDATED, - context.getCacheResponseStatus()); - } - - @Test - public void testSetsViaHeaderIfRequestWasSuccessfullyValidated() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control","public, max-age=5"); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - resp2.setHeader("Content-Length","128"); - resp2.setHeader("ETag","\"etag\""); - resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp2.setHeader("Cache-Control","public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2, context); - verifyMocks(); - Assert.assertNotNull(result.getFirstHeader("Via")); - } - - - @Test - public void testSetsModuleResponseContextIfValidationRequiredButFailed() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control","public, max-age=5, must-revalidate"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndThrows(new IOException()); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2, context); - verifyMocks(); - Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, - context.getCacheResponseStatus()); - } - - @Test - public void testSetsModuleResponseContextIfValidationFailsButNotRequired() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control","public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndThrows(new IOException()); - - replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2, context); - verifyMocks(); - Assert.assertEquals(CacheResponseStatus.CACHE_HIT, - context.getCacheResponseStatus()); - } - - @Test - public void testSetViaHeaderIfValidationFailsButNotRequired() - throws Exception { - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length","128"); - resp1.setHeader("ETag","\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control","public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndThrows(new IOException()); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2, context); - verifyMocks(); - Assert.assertNotNull(result.getFirstHeader("Via")); - } - - @Test - public void testReturns304ForIfNoneMatchPassesIfRequestServedFromOrigin() - throws Exception { - - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=5"); - - req2.addHeader("If-None-Match", "\"etag\""); - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_NOT_MODIFIED, "Not Modified"); - resp2.setHeader("ETag", "\"etag\""); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Cache-Control", "public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - } - - @Test - public void testReturns200ForIfNoneMatchFailsIfRequestServedFromOrigin() - throws Exception { - - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=5"); - - req2.addHeader("If-None-Match", "\"etag\""); - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - resp2.setHeader("Content-Length", "128"); - resp2.setHeader("ETag", "\"newetag\""); - resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp2.setHeader("Cache-Control", "public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); - } - - @Test - public void testReturns304ForIfModifiedSincePassesIfRequestServedFromOrigin() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=5"); - - req2.addHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_NOT_MODIFIED, "Not Modified"); - resp2.setHeader("ETag", "\"etag\""); - resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - resp2.setHeader("Cache-Control", "public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); - } - - @Test - public void testReturns200ForIfModifiedSinceFailsIfRequestServedFromOrigin() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=5"); - - req2.addHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - resp2.setHeader("Content-Length", "128"); - resp2.setHeader("ETag", "\"newetag\""); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Last-Modified", DateUtils.formatDate(now)); - resp2.setHeader("Cache-Control", "public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); - } - - @Test - public void testVariantMissServerIfReturns304CacheReturns200() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req1.addHeader("Accept-Encoding", "gzip"); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("Etag", "\"gzip_etag\""); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Vary", "Accept-Encoding"); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req2.addHeader("Accept-Encoding", "deflate"); - - final HttpRequestWrapper req2Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req2Server.addHeader("Accept-Encoding", "deflate"); - req2Server.addHeader("If-None-Match", "\"gzip_etag\""); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - resp2.setHeader("Content-Length", "128"); - resp2.setHeader("Etag", "\"deflate_etag\""); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Vary", "Accept-Encoding"); - resp2.setHeader("Cache-Control", "public, max-age=3600"); - - final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req3.addHeader("Accept-Encoding", "gzip,deflate"); - - final HttpRequestWrapper req3Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req3Server.addHeader("Accept-Encoding", "gzip,deflate"); - req3Server.addHeader("If-None-Match", "\"gzip_etag\",\"deflate_etag\""); - - final HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(HttpTestUtils.makeBody(128)); - resp3.setHeader("Content-Length", "128"); - resp3.setHeader("Etag", "\"gzip_etag\""); - resp3.setHeader("Date", DateUtils.formatDate(now)); - resp3.setHeader("Vary", "Accept-Encoding"); - resp3.setHeader("Cache-Control", "public, max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - backendExpectsAnyRequestAndReturn(resp3); - - replayMocks(); - final HttpResponse result1 = impl.execute(route, req1); - - final HttpResponse result2 = impl.execute(route, req2); - - final HttpResponse result3 = impl.execute(route, req3); - - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, result3.getStatusLine().getStatusCode()); - } - - @Test - public void testVariantsMissServerReturns304CacheReturns304() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req1.addHeader("Accept-Encoding", "gzip"); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp1.setEntity(HttpTestUtils.makeBody(128)); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("Etag", "\"gzip_etag\""); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Vary", "Accept-Encoding"); - resp1.setHeader("Cache-Control", "public, max-age=3600"); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req2.addHeader("Accept-Encoding", "deflate"); - - final HttpRequestWrapper req2Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req2Server.addHeader("Accept-Encoding", "deflate"); - req2Server.addHeader("If-None-Match", "\"gzip_etag\""); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - resp2.setHeader("Content-Length", "128"); - resp2.setHeader("Etag", "\"deflate_etag\""); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Vary", "Accept-Encoding"); - resp2.setHeader("Cache-Control", "public, max-age=3600"); - - final HttpRequestWrapper req4 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req4.addHeader("Accept-Encoding", "gzip,identity"); - req4.addHeader("If-None-Match", "\"gzip_etag\""); - - final HttpRequestWrapper req4Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); - req4Server.addHeader("Accept-Encoding", "gzip,identity"); - req4Server.addHeader("If-None-Match", "\"gzip_etag\""); - - final HttpResponse resp4 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); - resp4.setHeader("Etag", "\"gzip_etag\""); - resp4.setHeader("Date", DateUtils.formatDate(now)); - resp4.setHeader("Vary", "Accept-Encoding"); - resp4.setHeader("Cache-Control", "public, max-age=3600"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - backendExpectsAnyRequestAndReturn(resp4); - - replayMocks(); - final HttpResponse result1 = impl.execute(route, req1); - - final HttpResponse result2 = impl.execute(route, req2); - - final HttpResponse result4 = impl.execute(route, req4); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); - Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result4.getStatusLine().getStatusCode()); - - } - - @Test - public void testSocketTimeoutExceptionIsNotSilentlyCatched() - throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), - CacheConfig.DEFAULT); - final Date now = new Date(); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet( - "http://foo.example.com")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_OK, "OK"); - resp1.setEntity(new InputStreamEntity(new InputStream() { - private boolean closed = false; - - @Override - public void close() throws IOException { - closed = true; - } - - @Override - public int read() throws IOException { - if (closed) { - throw new SocketException("Socket closed"); - } - throw new SocketTimeoutException("Read timed out"); - } - }, 128)); - resp1.setHeader("Date", DateUtils.formatDate(now)); - - backendExpectsAnyRequestAndReturn(resp1); - - replayMocks(); - try { - final HttpResponse result1 = impl.execute(route, req1); - EntityUtils.toString(result1.getEntity()); - Assert.fail("We should have had a SocketTimeoutException"); - } catch (final SocketTimeoutException e) { - } - verifyMocks(); - - } - - @Test - public void testIsSharedCache() { - Assert.assertTrue(config.isSharedCache()); - } - - @Test - public void testTreatsCacheIOExceptionsAsCacheMiss() - throws Exception { - - impl = new CachingExec(mockBackend, mockCache, CacheConfig.DEFAULT); - final CloseableHttpResponse resp = Proxies.enhanceResponse(HttpTestUtils.make200Response()); - - mockCache.flushInvalidatedCacheEntriesFor(host, request); - expectLastCall().andThrow(new IOException()).anyTimes(); - mockCache.flushInvalidatedCacheEntriesFor(isA(HttpHost.class), isA(HttpRequest.class), isA(HttpResponse.class)); - expectLastCall().anyTimes(); - expect(mockCache.getCacheEntry(same(host), - isA(HttpRequest.class))) - .andThrow(new IOException()).anyTimes(); - expect(mockCache.getVariantCacheEntriesWithEtags(same(host), - isA(HttpRequest.class))) - .andThrow(new IOException()).anyTimes(); - expect(mockCache.cacheAndReturnResponse(same(host), - isA(HttpRequest.class), isA(HttpResponse.class), - isA(Date.class), isA(Date.class))) - .andReturn(resp).anyTimes(); - expect(mockBackend.execute( - same(route), - isA(HttpRequestWrapper.class), - isA(HttpClientContext.class), - (HttpExecutionAware) isNull())).andReturn(resp); - - replayMocks(); - final HttpResponse result = impl.execute(route, request); - verifyMocks(); - Assert.assertSame(resp, result); - } - - @Test - public void testIfOnlyIfCachedAndNoCacheEntryBackendNotCalled() throws Exception { - impl = new CachingExec(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); - - request.addHeader("Cache-Control", "only-if-cached"); - - final HttpResponse resp = impl.execute(route, request); - - Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode()); - } - - @Test - public void testIfOnlyIfCachedAndEntryNotSuitableBackendNotCalled() throws Exception { - - request.setHeader("Cache-Control", "only-if-cached"); - - entry = HttpTestUtils.makeCacheEntry(new Header[]{new BasicHeader("Cache-Control", "must-revalidate")}); - - requestIsFatallyNonCompliant(null); - cacheInvalidatorWasCalled(); - requestPolicyAllowsCaching(true); - getCacheEntryReturns(entry); - cacheEntrySuitable(false); - - replayMocks(); - final HttpResponse resp = impl.execute(route, request); - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode()); - } - - @Test - public void testIfOnlyIfCachedAndEntryExistsAndIsSuitableReturnsEntry() throws Exception { - - request.setHeader("Cache-Control", "only-if-cached"); - - requestIsFatallyNonCompliant(null); - cacheInvalidatorWasCalled(); - requestPolicyAllowsCaching(true); - getCacheEntryReturns(entry); - cacheEntrySuitable(true); - responseIsGeneratedFromCache(); - entryHasStaleness(0); - - replayMocks(); - final HttpResponse resp = impl.execute(route, request); - verifyMocks(); - - Assert.assertSame(mockCachedResponse, resp); - } - - @Test - public void testDoesNotSetConnectionInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingExec(backend); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(route, request); - impl.execute(route, request, ctx); - assertNull(ctx.getConnection()); - } - - @Test - public void testSetsTargetHostInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingExec(backend); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(route, request); - impl.execute(route, request, ctx); - assertSame(host, ctx.getTargetHost()); - } - - @Test - public void testSetsRouteInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingExec(backend); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(route, request); - impl.execute(route, request, ctx); - assertSame(route, ctx.getHttpRoute()); - } - - @Test - public void testSetsRequestInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingExec(backend); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(route, request); - impl.execute(route, request, ctx); - assertSame(request, ctx.getRequest()); - } - - @Test - public void testSetsResponseInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingExec(backend); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(route, request); - final HttpResponse result = impl.execute(route, request, ctx); - assertSame(result, ctx.getResponse()); - } - - @Test - public void testSetsRequestSentInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final HttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = new CachingExec(backend); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(route, request); - impl.execute(route, request, ctx); - assertTrue(ctx.isRequestSent()); - } - - @Test - public void testCanCacheAResponseWithoutABody() throws Exception { - final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); - response.setHeader("Date", DateUtils.formatDate(new Date())); - response.setHeader("Cache-Control","max-age=300"); - final DummyBackend backend = new DummyBackend(); - backend.setResponse(response); - impl = new CachingExec(backend); - impl.execute(route, request); - impl.execute(route, request); - assertEquals(1, backend.getExecutions()); - } - - @Test - public void testNoEntityForIfNoneMatchRequestNotYetInCache() throws Exception { - - final Date now = new Date(); - final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - - impl = new CachingExec(mockBackend, new BasicHttpCache(), - CacheConfig.DEFAULT); - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet( - "http://foo.example.com/")); - req1.addHeader("If-None-Match", "\"etag\""); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, - HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp1.setHeader("Content-Length", "128"); - resp1.setHeader("ETag", "\"etag\""); - resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - resp1.setHeader("Cache-Control", "public, max-age=5"); - - backendExpectsAnyRequestAndReturn(resp1); - replayMocks(); - final HttpResponse result = impl.execute(route, req1); - verifyMocks(); - - assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine() - .getStatusCode()); - assertNull("The 304 response messages MUST NOT contain a message-body", - result.getEntity()); - } - - @Test - public void testNotModifiedResponseUpdatesCacheEntryWhenNoEntity() throws Exception { - - final Date now = new Date(); - - impl = new CachingExec(mockBackend, new BasicHttpCache(),CacheConfig.DEFAULT); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req1.addHeader("If-None-Match", "etag"); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req2.addHeader("If-None-Match", "etag"); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Cache-Control","max-age=0"); - resp1.setHeader("Etag", "etag"); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Cache-Control","max-age=0"); - resp1.setHeader("Etag", "etag"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - replayMocks(); - final HttpResponse result1 = impl.execute(route, req1); - final HttpResponse result2 = impl.execute(route, req2); - verifyMocks(); - - assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getStatusLine().getStatusCode()); - assertEquals("etag", result1.getFirstHeader("Etag").getValue()); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getStatusLine().getStatusCode()); - assertEquals("etag", result2.getFirstHeader("Etag").getValue()); - } - - @Test - public void testNotModifiedResponseWithVaryUpdatesCacheEntryWhenNoEntity() throws Exception { - - final Date now = new Date(); - - impl = new CachingExec(mockBackend, new BasicHttpCache(),CacheConfig.DEFAULT); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req1.addHeader("If-None-Match", "etag"); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req2.addHeader("If-None-Match", "etag"); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Cache-Control","max-age=0"); - resp1.setHeader("Etag", "etag"); - resp1.setHeader("Vary", "Accept-Encoding"); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Cache-Control","max-age=0"); - resp1.setHeader("Etag", "etag"); - resp1.setHeader("Vary", "Accept-Encoding"); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - replayMocks(); - final HttpResponse result1 = impl.execute(route, req1); - final HttpResponse result2 = impl.execute(route, req2); - verifyMocks(); - - assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getStatusLine().getStatusCode()); - assertEquals("etag", result1.getFirstHeader("Etag").getValue()); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getStatusLine().getStatusCode()); - assertEquals("etag", result2.getFirstHeader("Etag").getValue()); - } - - @Test - public void testDoesNotSend304ForNonConditionalRequest() throws Exception { - - final Date now = new Date(); - final Date inOneMinute = new Date(System.currentTimeMillis()+60000); - - impl = new CachingExec(mockBackend, new BasicHttpCache(),CacheConfig.DEFAULT); - - final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - req1.addHeader("If-None-Match", "etag"); - - final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); - - final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); - resp1.setHeader("Date", DateUtils.formatDate(now)); - resp1.setHeader("Cache-Control","public, max-age=60"); - resp1.setHeader("Expires",DateUtils.formatDate(inOneMinute)); - resp1.setHeader("Etag", "etag"); - resp1.setHeader("Vary", "Accept-Encoding"); - - final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "Ok"); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Cache-Control","public, max-age=60"); - resp2.setHeader("Expires",DateUtils.formatDate(inOneMinute)); - resp2.setHeader("Etag", "etag"); - resp2.setHeader("Vary", "Accept-Encoding"); - resp2.setEntity(HttpTestUtils.makeBody(128)); - - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2).anyTimes(); - replayMocks(); - final HttpResponse result1 = impl.execute(route, req1); - final HttpResponse result2 = impl.execute(route, req2); - verifyMocks(); - - assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getStatusLine().getStatusCode()); - assertNull(result1.getEntity()); - assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); - Assert.assertNotNull(result2.getEntity()); - } - - private IExpectationSetters backendExpectsAnyRequestAndReturn( - final HttpResponse response) throws Exception { - final CloseableHttpResponse resp = mockBackend.execute( - EasyMock.isA(HttpRoute.class), - EasyMock.isA(HttpRequestWrapper.class), - EasyMock.isA(HttpClientContext.class), - EasyMock.isNull()); - return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); - } - private IExpectationSetters implExpectsAnyRequestAndReturn( final CloseableHttpResponse response) throws Exception { final CloseableHttpResponse resp = impl.callBackend( @@ -1782,50 +320,6 @@ public class TestCachingExec { return EasyMock.expect(resp).andReturn(response); } - private IExpectationSetters backendExpectsRequestAndReturn( - final HttpRequestWrapper request, final HttpResponse response) throws Exception { - final CloseableHttpResponse resp = mockBackend.execute( - EasyMock.isA(HttpRoute.class), - EasyMock.eq(request), - EasyMock.isA(HttpClientContext.class), - EasyMock.isNull()); - return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); - } - - private IExpectationSetters backendExpectsRequestAndReturn( - final HttpRequestWrapper request, final CloseableHttpResponse response) throws Exception { - final CloseableHttpResponse resp = mockBackend.execute( - EasyMock.isA(HttpRoute.class), - EasyMock.eq(request), - EasyMock.isA(HttpClientContext.class), - EasyMock.isNull()); - return EasyMock.expect(resp).andReturn(response); - } - - private IExpectationSetters backendExpectsAnyRequestAndThrows( - final Throwable throwable) throws Exception { - final CloseableHttpResponse resp = mockBackend.execute( - EasyMock.isA(HttpRoute.class), - EasyMock.isA(HttpRequestWrapper.class), - EasyMock.isA(HttpClientContext.class), - EasyMock.isNull()); - return EasyMock.expect(resp).andThrow(throwable); - } - - private IExpectationSetters backendCaptureRequestAndReturn( - final Capture cap, final HttpResponse response) throws Exception { - final CloseableHttpResponse resp = mockBackend.execute( - EasyMock.isA(HttpRoute.class), - EasyMock.capture(cap), - EasyMock.isA(HttpClientContext.class), - EasyMock.isNull()); - return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); - } - - private void getCacheEntryReturns(final HttpCacheEntry result) throws IOException { - expect(mockCache.getCacheEntry(host, request)).andReturn(result); - } - private void getVariantCacheEntriesReturns(final Map result) throws IOException { expect(mockCache.getVariantCacheEntriesWithEtags(host, request)).andReturn(result); } @@ -1836,62 +330,10 @@ public class TestCachingExec { (HttpRequest)anyObject()); } - private void cacheEntryValidatable(final boolean b) { - expect(mockValidityPolicy.isRevalidatable( - (HttpCacheEntry)anyObject())).andReturn(b); - } - - private void cacheEntryMustRevalidate(final boolean b) { - expect(mockValidityPolicy.mustRevalidate(mockCacheEntry)) - .andReturn(b); - } - - private void cacheEntryProxyRevalidate(final boolean b) { - expect(mockValidityPolicy.proxyRevalidate(mockCacheEntry)) - .andReturn(b); - } - - private void mayReturnStaleWhileRevalidating(final boolean b) { - expect(mockValidityPolicy.mayReturnStaleWhileRevalidating( - (HttpCacheEntry)anyObject(), (Date)anyObject())).andReturn(b); - } - - private void conditionalRequestBuilderReturns(final HttpRequestWrapper validate) - throws Exception { - expect(mockConditionalRequestBuilder.buildConditionalRequest( - request, entry)).andReturn(validate); -} - private void getCurrentDateReturns(final Date date) { expect(impl.getCurrentDate()).andReturn(date); } - private void requestPolicyAllowsCaching(final boolean allow) { - expect(mockRequestPolicy.isServableFromCache( - (HttpRequest)anyObject())).andReturn(allow); - } - - private void cacheEntrySuitable(final boolean suitable) { - expect( - mockSuitabilityChecker.canCachedResponseBeUsed( - (HttpHost)anyObject(), - (HttpRequest)anyObject(), - (HttpCacheEntry)anyObject(), - (Date)anyObject())).andReturn(suitable); - } - - private void entryHasStaleness(final long staleness) { - expect(mockValidityPolicy.getStalenessSecs( - (HttpCacheEntry)anyObject(), - (Date)anyObject() - )).andReturn(staleness); - } - - private void responseIsGeneratedFromCache() { - expect(mockResponseGenerator.generateResponse( - (HttpCacheEntry)anyObject())).andReturn(mockCachedResponse); - } - private void handleBackendResponseReturnsResponse(final HttpRequestWrapper request, final HttpResponse response) throws IOException { expect( diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java new file mode 100644 index 000000000..010b0e791 --- /dev/null +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java @@ -0,0 +1,1703 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client.cache; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.isNull; +import static org.easymock.classextension.EasyMock.createNiceMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import junit.framework.AssertionFailedError; + +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.cache.CacheResponseStatus; +import org.apache.http.client.cache.HttpCacheContext; +import org.apache.http.client.cache.HttpCacheEntry; +import org.apache.http.client.cache.HttpCacheStorage; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.DateUtils; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.impl.execchain.ClientExecChain; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicHttpRequest; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.util.EntityUtils; +import org.easymock.Capture; +import org.easymock.IExpectationSetters; +import org.easymock.classextension.EasyMock; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public abstract class TestCachingExecChain { + + private ClientExecChain impl; + + protected CacheValidityPolicy mockValidityPolicy; + protected CacheableRequestPolicy mockRequestPolicy; + protected ClientExecChain mockBackend; + protected HttpCache mockCache; + private HttpCacheStorage mockStorage; + protected CachedResponseSuitabilityChecker mockSuitabilityChecker; + protected ResponseCachingPolicy mockResponsePolicy; + protected HttpCacheEntry mockCacheEntry; + protected CachedHttpResponseGenerator mockResponseGenerator; + private ResponseHandler mockHandler; + private HttpUriRequest mockUriRequest; + private CloseableHttpResponse mockCachedResponse; + protected ConditionalRequestBuilder mockConditionalRequestBuilder; + private HttpRequest mockConditionalRequest; + private StatusLine mockStatusLine; + protected ResponseProtocolCompliance mockResponseProtocolCompliance; + protected RequestProtocolCompliance mockRequestProtocolCompliance; + protected CacheConfig config; + protected AsynchronousValidator asyncValidator; + + protected HttpRoute route; + protected HttpHost host; + protected HttpRequestWrapper request; + protected HttpCacheContext context; + protected HttpCacheEntry entry; + + @SuppressWarnings("unchecked") + @Before + public void setUp() { + mockRequestPolicy = createNiceMock(CacheableRequestPolicy.class); + mockValidityPolicy = createNiceMock(CacheValidityPolicy.class); + mockBackend = createNiceMock(ClientExecChain.class); + mockCache = createNiceMock(HttpCache.class); + mockSuitabilityChecker = createNiceMock(CachedResponseSuitabilityChecker.class); + mockResponsePolicy = createNiceMock(ResponseCachingPolicy.class); + mockHandler = createNiceMock(ResponseHandler.class); + mockUriRequest = createNiceMock(HttpUriRequest.class); + mockCacheEntry = createNiceMock(HttpCacheEntry.class); + mockResponseGenerator = createNiceMock(CachedHttpResponseGenerator.class); + mockCachedResponse = createNiceMock(CloseableHttpResponse.class); + mockConditionalRequestBuilder = createNiceMock(ConditionalRequestBuilder.class); + mockConditionalRequest = createNiceMock(HttpRequest.class); + mockStatusLine = createNiceMock(StatusLine.class); + mockResponseProtocolCompliance = createNiceMock(ResponseProtocolCompliance.class); + mockRequestProtocolCompliance = createNiceMock(RequestProtocolCompliance.class); + mockStorage = createNiceMock(HttpCacheStorage.class); + config = CacheConfig.DEFAULT; + asyncValidator = new AsynchronousValidator(config); + + host = new HttpHost("foo.example.com"); + route = new HttpRoute(host); + request = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/stuff", HttpVersion.HTTP_1_1)); + context = HttpCacheContext.create(); + entry = HttpTestUtils.makeCacheEntry(); + impl = createCachingExecChain( + mockBackend, + mockCache, + mockValidityPolicy, + mockResponsePolicy, + mockResponseGenerator, + mockRequestPolicy, + mockSuitabilityChecker, + mockConditionalRequestBuilder, + mockResponseProtocolCompliance, + mockRequestProtocolCompliance, + config, + asyncValidator); + } + + public abstract ClientExecChain createCachingExecChain( + ClientExecChain backend, HttpCache responseCache, + CacheValidityPolicy validityPolicy, + ResponseCachingPolicy responseCachingPolicy, + CachedHttpResponseGenerator responseGenerator, + CacheableRequestPolicy cacheableRequestPolicy, + CachedResponseSuitabilityChecker suitabilityChecker, + ConditionalRequestBuilder conditionalRequestBuilder, + ResponseProtocolCompliance responseCompliance, + RequestProtocolCompliance requestCompliance, CacheConfig config, + AsynchronousValidator asynchRevalidator); + + public abstract ClientExecChain createCachingExecChain( + ClientExecChain backend, HttpCache cache, CacheConfig config); + + public static HttpRequestWrapper eqRequest(final HttpRequestWrapper in) { + EasyMock.reportMatcher(new RequestEquivalent(in)); + return null; + } + + public static R eqResponse(final R in) { + EasyMock.reportMatcher(new ResponseEquivalent(in)); + return null; + } + + protected void replayMocks() { + replay(mockRequestPolicy); + replay(mockValidityPolicy); + replay(mockSuitabilityChecker); + replay(mockResponsePolicy); + replay(mockCacheEntry); + replay(mockResponseGenerator); + replay(mockBackend); + replay(mockCache); + replay(mockHandler); + replay(mockUriRequest); + replay(mockCachedResponse); + replay(mockConditionalRequestBuilder); + replay(mockConditionalRequest); + replay(mockStatusLine); + replay(mockResponseProtocolCompliance); + replay(mockRequestProtocolCompliance); + replay(mockStorage); + } + + protected void verifyMocks() { + verify(mockRequestPolicy); + verify(mockValidityPolicy); + verify(mockSuitabilityChecker); + verify(mockResponsePolicy); + verify(mockCacheEntry); + verify(mockResponseGenerator); + verify(mockBackend); + verify(mockCache); + verify(mockHandler); + verify(mockUriRequest); + verify(mockCachedResponse); + verify(mockConditionalRequestBuilder); + verify(mockConditionalRequest); + verify(mockStatusLine); + verify(mockResponseProtocolCompliance); + verify(mockRequestProtocolCompliance); + verify(mockStorage); + } + + @Test + public void testCacheableResponsesGoIntoCache() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + final HttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("Cache-Control","max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + verifyMocks(); + } + + @Test + public void testOlderCacheableResponsesDoNotGoIntoCache() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + final Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + final HttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Cache-Control", "max-age=3600"); + resp1.setHeader("Etag", "\"new-etag\""); + + backendExpectsAnyRequestAndReturn(resp1); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + req2.setHeader("Cache-Control","no-cache"); + final HttpResponse resp2 = HttpTestUtils.make200Response(); + resp2.setHeader("ETag", "\"old-etag\""); + resp2.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); + resp2.setHeader("Cache-Control","max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp2); + + final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); + verifyMocks(); + + assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); + } + + @Test + public void testNewerCacheableResponsesReplaceExistingCacheEntry() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + final Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + final HttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); + resp1.setHeader("Cache-Control", "max-age=3600"); + resp1.setHeader("Etag", "\"old-etag\""); + + backendExpectsAnyRequestAndReturn(resp1); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + req2.setHeader("Cache-Control","max-age=0"); + final HttpResponse resp2 = HttpTestUtils.make200Response(); + resp2.setHeader("ETag", "\"new-etag\""); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Cache-Control","max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp2); + + final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); + verifyMocks(); + + assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); + } + + protected void requestIsFatallyNonCompliant(final RequestProtocolError error) { + final List errors = new ArrayList(); + if (error != null) { + errors.add(error); + } + expect( + mockRequestProtocolCompliance.requestIsFatallyNonCompliant(eqRequest(request))).andReturn( + errors); + } + + @Test + public void testSuitableCacheEntryDoesNotCauseBackendRequest() throws Exception { + cacheInvalidatorWasCalled(); + requestPolicyAllowsCaching(true); + getCacheEntryReturns(mockCacheEntry); + cacheEntrySuitable(true); + responseIsGeneratedFromCache(); + requestIsFatallyNonCompliant(null); + entryHasStaleness(0L); + + replayMocks(); + final HttpResponse result = impl.execute(route, request, context, null); + verifyMocks(); + + Assert.assertSame(mockCachedResponse, result); + } + + @Test + public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception { + final CacheConfig config = CacheConfig.DEFAULT; + impl = createCachingExecChain(mockBackend, new BasicHttpCache(new HeapResourceFactory(), mockStorage, config), config); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); + final HttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("Cache-Control","no-cache"); + + expect(mockStorage.getEntry(isA(String.class))).andReturn(null).anyTimes(); + mockStorage.removeEntry(isA(String.class)); + expectLastCall().anyTimes(); + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + final HttpResponse result = impl.execute(route, req1, context, null); + verifyMocks(); + + assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); + } + + @Test + public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception { + + requestIsFatallyNonCompliant(null); + cacheInvalidatorWasCalled(); + requestPolicyAllowsCaching(true); + cacheEntrySuitable(true); + getCacheEntryReturns(mockCacheEntry); + responseIsGeneratedFromCache(); + entryHasStaleness(0L); + + replayMocks(); + impl.execute(route, request, context, null); + verifyMocks(); + } + + @Test + public void testNonCompliantRequestWrapsAndReThrowsProtocolException() throws Exception { + + final ClientProtocolException expected = new ClientProtocolException("ouch"); + + requestIsFatallyNonCompliant(null); + mockRequestProtocolCompliance.makeRequestCompliant((HttpRequestWrapper)anyObject()); + expectLastCall().andThrow(expected); + + boolean gotException = false; + replayMocks(); + try { + impl.execute(route, request, context, null); + } catch (final ClientProtocolException ex) { + Assert.assertSame(expected, ex); + gotException = true; + } + verifyMocks(); + Assert.assertTrue(gotException); + } + + @Test + public void testSetsModuleGeneratedResponseContextForCacheOptionsResponse() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS","*",HttpVersion.HTTP_1_1)); + req.setHeader("Max-Forwards","0"); + + impl.execute(route, req, context, null); + Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, + context.getCacheResponseStatus()); + } + + @Test + public void testSetsModuleGeneratedResponseContextForFatallyNoncompliantRequest() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req.setHeader("Range","bytes=0-50"); + req.setHeader("If-Range","W/\"weak-etag\""); + + impl.execute(route, req, context, null); + Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, + context.getCacheResponseStatus()); + } + + @Test + public void testRecordsClientProtocolInViaHeaderIfRequestNotServableFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req = HttpRequestWrapper.wrap( + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0)); + req.setHeader("Cache-Control","no-cache"); + final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); + final Capture cap = new Capture(); + + backendCaptureRequestAndReturn(cap, resp); + + replayMocks(); + impl.execute(route, req, context, null); + verifyMocks(); + + final HttpRequest captured = cap.getValue(); + final String via = captured.getFirstHeader("Via").getValue(); + final String proto = via.split("\\s+")[0]; + Assert.assertTrue("http/1.0".equalsIgnoreCase(proto) || + "1.0".equalsIgnoreCase(proto)); + } + + @Test + public void testSetsCacheMissContextIfRequestNotServableFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req.setHeader("Cache-Control","no-cache"); + final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); + + backendExpectsAnyRequestAndReturn(resp); + + replayMocks(); + impl.execute(route, req, context, null); + verifyMocks(); + Assert.assertEquals(CacheResponseStatus.CACHE_MISS, + context.getCacheResponseStatus()); + } + + @Test + public void testSetsViaHeaderOnResponseIfRequestNotServableFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req.setHeader("Cache-Control","no-cache"); + final HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); + + backendExpectsAnyRequestAndReturn(resp); + + replayMocks(); + final HttpResponse result = impl.execute(route, req, context, null); + verifyMocks(); + Assert.assertNotNull(result.getFirstHeader("Via")); + } + + @Test + public void testSetsViaHeaderOnResponseForCacheMiss() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control","public, max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + final HttpResponse result = impl.execute(route, req1, context, null); + verifyMocks(); + Assert.assertNotNull(result.getFirstHeader("Via")); + } + + @Test + public void testSetsCacheHitContextIfRequestServedFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control","public, max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(CacheResponseStatus.CACHE_HIT, + context.getCacheResponseStatus()); + } + + @Test + public void testSetsViaHeaderOnResponseIfRequestServedFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control","public, max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertNotNull(result.getFirstHeader("Via")); + } + + @Test + public void testReturns304ForIfModifiedSinceHeaderIfRequestServedFromCache() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testReturns304ForIfModifiedSinceHeaderIf304ResponseInCache() throws Exception { + final Date now = new Date(); + final Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L); + final Date inTenMinutes = new Date(now.getTime() + 600 * 1000L); + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req1.addHeader("If-Modified-Since", DateUtils.formatDate(oneHourAgo)); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req2.addHeader("If-Modified-Since", DateUtils.formatDate(oneHourAgo)); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Cache-control", "max-age=600"); + resp1.setHeader("Expires", DateUtils.formatDate(inTenMinutes)); + + expect(mockBackend.execute( + eq(route), + isA(HttpRequestWrapper.class), + isA(HttpClientContext.class), + (HttpExecutionAware) isNull())).andReturn(Proxies.enhanceResponse(resp1)).once(); + + expect(mockBackend.execute( + eq(route), + isA(HttpRequestWrapper.class), + isA(HttpClientContext.class), + (HttpExecutionAware) isNull())).andThrow( + new AssertionFailedError("Should have reused cached 304 response")).anyTimes(); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); + Assert.assertFalse(result.containsHeader("Last-Modified")); + } + + @Test + public void testReturns200ForIfModifiedSinceDateIsLess() throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + resp1.setHeader("Last-Modified", DateUtils.formatDate(new Date())); + + // The variant has been modified since this date + req2.addHeader("If-Modified-Since", DateUtils + .formatDate(tenSecondsAgo)); + + final HttpResponse resp2 = HttpTestUtils.make200Response(); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testReturns200ForIfModifiedSinceDateIsInvalid() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAfter = new Date(now.getTime() + 10 * 1000L); + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + resp1.setHeader("Last-Modified", DateUtils.formatDate(new Date())); + + // invalid date (date in the future) + req2.addHeader("If-Modified-Since", DateUtils + .formatDate(tenSecondsAfter)); + + backendExpectsAnyRequestAndReturn(resp1).times(2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testReturns304ForIfNoneMatchHeaderIfRequestServedFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req2.addHeader("If-None-Match", "*"); + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testReturns200ForIfNoneMatchHeaderFails() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(new Date())); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + + req2.addHeader("If-None-Match", "\"abc\""); + + final HttpResponse resp2 = HttpTestUtils.make200Response(); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(200, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testReturns304ForIfNoneMatchHeaderAndIfModifiedSinceIfRequestServedFromCache() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + resp1.setHeader("Last-Modified", DateUtils.formatDate(new Date())); + + req2.addHeader("If-None-Match", "*"); + req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testReturns200ForIfNoneMatchHeaderFailsIfModifiedSinceIgnored() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req2.addHeader("If-None-Match", "\"abc\""); + req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(200, result.getStatusLine().getStatusCode()); + + } + + @Test + public void testSetsValidatedContextIfRequestWasSuccessfullyValidated() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control","public, max-age=5"); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + resp2.setHeader("Content-Length","128"); + resp2.setHeader("ETag","\"etag\""); + resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp2.setHeader("Cache-Control","public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(CacheResponseStatus.VALIDATED, + context.getCacheResponseStatus()); + } + + @Test + public void testSetsViaHeaderIfRequestWasSuccessfullyValidated() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control","public, max-age=5"); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + resp2.setHeader("Content-Length","128"); + resp2.setHeader("ETag","\"etag\""); + resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp2.setHeader("Cache-Control","public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertNotNull(result.getFirstHeader("Via")); + } + + + @Test + public void testSetsModuleResponseContextIfValidationRequiredButFailed() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control","public, max-age=5, must-revalidate"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndThrows(new IOException()); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, + context.getCacheResponseStatus()); + } + + @Test + public void testSetsModuleResponseContextIfValidationFailsButNotRequired() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control","public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndThrows(new IOException()); + + replayMocks(); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertEquals(CacheResponseStatus.CACHE_HIT, + context.getCacheResponseStatus()); + } + + @Test + public void testSetViaHeaderIfValidationFailsButNotRequired() + throws Exception { + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length","128"); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control","public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndThrows(new IOException()); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + Assert.assertNotNull(result.getFirstHeader("Via")); + } + + @Test + public void testReturns304ForIfNoneMatchPassesIfRequestServedFromOrigin() + throws Exception { + + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=5"); + + req2.addHeader("If-None-Match", "\"etag\""); + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + resp2.setHeader("ETag", "\"etag\""); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Cache-Control", "public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); + } + + @Test + public void testReturns200ForIfNoneMatchFailsIfRequestServedFromOrigin() + throws Exception { + + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=5"); + + req2.addHeader("If-None-Match", "\"etag\""); + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + resp2.setHeader("Content-Length", "128"); + resp2.setHeader("ETag", "\"newetag\""); + resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp2.setHeader("Cache-Control", "public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + + Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); + } + + @Test + public void testReturns304ForIfModifiedSincePassesIfRequestServedFromOrigin() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=5"); + + req2.addHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + resp2.setHeader("ETag", "\"etag\""); + resp2.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); + resp2.setHeader("Cache-Control", "public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); + } + + @Test + public void testReturns200ForIfModifiedSinceFailsIfRequestServedFromOrigin() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=5"); + + req2.addHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + resp2.setHeader("Content-Length", "128"); + resp2.setHeader("ETag", "\"newetag\""); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Last-Modified", DateUtils.formatDate(now)); + resp2.setHeader("Cache-Control", "public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + + replayMocks(); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); + verifyMocks(); + + Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); + } + + @Test + public void testVariantMissServerIfReturns304CacheReturns200() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req1.addHeader("Accept-Encoding", "gzip"); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("Etag", "\"gzip_etag\""); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Vary", "Accept-Encoding"); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req2.addHeader("Accept-Encoding", "deflate"); + + final HttpRequestWrapper req2Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req2Server.addHeader("Accept-Encoding", "deflate"); + req2Server.addHeader("If-None-Match", "\"gzip_etag\""); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + resp2.setHeader("Content-Length", "128"); + resp2.setHeader("Etag", "\"deflate_etag\""); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Vary", "Accept-Encoding"); + resp2.setHeader("Cache-Control", "public, max-age=3600"); + + final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req3.addHeader("Accept-Encoding", "gzip,deflate"); + + final HttpRequestWrapper req3Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req3Server.addHeader("Accept-Encoding", "gzip,deflate"); + req3Server.addHeader("If-None-Match", "\"gzip_etag\",\"deflate_etag\""); + + final HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp3.setEntity(HttpTestUtils.makeBody(128)); + resp3.setHeader("Content-Length", "128"); + resp3.setHeader("Etag", "\"gzip_etag\""); + resp3.setHeader("Date", DateUtils.formatDate(now)); + resp3.setHeader("Vary", "Accept-Encoding"); + resp3.setHeader("Cache-Control", "public, max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + backendExpectsAnyRequestAndReturn(resp3); + + replayMocks(); + final HttpResponse result1 = impl.execute(route, req1, context, null); + + final HttpResponse result2 = impl.execute(route, req2, context, null); + + final HttpResponse result3 = impl.execute(route, req3, context, null); + + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, result3.getStatusLine().getStatusCode()); + } + + @Test + public void testVariantsMissServerReturns304CacheReturns304() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req1.addHeader("Accept-Encoding", "gzip"); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp1.setEntity(HttpTestUtils.makeBody(128)); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("Etag", "\"gzip_etag\""); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Vary", "Accept-Encoding"); + resp1.setHeader("Cache-Control", "public, max-age=3600"); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req2.addHeader("Accept-Encoding", "deflate"); + + final HttpRequestWrapper req2Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req2Server.addHeader("Accept-Encoding", "deflate"); + req2Server.addHeader("If-None-Match", "\"gzip_etag\""); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + resp2.setHeader("Content-Length", "128"); + resp2.setHeader("Etag", "\"deflate_etag\""); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Vary", "Accept-Encoding"); + resp2.setHeader("Cache-Control", "public, max-age=3600"); + + final HttpRequestWrapper req4 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req4.addHeader("Accept-Encoding", "gzip,identity"); + req4.addHeader("If-None-Match", "\"gzip_etag\""); + + final HttpRequestWrapper req4Server = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com")); + req4Server.addHeader("Accept-Encoding", "gzip,identity"); + req4Server.addHeader("If-None-Match", "\"gzip_etag\""); + + final HttpResponse resp4 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + resp4.setHeader("Etag", "\"gzip_etag\""); + resp4.setHeader("Date", DateUtils.formatDate(now)); + resp4.setHeader("Vary", "Accept-Encoding"); + resp4.setHeader("Cache-Control", "public, max-age=3600"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + backendExpectsAnyRequestAndReturn(resp4); + + replayMocks(); + final HttpResponse result1 = impl.execute(route, req1, context, null); + + final HttpResponse result2 = impl.execute(route, req2, context, null); + + final HttpResponse result4 = impl.execute(route, req4, context, null); + verifyMocks(); + Assert.assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result4.getStatusLine().getStatusCode()); + + } + + @Test + public void testSocketTimeoutExceptionIsNotSilentlyCatched() + throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final Date now = new Date(); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet( + "http://foo.example.com")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, "OK"); + resp1.setEntity(new InputStreamEntity(new InputStream() { + private boolean closed = false; + + @Override + public void close() throws IOException { + closed = true; + } + + @Override + public int read() throws IOException { + if (closed) { + throw new SocketException("Socket closed"); + } + throw new SocketTimeoutException("Read timed out"); + } + }, 128)); + resp1.setHeader("Date", DateUtils.formatDate(now)); + + backendExpectsAnyRequestAndReturn(resp1); + + replayMocks(); + try { + final HttpResponse result1 = impl.execute(route, req1, context, null); + EntityUtils.toString(result1.getEntity()); + Assert.fail("We should have had a SocketTimeoutException"); + } catch (final SocketTimeoutException e) { + } + verifyMocks(); + + } + + @Test + public void testIsSharedCache() { + Assert.assertTrue(config.isSharedCache()); + } + + @Test + public void testTreatsCacheIOExceptionsAsCacheMiss() + throws Exception { + + impl = createCachingExecChain(mockBackend, mockCache, CacheConfig.DEFAULT); + final CloseableHttpResponse resp = Proxies.enhanceResponse(HttpTestUtils.make200Response()); + + mockCache.flushInvalidatedCacheEntriesFor(host, request); + expectLastCall().andThrow(new IOException()).anyTimes(); + mockCache.flushInvalidatedCacheEntriesFor(isA(HttpHost.class), isA(HttpRequest.class), isA(HttpResponse.class)); + expectLastCall().anyTimes(); + expect(mockCache.getCacheEntry(eq(host), + isA(HttpRequest.class))) + .andThrow(new IOException()).anyTimes(); + expect(mockCache.getVariantCacheEntriesWithEtags(eq(host), + isA(HttpRequest.class))) + .andThrow(new IOException()).anyTimes(); + expect(mockCache.cacheAndReturnResponse(eq(host), + isA(HttpRequest.class), isA(HttpResponse.class), + isA(Date.class), isA(Date.class))) + .andReturn(resp).anyTimes(); + expect(mockBackend.execute( + eq(route), + isA(HttpRequestWrapper.class), + isA(HttpClientContext.class), + (HttpExecutionAware) isNull())).andReturn(resp); + + replayMocks(); + final HttpResponse result = impl.execute(route, request, context, null); + verifyMocks(); + Assert.assertSame(resp, result); + } + + @Test + public void testIfOnlyIfCachedAndNoCacheEntryBackendNotCalled() throws Exception { + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + + request.addHeader("Cache-Control", "only-if-cached"); + + final HttpResponse resp = impl.execute(route, request, context, null); + + Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode()); + } + + @Test + public void testIfOnlyIfCachedAndEntryNotSuitableBackendNotCalled() throws Exception { + + request.setHeader("Cache-Control", "only-if-cached"); + + entry = HttpTestUtils.makeCacheEntry(new Header[]{new BasicHeader("Cache-Control", "must-revalidate")}); + + requestIsFatallyNonCompliant(null); + cacheInvalidatorWasCalled(); + requestPolicyAllowsCaching(true); + getCacheEntryReturns(entry); + cacheEntrySuitable(false); + + replayMocks(); + final HttpResponse resp = impl.execute(route, request, context, null); + verifyMocks(); + + Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getStatusLine().getStatusCode()); + } + + @Test + public void testIfOnlyIfCachedAndEntryExistsAndIsSuitableReturnsEntry() throws Exception { + + request.setHeader("Cache-Control", "only-if-cached"); + + requestIsFatallyNonCompliant(null); + cacheInvalidatorWasCalled(); + requestPolicyAllowsCaching(true); + getCacheEntryReturns(entry); + cacheEntrySuitable(true); + responseIsGeneratedFromCache(); + entryHasStaleness(0); + + replayMocks(); + final HttpResponse resp = impl.execute(route, request, context, null); + verifyMocks(); + + Assert.assertSame(mockCachedResponse, resp); + } + + @Test + public void testDoesNotSetConnectionInContextOnCacheHit() throws Exception { + final DummyBackend backend = new DummyBackend(); + final HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request, context, null); + impl.execute(route, request, ctx, null); + assertNull(ctx.getConnection()); + } + + @Test + public void testSetsTargetHostInContextOnCacheHit() throws Exception { + final DummyBackend backend = new DummyBackend(); + final HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request, context, null); + impl.execute(route, request, ctx, null); + assertSame(host, ctx.getTargetHost()); + } + + @Test + public void testSetsRouteInContextOnCacheHit() throws Exception { + final DummyBackend backend = new DummyBackend(); + final HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request, context, null); + impl.execute(route, request, ctx, null); + assertEquals(route, ctx.getHttpRoute()); + } + + @Test + public void testSetsRequestInContextOnCacheHit() throws Exception { + final DummyBackend backend = new DummyBackend(); + final HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request, context, null); + impl.execute(route, request, ctx, null); + if (!HttpTestUtils.equivalent(request, ctx.getRequest())) { + assertSame(request, ctx.getRequest()); + } + } + + @Test + public void testSetsResponseInContextOnCacheHit() throws Exception { + final DummyBackend backend = new DummyBackend(); + final HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request, context, null); + final HttpResponse result = impl.execute(route, request, ctx, null); + if (!HttpTestUtils.equivalent(result, ctx.getResponse())) { + assertSame(result, ctx.getResponse()); + } + } + + @Test + public void testSetsRequestSentInContextOnCacheHit() throws Exception { + final DummyBackend backend = new DummyBackend(); + final HttpResponse response = HttpTestUtils.make200Response(); + response.setHeader("Cache-Control", "max-age=3600"); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpClientContext ctx = HttpClientContext.create(); + impl.execute(route, request, context, null); + impl.execute(route, request, ctx, null); + assertTrue(ctx.isRequestSent()); + } + + @Test + public void testCanCacheAResponseWithoutABody() throws Exception { + final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"); + response.setHeader("Date", DateUtils.formatDate(new Date())); + response.setHeader("Cache-Control","max-age=300"); + final DummyBackend backend = new DummyBackend(); + backend.setResponse(response); + impl = createCachingExecChain(backend, new BasicHttpCache(), CacheConfig.DEFAULT); + impl.execute(route, request, context, null); + impl.execute(route, request, context, null); + assertEquals(1, backend.getExecutions()); + } + + @Test + public void testNoEntityForIfNoneMatchRequestNotYetInCache() throws Exception { + + final Date now = new Date(); + final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet( + "http://foo.example.com/")); + req1.addHeader("If-None-Match", "\"etag\""); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp1.setHeader("Content-Length", "128"); + resp1.setHeader("ETag", "\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control", "public, max-age=5"); + + backendExpectsAnyRequestAndReturn(resp1); + replayMocks(); + final HttpResponse result = impl.execute(route, req1, context, null); + verifyMocks(); + + assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine() + .getStatusCode()); + assertNull("The 304 response messages MUST NOT contain a message-body", + result.getEntity()); + } + + @Test + public void testNotModifiedResponseUpdatesCacheEntryWhenNoEntity() throws Exception { + + final Date now = new Date(); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req1.addHeader("If-None-Match", "etag"); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req2.addHeader("If-None-Match", "etag"); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Cache-Control","max-age=0"); + resp1.setHeader("Etag", "etag"); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Cache-Control","max-age=0"); + resp1.setHeader("Etag", "etag"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + replayMocks(); + final HttpResponse result1 = impl.execute(route, req1, context, null); + final HttpResponse result2 = impl.execute(route, req2, context, null); + verifyMocks(); + + assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getStatusLine().getStatusCode()); + assertEquals("etag", result1.getFirstHeader("Etag").getValue()); + assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getStatusLine().getStatusCode()); + assertEquals("etag", result2.getFirstHeader("Etag").getValue()); + } + + @Test + public void testNotModifiedResponseWithVaryUpdatesCacheEntryWhenNoEntity() throws Exception { + + final Date now = new Date(); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req1.addHeader("If-None-Match", "etag"); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req2.addHeader("If-None-Match", "etag"); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Cache-Control","max-age=0"); + resp1.setHeader("Etag", "etag"); + resp1.setHeader("Vary", "Accept-Encoding"); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Cache-Control","max-age=0"); + resp1.setHeader("Etag", "etag"); + resp1.setHeader("Vary", "Accept-Encoding"); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2); + replayMocks(); + final HttpResponse result1 = impl.execute(route, req1, context, null); + final HttpResponse result2 = impl.execute(route, req2, context, null); + verifyMocks(); + + assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getStatusLine().getStatusCode()); + assertEquals("etag", result1.getFirstHeader("Etag").getValue()); + assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getStatusLine().getStatusCode()); + assertEquals("etag", result2.getFirstHeader("Etag").getValue()); + } + + @Test + public void testDoesNotSend304ForNonConditionalRequest() throws Exception { + + final Date now = new Date(); + final Date inOneMinute = new Date(System.currentTimeMillis()+60000); + + impl = createCachingExecChain(mockBackend, new BasicHttpCache(), CacheConfig.DEFAULT); + + final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + req1.addHeader("If-None-Match", "etag"); + + final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(new HttpGet("http://foo.example.com/")); + + final HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, "Not modified"); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Cache-Control","public, max-age=60"); + resp1.setHeader("Expires",DateUtils.formatDate(inOneMinute)); + resp1.setHeader("Etag", "etag"); + resp1.setHeader("Vary", "Accept-Encoding"); + + final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "Ok"); + resp2.setHeader("Date", DateUtils.formatDate(now)); + resp2.setHeader("Cache-Control","public, max-age=60"); + resp2.setHeader("Expires",DateUtils.formatDate(inOneMinute)); + resp2.setHeader("Etag", "etag"); + resp2.setHeader("Vary", "Accept-Encoding"); + resp2.setEntity(HttpTestUtils.makeBody(128)); + + backendExpectsAnyRequestAndReturn(resp1); + backendExpectsAnyRequestAndReturn(resp2).anyTimes(); + replayMocks(); + final HttpResponse result1 = impl.execute(route, req1, context, null); + final HttpResponse result2 = impl.execute(route, req2, context, null); + verifyMocks(); + + assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getStatusLine().getStatusCode()); + assertNull(result1.getEntity()); + assertEquals(HttpStatus.SC_OK, result2.getStatusLine().getStatusCode()); + Assert.assertNotNull(result2.getEntity()); + } + + private IExpectationSetters backendExpectsAnyRequestAndReturn( + final HttpResponse response) throws Exception { + final CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); + } + + protected IExpectationSetters backendExpectsRequestAndReturn( + final HttpRequestWrapper request, final HttpResponse response) throws Exception { + final CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.eq(request), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); + } + + protected IExpectationSetters backendExpectsRequestAndReturn( + final HttpRequestWrapper request, final CloseableHttpResponse response) throws Exception { + final CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.eq(request), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(response); + } + + protected IExpectationSetters backendExpectsAnyRequestAndThrows( + final Throwable throwable) throws Exception { + final CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.isA(HttpRequestWrapper.class), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andThrow(throwable); + } + + protected IExpectationSetters backendCaptureRequestAndReturn( + final Capture cap, final HttpResponse response) throws Exception { + final CloseableHttpResponse resp = mockBackend.execute( + EasyMock.isA(HttpRoute.class), + EasyMock.capture(cap), + EasyMock.isA(HttpClientContext.class), + EasyMock.isNull()); + return EasyMock.expect(resp).andReturn(Proxies.enhanceResponse(response)); + } + + protected void getCacheEntryReturns(final HttpCacheEntry result) throws IOException { + expect(mockCache.getCacheEntry(eq(host), eqRequest(request))).andReturn(result); + } + + private void cacheInvalidatorWasCalled() throws IOException { + mockCache.flushInvalidatedCacheEntriesFor( + (HttpHost)anyObject(), + (HttpRequest)anyObject()); + } + + protected void cacheEntryValidatable(final boolean b) { + expect(mockValidityPolicy.isRevalidatable( + (HttpCacheEntry)anyObject())).andReturn(b); + } + + protected void cacheEntryMustRevalidate(final boolean b) { + expect(mockValidityPolicy.mustRevalidate(mockCacheEntry)) + .andReturn(b); + } + + protected void cacheEntryProxyRevalidate(final boolean b) { + expect(mockValidityPolicy.proxyRevalidate(mockCacheEntry)) + .andReturn(b); + } + + protected void mayReturnStaleWhileRevalidating(final boolean b) { + expect(mockValidityPolicy.mayReturnStaleWhileRevalidating( + (HttpCacheEntry)anyObject(), (Date)anyObject())).andReturn(b); + } + + protected void conditionalRequestBuilderReturns(final HttpRequestWrapper validate) + throws Exception { + expect(mockConditionalRequestBuilder.buildConditionalRequest( + request, entry)).andReturn(validate); + } + + protected void requestPolicyAllowsCaching(final boolean allow) { + expect(mockRequestPolicy.isServableFromCache( + (HttpRequest)anyObject())).andReturn(allow); + } + + protected void cacheEntrySuitable(final boolean suitable) { + expect( + mockSuitabilityChecker.canCachedResponseBeUsed( + (HttpHost)anyObject(), + (HttpRequest)anyObject(), + (HttpCacheEntry)anyObject(), + (Date)anyObject())).andReturn(suitable); + } + + private void entryHasStaleness(final long staleness) { + expect(mockValidityPolicy.getStalenessSecs( + (HttpCacheEntry)anyObject(), + (Date)anyObject() + )).andReturn(staleness); + } + + protected void responseIsGeneratedFromCache() { + expect(mockResponseGenerator.generateResponse( + (HttpCacheEntry)anyObject())).andReturn(mockCachedResponse); + } + +} diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java index 5cb4353b9..a30ec2497 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestHttpCacheJiraNumber1147.java @@ -112,7 +112,7 @@ public class TestHttpCacheJiraNumber1147 { EasyMock.replay(backend); final BasicHttpCache cache = new BasicHttpCache(resourceFactory, httpCacheStorage, cacheConfig); - final CachingExec t = new CachingExec(backend, cache, cacheConfig); + final ClientExecChain t = createCachingExecChain(backend, cache, cacheConfig); final HttpResponse response1 = t.execute(route, get, context, null); Assert.assertEquals(200, response1.getStatusLine().getStatusCode()); @@ -137,4 +137,9 @@ public class TestHttpCacheJiraNumber1147 { EasyMock.verify(backend); } + protected ClientExecChain createCachingExecChain(final ClientExecChain backend, + final BasicHttpCache cache, final CacheConfig config) { + return new CachingExec(backend, cache, config); + } + } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java index 6344a662f..2de853e07 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolAllowedBehavior.java @@ -65,8 +65,8 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest { replayMocks(); behaveAsNonSharedCache(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -86,8 +86,8 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest { replayMocks(); behaveAsNonSharedCache(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java index 19f1c9d2c..3a7f02370 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java @@ -37,6 +37,7 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ProtocolVersion; import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.cache.HttpCacheContext; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; @@ -84,9 +85,10 @@ public class TestProtocolDeviations { private ClientExecChain mockBackend; private HttpCache mockCache; private HttpRequest request; + private HttpCacheContext context; private CloseableHttpResponse originResponse; - private CachingExec impl; + private ClientExecChain impl; @Before public void setUp() { @@ -98,6 +100,8 @@ public class TestProtocolDeviations { request = new BasicHttpRequest("GET", "/foo", HTTP_1_1); + context = HttpCacheContext.create(); + originResponse = Proxies.enhanceResponse(make200Response()); final CacheConfig config = CacheConfig.custom() @@ -110,7 +114,12 @@ public class TestProtocolDeviations { mockEntity = EasyMock.createNiceMock(HttpEntity.class); mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = new CachingExec(mockBackend, cache, config); + impl = createCachingExecChain(mockBackend, cache, config); + } + + protected ClientExecChain createCachingExecChain( + final ClientExecChain backend, final HttpCache cache, final CacheConfig config) { + return new CachingExec(backend, cache, config); } private HttpResponse make200Response() { @@ -169,7 +178,7 @@ public class TestProtocolDeviations { replayMocks(); - final HttpResponse response = impl.execute(route, HttpRequestWrapper.wrap(post)); + final HttpResponse response = impl.execute(route, HttpRequestWrapper.wrap(post), context, null); verifyMocks(); @@ -227,7 +236,7 @@ public class TestProtocolDeviations { replayMocks(); EasyMock.replay(mockBody); - final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(post)); + final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(post), context, null); verifyMocks(); EasyMock.verify(mockBody); @@ -266,7 +275,7 @@ public class TestProtocolDeviations { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(options)); + impl.execute(route, HttpRequestWrapper.wrap(options), context, null); verifyMocks(); @@ -308,7 +317,7 @@ public class TestProtocolDeviations { replayMocks(); try { - final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); + final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request), context, null); Assert.assertTrue(HttpStatus.SC_PARTIAL_CONTENT != result.getStatusLine() .getStatusCode()); } catch (final ClientProtocolException acceptableBehavior) { @@ -336,7 +345,7 @@ public class TestProtocolDeviations { EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); + final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request), context, null); verifyMocks(); Assert.assertSame(originResponse, result); } @@ -359,7 +368,7 @@ public class TestProtocolDeviations { EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); + final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request), context, null); verifyMocks(); Assert.assertSame(originResponse, result); } @@ -383,7 +392,7 @@ public class TestProtocolDeviations { EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request)); + final HttpResponse result = impl.execute(route, HttpRequestWrapper.wrap(request), context, null); verifyMocks(); Assert.assertSame(originResponse, result); } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java index 42b0b4f7e..84094d361 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java @@ -47,6 +47,7 @@ import org.apache.http.HttpVersion; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.utils.DateUtils; @@ -91,7 +92,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { originResponse.setHeader("Content-Encoding", "identity"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); boolean foundIdentity = false; for(final Header h : result.getHeaders("Content-Encoding")) { @@ -127,8 +128,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req2.setHeader(conditionalHeader, validator); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (HttpStatus.SC_NOT_MODIFIED == result.getStatusLine().getStatusCode()) { @@ -247,15 +248,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final Capture cap = new Capture(); EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp2)).times(0,1); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (!cap.hasCaptured() @@ -321,7 +322,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp); replayMocks(); - final HttpResponse result = impl.execute(route, req); + final HttpResponse result = impl.execute(route, req, context, null); verifyMocks(); assertNull(result.getFirstHeader(entityHeader)); @@ -384,7 +385,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp); replayMocks(); - final HttpResponse result = impl.execute(route, req); + final HttpResponse result = impl.execute(route, req, context, null); verifyMocks(); assertNull(result.getFirstHeader("Content-Range")); @@ -423,10 +424,10 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andThrow(new IOException()); replayMocks(); - impl.execute(route, req1); + impl.execute(route, req1, context, null); HttpResponse result = null; try { - result = impl.execute(route, req2); + result = impl.execute(route, req2, context, null); } catch (final IOException acceptable) { } verifyMocks(); @@ -504,8 +505,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andThrow(new IOException()).times(0,1); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -565,8 +566,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andThrow(new IOException()).anyTimes(); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -606,7 +607,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); assertNull(result.getFirstHeader("Warning")); @@ -627,7 +628,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); assertEquals(warning, result.getFirstHeader("Warning").getValue()); @@ -645,7 +646,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { .getCanonicalHeaderValue(originResponse, headerName); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); assertEquals(headerValue, result.getFirstHeader(headerName).getValue()); @@ -657,12 +658,12 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final Capture cap = new Capture(); EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); assertEquals(headerValue, HttpTestUtils.getCanonicalHeaderValue(cap.getValue(), @@ -947,15 +948,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -998,15 +999,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -1057,15 +1058,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), eqRequest(revalidate), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, @@ -1117,15 +1118,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -1193,16 +1194,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); - impl.execute(route,req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -1275,10 +1276,10 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req4.setHeader("User-Agent", "agent1"); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result1 = impl.execute(route, req3); - final HttpResponse result2 = impl.execute(route, req4); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result1 = impl.execute(route, req3, context, null); + final HttpResponse result2 = impl.execute(route, req4, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result1.getStatusLine().getStatusCode()); @@ -1321,9 +1322,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req3.setHeader("User-Agent", "agent2"); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -1372,16 +1373,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final Capture cap = new Capture(); EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -1414,7 +1415,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp1); final HttpRequestWrapper req2 = HttpRequestWrapper.wrap( - new HttpGet("http://foo.example.com/bar")); + new HttpPost("http://foo.example.com/bar")); final HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"new-etag\""); resp2.setHeader("Date", DateUtils.formatDate(now)); @@ -1429,9 +1430,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -1455,7 +1456,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req2); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -1473,7 +1474,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req2); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -1509,9 +1510,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp3, result)); @@ -1563,11 +1564,11 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp5); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); - final HttpResponse result4 = impl.execute(route, req4); - final HttpResponse result5 = impl.execute(route, req5); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); + final HttpResponse result4 = impl.execute(route, req4, context, null); + final HttpResponse result5 = impl.execute(route, req5, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp4, result4)); @@ -1604,9 +1605,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(HttpTestUtils.makeDefaultRequest()); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -1642,8 +1643,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -1668,8 +1669,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -1692,14 +1693,14 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final Capture cap = new Capture(); EasyMock.expect( mockBackend.execute( - EasyMock.same(route), + EasyMock.eq(route), EasyMock.capture(cap), EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn( Proxies.enhanceResponse(HttpTestUtils.make200Response())); replayMocks(); - impl.execute(route, req1); + impl.execute(route, req1, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -1737,7 +1738,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req.setHeader("Cache-Control", "only-if-cached"); replayMocks(); - final HttpResponse result = impl.execute(route, req); + final HttpResponse result = impl.execute(route, req, context, null); verifyMocks(); assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, @@ -1757,8 +1758,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req2.setHeader("Cache-Control", "only-if-cached"); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); @@ -1778,8 +1779,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req2.setHeader("Cache-Control", "only-if-cached"); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, @@ -1801,8 +1802,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req2.setHeader("Cache-Control", "max-stale=20, only-if-cached"); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); @@ -1822,8 +1823,8 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req2.setHeader("If-None-Match","W/\"weak-sauce\""); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java index 62d7a37f1..d2fd842b1 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java @@ -85,7 +85,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); @@ -118,7 +118,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertSame(originResponse, result); @@ -141,7 +141,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); @@ -172,7 +172,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); @@ -204,7 +204,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion()); @@ -223,7 +223,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion()); @@ -253,7 +253,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -278,7 +278,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -311,14 +311,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest forwarded = reqCapture.getValue(); Assert.assertNotNull(forwarded); - Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(request, h), HttpTestUtils - .getCanonicalHeaderValue(forwarded, h)); + final String expected = HttpTestUtils.getCanonicalHeaderValue(request, h); + final String actual = HttpTestUtils.getCanonicalHeaderValue(forwarded, h); + if (!actual.contains(expected)) { + Assert.assertEquals(expected, actual); + } } @@ -431,7 +434,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -520,7 +523,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); // in particular, there were no storage calls on the cache verifyMocks(); @@ -564,7 +567,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest forwarded = reqCap.getValue(); @@ -585,7 +588,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); final Header[] hdrs = result.getHeaders("X-Unknown-Header"); @@ -619,7 +622,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(post)); + impl.execute(route, HttpRequestWrapper.wrap(post), context, null); verifyMocks(); @@ -662,7 +665,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(post)); + impl.execute(route, HttpRequestWrapper.wrap(post), context, null); verifyMocks(); @@ -698,7 +701,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest forwarded = reqCap.getValue(); boolean foundExpectContinue = false; @@ -765,7 +768,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { try { // if a 100 response gets up to us from the HttpClient // backend, we can't really handle it at that point - impl.execute(route, HttpRequestWrapper.wrap(post)); + impl.execute(route, HttpRequestWrapper.wrap(post), context, null); Assert.fail("should have thrown an exception"); } catch (final ClientProtocolException expected) { } @@ -793,7 +796,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -819,7 +822,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); final Header contentLength = result.getFirstHeader("Content-Length"); @@ -843,7 +846,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request.setHeader("Max-Forwards", "0"); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -869,7 +872,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -894,7 +897,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest forwarded = reqCap.getValue(); @@ -919,7 +922,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -981,9 +984,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -1043,7 +1046,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(post)); + impl.execute(route, HttpRequestWrapper.wrap(post), context, null); verifyMocks(); } @@ -1073,7 +1076,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(put)); + impl.execute(route, HttpRequestWrapper.wrap(put), context, null); verifyMocks(); } @@ -1099,7 +1102,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -1126,7 +1129,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(trace)); + impl.execute(route, HttpRequestWrapper.wrap(trace), context, null); verifyMocks(); final HttpRequest forwarded = reqCap.getValue(); @@ -1160,7 +1163,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -1186,7 +1189,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -1213,7 +1216,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -1256,8 +1259,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp1).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) { @@ -1288,8 +1291,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp1).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) { @@ -1322,8 +1325,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp1).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) { @@ -1351,7 +1354,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); Assert.assertTrue(result.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT || result.getFirstHeader("Date") != null); @@ -1374,8 +1377,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); @@ -1400,8 +1403,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); @@ -1446,9 +1449,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); @@ -1496,8 +1499,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); @@ -1545,8 +1548,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); @@ -1640,9 +1643,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp3)).times(0, 1); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); @@ -1734,9 +1737,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp3)).times(0, 1); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); @@ -1766,7 +1769,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void test206ResponsesAreNotCachedIfTheCacheDoesNotSupportRangeAndContentRangeHeaders() throws Exception { - if (!impl.supportsRangeAndContentRangeHeaders()) { + if (!supportsRangeAndContentRangeHeaders(impl)) { emptyMockCacheExpectsNoPuts(); request = HttpRequestWrapper.wrap( @@ -1791,7 +1794,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } } @@ -1825,7 +1828,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -1856,7 +1859,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -1891,7 +1894,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Date")); @@ -1917,8 +1920,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { @@ -1952,8 +1955,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { @@ -1982,8 +1985,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { @@ -2049,9 +2052,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp2)).times(1, 2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); @@ -2103,8 +2106,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp1)).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); @@ -2188,8 +2191,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp3)); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -2265,8 +2268,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - impl.execute(route, initialRequest); - final HttpResponse result = impl.execute(route, secondRequest); + impl.execute(route, initialRequest, context, null); + final HttpResponse result = impl.execute(route, secondRequest, context, null); verifyMocks(); @@ -2301,7 +2304,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); if (result.getStatusLine().getStatusCode() == 401) { Assert.assertNotNull(result.getFirstHeader("WWW-Authenticate")); } @@ -2325,7 +2328,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); if (result.getStatusLine().getStatusCode() == 405) { Assert.assertNotNull(result.getFirstHeader("Allow")); } @@ -2354,7 +2357,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); if (result.getStatusLine().getStatusCode() == 407) { Assert.assertNotNull(result.getFirstHeader("Proxy-Authenticate")); } @@ -2381,7 +2384,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); if (result.getStatusLine().getStatusCode() == 416) { @@ -2425,8 +2428,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(orig416)).times(0, 1); replayMocks(); - impl.execute(route, request); - final HttpResponse result = impl.execute(route, rangeReq); + impl.execute(route, request, context, null); + final HttpResponse result = impl.execute(route, rangeReq, context, null); verifyMocks(); // might have gotten a 416 from the origin or the cache @@ -2501,8 +2504,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { notModified.setHeader("Date", DateUtils.formatDate(now)); notModified.setHeader("ETag", "\"etag\""); - mockCache.flushInvalidatedCacheEntriesFor(host, request); - EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); + mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), + eqRequest(request)); + EasyMock.expect( + mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))) + .andReturn(entry); EasyMock.expect( mockBackend.execute( EasyMock.eq(route), @@ -2510,16 +2516,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isA(HttpClientContext.class), EasyMock.isNull())).andReturn(notModified); EasyMock.expect(mockCache.updateCacheEntry( - EasyMock.same(host), - EasyMock.same(request), - EasyMock.same(entry), - EasyMock.same(notModified), + EasyMock.eq(host), + eqRequest(request), + EasyMock.eq(entry), + eqResponse(notModified), EasyMock.isA(Date.class), EasyMock.isA(Date.class))) .andReturn(HttpTestUtils.makeCacheEntry()); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -2545,11 +2551,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - mockCache.flushInvalidatedCacheEntriesFor(host, request); - EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); + mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); + EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -2593,8 +2599,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - mockCache.flushInvalidatedCacheEntriesFor(host, request); - EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); + mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); + EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); EasyMock.expect( mockBackend.execute( EasyMock.isA(HttpRoute.class), @@ -2605,7 +2611,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); @@ -2680,11 +2686,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse stale = impl.execute(route, req1); + final HttpResponse stale = impl.execute(route, req1, context, null); Assert.assertNotNull(stale.getFirstHeader("Warning")); - final HttpResponse result1 = impl.execute(route, req2); - final HttpResponse result2 = impl.execute(route, req3); + final HttpResponse result1 = impl.execute(route, req2, context, null); + final HttpResponse result2 = impl.execute(route, req3, context, null); verifyMocks(); @@ -2752,11 +2758,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); - final HttpResponse stale = impl.execute(route, req1); + final HttpResponse stale = impl.execute(route, req1, context, null); Assert.assertNotNull(stale.getFirstHeader("Warning")); - final HttpResponse result1 = impl.execute(route, req2); - final HttpResponse result2 = impl.execute(route, req3); + final HttpResponse result1 = impl.execute(route, req2, context, null); + final HttpResponse result2 = impl.execute(route, req3, context, null); verifyMocks(); @@ -2812,11 +2818,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - mockCache.flushInvalidatedCacheEntriesFor(host, request); - EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); + mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); + EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -2875,12 +2881,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final Capture cap = new Capture(); - mockCache.flushInvalidatedCacheEntriesFor(host, request); + mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); mockCache.flushInvalidatedCacheEntriesFor( EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequestWrapper.class), EasyMock.isA(HttpResponse.class)); - EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry); + EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); EasyMock.expect( mockBackend.execute( EasyMock.isA(HttpRoute.class), @@ -2893,12 +2899,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.expect(mockCache.cacheAndReturnResponse( EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequestWrapper.class), - EasyMock.same(validated), + eqResponse(validated), EasyMock.isA(Date.class), EasyMock.isA(Date.class))).andReturn(reconstructed).times(0, 1); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(200, result.getStatusLine().getStatusCode()); @@ -2966,9 +2972,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - final HttpResponse result = impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + final HttpResponse result = impl.execute(route, req3, context, null); verifyMocks(); Assert.assertEquals("\"etag1\"", result.getFirstHeader("ETag").getValue()); } @@ -2998,7 +3004,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse).times(0, 1); replayMocks(); - final HttpResponse response = impl.execute(route, request); + final HttpResponse response = impl.execute(route, request, context, null); verifyMocks(); // it's probably ok to return a 400 (Bad Request) to this client @@ -3099,8 +3105,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp1)).times(1, 2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertFalse(HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()); @@ -3149,8 +3155,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp1)); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); final HttpRequest validation = cap.getValue(); @@ -3224,8 +3230,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp1)).times(2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertFalse(HttpStatus.SC_NOT_MODIFIED == result.getStatusLine().getStatusCode()); @@ -3260,8 +3266,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp1)).times(1,2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -3276,7 +3282,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testCacheWithoutSupportForRangeAndContentRangeHeadersDoesNotCacheA206Response() throws Exception { - if (!impl.supportsRangeAndContentRangeHeaders()) { + if (!supportsRangeAndContentRangeHeaders(impl)) { emptyMockCacheExpectsNoPuts(); final HttpRequestWrapper req = HttpRequestWrapper.wrap( @@ -3295,7 +3301,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(Proxies.enhanceResponse(resp)); replayMocks(); - impl.execute(route, req); + impl.execute(route, req, context, null); verifyMocks(); } } @@ -3322,8 +3328,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse).times(2); replayMocks(); - impl.execute(route, request); - impl.execute(route, request); + impl.execute(route, request, context, null); + impl.execute(route, request, context, null); verifyMocks(); } @@ -3339,7 +3345,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3374,7 +3380,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertNull(result.getFirstHeader(header)); @@ -3415,8 +3421,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3457,8 +3463,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertNull(result.getFirstHeader(header)); @@ -3501,7 +3507,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(req)); + impl.execute(route, HttpRequestWrapper.wrap(req), context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -3548,7 +3554,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, HttpRequestWrapper.wrap(req)); + impl.execute(route, HttpRequestWrapper.wrap(req), context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -3602,7 +3608,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); final Header expHdr = result.getFirstHeader("Expires"); @@ -3625,8 +3631,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); final Header expHdr = result.getFirstHeader("Expires"); @@ -3649,7 +3655,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3688,8 +3694,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); @@ -3722,8 +3728,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse).times(1,2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertEquals("bytes 0-49/128", @@ -3825,8 +3831,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); final InputStream i1 = resp1.getEntity().getContent(); @@ -3888,8 +3894,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); final String[] endToEndHeaders = { @@ -3937,9 +3943,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(route, req1); - final HttpResponse result1 = impl.execute(route, req2); - final HttpResponse result2 = impl.execute(route, req3); + impl.execute(route, req1, context, null); + final HttpResponse result1 = impl.execute(route, req2, context, null); + final HttpResponse result2 = impl.execute(route, req3, context, null); verifyMocks(); final String[] endToEndHeaders = { @@ -3981,9 +3987,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(route, req1); - final HttpResponse result1 = impl.execute(route, req2); - final HttpResponse result2 = impl.execute(route, req3); + impl.execute(route, req1, context, null); + final HttpResponse result1 = impl.execute(route, req2, context, null); + final HttpResponse result2 = impl.execute(route, req3, context, null); verifyMocks(); final String h = "Cache-Control"; @@ -4058,9 +4064,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4110,9 +4116,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4163,9 +4169,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4217,9 +4223,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4271,9 +4277,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4326,9 +4332,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4381,9 +4387,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4435,9 +4441,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4477,8 +4483,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -4511,8 +4517,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -4590,8 +4596,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp200)).times(0,1); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (HttpStatus.SC_OK == result.getStatusLine().getStatusCode()) { @@ -4623,7 +4629,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); final int status = result.getStatusLine().getStatusCode(); @@ -4667,9 +4673,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, unsafeReq); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, unsafeReq, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4713,9 +4719,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp3); replayMocks(); - impl.execute(route, req1); - impl.execute(route, unsafeReq); - impl.execute(route, req3); + impl.execute(route, req1, context, null); + impl.execute(route, unsafeReq, context, null); + impl.execute(route, req3, context, null); verifyMocks(); } @@ -4817,9 +4823,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(otherRoute, req1); - impl.execute(route, unsafeReq); - impl.execute(otherRoute, req3); + impl.execute(otherRoute, req1, context, null); + impl.execute(route, unsafeReq, context, null); + impl.execute(otherRoute, req3, context, null); verifyMocks(); } @@ -4904,7 +4910,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp)); replayMocks(); - impl.execute(route, wrapper); + impl.execute(route, wrapper, context, null); verifyMocks(); } @@ -4982,7 +4988,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route,request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals("2147483648", @@ -5002,7 +5008,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Allow",allowHeaderValue); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route,request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(originResponse,"Allow"), HttpTestUtils.getCanonicalHeaderValue(result, "Allow")); @@ -5056,8 +5062,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } } @@ -5135,8 +5141,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -5213,8 +5219,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp2)).times(0,1); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (!cap.hasCaptured()) { @@ -5250,7 +5256,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { replayMocks(); try { - impl.execute(route, request); + impl.execute(route, request, context, null); } catch (final ClientProtocolException acceptable) { } verifyMocks(); @@ -5296,8 +5302,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req, context, null); verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); @@ -5357,8 +5363,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp2)); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); final HttpRequest reval = cap.getValue(); @@ -5405,8 +5411,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andThrow(new SocketTimeoutException()); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, @@ -5486,8 +5492,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } } @@ -5512,8 +5518,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2).times(0,1); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); Assert.assertNull(result.getFirstHeader("X-Personal")); } @@ -5546,8 +5552,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -5571,8 +5577,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -5611,8 +5617,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Proxies.enhanceResponse(resp2)).times(0,1); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); if (!cap.hasCaptured()) { @@ -5643,7 +5649,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route,request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -5656,7 +5662,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route,request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -5668,7 +5674,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route,request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -5680,7 +5686,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - impl.execute(route,request); + impl.execute(route, request, context, null); verifyMocks(); } @@ -5697,7 +5703,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route,request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); int total_encodings = 0; for(final Header hdr : result.getHeaders("Content-Encoding")) { @@ -5725,7 +5731,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route,request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); int total_encodings = 0; for(final Header hdr : result.getHeaders("Content-Encoding")) { @@ -5772,8 +5778,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -5793,7 +5799,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Date")); } @@ -5823,8 +5829,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -5864,8 +5870,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - impl.execute(route, req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); } @@ -5883,7 +5889,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(server, result.getFirstHeader("Server").getValue()); } @@ -5902,7 +5908,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); int transfer_encodings = 0; for(final Header h : result.getHeaders("Transfer-Encoding")) { @@ -5931,7 +5937,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); int transfer_encodings = 0; for(final Header h : result.getHeaders("Transfer-Encoding")) { @@ -5971,7 +5977,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); for(final Header h : result.getHeaders("Vary")) { for(final HeaderElement elt : h.getElements()) { @@ -5999,7 +6005,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -6012,7 +6018,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Via"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); assertValidViaHeader(result.getFirstHeader("Via").getValue()); } @@ -6100,7 +6106,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { EasyMock.isNull())).andReturn(originResponse); replayMocks(); - impl.execute(route, request); + impl.execute(route, request, context, null); verifyMocks(); final HttpRequest captured = cap.getValue(); @@ -6123,7 +6129,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); final String via = result.getFirstHeader("Via").getValue(); @@ -6151,7 +6157,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); Assert.assertEquals(warning, result.getFirstHeader("Warning").getValue()); @@ -6192,8 +6198,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); boolean oldWarningFound = false; @@ -6228,7 +6234,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Date", dateHdr); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); // note that currently the implementation acts as an HTTP/1.1 proxy, // which means that all the responses from the caching module should @@ -6272,7 +6278,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); for(final Header h : result.getHeaders("Warning")) { @@ -6292,7 +6298,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); for(final Header h : result.getHeaders("Warning")) { @@ -6311,7 +6317,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); - final HttpResponse result = impl.execute(route, request); + final HttpResponse result = impl.execute(route, request, context, null); verifyMocks(); final Header[] warningHeaders = result.getHeaders("Warning"); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java index a04555072..bf82be0fc 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRFC5861Compliance.java @@ -82,8 +82,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); HttpTestUtils.assert110WarningFound(result); @@ -110,8 +110,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - impl.execute(route,req2); + impl.execute(route, req1, context, null); + impl.execute(route, req2, context, null); verifyMocks(); assertTrue(cis.wasClosed()); @@ -133,8 +133,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); @@ -157,8 +157,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); @@ -184,8 +184,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); HttpTestUtils.assert110WarningFound(result); @@ -208,8 +208,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getStatusLine().getStatusCode()); @@ -232,8 +232,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); HttpTestUtils.assert110WarningFound(result); @@ -256,8 +256,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, @@ -282,8 +282,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route,req1); - final HttpResponse result = impl.execute(route,req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, @@ -324,8 +324,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1)); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -369,8 +369,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { req2.setHeader("If-None-Match","\"etag\""); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getStatusLine().getStatusCode()); @@ -420,8 +420,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -471,8 +471,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode()); @@ -523,8 +523,8 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { backendExpectsAnyRequestAndReturn(resp2); replayMocks(); - impl.execute(route, req1); - final HttpResponse result = impl.execute(route, req2); + impl.execute(route, req1, context, null); + final HttpResponse result = impl.execute(route, req2, context, null); verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getStatusLine().getStatusCode());