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/base/request_priority.h"
18 #include "net/http/http_response_headers.h"
19 #include "net/url_request/url_request.h"
20 #include "net/url_request/url_request_context.h"
21 #include "net/url_request/url_request_error_job.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "webkit/browser/appcache/appcache_response.h"
24 #include "webkit/browser/appcache/appcache_url_request_job.h"
25 #include "webkit/browser/appcache/mock_appcache_service.h"
28 using net::WrappedIOBuffer;
32 static const char kHttpBasicHeaders[] =
33 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
34 static const char kHttpBasicBody[] = "Hello";
36 static const int kNumBlocks = 4;
37 static const int kBlockSize = 1024;
39 class AppCacheURLRequestJobTest : public testing::Test {
42 // Test Harness -------------------------------------------------------------
43 // TODO(michaeln): share this test harness with AppCacheResponseTest
45 class MockStorageDelegate : public AppCacheStorage::Delegate {
47 explicit MockStorageDelegate(AppCacheURLRequestJobTest* test)
48 : loaded_info_id_(0), test_(test) {
51 virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
52 int64 response_id) OVERRIDE {
54 loaded_info_id_ = response_id;
55 test_->ScheduleNextTask();
58 scoped_refptr<AppCacheResponseInfo> loaded_info_;
59 int64 loaded_info_id_;
60 AppCacheURLRequestJobTest* test_;
63 class MockURLRequestDelegate : public net::URLRequest::Delegate {
65 explicit MockURLRequestDelegate(AppCacheURLRequestJobTest* test)
67 received_data_(new net::IOBuffer(kNumBlocks * kBlockSize)),
68 did_receive_headers_(false), amount_received_(0),
69 kill_after_amount_received_(0), kill_with_io_pending_(false) {
72 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
74 did_receive_headers_ = false;
75 if (request->status().is_success()) {
76 EXPECT_TRUE(request->response_headers());
77 did_receive_headers_ = true;
78 received_info_ = request->response_info();
85 virtual void OnReadCompleted(net::URLRequest* request,
86 int bytes_read) OVERRIDE {
88 amount_received_ += bytes_read;
90 if (kill_after_amount_received_ && !kill_with_io_pending_) {
91 if (amount_received_ >= kill_after_amount_received_) {
99 if (kill_after_amount_received_ && kill_with_io_pending_) {
100 if (amount_received_ >= kill_after_amount_received_) {
110 void ReadSome(net::URLRequest* request) {
111 DCHECK(amount_received_ + kBlockSize <= kNumBlocks * kBlockSize);
112 scoped_refptr<IOBuffer> wrapped_buffer(
113 new net::WrappedIOBuffer(received_data_->data() + amount_received_));
116 request->Read(wrapped_buffer.get(), kBlockSize, &bytes_read));
117 EXPECT_EQ(0, bytes_read);
120 void RequestComplete() {
121 test_->ScheduleNextTask();
124 AppCacheURLRequestJobTest* test_;
125 net::HttpResponseInfo received_info_;
126 scoped_refptr<net::IOBuffer> received_data_;
127 bool did_receive_headers_;
128 int amount_received_;
129 int kill_after_amount_received_;
130 bool kill_with_io_pending_;
133 static net::URLRequestJob* MockHttpJobFactory(
134 net::URLRequest* request,
135 net::NetworkDelegate* network_delegate,
136 const std::string& scheme) {
137 if (mock_factory_job_) {
138 net::URLRequestJob* temp = mock_factory_job_;
139 mock_factory_job_ = NULL;
142 return new net::URLRequestErrorJob(request,
144 net::ERR_INTERNET_DISCONNECTED);
148 // Helper callback to run a test on our io_thread. The io_thread is spun up
149 // once and reused for all tests.
150 template <class Method>
151 void MethodWrapper(Method method) {
156 static void SetUpTestCase() {
157 io_thread_.reset(new base::Thread("AppCacheURLRequestJobTest Thread"));
158 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
159 io_thread_->StartWithOptions(options);
162 static void TearDownTestCase() {
163 io_thread_.reset(NULL);
166 AppCacheURLRequestJobTest() {}
168 template <class Method>
169 void RunTestOnIOThread(Method method) {
170 test_finished_event_ .reset(new base::WaitableEvent(false, false));
171 io_thread_->message_loop()->PostTask(
172 FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper<Method>,
173 base::Unretained(this), method));
174 test_finished_event_->Wait();
178 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
179 DCHECK(task_stack_.empty());
180 orig_http_factory_ = net::URLRequest::Deprecated::RegisterProtocolFactory(
181 "http", MockHttpJobFactory);
182 url_request_delegate_.reset(new MockURLRequestDelegate(this));
183 storage_delegate_.reset(new MockStorageDelegate(this));
184 service_.reset(new MockAppCacheService());
185 expected_read_result_ = 0;
186 expected_write_result_ = 0;
187 written_response_id_ = 0;
188 reader_deletion_count_down_ = 0;
189 writer_deletion_count_down_ = 0;
192 void TearDownTest() {
193 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
194 net::URLRequest::Deprecated::RegisterProtocolFactory("http",
196 orig_http_factory_ = NULL;
198 url_request_delegate_.reset();
199 DCHECK(!mock_factory_job_);
201 while (!task_stack_.empty())
206 read_info_buffer_ = NULL;
208 write_buffer_ = NULL;
209 write_info_buffer_ = NULL;
210 storage_delegate_.reset();
214 void TestFinished() {
215 // We unwind the stack prior to finishing up to let stack
216 // based objects get deleted.
217 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
218 base::MessageLoop::current()->PostTask(
220 base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound,
221 base::Unretained(this)));
224 void TestFinishedUnwound() {
226 test_finished_event_->Signal();
229 void PushNextTask(const base::Closure& task) {
230 task_stack_.push(std::pair<base::Closure, bool>(task, false));
233 void PushNextTaskAsImmediate(const base::Closure& task) {
234 task_stack_.push(std::pair<base::Closure, bool>(task, true));
237 void ScheduleNextTask() {
238 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
239 if (task_stack_.empty()) {
243 base::Closure task =task_stack_.top().first;
244 bool immediate = task_stack_.top().second;
249 base::MessageLoop::current()->PostTask(FROM_HERE, task);
252 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
254 void WriteBasicResponse() {
255 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBasicBody));
256 std::string raw_headers(kHttpBasicHeaders, arraysize(kHttpBasicHeaders));
258 MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBasicBody));
261 void WriteResponse(net::HttpResponseInfo* head,
262 IOBuffer* body, int body_len) {
264 scoped_refptr<IOBuffer> body_ref(body);
265 PushNextTask(base::Bind(&AppCacheURLRequestJobTest::WriteResponseBody,
266 base::Unretained(this), body_ref, body_len));
267 WriteResponseHead(head);
270 void WriteResponseHead(net::HttpResponseInfo* head) {
271 EXPECT_FALSE(writer_->IsWritePending());
272 expected_write_result_ = GetHttpResponseInfoSize(head);
273 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
275 write_info_buffer_.get(),
276 base::Bind(&AppCacheURLRequestJobTest::OnWriteInfoComplete,
277 base::Unretained(this)));
280 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
281 EXPECT_FALSE(writer_->IsWritePending());
282 write_buffer_ = io_buffer;
283 expected_write_result_ = buf_len;
284 writer_->WriteData(write_buffer_.get(),
286 base::Bind(&AppCacheURLRequestJobTest::OnWriteComplete,
287 base::Unretained(this)));
290 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
291 EXPECT_FALSE(reader_->IsReadPending());
292 read_buffer_ = io_buffer;
293 expected_read_result_ = buf_len;
294 reader_->ReadData(read_buffer_.get(),
296 base::Bind(&AppCacheURLRequestJobTest::OnReadComplete,
297 base::Unretained(this)));
300 // AppCacheResponseReader / Writer completion callbacks
302 void OnWriteInfoComplete(int result) {
303 EXPECT_FALSE(writer_->IsWritePending());
304 EXPECT_EQ(expected_write_result_, result);
308 void OnWriteComplete(int result) {
309 EXPECT_FALSE(writer_->IsWritePending());
310 EXPECT_EQ(expected_write_result_, result);
314 void OnReadInfoComplete(int result) {
315 EXPECT_FALSE(reader_->IsReadPending());
316 EXPECT_EQ(expected_read_result_, result);
320 void OnReadComplete(int result) {
321 EXPECT_FALSE(reader_->IsReadPending());
322 EXPECT_EQ(expected_read_result_, result);
326 // Helpers to work with HttpResponseInfo objects
328 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
329 net::HttpResponseInfo* info = new net::HttpResponseInfo;
330 info->request_time = base::Time::Now();
331 info->response_time = base::Time::Now();
332 info->was_cached = false;
333 info->headers = new net::HttpResponseHeaders(raw_headers);
337 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
339 return PickleHttpResonseInfo(&pickle, info);
342 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
343 const net::HttpResponseInfo* info2) {
346 PickleHttpResonseInfo(&pickle1, info1);
347 PickleHttpResonseInfo(&pickle2, info2);
348 return (pickle1.size() == pickle2.size()) &&
349 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
352 int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) {
353 const bool kSkipTransientHeaders = true;
354 const bool kTruncated = false;
355 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
356 return pickle->size();
359 // Helpers to fill and verify blocks of memory with a value
361 void FillData(char value, char* data, int data_len) {
362 memset(data, value, data_len);
365 bool CheckData(char value, const char* data, int data_len) {
366 for (int i = 0; i < data_len; ++i, ++data) {
373 // Individual Tests ---------------------------------------------------------
374 // Some of the individual tests involve multiple async steps. Each test
375 // is delineated with a section header.
377 // Basic -------------------------------------------------------------------
379 AppCacheStorage* storage = service_->storage();
380 net::URLRequest request(
381 GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, &empty_context_);
382 scoped_refptr<AppCacheURLRequestJob> job;
384 // Create an instance and see that it looks as expected.
386 job = new AppCacheURLRequestJob(
387 &request, NULL, storage, NULL, false);
388 EXPECT_TRUE(job->is_waiting());
389 EXPECT_FALSE(job->is_delivering_appcache_response());
390 EXPECT_FALSE(job->is_delivering_network_response());
391 EXPECT_FALSE(job->is_delivering_error_response());
392 EXPECT_FALSE(job->has_been_started());
393 EXPECT_FALSE(job->has_been_killed());
394 EXPECT_EQ(GURL(), job->manifest_url());
395 EXPECT_EQ(kNoCacheId, job->cache_id());
396 EXPECT_FALSE(job->entry().has_response_id());
401 // DeliveryOrders -----------------------------------------------------
402 void DeliveryOrders() {
403 AppCacheStorage* storage = service_->storage();
404 net::URLRequest request(
405 GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, &empty_context_);
406 scoped_refptr<AppCacheURLRequestJob> job;
408 // Create an instance, give it a delivery order and see that
409 // it looks as expected.
411 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
412 job->DeliverErrorResponse();
413 EXPECT_TRUE(job->is_delivering_error_response());
414 EXPECT_FALSE(job->has_been_started());
416 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
417 job->DeliverNetworkResponse();
418 EXPECT_TRUE(job->is_delivering_network_response());
419 EXPECT_FALSE(job->has_been_started());
421 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
422 const GURL kManifestUrl("http://blah/");
423 const int64 kCacheId(1);
424 const int64 kGroupId(1);
425 const AppCacheEntry kEntry(AppCacheEntry::EXPLICIT, 1);
426 job->DeliverAppCachedResponse(kManifestUrl, kCacheId, kGroupId,
428 EXPECT_FALSE(job->is_waiting());
429 EXPECT_TRUE(job->is_delivering_appcache_response());
430 EXPECT_FALSE(job->has_been_started());
431 EXPECT_EQ(kManifestUrl, job->manifest_url());
432 EXPECT_EQ(kCacheId, job->cache_id());
433 EXPECT_EQ(kGroupId, job->group_id());
434 EXPECT_EQ(kEntry.types(), job->entry().types());
435 EXPECT_EQ(kEntry.response_id(), job->entry().response_id());
440 // DeliverNetworkResponse --------------------------------------------------
442 void DeliverNetworkResponse() {
443 // This test has async steps.
445 base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverNetworkResponse,
446 base::Unretained(this)));
448 AppCacheStorage* storage = service_->storage();
449 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
450 net::DEFAULT_PRIORITY,
451 url_request_delegate_.get(),
454 // Setup to create an AppCacheURLRequestJob with orders to deliver
455 // a network response.
456 mock_factory_job_ = new AppCacheURLRequestJob(
457 request_.get(), NULL, storage, NULL, false);
458 mock_factory_job_->DeliverNetworkResponse();
459 EXPECT_TRUE(mock_factory_job_->is_delivering_network_response());
460 EXPECT_FALSE(mock_factory_job_->has_been_started());
462 // Start the request.
465 // The job should have been picked up.
466 EXPECT_FALSE(mock_factory_job_);
467 // Completion is async.
470 void VerifyDeliverNetworkResponse() {
471 EXPECT_EQ(request_->status().error(),
472 net::ERR_INTERNET_DISCONNECTED);
476 // DeliverErrorResponse --------------------------------------------------
478 void DeliverErrorResponse() {
479 // This test has async steps.
481 base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverErrorResponse,
482 base::Unretained(this)));
484 AppCacheStorage* storage = service_->storage();
485 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
486 net::DEFAULT_PRIORITY,
487 url_request_delegate_.get(),
490 // Setup to create an AppCacheURLRequestJob with orders to deliver
491 // a network response.
492 mock_factory_job_ = new AppCacheURLRequestJob(
493 request_.get(), NULL, storage, NULL, false);
494 mock_factory_job_->DeliverErrorResponse();
495 EXPECT_TRUE(mock_factory_job_->is_delivering_error_response());
496 EXPECT_FALSE(mock_factory_job_->has_been_started());
498 // Start the request.
501 // The job should have been picked up.
502 EXPECT_FALSE(mock_factory_job_);
503 // Completion is async.
506 void VerifyDeliverErrorResponse() {
507 EXPECT_EQ(request_->status().error(), net::ERR_FAILED);
511 // DeliverSmallAppCachedResponse --------------------------------------
512 // "Small" being small enough to read completely in a single
513 // request->Read call.
515 void DeliverSmallAppCachedResponse() {
516 // This test has several async steps.
517 // 1. Write a small response to response storage.
518 // 2. Use net::URLRequest to retrieve it.
519 // 3. Verify we received what we expected to receive.
521 PushNextTask(base::Bind(
522 &AppCacheURLRequestJobTest::VerifyDeliverSmallAppCachedResponse,
523 base::Unretained(this)));
525 base::Bind(&AppCacheURLRequestJobTest::RequestAppCachedResource,
526 base::Unretained(this), false));
528 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
529 written_response_id_ = writer_->response_id();
530 WriteBasicResponse();
534 void RequestAppCachedResource(bool start_after_delivery_orders) {
535 AppCacheStorage* storage = service_->storage();
536 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
537 net::DEFAULT_PRIORITY,
538 url_request_delegate_.get(),
541 // Setup to create an AppCacheURLRequestJob with orders to deliver
542 // a network response.
543 scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
544 request_.get(), NULL, storage, NULL, false));
546 if (start_after_delivery_orders) {
547 job->DeliverAppCachedResponse(
549 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
551 EXPECT_TRUE(job->is_delivering_appcache_response());
554 // Start the request.
555 EXPECT_FALSE(job->has_been_started());
556 mock_factory_job_ = job.get();
558 EXPECT_FALSE(mock_factory_job_);
559 EXPECT_TRUE(job->has_been_started());
561 if (!start_after_delivery_orders) {
562 job->DeliverAppCachedResponse(
564 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
566 EXPECT_TRUE(job->is_delivering_appcache_response());
569 // Completion is async.
572 void VerifyDeliverSmallAppCachedResponse() {
573 EXPECT_TRUE(request_->status().is_success());
574 EXPECT_TRUE(CompareHttpResponseInfos(
575 write_info_buffer_->http_info.get(),
576 &url_request_delegate_->received_info_));
577 EXPECT_EQ(5, url_request_delegate_->amount_received_);
578 EXPECT_EQ(0, memcmp(kHttpBasicBody,
579 url_request_delegate_->received_data_->data(),
580 strlen(kHttpBasicBody)));
584 // DeliverLargeAppCachedResponse --------------------------------------
585 // "Large" enough to require multiple calls to request->Read to complete.
587 void DeliverLargeAppCachedResponse() {
588 // This test has several async steps.
589 // 1. Write a large response to response storage.
590 // 2. Use net::URLRequest to retrieve it.
591 // 3. Verify we received what we expected to receive.
593 PushNextTask(base::Bind(
594 &AppCacheURLRequestJobTest::VerifyDeliverLargeAppCachedResponse,
595 base::Unretained(this)));
596 PushNextTask(base::Bind(
597 &AppCacheURLRequestJobTest::RequestAppCachedResource,
598 base::Unretained(this), true));
600 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
601 written_response_id_ = writer_->response_id();
602 WriteLargeResponse();
606 void WriteLargeResponse() {
608 static const char kHttpHeaders[] =
609 "HTTP/1.0 200 OK\0Content-Length: 3072\0\0";
610 scoped_refptr<IOBuffer> body(new IOBuffer(kBlockSize * 3));
611 char* p = body->data();
612 for (int i = 0; i < 3; ++i, p += kBlockSize)
613 FillData(i + 1, p, kBlockSize);
614 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
616 MakeHttpResponseInfo(raw_headers), body.get(), kBlockSize * 3);
619 void VerifyDeliverLargeAppCachedResponse() {
620 EXPECT_TRUE(request_->status().is_success());
621 EXPECT_TRUE(CompareHttpResponseInfos(
622 write_info_buffer_->http_info.get(),
623 &url_request_delegate_->received_info_));
624 EXPECT_EQ(3072, url_request_delegate_->amount_received_);
625 char* p = url_request_delegate_->received_data_->data();
626 for (int i = 0; i < 3; ++i, p += kBlockSize)
627 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
631 // DeliverPartialResponse --------------------------------------
633 void DeliverPartialResponse() {
634 // This test has several async steps.
635 // 1. Write a small response to response storage.
636 // 2. Use net::URLRequest to retrieve it a subset using a range request
637 // 3. Verify we received what we expected to receive.
638 PushNextTask(base::Bind(
639 &AppCacheURLRequestJobTest::VerifyDeliverPartialResponse,
640 base::Unretained(this)));
641 PushNextTask(base::Bind(
642 &AppCacheURLRequestJobTest::MakeRangeRequest, base::Unretained(this)));
643 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
644 written_response_id_ = writer_->response_id();
645 WriteBasicResponse();
649 void MakeRangeRequest() {
650 AppCacheStorage* storage = service_->storage();
651 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
652 net::DEFAULT_PRIORITY,
653 url_request_delegate_.get(),
656 // Request a range, the 3 middle chars out of 'Hello'
657 net::HttpRequestHeaders extra_headers;
658 extra_headers.SetHeader("Range", "bytes= 1-3");
659 request_->SetExtraRequestHeaders(extra_headers);
661 // Create job with orders to deliver an appcached entry.
662 scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
663 request_.get(), NULL, storage, NULL, false));
664 job->DeliverAppCachedResponse(
666 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
668 EXPECT_TRUE(job->is_delivering_appcache_response());
670 // Start the request.
671 EXPECT_FALSE(job->has_been_started());
672 mock_factory_job_ = job.get();
674 EXPECT_FALSE(mock_factory_job_);
675 EXPECT_TRUE(job->has_been_started());
676 // Completion is async.
679 void VerifyDeliverPartialResponse() {
680 EXPECT_TRUE(request_->status().is_success());
681 EXPECT_EQ(3, url_request_delegate_->amount_received_);
682 EXPECT_EQ(0, memcmp(kHttpBasicBody + 1,
683 url_request_delegate_->received_data_->data(),
685 net::HttpResponseHeaders* headers =
686 url_request_delegate_->received_info_.headers.get();
687 EXPECT_EQ(206, headers->response_code());
688 EXPECT_EQ(3, headers->GetContentLength());
689 int64 range_start, range_end, object_size;
691 headers->GetContentRange(&range_start, &range_end, &object_size));
692 EXPECT_EQ(1, range_start);
693 EXPECT_EQ(3, range_end);
694 EXPECT_EQ(5, object_size);
698 // CancelRequest --------------------------------------
700 void CancelRequest() {
701 // This test has several async steps.
702 // 1. Write a large response to response storage.
703 // 2. Use net::URLRequest to retrieve it.
704 // 3. Cancel the request after data starts coming in.
706 PushNextTask(base::Bind(
707 &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this)));
708 PushNextTask(base::Bind(
709 &AppCacheURLRequestJobTest::RequestAppCachedResource,
710 base::Unretained(this), true));
712 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
713 written_response_id_ = writer_->response_id();
714 WriteLargeResponse();
716 url_request_delegate_->kill_after_amount_received_ = kBlockSize;
717 url_request_delegate_->kill_with_io_pending_ = false;
721 void VerifyCancel() {
722 EXPECT_EQ(net::URLRequestStatus::CANCELED,
723 request_->status().status());
727 // CancelRequestWithIOPending --------------------------------------
729 void CancelRequestWithIOPending() {
730 // This test has several async steps.
731 // 1. Write a large response to response storage.
732 // 2. Use net::URLRequest to retrieve it.
733 // 3. Cancel the request after data starts coming in.
735 PushNextTask(base::Bind(
736 &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this)));
737 PushNextTask(base::Bind(
738 &AppCacheURLRequestJobTest::RequestAppCachedResource,
739 base::Unretained(this), true));
741 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
742 written_response_id_ = writer_->response_id();
743 WriteLargeResponse();
745 url_request_delegate_->kill_after_amount_received_ = kBlockSize;
746 url_request_delegate_->kill_with_io_pending_ = true;
751 // Data members --------------------------------------------------------
753 scoped_ptr<base::WaitableEvent> test_finished_event_;
754 scoped_ptr<MockStorageDelegate> storage_delegate_;
755 scoped_ptr<MockAppCacheService> service_;
756 std::stack<std::pair<base::Closure, bool> > task_stack_;
758 scoped_ptr<AppCacheResponseReader> reader_;
759 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
760 scoped_refptr<IOBuffer> read_buffer_;
761 int expected_read_result_;
762 int reader_deletion_count_down_;
764 int64 written_response_id_;
765 scoped_ptr<AppCacheResponseWriter> writer_;
766 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
767 scoped_refptr<IOBuffer> write_buffer_;
768 int expected_write_result_;
769 int writer_deletion_count_down_;
771 net::URLRequest::ProtocolFactory* orig_http_factory_;
772 net::URLRequestContext empty_context_;
773 scoped_ptr<net::URLRequest> request_;
774 scoped_ptr<MockURLRequestDelegate> url_request_delegate_;
776 static scoped_ptr<base::Thread> io_thread_;
777 static AppCacheURLRequestJob* mock_factory_job_;
781 scoped_ptr<base::Thread> AppCacheURLRequestJobTest::io_thread_;
782 AppCacheURLRequestJob* AppCacheURLRequestJobTest::mock_factory_job_ = NULL;
784 TEST_F(AppCacheURLRequestJobTest, Basic) {
785 RunTestOnIOThread(&AppCacheURLRequestJobTest::Basic);
788 TEST_F(AppCacheURLRequestJobTest, DeliveryOrders) {
789 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliveryOrders);
792 TEST_F(AppCacheURLRequestJobTest, DeliverNetworkResponse) {
793 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverNetworkResponse);
796 TEST_F(AppCacheURLRequestJobTest, DeliverErrorResponse) {
797 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverErrorResponse);
800 TEST_F(AppCacheURLRequestJobTest, DeliverSmallAppCachedResponse) {
801 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverSmallAppCachedResponse);
804 TEST_F(AppCacheURLRequestJobTest, DeliverLargeAppCachedResponse) {
805 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverLargeAppCachedResponse);
808 TEST_F(AppCacheURLRequestJobTest, DeliverPartialResponse) {
809 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverPartialResponse);
812 TEST_F(AppCacheURLRequestJobTest, CancelRequest) {
813 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequest);
816 TEST_F(AppCacheURLRequestJobTest, CancelRequestWithIOPending) {
817 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequestWithIOPending);
820 } // namespace appcache