Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / fetch / CachingCorrectnessTest.cpp
blobc772cf3d04a3a2838a51cf73b1840bd1f92bd071
1 /*
2 * Copyright (c) 2014, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "config.h"
33 #include "core/fetch/FetchContext.h"
34 #include "core/fetch/ImageResource.h"
35 #include "core/fetch/MemoryCache.h"
36 #include "core/fetch/RawResource.h"
37 #include "core/fetch/Resource.h"
38 #include "core/fetch/ResourceFetcher.h"
39 #include "core/fetch/ResourcePtr.h"
40 #include "platform/network/ResourceRequest.h"
41 #include "public/platform/Platform.h"
42 #include "wtf/OwnPtr.h"
43 #include "wtf/RefPtr.h"
44 #include <gtest/gtest.h>
46 namespace blink {
48 // An URL for the original request.
49 const char kResourceURL[] = "http://resource.com/";
51 // The origin time of our first request.
52 const char kOriginalRequestDateAsString[] = "Thu, 25 May 1977 18:30:00 GMT";
53 const double kOriginalRequestDateAsDouble = 233433000.;
55 const char kOneDayBeforeOriginalRequest[] = "Wed, 24 May 1977 18:30:00 GMT";
56 const char kOneDayAfterOriginalRequest[] = "Fri, 26 May 1977 18:30:00 GMT";
58 const unsigned char kAConstUnsignedCharZero = 0;
60 class MockFetchContext : public FetchContext {
61 public:
62 static MockFetchContext* create()
64 return new MockFetchContext;
67 ~MockFetchContext() { }
69 bool allowImage(bool imagesEnabled, const KURL&) const override { return true; }
70 bool canRequest(Resource::Type, const ResourceRequest&, const KURL&, const ResourceLoaderOptions&, bool forPreload, FetchRequest::OriginRestriction) const override { return true; }
72 private:
73 MockFetchContext() { }
76 class CachingCorrectnessTest : public ::testing::Test {
77 protected:
78 void advanceClock(double seconds)
80 m_proxyPlatform.advanceClock(seconds);
83 ResourcePtr<Resource> resourceFromResourceResponse(ResourceResponse response, Resource::Type type = Resource::Raw)
85 if (response.url().isNull())
86 response.setURL(KURL(ParsedURLString, kResourceURL));
87 ResourcePtr<Resource> resource =
88 new Resource(ResourceRequest(response.url()), type);
89 resource->setResponse(response);
90 memoryCache()->add(resource.get());
92 return resource;
95 ResourcePtr<Resource> resourceFromResourceRequest(ResourceRequest request, Resource::Type type = Resource::Raw)
97 if (request.url().isNull())
98 request.setURL(KURL(ParsedURLString, kResourceURL));
99 ResourcePtr<Resource> resource =
100 new Resource(request, type);
101 resource->setResponse(ResourceResponse(KURL(ParsedURLString, kResourceURL), "text/html", 0, nullAtom, String()));
102 memoryCache()->add(resource.get());
104 return resource;
107 ResourcePtr<Resource> fetch()
109 FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourceURL)), FetchInitiatorInfo());
110 return RawResource::fetchSynchronously(fetchRequest, fetcher());
113 ResourcePtr<Resource> fetchImage()
115 FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourceURL)), FetchInitiatorInfo());
116 return ImageResource::fetch(fetchRequest, fetcher());
119 ResourceFetcher* fetcher() const { return m_fetcher.get(); }
121 private:
122 // A simple platform that mocks out the clock, for cache freshness testing.
123 class ProxyPlatform : public blink::Platform {
124 public:
125 ProxyPlatform() : m_platform(blink::Platform::current()), m_elapsedSeconds(0.) { }
127 ~ProxyPlatform()
129 blink::Platform::initialize(m_platform);
132 void advanceClock(double seconds)
134 m_elapsedSeconds += seconds;
137 WebThread* currentThread() override
139 return m_platform->currentThread();
142 private:
143 // From blink::Platform:
144 virtual double currentTime()
146 return kOriginalRequestDateAsDouble + m_elapsedSeconds;
149 // These blink::Platform methods must be overriden to make a usable object.
150 virtual void cryptographicallyRandomValues(unsigned char* buffer, size_t length) { ASSERT_NOT_REACHED(); }
151 virtual const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName)
153 return &kAConstUnsignedCharZero;
156 blink::Platform* m_platform; // Not owned.
157 double m_elapsedSeconds;
160 virtual void SetUp()
162 blink::Platform::initialize(&m_proxyPlatform);
164 // Save the global memory cache to restore it upon teardown.
165 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create());
167 m_fetcher = ResourceFetcher::create(MockFetchContext::create());
170 virtual void TearDown()
172 memoryCache()->evictResources();
174 // Yield the ownership of the global memory cache back.
175 replaceMemoryCacheForTesting(m_globalMemoryCache.release());
178 ProxyPlatform m_proxyPlatform;
180 Persistent<MemoryCache> m_globalMemoryCache;
181 Persistent<ResourceFetcher> m_fetcher;
184 TEST_F(CachingCorrectnessTest, FreshFromLastModified)
186 ResourceResponse fresh200Response;
187 fresh200Response.setHTTPStatusCode(200);
188 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
189 fresh200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRequest);
191 ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Response);
193 // Advance the clock within the implicit freshness period of this resource before we make a request.
194 advanceClock(600.);
196 ResourcePtr<Resource> fetched = fetch();
197 EXPECT_EQ(fresh200, fetched);
200 TEST_F(CachingCorrectnessTest, FreshFromExpires)
202 ResourceResponse fresh200Response;
203 fresh200Response.setHTTPStatusCode(200);
204 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
205 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
207 ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Response);
209 // Advance the clock within the freshness period of this resource before we make a request.
210 advanceClock(24. * 60. * 60. - 15.);
212 ResourcePtr<Resource> fetched = fetch();
213 EXPECT_EQ(fresh200, fetched);
216 TEST_F(CachingCorrectnessTest, FreshFromMaxAge)
218 ResourceResponse fresh200Response;
219 fresh200Response.setHTTPStatusCode(200);
220 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
221 fresh200Response.setHTTPHeaderField("Cache-Control", "max-age=600");
223 ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Response);
225 // Advance the clock within the freshness period of this resource before we make a request.
226 advanceClock(500.);
228 ResourcePtr<Resource> fetched = fetch();
229 EXPECT_EQ(fresh200, fetched);
232 // The strong validator causes a revalidation to be launched, and the proxy and original resources leak because of their reference loop.
233 TEST_F(CachingCorrectnessTest, DISABLED_ExpiredFromLastModified)
235 ResourceResponse expired200Response;
236 expired200Response.setHTTPStatusCode(200);
237 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
238 expired200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRequest);
240 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response);
242 // Advance the clock beyond the implicit freshness period.
243 advanceClock(24. * 60. * 60. * 0.2);
245 ResourcePtr<Resource> fetched = fetch();
246 EXPECT_NE(expired200, fetched);
249 TEST_F(CachingCorrectnessTest, ExpiredFromExpires)
251 ResourceResponse expired200Response;
252 expired200Response.setHTTPStatusCode(200);
253 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
254 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
256 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response);
258 // Advance the clock within the expiredness period of this resource before we make a request.
259 advanceClock(24. * 60. * 60. + 15.);
261 ResourcePtr<Resource> fetched = fetch();
262 EXPECT_NE(expired200, fetched);
265 // If the image hasn't been loaded in this "document" before, then it shouldn't have list of available images logic.
266 TEST_F(CachingCorrectnessTest, NewImageExpiredFromExpires)
268 ResourceResponse expired200Response;
269 expired200Response.setHTTPStatusCode(200);
270 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
271 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
273 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response, Resource::Image);
275 // Advance the clock within the expiredness period of this resource before we make a request.
276 advanceClock(24. * 60. * 60. + 15.);
278 ResourcePtr<Resource> fetched = fetchImage();
279 EXPECT_NE(expired200, fetched);
282 // If the image has been loaded in this "document" before, then it should have list of available images logic, and so
283 // normal cache testing should be bypassed.
284 TEST_F(CachingCorrectnessTest, ReuseImageExpiredFromExpires)
286 ResourceResponse expired200Response;
287 expired200Response.setHTTPStatusCode(200);
288 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
289 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
291 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response, Resource::Image);
293 // Advance the clock within the freshness period, and make a request to add this image to the document resources.
294 advanceClock(15.);
295 ResourcePtr<Resource> firstFetched = fetchImage();
296 EXPECT_EQ(expired200, firstFetched);
298 // Advance the clock within the expiredness period of this resource before we make a request.
299 advanceClock(24. * 60. * 60. + 15.);
301 ResourcePtr<Resource> fetched = fetchImage();
302 EXPECT_EQ(expired200, fetched);
305 TEST_F(CachingCorrectnessTest, ExpiredFromMaxAge)
307 ResourceResponse expired200Response;
308 expired200Response.setHTTPStatusCode(200);
309 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
310 expired200Response.setHTTPHeaderField("Cache-Control", "max-age=600");
312 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Response);
314 // Advance the clock within the expiredness period of this resource before we make a request.
315 advanceClock(700.);
317 ResourcePtr<Resource> fetched = fetch();
318 EXPECT_NE(expired200, fetched);
321 TEST_F(CachingCorrectnessTest, FreshButNoCache)
323 ResourceResponse fresh200NocacheResponse;
324 fresh200NocacheResponse.setHTTPStatusCode(200);
325 fresh200NocacheResponse.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
326 fresh200NocacheResponse.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
327 fresh200NocacheResponse.setHTTPHeaderField("Cache-Control", "no-cache");
329 ResourcePtr<Resource> fresh200Nocache = resourceFromResourceResponse(fresh200NocacheResponse);
331 // Advance the clock within the freshness period of this resource before we make a request.
332 advanceClock(24. * 60. * 60. - 15.);
334 ResourcePtr<Resource> fetched = fetch();
335 EXPECT_NE(fresh200Nocache, fetched);
338 TEST_F(CachingCorrectnessTest, RequestWithNoCahe)
340 ResourceRequest noCacheRequest;
341 noCacheRequest.setHTTPHeaderField("Cache-Control", "no-cache");
342 ResourcePtr<Resource> noCacheResource = resourceFromResourceRequest(noCacheRequest);
343 ResourcePtr<Resource> fetched = fetch();
344 EXPECT_NE(noCacheResource, fetched);
347 TEST_F(CachingCorrectnessTest, FreshButNoStore)
349 ResourceResponse fresh200NostoreResponse;
350 fresh200NostoreResponse.setHTTPStatusCode(200);
351 fresh200NostoreResponse.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
352 fresh200NostoreResponse.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
353 fresh200NostoreResponse.setHTTPHeaderField("Cache-Control", "no-store");
355 ResourcePtr<Resource> fresh200Nostore = resourceFromResourceResponse(fresh200NostoreResponse);
357 // Advance the clock within the freshness period of this resource before we make a request.
358 advanceClock(24. * 60. * 60. - 15.);
360 ResourcePtr<Resource> fetched = fetch();
361 EXPECT_NE(fresh200Nostore, fetched);
364 TEST_F(CachingCorrectnessTest, RequestWithNoStore)
366 ResourceRequest noStoreRequest;
367 noStoreRequest.setHTTPHeaderField("Cache-Control", "no-store");
368 ResourcePtr<Resource> noStoreResource = resourceFromResourceRequest(noStoreRequest);
369 ResourcePtr<Resource> fetched = fetch();
370 EXPECT_NE(noStoreResource, fetched);
373 // FIXME: Determine if ignoring must-revalidate for blink is correct behaviour.
374 // See crbug.com/340088 .
375 TEST_F(CachingCorrectnessTest, DISABLED_FreshButMustRevalidate)
377 ResourceResponse fresh200MustRevalidateResponse;
378 fresh200MustRevalidateResponse.setHTTPStatusCode(200);
379 fresh200MustRevalidateResponse.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
380 fresh200MustRevalidateResponse.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
381 fresh200MustRevalidateResponse.setHTTPHeaderField("Cache-Control", "must-revalidate");
383 ResourcePtr<Resource> fresh200MustRevalidate = resourceFromResourceResponse(fresh200MustRevalidateResponse);
385 // Advance the clock within the freshness period of this resource before we make a request.
386 advanceClock(24. * 60. * 60. - 15.);
388 ResourcePtr<Resource> fetched = fetch();
389 EXPECT_NE(fresh200MustRevalidate, fetched);
392 TEST_F(CachingCorrectnessTest, FreshWithFreshRedirect)
394 KURL redirectUrl(ParsedURLString, kResourceURL);
395 const char redirectTargetUrlString[] = "http://redirect-target.com";
396 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
398 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw);
400 ResourceResponse fresh301Response;
401 fresh301Response.setURL(redirectUrl);
402 fresh301Response.setHTTPStatusCode(301);
403 fresh301Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
404 fresh301Response.setHTTPHeaderField("Location", redirectTargetUrlString);
405 fresh301Response.setHTTPHeaderField("Cache-Control", "max-age=600");
407 // Add the redirect to our request.
408 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
409 firstResource->willFollowRedirect(redirectRequest, fresh301Response);
411 // Add the final response to our request.
412 ResourceResponse fresh200Response;
413 fresh200Response.setURL(redirectTargetUrl);
414 fresh200Response.setHTTPStatusCode(200);
415 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
416 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
418 firstResource->setResponse(fresh200Response);
419 memoryCache()->add(firstResource.get());
421 advanceClock(500.);
423 ResourcePtr<Resource> fetched = fetch();
424 EXPECT_EQ(firstResource, fetched);
427 TEST_F(CachingCorrectnessTest, FreshWithStaleRedirect)
429 KURL redirectUrl(ParsedURLString, kResourceURL);
430 const char redirectTargetUrlString[] = "http://redirect-target.com";
431 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
433 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw);
435 ResourceResponse stale301Response;
436 stale301Response.setURL(redirectUrl);
437 stale301Response.setHTTPStatusCode(301);
438 stale301Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
439 stale301Response.setHTTPHeaderField("Location", redirectTargetUrlString);
441 // Add the redirect to our request.
442 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
443 firstResource->willFollowRedirect(redirectRequest, stale301Response);
445 // Add the final response to our request.
446 ResourceResponse fresh200Response;
447 fresh200Response.setURL(redirectTargetUrl);
448 fresh200Response.setHTTPStatusCode(200);
449 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
450 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
452 firstResource->setResponse(fresh200Response);
453 memoryCache()->add(firstResource.get());
455 advanceClock(500.);
457 ResourcePtr<Resource> fetched = fetch();
458 EXPECT_NE(firstResource, fetched);
461 TEST_F(CachingCorrectnessTest, PostToSameURLTwice)
463 ResourceRequest request1(KURL(ParsedURLString, kResourceURL));
464 request1.setHTTPMethod("POST");
465 ResourcePtr<Resource> resource1 = new Resource(ResourceRequest(request1.url()), Resource::Raw);
466 resource1->setLoading(true);
467 memoryCache()->add(resource1.get());
469 ResourceRequest request2(KURL(ParsedURLString, kResourceURL));
470 request2.setHTTPMethod("POST");
471 FetchRequest fetch2(request2, FetchInitiatorInfo());
472 ResourcePtr<Resource> resource2 = RawResource::fetchSynchronously(fetch2, fetcher());
474 EXPECT_EQ(resource2, memoryCache()->resourceForURL(request2.url()));
475 EXPECT_NE(resource1, resource2);
478 TEST_F(CachingCorrectnessTest, 302RedirectNotImplicitlyFresh)
480 KURL redirectUrl(ParsedURLString, kResourceURL);
481 const char redirectTargetUrlString[] = "http://redirect-target.com";
482 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
484 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw);
486 ResourceResponse fresh302Response;
487 fresh302Response.setURL(redirectUrl);
488 fresh302Response.setHTTPStatusCode(302);
489 fresh302Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
490 fresh302Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRequest);
491 fresh302Response.setHTTPHeaderField("Location", redirectTargetUrlString);
493 // Add the redirect to our request.
494 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
495 firstResource->willFollowRedirect(redirectRequest, fresh302Response);
497 // Add the final response to our request.
498 ResourceResponse fresh200Response;
499 fresh200Response.setURL(redirectTargetUrl);
500 fresh200Response.setHTTPStatusCode(200);
501 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
502 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
504 firstResource->setResponse(fresh200Response);
505 memoryCache()->add(firstResource.get());
507 advanceClock(500.);
509 ResourcePtr<Resource> fetched = fetch();
510 EXPECT_NE(firstResource, fetched);
513 TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshMaxAge)
515 KURL redirectUrl(ParsedURLString, kResourceURL);
516 const char redirectTargetUrlString[] = "http://redirect-target.com";
517 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
519 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw);
521 ResourceResponse fresh302Response;
522 fresh302Response.setURL(redirectUrl);
523 fresh302Response.setHTTPStatusCode(302);
524 fresh302Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
525 fresh302Response.setHTTPHeaderField("Cache-Control", "max-age=600");
526 fresh302Response.setHTTPHeaderField("Location", redirectTargetUrlString);
528 // Add the redirect to our request.
529 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
530 firstResource->willFollowRedirect(redirectRequest, fresh302Response);
532 // Add the final response to our request.
533 ResourceResponse fresh200Response;
534 fresh200Response.setURL(redirectTargetUrl);
535 fresh200Response.setHTTPStatusCode(200);
536 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
537 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
539 firstResource->setResponse(fresh200Response);
540 memoryCache()->add(firstResource.get());
542 advanceClock(500.);
544 ResourcePtr<Resource> fetched = fetch();
545 EXPECT_EQ(firstResource, fetched);
548 TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshExpires)
550 KURL redirectUrl(ParsedURLString, kResourceURL);
551 const char redirectTargetUrlString[] = "http://redirect-target.com";
552 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
554 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw);
556 ResourceResponse fresh302Response;
557 fresh302Response.setURL(redirectUrl);
558 fresh302Response.setHTTPStatusCode(302);
559 fresh302Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
560 fresh302Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
561 fresh302Response.setHTTPHeaderField("Location", redirectTargetUrlString);
563 // Add the redirect to our request.
564 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
565 firstResource->willFollowRedirect(redirectRequest, fresh302Response);
567 // Add the final response to our request.
568 ResourceResponse fresh200Response;
569 fresh200Response.setURL(redirectTargetUrl);
570 fresh200Response.setHTTPStatusCode(200);
571 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
572 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
574 firstResource->setResponse(fresh200Response);
575 memoryCache()->add(firstResource.get());
577 advanceClock(500.);
579 ResourcePtr<Resource> fetched = fetch();
580 EXPECT_EQ(firstResource, fetched);
583 } // namespace blink