diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/chromium/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp b/chromium/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp new file mode 100644 index 00000000000..b733023027c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2014, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "core/fetch/ImageResource.h" +#include "core/fetch/MemoryCache.h" +#include "core/fetch/Resource.h" +#include "core/fetch/ResourceFetcher.h" +#include "core/fetch/ResourcePtr.h" +#include "core/html/HTMLDocument.h" +#include "core/loader/DocumentLoader.h" +#include "platform/network/ResourceRequest.h" +#include "public/platform/Platform.h" +#include "wtf/OwnPtr.h" +#include "wtf/RefPtr.h" + +#include <gtest/gtest.h> + +using namespace WebCore; + +namespace { + +// An URL for the original request. +const char kResourceURL[] = "http://resource.com/"; + +// The origin time of our first request. +const char kOriginalRequestDateAsString[] = "Thu, 25 May 1977 18:30:00 GMT"; +const double kOriginalRequestDateAsDouble = 233433000.; + +const char kOneDayBeforeOriginalRequest[] = "Wed, 24 May 1977 18:30:00 GMT"; +const char kOneDayAfterOriginalRequest[] = "Fri, 26 May 1977 18:30:00 GMT"; + +const unsigned char kAConstUnsignedCharZero = 0; + +class CachingCorrectnessTest : public ::testing::Test { +protected: + void advanceClock(double seconds) + { + m_proxyPlatform.advanceClock(seconds); + } + + ResourcePtr<Resource> resourceFromResourceResponse(ResourceResponse response, Resource::Type type = Resource::Raw) + { + if (response.url().isNull()) + response.setURL(KURL(ParsedURLString, kResourceURL)); + ResourcePtr<Resource> resource = + new Resource(ResourceRequest(response.url()), type); + resource->setResponse(response); + memoryCache()->add(resource.get()); + + return resource; + } + + ResourcePtr<Resource> resourceFromResourceRequest(ResourceRequest request, Resource::Type type = Resource::Raw) + { + if (request.url().isNull()) + request.setURL(KURL(ParsedURLString, kResourceURL)); + ResourcePtr<Resource> resource = + new Resource(request, type); + resource->setResponse(ResourceResponse(KURL(ParsedURLString, kResourceURL), "text/html", 0, nullAtom, String())); + memoryCache()->add(resource.get()); + + return resource; + } + + ResourcePtr<Resource> fetch() + { + FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourceURL)), FetchInitiatorInfo()); + return m_fetcher->fetchSynchronously(fetchRequest); + } + + ResourcePtr<Resource> fetchImage() + { + FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourceURL)), FetchInitiatorInfo()); + return m_fetcher->fetchImage(fetchRequest); + } + + ResourceFetcher* fetcher() const { return m_fetcher.get(); } + +private: + // A simple platform that mocks out the clock, for cache freshness testing. + class ProxyPlatform : public blink::Platform { + public: + ProxyPlatform() : m_elapsedSeconds(0.) { } + + void advanceClock(double seconds) + { + m_elapsedSeconds += seconds; + } + + private: + // From blink::Platform: + virtual double currentTime() + { + return kOriginalRequestDateAsDouble + m_elapsedSeconds; + } + + // These blink::Platform methods must be overriden to make a usable object. + virtual void cryptographicallyRandomValues(unsigned char* buffer, size_t length) { ASSERT_NOT_REACHED(); } + virtual const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) + { + return &kAConstUnsignedCharZero; + } + + double m_elapsedSeconds; + }; + + virtual void SetUp() + { + m_savedPlatform = blink::Platform::current(); + blink::Platform::initialize(&m_proxyPlatform); + + // Save the global memory cache to restore it upon teardown. + m_globalMemoryCache = adoptPtr(memoryCache()); + // Create the test memory cache instance and hook it in. + m_testingMemoryCache = adoptPtr(new MemoryCache()); + setMemoryCacheForTesting(m_testingMemoryCache.leakPtr()); + + // Create a ResourceFetcher that has a real DocumentLoader and Document, but is not attached to a LocalFrame. + const KURL kDocumentURL(ParsedURLString, "http://document.com/"); + m_documentLoader = DocumentLoader::create(0, ResourceRequest(kDocumentURL), SubstituteData()); + m_document = HTMLDocument::create(); + m_fetcher = ResourceFetcher::create(m_documentLoader.get()); + m_fetcher->setDocument(m_document.get()); + } + + virtual void TearDown() + { + memoryCache()->evictResources(); + + // Regain the ownership of testing memory cache, so that it will be + // destroyed. + m_testingMemoryCache = adoptPtr(memoryCache()); + + // Yield the ownership of the global memory cache back. + setMemoryCacheForTesting(m_globalMemoryCache.leakPtr()); + + blink::Platform::initialize(m_savedPlatform); + } + + blink::Platform* m_savedPlatform; + ProxyPlatform m_proxyPlatform; + + OwnPtr<MemoryCache> m_testingMemoryCache; + OwnPtr<MemoryCache> m_globalMemoryCache; + + RefPtr<DocumentLoader> m_documentLoader; + + RefPtrWillBePersistent<HTMLDocument> m_document; + RefPtrWillBePersistent<ResourceFetcher> m_fetcher; +}; + +TEST_F(CachingCorrectnessTest, FreshFromLastModified) +{ + ResourceResponse fresh200Response; + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRequest); + + ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Response); + + // Advance the clock within the implicit freshness period of this resource before we make a request. + advanceClock(600.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_EQ(fresh200, fetched); +} + +TEST_F(CachingCorrectnessTest, FreshFromExpires) +{ + ResourceResponse fresh200Response; + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Response); + + // Advance the clock within the freshness period of this resource before we make a request. + advanceClock(24. * 60. * 60. - 15.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_EQ(fresh200, fetched); +} + +TEST_F(CachingCorrectnessTest, FreshFromMaxAge) +{ + ResourceResponse fresh200Response; + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Cache-Control", "max-age=600"); + + ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Response); + + // Advance the clock within the freshness period of this resource before we make a request. + advanceClock(500.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_EQ(fresh200, fetched); +} + +// The strong validator causes a revalidation to be launched, and the proxy and original resources leak because of their reference loop. +TEST_F(CachingCorrectnessTest, DISABLED_ExpiredFromLastModified) +{ + ResourceResponse expired200Response; + expired200Response.setHTTPStatusCode(200); + expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + expired200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRequest); + + ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response); + + // Advance the clock beyond the implicit freshness period. + advanceClock(24. * 60. * 60. * 0.2); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(expired200, fetched); +} + +TEST_F(CachingCorrectnessTest, ExpiredFromExpires) +{ + ResourceResponse expired200Response; + expired200Response.setHTTPStatusCode(200); + expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response); + + // Advance the clock within the expiredness period of this resource before we make a request. + advanceClock(24. * 60. * 60. + 15.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(expired200, fetched); +} + +// If the image hasn't been loaded in this "document" before, then it shouldn't have list of available images logic. +TEST_F(CachingCorrectnessTest, NewImageExpiredFromExpires) +{ + ResourceResponse expired200Response; + expired200Response.setHTTPStatusCode(200); + expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response, Resource::Image); + + // Advance the clock within the expiredness period of this resource before we make a request. + advanceClock(24. * 60. * 60. + 15.); + + ResourcePtr<Resource> fetched = fetchImage(); + EXPECT_NE(expired200, fetched); +} + +// If the image has been loaded in this "document" before, then it should have list of available images logic, and so +// normal cache testing should be bypassed. +TEST_F(CachingCorrectnessTest, ReuseImageExpiredFromExpires) +{ + ResourceResponse expired200Response; + expired200Response.setHTTPStatusCode(200); + expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response, Resource::Image); + + // Advance the clock within the freshness period, and make a request to add this image to the document resources. + advanceClock(15.); + ResourcePtr<Resource> firstFetched = fetchImage(); + EXPECT_EQ(expired200, firstFetched); + + // Advance the clock within the expiredness period of this resource before we make a request. + advanceClock(24. * 60. * 60. + 15.); + + ResourcePtr<Resource> fetched = fetchImage(); + EXPECT_EQ(expired200, fetched); +} + +TEST_F(CachingCorrectnessTest, ExpiredFromMaxAge) +{ + ResourceResponse expired200Response; + expired200Response.setHTTPStatusCode(200); + expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + expired200Response.setHTTPHeaderField("Cache-Control", "max-age=600"); + + ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response); + + // Advance the clock within the expiredness period of this resource before we make a request. + advanceClock(700.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(expired200, fetched); +} + +TEST_F(CachingCorrectnessTest, FreshButNoCache) +{ + ResourceResponse fresh200NocacheResponse; + fresh200NocacheResponse.setHTTPStatusCode(200); + fresh200NocacheResponse.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200NocacheResponse.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + fresh200NocacheResponse.setHTTPHeaderField("Cache-Control", "no-cache"); + + ResourcePtr<Resource> fresh200Nocache = resourceFromResourceResponse(fresh200NocacheResponse); + + // Advance the clock within the freshness period of this resource before we make a request. + advanceClock(24. * 60. * 60. - 15.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(fresh200Nocache, fetched); +} + +TEST_F(CachingCorrectnessTest, RequestWithNoCahe) +{ + ResourceRequest noCacheRequest; + noCacheRequest.setHTTPHeaderField("Cache-Control", "no-cache"); + ResourcePtr<Resource> noCacheResource = resourceFromResourceRequest(noCacheRequest); + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(noCacheResource, fetched); +} + +TEST_F(CachingCorrectnessTest, FreshButNoStore) +{ + ResourceResponse fresh200NostoreResponse; + fresh200NostoreResponse.setHTTPStatusCode(200); + fresh200NostoreResponse.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200NostoreResponse.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + fresh200NostoreResponse.setHTTPHeaderField("Cache-Control", "no-store"); + + ResourcePtr<Resource> fresh200Nostore = resourceFromResourceResponse(fresh200NostoreResponse); + + // Advance the clock within the freshness period of this resource before we make a request. + advanceClock(24. * 60. * 60. - 15.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(fresh200Nostore, fetched); +} + +TEST_F(CachingCorrectnessTest, RequestWithNoStore) +{ + ResourceRequest noStoreRequest; + noStoreRequest.setHTTPHeaderField("Cache-Control", "no-store"); + ResourcePtr<Resource> noStoreResource = resourceFromResourceRequest(noStoreRequest); + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(noStoreResource, fetched); +} + +// FIXME: Determine if ignoring must-revalidate for blink is correct behaviour. +// See crbug.com/340088 . +TEST_F(CachingCorrectnessTest, DISABLED_FreshButMustRevalidate) +{ + ResourceResponse fresh200MustRevalidateResponse; + fresh200MustRevalidateResponse.setHTTPStatusCode(200); + fresh200MustRevalidateResponse.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200MustRevalidateResponse.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + fresh200MustRevalidateResponse.setHTTPHeaderField("Cache-Control", "must-revalidate"); + + ResourcePtr<Resource> fresh200MustRevalidate = resourceFromResourceResponse(fresh200MustRevalidateResponse); + + // Advance the clock within the freshness period of this resource before we make a request. + advanceClock(24. * 60. * 60. - 15.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(fresh200MustRevalidate, fetched); +} + +TEST_F(CachingCorrectnessTest, FreshWithFreshRedirect) +{ + KURL redirectUrl(ParsedURLString, kResourceURL); + const char redirectTargetUrlString[] = "http://redirect-target.com"; + KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); + + ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw); + + ResourceResponse fresh301Response; + fresh301Response.setURL(redirectUrl); + fresh301Response.setHTTPStatusCode(301); + fresh301Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh301Response.setHTTPHeaderField("Location", redirectTargetUrlString); + fresh301Response.setHTTPHeaderField("Cache-Control", "max-age=600"); + + // Add the redirect to our request. + ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); + firstResource->willSendRequest(redirectRequest, fresh301Response); + + // Add the final response to our request. + ResourceResponse fresh200Response; + fresh200Response.setURL(redirectTargetUrl); + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + firstResource->setResponse(fresh200Response); + memoryCache()->add(firstResource.get()); + + advanceClock(500.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_EQ(firstResource, fetched); +} + +TEST_F(CachingCorrectnessTest, FreshWithStaleRedirect) +{ + KURL redirectUrl(ParsedURLString, kResourceURL); + const char redirectTargetUrlString[] = "http://redirect-target.com"; + KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); + + ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw); + + ResourceResponse stale301Response; + stale301Response.setURL(redirectUrl); + stale301Response.setHTTPStatusCode(301); + stale301Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + stale301Response.setHTTPHeaderField("Location", redirectTargetUrlString); + + // Add the redirect to our request. + ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); + firstResource->willSendRequest(redirectRequest, stale301Response); + + // Add the final response to our request. + ResourceResponse fresh200Response; + fresh200Response.setURL(redirectTargetUrl); + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + firstResource->setResponse(fresh200Response); + memoryCache()->add(firstResource.get()); + + advanceClock(500.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(firstResource, fetched); +} + +TEST_F(CachingCorrectnessTest, PostToSameURLTwice) +{ + ResourceRequest request1(KURL(ParsedURLString, kResourceURL)); + request1.setHTTPMethod("POST"); + ResourcePtr<Resource> resource1 = new Resource(ResourceRequest(request1.url()), Resource::Raw); + resource1->setLoading(true); + memoryCache()->add(resource1.get()); + + ResourceRequest request2(KURL(ParsedURLString, kResourceURL)); + request2.setHTTPMethod("POST"); + FetchRequest fetch2(request2, FetchInitiatorInfo()); + ResourcePtr<Resource> resource2 = fetcher()->fetchSynchronously(fetch2); + + EXPECT_EQ(resource2, memoryCache()->resourceForURL(request2.url())); + EXPECT_NE(resource1, resource2); +} + +TEST_F(CachingCorrectnessTest, 302RedirectNotImplicitlyFresh) +{ + KURL redirectUrl(ParsedURLString, kResourceURL); + const char redirectTargetUrlString[] = "http://redirect-target.com"; + KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); + + ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw); + + ResourceResponse fresh302Response; + fresh302Response.setURL(redirectUrl); + fresh302Response.setHTTPStatusCode(302); + fresh302Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh302Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRequest); + fresh302Response.setHTTPHeaderField("Location", redirectTargetUrlString); + + // Add the redirect to our request. + ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); + firstResource->willSendRequest(redirectRequest, fresh302Response); + + // Add the final response to our request. + ResourceResponse fresh200Response; + fresh200Response.setURL(redirectTargetUrl); + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + firstResource->setResponse(fresh200Response); + memoryCache()->add(firstResource.get()); + + advanceClock(500.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_NE(firstResource, fetched); +} + +TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshMaxAge) +{ + KURL redirectUrl(ParsedURLString, kResourceURL); + const char redirectTargetUrlString[] = "http://redirect-target.com"; + KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); + + ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw); + + ResourceResponse fresh302Response; + fresh302Response.setURL(redirectUrl); + fresh302Response.setHTTPStatusCode(302); + fresh302Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh302Response.setHTTPHeaderField("Cache-Control", "max-age=600"); + fresh302Response.setHTTPHeaderField("Location", redirectTargetUrlString); + + // Add the redirect to our request. + ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); + firstResource->willSendRequest(redirectRequest, fresh302Response); + + // Add the final response to our request. + ResourceResponse fresh200Response; + fresh200Response.setURL(redirectTargetUrl); + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + firstResource->setResponse(fresh200Response); + memoryCache()->add(firstResource.get()); + + advanceClock(500.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_EQ(firstResource, fetched); +} + +TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshExpires) +{ + KURL redirectUrl(ParsedURLString, kResourceURL); + const char redirectTargetUrlString[] = "http://redirect-target.com"; + KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); + + ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw); + + ResourceResponse fresh302Response; + fresh302Response.setURL(redirectUrl); + fresh302Response.setHTTPStatusCode(302); + fresh302Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh302Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + fresh302Response.setHTTPHeaderField("Location", redirectTargetUrlString); + + // Add the redirect to our request. + ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); + firstResource->willSendRequest(redirectRequest, fresh302Response); + + // Add the final response to our request. + ResourceResponse fresh200Response; + fresh200Response.setURL(redirectTargetUrl); + fresh200Response.setHTTPStatusCode(200); + fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); + fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); + + firstResource->setResponse(fresh200Response); + memoryCache()->add(firstResource.get()); + + advanceClock(500.); + + ResourcePtr<Resource> fetched = fetch(); + EXPECT_EQ(firstResource, fetched); +} + +} // namespace |