OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2013, Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
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. | |
17 * | |
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. | |
29 */ | |
30 | |
31 #include "core/fetch/RawResource.h" | |
32 | |
33 #include "core/fetch/MemoryCache.h" | |
34 #include "core/fetch/ResourceFetcher.h" | |
35 #include "platform/SharedBuffer.h" | |
36 #include "platform/heap/Handle.h" | |
37 #include "platform/network/ResourceTimingInfo.h" | |
38 #include "platform/testing/UnitTestHelpers.h" | |
39 #include "public/platform/Platform.h" | |
40 #include "public/platform/WebScheduler.h" | |
41 #include "public/platform/WebThread.h" | |
42 #include "public/platform/WebURL.h" | |
43 #include "public/platform/WebURLResponse.h" | |
44 #include "testing/gmock/include/gmock/gmock.h" | |
45 #include "testing/gtest/include/gtest/gtest.h" | |
46 | |
47 namespace blink { | |
48 | |
49 using ::testing::InSequence; | |
50 using ::testing::_; | |
51 using Checkpoint = ::testing::StrictMock<::testing::MockFunction<void(int)>>; | |
52 | |
53 class MockRawResourceClient | |
54 : public GarbageCollectedFinalized<MockRawResourceClient>, | |
55 public RawResourceClient { | |
56 USING_GARBAGE_COLLECTED_MIXIN(MockRawResourceClient); | |
57 | |
58 public: | |
59 static MockRawResourceClient* create() { | |
60 return new ::testing::StrictMock<MockRawResourceClient>; | |
61 } | |
62 | |
63 MOCK_METHOD3(dataSent, | |
64 void(Resource*, unsigned long long, unsigned long long)); | |
65 MOCK_METHOD3(responseReceivedInternal, | |
66 void(Resource*, | |
67 const ResourceResponse&, | |
68 WebDataConsumerHandle*)); | |
69 MOCK_METHOD3(setSerializedCachedMetadata, | |
70 void(Resource*, const char*, size_t)); | |
71 MOCK_METHOD3(dataReceived, void(Resource*, const char*, size_t)); | |
72 MOCK_METHOD3(redirectReceived, | |
73 bool(Resource*, | |
74 const ResourceRequest&, | |
75 const ResourceResponse&)); | |
76 MOCK_METHOD0(redirectBlocked, void()); | |
77 MOCK_METHOD2(dataDownloaded, void(Resource*, int)); | |
78 MOCK_METHOD2(didReceiveResourceTiming, | |
79 void(Resource*, const ResourceTimingInfo&)); | |
80 | |
81 void responseReceived( | |
82 Resource* resource, | |
83 const ResourceResponse& response, | |
84 std::unique_ptr<WebDataConsumerHandle> handle) override { | |
85 responseReceivedInternal(resource, response, handle.get()); | |
86 } | |
87 | |
88 String debugName() const override { return "MockRawResourceClient"; } | |
89 | |
90 DEFINE_INLINE_VIRTUAL_TRACE() { RawResourceClient::trace(visitor); } | |
91 | |
92 protected: | |
93 MockRawResourceClient() = default; | |
94 }; | |
95 | |
96 TEST(RawResourceTest, DontIgnoreAcceptForCacheReuse) { | |
97 ResourceRequest jpegRequest; | |
98 jpegRequest.setHTTPAccept("image/jpeg"); | |
99 | |
100 RawResource* jpegResource(RawResource::create(jpegRequest, Resource::Raw)); | |
101 | |
102 ResourceRequest pngRequest; | |
103 pngRequest.setHTTPAccept("image/png"); | |
104 | |
105 EXPECT_FALSE(jpegResource->canReuse(pngRequest)); | |
106 } | |
107 | |
108 class DummyClient final : public GarbageCollectedFinalized<DummyClient>, | |
109 public RawResourceClient { | |
110 USING_GARBAGE_COLLECTED_MIXIN(DummyClient); | |
111 | |
112 public: | |
113 DummyClient() : m_called(false), m_numberOfRedirectsReceived(0) {} | |
114 ~DummyClient() override {} | |
115 | |
116 // ResourceClient implementation. | |
117 void notifyFinished(Resource* resource) override { m_called = true; } | |
118 String debugName() const override { return "DummyClient"; } | |
119 | |
120 void dataReceived(Resource*, const char* data, size_t length) override { | |
121 m_data.append(data, length); | |
122 } | |
123 | |
124 bool redirectReceived(Resource*, | |
125 const ResourceRequest&, | |
126 const ResourceResponse&) override { | |
127 ++m_numberOfRedirectsReceived; | |
128 return true; | |
129 } | |
130 | |
131 bool called() { return m_called; } | |
132 int numberOfRedirectsReceived() const { return m_numberOfRedirectsReceived; } | |
133 const Vector<char>& data() { return m_data; } | |
134 DEFINE_INLINE_TRACE() { RawResourceClient::trace(visitor); } | |
135 | |
136 private: | |
137 bool m_called; | |
138 int m_numberOfRedirectsReceived; | |
139 Vector<char> m_data; | |
140 }; | |
141 | |
142 // This client adds another client when notified. | |
143 class AddingClient final : public GarbageCollectedFinalized<AddingClient>, | |
144 public RawResourceClient { | |
145 USING_GARBAGE_COLLECTED_MIXIN(AddingClient); | |
146 | |
147 public: | |
148 AddingClient(DummyClient* client, Resource* resource) | |
149 : m_dummyClient(client), m_resource(resource) {} | |
150 | |
151 ~AddingClient() override {} | |
152 | |
153 // ResourceClient implementation. | |
154 void notifyFinished(Resource* resource) override { | |
155 // First schedule an asynchronous task to remove the client. | |
156 // We do not expect a client to be called if the client is removed before | |
157 // a callback invocation task queued inside addClient() is scheduled. | |
158 Platform::current() | |
159 ->currentThread() | |
160 ->scheduler() | |
161 ->loadingTaskRunner() | |
162 ->postTask(BLINK_FROM_HERE, WTF::bind(&AddingClient::removeClient, | |
163 wrapPersistent(this))); | |
164 resource->addClient(m_dummyClient); | |
165 } | |
166 String debugName() const override { return "AddingClient"; } | |
167 | |
168 void removeClient() { m_resource->removeClient(m_dummyClient); } | |
169 | |
170 DEFINE_INLINE_VIRTUAL_TRACE() { | |
171 visitor->trace(m_dummyClient); | |
172 visitor->trace(m_resource); | |
173 RawResourceClient::trace(visitor); | |
174 } | |
175 | |
176 private: | |
177 Member<DummyClient> m_dummyClient; | |
178 Member<Resource> m_resource; | |
179 }; | |
180 | |
181 TEST(RawResourceTest, RevalidationSucceeded) { | |
182 Resource* resource = | |
183 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
184 ResourceResponse response; | |
185 response.setHTTPStatusCode(200); | |
186 resource->responseReceived(response, nullptr); | |
187 const char data[5] = "abcd"; | |
188 resource->appendData(data, 4); | |
189 resource->finish(); | |
190 memoryCache()->add(resource); | |
191 | |
192 // Simulate a successful revalidation. | |
193 resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); | |
194 | |
195 Persistent<DummyClient> client = new DummyClient; | |
196 resource->addClient(client); | |
197 | |
198 ResourceResponse revalidatingResponse; | |
199 revalidatingResponse.setHTTPStatusCode(304); | |
200 resource->responseReceived(revalidatingResponse, nullptr); | |
201 EXPECT_FALSE(resource->isCacheValidator()); | |
202 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
203 EXPECT_EQ(4u, resource->resourceBuffer()->size()); | |
204 EXPECT_EQ(resource, memoryCache()->resourceForURL( | |
205 KURL(ParsedURLString, "data:text/html,"))); | |
206 memoryCache()->remove(resource); | |
207 | |
208 resource->removeClient(client); | |
209 EXPECT_FALSE(resource->isAlive()); | |
210 EXPECT_FALSE(client->called()); | |
211 EXPECT_EQ("abcd", String(client->data().data(), client->data().size())); | |
212 } | |
213 | |
214 TEST(RawResourceTest, RevalidationSucceededForResourceWithoutBody) { | |
215 Resource* resource = | |
216 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
217 ResourceResponse response; | |
218 response.setHTTPStatusCode(200); | |
219 resource->responseReceived(response, nullptr); | |
220 resource->finish(); | |
221 memoryCache()->add(resource); | |
222 | |
223 // Simulate a successful revalidation. | |
224 resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); | |
225 | |
226 Persistent<DummyClient> client = new DummyClient; | |
227 resource->addClient(client); | |
228 | |
229 ResourceResponse revalidatingResponse; | |
230 revalidatingResponse.setHTTPStatusCode(304); | |
231 resource->responseReceived(revalidatingResponse, nullptr); | |
232 EXPECT_FALSE(resource->isCacheValidator()); | |
233 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
234 EXPECT_FALSE(resource->resourceBuffer()); | |
235 EXPECT_EQ(resource, memoryCache()->resourceForURL( | |
236 KURL(ParsedURLString, "data:text/html,"))); | |
237 memoryCache()->remove(resource); | |
238 | |
239 resource->removeClient(client); | |
240 EXPECT_FALSE(resource->isAlive()); | |
241 EXPECT_FALSE(client->called()); | |
242 EXPECT_EQ(0u, client->data().size()); | |
243 } | |
244 | |
245 TEST(RawResourceTest, RevalidationSucceededUpdateHeaders) { | |
246 Resource* resource = | |
247 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
248 ResourceResponse response; | |
249 response.setHTTPStatusCode(200); | |
250 response.addHTTPHeaderField("keep-alive", "keep-alive value"); | |
251 response.addHTTPHeaderField("expires", "expires value"); | |
252 response.addHTTPHeaderField("last-modified", "last-modified value"); | |
253 response.addHTTPHeaderField("proxy-authenticate", "proxy-authenticate value"); | |
254 response.addHTTPHeaderField("proxy-connection", "proxy-connection value"); | |
255 response.addHTTPHeaderField("x-custom", "custom value"); | |
256 resource->responseReceived(response, nullptr); | |
257 resource->finish(); | |
258 memoryCache()->add(resource); | |
259 | |
260 // Simulate a successful revalidation. | |
261 resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); | |
262 | |
263 // Validate that these headers pre-update. | |
264 EXPECT_EQ("keep-alive value", | |
265 resource->response().httpHeaderField("keep-alive")); | |
266 EXPECT_EQ("expires value", resource->response().httpHeaderField("expires")); | |
267 EXPECT_EQ("last-modified value", | |
268 resource->response().httpHeaderField("last-modified")); | |
269 EXPECT_EQ("proxy-authenticate value", | |
270 resource->response().httpHeaderField("proxy-authenticate")); | |
271 EXPECT_EQ("proxy-authenticate value", | |
272 resource->response().httpHeaderField("proxy-authenticate")); | |
273 EXPECT_EQ("proxy-connection value", | |
274 resource->response().httpHeaderField("proxy-connection")); | |
275 EXPECT_EQ("custom value", resource->response().httpHeaderField("x-custom")); | |
276 | |
277 Persistent<DummyClient> client = new DummyClient; | |
278 resource->addClient(client.get()); | |
279 | |
280 // Perform a revalidation step. | |
281 ResourceResponse revalidatingResponse; | |
282 revalidatingResponse.setHTTPStatusCode(304); | |
283 // Headers that aren't copied with an 304 code. | |
284 revalidatingResponse.addHTTPHeaderField("keep-alive", "garbage"); | |
285 revalidatingResponse.addHTTPHeaderField("expires", "garbage"); | |
286 revalidatingResponse.addHTTPHeaderField("last-modified", "garbage"); | |
287 revalidatingResponse.addHTTPHeaderField("proxy-authenticate", "garbage"); | |
288 revalidatingResponse.addHTTPHeaderField("proxy-connection", "garbage"); | |
289 // Header that is updated with 304 code. | |
290 revalidatingResponse.addHTTPHeaderField("x-custom", "updated"); | |
291 resource->responseReceived(revalidatingResponse, nullptr); | |
292 | |
293 // Validate the original response. | |
294 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
295 | |
296 // Validate that these headers are not updated. | |
297 EXPECT_EQ("keep-alive value", | |
298 resource->response().httpHeaderField("keep-alive")); | |
299 EXPECT_EQ("expires value", resource->response().httpHeaderField("expires")); | |
300 EXPECT_EQ("last-modified value", | |
301 resource->response().httpHeaderField("last-modified")); | |
302 EXPECT_EQ("proxy-authenticate value", | |
303 resource->response().httpHeaderField("proxy-authenticate")); | |
304 EXPECT_EQ("proxy-authenticate value", | |
305 resource->response().httpHeaderField("proxy-authenticate")); | |
306 EXPECT_EQ("proxy-connection value", | |
307 resource->response().httpHeaderField("proxy-connection")); | |
308 EXPECT_EQ("updated", resource->response().httpHeaderField("x-custom")); | |
309 | |
310 memoryCache()->remove(resource); | |
311 | |
312 resource->removeClient(client); | |
313 EXPECT_FALSE(resource->isAlive()); | |
314 EXPECT_FALSE(client->called()); | |
315 EXPECT_EQ(0u, client->data().size()); | |
316 } | |
317 | |
318 TEST(RawResourceTest, RedirectDuringRevalidation) { | |
319 Resource* resource = RawResource::create( | |
320 ResourceRequest("https://example.com/1"), Resource::Raw); | |
321 ResourceResponse response; | |
322 response.setURL(KURL(ParsedURLString, "https://example.com/1")); | |
323 response.setHTTPStatusCode(200); | |
324 resource->responseReceived(response, nullptr); | |
325 const char data[5] = "abcd"; | |
326 resource->appendData(data, 4); | |
327 resource->finish(); | |
328 memoryCache()->add(resource); | |
329 | |
330 EXPECT_FALSE(resource->isCacheValidator()); | |
331 EXPECT_EQ("https://example.com/1", | |
332 resource->resourceRequest().url().getString()); | |
333 EXPECT_EQ("https://example.com/1", | |
334 resource->lastResourceRequest().url().getString()); | |
335 | |
336 // Simulate a revalidation. | |
337 resource->setRevalidatingRequest(ResourceRequest("https://example.com/1")); | |
338 EXPECT_TRUE(resource->isCacheValidator()); | |
339 EXPECT_EQ("https://example.com/1", | |
340 resource->resourceRequest().url().getString()); | |
341 EXPECT_EQ("https://example.com/1", | |
342 resource->lastResourceRequest().url().getString()); | |
343 | |
344 Persistent<DummyClient> client = new DummyClient; | |
345 resource->addClient(client); | |
346 | |
347 // The revalidating request is redirected. | |
348 ResourceResponse redirectResponse; | |
349 redirectResponse.setURL(KURL(ParsedURLString, "https://example.com/1")); | |
350 redirectResponse.setHTTPHeaderField("location", "https://example.com/2"); | |
351 redirectResponse.setHTTPStatusCode(308); | |
352 ResourceRequest redirectedRevalidatingRequest("https://example.com/2"); | |
353 resource->willFollowRedirect(redirectedRevalidatingRequest, redirectResponse); | |
354 EXPECT_FALSE(resource->isCacheValidator()); | |
355 EXPECT_EQ("https://example.com/1", | |
356 resource->resourceRequest().url().getString()); | |
357 EXPECT_EQ("https://example.com/2", | |
358 resource->lastResourceRequest().url().getString()); | |
359 | |
360 // The final response is received. | |
361 ResourceResponse revalidatingResponse; | |
362 revalidatingResponse.setURL(KURL(ParsedURLString, "https://example.com/2")); | |
363 revalidatingResponse.setHTTPStatusCode(200); | |
364 resource->responseReceived(revalidatingResponse, nullptr); | |
365 const char data2[4] = "xyz"; | |
366 resource->appendData(data2, 3); | |
367 resource->finish(); | |
368 EXPECT_FALSE(resource->isCacheValidator()); | |
369 EXPECT_EQ("https://example.com/1", | |
370 resource->resourceRequest().url().getString()); | |
371 EXPECT_EQ("https://example.com/2", | |
372 resource->lastResourceRequest().url().getString()); | |
373 EXPECT_FALSE(resource->isCacheValidator()); | |
374 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
375 EXPECT_EQ(3u, resource->resourceBuffer()->size()); | |
376 EXPECT_EQ(resource, memoryCache()->resourceForURL( | |
377 KURL(ParsedURLString, "https://example.com/1"))); | |
378 | |
379 EXPECT_TRUE(client->called()); | |
380 EXPECT_EQ(1, client->numberOfRedirectsReceived()); | |
381 EXPECT_EQ("xyz", String(client->data().data(), client->data().size())); | |
382 | |
383 // Test the case where a client is added after revalidation is completed. | |
384 Persistent<DummyClient> client2 = new DummyClient; | |
385 resource->addClient(client2); | |
386 | |
387 // Because RawResourceClient is added asynchronously, | |
388 // |runPendingTasks()| is called to make |client2| to be notified. | |
389 testing::runPendingTasks(); | |
390 | |
391 EXPECT_TRUE(client2->called()); | |
392 EXPECT_EQ(1, client2->numberOfRedirectsReceived()); | |
393 EXPECT_EQ("xyz", String(client2->data().data(), client2->data().size())); | |
394 | |
395 memoryCache()->remove(resource); | |
396 | |
397 resource->removeClient(client); | |
398 resource->removeClient(client2); | |
399 EXPECT_FALSE(resource->isAlive()); | |
400 } | |
401 | |
402 TEST(RawResourceTest, AddClientDuringCallback) { | |
403 Resource* raw = | |
404 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
405 | |
406 // Create a non-null response. | |
407 ResourceResponse response = raw->response(); | |
408 response.setURL(KURL(ParsedURLString, "http://600.613/")); | |
409 raw->setResponse(response); | |
410 raw->finish(); | |
411 EXPECT_FALSE(raw->response().isNull()); | |
412 | |
413 Persistent<DummyClient> dummyClient = new DummyClient(); | |
414 Persistent<AddingClient> addingClient = | |
415 new AddingClient(dummyClient.get(), raw); | |
416 raw->addClient(addingClient); | |
417 testing::runPendingTasks(); | |
418 raw->removeClient(addingClient); | |
419 EXPECT_FALSE(dummyClient->called()); | |
420 EXPECT_FALSE(raw->isAlive()); | |
421 } | |
422 | |
423 // This client removes another client when notified. | |
424 class RemovingClient : public GarbageCollectedFinalized<RemovingClient>, | |
425 public RawResourceClient { | |
426 USING_GARBAGE_COLLECTED_MIXIN(RemovingClient); | |
427 | |
428 public: | |
429 explicit RemovingClient(DummyClient* client) : m_dummyClient(client) {} | |
430 | |
431 ~RemovingClient() override {} | |
432 | |
433 // ResourceClient implementation. | |
434 void notifyFinished(Resource* resource) override { | |
435 resource->removeClient(m_dummyClient); | |
436 resource->removeClient(this); | |
437 } | |
438 String debugName() const override { return "RemovingClient"; } | |
439 DEFINE_INLINE_TRACE() { | |
440 visitor->trace(m_dummyClient); | |
441 RawResourceClient::trace(visitor); | |
442 } | |
443 | |
444 private: | |
445 Member<DummyClient> m_dummyClient; | |
446 }; | |
447 | |
448 TEST(RawResourceTest, RemoveClientDuringCallback) { | |
449 Resource* raw = | |
450 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
451 | |
452 // Create a non-null response. | |
453 ResourceResponse response = raw->response(); | |
454 response.setURL(KURL(ParsedURLString, "http://600.613/")); | |
455 raw->setResponse(response); | |
456 raw->finish(); | |
457 EXPECT_FALSE(raw->response().isNull()); | |
458 | |
459 Persistent<DummyClient> dummyClient = new DummyClient(); | |
460 Persistent<RemovingClient> removingClient = | |
461 new RemovingClient(dummyClient.get()); | |
462 raw->addClient(dummyClient); | |
463 raw->addClient(removingClient); | |
464 testing::runPendingTasks(); | |
465 EXPECT_FALSE(raw->isAlive()); | |
466 } | |
467 | |
468 // ResourceClient can be added to |m_clients| asynchronously via | |
469 // ResourceCallback. When revalidation is started after ResourceCallback is | |
470 // scheduled and before it is dispatched, ResourceClient's callbacks should be | |
471 // called appropriately. | |
472 TEST(RawResourceTest, StartFailedRevalidationWhileResourceCallback) { | |
473 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); | |
474 | |
475 ResourceResponse response; | |
476 response.setURL(url); | |
477 response.setHTTPStatusCode(200); | |
478 | |
479 ResourceResponse newResponse; | |
480 newResponse.setURL(url); | |
481 newResponse.setHTTPStatusCode(201); | |
482 | |
483 Resource* resource = | |
484 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
485 resource->responseReceived(response, nullptr); | |
486 resource->appendData("oldData", 8); | |
487 resource->finish(); | |
488 | |
489 InSequence s; | |
490 Checkpoint checkpoint; | |
491 | |
492 MockRawResourceClient* client = MockRawResourceClient::create(); | |
493 | |
494 EXPECT_CALL(checkpoint, Call(1)); | |
495 EXPECT_CALL(*client, responseReceivedInternal(resource, newResponse, _)); | |
496 EXPECT_CALL(*client, dataReceived(resource, ::testing::StrEq("newData"), 8)); | |
497 | |
498 // Add a client. No callbacks are made here because ResourceCallback is | |
499 // scheduled asynchronously. | |
500 resource->addClient(client); | |
501 EXPECT_FALSE(resource->isCacheValidator()); | |
502 | |
503 // Start revalidation. | |
504 resource->setRevalidatingRequest(ResourceRequest(url)); | |
505 EXPECT_TRUE(resource->isCacheValidator()); | |
506 | |
507 // Make the ResourceCallback to be dispatched. | |
508 testing::runPendingTasks(); | |
509 | |
510 checkpoint.Call(1); | |
511 | |
512 resource->responseReceived(newResponse, nullptr); | |
513 resource->appendData("newData", 8); | |
514 } | |
515 | |
516 TEST(RawResourceTest, StartSuccessfulRevalidationWhileResourceCallback) { | |
517 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); | |
518 | |
519 ResourceResponse response; | |
520 response.setURL(url); | |
521 response.setHTTPStatusCode(200); | |
522 | |
523 ResourceResponse newResponse; | |
524 newResponse.setURL(url); | |
525 newResponse.setHTTPStatusCode(304); | |
526 | |
527 Resource* resource = | |
528 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
529 resource->responseReceived(response, nullptr); | |
530 resource->appendData("oldData", 8); | |
531 resource->finish(); | |
532 | |
533 InSequence s; | |
534 Checkpoint checkpoint; | |
535 | |
536 MockRawResourceClient* client = MockRawResourceClient::create(); | |
537 | |
538 EXPECT_CALL(checkpoint, Call(1)); | |
539 EXPECT_CALL(*client, responseReceivedInternal(resource, response, _)); | |
540 EXPECT_CALL(*client, dataReceived(resource, ::testing::StrEq("oldData"), 8)); | |
541 | |
542 // Add a client. No callbacks are made here because ResourceCallback is | |
543 // scheduled asynchronously. | |
544 resource->addClient(client); | |
545 EXPECT_FALSE(resource->isCacheValidator()); | |
546 | |
547 // Start revalidation. | |
548 resource->setRevalidatingRequest(ResourceRequest(url)); | |
549 EXPECT_TRUE(resource->isCacheValidator()); | |
550 | |
551 // Make the ResourceCallback to be dispatched. | |
552 testing::runPendingTasks(); | |
553 | |
554 checkpoint.Call(1); | |
555 | |
556 resource->responseReceived(newResponse, nullptr); | |
557 } | |
558 | |
559 TEST(RawResourceTest, CanReuseDevToolsEmulateNetworkConditionsClientIdHeader) { | |
560 ResourceRequest request("data:text/html,"); | |
561 request.setHTTPHeaderField( | |
562 HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id, "Foo"); | |
563 Resource* raw = RawResource::create(request, Resource::Raw); | |
564 EXPECT_TRUE(raw->canReuse(ResourceRequest("data:text/html,"))); | |
565 } | |
566 | |
567 } // namespace blink | |
OLD | NEW |