From 760795b6dfa6db8359aa9a4cd740a09ffb49b8f8 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 12 Jun 2021 21:57:44 +0200 Subject: [PATCH] HTTPCLIENT-1244: Replaced EasyMock with Mockito in the HTTP cache unit tests --- .travis.yml | 6 +- httpclient5-cache/pom.xml | 5 - .../http/impl/cache/AbstractProtocolTest.java | 186 -- .../client5/http/impl/cache/DummyBackend.java | 65 - .../http/impl/cache/HttpTestUtils.java | 14 +- .../http/impl/cache/RequestEquivalent.java | 23 +- .../http/impl/cache/ResponseEquivalent.java | 23 +- .../http/impl/cache/TestCachingExec.java | 458 ----- .../http/impl/cache/TestCachingExecChain.java | 925 +++------- .../cache/TestProtocolAllowedBehavior.java | 96 +- .../impl/cache/TestProtocolDeviations.java | 178 +- .../cache/TestProtocolRecommendations.java | 441 +++-- .../impl/cache/TestProtocolRequirements.java | 1593 ++++++----------- .../impl/cache/TestRFC5861Compliance.java | 228 ++- pom.xml | 7 - 15 files changed, 1270 insertions(+), 2978 deletions(-) delete mode 100644 httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/AbstractProtocolTest.java delete mode 100644 httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java delete mode 100644 httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java diff --git a/.travis.yml b/.travis.yml index 79392d417..1e0a68394 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,14 +27,10 @@ addons: - maven jdk: - - oraclejdk8 - openjdk12 - - oraclejdk12 + - oraclejdk16 - openjdk-ea matrix: allow_failures: - jdk: openjdk-ea - -after_success: - - mvn clean cobertura:cobertura coveralls:report diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index 743d16921..2a4b6489f 100644 --- a/httpclient5-cache/pom.xml +++ b/httpclient5-cache/pom.xml @@ -79,11 +79,6 @@ mockito-core test - - org.easymock - easymock - test - org.apache.httpcomponents.client5 httpclient5 diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/AbstractProtocolTest.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/AbstractProtocolTest.java deleted file mode 100644 index 67e75a213..000000000 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/AbstractProtocolTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * ==================================================================== - * 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.hc.client5.http.impl.cache; - -import java.io.IOException; -import java.util.HashMap; - -import org.apache.hc.client5.http.HttpRoute; -import org.apache.hc.client5.http.classic.ExecChain; -import org.apache.hc.client5.http.classic.ExecChainHandler; -import org.apache.hc.client5.http.classic.ExecRuntime; -import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.core5.http.ClassicHttpRequest; -import org.apache.hc.core5.http.ClassicHttpResponse; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpException; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; -import org.apache.hc.core5.http.message.BasicClassicHttpRequest; -import org.easymock.EasyMock; -import org.easymock.IExpectationSetters; -import org.junit.Before; - -public abstract class AbstractProtocolTest { - - protected static final int MAX_BYTES = 1024; - protected static final int MAX_ENTRIES = 100; - protected final int entityLength = 128; - protected HttpHost host; - protected HttpRoute route; - protected HttpEntity body; - protected HttpClientContext context; - protected ExecChain mockExecChain; - protected ExecRuntime mockExecRuntime; - protected HttpCache mockCache; - protected ClassicHttpRequest request; - protected ClassicHttpResponse originResponse; - protected CacheConfig config; - protected ExecChainHandler impl; - protected HttpCache cache; - - public static ClassicHttpRequest eqRequest(final ClassicHttpRequest in) { - EasyMock.reportMatcher(new RequestEquivalent(in)); - return null; - } - - public static HttpResponse eqResponse(final HttpResponse in) { - EasyMock.reportMatcher(new ResponseEquivalent(in)); - return null; - } - - public static ClassicHttpResponse eqCloseableResponse(final ClassicHttpResponse in) { - EasyMock.reportMatcher(new ResponseEquivalent(in)); - return null; - } - - @Before - public void setUp() { - host = new HttpHost("foo.example.com", 80); - - route = new HttpRoute(host); - - body = HttpTestUtils.makeBody(entityLength); - - request = new BasicClassicHttpRequest("GET", "/foo"); - - context = HttpClientContext.create(); - - originResponse = HttpTestUtils.make200Response(); - - config = CacheConfig.custom() - .setMaxCacheEntries(MAX_ENTRIES) - .setMaxObjectSize(MAX_BYTES) - .build(); - - cache = new BasicHttpCache(config); - mockExecChain = EasyMock.createNiceMock(ExecChain.class); - mockExecRuntime = EasyMock.createNiceMock(ExecRuntime.class); - mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = createCachingExecChain(cache, config); - } - - public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { - return impl.execute( - ClassicRequestBuilder.copy(request).build(), - new ExecChain.Scope("test", route, request, mockExecRuntime, context), - mockExecChain); - } - - protected ExecChainHandler createCachingExecChain(final HttpCache cache, final CacheConfig config) { - return new CachingExec(cache, null, config); - } - - protected boolean supportsRangeAndContentRangeHeaders(final ExecChainHandler impl) { - return impl instanceof CachingExec && ((CachingExec) impl).supportsRangeAndContentRangeHeaders(); - } - - protected void replayMocks() { - EasyMock.replay(mockExecChain); - EasyMock.replay(mockCache); - } - - protected void verifyMocks() { - EasyMock.verify(mockExecChain); - EasyMock.verify(mockCache); - } - - protected IExpectationSetters backendExpectsAnyRequest() throws Exception { - final ClassicHttpResponse resp = mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class)); - return EasyMock.expect(resp); - } - - protected IExpectationSetters backendExpectsAnyRequestAndReturn( - final ClassicHttpResponse response) throws Exception { - final ClassicHttpResponse resp = mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class)); - return EasyMock.expect(resp).andReturn(response); - } - - protected void emptyMockCacheExpectsNoPuts() throws Exception { - mockExecChain = EasyMock.createNiceMock(ExecChain.class); - mockCache = EasyMock.createNiceMock(HttpCache.class); - - impl = new CachingExec(mockCache, null, config); - - EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class))) - .andReturn(null).anyTimes(); - EasyMock.expect(mockCache.getVariantCacheEntriesWithEtags(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class))) - .andReturn(new HashMap<>()).anyTimes(); - - mockCache.flushCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)); - EasyMock.expectLastCall().anyTimes(); - - mockCache.flushCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)); - EasyMock.expectLastCall().anyTimes(); - - mockCache.flushCacheEntriesInvalidatedByRequest(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)); - EasyMock.expectLastCall().anyTimes(); - - mockCache.flushCacheEntriesInvalidatedByExchange(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class), EasyMock.isA(HttpResponse.class)); - EasyMock.expectLastCall().anyTimes(); - } - - protected void behaveAsNonSharedCache() { - config = CacheConfig.custom() - .setMaxCacheEntries(MAX_ENTRIES) - .setMaxObjectSize(MAX_BYTES) - .setSharedCache(false) - .build(); - impl = new CachingExec(cache, null, config); - } - - public AbstractProtocolTest() { - super(); - } - -} diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java deleted file mode 100644 index 4694e381a..000000000 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * ==================================================================== - * 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.hc.client5.http.impl.cache; - -import java.io.IOException; - -import org.apache.hc.client5.http.classic.ExecChain; -import org.apache.hc.core5.http.ClassicHttpRequest; -import org.apache.hc.core5.http.ClassicHttpResponse; -import org.apache.hc.core5.http.HttpException; -import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; - -public class DummyBackend implements ExecChain { - - private ClassicHttpRequest request; - private ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); - private int executions; - - public void setResponse(final ClassicHttpResponse resp) { - response = resp; - } - - public HttpRequest getCapturedRequest() { - return request; - } - - @Override - public ClassicHttpResponse proceed( - final ClassicHttpRequest request, - final Scope scope) throws IOException, HttpException { - this.request = request; - executions++; - return response; - } - - public int getExecutions() { - return executions; - } -} diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java index b87e066a9..3136b037b 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/HttpTestUtils.java @@ -251,7 +251,7 @@ public class HttpTestUtils { } public static HttpCacheEntry makeCacheEntry(final Date requestDate, - final Date responseDate, final Header[] headers) { + final Date responseDate, final Header... headers) { final byte[] bytes = getRandomBytes(128); return makeCacheEntry(requestDate, responseDate, headers, bytes); } @@ -283,7 +283,7 @@ public class HttpTestUtils { return makeCacheEntry(getStockHeaders(new Date()), bytes); } - public static HttpCacheEntry makeCacheEntry(final Header[] headers) { + public static HttpCacheEntry makeCacheEntry(final Header... headers) { return makeCacheEntry(headers, getRandomBytes(128)); } @@ -292,27 +292,27 @@ public class HttpTestUtils { return makeCacheEntry(now, now); } - public static HttpCacheEntry makeCacheEntryWithNoRequestMethodOrEntity(final Header[] headers) { + public static HttpCacheEntry makeCacheEntryWithNoRequestMethodOrEntity(final Header... headers) { final Date now = new Date(); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, null, null); } - public static HttpCacheEntry makeCacheEntryWithNoRequestMethod(final Header[] headers) { + public static HttpCacheEntry makeCacheEntryWithNoRequestMethod(final Header... headers) { final Date now = new Date(); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, new HeapResource(getRandomBytes(128)), null); } - public static HttpCacheEntry make204CacheEntryWithNoRequestMethod(final Header[] headers) { + public static HttpCacheEntry make204CacheEntryWithNoRequestMethod(final Header... headers) { final Date now = new Date(); return new HttpCacheEntry(now, now, HttpStatus.SC_NO_CONTENT, headers, null, null); } - public static HttpCacheEntry makeHeadCacheEntry(final Header[] headers) { + public static HttpCacheEntry makeHeadCacheEntry(final Header... headers) { final Date now = new Date(); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, null, null); } - public static HttpCacheEntry makeHeadCacheEntryWithNoRequestMethod(final Header[] headers) { + public static HttpCacheEntry makeHeadCacheEntryWithNoRequestMethod(final Header... headers) { final Date now = new Date(); return new HttpCacheEntry(now, now, HttpStatus.SC_OK, headers, null, null); } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/RequestEquivalent.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/RequestEquivalent.java index bd0c6e980..769539e9d 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/RequestEquivalent.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/RequestEquivalent.java @@ -27,30 +27,27 @@ package org.apache.hc.client5.http.impl.cache; import org.apache.hc.core5.http.HttpRequest; -import org.easymock.IArgumentMatcher; +import org.mockito.ArgumentMatcher; +import org.mockito.ArgumentMatchers; -public class RequestEquivalent implements IArgumentMatcher { +public class RequestEquivalent implements ArgumentMatcher { - private final HttpRequest expected; + private final T expected; - public RequestEquivalent(final HttpRequest expected) { + public RequestEquivalent(final T expected) { this.expected = expected; } @Override - public boolean matches(final Object actual) { - if (!(actual instanceof HttpRequest)) { + public boolean matches(final T argument) { + if (argument == null) { return false; } - final HttpRequest other = (HttpRequest) actual; - return HttpTestUtils.equivalent(expected, other); + return HttpTestUtils.equivalent(expected, argument); } - @Override - public void appendTo(final StringBuffer buf) { - buf.append("eqRequest("); - buf.append(expected); - buf.append(")"); + public static T eq(final T request) { + return ArgumentMatchers.argThat(new RequestEquivalent<>(request)); } } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/ResponseEquivalent.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/ResponseEquivalent.java index fb0c3c316..0cdc9fc02 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/ResponseEquivalent.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/ResponseEquivalent.java @@ -27,30 +27,27 @@ package org.apache.hc.client5.http.impl.cache; import org.apache.hc.core5.http.HttpResponse; -import org.easymock.IArgumentMatcher; +import org.mockito.ArgumentMatcher; +import org.mockito.ArgumentMatchers; -public class ResponseEquivalent implements IArgumentMatcher { +public class ResponseEquivalent implements ArgumentMatcher { - private final HttpResponse expected; + private final T expected; - public ResponseEquivalent(final HttpResponse expected) { + public ResponseEquivalent(final T expected) { this.expected = expected; } @Override - public boolean matches(final Object actual) { - if (!(actual instanceof HttpResponse)) { + public boolean matches(final T argument) { + if (argument == null) { return false; } - final HttpResponse other = (HttpResponse) actual; - return HttpTestUtils.equivalent(expected, other); + return HttpTestUtils.equivalent(expected, argument); } - @Override - public void appendTo(final StringBuffer buf) { - buf.append("eqRequest("); - buf.append(expected); - buf.append(")"); + public static T eq(final T response) { + return ArgumentMatchers.argThat(new ResponseEquivalent<>(response)); } } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java deleted file mode 100644 index 8ec3db627..000000000 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExec.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * ==================================================================== - * 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.hc.client5.http.impl.cache; - -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.isA; -import static org.easymock.EasyMock.same; -import static org.easymock.EasyMock.createMockBuilder; -import static org.easymock.EasyMock.createNiceMock; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; -import org.apache.hc.client5.http.cache.HttpCacheEntry; -import org.apache.hc.client5.http.classic.ExecChain; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.utils.DateUtils; -import org.apache.hc.core5.http.ClassicHttpRequest; -import org.apache.hc.core5.http.ClassicHttpResponse; -import org.apache.hc.core5.http.HeaderElements; -import org.apache.hc.core5.http.HttpHeaders; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.HttpVersion; -import org.apache.hc.core5.http.io.entity.InputStreamEntity; -import org.apache.hc.core5.http.message.BasicClassicHttpRequest; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.easymock.EasyMock; -import org.easymock.IExpectationSetters; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -@SuppressWarnings("boxing") // test code -public class TestCachingExec extends TestCachingExecChain { - - private static final String GET_CURRENT_DATE = "getCurrentDate"; - - private static final String HANDLE_BACKEND_RESPONSE = "handleBackendResponse"; - - private static final String CALL_BACKEND = "callBackend"; - - private static final String REVALIDATE_CACHE_ENTRY = "revalidateCacheEntry"; - - private CachingExec impl; - private boolean mockedImpl; - - private ExecChain.Scope scope; - private ClassicHttpResponse mockBackendResponse; - - private Date requestDate; - private Date responseDate; - - @Override - @Before - public void setUp() { - super.setUp(); - - scope = new ExecChain.Scope("test", route, request, mockEndpoint, context); - mockBackendResponse = createNiceMock(ClassicHttpResponse.class); - - requestDate = new Date(System.currentTimeMillis() - 1000); - responseDate = new Date(); - } - - @Override - public CachingExec createCachingExecChain( - final HttpCache mockCache, final CacheValidityPolicy mockValidityPolicy, - final ResponseCachingPolicy mockResponsePolicy, - final CachedHttpResponseGenerator mockResponseGenerator, - final CacheableRequestPolicy mockRequestPolicy, - final CachedResponseSuitabilityChecker mockSuitabilityChecker, - final ResponseProtocolCompliance mockResponseProtocolCompliance, - final RequestProtocolCompliance mockRequestProtocolCompliance, - final DefaultCacheRevalidator mockCacheRevalidator, - final ConditionalRequestBuilder mockConditionalRequestBuilder, - final CacheConfig config) { - return impl = new CachingExec( - mockCache, - mockValidityPolicy, - mockResponsePolicy, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance, - mockCacheRevalidator, - mockConditionalRequestBuilder, - config); - } - - @Override - public CachingExec createCachingExecChain(final HttpCache cache, final CacheConfig config) { - return impl = new CachingExec(cache, null, config); - } - - @Override - protected void replayMocks() { - super.replayMocks(); - replay(mockBackendResponse); - if (mockedImpl) { - replay(impl); - } - } - - @Override - protected void verifyMocks() { - super.verifyMocks(); - verify(mockBackendResponse); - if (mockedImpl) { - verify(impl); - } - } - - - @Test - public void testRequestThatCannotBeServedFromCacheCausesBackendRequest() throws Exception { - cacheInvalidatorWasCalled(); - requestPolicyAllowsCaching(false); - mockImplMethods(CALL_BACKEND); - - implExpectsAnyRequestAndReturn(mockBackendResponse); - requestIsFatallyNonCompliant(null); - - replayMocks(); - final HttpResponse result = impl.execute(request, scope, mockExecChain); - verifyMocks(); - - Assert.assertSame(mockBackendResponse, result); - } - - @Test - public void testCacheMissCausesBackendRequest() throws Exception { - mockImplMethods(CALL_BACKEND); - requestPolicyAllowsCaching(true); - getCacheEntryReturns(null); - getVariantCacheEntriesReturns(new HashMap<>()); - - requestIsFatallyNonCompliant(null); - - implExpectsAnyRequestAndReturn(mockBackendResponse); - - replayMocks(); - final HttpResponse result = impl.execute(request, scope, mockExecChain); - verifyMocks(); - - Assert.assertSame(mockBackendResponse, result); - Assert.assertEquals(1, impl.getCacheMisses()); - Assert.assertEquals(0, impl.getCacheHits()); - Assert.assertEquals(0, impl.getCacheUpdates()); - } - - @Test - public void testUnsuitableUnvalidatableCacheEntryCausesBackendRequest() throws Exception { - mockImplMethods(CALL_BACKEND); - requestPolicyAllowsCaching(true); - requestIsFatallyNonCompliant(null); - - getCacheEntryReturns(mockCacheEntry); - cacheEntrySuitable(false); - cacheEntryValidatable(false); - expect(mockConditionalRequestBuilder.buildConditionalRequest(request, mockCacheEntry)) - .andReturn(request); - backendExpectsRequestAndReturn(request, mockBackendResponse); - expect(mockBackendResponse.getVersion()).andReturn(HttpVersion.HTTP_1_1).anyTimes(); - expect(mockBackendResponse.getCode()).andReturn(200); - - replayMocks(); - final HttpResponse result = impl.execute(request, scope, mockExecChain); - verifyMocks(); - - Assert.assertSame(mockBackendResponse, result); - Assert.assertEquals(0, impl.getCacheMisses()); - Assert.assertEquals(1, impl.getCacheHits()); - Assert.assertEquals(1, impl.getCacheUpdates()); - } - - @Test - public void testUnsuitableValidatableCacheEntryCausesRevalidation() throws Exception { - mockImplMethods(REVALIDATE_CACHE_ENTRY); - requestPolicyAllowsCaching(true); - requestIsFatallyNonCompliant(null); - - getCacheEntryReturns(mockCacheEntry); - cacheEntrySuitable(false); - cacheEntryValidatable(true); - cacheEntryMustRevalidate(false); - cacheEntryProxyRevalidate(false); - mayReturnStaleWhileRevalidating(false); - - expect(impl.revalidateCacheEntry( - isA(HttpHost.class), - isA(ClassicHttpRequest.class), - isA(ExecChain.Scope.class), - isA(ExecChain.class), - isA(HttpCacheEntry.class))).andReturn(mockBackendResponse); - - replayMocks(); - final HttpResponse result = impl.execute(request, scope, mockExecChain); - verifyMocks(); - - Assert.assertSame(mockBackendResponse, result); - Assert.assertEquals(0, impl.getCacheMisses()); - Assert.assertEquals(1, impl.getCacheHits()); - Assert.assertEquals(0, impl.getCacheUpdates()); - } - - @Test - public void testRevalidationCallsHandleBackEndResponseWhenNot200Or304() throws Exception { - mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); - - final ClassicHttpRequest validate = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NOT_FOUND, "Not Found"); - final ClassicHttpResponse finalResponse = HttpTestUtils.make200Response(); - - conditionalRequestBuilderReturns(validate); - getCurrentDateReturns(requestDate); - backendExpectsRequestAndReturn(validate, originResponse); - getCurrentDateReturns(responseDate); - expect(impl.handleBackendResponse( - same(host), - same(validate), - same(scope), - eq(requestDate), - eq(responseDate), - same(originResponse))).andReturn(finalResponse); - - replayMocks(); - final HttpResponse result = - impl.revalidateCacheEntry(host, request, scope, mockExecChain, entry); - verifyMocks(); - - Assert.assertSame(finalResponse, result); - } - - @Test - public void testRevalidationUpdatesCacheEntryAndPutsItToCacheWhen304ReturningCachedResponse() - throws Exception { - - mockImplMethods(GET_CURRENT_DATE); - - final ClassicHttpRequest validate = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse originResponse = HttpTestUtils.make304Response(); - final HttpCacheEntry updatedEntry = HttpTestUtils.makeCacheEntry(); - - conditionalRequestBuilderReturns(validate); - getCurrentDateReturns(requestDate); - backendExpectsRequestAndReturn(validate, originResponse); - getCurrentDateReturns(responseDate); - expect(mockCache.updateCacheEntry( - eq(host), - same(request), - same(entry), - same(originResponse), - eq(requestDate), - eq(responseDate))) - .andReturn(updatedEntry); - expect(mockSuitabilityChecker.isConditional(request)).andReturn(false); - responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK)); - - replayMocks(); - impl.revalidateCacheEntry(host, request, scope, mockExecChain, entry); - verifyMocks(); - } - - @Test - public void testRevalidationRewritesAbsoluteUri() throws Exception { - - mockImplMethods(GET_CURRENT_DATE); - - // Fail on an unexpected request, rather than causing a later NPE - EasyMock.resetToStrict(mockExecChain); - - final ClassicHttpRequest validate = new HttpGet("http://foo.example.com/resource"); - final ClassicHttpRequest relativeValidate = new BasicClassicHttpRequest("GET", "/resource"); - final ClassicHttpResponse originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "Okay"); - - conditionalRequestBuilderReturns(validate); - getCurrentDateReturns(requestDate); - - final ClassicHttpResponse resp = mockExecChain.proceed( - eqRequest(relativeValidate), isA(ExecChain.Scope.class)); - expect(resp).andReturn(originResponse); - - getCurrentDateReturns(responseDate); - - replayMocks(); - impl.revalidateCacheEntry(host, request, scope, mockExecChain, entry); - verifyMocks(); - } - - @Test - public void testEndlessResponsesArePassedThrough() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); - resp1.setHeader("Date", DateUtils.formatDate(new Date())); - resp1.setHeader("Server", "MockOrigin/1.0"); - resp1.setHeader(HttpHeaders.TRANSFER_ENCODING, HeaderElements.CHUNKED_ENCODING); - - final AtomicInteger size = new AtomicInteger(); - final AtomicInteger maxlength = new AtomicInteger(Integer.MAX_VALUE); - resp1.setEntity(new InputStreamEntity(new InputStream() { - private Throwable closed; - - @Override - public void close() throws IOException { - closed = new Throwable(); - super.close(); - } - - @Override - public int read() throws IOException { - Thread.yield(); - if (closed != null) { - throw new IOException("Response has been closed"); - - } - if (size.incrementAndGet() > maxlength.get()) { - return -1; - } - return 'y'; - } - }, -1, null)); - - final ClassicHttpResponse resp = mockExecChain.proceed( - isA(ClassicHttpRequest.class), isA(ExecChain.Scope.class)); - EasyMock.expect(resp).andReturn(resp1); - - final ClassicHttpRequest req1 = HttpTestUtils.makeDefaultRequest(); - - replayMocks(); - final ClassicHttpResponse resp2 = impl.execute(req1, scope, mockExecChain); - maxlength.set(size.get() * 2); - verifyMocks(); - assertTrue(HttpTestUtils.semanticallyTransparent(resp1, resp2)); - } - - @Test - public void testCallBackendMakesBackEndRequestAndHandlesResponse() throws Exception { - mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); - final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); - getCurrentDateReturns(requestDate); - backendExpectsRequestAndReturn(request, resp); - getCurrentDateReturns(responseDate); - handleBackendResponseReturnsResponse(request, resp); - - replayMocks(); - - impl.callBackend(host, request, scope, mockExecChain); - - verifyMocks(); - } - - @Test - public void testDoesNotFlushCachesOnCacheHit() throws Exception { - requestPolicyAllowsCaching(true); - requestIsFatallyNonCompliant(null); - - getCacheEntryReturns(mockCacheEntry); - doesNotFlushCache(); - cacheEntrySuitable(true); - cacheEntryValidatable(true); - - responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK)); - - replayMocks(); - impl.execute(request, scope, mockExecChain); - verifyMocks(); - } - - private IExpectationSetters implExpectsAnyRequestAndReturn( - final ClassicHttpResponse response) throws Exception { - final ClassicHttpResponse resp = impl.callBackend( - same(host), - isA(ClassicHttpRequest.class), - isA(ExecChain.Scope.class), - isA(ExecChain.class)); - return EasyMock.expect(resp).andReturn(response); - } - - private void getVariantCacheEntriesReturns(final Map result) { - expect(mockCache.getVariantCacheEntriesWithEtags(host, request)).andReturn(result); - } - - private void cacheInvalidatorWasCalled() { - mockCache.flushCacheEntriesInvalidatedByRequest((HttpHost)anyObject(), (HttpRequest)anyObject()); - } - - private void getCurrentDateReturns(final Date date) { - expect(impl.getCurrentDate()).andReturn(date); - } - - private void handleBackendResponseReturnsResponse(final ClassicHttpRequest request, final ClassicHttpResponse response) - throws IOException { - expect( - impl.handleBackendResponse( - same(host), - same(request), - same(scope), - isA(Date.class), - isA(Date.class), - isA(ClassicHttpResponse.class))).andReturn(response); - } - - private void mockImplMethods(final String... methods) { - mockedImpl = true; - impl = createMockBuilder(CachingExec.class).withConstructor( - mockCache, - mockValidityPolicy, - mockResponsePolicy, - mockResponseGenerator, - mockRequestPolicy, - mockSuitabilityChecker, - mockResponseProtocolCompliance, - mockRequestProtocolCompliance, - mockCacheRevalidator, - mockConditionalRequestBuilder, - config).addMockedMethods(methods).createNiceMock(); - } - -} diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java index 842d20025..707498960 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestCachingExecChain.java @@ -26,27 +26,13 @@ */ package org.apache.hc.client5.http.impl.cache; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.createNiceMock; -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.replay; -import static org.easymock.EasyMock.same; -import static org.easymock.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 org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; @@ -63,82 +49,49 @@ import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; -import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpVersion; -import org.apache.hc.core5.http.io.HttpClientResponseHandler; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.InputStreamEntity; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.net.URIAuthority; -import org.apache.hc.core5.util.ByteArrayBuffer; -import org.apache.hc.core5.util.TimeValue; -import org.easymock.Capture; -import org.easymock.EasyMock; -import org.easymock.IExpectationSetters; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; -import junit.framework.AssertionFailedError; +@RunWith(MockitoJUnitRunner.class) +public class TestCachingExecChain { -@SuppressWarnings("boxing") // test code -public abstract class TestCachingExecChain { + @Mock + ExecChain mockExecChain; + @Mock + ExecRuntime mockExecRuntime; + @Mock + HttpCacheStorage mockStorage; + @Spy + HttpCache cache = new BasicHttpCache(); - private CachingExec impl; + CacheConfig config; + HttpRoute route; + HttpHost host; + ClassicHttpRequest request; + HttpCacheContext context; + HttpCacheEntry entry; + CachingExec impl; - protected CacheValidityPolicy mockValidityPolicy; - protected CacheableRequestPolicy mockRequestPolicy; - protected ExecChain mockExecChain; - protected ExecRuntime mockEndpoint; - protected HttpCache mockCache; - private HttpCacheStorage mockStorage; - protected CachedResponseSuitabilityChecker mockSuitabilityChecker; - protected ResponseCachingPolicy mockResponsePolicy; - protected HttpCacheEntry mockCacheEntry; - protected CachedHttpResponseGenerator mockResponseGenerator; - private HttpClientResponseHandler mockHandler; - private ClassicHttpRequest mockUriRequest; - private HttpRequest mockConditionalRequest; - protected ResponseProtocolCompliance mockResponseProtocolCompliance; - protected RequestProtocolCompliance mockRequestProtocolCompliance; - protected DefaultCacheRevalidator mockCacheRevalidator; - protected ConditionalRequestBuilder mockConditionalRequestBuilder; - protected CacheConfig config; - - protected HttpRoute route; - protected HttpHost host; - protected ClassicHttpRequest request; - protected HttpCacheContext context; - protected HttpCacheEntry entry; - - @SuppressWarnings("unchecked") @Before public void setUp() { - mockRequestPolicy = createNiceMock(CacheableRequestPolicy.class); - mockValidityPolicy = createNiceMock(CacheValidityPolicy.class); - mockEndpoint = createNiceMock(ExecRuntime.class); - mockExecChain = createNiceMock(ExecChain.class); - mockCache = createNiceMock(HttpCache.class); - mockSuitabilityChecker = createNiceMock(CachedResponseSuitabilityChecker.class); - mockResponsePolicy = createNiceMock(ResponseCachingPolicy.class); - mockHandler = createNiceMock(HttpClientResponseHandler.class); - mockUriRequest = createNiceMock(ClassicHttpRequest.class); - mockCacheEntry = createNiceMock(HttpCacheEntry.class); - mockResponseGenerator = createNiceMock(CachedHttpResponseGenerator.class); - mockConditionalRequest = createNiceMock(HttpRequest.class); - mockResponseProtocolCompliance = createNiceMock(ResponseProtocolCompliance.class); - mockRequestProtocolCompliance = createNiceMock(RequestProtocolCompliance.class); - mockCacheRevalidator = createNiceMock(DefaultCacheRevalidator.class); - mockConditionalRequestBuilder = createNiceMock(ConditionalRequestBuilder.class); - mockStorage = createNiceMock(HttpCacheStorage.class); config = CacheConfig.DEFAULT; host = new HttpHost("foo.example.com", 80); @@ -146,98 +99,35 @@ public abstract class TestCachingExecChain { request = new BasicClassicHttpRequest("GET", "/stuff"); context = HttpCacheContext.create(); entry = HttpTestUtils.makeCacheEntry(); - impl = createCachingExecChain(mockCache, mockValidityPolicy, - mockResponsePolicy, mockResponseGenerator, mockRequestPolicy, mockSuitabilityChecker, - mockResponseProtocolCompliance,mockRequestProtocolCompliance, - mockCacheRevalidator, mockConditionalRequestBuilder, config); + + impl = new CachingExec(cache, null, CacheConfig.DEFAULT); } - public abstract CachingExec createCachingExecChain( - HttpCache responseCache, CacheValidityPolicy validityPolicy, - ResponseCachingPolicy responseCachingPolicy, CachedHttpResponseGenerator responseGenerator, - CacheableRequestPolicy cacheableRequestPolicy, - CachedResponseSuitabilityChecker suitabilityChecker, - ResponseProtocolCompliance responseCompliance, RequestProtocolCompliance requestCompliance, - DefaultCacheRevalidator cacheRevalidator, - ConditionalRequestBuilder conditionalRequestBuilder, - CacheConfig config); - - public abstract CachingExec createCachingExecChain(HttpCache cache, CacheConfig config); - - protected ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { - return impl.execute( - ClassicRequestBuilder.copy(request).build(), - new ExecChain.Scope("test", route, request, mockEndpoint, context), - mockExecChain); - } - - public static ClassicHttpRequest eqRequest(final ClassicHttpRequest 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(mockExecChain); - replay(mockCache); - replay(mockHandler); - replay(mockUriRequest); - replay(mockConditionalRequestBuilder); - replay(mockConditionalRequest); - replay(mockResponseProtocolCompliance); - replay(mockRequestProtocolCompliance); - replay(mockStorage); - } - - protected void verifyMocks() { - verify(mockRequestPolicy); - verify(mockValidityPolicy); - verify(mockSuitabilityChecker); - verify(mockResponsePolicy); - verify(mockCacheEntry); - verify(mockResponseGenerator); - verify(mockExecChain); - verify(mockCache); - verify(mockHandler); - verify(mockUriRequest); - verify(mockConditionalRequestBuilder); - verify(mockConditionalRequest); - verify(mockResponseProtocolCompliance); - verify(mockRequestProtocolCompliance); - verify(mockStorage); + public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { + final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, mockExecRuntime, context); + return impl.execute(ClassicRequestBuilder.copy(request).build(), scope, mockExecChain); } @Test public void testCacheableResponsesGoIntoCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final ClassicHttpRequest req1 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control", "max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); execute(req2); - verifyMocks(); + + Mockito.verify(mockExecChain).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(cache).createCacheEntry(Mockito.eq(host), RequestEquivalent.eq(req1), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); } @Test public void testOlderCacheableResponsesDoNotGoIntoCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); @@ -247,8 +137,6 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Etag", "\"new-etag\""); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "no-cache"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); @@ -256,22 +144,22 @@ public abstract class TestCachingExecChain { resp2.setHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); resp2.setHeader("Cache-Control", "max-age=3600"); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = HttpTestUtils.makeDefaultRequest(); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); final ClassicHttpResponse result = execute(req3); - verifyMocks(); - assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); + Assert.assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); } @Test public void testNewerCacheableResponsesReplaceExistingCacheEntry() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); @@ -281,8 +169,6 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Etag", "\"old-etag\""); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "max-age=0"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); @@ -290,119 +176,74 @@ public abstract class TestCachingExecChain { resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Cache-Control", "max-age=3600"); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = HttpTestUtils.makeDefaultRequest(); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); final ClassicHttpResponse result = execute(req3); - 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 { - requestPolicyAllowsCaching(true); - getCacheEntryReturns(mockCacheEntry); - cacheEntrySuitable(true); - responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK)); - requestIsFatallyNonCompliant(null); - entryHasStaleness(TimeValue.ZERO_MILLISECONDS); - - replayMocks(); - final ClassicHttpResponse result = execute(request); - verifyMocks(); + Assert.assertEquals("\"new-etag\"", result.getFirstHeader("ETag").getValue()); } @Test public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception { - final CacheConfig configDefault = CacheConfig.DEFAULT; - impl = createCachingExecChain(new BasicHttpCache(new HeapResourceFactory(), - mockStorage), configDefault); + final HttpCache cache = new BasicHttpCache(new HeapResourceFactory(), mockStorage); + impl = new CachingExec(cache, null, CacheConfig.DEFAULT); final ClassicHttpRequest req1 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse 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); + Mockito.when(mockStorage.getEntry(Mockito.any())).thenReturn(null); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); final ClassicHttpResponse result = execute(req1); - verifyMocks(); - assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); - } + Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); - @Test - public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception { - - requestIsFatallyNonCompliant(null); - requestPolicyAllowsCaching(true); - cacheEntrySuitable(true); - getCacheEntryReturns(mockCacheEntry); - responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK)); - entryHasStaleness(TimeValue.ZERO_MILLISECONDS); - - replayMocks(); - execute(request); - verifyMocks(); + Mockito.verify(mockStorage, Mockito.never()).putEntry(Mockito.any(), Mockito.any()); } @Test public void testSetsModuleGeneratedResponseContextForCacheOptionsResponse() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req = new BasicClassicHttpRequest("OPTIONS", "*"); req.setHeader("Max-Forwards", "0"); execute(req); - Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, - context.getCacheResponseStatus()); + Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, context.getCacheResponseStatus()); } @Test public void testSetsModuleGeneratedResponseContextForFatallyNoncompliantRequest() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req = new HttpGet("http://foo.example.com/"); req.setHeader("Range", "bytes=0-50"); req.setHeader("If-Range", "W/\"weak-etag\""); execute(req); - Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, - context.getCacheResponseStatus()); + Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, context.getCacheResponseStatus()); } @Test public void testRecordsClientProtocolInViaHeaderIfRequestNotServableFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest originalRequest = new BasicClassicHttpRequest("GET", "/"); originalRequest.setVersion(HttpVersion.HTTP_1_0); final ClassicHttpRequest req = originalRequest; req.setHeader("Cache-Control", "no-cache"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - final Capture cap = EasyMock.newCapture(); - backendCaptureRequestAndReturn(cap, resp); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp); - replayMocks(); execute(req); - verifyMocks(); - final HttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final HttpRequest captured = reqCapture.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)); @@ -410,95 +251,77 @@ public abstract class TestCachingExecChain { @Test public void testSetsCacheMissContextIfRequestNotServableFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req = new HttpGet("http://foo.example.com/"); req.setHeader("Cache-Control", "no-cache"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequestAndReturn(resp); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp); - replayMocks(); execute(req); - verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_MISS, context.getCacheResponseStatus()); } @Test public void testSetsViaHeaderOnResponseIfRequestNotServableFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req = new HttpGet("http://foo.example.com/"); req.setHeader("Cache-Control", "no-cache"); final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequestAndReturn(resp); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp); - replayMocks(); final ClassicHttpResponse result = execute(req); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @Test public void testSetsViaHeaderOnResponseForCacheMiss() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); final ClassicHttpResponse result = execute(req1); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @Test public void testSetsCacheHitContextIfRequestServedFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_HIT, context.getCacheResponseStatus()); } @Test public void testSetsViaHeaderOnResponseIfRequestServedFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -506,12 +329,10 @@ public abstract class TestCachingExecChain { public void testReturns304ForIfModifiedSinceHeaderIfRequestServedFromCache() throws Exception { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -519,14 +340,11 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "public, max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); - } @Test @@ -534,7 +352,6 @@ public abstract class TestCachingExecChain { 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(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); req1.addHeader("If-Modified-Since", DateUtils.formatDate(oneHourAgo)); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); @@ -545,31 +362,25 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-control", "max-age=600"); resp1.setHeader("Expires", DateUtils.formatDate(inTenMinutes)); - expect( - mockExecChain.proceed(isA(ClassicHttpRequest.class), isA(ExecChain.Scope.class))).andReturn(resp1).once(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - expect( - mockExecChain.proceed(isA(ClassicHttpRequest.class), isA(ExecChain.Scope.class))).andThrow( - new AssertionFailedError("Should have reused cached 304 response")).anyTimes(); - - replayMocks(); execute(req1); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); Assert.assertFalse(result.containsHeader("Last-Modified")); + + Mockito.verify(mockExecChain).proceed(Mockito.any(), Mockito.any()); } @Test public void testReturns200ForIfModifiedSinceDateIsLess() throws Exception { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -582,27 +393,24 @@ public abstract class TestCachingExecChain { final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - final ClassicHttpResponse result = execute(req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + final ClassicHttpResponse result = execute(req2); + Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); } @Test public void testReturns200ForIfModifiedSinceDateIsInvalid() throws Exception { final Date now = new Date(); final Date tenSecondsAfter = new Date(now.getTime() + 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -613,48 +421,41 @@ public abstract class TestCachingExecChain { // invalid date (date in the future) req2.addHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAfter)); - backendExpectsAnyRequestAndReturn(resp1).times(2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } @Test public void testReturns304ForIfNoneMatchHeaderIfRequestServedFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); req2.addHeader("If-None-Match", "*"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); } @Test public void testReturns200ForIfNoneMatchHeaderFails() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -665,27 +466,24 @@ public abstract class TestCachingExecChain { final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - final ClassicHttpResponse result = execute(req2); - verifyMocks(); - Assert.assertEquals(200, result.getCode()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + final ClassicHttpResponse result = execute(req2); + Assert.assertEquals(200, result.getCode()); } @Test public void testReturns304ForIfNoneMatchHeaderAndIfModifiedSinceIfRequestServedFromCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -696,27 +494,22 @@ public abstract class TestCachingExecChain { req2.addHeader("If-None-Match", "*"); req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); - } @Test public void testReturns200ForIfNoneMatchHeaderFailsIfModifiedSinceIgnored() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); req2.addHeader("If-None-Match", "\"abc\""); req2.addHeader("If-Modified-Since", DateUtils.formatDate(now)); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -724,21 +517,16 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "public, max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(200, result.getCode()); - } @Test public void testReturns200ForOptionsFollowedByGetIfAuthorizationHeaderAndSharedCache() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.custom() - .setSharedCache(true).build()); + impl = new CachingExec(cache, null, CacheConfig.custom().setSharedCache(true).build()); final Date now = new Date(); final ClassicHttpRequest req1 = new HttpOptions("http://foo.example.com/"); req1.setHeader("Authorization", StandardAuthScheme.BASIC + " QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); @@ -750,8 +538,7 @@ public abstract class TestCachingExecChain { resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "public, max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(now)); - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"get-etag\""); @@ -759,13 +546,12 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "public, max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(200, result.getCode()); } @@ -774,33 +560,29 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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 ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(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(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); - verifyMocks(); Assert.assertEquals(CacheResponseStatus.VALIDATED, context.getCacheResponseStatus()); } @@ -809,33 +591,30 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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 ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(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); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -844,25 +623,23 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new IOException()); + execute(req2); - verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_MODULE_RESPONSE, context.getCacheResponseStatus()); } @@ -872,25 +649,23 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new IOException()); + execute(req2); - verifyMocks(); Assert.assertEquals(CacheResponseStatus.CACHE_HIT, context.getCacheResponseStatus()); } @@ -899,25 +674,23 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(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()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new IOException()); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Via")); } @@ -927,12 +700,10 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -945,12 +716,12 @@ public abstract class TestCachingExecChain { resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Cache-Control", "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); } @@ -961,12 +732,10 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -974,37 +743,32 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "public, max-age=5"); req2.addHeader("If-None-Match", "\"etag\""); - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(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(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); } @Test public void testReturns304ForIfModifiedSincePassesIfRequestServedFromOrigin() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -1019,28 +783,26 @@ public abstract class TestCachingExecChain { resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); resp2.setHeader("Cache-Control", "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); } @Test public void testReturns200ForIfModifiedSinceFailsIfRequestServedFromOrigin() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); final ClassicHttpRequest req2 = new HttpGet("http://foo.example.com/"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("ETag", "\"etag\""); @@ -1049,8 +811,7 @@ public abstract class TestCachingExecChain { resp1.setHeader("Cache-Control", "public, max-age=5"); req2.addHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp2.setEntity(HttpTestUtils.makeBody(128)); resp2.setHeader("Content-Length", "128"); resp2.setHeader("ETag", "\"newetag\""); @@ -1058,27 +819,25 @@ public abstract class TestCachingExecChain { resp1.setHeader("Last-Modified", DateUtils.formatDate(now)); resp2.setHeader("Cache-Control", "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); } @Test public void testVariantMissServerIfReturns304CacheReturns200() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com"); req1.addHeader("Accept-Encoding", "gzip"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("Etag", "\"gzip_etag\""); @@ -1093,8 +852,7 @@ public abstract class TestCachingExecChain { req2Server.addHeader("Accept-Encoding", "deflate"); req2Server.addHeader("If-None-Match", "\"gzip_etag\""); - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp2.setEntity(HttpTestUtils.makeBody(128)); resp2.setHeader("Content-Length", "128"); resp2.setHeader("Etag", "\"deflate_etag\""); @@ -1109,8 +867,7 @@ public abstract class TestCachingExecChain { req3Server.addHeader("Accept-Encoding", "gzip,deflate"); req3Server.addHeader("If-None-Match", "\"gzip_etag\",\"deflate_etag\""); - final ClassicHttpResponse resp3 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp3 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Content-Length", "128"); resp3.setHeader("Etag", "\"gzip_etag\""); @@ -1118,18 +875,18 @@ public abstract class TestCachingExecChain { resp3.setHeader("Vary", "Accept-Encoding"); resp3.setHeader("Cache-Control", "public, max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); final ClassicHttpResponse result1 = execute(req1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result2 = execute(req2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); + final ClassicHttpResponse result3 = execute(req3); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result1.getCode()); Assert.assertEquals(HttpStatus.SC_OK, result2.getCode()); Assert.assertEquals(HttpStatus.SC_OK, result3.getCode()); @@ -1137,14 +894,12 @@ public abstract class TestCachingExecChain { @Test public void testVariantsMissServerReturns304CacheReturns304() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com"); req1.addHeader("Accept-Encoding", "gzip"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(HttpTestUtils.makeBody(128)); resp1.setHeader("Content-Length", "128"); resp1.setHeader("Etag", "\"gzip_etag\""); @@ -1159,8 +914,7 @@ public abstract class TestCachingExecChain { req2Server.addHeader("Accept-Encoding", "deflate"); req2Server.addHeader("If-None-Match", "\"gzip_etag\""); - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp2.setEntity(HttpTestUtils.makeBody(128)); resp2.setHeader("Content-Length", "128"); resp2.setHeader("Etag", "\"deflate_etag\""); @@ -1182,17 +936,17 @@ public abstract class TestCachingExecChain { resp4.setHeader("Vary", "Accept-Encoding"); resp4.setHeader("Cache-Control", "public, max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - backendExpectsAnyRequestAndReturn(resp4); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); final ClassicHttpResponse result1 = execute(req1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result2 = execute(req2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp4); + final ClassicHttpResponse result4 = execute(req4); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_OK, result1.getCode()); Assert.assertEquals(HttpStatus.SC_OK, result2.getCode()); Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result4.getCode()); @@ -1201,13 +955,11 @@ public abstract class TestCachingExecChain { @Test public void testSocketTimeoutExceptionIsNotSilentlyCatched() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final Date now = new Date(); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com"); - final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, - "OK"); + final ClassicHttpResponse resp1 = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK"); resp1.setEntity(new InputStreamEntity(new InputStream() { private boolean closed; @@ -1226,17 +978,12 @@ public abstract class TestCachingExecChain { }, 128, null)); resp1.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); - try { + Assert.assertThrows(SocketTimeoutException.class, () -> { final ClassicHttpResponse result1 = execute(req1); EntityUtils.toString(result1.getEntity()); - Assert.fail("We should have had a SocketTimeoutException"); - } catch (final SocketTimeoutException e) { - } - verifyMocks(); - + }); } @Test @@ -1246,12 +993,6 @@ public abstract class TestCachingExecChain { @Test public void testTooLargeResponsesAreNotCached() throws Exception { - mockCache = EasyMock.createStrictMock(HttpCache.class); - impl = createCachingExecChain(mockCache, mockValidityPolicy, - mockResponsePolicy, mockResponseGenerator, mockRequestPolicy, mockSuitabilityChecker, - mockResponseProtocolCompliance, mockRequestProtocolCompliance, - mockCacheRevalidator, mockConditionalRequestBuilder, config); - final HttpHost host = new HttpHost("foo.example.com"); final ClassicHttpRequest request = new HttpGet("http://foo.example.com/bar"); @@ -1266,15 +1007,18 @@ public abstract class TestCachingExecChain { originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated)); originResponse.setHeader("ETag", "\"etag\""); - replayMocks(); - final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, mockEndpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, mockExecRuntime, context); impl.cacheAndReturnResponse(host, request, originResponse, scope, requestSent, responseReceived); - verifyMocks(); + Mockito.verify(cache, Mockito.never()).createCacheEntry( + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); } @Test public void testSmallEnoughResponsesAreCached() throws Exception { + final HttpCache mockCache = Mockito.mock(HttpCache.class); + impl = new CachingExec(mockCache, null, CacheConfig.DEFAULT); + final HttpHost host = new HttpHost("foo.example.com"); final ClassicHttpRequest request = new HttpGet("http://foo.example.com/bar"); @@ -1292,28 +1036,28 @@ public abstract class TestCachingExecChain { final HttpCacheEntry httpCacheEntry = HttpTestUtils.makeCacheEntry(); final SimpleHttpResponse response = SimpleHttpResponse.create(HttpStatus.SC_OK); - EasyMock.expect(mockCache.createCacheEntry( - eq(host), - same(request), - same(originResponse), - isA(ByteArrayBuffer.class), - eq(requestSent), - eq(responseReceived))).andReturn(httpCacheEntry).once(); - EasyMock.expect(mockResponseGenerator.generateResponse( - same(request), - same(httpCacheEntry))).andReturn(response).once(); - replayMocks(); + Mockito.when(mockCache.createCacheEntry( + Mockito.eq(host), + RequestEquivalent.eq(request), + ResponseEquivalent.eq(response), + Mockito.any(), + Mockito.eq(requestSent), + Mockito.eq(responseReceived))).thenReturn(httpCacheEntry); - final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, mockEndpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, mockExecRuntime, context); impl.cacheAndReturnResponse(host, request, originResponse, scope, requestSent, responseReceived); - verifyMocks(); + Mockito.verify(mockCache).createCacheEntry( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any()); } @Test public void testIfOnlyIfCachedAndNoCacheEntryBackendNotCalled() throws Exception { - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - request.addHeader("Cache-Control", "only-if-cached"); final ClassicHttpResponse resp = execute(request); @@ -1321,90 +1065,27 @@ public abstract class TestCachingExecChain { Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getCode()); } - @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); - requestPolicyAllowsCaching(true); - getCacheEntryReturns(entry); - cacheEntrySuitable(false); - - replayMocks(); - final ClassicHttpResponse resp = execute(request); - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, resp.getCode()); - } - - @Test - public void testIfOnlyIfCachedAndEntryExistsAndIsSuitableReturnsEntry() throws Exception { - - request.setHeader("Cache-Control", "only-if-cached"); - - requestIsFatallyNonCompliant(null); - requestPolicyAllowsCaching(true); - getCacheEntryReturns(entry); - cacheEntrySuitable(true); - responseIsGeneratedFromCache(SimpleHttpResponse.create(HttpStatus.SC_OK)); - entryHasStaleness(TimeValue.ZERO_MILLISECONDS); - - replayMocks(); - final ClassicHttpResponse resp = execute(request); - verifyMocks(); - } - - @Test - public void testDoesNotSetConnectionInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final ClassicHttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, ctx), backend); - } - - @Test - public void testSetsTargetHostInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); - final ClassicHttpResponse response = HttpTestUtils.make200Response(); - response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, ctx), backend); - } - @Test public void testSetsRouteInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); final ClassicHttpResponse response = HttpTestUtils.make200Response(); response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(response); + final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, ctx), backend); - assertEquals(route, ctx.getHttpRoute()); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, ctx), mockExecChain); + Assert.assertEquals(route, ctx.getHttpRoute()); } @Test public void testSetsRequestInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); final ClassicHttpResponse response = HttpTestUtils.make200Response(); response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(response); + final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, ctx), backend); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, ctx), mockExecChain); if (!HttpTestUtils.equivalent(request, ctx.getRequest())) { assertSame(request, ctx.getRequest()); } @@ -1412,14 +1093,13 @@ public abstract class TestCachingExecChain { @Test public void testSetsResponseInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); final ClassicHttpResponse response = HttpTestUtils.make200Response(); response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(response); + final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - final ClassicHttpResponse result = impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, ctx), null); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + final ClassicHttpResponse result = impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, ctx), null); if (!HttpTestUtils.equivalent(result, ctx.getResponse())) { assertSame(result, ctx.getResponse()); } @@ -1427,14 +1107,13 @@ public abstract class TestCachingExecChain { @Test public void testSetsRequestSentInContextOnCacheHit() throws Exception { - final DummyBackend backend = new DummyBackend(); final ClassicHttpResponse response = HttpTestUtils.make200Response(); response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(response); + final HttpClientContext ctx = HttpClientContext.create(); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, ctx), backend); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, ctx), mockExecChain); } @Test @@ -1442,12 +1121,12 @@ public abstract class TestCachingExecChain { final ClassicHttpResponse response = new BasicClassicHttpResponse(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(new BasicHttpCache(), CacheConfig.DEFAULT); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - assertEquals(1, backend.getExecutions()); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(response); + + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + + Mockito.verify(mockExecChain).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1456,7 +1135,6 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); req1.addHeader("If-None-Match", "\"etag\""); @@ -1466,13 +1144,11 @@ public abstract class TestCachingExecChain { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control", "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpResponse result = execute(req1); - verifyMocks(); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); - assertNull("The 304 response messages MUST NOT contain a message-body", result.getEntity()); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); + Assert.assertNull("The 304 response messages MUST NOT contain a message-body", result.getEntity()); } @Test @@ -1480,8 +1156,6 @@ public abstract class TestCachingExecChain { final Date now = new Date(); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); req1.addHeader("If-None-Match", "etag"); @@ -1498,17 +1172,17 @@ public abstract class TestCachingExecChain { resp2.setHeader("Cache-Control", "max-age=0"); resp1.setHeader("Etag", "etag"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - replayMocks(); - final ClassicHttpResponse result1 = execute(req1); - final ClassicHttpResponse result2 = execute(req2); - verifyMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getCode()); - assertEquals("etag", result1.getFirstHeader("Etag").getValue()); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getCode()); - assertEquals("etag", result2.getFirstHeader("Etag").getValue()); + final ClassicHttpResponse result1 = execute(req1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + final ClassicHttpResponse result2 = execute(req2); + + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getCode()); + Assert.assertEquals("etag", result1.getFirstHeader("Etag").getValue()); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getCode()); + Assert.assertEquals("etag", result2.getFirstHeader("Etag").getValue()); } @Test @@ -1516,8 +1190,6 @@ public abstract class TestCachingExecChain { final Date now = new Date(); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); req1.addHeader("If-None-Match", "etag"); @@ -1536,17 +1208,18 @@ public abstract class TestCachingExecChain { resp1.setHeader("Etag", "etag"); resp1.setHeader("Vary", "Accept-Encoding"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - replayMocks(); - final ClassicHttpResponse result1 = execute(req1); - final ClassicHttpResponse result2 = execute(req2); - verifyMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getCode()); - assertEquals("etag", result1.getFirstHeader("Etag").getValue()); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getCode()); - assertEquals("etag", result2.getFirstHeader("Etag").getValue()); + final ClassicHttpResponse result1 = execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + final ClassicHttpResponse result2 = execute(req2); + + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getCode()); + Assert.assertEquals("etag", result1.getFirstHeader("Etag").getValue()); + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result2.getCode()); + Assert.assertEquals("etag", result2.getFirstHeader("Etag").getValue()); } @Test @@ -1555,8 +1228,6 @@ public abstract class TestCachingExecChain { final Date now = new Date(); final Date inOneMinute = new Date(System.currentTimeMillis() + 60000); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - final ClassicHttpRequest req1 = new HttpGet("http://foo.example.com/"); req1.addHeader("If-None-Match", "etag"); @@ -1578,122 +1249,38 @@ public abstract class TestCachingExecChain { resp2.setHeader("Vary", "Accept-Encoding"); resp2.setEntity(HttpTestUtils.makeBody(128)); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2).anyTimes(); - replayMocks(); - final ClassicHttpResponse result1 = execute(req1); - final ClassicHttpResponse result2 = execute(req2); - verifyMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getCode()); - assertNull(result1.getEntity()); - assertEquals(HttpStatus.SC_OK, result2.getCode()); + final ClassicHttpResponse result1 = execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + final ClassicHttpResponse result2 = execute(req2); + + Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, result1.getCode()); + Assert.assertNull(result1.getEntity()); + Assert.assertEquals(HttpStatus.SC_OK, result2.getCode()); Assert.assertNotNull(result2.getEntity()); } @Test public void testUsesVirtualHostForCacheKey() throws Exception { - final DummyBackend backend = new DummyBackend(); final ClassicHttpResponse response = HttpTestUtils.make200Response(); response.setHeader("Cache-Control", "max-age=3600"); - backend.setResponse(response); - impl = createCachingExecChain(new BasicHttpCache(), CacheConfig.DEFAULT); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - assertEquals(1, backend.getExecutions()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(response); + + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); + + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); + request.setAuthority(new URIAuthority("bar.example.com")); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - assertEquals(2, backend.getExecutions()); - impl.execute(request, new ExecChain.Scope("test", route, request, mockEndpoint, context), backend); - assertEquals(2, backend.getExecutions()); - } + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); - protected IExpectationSetters backendExpectsRequestAndReturn( - final ClassicHttpRequest request, final ClassicHttpResponse response) throws Exception { - final ClassicHttpResponse resp = mockExecChain.proceed( - EasyMock.eq(request), EasyMock.isA(ExecChain.Scope.class)); - return EasyMock.expect(resp).andReturn(response); - } + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); - private IExpectationSetters backendExpectsAnyRequestAndReturn( - final ClassicHttpResponse response) throws Exception { - final ClassicHttpResponse resp = mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), EasyMock.isA(ExecChain.Scope.class)); - return EasyMock.expect(resp).andReturn(response); - } + impl.execute(request, new ExecChain.Scope("test", route, request, mockExecRuntime, context), mockExecChain); - protected IExpectationSetters backendExpectsAnyRequestAndThrows( - final Throwable throwable) throws Exception { - final ClassicHttpResponse resp = mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), EasyMock.isA(ExecChain.Scope.class)); - return EasyMock.expect(resp).andThrow(throwable); - } - - protected IExpectationSetters backendCaptureRequestAndReturn( - final Capture cap, final ClassicHttpResponse response) throws Exception { - final ClassicHttpResponse resp = mockExecChain.proceed( - EasyMock.capture(cap), EasyMock.isA(ExecChain.Scope.class)); - return EasyMock.expect(resp).andReturn(response); - } - - protected void getCacheEntryReturns(final HttpCacheEntry result) throws IOException { - expect(mockCache.getCacheEntry(eq(host), eqRequest(request))).andReturn(result); - } - - private void cacheInvalidatorWasCalled() throws IOException { - mockCache.flushCacheEntriesInvalidatedByRequest((HttpHost) anyObject(), (HttpRequest) anyObject()); - } - - protected void cacheEntryValidatable(final boolean b) { - expect(mockValidityPolicy.isRevalidatable((HttpCacheEntry) anyObject())).andReturn(b) - .anyTimes(); - } - - 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 ClassicHttpRequest 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 TimeValue staleness) { - expect( - mockValidityPolicy.getStaleness((HttpCacheEntry) anyObject(), (Date) anyObject())) - .andReturn(staleness); - } - - protected void responseIsGeneratedFromCache(final SimpleHttpResponse cachedResponse) throws IOException { - expect( - mockResponseGenerator.generateResponse( - (ClassicHttpRequest) anyObject(), - (HttpCacheEntry) anyObject())).andReturn(cachedResponse); - } - - protected void doesNotFlushCache() throws IOException { - mockCache.flushCacheEntriesInvalidatedByRequest(isA(HttpHost.class), isA(HttpRequest.class)); - EasyMock.expectLastCall().andThrow(new AssertionError("flushCacheEntriesInvalidByResponse should not have been called")).anyTimes(); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolAllowedBehavior.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolAllowedBehavior.java index e2859652e..a4146f897 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolAllowedBehavior.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolAllowedBehavior.java @@ -26,26 +26,90 @@ */ package org.apache.hc.client5.http.impl.cache; +import java.io.IOException; import java.net.SocketTimeoutException; import java.util.Date; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.classic.ExecChain; +import org.apache.hc.client5.http.classic.ExecRuntime; +import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /** * This class tests behavior that is allowed (MAY) by the HTTP/1.1 protocol * specification and for which we have implemented the behavior in HTTP cache. */ -public class TestProtocolAllowedBehavior extends AbstractProtocolTest { +@RunWith(MockitoJUnitRunner.class) +public class TestProtocolAllowedBehavior { + + static final int MAX_BYTES = 1024; + static final int MAX_ENTRIES = 100; + static final int ENTITY_LENGTH = 128; + + HttpHost host; + HttpRoute route; + HttpClientContext context; + @Mock + ExecChain mockExecChain; + @Mock + ExecRuntime mockExecRuntime; + @Mock + HttpCache mockCache; + ClassicHttpRequest request; + ClassicHttpResponse originResponse; + CacheConfig config; + CachingExec impl; + HttpCache cache; + + @Before + public void setUp() throws Exception { + host = new HttpHost("foo.example.com", 80); + + route = new HttpRoute(host); + + request = new BasicClassicHttpRequest("GET", "/foo"); + + context = HttpClientContext.create(); + + originResponse = HttpTestUtils.make200Response(); + + config = CacheConfig.custom() + .setMaxCacheEntries(MAX_ENTRIES) + .setMaxObjectSize(MAX_BYTES) + .setSharedCache(false) + .build(); + + cache = new BasicHttpCache(config); + impl = new CachingExec(cache, null, config); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + } + + public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { + return impl.execute( + ClassicRequestBuilder.copy(request).build(), + new ExecChain.Scope("test", route, request, mockExecRuntime, context), + mockExecChain); + } @Test - public void testNonSharedCacheReturnsStaleResponseWhenRevalidationFailsForProxyRevalidate() - throws Exception { + public void testNonSharedCacheReturnsStaleResponseWhenRevalidationFailsForProxyRevalidate() throws Exception { final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET","/"); final Date now = new Date(); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); @@ -53,37 +117,33 @@ public class TestProtocolAllowedBehavior extends AbstractProtocolTest { originResponse.setHeader("Cache-Control","max-age=5,proxy-revalidate"); originResponse.setHeader("Etag","\"etag\""); - backendExpectsAnyRequest().andReturn(originResponse); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET","/"); - backendExpectsAnyRequest().andThrow(new SocketTimeoutException()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); - behaveAsNonSharedCache(); execute(req1); - final HttpResponse result = execute(req2); - verifyMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new SocketTimeoutException()); + + final HttpResponse result = execute(req2); Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); + + Mockito.verifyNoInteractions(mockCache); } @Test - public void testNonSharedCacheMayCacheResponsesWithCacheControlPrivate() - throws Exception { + public void testNonSharedCacheMayCacheResponsesWithCacheControlPrivate() throws Exception { final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET","/"); originResponse.setHeader("Cache-Control","private,max-age=3600"); - backendExpectsAnyRequest().andReturn(originResponse); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET","/"); - replayMocks(); - behaveAsNonSharedCache(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + execute(req1); final HttpResponse result = execute(req2); - verifyMocks(); - Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); + + Mockito.verifyNoInteractions(mockCache); } } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolDeviations.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolDeviations.java index 0d16bc4a7..6b89f1434 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolDeviations.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolDeviations.java @@ -42,18 +42,18 @@ import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.easymock.Capture; -import org.easymock.EasyMock; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /** * We are a conditionally-compliant HTTP/1.1 client with a cache. However, a lot @@ -70,22 +70,27 @@ import org.junit.Test; * document the places where we differ from the HTTP RFC. */ @SuppressWarnings("boxing") // test code +@RunWith(MockitoJUnitRunner.class) public class TestProtocolDeviations { private static final int MAX_BYTES = 1024; private static final int MAX_ENTRIES = 100; - private HttpHost host; - private HttpRoute route; - private HttpEntity mockEntity; - private ExecRuntime mockEndpoint; - private ExecChain mockExecChain; - private HttpCache mockCache; - private ClassicHttpRequest request; - private HttpCacheContext context; - private ClassicHttpResponse originResponse; + HttpHost host; + HttpRoute route; + @Mock + HttpEntity mockEntity; + @Mock + ExecRuntime mockEndpoint; + @Mock + ExecChain mockExecChain; + @Mock + HttpCache mockCache; + ClassicHttpRequest request; + HttpCacheContext context; + ClassicHttpResponse originResponse; - private ExecChainHandler impl; + ExecChainHandler impl; @Before public void setUp() { @@ -105,11 +110,6 @@ public class TestProtocolDeviations { .build(); final HttpCache cache = new BasicHttpCache(config); - mockEndpoint = EasyMock.createNiceMock(ExecRuntime.class); - mockExecChain = EasyMock.createNiceMock(ExecChain.class); - mockEntity = EasyMock.createNiceMock(HttpEntity.class); - mockCache = EasyMock.createNiceMock(HttpCache.class); - impl = createCachingExecChain(cache, config); } @@ -131,122 +131,12 @@ public class TestProtocolDeviations { return out; } - private void replayMocks() { - EasyMock.replay(mockExecChain); - EasyMock.replay(mockCache); - EasyMock.replay(mockEntity); - } - - private void verifyMocks() { - EasyMock.verify(mockExecChain); - EasyMock.verify(mockCache); - EasyMock.verify(mockEntity); - } - private HttpEntity makeBody(final int nbytes) { final byte[] bytes = new byte[nbytes]; new Random().nextBytes(bytes); return new ByteArrayEntity(bytes, null); } - public static HttpRequest eqRequest(final HttpRequest in) { - org.easymock.EasyMock.reportMatcher(new RequestEquivalent(in)); - return null; - } - - /* - * "For compatibility with HTTP/1.0 applications, HTTP/1.1 requests - * containing a message-body MUST include a valid Content-Length header - * field unless the server is known to be HTTP/1.1 compliant. If a request - * contains a message-body and a Content-Length is not given, the server - * SHOULD respond with 400 (bad request) if it cannot determine the length - * of the message, or with 411 (length required) if it wishes to insist on - * receiving a valid Content-Length." - * - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 - * - * 8/23/2010 JRC - This test has been moved to Ignore. The caching client - * was set to return status code 411 on a missing content-length header when - * a request had a body. It seems that somewhere deeper in the client stack - * this header is added automatically for us - so the caching client shouldn't - * specifically be worried about this requirement. - */ - @Ignore - public void testHTTP1_1RequestsWithBodiesOfKnownLengthMustHaveContentLength() throws Exception { - final ClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/"); - post.setEntity(mockEntity); - - replayMocks(); - - final HttpResponse response = execute(post); - - verifyMocks(); - - Assert.assertEquals(HttpStatus.SC_LENGTH_REQUIRED, response.getCode()); - } - - /* - * Discussion: if an incoming request has a body, but the HttpEntity - * attached has an unknown length (meaning entity.getContentLength() is - * negative), we have two choices if we want to be conditionally compliant. - * (1) we can slurp the whole body into a bytearray and compute its length - * before sending; or (2) we can push responsibility for (1) back onto the - * client by just generating a 411 response - * - * There is a third option, which is that we delegate responsibility for (1) - * onto the backend HttpClient, but because that is an injected dependency, - * we can't rely on it necessarily being conditionally compliant with - * HTTP/1.1. Currently, option (2) seems like the safest bet, as this - * exposes to the client application that the slurping required for (1) - * needs to happen in order to compute the content length. - * - * In any event, this test just captures the behavior required. - * - * 8/23/2010 JRC - This test has been moved to Ignore. The caching client - * was set to return status code 411 on a missing content-length header when - * a request had a body. It seems that somewhere deeper in the client stack - * this header is added automatically for us - so the caching client shouldn't - * specifically be worried about this requirement. - */ - @Ignore - public void testHTTP1_1RequestsWithUnknownBodyLengthAreRejectedOrHaveContentLengthAdded() - throws Exception { - final ClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/"); - - final byte[] bytes = new byte[128]; - new Random().nextBytes(bytes); - - final HttpEntity mockBody = EasyMock.createMockBuilder(ByteArrayEntity.class).withConstructor( - new Object[] { bytes }).addMockedMethods("getContentLength").createNiceMock(); - org.easymock.EasyMock.expect(mockBody.getContentLength()).andReturn(-1L).anyTimes(); - post.setEntity(mockBody); - - final Capture reqCap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(reqCap), - EasyMock.isA(ExecChain.Scope.class))).andReturn( - originResponse).times(0, 1); - - replayMocks(); - EasyMock.replay(mockBody); - - final HttpResponse result = execute(post); - - verifyMocks(); - EasyMock.verify(mockBody); - - if (reqCap.hasCaptured()) { - // backend request was made - final HttpRequest forwarded = reqCap.getValue(); - Assert.assertNotNull(forwarded.getFirstHeader("Content-Length")); - } else { - final int status = result.getCode(); - Assert.assertTrue(HttpStatus.SC_LENGTH_REQUIRED == status - || HttpStatus.SC_BAD_REQUEST == status); - } - } - /* * "10.2.7 206 Partial Content ... The request MUST have included a Range * header field (section 14.35) indicating the desired range, and MAY have @@ -266,12 +156,8 @@ public class TestProtocolDeviations { originResponse.setHeader("Content-Range", "bytes 0-499/1234"); originResponse.setEntity(makeBody(500)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); try { final HttpResponse result = execute(request); Assert.assertTrue(HttpStatus.SC_PARTIAL_CONTENT != result.getCode()); @@ -292,13 +178,9 @@ public class TestProtocolDeviations { originResponse = new BasicClassicHttpResponse(401, "Unauthorized"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + final HttpResponse result = execute(request); - verifyMocks(); Assert.assertSame(originResponse, result); } @@ -312,13 +194,9 @@ public class TestProtocolDeviations { public void testPassesOnOrigin405WithoutAllowHeader() throws Exception { originResponse = new BasicClassicHttpResponse(405, "Method Not Allowed"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + final HttpResponse result = execute(request); - verifyMocks(); Assert.assertSame(originResponse, result); } @@ -333,13 +211,9 @@ public class TestProtocolDeviations { public void testPassesOnOrigin407WithoutAProxyAuthenticateHeader() throws Exception { originResponse = new BasicClassicHttpResponse(407, "Proxy Authentication Required"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + final HttpResponse result = execute(request); - verifyMocks(); Assert.assertSame(originResponse, result); } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRecommendations.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRecommendations.java index f8f8a1e11..c6afcb82b 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRecommendations.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRecommendations.java @@ -39,44 +39,101 @@ import java.util.Date; import java.util.Iterator; import java.util.List; +import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.classic.ExecChain; +import org.apache.hc.client5.http.classic.ExecRuntime; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HeaderElement; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpVersion; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; import org.apache.hc.core5.http.message.MessageSupport; -import org.easymock.Capture; -import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /* * This test class captures functionality required to achieve unconditional * compliance with the HTTP/1.1 spec, i.e. all the SHOULD, SHOULD NOT, * RECOMMENDED, and NOT RECOMMENDED behaviors. */ -public class TestProtocolRecommendations extends AbstractProtocolTest { +@RunWith(MockitoJUnitRunner.class) +public class TestProtocolRecommendations { - private Date now; - private Date tenSecondsAgo; - private Date twoMinutesAgo; + static final int MAX_BYTES = 1024; + static final int MAX_ENTRIES = 100; + static final int ENTITY_LENGTH = 128; + + HttpHost host; + HttpRoute route; + HttpEntity body; + HttpClientContext context; + @Mock + ExecChain mockExecChain; + @Mock + ExecRuntime mockExecRuntime; + @Mock + HttpCache mockCache; + ClassicHttpRequest request; + ClassicHttpResponse originResponse; + CacheConfig config; + CachingExec impl; + HttpCache cache; + Date now; + Date tenSecondsAgo; + Date twoMinutesAgo; - @Override @Before - public void setUp() { - super.setUp(); + public void setUp() throws Exception { + host = new HttpHost("foo.example.com", 80); + + route = new HttpRoute(host); + + body = HttpTestUtils.makeBody(ENTITY_LENGTH); + + request = new BasicClassicHttpRequest("GET", "/foo"); + + context = HttpClientContext.create(); + + originResponse = HttpTestUtils.make200Response(); + + config = CacheConfig.custom() + .setMaxCacheEntries(MAX_ENTRIES) + .setMaxObjectSize(MAX_BYTES) + .build(); + + cache = new BasicHttpCache(config); + impl = new CachingExec(cache, null, config); + now = new Date(); tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); twoMinutesAgo = new Date(now.getTime() - 2 * 60 * 1000L); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + } + + public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { + return impl.execute( + ClassicRequestBuilder.copy(request).build(), + new ExecChain.Scope("test", route, request, mockExecRuntime, context), + mockExecChain); } /* "identity: The default (identity) encoding; the use of no @@ -89,10 +146,10 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { @Test public void testIdentityCodingIsNotUsedInContentEncodingHeader() throws Exception { originResponse.setHeader("Content-Encoding", "identity"); - backendExpectsAnyRequest().andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + final ClassicHttpResponse result = execute(request); - verifyMocks(); + boolean foundIdentity = false; final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_ENCODING); while (it.hasNext()) { @@ -120,15 +177,14 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader(validatorHeader, validator); resp1.setHeader(headerName, headerValue); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader(conditionalHeader, validator); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); + if (HttpStatus.SC_NOT_MODIFIED == result.getCode()) { assertNull(result.getFirstHeader(headerName)); @@ -217,7 +273,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader(validatorHeader, validator); resp1.setHeader("Content-Range", "bytes 0-127/256"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("If-Range", validator); @@ -230,19 +286,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { // cache module does not currently deal with byte ranges, but we want // this test to work even if it does some day - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2).times(0,1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (!cap.hasCaptured() - && HttpStatus.SC_NOT_MODIFIED == result.getCode()) { + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(reqCapture.capture(), Mockito.any()); + + final List allRequests = reqCapture.getAllValues(); + if (allRequests.isEmpty() && HttpStatus.SC_NOT_MODIFIED == result.getCode()) { // cache generated a 304 assertNull(result.getFirstHeader("Content-Range")); } @@ -294,11 +346,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp.setHeader("Etag", "\"etag\""); resp.setHeader(entityHeader, entityHeaderValue); - backendExpectsAnyRequestAndReturn(resp); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp); - replayMocks(); final ClassicHttpResponse result = execute(req); - verifyMocks(); assertNull(result.getFirstHeader(entityHeader)); } @@ -350,11 +400,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp.setHeader("ETag", "\"etag\""); resp.setHeader("Content-Range", "bytes 0-127/256"); - backendExpectsAnyRequestAndReturn(resp); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp); - replayMocks(); final ClassicHttpResponse result = execute(req); - verifyMocks(); assertNull(result.getFirstHeader("Content-Range")); } @@ -377,23 +425,22 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control","public,max-age=5"); resp1.setHeader("Etag","\"etag\""); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); return req1; } private void testDoesNotReturnStaleResponseOnError(final ClassicHttpRequest req2) throws Exception { final ClassicHttpRequest req1 = requestToPopulateStaleCacheEntry(); - backendExpectsAnyRequest().andThrow(new IOException()); - - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new IOException()); + ClassicHttpResponse result = null; try { result = execute(req2); } catch (final IOException acceptable) { } - verifyMocks(); if (result != null) { assertNotEquals(HttpStatus.SC_OK, result.getCode()); @@ -451,15 +498,14 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control","max-stale=20"); - backendExpectsAnyRequest().andThrow(new IOException()).times(0,1); - - replayMocks(); execute(req1); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getCode()); assertNotNull(result.getFirstHeader("Warning")); + + Mockito.verify(mockExecChain, Mockito.atMost(1)).proceed(Mockito.any(), Mockito.any()); } /* @@ -503,16 +549,17 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); - backendExpectsAnyRequest().andThrow(new IOException()).anyTimes(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new IOException()); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); + + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); assertEquals(HttpStatus.SC_OK, result.getCode()); boolean warning111Found = false; @@ -545,11 +592,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { originResponse.setHeader("Cache-Control","public, max-age=5"); originResponse.setHeader("ETag","\"etag\""); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); assertNull(result.getFirstHeader("Warning")); } @@ -563,11 +608,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final String warning = "110 fred \"Response is stale\""; originResponse.addHeader("Warning",warning); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); assertEquals(warning, result.getFirstHeader("Warning").getValue()); } @@ -581,27 +624,23 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { private void testDoesNotModifyHeaderOnResponses(final String headerName) throws Exception { final String headerValue = HttpTestUtils .getCanonicalHeaderValue(originResponse, headerName); - backendExpectsAnyRequest().andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + final ClassicHttpResponse result = execute(request); - verifyMocks(); - assertEquals(headerValue, - result.getFirstHeader(headerName).getValue()); + + assertEquals(headerValue, result.getFirstHeader(headerName).getValue()); } private void testDoesNotModifyHeaderOnRequests(final String headerName) throws Exception { final String headerValue = HttpTestUtils.getCanonicalHeaderValue(request, headerName); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + execute(request); - verifyMocks(); - assertEquals(headerValue, - HttpTestUtils.getCanonicalHeaderValue(cap.getValue(), - headerName)); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + assertEquals(headerValue, HttpTestUtils.getCanonicalHeaderValue(reqCapture.getValue(), headerName)); } @Test @@ -834,25 +873,22 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Last-Modified", lmDate); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - - final Capture cap = EasyMock.newCapture(); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - execute(req2); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); - final Header ifModifiedSince = - captured.getFirstHeader("If-Modified-Since"); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); + final Header ifModifiedSince = captured.getFirstHeader("If-Modified-Since"); assertEquals(lmDate, ifModifiedSince.getValue()); } @@ -877,28 +913,24 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control","max-age=5"); resp1.setHeader("ETag", etag); - backendExpectsAnyRequestAndReturn(resp1); - - final Capture cap = EasyMock.newCapture(); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - execute(req2); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); - final Header ifModifiedSince = - captured.getFirstHeader("If-Modified-Since"); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); + final Header ifModifiedSince = captured.getFirstHeader("If-Modified-Since"); assertEquals(lmDate, ifModifiedSince.getValue()); - final Header ifNoneMatch = - captured.getFirstHeader("If-None-Match"); + final Header ifNoneMatch = captured.getFirstHeader("If-None-Match"); assertEquals(etag, ifNoneMatch.getValue()); } @@ -922,7 +954,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Expires",DateUtils.formatDate(oneSecondAgo)); resp1.setHeader("Cache-Control", "public"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpRequest revalidate = new BasicClassicHttpRequest("GET", "/"); @@ -933,18 +965,12 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Expires", DateUtils.formatDate(oneSecondFromNow)); resp2.setHeader("ETag","\"etag\""); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(revalidate), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(revalidate), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - assertEquals(HttpStatus.SC_OK, - result.getCode()); + assertEquals(HttpStatus.SC_OK, result.getCode()); } /* "When a client tries to revalidate a cache entry, and the response @@ -969,32 +995,23 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make304Response(); resp2.setHeader("ETag","\"etag\""); resp2.setHeader("Date", DateUtils.formatDate(elevenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - final Capture cap = EasyMock.newCapture(); - final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); - resp3.setHeader("ETag","\"etag2\""); - resp3.setHeader("Date", DateUtils.formatDate(now)); - resp3.setHeader("Cache-Control","max-age=5"); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3); - - replayMocks(); execute(req1); - execute(req2); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(3)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); boolean hasMaxAge0 = false; boolean hasNoCache = false; final Iterator it = MessageSupport.iterate(captured, HttpHeaders.CACHE_CONTROL); @@ -1037,8 +1054,6 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Vary","User-Agent"); resp1.setHeader("Etag","\"etag1\""); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET","/"); req2.setHeader("User-Agent","agent2"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); @@ -1046,25 +1061,26 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Vary","User-Agent"); resp2.setHeader("Etag","\"etag2\""); - backendExpectsAnyRequestAndReturn(resp2); - - final Capture cap = EasyMock.newCapture(); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET","/"); req3.setHeader("User-Agent","agent3"); final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - execute(req2); - execute(req3); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + Mockito.when(mockExecChain.proceed(Mockito.any(),Mockito.any())).thenReturn(resp3); + + execute(req3); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(3)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); boolean foundEtag1 = false; boolean foundEtag2 = false; for(final Header h : captured.getHeaders("If-None-Match")) { @@ -1099,9 +1115,6 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); - - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("User-Agent", "agent2"); @@ -1111,8 +1124,6 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Cache-Control", "max-age=3600"); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("User-Agent", "agent3"); @@ -1120,17 +1131,21 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); resp3.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequestAndReturn(resp3); - final ClassicHttpRequest req4 = new BasicClassicHttpRequest("GET", "/"); req4.setHeader("User-Agent", "agent1"); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); + final ClassicHttpResponse result1 = execute(req3); final ClassicHttpResponse result2 = execute(req4); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result1.getCode()); assertEquals("\"etag1\"", result1.getFirstHeader("ETag").getValue()); @@ -1150,7 +1165,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("User-Agent", "agent2"); @@ -1159,16 +1174,14 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("User-Agent", "agent2"); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } /* "If any of the existing cache entries contains only partial content @@ -1187,8 +1200,6 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Vary", "User-Agent"); resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("User-Agent", "agent2"); req2.setHeader("Range", "bytes=0-49"); @@ -1201,8 +1212,6 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Date", DateUtils.formatDate(new Date())); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = HttpTestUtils.makeDefaultRequest(); req3.setHeader("User-Agent", "agent3"); @@ -1211,19 +1220,22 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Vary", "User-Agent"); resp1.setHeader("ETag", "\"etag3\""); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - execute(req2); - execute(req3); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); + + execute(req3); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(3)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); final Iterator it = MessageSupport.iterate(captured, HttpHeaders.IF_NONE_MATCH); while (it.hasNext()) { final HeaderElement elt = it.next(); @@ -1248,7 +1260,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("ETag", "\"old-etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new HttpPost("http://foo.example.com/bar"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); @@ -1256,18 +1268,16 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Content-Location", "http://foo.example.com/"); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new HttpGet("http://foo.example.com"); final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } /* @@ -1286,11 +1296,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Content-Length","200"); resp2.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req2); - verifyMocks(); } @Test @@ -1303,11 +1311,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Date", DateUtils.formatDate(now)); resp2.setHeader("Via","1.0 someproxy"); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req2); - verifyMocks(); } /* @@ -1323,25 +1329,23 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("FROB", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("ETag", "\"etag\""); - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); final ClassicHttpResponse result = execute(req3); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp3, result)); } @@ -1354,44 +1358,46 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary", "User-Agent"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("User-Agent", "agent2"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Vary", "User-Agent"); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = new BasicClassicHttpRequest("FROB", "/"); req3.setHeader("User-Agent", "agent3"); final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequestAndReturn(resp3); - final ClassicHttpRequest req4 = new BasicClassicHttpRequest("GET", "/"); req4.setHeader("User-Agent", "agent1"); final ClassicHttpResponse resp4 = HttpTestUtils.make200Response(); resp4.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequestAndReturn(resp4); - final ClassicHttpRequest req5 = new BasicClassicHttpRequest("GET", "/"); req5.setHeader("User-Agent", "agent2"); final ClassicHttpResponse resp5 = HttpTestUtils.make200Response(); resp5.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequestAndReturn(resp5); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); + execute(req3); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp4); + final ClassicHttpResponse result4 = execute(req4); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp5); + final ClassicHttpResponse result5 = execute(req5); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp4, result4)); assertTrue(HttpTestUtils.semanticallyTransparent(resp5, result5)); @@ -1412,7 +1418,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "max-age=0"); @@ -1421,15 +1427,13 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp2.setHeader("Cache-Control", "max-age=3600"); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = HttpTestUtils.makeDefaultRequest(); - replayMocks(); execute(req1); execute(req2); final ClassicHttpResponse result = execute(req3); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); } @@ -1453,19 +1457,17 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Expires", DateUtils.formatDate(now)); resp1.removeHeaders("Cache-Control"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "max-stale=1000"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); } @@ -1478,19 +1480,17 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Expires", DateUtils.formatDate(tenSecondsAgo)); resp1.removeHeaders("Cache-Control"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "max-stale=1000"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"etag2\""); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); } @@ -1507,18 +1507,12 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { req1.setHeader("Cache-Control", "min-fresh=10, no-cache"); req1.addHeader("Cache-Control", "max-stale=0, max-age=0"); - - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(HttpTestUtils.make200Response()); - - replayMocks(); execute(req1); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); boolean foundNoCache = false; boolean foundDisallowedDirective = false; final List disallowed = @@ -1551,12 +1545,9 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final ClassicHttpRequest req = HttpTestUtils.makeDefaultRequest(); req.setHeader("Cache-Control", "only-if-cached"); - replayMocks(); final ClassicHttpResponse result = execute(req); - verifyMocks(); - assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, - result.getCode()); + assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, result.getCode()); } @Test @@ -1565,15 +1556,13 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "only-if-cached"); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); } @@ -1585,18 +1574,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "only-if-cached"); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, - result.getCode()); + assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, result.getCode()); } @Test @@ -1607,15 +1593,13 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "max-stale=20, only-if-cached"); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpTestUtils.semanticallyTransparent(resp1, result)); } @@ -1628,18 +1612,15 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "max-age=300"); resp1.setHeader("ETag","W/\"weak-sauce\""); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("If-None-Match","W/\"weak-sauce\""); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); - } } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java index 78c374205..1cadf0389 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java @@ -32,6 +32,7 @@ import java.net.SocketTimeoutException; import java.util.Arrays; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,12 +42,16 @@ import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.classic.ExecChain; +import org.apache.hc.client5.http.classic.ExecRuntime; +import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HeaderElements; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; @@ -54,16 +59,19 @@ import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.MessageSupport; -import org.apache.hc.core5.util.ByteArrayBuffer; -import org.easymock.Capture; -import org.easymock.EasyMock; import org.junit.Assert; -import org.junit.Ignore; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /** * We are a conditionally-compliant HTTP/1.1 client with a cache. However, a lot @@ -74,19 +82,68 @@ import org.junit.Test; * pass downstream to the backend HttpClient are are conditionally compliant * with the rules for an HTTP/1.1 client. */ -public class TestProtocolRequirements extends AbstractProtocolTest { +@RunWith(MockitoJUnitRunner.class) +public class TestProtocolRequirements { + + static final int MAX_BYTES = 1024; + static final int MAX_ENTRIES = 100; + static final int ENTITY_LENGTH = 128; + + HttpHost host; + HttpRoute route; + HttpEntity body; + HttpClientContext context; + @Mock + ExecChain mockExecChain; + @Mock + ExecRuntime mockExecRuntime; + @Mock + HttpCache mockCache; + ClassicHttpRequest request; + ClassicHttpResponse originResponse; + CacheConfig config; + CachingExec impl; + HttpCache cache; + + @Before + public void setUp() throws Exception { + host = new HttpHost("foo.example.com", 80); + + route = new HttpRoute(host); + + body = HttpTestUtils.makeBody(ENTITY_LENGTH); + + request = new BasicClassicHttpRequest("GET", "/foo"); + + context = HttpClientContext.create(); + + originResponse = HttpTestUtils.make200Response(); + + config = CacheConfig.custom() + .setMaxCacheEntries(MAX_ENTRIES) + .setMaxObjectSize(MAX_BYTES) + .build(); + + cache = new BasicHttpCache(config); + impl = new CachingExec(cache, null, config); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + } + + public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { + return impl.execute( + ClassicRequestBuilder.copy(request).build(), + new ExecChain.Scope("test", route, request, mockExecRuntime, context), + mockExecChain); + } @Test public void testCacheMissOnGETUsesOriginResponse() throws Exception { - EasyMock.expect( - mockExecChain.proceed( - eqRequest(request), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); } @@ -109,15 +166,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = new BasicClassicHttpRequest("GET", "/foo"); request.setVersion(new ProtocolVersion("HTTP", 2, 13)); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(request), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(request), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertSame(originResponse, result); } @@ -130,15 +182,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest downgraded = new BasicClassicHttpRequest("GET", "/foo"); downgraded.setVersion(HttpVersion.HTTP_1_1); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(downgraded), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(downgraded), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); } @@ -159,15 +206,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest upgraded = new BasicClassicHttpRequest("GET", "/foo"); upgraded.setVersion(HttpVersion.HTTP_1_1); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(upgraded), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(upgraded), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result)); } @@ -189,15 +231,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // not testing this internal behavior in this test, just want // to check the protocol version that comes out the other end - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getVersion()); } @@ -206,15 +243,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = new BasicClassicHttpRequest("GET", "/foo"); request.setVersion(new ProtocolVersion("HTTP", 1, 0)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(HttpVersion.HTTP_1_1, result.getVersion()); } @@ -234,15 +266,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { downgraded.removeHeaders("Connection"); downgraded.addHeader("X-Unknown-Header", "some-value"); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(downgraded), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(downgraded), Mockito.any())).thenReturn(originResponse); execute(request); - - verifyMocks(); } /* @@ -257,16 +283,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest originalRequest = new BasicClassicHttpRequest("GET", "/foo"); originalRequest.setVersion(new ProtocolVersion("HTTP", 1, 0)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(originalRequest); - verifyMocks(); - Assert.assertNull(result.getFirstHeader("TE")); Assert.assertNull(result.getFirstHeader("Transfer-Encoding")); } @@ -285,26 +305,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 */ private void testOrderOfMultipleHeadersIsPreservedOnRequests(final String h, final ClassicHttpRequest request) throws Exception { - final Capture reqCapture = EasyMock.newCapture(); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(reqCapture), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(request); - verifyMocks(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); final ClassicHttpRequest forwarded = reqCapture.getValue(); - Assert.assertNotNull(forwarded); final String expected = HttpTestUtils.getCanonicalHeaderValue(request, h); final String actual = HttpTestUtils.getCanonicalHeaderValue(forwarded, h); if (!actual.contains(expected)) { Assert.assertEquals(expected, actual); } - } @Test @@ -404,16 +417,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } private void testOrderOfMultipleHeadersIsPreservedOnResponses(final String h) throws Exception { - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); - Assert.assertNotNull(result); Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(originResponse, h), HttpTestUtils .getCanonicalHeaderValue(result, h)); @@ -480,25 +487,18 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ private void testUnknownResponseStatusCodeIsNotCached(final int code) throws Exception { - emptyMockCacheExpectsNoPuts(); - originResponse = new BasicClassicHttpResponse(code, "Moo"); originResponse.setHeader("Date", DateUtils.formatDate(new Date())); originResponse.setHeader("Server", "MockOrigin/1.0"); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setEntity(body); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(request); // in particular, there were no storage calls on the cache - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } @Test @@ -529,18 +529,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testUnknownHeadersOnRequestsAreForwarded() throws Exception { request.addHeader("X-Unknown-Header", "blahblah"); - final Capture reqCap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(reqCap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(request); - verifyMocks(); - final ClassicHttpRequest forwarded = reqCap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + final ClassicHttpRequest forwarded = reqCapture.getValue(); final Header[] hdrs = forwarded.getHeaders("X-Unknown-Header"); Assert.assertEquals(1, hdrs.length); Assert.assertEquals("blahblah", hdrs[0].getValue()); @@ -549,16 +544,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testUnknownHeadersOnResponsesAreForwarded() throws Exception { originResponse.addHeader("X-Unknown-Header", "blahblah"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); final Header[] hdrs = result.getHeaders("X-Unknown-Header"); Assert.assertEquals(1, hdrs.length); Assert.assertEquals("blahblah", hdrs[0].getValue()); @@ -578,20 +567,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.setHeader("Content-Length", "128"); post.setEntity(new StringEntity("whatever")); - final Capture reqCap = EasyMock.newCapture(); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(reqCap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(post); - verifyMocks(); - - final ClassicHttpRequest forwarded = reqCap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + final ClassicHttpRequest forwarded = reqCapture.getValue(); boolean foundExpect = false; final Iterator it = MessageSupport.iterate(forwarded, HttpHeaders.EXPECT); while (it.hasNext()) { @@ -617,20 +599,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.setHeader("Content-Length", "128"); post.setEntity(new StringEntity("whatever")); - final Capture reqCap = EasyMock.newCapture(); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(reqCap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(post); - verifyMocks(); - - final ClassicHttpRequest forwarded = reqCap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + final ClassicHttpRequest forwarded = reqCapture.getValue(); boolean foundExpect = false; final Iterator it = MessageSupport.iterate(forwarded, HttpHeaders.EXPECT); while (it.hasNext()) { @@ -681,11 +656,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { post.setHeader("Content-Length", "128"); originResponse = new BasicClassicHttpResponse(100, "Continue"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); try { // if a 100 response gets up to us from the HttpClient @@ -694,8 +665,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Assert.fail("should have thrown an exception"); } catch (final ClientProtocolException expected) { } - - verifyMocks(); } /* @@ -705,20 +674,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testResponsesToOPTIONSAreNotCacheable() throws Exception { - emptyMockCacheExpectsNoPuts(); request = new BasicClassicHttpRequest("OPTIONS", "/"); originResponse.addHeader("Cache-Control", "max-age=3600"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(request); - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } /* @@ -734,15 +697,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setEntity(null); originResponse.setHeader("Content-Length", "0"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); final Header contentLength = result.getFirstHeader("Content-Length"); Assert.assertNotNull(contentLength); Assert.assertEquals("0", contentLength.getValue()); @@ -762,9 +720,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = new BasicClassicHttpRequest("OPTIONS", "*"); request.setHeader("Max-Forwards", "0"); - replayMocks(); execute(request); - verifyMocks(); } /* @@ -779,18 +735,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = new BasicClassicHttpRequest("OPTIONS", "*"); request.setHeader("Max-Forwards", "7"); - final Capture cap = EasyMock.newCapture(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); execute(request); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); Assert.assertEquals("6", captured.getFirstHeader("Max-Forwards").getValue()); } @@ -803,17 +755,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDoesNotAddAMaxForwardsHeaderToForwardedOPTIONSRequests() throws Exception { request = new BasicClassicHttpRequest("OPTIONS", "/"); - final Capture reqCap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(reqCap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); - final ClassicHttpRequest forwarded = reqCap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest forwarded = reqCapture.getValue(); Assert.assertNull(forwarded.getFirstHeader("Max-Forwards")); } @@ -826,17 +775,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testResponseToAHEADRequestMustNotHaveABody() throws Exception { request = new BasicClassicHttpRequest("HEAD", "/"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); - Assert.assertTrue(result.getEntity() == null || result.getEntity().getContentLength() == 0); } @@ -870,26 +812,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader(eHeader, newVal); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(req1), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(req2), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3); - - replayMocks(); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(req1), Mockito.any())).thenReturn(originResponse); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(req2), Mockito.any())).thenReturn(originResponse); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(req3), Mockito.any())).thenReturn(resp3); execute(req1); execute(req2); execute(req3); - - verifyMocks(); } @Test @@ -927,7 +856,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testResponsesToPOSTWithoutCacheControlOrExpiresAreNotCached() throws Exception { - emptyMockCacheExpectsNoPuts(); final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/"); post.setHeader("Content-Length", "128"); @@ -936,16 +864,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Cache-Control"); originResponse.removeHeaders("Expires"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(post); - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } /* @@ -955,7 +878,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testResponsesToPUTsAreNotCached() throws Exception { - emptyMockCacheExpectsNoPuts(); final BasicClassicHttpRequest put = new BasicClassicHttpRequest("PUT", "/"); put.setEntity(HttpTestUtils.makeBody(128)); @@ -963,16 +885,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control", "max-age=3600"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(put); - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } /* @@ -982,21 +899,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testResponsesToDELETEsAreNotCached() throws Exception { - emptyMockCacheExpectsNoPuts(); request = new BasicClassicHttpRequest("DELETE", "/"); originResponse.setHeader("Cache-Control", "max-age=3600"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(request); - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } /* @@ -1006,44 +917,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testResponsesToTRACEsAreNotCached() throws Exception { - emptyMockCacheExpectsNoPuts(); request = new BasicClassicHttpRequest("TRACE", "/"); originResponse.setHeader("Cache-Control", "max-age=3600"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(request); - verifyMocks(); - } - - /* - * "The 204 response MUST NOT include a message-body, and thus is always - * terminated by the first empty line after the header fields." - * - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5 - */ - @Test - public void test204ResponsesDoNotContainMessageBodies() throws Exception { - originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); - - final ClassicHttpResponse result = execute(request); - - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } /* @@ -1076,12 +958,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range", "bytes=0-50"); - backendExpectsAnyRequestAndReturn(resp1).times(1, 2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getCode()) { if (result.getFirstHeader("Content-Range") == null) { @@ -1092,6 +972,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Assert.assertNotEquals("", elt.getParameterByName("boundary").getValue().trim()); } } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1105,12 +986,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range", "bytes=0-50"); - backendExpectsAnyRequestAndReturn(resp1).times(1, 2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getCode()) { final Header h = result.getFirstHeader("Content-Length"); @@ -1125,6 +1004,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Assert.assertEquals(contentLength, bytesRead); } } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1137,16 +1017,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range", "bytes=0-50"); - backendExpectsAnyRequestAndReturn(resp1).times(1, 2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); if (HttpStatus.SC_PARTIAL_CONTENT == result.getCode()) { Assert.assertNotNull(result.getFirstHeader("Date")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1159,18 +1038,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Content-Range", "bytes 0-499/1234"); originResponse.removeHeaders("Date"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); Assert.assertTrue(result.getCode() != HttpStatus.SC_PARTIAL_CONTENT || result.getFirstHeader("Date") != null); - verifyMocks(); } @Test @@ -1183,18 +1056,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.addHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(originResponse).times(1, 2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) { Assert.assertNotNull(result.getFirstHeader("ETag")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1207,18 +1077,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.addHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(originResponse).times(1, 2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) { Assert.assertNotNull(result.getFirstHeader("Content-Location")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1249,22 +1116,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req3.addHeader("Range", "bytes=0-50"); req3.addHeader("Accept-Encoding", "gzip"); - backendExpectsAnyRequest().andReturn(originResponse); - backendExpectsAnyRequestAndReturn(originResponse2).times(1, 2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse2); + execute(req2); final ClassicHttpResponse result = execute(req3); - verifyMocks(); if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) { Assert.assertNotNull(result.getFirstHeader("Expires")); Assert.assertNotNull(result.getFirstHeader("Cache-Control")); Assert.assertNotNull(result.getFirstHeader("Vary")); } + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1297,15 +1164,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.addHeader("If-Range", "W/\"weak-tag\""); req2.addHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(originResponse).times(1, 2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) { Assert.assertNull(result.getFirstHeader("Allow")); Assert.assertNull(result.getFirstHeader("Content-Encoding")); @@ -1313,6 +1176,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Assert.assertNull(result.getFirstHeader("Content-MD5")); Assert.assertNull(result.getFirstHeader("Last-Modified")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1343,15 +1207,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.addHeader("If-Range", "\"strong-tag\""); req2.addHeader("Range", "bytes=0-50"); - backendExpectsAnyRequest().andReturn(originResponse).times(1, 2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) { Assert.assertEquals("GET,HEAD", result.getFirstHeader("Allow").getValue()); Assert.assertEquals("max-age=3600", result.getFirstHeader("Cache-Control").getValue()); @@ -1362,6 +1222,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Assert.assertEquals(originResponse.getFirstHeader("Last-Modified").getValue(), result .getFirstHeader("Last-Modified").getValue()); } + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1401,33 +1262,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final Date inTwoSeconds = new Date(now.getTime() + 2000L); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); - resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds)); - resp3.setHeader("Cache-Control", "max-age=3600"); - resp3.setHeader("ETag", "\"etag2\""); - final byte[] bytes3 = new byte[128]; - Arrays.fill(bytes3, (byte) 2); - resp3.setEntity(new ByteArrayEntity(bytes3, null)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3).times(0, 1); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); - execute(req2); - final ClassicHttpResponse result = execute(req3); - verifyMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ClassicHttpResponse result = execute(req3); final InputStream i = result.getEntity().getContent(); int b; @@ -1443,6 +1287,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } i.close(); Assert.assertFalse(found1 && found2); // mixture of content + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1476,33 +1321,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final Date inTwoSeconds = new Date(now.getTime() + 2000L); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); - resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds)); - resp3.setHeader("Cache-Control", "max-age=3600"); - resp3.setHeader("ETag", "\"etag2\""); - final byte[] bytes3 = new byte[128]; - Arrays.fill(bytes3, (byte) 2); - resp3.setEntity(new ByteArrayEntity(bytes3, null)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3).times(0, 1); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); - execute(req2); - final ClassicHttpResponse result = execute(req3); - verifyMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ClassicHttpResponse result = execute(req3); final InputStream i = result.getEntity().getContent(); int b; @@ -1518,6 +1346,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } i.close(); Assert.assertFalse(found1 && found2); // mixture of content + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1529,9 +1358,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ResponsesAreNotCachedIfTheCacheDoesNotSupportRangeAndContentRangeHeaders() throws Exception { - if (!supportsRangeAndContentRangeHeaders(impl)) { - emptyMockCacheExpectsNoPuts(); - + if (!impl.supportsRangeAndContentRangeHeaders()) { request = new BasicClassicHttpRequest("GET", "/"); request.addHeader("Range", "bytes=0-50"); @@ -1542,14 +1369,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { new Random().nextBytes(bytes); originResponse.setEntity(new ByteArrayEntity(bytes, null)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } } @@ -1561,7 +1384,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void test303ResponsesAreNotCached() throws Exception { - emptyMockCacheExpectsNoPuts(); request = new BasicClassicHttpRequest("GET", "/"); @@ -1571,44 +1393,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader("Content-Type", "application/x-cachingclient-test"); originResponse.setHeader("Location", "http://foo.example.com/other"); - originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); + originResponse.setEntity(HttpTestUtils.makeBody(ENTITY_LENGTH)); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); - } - /* - * "The 304 response MUST NOT contain a message-body, and thus is always - * terminated by the first empty line after the header fields." - * - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 - */ - @Test - public void test304ResponseDoesNotContainABody() throws Exception { - request.setHeader("If-None-Match", "\"etag\""); - - originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED,"Not Modified"); - originResponse.setHeader("Date", DateUtils.formatDate(new Date())); - originResponse.setHeader("Server", "MockServer/1.0"); - originResponse.setHeader("Content-Length", "128"); - originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); - - final ClassicHttpResponse result = execute(request); - - verifyMocks(); + Mockito.verifyNoInteractions(mockCache); } /* @@ -1628,15 +1419,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Server", "MockServer/1.0"); originResponse.setHeader("ETag", "\"etag\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Date")); } @@ -1650,19 +1436,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("If-None-Match", "\"etag\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse).times(1, 2); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) { Assert.assertNotNull(result.getFirstHeader("Date")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1681,19 +1463,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("If-None-Match", "\"etag\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse).times(1, 2); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) { Assert.assertNotNull(result.getFirstHeader("ETag")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -1706,19 +1484,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("If-None-Match", "\"etag\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse).times(1, 2); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) { Assert.assertNotNull(result.getFirstHeader("Content-Location")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1742,7 +1516,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "max-age=7200"); resp1.setHeader("Expires", DateUtils.formatDate(inTwoHours)); resp1.setHeader("Vary", "Accept-Encoding"); - resp1.setEntity(HttpTestUtils.makeBody(entityLength)); + resp1.setEntity(HttpTestUtils.makeBody(ENTITY_LENGTH)); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req1.setHeader("Accept-Encoding", "gzip"); @@ -1753,33 +1527,27 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Cache-Control", "max-age=3600"); resp2.setHeader("Expires", DateUtils.formatDate(inTwoHours)); resp2.setHeader("Vary", "Accept-Encoding"); - resp2.setEntity(HttpTestUtils.makeBody(entityLength)); + resp2.setEntity(HttpTestUtils.makeBody(ENTITY_LENGTH)); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("Accept-Encoding", "gzip"); req3.setHeader("If-None-Match", "\"v2\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2).times(1, 2); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); final ClassicHttpResponse result = execute(req3); - verifyMocks(); - if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) { Assert.assertNotNull(result.getFirstHeader("Expires")); Assert.assertNotNull(result.getFirstHeader("Cache-Control")); Assert.assertNotNull(result.getFirstHeader("Vary")); } + Mockito.verify(mockExecChain, Mockito.times(3)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1811,17 +1579,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("If-None-Match", "W/\"v1\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1).times(1, 2); - replayMocks(); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(req1), Mockito.any())).thenReturn(resp1); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) { Assert.assertNull(result.getFirstHeader("Allow")); Assert.assertNull(result.getFirstHeader("Content-Encoding")); @@ -1830,6 +1592,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Assert.assertNull(result.getFirstHeader("Content-Type")); Assert.assertNull(result.getFirstHeader("Last-Modified")); } + Mockito.verify(mockExecChain, Mockito.times(1)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1854,44 +1617,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control", "max-age=0,max-stale=0"); - // updated ETag provided to a conditional revalidation - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, - "Not Modified"); - resp2.setHeader("Date", DateUtils.formatDate(now)); - resp2.setHeader("Server", "MockServer/1.0"); - resp2.setHeader("ETag", "\"etag2\""); - - // conditional validation uses If-None-Match - final ClassicHttpRequest conditionalValidation = new BasicClassicHttpRequest("GET", "/"); - conditionalValidation.setHeader("If-None-Match", "\"etag1\""); - // unconditional validation doesn't use If-None-Match final ClassicHttpRequest unconditionalValidation = new BasicClassicHttpRequest("GET", "/"); // new response to unconditional validation provides new body - final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); + final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag2\""); resp1.setHeader("Cache-Control", "max-age=3600"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); // this next one will happen once if the cache tries to // conditionally validate, zero if it goes full revalidation - EasyMock.expect( - mockExecChain.proceed( - eqRequest(conditionalValidation), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2).times(0, 1); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(unconditionalValidation), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp3); - replayMocks(); + + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(unconditionalValidation), Mockito.any())).thenReturn(resp2); execute(req1); execute(req2); - verifyMocks(); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } /* @@ -1919,8 +1661,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest conditionalValidationRequest = new BasicClassicHttpRequest("GET", "/"); conditionalValidationRequest.setHeader("If-None-Match", "\"etag\""); - final ClassicHttpRequest unconditionalValidationRequest = new BasicClassicHttpRequest("GET", "/"); - // to be used if the cache generates a conditional validation final ClassicHttpResponse conditionalResponse = HttpTestUtils.make304Response(); conditionalResponse.setHeader("Date", DateUtils.formatDate(inFiveSeconds)); @@ -1933,37 +1673,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { unconditionalResponse.setHeader("Date", DateUtils.formatDate(inFiveSeconds)); unconditionalResponse.setHeader("ETag", "\"etag\""); - final Capture cap1 = EasyMock.newCapture(); - final Capture cap2 = EasyMock.newCapture(); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(cachedResponse); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.and(eqRequest(conditionalValidationRequest), EasyMock.capture(cap1)), - EasyMock.isA(ExecChain.Scope.class))).andReturn(conditionalResponse).times(0, 1); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.and(eqRequest(unconditionalValidationRequest), EasyMock.capture(cap2)), - EasyMock.isA(ExecChain.Scope.class))).andReturn(unconditionalResponse).times(0, 1); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(cachedResponse); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(conditionalValidationRequest), Mockito.any())).thenReturn(conditionalResponse); execute(initialRequest); final ClassicHttpResponse result = execute(secondRequest); - verifyMocks(); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); - Assert.assertTrue((cap1.hasCaptured() && !cap2.hasCaptured()) - || (!cap1.hasCaptured() && cap2.hasCaptured())); - - if (cap1.hasCaptured()) { - Assert.assertEquals(DateUtils.formatDate(inFiveSeconds), result.getFirstHeader("Date") - .getValue()); - Assert.assertEquals("junk", result.getFirstHeader("X-Extra").getValue()); - } + Assert.assertEquals(DateUtils.formatDate(inFiveSeconds), result.getFirstHeader("Date").getValue()); + Assert.assertEquals("junk", result.getFirstHeader("X-Extra").getValue()); } /* @@ -1978,18 +1697,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse = new BasicClassicHttpResponse(401, "Unauthorized"); originResponse.setHeader("WWW-Authenticate", "x-scheme x-param"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - if (result.getCode() == 401) { - Assert.assertNotNull(result.getFirstHeader("WWW-Authenticate")); - } - - verifyMocks(); + Assert.assertEquals(401, result.getCode()); + Assert.assertNotNull(result.getFirstHeader("WWW-Authenticate")); } /* @@ -2003,16 +1715,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse = new BasicClassicHttpResponse(405, "Method Not Allowed"); originResponse.setHeader("Allow", "GET, HEAD"); - backendExpectsAnyRequest().andReturn(originResponse); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - if (result.getCode() == 405) { - Assert.assertNotNull(result.getFirstHeader("Allow")); - } - - verifyMocks(); + Assert.assertEquals(405, result.getCode()); + Assert.assertNotNull(result.getFirstHeader("Allow")); } /* @@ -2027,18 +1734,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse = new BasicClassicHttpResponse(407, "Proxy Authentication Required"); originResponse.setHeader("Proxy-Authenticate", "x-scheme x-param"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - if (result.getCode() == 407) { - Assert.assertNotNull(result.getFirstHeader("Proxy-Authenticate")); - } - - verifyMocks(); + Assert.assertEquals(407, result.getCode()); + Assert.assertNotNull(result.getFirstHeader("Proxy-Authenticate")); } /* @@ -2051,28 +1751,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testMustNotAddMultipartByteRangeContentTypeTo416Response() throws Exception { originResponse = new BasicClassicHttpResponse(416, "Requested Range Not Satisfiable"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); - if (result.getCode() == 416) { - final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_TYPE); - while (it.hasNext()) { - final HeaderElement elt = it.next(); - Assert.assertFalse("multipart/byteranges".equalsIgnoreCase(elt.getName())); - } + Assert.assertEquals(416, result.getCode()); + final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_TYPE); + while (it.hasNext()) { + final HeaderElement elt = it.next(); + Assert.assertFalse("multipart/byteranges".equalsIgnoreCase(elt.getName())); } } @Test public void testMustNotUseMultipartByteRangeContentTypeOnCacheGenerated416Responses() throws Exception { - originResponse.setEntity(HttpTestUtils.makeBody(entityLength)); + originResponse.setEntity(HttpTestUtils.makeBody(ENTITY_LENGTH)); originResponse.setHeader("Content-Length", "128"); originResponse.setHeader("Cache-Control", "max-age=3600"); @@ -2082,30 +1776,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse orig416 = new BasicClassicHttpResponse(416, "Requested Range Not Satisfiable"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); // cache may 416 me right away if it understands byte ranges, // ok to delegate to origin though - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(orig416).times(0, 1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(rangeReq), Mockito.any())).thenReturn(orig416); - replayMocks(); execute(request); final ClassicHttpResponse result = execute(rangeReq); - verifyMocks(); // might have gotten a 416 from the origin or the cache - if (result.getCode() == 416) { - final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_TYPE); - while (it.hasNext()) { - final HeaderElement elt = it.next(); - Assert.assertFalse("multipart/byteranges".equalsIgnoreCase(elt.getName())); - } + Assert.assertEquals(416, result.getCode()); + final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_TYPE); + while (it.hasNext()) { + final HeaderElement elt = it.next(); + Assert.assertFalse("multipart/byteranges".equalsIgnoreCase(elt.getName())); } + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } /* @@ -2167,25 +1853,26 @@ public class TestProtocolRequirements extends AbstractProtocolTest { notModified.setHeader("Date", DateUtils.formatDate(now)); notModified.setHeader("ETag", "\"etag\""); - EasyMock.expect( - mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))) - .andReturn(entry); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(validate), - EasyMock.isA(ExecChain.Scope.class))).andReturn(notModified); - EasyMock.expect(mockCache.updateCacheEntry( - EasyMock.eq(host), - eqRequest(request), - EasyMock.eq(entry), - eqResponse(notModified), - EasyMock.isA(Date.class), - EasyMock.isA(Date.class))) - .andReturn(HttpTestUtils.makeCacheEntry()); + Mockito.when(mockCache.getCacheEntry(Mockito.eq(host), RequestEquivalent.eq(request))).thenReturn(entry); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(validate), Mockito.any())).thenReturn(notModified); + Mockito.when(mockCache.updateCacheEntry( + Mockito.eq(host), + RequestEquivalent.eq(request), + Mockito.eq(entry), + ResponseEquivalent.eq(notModified), + Mockito.any(), + Mockito.any())) + .thenReturn(HttpTestUtils.makeCacheEntry()); - replayMocks(); execute(request); - verifyMocks(); + + Mockito.verify(mockCache).updateCacheEntry( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any()); } @Test @@ -2210,11 +1897,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { impl = new CachingExec(mockCache, null, config); request = new BasicClassicHttpRequest("GET", "/thing"); - EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); + Mockito.when(mockCache.getCacheEntry(Mockito.eq(host), RequestEquivalent.eq(request))).thenReturn(entry); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(200, result.getCode()); } @@ -2256,31 +1941,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { impl = new CachingExec(mockCache, null, config); request = new BasicClassicHttpRequest("GET", "/thing"); - EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andThrow( - new IOException("can't talk to origin!")).anyTimes(); - - replayMocks(); + Mockito.when(mockCache.getCacheEntry(Mockito.eq(host), RequestEquivalent.eq(request))).thenReturn(entry); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow( + new IOException("can't talk to origin!")); final ClassicHttpResponse result = execute(request); - verifyMocks(); - final int status = result.getCode(); - if (status == 200) { - boolean foundWarning = false; - for (final Header h : result.getHeaders("Warning")) { - if (h.getValue().split(" ")[0].equals("111")) { - foundWarning = true; - } + Assert.assertEquals(200, result.getCode()); + boolean foundWarning = false; + for (final Header h : result.getHeaders("Warning")) { + if (h.getValue().split(" ")[0].equals("111")) { + foundWarning = true; } - Assert.assertTrue(foundWarning); - } else { - Assert.assertTrue(status >= 500 && status <= 599); } + Assert.assertTrue(foundWarning); } /* @@ -2326,15 +2001,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("ETag", "\"etag\""); resp2.setHeader("Via", "1.1 fred"); - backendExpectsAnyRequestAndReturn(resp1); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(validate), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(validate), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - replayMocks(); final ClassicHttpResponse stale = execute(req1); Assert.assertNotNull(stale.getFirstHeader("Warning")); @@ -2342,8 +2013,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse result1 = execute(req2); final ClassicHttpResponse result2 = execute(req3); - verifyMocks(); - boolean found1xxWarning = false; final Iterator it = MessageSupport.iterate(result1, HttpHeaders.WARNING); while (it.hasNext()) { @@ -2395,14 +2064,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - backendExpectsAnyRequestAndReturn(resp1); - - EasyMock.expect( - mockExecChain.proceed( - eqRequest(validate), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); - - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(validate), Mockito.any())).thenReturn(resp2); final ClassicHttpResponse stale = execute(req1); Assert.assertNotNull(stale.getFirstHeader("Warning")); @@ -2410,8 +2073,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse result1 = execute(req2); final ClassicHttpResponse result2 = execute(req3); - verifyMocks(); - boolean found214Warning = false; final Iterator it = MessageSupport.iterate(result1, HttpHeaders.WARNING); while (it.hasNext()) { @@ -2464,11 +2125,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { impl = new CachingExec(mockCache, null, config); request = new BasicClassicHttpRequest("GET", "/thing"); - EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); + Mockito.when(mockCache.getCacheEntry(Mockito.eq(host), RequestEquivalent.eq(request))).thenReturn(entry); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(200, result.getCode()); Assert.assertEquals("11", result.getFirstHeader("Age").getValue()); @@ -2523,34 +2182,24 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(); - final Capture cap = EasyMock.newCapture(); + Mockito.when(mockCache.getCacheEntry(Mockito.eq(host), RequestEquivalent.eq(request))).thenReturn(entry); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(validated); + Mockito.when(mockCache.createCacheEntry( + Mockito.any(), + Mockito.any(), + ResponseEquivalent.eq(validated), + Mockito.any(), + Mockito.any(), + Mockito.any())).thenReturn(cacheEntry); - mockCache.flushCacheEntriesInvalidatedByExchange( - EasyMock.isA(HttpHost.class), - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ClassicHttpResponse.class)); - EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(validated).times(0, 1); - EasyMock.expect(mockCache.getCacheEntry( - EasyMock.isA(HttpHost.class), - EasyMock.isA(ClassicHttpRequest.class))).andReturn(entry).times(0, 1); - EasyMock.expect(mockCache.createCacheEntry( - EasyMock.isA(HttpHost.class), - EasyMock.isA(ClassicHttpRequest.class), - eqCloseableResponse(validated), - EasyMock.isA(ByteArrayBuffer.class), - EasyMock.isA(Date.class), - EasyMock.isA(Date.class))).andReturn(cacheEntry).times(0, 1); - - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(200, result.getCode()); - if (!cap.hasCaptured()) { + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.atMostOnce()).proceed(reqCapture.capture(), Mockito.any()); + final List allRequests = reqCapture.getAllValues(); + if (allRequests.isEmpty()) { // heuristic cache hit boolean found113Warning = false; final Iterator it = MessageSupport.iterate(result, HttpHeaders.WARNING); @@ -2564,6 +2213,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { } Assert.assertTrue(found113Warning); } + Mockito.verify(mockCache).createCacheEntry( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any()); } /* @@ -2600,18 +2256,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - EasyMock.expect( - mockExecChain.proceed( - eqRequest(req1), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); final ClassicHttpResponse result = execute(req3); - verifyMocks(); Assert.assertEquals("\"etag1\"", result.getFirstHeader("ETag").getValue()); } @@ -2630,26 +2282,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * from upstream. */ private ClassicHttpResponse testRequestWithWeakETagValidatorIsNotAllowed(final String header) throws Exception { - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse).times(0, 1); - - replayMocks(); final ClassicHttpResponse response = execute(request); - verifyMocks(); // it's probably ok to return a 400 (Bad Request) to this client - if (cap.hasCaptured()) { - final ClassicHttpRequest forwarded = cap.getValue(); - final Header h = forwarded.getFirstHeader(header); - if (h != null) { - Assert.assertFalse(h.getValue().startsWith("W/")); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.atMostOnce()).proceed(reqCapture.capture(), Mockito.any()); + final List allRequests = reqCapture.getAllValues(); + if (!allRequests.isEmpty()) { + final ClassicHttpRequest forwarded = reqCapture.getValue(); + if (forwarded != null) { + final Header h = forwarded.getFirstHeader(header); + if (h != null) { + Assert.assertFalse(h.getValue().startsWith("W/")); + } } } return response; - } @Test @@ -2725,17 +2373,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range", "bytes=0-50"); req2.setHeader("If-Range", "W/\"etag\""); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1).times(1, 2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertNotEquals(HttpStatus.SC_PARTIAL_CONTENT, result.getCode()); + + Mockito.verify(mockExecChain).proceed(Mockito.any(), Mockito.any()); } /* @@ -2761,23 +2406,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control", "max-age=0,max-stale=0"); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1); - - replayMocks(); execute(req1); execute(req2); - verifyMocks(); - final ClassicHttpRequest validation = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(reqCapture.capture(), Mockito.any()); + + final List allRequests = reqCapture.getAllValues(); + Assert.assertEquals(2, allRequests.size()); + final ClassicHttpRequest validation = allRequests.get(1); boolean isConditional = false; final String[] conditionalHeaders = { "If-Range", "If-Modified-Since", "If-Unmodified-Since", "If-Match", "If-None-Match" }; @@ -2836,17 +2475,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("If-Modified-Since", DateUtils.formatDate(twentySecondsAgo)); // must hit the origin again for the second request - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1).times(2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertNotEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -2866,15 +2501,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("If-Modified-Since", DateUtils.formatDate(tenSecondsAgo)); // may hit the origin again for the second request - EasyMock.expect( - mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp1).times(1,2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); + + Mockito.verify(mockExecChain, Mockito.atLeastOnce()).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(Mockito.any(), Mockito.any()); } @@ -2887,9 +2520,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testCacheWithoutSupportForRangeAndContentRangeHeadersDoesNotCacheA206Response() throws Exception { - if (!supportsRangeAndContentRangeHeaders(impl)) { - emptyMockCacheExpectsNoPuts(); - + if (!impl.supportsRangeAndContentRangeHeaders()) { final ClassicHttpRequest req = new BasicClassicHttpRequest("GET", "/"); req.setHeader("Range", "bytes=0-50"); @@ -2898,13 +2529,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp.setHeader("ETag", "\"etag\""); resp.setHeader("Cache-Control", "max-age=3600"); - EasyMock.expect(mockExecChain.proceed( - EasyMock.isA(ClassicHttpRequest.class), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp); + Mockito.when(mockExecChain.proceed(Mockito.any(),Mockito.any())).thenReturn(resp); - replayMocks(); execute(req); - verifyMocks(); + + Mockito.verifyNoInteractions(mockCache); } } @@ -2926,12 +2555,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Expires"); originResponse.removeHeaders("Cache-Control"); - backendExpectsAnyRequest().andReturn(originResponse).times(2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); execute(request); - verifyMocks(); + + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } /* @@ -2943,11 +2572,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse = HttpTestUtils.make200Response(); originResponse.setHeader(header, value); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); } @@ -2978,11 +2605,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testDoesNotAddHeaderToOriginResponse(final String header) throws Exception { originResponse.removeHeaders(header); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertNull(result.getFirstHeader(header)); } @@ -3016,12 +2641,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader(header, value); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); } @@ -3056,12 +2679,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.removeHeaders(header); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertNull(result.getFirstHeader(header)); } @@ -3092,18 +2713,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req.setHeader("Content-Length","128"); req.setHeader(header,value); - final Capture cap = EasyMock.newCapture(); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); execute(req); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); Assert.assertEquals(value, captured.getFirstHeader(header).getValue()); } @@ -3136,18 +2751,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req.setHeader("Content-Length","128"); req.removeHeaders(header); - final Capture cap = EasyMock.newCapture(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - - replayMocks(); execute(req); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); Assert.assertNull(captured.getFirstHeader(header)); } @@ -3195,11 +2806,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testExpiresHeaderMatchesDateIfAddedToOriginResponse() throws Exception { originResponse.removeHeaders("Expires"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); final Header expHdr = result.getFirstHeader("Expires"); if (expHdr != null) { @@ -3216,12 +2825,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control","max-age=3600"); originResponse.removeHeaders("Expires"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); final Header expHdr = result.getFirstHeader("Expires"); if (expHdr != null) { @@ -3240,11 +2847,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Cache-Control","no-transform"); originResponse.setHeader(header, value); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); } @@ -3276,12 +2881,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Cache-Control","max-age=3600, no-transform"); originResponse.setHeader(header, value); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(value, result.getFirstHeader(header).getValue()); } @@ -3308,15 +2911,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Cache-Control","max-age=3600, no-transform"); originResponse.setHeader("Content-Range", "bytes 0-49/128"); - backendExpectsAnyRequest().andReturn(originResponse).times(1,2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals("bytes 0-49/128", result.getFirstHeader("Content-Range").getValue()); + + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -3408,13 +3011,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Cache-Control","max-age=0, max-stale=0"); final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); final InputStream i1 = resp1.getEntity().getContent(); final InputStream i2 = result.getEntity().getContent(); @@ -3469,13 +3072,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Date", DateUtils.formatDate(new Date())); resp2.setHeader("Server", "MockServer/1.0"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(req2), Mockito.any())).thenReturn(resp2); final ClassicHttpResponse result = execute(req2); - verifyMocks(); final String[] endToEndHeaders = { "Cache-Control", "ETag", "Allow", "Content-Encoding", @@ -3513,16 +3115,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Pragma","x-new-pragma"); resp2.setHeader("Retry-After","120"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpResponse result1 = execute(req2); final ClassicHttpResponse result2 = execute(req3); - verifyMocks(); final String[] endToEndHeaders = { "Date", "Cache-Control", "Allow", "Content-Language", @@ -3554,16 +3155,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified"); resp2.setHeader("Cache-Control", "max-age=1800"); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result1 = execute(req2); final ClassicHttpResponse result2 = execute(req3); - verifyMocks(); final String h = "Cache-Control"; Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(resp2, h), @@ -3609,7 +3210,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("ETag","\"etag1\""); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3621,7 +3222,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); @@ -3630,13 +3231,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3656,7 +3255,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3669,7 +3268,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); @@ -3678,13 +3277,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3705,7 +3302,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3718,7 +3315,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); @@ -3727,13 +3324,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3754,7 +3349,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3766,7 +3361,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("Range","bytes=0-49"); @@ -3777,13 +3372,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3803,7 +3396,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3816,7 +3409,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("Range","bytes=0-49"); @@ -3827,13 +3420,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3854,7 +3445,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3867,7 +3458,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("Range","bytes=0-49"); @@ -3878,13 +3469,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3905,7 +3494,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3918,7 +3507,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("Range","bytes=50-127"); @@ -3929,13 +3518,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } @Test @@ -3955,7 +3542,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Range","bytes=50-127"); @@ -3968,7 +3555,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Server","MockServer/1.0"); resp2.setHeader("Date", DateUtils.formatDate(oneSecondAgo)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); req3.setHeader("Range","bytes=0-49"); @@ -3979,13 +3566,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp3.setHeader("Date", DateUtils.formatDate(now)); // must make this request; cannot serve from cache - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(req2); execute(req3); - verifyMocks(); } /* "When the cache receives a subsequent request whose Request-URI @@ -4008,7 +3593,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","Accept-Encoding"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.removeHeaders("Accept-Encoding"); @@ -4018,12 +3603,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Cache-Control","max-age=3600"); // not allowed to have a cache hit; must forward request - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } /* "A Vary header field-value of "*" always fails to match and @@ -4041,7 +3624,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","*"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); @@ -4050,12 +3633,10 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Cache-Control","max-age=3600"); // not allowed to have a cache hit; must forward request - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } /* " If the selecting request header fields for the cached entry @@ -4092,47 +3673,26 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Vary","User-Agent"); resp1.setHeader("Content-Type","application/octet-stream"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("User-Agent","MyBrowser/1.5"); - final ClassicHttpRequest conditional = new BasicClassicHttpRequest("GET", "/"); - conditional.setHeader("User-Agent","MyBrowser/1.5"); - conditional.setHeader("If-None-Match","\"etag1\""); - final ClassicHttpResponse resp200 = HttpTestUtils.make200Response(); resp200.setHeader("ETag","\"etag1\""); resp200.setHeader("Vary","User-Agent"); - final ClassicHttpResponse resp304 = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified"); - resp304.setHeader("ETag","\"etag1\""); - resp304.setHeader("Vary","User-Agent"); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - final Capture condCap = EasyMock.newCapture(); - final Capture uncondCap = EasyMock.newCapture(); - - EasyMock.expect( - mockExecChain.proceed( - EasyMock.and(eqRequest(conditional), EasyMock.capture(condCap)), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp304).times(0,1); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.and(eqRequest(req2), EasyMock.capture(uncondCap)), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp200).times(0,1); - - replayMocks(); execute(req1); - final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (HttpStatus.SC_OK == result.getCode()) { - Assert.assertTrue(condCap.hasCaptured() - || uncondCap.hasCaptured()); - if (uncondCap.hasCaptured()) { - Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp200, result)); - } - } + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(req2), Mockito.any())).thenReturn(resp200); + + final ClassicHttpResponse result = execute(req2); + + Assert.assertEquals(HttpStatus.SC_OK, result.getCode()); + + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(Mockito.any(), Mockito.any()); + + Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp200, result)); } /* "Some HTTP methods MUST cause a cache to invalidate an @@ -4151,24 +3711,30 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","public, max-age=3600"); // this origin request MUST happen due to invalidation - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(unsafeReq); execute(req3); - verifyMocks(); + } + + protected ClassicHttpRequest makeRequestWithBody(final String method, final String requestUri) { + final ClassicHttpRequest req = new BasicClassicHttpRequest(method, requestUri); + final int nbytes = 128; + req.setEntity(HttpTestUtils.makeBody(nbytes)); + req.setHeader("Content-Length", Long.toString(nbytes)); + return req; } @Test @@ -4195,24 +3761,22 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/content"); final ClassicHttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","public, max-age=3600"); // this origin request MUST happen due to invalidation - backendExpectsAnyRequestAndReturn(resp3); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp3); - replayMocks(); execute(req1); execute(unsafeReq); execute(req3); - verifyMocks(); } protected void testUnsafeMethodInvalidatesCacheForUriInContentLocationHeader( @@ -4302,19 +3866,18 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); - backendExpectsAnyRequestAndReturn(resp2); - final ClassicHttpRequest req3 = new BasicClassicHttpRequest("GET", "/content"); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(unsafeReq); execute(req3); - verifyMocks(); } protected void testUnsafeMethodDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts( @@ -4329,15 +3892,6 @@ public class TestProtocolRequirements extends AbstractProtocolTest { testUnsafeMethodDoesNotInvalidateCacheForHeaderUri(unsafeReq); } - protected ClassicHttpRequest makeRequestWithBody(final String method, final String requestUri) { - final ClassicHttpRequest req = - new BasicClassicHttpRequest(method, requestUri); - final int nbytes = 128; - req.setEntity(HttpTestUtils.makeBody(nbytes)); - req.setHeader("Content-Length",""+nbytes); - return req; - } - @Test public void testPutDoesNotInvalidateCacheForUriInContentLocationHeadersFromOtherHosts() throws Exception { final ClassicHttpRequest req = makeRequestWithBody("PUT","/"); @@ -4386,17 +3940,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testRequestIsWrittenThroughToOrigin(final ClassicHttpRequest req) throws Exception { final ClassicHttpResponse resp = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); final ClassicHttpRequest wrapper = req; - EasyMock.expect( - mockExecChain.proceed( - eqRequest(wrapper), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp); + Mockito.when(mockExecChain.proceed(RequestEquivalent.eq(wrapper), Mockito.any())).thenReturn(resp); - replayMocks(); execute(wrapper); - verifyMocks(); } - @Test @Ignore + @Test public void testOPTIONSRequestsAreWrittenThroughToOrigin() throws Exception { final ClassicHttpRequest req = new BasicClassicHttpRequest("OPTIONS","*"); testRequestIsWrittenThroughToOrigin(req); @@ -4454,11 +4003,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final String reallyOldAge = "1" + Long.MAX_VALUE; originResponse.setHeader("Age",reallyOldAge); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals("2147483648", result.getFirstHeader("Age").getValue()); @@ -4474,10 +4021,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testDoesNotModifyAllowHeaderWithUnknownMethods() throws Exception { final String allowHeaderValue = "GET, HEAD, FOOBAR"; originResponse.setHeader("Allow",allowHeaderValue); - backendExpectsAnyRequest().andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(originResponse,"Allow"), HttpTestUtils.getCanonicalHeaderValue(result, "Allow")); } @@ -4514,21 +4059,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); req1.setHeader("Authorization",authorization); - backendExpectsAnyRequestAndReturn(authorizedResponse); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); - if (maxTimes > 0) { - // this request MUST happen - backendExpectsAnyRequest().andReturn(resp2).times(minTimes,maxTimes); - } + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(authorizedResponse); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); - verifyMocks(); + + Mockito.verify(mockExecChain, Mockito.atLeast(1 + minTimes)).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(mockExecChain, Mockito.atMost(1 + maxTimes)).proceed(Mockito.any(), Mockito.any()); } } @@ -4580,25 +4124,26 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); req1.setHeader("Authorization",authorization1); - backendExpectsAnyRequestAndReturn(authorizedResponse); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Authorization",authorization2); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(authorizedResponse); - replayMocks(); execute(req1); - execute(req2); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(reqCapture.capture(), Mockito.any()); + + final List allRequests = reqCapture.getAllValues(); + Assert.assertEquals(2, allRequests.size()); + + final ClassicHttpRequest captured = allRequests.get(1); Assert.assertEquals(HttpTestUtils.getCanonicalHeaderValue(req2, "Authorization"), HttpTestUtils.getCanonicalHeaderValue(captured, "Authorization")); } @@ -4651,24 +4196,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Cache-Control","max-age=5"); resp1.setHeader("Etag","\"etag\""); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control","max-stale=60"); - final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2).times(0,1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (!cap.hasCaptured()) { + final ClassicHttpResponse result = execute(req2); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.atMostOnce()).proceed(reqCapture.capture(), Mockito.any()); + + final List allRequests = reqCapture.getAllValues(); + if (allRequests.isEmpty()) { boolean found110Warning = false; final Iterator it = MessageSupport.iterate(result, HttpHeaders.WARNING); while (it.hasNext()) { @@ -4691,20 +4232,19 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testDoesNotTransmitNoCacheDirectivesWithFieldsDownstream() throws Exception { request.setHeader("Cache-Control","no-cache=\"X-Field\""); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect(mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse).times(0,1); - replayMocks(); try { execute(request); } catch (final ClientProtocolException acceptable) { } - verifyMocks(); - if (cap.hasCaptured()) { - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.atMostOnce()).proceed(reqCapture.capture(), Mockito.any()); + + final List allRequests = reqCapture.getAllValues(); + + if (!allRequests.isEmpty()) { + final ClassicHttpRequest captured = reqCapture.getValue(); final Iterator it = MessageSupport.iterate(captured, HttpHeaders.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); @@ -4727,24 +4267,24 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("Etag","\"etag\""); resp1.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + + execute(req1); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Etag","\"etag2\""); resp2.setHeader("Cache-Control","max-age=1200"); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect(mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); - execute(req1); final ClassicHttpResponse result = execute(req); - verifyMocks(); Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result)); - final ClassicHttpRequest captured = cap.getValue(); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); Assert.assertTrue(HttpTestUtils.equivalent(req, captured)); } @@ -4775,27 +4315,25 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse staleResponse) throws Exception { final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); - backendExpectsAnyRequestAndReturn(staleResponse); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control","max-stale=3600"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag2\""); resp2.setHeader("Cache-Control","max-age=5, must-revalidate"); - final Capture cap = EasyMock.newCapture(); // this request MUST happen - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(staleResponse); - replayMocks(); execute(req1); - execute(req2); - verifyMocks(); - final ClassicHttpRequest reval = cap.getValue(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + execute(req2); + + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.times(2)).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest reval = reqCapture.getValue(); boolean foundMaxAge0 = false; final Iterator it = MessageSupport.iterate(reval, HttpHeaders.CACHE_CONTROL); while (it.hasNext()) { @@ -4829,16 +4367,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpResponse staleResponse) throws Exception { final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); - backendExpectsAnyRequestAndReturn(staleResponse); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); - backendExpectsAnyRequest().andThrow(new SocketTimeoutException()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(staleResponse); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new SocketTimeoutException()); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); Assert.assertEquals(HttpStatus.SC_GATEWAY_TIMEOUT, result.getCode()); @@ -4898,47 +4435,46 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testCacheControlPrivateIsNotCacheableBySharedCache() throws Exception { - if (config.isSharedCache()) { - final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); - resp1.setHeader("Cache-Control","private,max-age=3600"); + if (config.isSharedCache()) { + final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); + final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("Cache-Control", "private,max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - // this backend request MUST happen - backendExpectsAnyRequestAndReturn(resp2); + final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); + final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); + // this backend request MUST happen + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); - execute(req1); - execute(req2); - verifyMocks(); - } + execute(req1); + execute(req2); + } } @Test public void testCacheControlPrivateOnFieldIsNotReturnedBySharedCache() throws Exception { - if (config.isSharedCache()) { - final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); - resp1.setHeader("X-Personal","stuff"); - resp1.setHeader("Cache-Control","private=\"X-Personal\",s-maxage=3600"); + if (config.isSharedCache()) { + final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET", "/"); + final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("X-Personal", "stuff"); + resp1.setHeader("Cache-Control", "private=\"X-Personal\",s-maxage=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); - final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); + final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); + final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - // this backend request MAY happen - backendExpectsAnyRequestAndReturn(resp2).times(0,1); + // this backend request MAY happen + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); - execute(req1); - final ClassicHttpResponse result = execute(req2); - verifyMocks(); - Assert.assertNull(result.getFirstHeader("X-Personal")); - } + execute(req1); + final ClassicHttpResponse result = execute(req2); + Assert.assertNull(result.getFirstHeader("X-Personal")); + + Mockito.verify(mockExecChain, Mockito.atLeastOnce()).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(Mockito.any(), Mockito.any()); + } } /* "If the no-cache directive does not specify a field-name, then a @@ -4956,18 +4492,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","no-cache"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); // this MUST happen - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } @Test @@ -4977,19 +4511,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","no-cache,s-maxage=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control","max-stale=7200"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); // this MUST happen - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } /* "If the no-cache directive does specify one or more field-names, then @@ -5006,7 +4538,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp1.setHeader("X-Stuff","things"); resp1.setHeader("Cache-Control","no-cache=\"X-Stuff\", max-age=3600"); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); @@ -5014,18 +4546,16 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("X-Stuff","things"); resp2.setHeader("Cache-Control","no-cache=\"X-Stuff\",max-age=3600"); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(resp2).times(0,1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); - if (!cap.hasCaptured()) { + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(reqCapture.capture(), Mockito.any()); + + final List allRequests = reqCapture.getAllValues(); + if (allRequests.isEmpty()) { Assert.assertNull(result.getFirstHeader("X-Stuff")); } } @@ -5047,47 +4577,43 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testNoStoreOnRequestIsNotStoredInCache() throws Exception { - emptyMockCacheExpectsNoPuts(); request.setHeader("Cache-Control","no-store"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); + + Mockito.verifyNoInteractions(mockCache); } @Test public void testNoStoreOnRequestIsNotStoredInCacheEvenIfResponseMarkedCacheable() throws Exception { - emptyMockCacheExpectsNoPuts(); request.setHeader("Cache-Control","no-store"); originResponse.setHeader("Cache-Control","max-age=3600"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); + + Mockito.verifyNoInteractions(mockCache); } @Test public void testNoStoreOnResponseIsNotStoredInCache() throws Exception { - emptyMockCacheExpectsNoPuts(); originResponse.setHeader("Cache-Control","no-store"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); + + Mockito.verifyNoInteractions(mockCache); } @Test public void testNoStoreOnResponseIsNotStoredInCacheEvenWithContraryIndicators() throws Exception { - emptyMockCacheExpectsNoPuts(); originResponse.setHeader("Cache-Control","no-store,max-age=3600"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); + + Mockito.verifyNoInteractions(mockCache); } /* "If multiple encodings have been applied to an entity, the content @@ -5099,11 +4625,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testOrderOfMultipleContentEncodingHeaderValuesIsPreserved() throws Exception { originResponse.addHeader("Content-Encoding","gzip"); originResponse.addHeader("Content-Encoding","deflate"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); int total_encodings = 0; final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_ENCODING); while (it.hasNext()) { @@ -5126,11 +4650,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testOrderOfMultipleParametersInContentEncodingHeaderIsPreserved() throws Exception { originResponse.addHeader("Content-Encoding","gzip,deflate"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); int total_encodings = 0; final Iterator it = MessageSupport.iterate(result, HttpHeaders.CONTENT_ENCODING); while (it.hasNext()) { @@ -5169,13 +4691,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { resp2.setHeader("Cache-Control","public,max-age=3600"); resp2.setHeader("Etag","\"etag\""); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } /* "A received message that does not have a Date header field MUST be @@ -5190,11 +4710,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Cache-Control","public"); originResponse.setHeader("ETag","\"etag\""); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertNotNull(result.getFirstHeader("Date")); } @@ -5216,14 +4734,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); // second request to origin MUST happen - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } @Test @@ -5252,14 +4768,12 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); - backendExpectsAnyRequestAndReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); // second request to origin MUST happen - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); execute(req2); - verifyMocks(); } /* "If the response is being forwarded through a proxy, the proxy @@ -5272,11 +4786,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final String server = "MockServer/1.0"; originResponse.setHeader("Server", server); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(server, result.getFirstHeader("Server").getValue()); } @@ -5290,11 +4802,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Transfer-Encoding","chunked"); originResponse.addHeader("Transfer-Encoding","x-transfer"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); int transfer_encodings = 0; final Iterator it = MessageSupport.iterate(result, HttpHeaders.TRANSFER_ENCODING); while (it.hasNext()) { @@ -5318,11 +4828,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testOrderOfMultipleTransferEncodingsInSingleHeadersIsPreserved() throws Exception { originResponse.addHeader("Transfer-Encoding","chunked, x-transfer"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); int transfer_encodings = 0; final Iterator it = MessageSupport.iterate(result, HttpHeaders.TRANSFER_ENCODING); while (it.hasNext()) { @@ -5357,11 +4865,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Vary","User-Agent"); originResponse.setHeader("ETag","\"etag\""); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); final Iterator it = MessageSupport.iterate(result, HttpHeaders.VARY); while (it.hasNext()) { final HeaderElement elt = it.next(); @@ -5378,18 +4884,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testProperlyFormattedViaHeaderIsAddedToRequests() throws Exception { - final Capture cap = EasyMock.newCapture(); request.removeHeaders("Via"); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); execute(request); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); final String via = captured.getFirstHeader("Via").getValue(); assertValidViaHeader(via); } @@ -5397,10 +4900,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testProperlyFormattedViaHeaderIsAddedToResponses() throws Exception { originResponse.removeHeaders("Via"); - backendExpectsAnyRequest().andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); assertValidViaHeader(result.getFirstHeader("Via").getValue()); } @@ -5479,17 +4980,15 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originalRequest.setVersion(HttpVersion.HTTP_1_0); request = originalRequest; request.removeHeaders("Via"); - final Capture cap = EasyMock.newCapture(); - EasyMock.expect( - mockExecChain.proceed( - EasyMock.capture(cap), - EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + execute(request); - verifyMocks(); - final ClassicHttpRequest captured = cap.getValue(); + final ArgumentCaptor reqCapture = ArgumentCaptor.forClass(ClassicHttpRequest.class); + Mockito.verify(mockExecChain).proceed(reqCapture.capture(), Mockito.any()); + + final ClassicHttpRequest captured = reqCapture.getValue(); final String via = captured.getFirstHeader("Via").getValue(); final String protocol = via.split("\\s+")[0]; final String[] protoParts = protocol.split("/"); @@ -5505,11 +5004,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content"); originResponse.setVersion(HttpVersion.HTTP_1_0); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); final String via = result.getFirstHeader("Via").getValue(); final String protocol = via.split("\\s+")[0]; @@ -5532,11 +5029,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.removeHeaders("Warning"); final String warning = "199 fred \"misc\""; originResponse.addHeader("Warning", warning); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); Assert.assertEquals(warning, result.getFirstHeader("Warning").getValue()); } @@ -5569,13 +5064,11 @@ public class TestProtocolRequirements extends AbstractProtocolTest { final String newWarning = "113 betty \"stale too\""; resp2.setHeader("Warning", newWarning); - backendExpectsAnyRequestAndReturn(resp1); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); - replayMocks(); execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); boolean oldWarningFound = false; boolean newWarningFound = false; @@ -5607,10 +5100,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setVersion(HttpVersion.HTTP_1_0); originResponse.addHeader("Warning", origWarning); originResponse.setHeader("Date", dateHdr); - backendExpectsAnyRequest().andReturn(originResponse); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); final ClassicHttpResponse result = execute(request); - verifyMocks(); // note that currently the implementation acts as an HTTP/1.1 proxy, // which means that all the responses from the caching module should // be HTTP/1.1, so we won't actually be testing anything here until @@ -5649,11 +5140,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Warning", "110 fred \"stale\", 110 wilma \"stale\" \"" + DateUtils.formatDate(tenSecondsAgo) + "\""); originResponse.setHeader("Cache-Control","no-cache,no-store"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); for(final Header h : result.getHeaders("Warning")) { Assert.assertFalse(h.getValue().contains("wilma")); @@ -5668,11 +5157,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.addHeader("Warning", "110 fred \"stale\", 110 wilma \"stale\" \"" + DateUtils.formatDate(tenSecondsAgo) + "\""); originResponse.setHeader("Cache-Control","public,max-age=3600"); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); for(final Header h : result.getHeaders("Warning")) { Assert.assertFalse(h.getValue().contains("wilma")); @@ -5686,11 +5173,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest { originResponse.setHeader("Date", DateUtils.formatDate(now)); originResponse.addHeader("Warning", "110 wilma \"stale\" \"" + DateUtils.formatDate(tenSecondsAgo) + "\""); - backendExpectsAnyRequest().andReturn(originResponse); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); - replayMocks(); final ClassicHttpResponse result = execute(request); - verifyMocks(); final Header[] warningHeaders = result.getHeaders("Warning"); Assert.assertTrue(warningHeaders == null || warningHeaders.length == 0); diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestRFC5861Compliance.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestRFC5861Compliance.java index c1cd83bb0..c40fe4a5b 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestRFC5861Compliance.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestRFC5861Compliance.java @@ -31,37 +31,90 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.util.Date; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.classic.ExecChain; +import org.apache.hc.client5.http.classic.ExecRuntime; import org.apache.hc.client5.http.impl.schedule.ImmediateSchedulingStrategy; +import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; -import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /** * A suite of acceptance tests for compliance with RFC5861, which * describes the stale-if-error and stale-while-revalidate * Cache-Control extensions. */ -public class TestRFC5861Compliance extends AbstractProtocolTest { +@RunWith(MockitoJUnitRunner.class) +public class TestRFC5861Compliance { - private ScheduledExecutorService executorService; + static final int MAX_BYTES = 1024; + static final int MAX_ENTRIES = 100; + static final int ENTITY_LENGTH = 128; + + HttpHost host; + HttpRoute route; + HttpEntity body; + HttpClientContext context; + @Mock + ExecChain mockExecChain; + @Mock + ExecRuntime mockExecRuntime; + @Mock + HttpCache mockCache; + ClassicHttpRequest request; + ClassicHttpResponse originResponse; + CacheConfig config; + CachingExec impl; + HttpCache cache; + ScheduledExecutorService executorService; @Before - public void setup() { + public void setUp() throws Exception { + host = new HttpHost("foo.example.com", 80); + + route = new HttpRoute(host); + + body = HttpTestUtils.makeBody(ENTITY_LENGTH); + + request = new BasicClassicHttpRequest("GET", "/foo"); + + context = HttpClientContext.create(); + + originResponse = HttpTestUtils.make200Response(); + + config = CacheConfig.custom() + .setMaxCacheEntries(MAX_ENTRIES) + .setMaxObjectSize(MAX_BYTES) + .build(); + + cache = new BasicHttpCache(config); + impl = new CachingExec(cache, null, config); + executorService = new ScheduledThreadPoolExecutor(1); - EasyMock.expect(mockExecRuntime.fork(null)).andReturn(mockExecRuntime).anyTimes(); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse); + Mockito.when(mockExecRuntime.fork(null)).thenReturn(mockExecRuntime); } @After @@ -69,16 +122,11 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { executorService.shutdownNow(); } - @Override - protected void replayMocks() { - super.replayMocks(); - EasyMock.replay(mockExecRuntime); - } - - @Override - protected void verifyMocks() { - super.verifyMocks(); - EasyMock.verify(mockExecRuntime); + public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException { + return impl.execute( + ClassicRequestBuilder.copy(request).build(), + new ExecChain.Scope("test", route, request, mockExecRuntime, context), + mockExecChain); } /* @@ -104,17 +152,16 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); HttpTestUtils.assert110WarningFound(result); } @@ -127,8 +174,6 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); final byte[] body101 = HttpTestUtils.getRandomBytes(101); @@ -137,12 +182,13 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final HttpEntity entity = new InputStreamEntity(cis, 101, null); resp2.setEntity(entity); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + execute(req2); - verifyMocks(); assertTrue(cis.wasClosed()); } @@ -155,17 +201,16 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60, must-revalidate"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getCode()); } @@ -179,17 +224,16 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60, proxy-revalidate"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getCode()); } @@ -206,17 +250,16 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60, proxy-revalidate"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); HttpTestUtils.assert110WarningFound(result); } @@ -229,18 +272,17 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=60"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control","min-fresh=2"); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertTrue(HttpStatus.SC_OK != result.getCode()); } @@ -253,18 +295,17 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control","public, stale-if-error=60"); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); HttpTestUtils.assert110WarningFound(result); } @@ -278,18 +319,17 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control", "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control", "public, stale-if-error=60"); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); HttpTestUtils.assert110WarningFound(result); } @@ -303,17 +343,16 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5, stale-if-error=2"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, result.getCode()); @@ -328,21 +367,19 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { final ClassicHttpResponse resp1 = HttpTestUtils.make200Response(tenSecondsAgo, "public, max-age=5"); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = HttpTestUtils.makeDefaultRequest(); req2.setHeader("Cache-Control","stale-if-error=2"); final ClassicHttpResponse resp2 = HttpTestUtils.make500Response(); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); - final ClassicHttpResponse result = execute(req2); - verifyMocks(); - assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, - result.getCode()); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + + final ClassicHttpResponse result = execute(req2); + + assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, result.getCode()); } /* @@ -372,14 +409,12 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1).times(1,2); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getCode()); boolean warning110Found = false; @@ -392,6 +427,9 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { } } assertTrue(warning110Found); + + Mockito.verify(mockExecChain, Mockito.atLeastOnce()).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -409,14 +447,12 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15"); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1).times(1, 2); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getCode()); boolean warning110Found = false; @@ -429,6 +465,9 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { } } assertTrue(warning110Found); + + Mockito.verify(mockExecChain, Mockito.atLeastOnce()).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(Mockito.any(), Mockito.any()); } @Test @@ -451,15 +490,13 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1).times(1,2); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("If-None-Match","\"etag\""); - replayMocks(); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); + execute(req1); final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_NOT_MODIFIED, result.getCode()); boolean warning110Found = false; @@ -472,8 +509,10 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { } } assertTrue(warning110Found); - } + Mockito.verify(mockExecChain, Mockito.atLeastOnce()).proceed(Mockito.any(), Mockito.any()); + Mockito.verify(mockExecChain, Mockito.atMost(2)).proceed(Mockito.any(), Mockito.any()); + } @Test public void testStaleWhileRevalidateYieldsToMustRevalidate() @@ -495,20 +534,19 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, must-revalidate"); resp2.setHeader("ETag","\"etag\""); resp2.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getCode()); boolean warning110Found = false; @@ -544,20 +582,19 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control", "public, max-age=5, stale-while-revalidate=15, proxy-revalidate"); resp2.setHeader("ETag","\"etag\""); resp2.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getCode()); boolean warning110Found = false; @@ -593,8 +630,6 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); - backendExpectsAnyRequestAndReturn(resp1); - final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET", "/"); req2.setHeader("Cache-Control","min-fresh=2"); final ClassicHttpResponse resp2 = HttpTestUtils.make200Response(); @@ -602,12 +637,13 @@ public class TestRFC5861Compliance extends AbstractProtocolTest { resp2.setHeader("ETag","\"etag\""); resp2.setHeader("Date", DateUtils.formatDate(now)); - backendExpectsAnyRequestAndReturn(resp2); + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp1); - replayMocks(); execute(req1); + + Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(resp2); + final ClassicHttpResponse result = execute(req2); - verifyMocks(); assertEquals(HttpStatus.SC_OK, result.getCode()); boolean warning110Found = false; diff --git a/pom.xml b/pom.xml index 9f7a8d20a..f49b93e5a 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,6 @@ 2.12.3 1.7.25 4.13 - 3.6 3.10.0 5.2.0 1 @@ -189,12 +188,6 @@ ${mockito.version} test - - org.easymock - easymock - ${easymock.version} - test -