You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2010/04/30 23:00:10 UTC

svn commit: r939814 [6/6] - in /httpcomponents/httpclient/trunk: ./ httpclient-cache/ httpclient-cache/src/ httpclient-cache/src/main/ httpclient-cache/src/main/java/ httpclient-cache/src/main/java/org/ httpclient-cache/src/main/java/org/apache/ httpcl...

Added: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCache.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCache.java?rev=939814&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCache.java (added)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCache.java Fri Apr 30 21:00:08 2010
@@ -0,0 +1,163 @@
+/*
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.client.cache.impl;
+
+import org.apache.http.client.cache.HttpCacheOperationException;
+import org.apache.http.client.cache.HttpCacheUpdateCallback;
+import org.apache.http.client.cache.impl.BasicHttpCache;
+import org.apache.http.client.cache.impl.CacheEntry;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestResponseCache {
+
+    private BasicHttpCache cache;
+
+    @Before
+    public void setUp() {
+        cache = new BasicHttpCache(5);
+    }
+
+    @Test
+    public void testEntryRemainsInCacheWhenPutThere() {
+        CacheEntry entry = new CacheEntry();
+        cache.putEntry("foo", entry);
+
+        CacheEntry cachedEntry = cache.getEntry("foo");
+
+        Assert.assertSame(entry, cachedEntry);
+    }
+
+    @Test
+    public void testRemovedEntriesDoNotExistAnymore() {
+        CacheEntry entry = new CacheEntry();
+        cache.putEntry("foo", entry);
+
+        cache.removeEntry("foo");
+
+        CacheEntry nullEntry = cache.getEntry("foo");
+
+        Assert.assertNull(nullEntry);
+    }
+
+    @Test
+    public void testCacheHoldsNoMoreThanSpecifiedMaxEntries() {
+        BasicHttpCache cache = new BasicHttpCache(1);
+
+        CacheEntry entry1 = new CacheEntry();
+        cache.putEntry("foo", entry1);
+
+        CacheEntry entry2 = new CacheEntry();
+        cache.putEntry("bar", entry2);
+
+        CacheEntry entry3 = new CacheEntry();
+        cache.putEntry("baz", entry3);
+
+        CacheEntry e1 = cache.getEntry("foo");
+        Assert.assertNull("Got foo entry when we should not", e1);
+
+        CacheEntry e2 = cache.getEntry("bar");
+        Assert.assertNull("Got bar entry when we should not", e2);
+
+        CacheEntry e3 = cache.getEntry("baz");
+        Assert.assertNotNull("Did not get baz entry, but should have", e3);
+    }
+
+    @Test
+    public void testSmallCacheKeepsMostRecentlyUsedEntry() {
+
+        final int max_size = 3;
+        BasicHttpCache cache = new BasicHttpCache(max_size);
+
+        // fill the cache with entries
+        for (int i = 0; i < max_size; i++) {
+            CacheEntry entry = new CacheEntry();
+            cache.putEntry("entry" + i, entry);
+        }
+
+        // read the eldest entry to make it the MRU entry
+        cache.getEntry("entry0");
+
+        // add another entry, which kicks out the eldest (should be the 2nd one
+        // created), and becomes the new MRU entry
+        CacheEntry newMru = new CacheEntry();
+        cache.putEntry("newMru", newMru);
+
+        // get the original second eldest
+        CacheEntry gone = cache.getEntry("entry1");
+        Assert.assertNull("entry1 should be gone", gone);
+
+        CacheEntry latest = cache.getEntry("newMru");
+        Assert.assertNotNull("latest entry should still be there", latest);
+
+        CacheEntry originalEldest = cache.getEntry("entry0");
+        Assert.assertNotNull("original eldest entry should still be there", originalEldest);
+    }
+
+    @Test
+    public void testZeroMaxSizeCacheDoesNotStoreAnything() {
+        BasicHttpCache cache = new BasicHttpCache(0);
+
+        CacheEntry entry = new CacheEntry();
+        cache.putEntry("foo", entry);
+
+        CacheEntry gone = cache.getEntry("foo");
+
+        Assert.assertNull("This cache should not have anything in it!", gone);
+    }
+
+    @Test
+    public void testCacheEntryCallbackUpdatesCacheEntry() throws HttpCacheOperationException {
+
+        final byte[] expectedArray = new byte[] { 1, 2, 3, 4, 5 };
+
+        CacheEntry entry = new CacheEntry();
+        CacheEntry entry2 = new CacheEntry();
+
+        cache.putEntry("foo", entry);
+        cache.putEntry("bar", entry2);
+
+        cache.updateCacheEntry("foo", new HttpCacheUpdateCallback<CacheEntry>() {
+
+            public CacheEntry getUpdatedEntry(CacheEntry existing) {
+                existing.setBody(expectedArray);
+
+                cache.removeEntry("bar");
+                return existing;
+            }
+        });
+
+        CacheEntry afterUpdate = cache.getEntry("foo");
+        CacheEntry bar = cache.getEntry("bar");
+
+        Assert.assertNull(bar);
+
+        Assert.assertArrayEquals(expectedArray, afterUpdate.getBody());
+    }
+
+}

Added: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCachingPolicy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCachingPolicy.java?rev=939814&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCachingPolicy.java (added)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestResponseCachingPolicy.java Fri Apr 30 21:00:08 2010
@@ -0,0 +1,331 @@
+/*
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.client.cache.impl;
+
+import java.util.Date;
+import java.util.Random;
+
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.client.cache.impl.ResponseCachingPolicy;
+import org.apache.http.impl.cookie.DateUtils;
+import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.message.BasicHttpResponse;
+import org.apache.http.message.BasicStatusLine;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestResponseCachingPolicy {
+
+    private static final ProtocolVersion PROTOCOL_VERSION = new ProtocolVersion("HTTP", 1, 1);
+    private ResponseCachingPolicy policy;
+    private HttpResponse response;
+    private HttpRequest request;
+    private int[] acceptableCodes = new int[] { HttpStatus.SC_OK,
+            HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION, HttpStatus.SC_MULTIPLE_CHOICES,
+            HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_GONE };
+
+    @Before
+    public void setUp() throws Exception {
+        policy = new ResponseCachingPolicy(0);
+        response = new BasicHttpResponse(
+                new BasicStatusLine(PROTOCOL_VERSION, HttpStatus.SC_OK, ""));
+        response.setHeader("Date", DateUtils.formatDate(new Date()));
+        response.setHeader("Content-Length", "0");
+    }
+
+    @Test
+    public void testIsGetCacheable() {
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void test203ResponseCodeIsCacheable() {
+        response.setStatusCode(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION);
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void test206ResponseCodeIsNotCacheable() {
+        response.setStatusCode(HttpStatus.SC_PARTIAL_CONTENT);
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void test300ResponseCodeIsCacheable() {
+        response.setStatusCode(HttpStatus.SC_MULTIPLE_CHOICES);
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void test301ResponseCodeIsCacheable() {
+        response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY);
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void test410ResponseCodeIsCacheable() {
+        response.setStatusCode(HttpStatus.SC_GONE);
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testPlain302ResponseCodeIsNotCacheable() {
+        response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
+        response.removeHeaders("Expires");
+        response.removeHeaders("Cache-Control");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testPlain307ResponseCodeIsNotCacheable() {
+        response.setStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT);
+        response.removeHeaders("Expires");
+        response.removeHeaders("Cache-Control");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testNon206WithExplicitExpiresIsCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Expires", DateUtils.formatDate(new Date()));
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testNon206WithMaxAgeIsCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Cache-Control", "max-age=0");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testNon206WithSMaxAgeIsCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Cache-Control", "s-maxage=0");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testNon206WithMustRevalidateIsCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Cache-Control", "must-revalidate");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testNon206WithProxyRevalidateIsCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Cache-Control", "proxy-revalidate");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testNon206WithPublicCacheControlIsCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Cache-Control", "public");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    // are we truly a non-shared cache? best be safe
+    @Test
+    public void testNon206WithPrivateCacheControlIsNotCacheable() {
+        int status = getRandomStatus();
+        response.setStatusCode(status);
+        response.setHeader("Cache-Control", "private");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithNoCacheCacheable() {
+        response.addHeader("Cache-Control", "no-cache");
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithNoStoreCacheable() {
+        response.addHeader("Cache-Control", "no-store");
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithNoStoreEmbeddedInListCacheable() {
+        response.addHeader("Cache-Control", "public, no-store");
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithNoCacheEmbeddedInListCacheable() {
+        response.addHeader("Cache-Control", "public, no-cache");
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithNoCacheEmbeddedInListAfterFirstHeaderCacheable() {
+        response.addHeader("Cache-Control", "max-age=20");
+        response.addHeader("Cache-Control", "public, no-cache");
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithNoStoreEmbeddedInListAfterFirstHeaderCacheable() {
+        response.addHeader("Cache-Control", "max-age=20");
+        response.addHeader("Cache-Control", "public, no-store");
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithAnyCacheControlCacheable() {
+        response.addHeader("Cache-Control", "max=10");
+
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+
+        response = new BasicHttpResponse(
+                new BasicStatusLine(PROTOCOL_VERSION, HttpStatus.SC_OK, ""));
+        response.setHeader("Date", DateUtils.formatDate(new Date()));
+        response.addHeader("Cache-Control", "no-transform");
+        response.setHeader("Content-Length", "0");
+
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithout200Cacheable() {
+        HttpResponse response = new BasicHttpResponse(new BasicStatusLine(PROTOCOL_VERSION,
+                HttpStatus.SC_NOT_FOUND, ""));
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+
+        response = new BasicHttpResponse(new BasicStatusLine(PROTOCOL_VERSION,
+                HttpStatus.SC_GATEWAY_TIMEOUT, ""));
+
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testVaryStarIsNotCacheable() {
+        response.setHeader("Vary", "*");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsGetWithVaryHeaderCacheable() {
+        response.addHeader("Vary", "Accept-Encoding");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testIsArbitraryMethodCacheable() {
+
+        Assert.assertFalse(policy.isResponseCacheable("PUT", response));
+
+        Assert.assertFalse(policy.isResponseCacheable("get", response));
+    }
+
+    @Test
+    public void testResponsesWithMultipleAgeHeadersAreNotCacheable() {
+        response.addHeader("Age", "3");
+        response.addHeader("Age", "5");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponsesWithMultipleDateHeadersAreNotCacheable() {
+        Date now = new Date();
+        Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+        response.addHeader("Date", DateUtils.formatDate(now));
+        response.addHeader("Date", DateUtils.formatDate(sixSecondsAgo));
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponsesWithMalformedDateHeadersAreNotCacheable() {
+        response.addHeader("Date", "garbage");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponsesWithMultipleExpiresHeadersAreNotCacheable() {
+        Date now = new Date();
+        Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+        response.addHeader("Expires", DateUtils.formatDate(now));
+        response.addHeader("Expires", DateUtils.formatDate(sixSecondsAgo));
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponsesWithoutDateHeadersAreNotCacheable() {
+        response.removeHeaders("Date");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponseThatHasTooMuchContentIsNotCacheable() {
+        response.setHeader("Content-Length", "9000");
+        Assert.assertFalse(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponsesThatAreSmallEnoughAreCacheable() {
+        response.setHeader("Content-Length", "0");
+        Assert.assertTrue(policy.isResponseCacheable("GET", response));
+    }
+
+    @Test
+    public void testResponsesToGETWithQueryParamsButNoExplicitCachingAreNotCacheable() {
+        request = new BasicHttpRequest("GET", "/foo?s=bar");
+        Assert.assertFalse(policy.isResponseCacheable(request, response));
+    }
+
+    @Test
+    public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheable() {
+        request = new BasicHttpRequest("GET", "/foo?s=bar");
+        response.setHeader("Expires", DateUtils.formatDate(new Date()));
+        Assert.assertTrue(policy.isResponseCacheable(request, response));
+    }
+
+    private int getRandomStatus() {
+        int rnd = (new Random()).nextInt(acceptableCodes.length);
+
+        return acceptableCodes[rnd];
+    }
+}

Added: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestSizeLimitedResponseReader.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestSizeLimitedResponseReader.java?rev=939814&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestSizeLimitedResponseReader.java (added)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestSizeLimitedResponseReader.java Fri Apr 30 21:00:08 2010
@@ -0,0 +1,252 @@
+/*
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.client.cache.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.client.cache.impl.SizeLimitedResponseReader;
+import org.easymock.classextension.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSizeLimitedResponseReader {
+
+    private static final int MAX_SIZE = 4;
+
+    private SizeLimitedResponseReader impl;
+    private HttpResponse mockResponse;
+    private HttpEntity mockEntity;
+    private InputStream mockInputStream;
+    private ProtocolVersion mockVersion;
+
+    private boolean mockedImpl;
+
+    @Before
+    public void setUp() {
+        mockResponse = EasyMock.createMock(HttpResponse.class);
+        mockEntity = EasyMock.createMock(HttpEntity.class);
+        mockInputStream = EasyMock.createMock(InputStream.class);
+        mockVersion = EasyMock.createMock(ProtocolVersion.class);
+
+    }
+
+    @Test
+    public void testLargeResponseIsTooLarge() throws Exception {
+
+        responseHasValidEntity();
+        entityHasValidContentStream();
+        inputStreamReturnsValidBytes(5);
+
+        getReader();
+
+        replayMocks();
+        boolean tooLarge = impl.isResponseTooLarge();
+        byte[] result = impl.getResponseBytes();
+        verifyMocks();
+
+        Assert.assertTrue(tooLarge);
+
+        Assert.assertArrayEquals(new byte[] { 1, 1, 1, 1, 1 }, result);
+    }
+
+    @Test
+    public void testExactSizeResponseIsNotTooLarge() throws Exception {
+        responseHasValidEntity();
+        entityHasValidContentStream();
+        inputStreamReturnsValidBytes(4);
+        inputStreamReturnsEndOfStream();
+
+        getReader();
+        replayMocks();
+        boolean tooLarge = impl.isResponseTooLarge();
+        byte[] result = impl.getResponseBytes();
+        verifyMocks();
+
+        Assert.assertFalse(tooLarge);
+
+        Assert.assertArrayEquals(new byte[] { 1, 1, 1, 1 }, result);
+    }
+
+    @Test
+    public void testSmallResponseIsNotTooLarge() throws Exception {
+        responseHasValidEntity();
+        entityHasValidContentStream();
+
+        org.easymock.EasyMock.expect(mockInputStream.read()).andReturn(1).times(3);
+
+        org.easymock.EasyMock.expect(mockInputStream.read()).andReturn(-1).times(2);
+
+        getReader();
+        replayMocks();
+        boolean tooLarge = impl.isResponseTooLarge();
+        byte[] result = impl.getResponseBytes();
+        verifyMocks();
+
+        Assert.assertFalse(tooLarge);
+
+        Assert.assertArrayEquals(new byte[] { 1, 1, 1 }, result);
+    }
+
+    @Test
+    public void testResponseWithNoEntityIsNotTooLarge() throws Exception {
+        responseHasNullEntity();
+
+        getReader();
+        replayMocks();
+        boolean tooLarge = impl.isResponseTooLarge();
+        verifyMocks();
+
+        Assert.assertFalse(tooLarge);
+    }
+
+    @Test
+    public void testReconstructedSmallResponseHasCorrectLength() throws Exception {
+
+        byte[] expectedArray = new byte[] { 1, 1, 1, 1 };
+
+        InputStream stream = new ByteArrayInputStream(new byte[] {});
+
+        responseReturnsHeaders();
+        responseReturnsProtocolVersion();
+
+        getReader();
+        mockImplMethods("getResponseBytes", "getContentInputStream");
+        getContentInputStreamReturns(stream);
+        getResponseBytesReturns(expectedArray);
+        replayMocks();
+
+        HttpResponse response = impl.getReconstructedResponse();
+
+        verifyMocks();
+
+        Assert.assertNotNull("Response should not be null", response);
+        InputStream resultStream = response.getEntity().getContent();
+
+        byte[] buffer = new byte[expectedArray.length];
+        resultStream.read(buffer);
+
+        Assert.assertArrayEquals(expectedArray, buffer);
+    }
+
+    private void getContentInputStreamReturns(InputStream inputStream) {
+        org.easymock.EasyMock.expect(impl.getContentInputStream()).andReturn(inputStream);
+    }
+
+    @Test
+    public void testReconstructedLargeResponseHasCorrectLength() throws Exception {
+
+        byte[] expectedArray = new byte[] { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 };
+        byte[] arrayAfterConsumedBytes = new byte[] { 1, 1, 1, 1, 1, 1, 1 };
+        byte[] smallArray = new byte[] { 2, 2, 2, 2, };
+        InputStream is = new ByteArrayInputStream(arrayAfterConsumedBytes);
+
+        responseReturnsHeaders();
+        responseReturnsProtocolVersion();
+
+        getReader();
+        mockImplMethods("getResponseBytes", "getContentInputStream");
+        getResponseBytesReturns(smallArray);
+        getContentInputStreamReturns(is);
+
+        replayMocks();
+
+        HttpResponse response = impl.getReconstructedResponse();
+
+        verifyMocks();
+
+        InputStream resultStream = response.getEntity().getContent();
+
+        byte[] buffer = new byte[expectedArray.length];
+        resultStream.read(buffer);
+
+        Assert.assertArrayEquals(expectedArray, buffer);
+    }
+
+    private void getResponseBytesReturns(byte[] expectedArray) {
+        org.easymock.EasyMock.expect(impl.getResponseBytes()).andReturn(expectedArray);
+    }
+
+    private void responseReturnsHeaders() {
+        org.easymock.EasyMock.expect(mockResponse.getAllHeaders()).andReturn(new Header[] {});
+    }
+
+    private void entityHasValidContentStream() throws IOException {
+        org.easymock.EasyMock.expect(mockEntity.getContent()).andReturn(mockInputStream);
+    }
+
+    private void inputStreamReturnsEndOfStream() throws IOException {
+        org.easymock.EasyMock.expect(mockInputStream.read()).andReturn(-1);
+    }
+
+    private void responseHasValidEntity() {
+        org.easymock.EasyMock.expect(mockResponse.getEntity()).andReturn(mockEntity);
+    }
+
+    private void responseReturnsProtocolVersion() {
+        org.easymock.EasyMock.expect(mockResponse.getProtocolVersion()).andReturn(mockVersion);
+    }
+
+    private void inputStreamReturnsValidBytes(int times) throws IOException {
+        org.easymock.EasyMock.expect(mockInputStream.read()).andReturn(1).times(times);
+    }
+
+    private void responseHasNullEntity() {
+        org.easymock.EasyMock.expect(mockResponse.getEntity()).andReturn(null);
+    }
+
+    private void verifyMocks() {
+        EasyMock.verify(mockResponse, mockEntity, mockInputStream, mockVersion);
+        if (mockedImpl) {
+            EasyMock.verify(impl);
+        }
+    }
+
+    private void replayMocks() {
+        EasyMock.replay(mockResponse, mockEntity, mockInputStream, mockVersion);
+        if (mockedImpl) {
+            EasyMock.replay(impl);
+        }
+    }
+
+    private void getReader() throws IOException {
+        impl = new SizeLimitedResponseReader(MAX_SIZE, mockResponse);
+    }
+
+    private void mockImplMethods(String... methods) {
+        mockedImpl = true;
+        impl = EasyMock.createMockBuilder(SizeLimitedResponseReader.class).withConstructor(
+                MAX_SIZE, mockResponse).addMockedMethods(methods).createMock();
+    }
+
+}

Added: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestURIExtractor.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestURIExtractor.java?rev=939814&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestURIExtractor.java (added)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/client/cache/impl/TestURIExtractor.java Fri Apr 30 21:00:08 2010
@@ -0,0 +1,261 @@
+/*
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.client.cache.impl;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.client.cache.impl.CacheEntry;
+import org.apache.http.client.cache.impl.URIExtractor;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.message.BasicHttpRequest;
+import org.easymock.classextension.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestURIExtractor {
+
+    private static final BasicHttpRequest REQUEST_FULL_EPISODES = new BasicHttpRequest("GET",
+            "/full_episodes");
+    private static final BasicHttpRequest REQUEST_ROOT = new BasicHttpRequest("GET", "/");
+
+    URIExtractor extractor;
+    private HttpHost host;
+    private CacheEntry mockEntry;
+    private HttpRequest mockRequest;
+
+    @Before
+    public void setUp() throws Exception {
+        host = new HttpHost("foo.example.com");
+        mockEntry = EasyMock.createMock(CacheEntry.class);
+        mockRequest = EasyMock.createMock(HttpRequest.class);
+        extractor = new URIExtractor();
+    }
+
+    private void replayMocks() {
+        EasyMock.replay(mockEntry);
+        EasyMock.replay(mockRequest);
+    }
+
+    private void verifyMocks() {
+        EasyMock.verify(mockEntry);
+        EasyMock.verify(mockRequest);
+    }
+
+    @Test
+    public void testGetURIWithDefaultPortAndScheme() {
+        Assert.assertEquals("http://www.comcast.net/", extractor.getURI(new HttpHost(
+                "www.comcast.net"), REQUEST_ROOT));
+
+        Assert.assertEquals("http://www.fancast.com/full_episodes", extractor.getURI(new HttpHost(
+                "www.fancast.com"), REQUEST_FULL_EPISODES));
+    }
+
+    @Test
+    public void testGetURIWithDifferentScheme() {
+        Assert.assertEquals("https://www.comcast.net/", extractor.getURI(new HttpHost(
+                "www.comcast.net", -1, "https"), REQUEST_ROOT));
+
+        Assert.assertEquals("myhttp://www.fancast.com/full_episodes", extractor.getURI(
+                new HttpHost("www.fancast.com", -1, "myhttp"), REQUEST_FULL_EPISODES));
+    }
+
+    @Test
+    public void testGetURIWithDifferentPort() {
+        Assert.assertEquals("http://www.comcast.net:8080/", extractor.getURI(new HttpHost(
+                "www.comcast.net", 8080), REQUEST_ROOT));
+
+        Assert.assertEquals("http://www.fancast.com:9999/full_episodes", extractor.getURI(
+                new HttpHost("www.fancast.com", 9999), REQUEST_FULL_EPISODES));
+    }
+
+    @Test
+    public void testGetURIWithDifferentPortAndScheme() {
+        Assert.assertEquals("https://www.comcast.net:8080/", extractor.getURI(new HttpHost(
+                "www.comcast.net", 8080, "https"), REQUEST_ROOT));
+
+        Assert.assertEquals("myhttp://www.fancast.com:9999/full_episodes", extractor.getURI(
+                new HttpHost("www.fancast.com", 9999, "myhttp"), REQUEST_FULL_EPISODES));
+    }
+
+    @Test
+    public void testGetURIWithQueryParameters() {
+        Assert.assertEquals("http://www.comcast.net/?foo=bar", extractor.getURI(new HttpHost(
+                "www.comcast.net", -1, "http"), new BasicHttpRequest("GET", "/?foo=bar")));
+        Assert.assertEquals("http://www.fancast.com/full_episodes?foo=bar", extractor.getURI(
+                new HttpHost("www.fancast.com", -1, "http"), new BasicHttpRequest("GET",
+                        "/full_episodes?foo=bar")));
+    }
+
+    @Test
+    public void testGetVariantURIWithNoVaryHeaderReturnsNormalURI() {
+        final String theURI = "theURI";
+        Header[] noHdrs = new Header[0];
+        org.easymock.EasyMock.expect(mockEntry.getHeaders("Vary")).andReturn(noHdrs);
+        extractor = new URIExtractor() {
+            @Override
+            public String getURI(HttpHost h, HttpRequest req) {
+                Assert.assertSame(host, h);
+                Assert.assertSame(mockRequest, req);
+                return theURI;
+            }
+        };
+
+        replayMocks();
+        String result = extractor.getVariantURI(host, mockRequest, mockEntry);
+        verifyMocks();
+        Assert.assertSame(theURI, result);
+    }
+
+    @Test
+    public void testGetVariantURIWithSingleValueVaryHeaderPrepends() {
+        final String theURI = "theURI";
+        Header[] varyHeaders = { new BasicHeader("Vary", "Accept-Encoding") };
+        Header[] encHeaders = { new BasicHeader("Accept-Encoding", "gzip") };
+
+        extractor = new URIExtractor() {
+            @Override
+            public String getURI(HttpHost h, HttpRequest req) {
+                Assert.assertSame(host, h);
+                Assert.assertSame(mockRequest, req);
+                return theURI;
+            }
+        };
+        org.easymock.EasyMock.expect(mockEntry.getHeaders("Vary")).andReturn(varyHeaders);
+        org.easymock.EasyMock.expect(mockRequest.getHeaders("Accept-Encoding")).andReturn(
+                encHeaders);
+        replayMocks();
+
+        String result = extractor.getVariantURI(host, mockRequest, mockEntry);
+
+        verifyMocks();
+        Assert.assertEquals("{Accept-Encoding=gzip}" + theURI, result);
+    }
+
+    @Test
+    public void testGetVariantURIWithMissingRequestHeader() {
+        final String theURI = "theURI";
+        Header[] noHeaders = new Header[0];
+        Header[] varyHeaders = { new BasicHeader("Vary", "Accept-Encoding") };
+        extractor = new URIExtractor() {
+            @Override
+            public String getURI(HttpHost h, HttpRequest req) {
+                Assert.assertSame(host, h);
+                Assert.assertSame(mockRequest, req);
+                return theURI;
+            }
+        };
+        org.easymock.EasyMock.expect(mockEntry.getHeaders("Vary")).andReturn(varyHeaders);
+        org.easymock.EasyMock.expect(mockRequest.getHeaders("Accept-Encoding"))
+                .andReturn(noHeaders);
+        replayMocks();
+
+        String result = extractor.getVariantURI(host, mockRequest, mockEntry);
+
+        verifyMocks();
+        Assert.assertEquals("{Accept-Encoding=}" + theURI, result);
+    }
+
+    @Test
+    public void testGetVariantURIAlphabetizesWithMultipleVaryingHeaders() {
+        final String theURI = "theURI";
+        Header[] varyHeaders = { new BasicHeader("Vary", "User-Agent, Accept-Encoding") };
+        Header[] encHeaders = { new BasicHeader("Accept-Encoding", "gzip") };
+        Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") };
+        extractor = new URIExtractor() {
+            @Override
+            public String getURI(HttpHost h, HttpRequest req) {
+                Assert.assertSame(host, h);
+                Assert.assertSame(mockRequest, req);
+                return theURI;
+            }
+        };
+        org.easymock.EasyMock.expect(mockEntry.getHeaders("Vary")).andReturn(varyHeaders);
+        org.easymock.EasyMock.expect(mockRequest.getHeaders("Accept-Encoding")).andReturn(
+                encHeaders);
+        org.easymock.EasyMock.expect(mockRequest.getHeaders("User-Agent")).andReturn(uaHeaders);
+        replayMocks();
+
+        String result = extractor.getVariantURI(host, mockRequest, mockEntry);
+
+        verifyMocks();
+        Assert.assertEquals("{Accept-Encoding=gzip&User-Agent=browser}" + theURI, result);
+    }
+
+    @Test
+    public void testGetVariantURIHandlesMultipleVaryHeaders() {
+        final String theURI = "theURI";
+        Header[] varyHeaders = { new BasicHeader("Vary", "User-Agent"),
+                new BasicHeader("Vary", "Accept-Encoding") };
+        Header[] encHeaders = { new BasicHeader("Accept-Encoding", "gzip") };
+        Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") };
+        extractor = new URIExtractor() {
+            public String getURI(HttpHost h, HttpRequest req) {
+                Assert.assertSame(host, h);
+                Assert.assertSame(mockRequest, req);
+                return theURI;
+            }
+        };
+        EasyMock.expect(mockEntry.getHeaders("Vary")).andReturn(varyHeaders);
+        EasyMock.expect(mockRequest.getHeaders("Accept-Encoding")).andReturn(encHeaders);
+        EasyMock.expect(mockRequest.getHeaders("User-Agent")).andReturn(uaHeaders);
+        replayMocks();
+
+        String result = extractor.getVariantURI(host, mockRequest, mockEntry);
+
+        verifyMocks();
+        Assert.assertEquals("{Accept-Encoding=gzip&User-Agent=browser}" + theURI, result);
+    }
+
+    @Test
+    public void testGetVariantURIHandlesMultipleLineRequestHeaders() {
+        final String theURI = "theURI";
+        Header[] varyHeaders = { new BasicHeader("Vary", "User-Agent, Accept-Encoding") };
+        Header[] encHeaders = { new BasicHeader("Accept-Encoding", "gzip"),
+                new BasicHeader("Accept-Encoding", "deflate") };
+        Header[] uaHeaders = { new BasicHeader("User-Agent", "browser") };
+        extractor = new URIExtractor() {
+            public String getURI(HttpHost h, HttpRequest req) {
+                Assert.assertSame(host, h);
+                Assert.assertSame(mockRequest, req);
+                return theURI;
+            }
+        };
+        EasyMock.expect(mockEntry.getHeaders("Vary")).andReturn(varyHeaders);
+        EasyMock.expect(mockRequest.getHeaders("Accept-Encoding")).andReturn(encHeaders);
+        EasyMock.expect(mockRequest.getHeaders("User-Agent")).andReturn(uaHeaders);
+        replayMocks();
+
+        String result = extractor.getVariantURI(host, mockRequest, mockEntry);
+
+        verifyMocks();
+        Assert
+                .assertEquals("{Accept-Encoding=gzip%2C+deflate&User-Agent=browser}" + theURI,
+                        result);
+    }
+}

Modified: httpcomponents/httpclient/trunk/pom.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/pom.xml?rev=939814&r1=939813&r2=939814&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/pom.xml (original)
+++ httpcomponents/httpclient/trunk/pom.xml Fri Apr 30 21:00:08 2010
@@ -73,11 +73,13 @@
     <commons-codec.version>1.4</commons-codec.version>
     <mime4j.version>0.6</mime4j.version>
     <junit.version>4.8.1</junit.version>
+    <easymock.version>2.5.2</easymock.version>
   </properties>
 
   <modules>
     <module>httpclient</module>
     <module>httpmime</module>
+    <module>httpclient-cache</module>
     <module>httpclient-osgi</module>
   </modules>