1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/compiler_specific.h"
12 #include "base/pickle.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/url_request/url_request.h"
19 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_error_job.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "webkit/appcache/appcache_response.h"
23 #include "webkit/appcache/appcache_url_request_job.h"
24 #include "webkit/appcache/mock_appcache_service.h"
27 using net::WrappedIOBuffer
;
31 static const char kHttpBasicHeaders
[] =
32 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
33 static const char kHttpBasicBody
[] = "Hello";
35 static const int kNumBlocks
= 4;
36 static const int kBlockSize
= 1024;
38 class AppCacheURLRequestJobTest
: public testing::Test
{
41 // Test Harness -------------------------------------------------------------
42 // TODO(michaeln): share this test harness with AppCacheResponseTest
44 class MockStorageDelegate
: public AppCacheStorage::Delegate
{
46 explicit MockStorageDelegate(AppCacheURLRequestJobTest
* test
)
47 : loaded_info_id_(0), test_(test
) {
50 virtual void OnResponseInfoLoaded(AppCacheResponseInfo
* info
,
53 loaded_info_id_
= response_id
;
54 test_
->ScheduleNextTask();
57 scoped_refptr
<AppCacheResponseInfo
> loaded_info_
;
58 int64 loaded_info_id_
;
59 AppCacheURLRequestJobTest
* test_
;
62 class MockURLRequestDelegate
: public net::URLRequest::Delegate
{
64 explicit MockURLRequestDelegate(AppCacheURLRequestJobTest
* test
)
66 received_data_(new net::IOBuffer(kNumBlocks
* kBlockSize
)),
67 did_receive_headers_(false), amount_received_(0),
68 kill_after_amount_received_(0), kill_with_io_pending_(false) {
71 virtual void OnResponseStarted(net::URLRequest
* request
) {
73 did_receive_headers_
= false;
74 if (request
->status().is_success()) {
75 EXPECT_TRUE(request
->response_headers());
76 did_receive_headers_
= true;
77 received_info_
= request
->response_info();
84 virtual void OnReadCompleted(net::URLRequest
* request
, int bytes_read
) {
86 amount_received_
+= bytes_read
;
88 if (kill_after_amount_received_
&& !kill_with_io_pending_
) {
89 if (amount_received_
>= kill_after_amount_received_
) {
97 if (kill_after_amount_received_
&& kill_with_io_pending_
) {
98 if (amount_received_
>= kill_after_amount_received_
) {
108 void ReadSome(net::URLRequest
* request
) {
109 DCHECK(amount_received_
+ kBlockSize
<= kNumBlocks
* kBlockSize
);
110 scoped_refptr
<IOBuffer
> wrapped_buffer(
111 new net::WrappedIOBuffer(received_data_
->data() + amount_received_
));
113 EXPECT_FALSE(request
->Read(wrapped_buffer
, kBlockSize
, &bytes_read
));
114 EXPECT_EQ(0, bytes_read
);
117 void RequestComplete() {
118 test_
->ScheduleNextTask();
121 AppCacheURLRequestJobTest
* test_
;
122 net::HttpResponseInfo received_info_
;
123 scoped_refptr
<net::IOBuffer
> received_data_
;
124 bool did_receive_headers_
;
125 int amount_received_
;
126 int kill_after_amount_received_
;
127 bool kill_with_io_pending_
;
130 static net::URLRequestJob
* MockHttpJobFactory(
131 net::URLRequest
* request
,
132 net::NetworkDelegate
* network_delegate
,
133 const std::string
& scheme
) {
134 if (mock_factory_job_
) {
135 net::URLRequestJob
* temp
= mock_factory_job_
;
136 mock_factory_job_
= NULL
;
139 return new net::URLRequestErrorJob(request
,
141 net::ERR_INTERNET_DISCONNECTED
);
145 // Helper callback to run a test on our io_thread. The io_thread is spun up
146 // once and reused for all tests.
147 template <class Method
>
148 void MethodWrapper(Method method
) {
153 static void SetUpTestCase() {
154 io_thread_
.reset(new base::Thread("AppCacheURLRequestJobTest Thread"));
155 base::Thread::Options
options(MessageLoop::TYPE_IO
, 0);
156 io_thread_
->StartWithOptions(options
);
159 static void TearDownTestCase() {
160 io_thread_
.reset(NULL
);
163 AppCacheURLRequestJobTest() {}
165 template <class Method
>
166 void RunTestOnIOThread(Method method
) {
167 test_finished_event_
.reset(new base::WaitableEvent(false, false));
168 io_thread_
->message_loop()->PostTask(
169 FROM_HERE
, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper
<Method
>,
170 base::Unretained(this), method
));
171 test_finished_event_
->Wait();
175 DCHECK(MessageLoop::current() == io_thread_
->message_loop());
176 DCHECK(task_stack_
.empty());
177 orig_http_factory_
= net::URLRequest::Deprecated::RegisterProtocolFactory(
178 "http", MockHttpJobFactory
);
179 url_request_delegate_
.reset(new MockURLRequestDelegate(this));
180 storage_delegate_
.reset(new MockStorageDelegate(this));
181 service_
.reset(new MockAppCacheService());
182 expected_read_result_
= 0;
183 expected_write_result_
= 0;
184 written_response_id_
= 0;
185 reader_deletion_count_down_
= 0;
186 writer_deletion_count_down_
= 0;
189 void TearDownTest() {
190 DCHECK(MessageLoop::current() == io_thread_
->message_loop());
191 net::URLRequest::Deprecated::RegisterProtocolFactory(
192 "http", orig_http_factory_
);
193 orig_http_factory_
= NULL
;
195 url_request_delegate_
.reset();
196 DCHECK(!mock_factory_job_
);
198 while (!task_stack_
.empty())
203 read_info_buffer_
= NULL
;
205 write_buffer_
= NULL
;
206 write_info_buffer_
= NULL
;
207 storage_delegate_
.reset();
211 void TestFinished() {
212 // We unwind the stack prior to finishing up to let stack
213 // based objects get deleted.
214 DCHECK(MessageLoop::current() == io_thread_
->message_loop());
215 MessageLoop::current()->PostTask(FROM_HERE
,
216 base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound
,
217 base::Unretained(this)));
220 void TestFinishedUnwound() {
222 test_finished_event_
->Signal();
225 void PushNextTask(const base::Closure
& task
) {
226 task_stack_
.push(std::pair
<base::Closure
, bool>(task
, false));
229 void PushNextTaskAsImmediate(const base::Closure
& task
) {
230 task_stack_
.push(std::pair
<base::Closure
, bool>(task
, true));
233 void ScheduleNextTask() {
234 DCHECK(MessageLoop::current() == io_thread_
->message_loop());
235 if (task_stack_
.empty()) {
239 base::Closure task
=task_stack_
.top().first
;
240 bool immediate
= task_stack_
.top().second
;
245 MessageLoop::current()->PostTask(FROM_HERE
, task
);
248 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
250 void WriteBasicResponse() {
251 scoped_refptr
<IOBuffer
> body(new WrappedIOBuffer(kHttpBasicBody
));
252 std::string
raw_headers(kHttpBasicHeaders
, arraysize(kHttpBasicHeaders
));
253 WriteResponse(MakeHttpResponseInfo(raw_headers
), body
,
254 strlen(kHttpBasicBody
));
257 void WriteResponse(net::HttpResponseInfo
* head
,
258 IOBuffer
* body
, int body_len
) {
260 scoped_refptr
<IOBuffer
> body_ref(body
);
261 PushNextTask(base::Bind(&AppCacheURLRequestJobTest::WriteResponseBody
,
262 base::Unretained(this), body_ref
, body_len
));
263 WriteResponseHead(head
);
266 void WriteResponseHead(net::HttpResponseInfo
* head
) {
267 EXPECT_FALSE(writer_
->IsWritePending());
268 expected_write_result_
= GetHttpResponseInfoSize(head
);
269 write_info_buffer_
= new HttpResponseInfoIOBuffer(head
);
272 base::Bind(&AppCacheURLRequestJobTest::OnWriteInfoComplete
,
273 base::Unretained(this)));
276 void WriteResponseBody(scoped_refptr
<IOBuffer
> io_buffer
, int buf_len
) {
277 EXPECT_FALSE(writer_
->IsWritePending());
278 write_buffer_
= io_buffer
;
279 expected_write_result_
= buf_len
;
281 write_buffer_
, buf_len
,
282 base::Bind(&AppCacheURLRequestJobTest::OnWriteComplete
,
283 base::Unretained(this)));
286 void ReadResponseBody(scoped_refptr
<IOBuffer
> io_buffer
, int buf_len
) {
287 EXPECT_FALSE(reader_
->IsReadPending());
288 read_buffer_
= io_buffer
;
289 expected_read_result_
= buf_len
;
291 read_buffer_
, buf_len
,
292 base::Bind(&AppCacheURLRequestJobTest::OnReadComplete
,
293 base::Unretained(this)));
296 // AppCacheResponseReader / Writer completion callbacks
298 void OnWriteInfoComplete(int result
) {
299 EXPECT_FALSE(writer_
->IsWritePending());
300 EXPECT_EQ(expected_write_result_
, result
);
304 void OnWriteComplete(int result
) {
305 EXPECT_FALSE(writer_
->IsWritePending());
306 EXPECT_EQ(expected_write_result_
, result
);
310 void OnReadInfoComplete(int result
) {
311 EXPECT_FALSE(reader_
->IsReadPending());
312 EXPECT_EQ(expected_read_result_
, result
);
316 void OnReadComplete(int result
) {
317 EXPECT_FALSE(reader_
->IsReadPending());
318 EXPECT_EQ(expected_read_result_
, result
);
322 // Helpers to work with HttpResponseInfo objects
324 net::HttpResponseInfo
* MakeHttpResponseInfo(const std::string
& raw_headers
) {
325 net::HttpResponseInfo
* info
= new net::HttpResponseInfo
;
326 info
->request_time
= base::Time::Now();
327 info
->response_time
= base::Time::Now();
328 info
->was_cached
= false;
329 info
->headers
= new net::HttpResponseHeaders(raw_headers
);
333 int GetHttpResponseInfoSize(const net::HttpResponseInfo
* info
) {
335 return PickleHttpResonseInfo(&pickle
, info
);
338 bool CompareHttpResponseInfos(const net::HttpResponseInfo
* info1
,
339 const net::HttpResponseInfo
* info2
) {
342 PickleHttpResonseInfo(&pickle1
, info1
);
343 PickleHttpResonseInfo(&pickle2
, info2
);
344 return (pickle1
.size() == pickle2
.size()) &&
345 (0 == memcmp(pickle1
.data(), pickle2
.data(), pickle1
.size()));
348 int PickleHttpResonseInfo(Pickle
* pickle
, const net::HttpResponseInfo
* info
) {
349 const bool kSkipTransientHeaders
= true;
350 const bool kTruncated
= false;
351 info
->Persist(pickle
, kSkipTransientHeaders
, kTruncated
);
352 return pickle
->size();
355 // Helpers to fill and verify blocks of memory with a value
357 void FillData(char value
, char* data
, int data_len
) {
358 memset(data
, value
, data_len
);
361 bool CheckData(char value
, const char* data
, int data_len
) {
362 for (int i
= 0; i
< data_len
; ++i
, ++data
) {
369 // Individual Tests ---------------------------------------------------------
370 // Some of the individual tests involve multiple async steps. Each test
371 // is delineated with a section header.
373 // Basic -------------------------------------------------------------------
375 AppCacheStorage
* storage
= service_
->storage();
376 net::URLRequest
request(GURL("http://blah/"), NULL
, &empty_context_
);
377 scoped_refptr
<AppCacheURLRequestJob
> job
;
379 // Create an instance and see that it looks as expected.
381 job
= new AppCacheURLRequestJob(
382 &request
, empty_context_
.network_delegate(), storage
);
383 EXPECT_TRUE(job
->is_waiting());
384 EXPECT_FALSE(job
->is_delivering_appcache_response());
385 EXPECT_FALSE(job
->is_delivering_network_response());
386 EXPECT_FALSE(job
->is_delivering_error_response());
387 EXPECT_FALSE(job
->has_been_started());
388 EXPECT_FALSE(job
->has_been_killed());
389 EXPECT_EQ(GURL(), job
->manifest_url());
390 EXPECT_EQ(kNoCacheId
, job
->cache_id());
391 EXPECT_FALSE(job
->entry().has_response_id());
396 // DeliveryOrders -----------------------------------------------------
397 void DeliveryOrders() {
398 AppCacheStorage
* storage
= service_
->storage();
399 net::URLRequest
request(GURL("http://blah/"), NULL
, &empty_context_
);
400 scoped_refptr
<AppCacheURLRequestJob
> job
;
402 // Create an instance, give it a delivery order and see that
403 // it looks as expected.
405 job
= new AppCacheURLRequestJob(
406 &request
, empty_context_
.network_delegate(), storage
);
407 job
->DeliverErrorResponse();
408 EXPECT_TRUE(job
->is_delivering_error_response());
409 EXPECT_FALSE(job
->has_been_started());
411 job
= new AppCacheURLRequestJob(
412 &request
, empty_context_
.network_delegate(), storage
);
413 job
->DeliverNetworkResponse();
414 EXPECT_TRUE(job
->is_delivering_network_response());
415 EXPECT_FALSE(job
->has_been_started());
417 job
= new AppCacheURLRequestJob(
418 &request
, empty_context_
.network_delegate(), storage
);
419 const GURL
kManifestUrl("http://blah/");
420 const int64
kCacheId(1);
421 const int64
kGroupId(1);
422 const AppCacheEntry
kEntry(AppCacheEntry::EXPLICIT
, 1);
423 job
->DeliverAppCachedResponse(kManifestUrl
, kCacheId
, kGroupId
,
425 EXPECT_FALSE(job
->is_waiting());
426 EXPECT_TRUE(job
->is_delivering_appcache_response());
427 EXPECT_FALSE(job
->has_been_started());
428 EXPECT_EQ(kManifestUrl
, job
->manifest_url());
429 EXPECT_EQ(kCacheId
, job
->cache_id());
430 EXPECT_EQ(kGroupId
, job
->group_id());
431 EXPECT_EQ(kEntry
.types(), job
->entry().types());
432 EXPECT_EQ(kEntry
.response_id(), job
->entry().response_id());
437 // DeliverNetworkResponse --------------------------------------------------
439 void DeliverNetworkResponse() {
440 // This test has async steps.
442 base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverNetworkResponse
,
443 base::Unretained(this)));
445 AppCacheStorage
* storage
= service_
->storage();
446 request_
.reset(empty_context_
.CreateRequest(
447 GURL("http://blah/"), url_request_delegate_
.get()));
449 // Setup to create an AppCacheURLRequestJob with orders to deliver
450 // a network response.
451 mock_factory_job_
= new AppCacheURLRequestJob(
452 request_
.get(), empty_context_
.network_delegate(), storage
);
453 mock_factory_job_
->DeliverNetworkResponse();
454 EXPECT_TRUE(mock_factory_job_
->is_delivering_network_response());
455 EXPECT_FALSE(mock_factory_job_
->has_been_started());
457 // Start the request.
460 // The job should have been picked up.
461 EXPECT_FALSE(mock_factory_job_
);
462 // Completion is async.
465 void VerifyDeliverNetworkResponse() {
466 EXPECT_EQ(request_
->status().error(),
467 net::ERR_INTERNET_DISCONNECTED
);
471 // DeliverErrorResponse --------------------------------------------------
473 void DeliverErrorResponse() {
474 // This test has async steps.
476 base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverErrorResponse
,
477 base::Unretained(this)));
479 AppCacheStorage
* storage
= service_
->storage();
480 request_
.reset(empty_context_
.CreateRequest(GURL(
481 "http://blah/"), url_request_delegate_
.get()));
483 // Setup to create an AppCacheURLRequestJob with orders to deliver
484 // a network response.
485 mock_factory_job_
= new AppCacheURLRequestJob(
486 request_
.get(), empty_context_
.network_delegate(), storage
);
487 mock_factory_job_
->DeliverErrorResponse();
488 EXPECT_TRUE(mock_factory_job_
->is_delivering_error_response());
489 EXPECT_FALSE(mock_factory_job_
->has_been_started());
491 // Start the request.
494 // The job should have been picked up.
495 EXPECT_FALSE(mock_factory_job_
);
496 // Completion is async.
499 void VerifyDeliverErrorResponse() {
500 EXPECT_EQ(request_
->status().error(), net::ERR_FAILED
);
504 // DeliverSmallAppCachedResponse --------------------------------------
505 // "Small" being small enough to read completely in a single
506 // request->Read call.
508 void DeliverSmallAppCachedResponse() {
509 // This test has several async steps.
510 // 1. Write a small response to response storage.
511 // 2. Use net::URLRequest to retrieve it.
512 // 3. Verify we received what we expected to receive.
514 PushNextTask(base::Bind(
515 &AppCacheURLRequestJobTest::VerifyDeliverSmallAppCachedResponse
,
516 base::Unretained(this)));
518 base::Bind(&AppCacheURLRequestJobTest::RequestAppCachedResource
,
519 base::Unretained(this), false));
521 writer_
.reset(service_
->storage()->CreateResponseWriter(GURL(), 0));
522 written_response_id_
= writer_
->response_id();
523 WriteBasicResponse();
527 void RequestAppCachedResource(bool start_after_delivery_orders
) {
528 AppCacheStorage
* storage
= service_
->storage();
529 request_
.reset(empty_context_
.CreateRequest(
530 GURL("http://blah/"), url_request_delegate_
.get()));
532 // Setup to create an AppCacheURLRequestJob with orders to deliver
533 // a network response.
534 scoped_refptr
<AppCacheURLRequestJob
> job(new AppCacheURLRequestJob(
535 request_
.get(), empty_context_
.network_delegate(), storage
));
537 if (start_after_delivery_orders
) {
538 job
->DeliverAppCachedResponse(
540 AppCacheEntry(AppCacheEntry::EXPLICIT
, written_response_id_
),
542 EXPECT_TRUE(job
->is_delivering_appcache_response());
545 // Start the request.
546 EXPECT_FALSE(job
->has_been_started());
547 mock_factory_job_
= job
;
549 EXPECT_FALSE(mock_factory_job_
);
550 EXPECT_TRUE(job
->has_been_started());
552 if (!start_after_delivery_orders
) {
553 job
->DeliverAppCachedResponse(
555 AppCacheEntry(AppCacheEntry::EXPLICIT
, written_response_id_
),
557 EXPECT_TRUE(job
->is_delivering_appcache_response());
560 // Completion is async.
563 void VerifyDeliverSmallAppCachedResponse() {
564 EXPECT_TRUE(request_
->status().is_success());
565 EXPECT_TRUE(CompareHttpResponseInfos(
566 write_info_buffer_
->http_info
.get(),
567 &url_request_delegate_
->received_info_
));
568 EXPECT_EQ(5, url_request_delegate_
->amount_received_
);
569 EXPECT_EQ(0, memcmp(kHttpBasicBody
,
570 url_request_delegate_
->received_data_
->data(),
571 strlen(kHttpBasicBody
)));
575 // DeliverLargeAppCachedResponse --------------------------------------
576 // "Large" enough to require multiple calls to request->Read to complete.
578 void DeliverLargeAppCachedResponse() {
579 // This test has several async steps.
580 // 1. Write a large response to response storage.
581 // 2. Use net::URLRequest to retrieve it.
582 // 3. Verify we received what we expected to receive.
584 PushNextTask(base::Bind(
585 &AppCacheURLRequestJobTest::VerifyDeliverLargeAppCachedResponse
,
586 base::Unretained(this)));
587 PushNextTask(base::Bind(
588 &AppCacheURLRequestJobTest::RequestAppCachedResource
,
589 base::Unretained(this), true));
591 writer_
.reset(service_
->storage()->CreateResponseWriter(GURL(), 0));
592 written_response_id_
= writer_
->response_id();
593 WriteLargeResponse();
597 void WriteLargeResponse() {
599 static const char kHttpHeaders
[] =
600 "HTTP/1.0 200 OK\0Content-Length: 3072\0\0";
601 scoped_refptr
<IOBuffer
> body(new IOBuffer(kBlockSize
* 3));
602 char* p
= body
->data();
603 for (int i
= 0; i
< 3; ++i
, p
+= kBlockSize
)
604 FillData(i
+ 1, p
, kBlockSize
);
605 std::string
raw_headers(kHttpHeaders
, arraysize(kHttpHeaders
));
606 WriteResponse(MakeHttpResponseInfo(raw_headers
), body
, kBlockSize
* 3);
609 void VerifyDeliverLargeAppCachedResponse() {
610 EXPECT_TRUE(request_
->status().is_success());
611 EXPECT_TRUE(CompareHttpResponseInfos(
612 write_info_buffer_
->http_info
.get(),
613 &url_request_delegate_
->received_info_
));
614 EXPECT_EQ(3072, url_request_delegate_
->amount_received_
);
615 char* p
= url_request_delegate_
->received_data_
->data();
616 for (int i
= 0; i
< 3; ++i
, p
+= kBlockSize
)
617 EXPECT_TRUE(CheckData(i
+ 1, p
, kBlockSize
));
621 // DeliverPartialResponse --------------------------------------
623 void DeliverPartialResponse() {
624 // This test has several async steps.
625 // 1. Write a small response to response storage.
626 // 2. Use net::URLRequest to retrieve it a subset using a range request
627 // 3. Verify we received what we expected to receive.
628 PushNextTask(base::Bind(
629 &AppCacheURLRequestJobTest::VerifyDeliverPartialResponse
,
630 base::Unretained(this)));
631 PushNextTask(base::Bind(
632 &AppCacheURLRequestJobTest::MakeRangeRequest
, base::Unretained(this)));
633 writer_
.reset(service_
->storage()->CreateResponseWriter(GURL(), 0));
634 written_response_id_
= writer_
->response_id();
635 WriteBasicResponse();
639 void MakeRangeRequest() {
640 AppCacheStorage
* storage
= service_
->storage();
641 request_
.reset(empty_context_
.CreateRequest(
642 GURL("http://blah/"), url_request_delegate_
.get()));
644 // Request a range, the 3 middle chars out of 'Hello'
645 net::HttpRequestHeaders extra_headers
;
646 extra_headers
.SetHeader("Range", "bytes= 1-3");
647 request_
->SetExtraRequestHeaders(extra_headers
);
649 // Create job with orders to deliver an appcached entry.
650 scoped_refptr
<AppCacheURLRequestJob
> job(new AppCacheURLRequestJob(
651 request_
.get(), empty_context_
.network_delegate(), storage
));
652 job
->DeliverAppCachedResponse(
654 AppCacheEntry(AppCacheEntry::EXPLICIT
, written_response_id_
),
656 EXPECT_TRUE(job
->is_delivering_appcache_response());
658 // Start the request.
659 EXPECT_FALSE(job
->has_been_started());
660 mock_factory_job_
= job
;
662 EXPECT_FALSE(mock_factory_job_
);
663 EXPECT_TRUE(job
->has_been_started());
664 // Completion is async.
667 void VerifyDeliverPartialResponse() {
668 EXPECT_TRUE(request_
->status().is_success());
669 EXPECT_EQ(3, url_request_delegate_
->amount_received_
);
670 EXPECT_EQ(0, memcmp(kHttpBasicBody
+ 1,
671 url_request_delegate_
->received_data_
->data(),
673 net::HttpResponseHeaders
* headers
=
674 url_request_delegate_
->received_info_
.headers
.get();
675 EXPECT_EQ(206, headers
->response_code());
676 EXPECT_EQ(3, headers
->GetContentLength());
677 int64 range_start
, range_end
, object_size
;
679 headers
->GetContentRange(&range_start
, &range_end
, &object_size
));
680 EXPECT_EQ(1, range_start
);
681 EXPECT_EQ(3, range_end
);
682 EXPECT_EQ(5, object_size
);
686 // CancelRequest --------------------------------------
688 void CancelRequest() {
689 // This test has several async steps.
690 // 1. Write a large response to response storage.
691 // 2. Use net::URLRequest to retrieve it.
692 // 3. Cancel the request after data starts coming in.
694 PushNextTask(base::Bind(
695 &AppCacheURLRequestJobTest::VerifyCancel
, base::Unretained(this)));
696 PushNextTask(base::Bind(
697 &AppCacheURLRequestJobTest::RequestAppCachedResource
,
698 base::Unretained(this), true));
700 writer_
.reset(service_
->storage()->CreateResponseWriter(GURL(), 0));
701 written_response_id_
= writer_
->response_id();
702 WriteLargeResponse();
704 url_request_delegate_
->kill_after_amount_received_
= kBlockSize
;
705 url_request_delegate_
->kill_with_io_pending_
= false;
709 void VerifyCancel() {
710 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
711 request_
->status().status());
715 // CancelRequestWithIOPending --------------------------------------
717 void CancelRequestWithIOPending() {
718 // This test has several async steps.
719 // 1. Write a large response to response storage.
720 // 2. Use net::URLRequest to retrieve it.
721 // 3. Cancel the request after data starts coming in.
723 PushNextTask(base::Bind(
724 &AppCacheURLRequestJobTest::VerifyCancel
, base::Unretained(this)));
725 PushNextTask(base::Bind(
726 &AppCacheURLRequestJobTest::RequestAppCachedResource
,
727 base::Unretained(this), true));
729 writer_
.reset(service_
->storage()->CreateResponseWriter(GURL(), 0));
730 written_response_id_
= writer_
->response_id();
731 WriteLargeResponse();
733 url_request_delegate_
->kill_after_amount_received_
= kBlockSize
;
734 url_request_delegate_
->kill_with_io_pending_
= true;
739 // Data members --------------------------------------------------------
741 scoped_ptr
<base::WaitableEvent
> test_finished_event_
;
742 scoped_ptr
<MockStorageDelegate
> storage_delegate_
;
743 scoped_ptr
<MockAppCacheService
> service_
;
744 std::stack
<std::pair
<base::Closure
, bool> > task_stack_
;
746 scoped_ptr
<AppCacheResponseReader
> reader_
;
747 scoped_refptr
<HttpResponseInfoIOBuffer
> read_info_buffer_
;
748 scoped_refptr
<IOBuffer
> read_buffer_
;
749 int expected_read_result_
;
750 int reader_deletion_count_down_
;
752 int64 written_response_id_
;
753 scoped_ptr
<AppCacheResponseWriter
> writer_
;
754 scoped_refptr
<HttpResponseInfoIOBuffer
> write_info_buffer_
;
755 scoped_refptr
<IOBuffer
> write_buffer_
;
756 int expected_write_result_
;
757 int writer_deletion_count_down_
;
759 net::URLRequest::ProtocolFactory
* orig_http_factory_
;
760 net::URLRequestContext empty_context_
;
761 scoped_ptr
<net::URLRequest
> request_
;
762 scoped_ptr
<MockURLRequestDelegate
> url_request_delegate_
;
764 static scoped_ptr
<base::Thread
> io_thread_
;
765 static AppCacheURLRequestJob
* mock_factory_job_
;
769 scoped_ptr
<base::Thread
> AppCacheURLRequestJobTest::io_thread_
;
770 AppCacheURLRequestJob
* AppCacheURLRequestJobTest::mock_factory_job_
= NULL
;
772 TEST_F(AppCacheURLRequestJobTest
, Basic
) {
773 RunTestOnIOThread(&AppCacheURLRequestJobTest::Basic
);
776 TEST_F(AppCacheURLRequestJobTest
, DeliveryOrders
) {
777 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliveryOrders
);
780 TEST_F(AppCacheURLRequestJobTest
, DeliverNetworkResponse
) {
781 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverNetworkResponse
);
784 TEST_F(AppCacheURLRequestJobTest
, DeliverErrorResponse
) {
785 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverErrorResponse
);
788 TEST_F(AppCacheURLRequestJobTest
, DeliverSmallAppCachedResponse
) {
789 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverSmallAppCachedResponse
);
792 TEST_F(AppCacheURLRequestJobTest
, DeliverLargeAppCachedResponse
) {
793 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverLargeAppCachedResponse
);
796 TEST_F(AppCacheURLRequestJobTest
, DeliverPartialResponse
) {
797 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverPartialResponse
);
800 TEST_F(AppCacheURLRequestJobTest
, CancelRequest
) {
801 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequest
);
804 TEST_F(AppCacheURLRequestJobTest
, CancelRequestWithIOPending
) {
805 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequestWithIOPending
);
808 } // namespace appcache