Dismiss autofill popup on screen orientation change.
[chromium-blink-merge.git] / webkit / browser / appcache / appcache_url_request_job_unittest.cc
blob95ad3bb8ae22689919fb2ccc7f79611dcc3235d0
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.
5 #include <stack>
6 #include <utility>
8 #include "base/bind.h"
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/browser/appcache/appcache_response.h"
23 #include "webkit/browser/appcache/appcache_url_request_job.h"
24 #include "webkit/browser/appcache/mock_appcache_service.h"
26 using net::IOBuffer;
27 using net::WrappedIOBuffer;
29 namespace appcache {
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 {
39 public:
41 // Test Harness -------------------------------------------------------------
42 // TODO(michaeln): share this test harness with AppCacheResponseTest
44 class MockStorageDelegate : public AppCacheStorage::Delegate {
45 public:
46 explicit MockStorageDelegate(AppCacheURLRequestJobTest* test)
47 : loaded_info_id_(0), test_(test) {
50 virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
51 int64 response_id) OVERRIDE {
52 loaded_info_ = 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 {
63 public:
64 explicit MockURLRequestDelegate(AppCacheURLRequestJobTest* test)
65 : test_(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) OVERRIDE {
72 amount_received_ = 0;
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();
78 ReadSome(request);
79 } else {
80 RequestComplete();
84 virtual void OnReadCompleted(net::URLRequest* request,
85 int bytes_read) OVERRIDE {
86 if (bytes_read > 0) {
87 amount_received_ += bytes_read;
89 if (kill_after_amount_received_ && !kill_with_io_pending_) {
90 if (amount_received_ >= kill_after_amount_received_) {
91 request->Cancel();
92 return;
96 ReadSome(request);
98 if (kill_after_amount_received_ && kill_with_io_pending_) {
99 if (amount_received_ >= kill_after_amount_received_) {
100 request->Cancel();
101 return;
104 } else {
105 RequestComplete();
109 void ReadSome(net::URLRequest* request) {
110 DCHECK(amount_received_ + kBlockSize <= kNumBlocks * kBlockSize);
111 scoped_refptr<IOBuffer> wrapped_buffer(
112 new net::WrappedIOBuffer(received_data_->data() + amount_received_));
113 int bytes_read = 0;
114 EXPECT_FALSE(
115 request->Read(wrapped_buffer.get(), kBlockSize, &bytes_read));
116 EXPECT_EQ(0, bytes_read);
119 void RequestComplete() {
120 test_->ScheduleNextTask();
123 AppCacheURLRequestJobTest* test_;
124 net::HttpResponseInfo received_info_;
125 scoped_refptr<net::IOBuffer> received_data_;
126 bool did_receive_headers_;
127 int amount_received_;
128 int kill_after_amount_received_;
129 bool kill_with_io_pending_;
132 static net::URLRequestJob* MockHttpJobFactory(
133 net::URLRequest* request,
134 net::NetworkDelegate* network_delegate,
135 const std::string& scheme) {
136 if (mock_factory_job_) {
137 net::URLRequestJob* temp = mock_factory_job_;
138 mock_factory_job_ = NULL;
139 return temp;
140 } else {
141 return new net::URLRequestErrorJob(request,
142 network_delegate,
143 net::ERR_INTERNET_DISCONNECTED);
147 // Helper callback to run a test on our io_thread. The io_thread is spun up
148 // once and reused for all tests.
149 template <class Method>
150 void MethodWrapper(Method method) {
151 SetUpTest();
152 (this->*method)();
155 static void SetUpTestCase() {
156 io_thread_.reset(new base::Thread("AppCacheURLRequestJobTest Thread"));
157 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
158 io_thread_->StartWithOptions(options);
161 static void TearDownTestCase() {
162 io_thread_.reset(NULL);
165 AppCacheURLRequestJobTest() {}
167 template <class Method>
168 void RunTestOnIOThread(Method method) {
169 test_finished_event_ .reset(new base::WaitableEvent(false, false));
170 io_thread_->message_loop()->PostTask(
171 FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper<Method>,
172 base::Unretained(this), method));
173 test_finished_event_->Wait();
176 void SetUpTest() {
177 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
178 DCHECK(task_stack_.empty());
179 orig_http_factory_ = net::URLRequest::Deprecated::RegisterProtocolFactory(
180 "http", MockHttpJobFactory);
181 url_request_delegate_.reset(new MockURLRequestDelegate(this));
182 storage_delegate_.reset(new MockStorageDelegate(this));
183 service_.reset(new MockAppCacheService());
184 expected_read_result_ = 0;
185 expected_write_result_ = 0;
186 written_response_id_ = 0;
187 reader_deletion_count_down_ = 0;
188 writer_deletion_count_down_ = 0;
191 void TearDownTest() {
192 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
193 net::URLRequest::Deprecated::RegisterProtocolFactory("http",
194 orig_http_factory_);
195 orig_http_factory_ = NULL;
196 request_.reset();
197 url_request_delegate_.reset();
198 DCHECK(!mock_factory_job_);
200 while (!task_stack_.empty())
201 task_stack_.pop();
203 reader_.reset();
204 read_buffer_ = NULL;
205 read_info_buffer_ = NULL;
206 writer_.reset();
207 write_buffer_ = NULL;
208 write_info_buffer_ = NULL;
209 storage_delegate_.reset();
210 service_.reset();
213 void TestFinished() {
214 // We unwind the stack prior to finishing up to let stack
215 // based objects get deleted.
216 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
217 base::MessageLoop::current()->PostTask(
218 FROM_HERE,
219 base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound,
220 base::Unretained(this)));
223 void TestFinishedUnwound() {
224 TearDownTest();
225 test_finished_event_->Signal();
228 void PushNextTask(const base::Closure& task) {
229 task_stack_.push(std::pair<base::Closure, bool>(task, false));
232 void PushNextTaskAsImmediate(const base::Closure& task) {
233 task_stack_.push(std::pair<base::Closure, bool>(task, true));
236 void ScheduleNextTask() {
237 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
238 if (task_stack_.empty()) {
239 TestFinished();
240 return;
242 base::Closure task =task_stack_.top().first;
243 bool immediate = task_stack_.top().second;
244 task_stack_.pop();
245 if (immediate)
246 task.Run();
247 else
248 base::MessageLoop::current()->PostTask(FROM_HERE, task);
251 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
253 void WriteBasicResponse() {
254 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBasicBody));
255 std::string raw_headers(kHttpBasicHeaders, arraysize(kHttpBasicHeaders));
256 WriteResponse(
257 MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBasicBody));
260 void WriteResponse(net::HttpResponseInfo* head,
261 IOBuffer* body, int body_len) {
262 DCHECK(body);
263 scoped_refptr<IOBuffer> body_ref(body);
264 PushNextTask(base::Bind(&AppCacheURLRequestJobTest::WriteResponseBody,
265 base::Unretained(this), body_ref, body_len));
266 WriteResponseHead(head);
269 void WriteResponseHead(net::HttpResponseInfo* head) {
270 EXPECT_FALSE(writer_->IsWritePending());
271 expected_write_result_ = GetHttpResponseInfoSize(head);
272 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
273 writer_->WriteInfo(
274 write_info_buffer_.get(),
275 base::Bind(&AppCacheURLRequestJobTest::OnWriteInfoComplete,
276 base::Unretained(this)));
279 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
280 EXPECT_FALSE(writer_->IsWritePending());
281 write_buffer_ = io_buffer;
282 expected_write_result_ = buf_len;
283 writer_->WriteData(write_buffer_.get(),
284 buf_len,
285 base::Bind(&AppCacheURLRequestJobTest::OnWriteComplete,
286 base::Unretained(this)));
289 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
290 EXPECT_FALSE(reader_->IsReadPending());
291 read_buffer_ = io_buffer;
292 expected_read_result_ = buf_len;
293 reader_->ReadData(read_buffer_.get(),
294 buf_len,
295 base::Bind(&AppCacheURLRequestJobTest::OnReadComplete,
296 base::Unretained(this)));
299 // AppCacheResponseReader / Writer completion callbacks
301 void OnWriteInfoComplete(int result) {
302 EXPECT_FALSE(writer_->IsWritePending());
303 EXPECT_EQ(expected_write_result_, result);
304 ScheduleNextTask();
307 void OnWriteComplete(int result) {
308 EXPECT_FALSE(writer_->IsWritePending());
309 EXPECT_EQ(expected_write_result_, result);
310 ScheduleNextTask();
313 void OnReadInfoComplete(int result) {
314 EXPECT_FALSE(reader_->IsReadPending());
315 EXPECT_EQ(expected_read_result_, result);
316 ScheduleNextTask();
319 void OnReadComplete(int result) {
320 EXPECT_FALSE(reader_->IsReadPending());
321 EXPECT_EQ(expected_read_result_, result);
322 ScheduleNextTask();
325 // Helpers to work with HttpResponseInfo objects
327 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
328 net::HttpResponseInfo* info = new net::HttpResponseInfo;
329 info->request_time = base::Time::Now();
330 info->response_time = base::Time::Now();
331 info->was_cached = false;
332 info->headers = new net::HttpResponseHeaders(raw_headers);
333 return info;
336 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
337 Pickle pickle;
338 return PickleHttpResonseInfo(&pickle, info);
341 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
342 const net::HttpResponseInfo* info2) {
343 Pickle pickle1;
344 Pickle pickle2;
345 PickleHttpResonseInfo(&pickle1, info1);
346 PickleHttpResonseInfo(&pickle2, info2);
347 return (pickle1.size() == pickle2.size()) &&
348 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
351 int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) {
352 const bool kSkipTransientHeaders = true;
353 const bool kTruncated = false;
354 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
355 return pickle->size();
358 // Helpers to fill and verify blocks of memory with a value
360 void FillData(char value, char* data, int data_len) {
361 memset(data, value, data_len);
364 bool CheckData(char value, const char* data, int data_len) {
365 for (int i = 0; i < data_len; ++i, ++data) {
366 if (*data != value)
367 return false;
369 return true;
372 // Individual Tests ---------------------------------------------------------
373 // Some of the individual tests involve multiple async steps. Each test
374 // is delineated with a section header.
376 // Basic -------------------------------------------------------------------
377 void Basic() {
378 AppCacheStorage* storage = service_->storage();
379 net::URLRequest request(GURL("http://blah/"), NULL, &empty_context_);
380 scoped_refptr<AppCacheURLRequestJob> job;
382 // Create an instance and see that it looks as expected.
384 job = new AppCacheURLRequestJob(
385 &request, NULL, storage, NULL);
386 EXPECT_TRUE(job->is_waiting());
387 EXPECT_FALSE(job->is_delivering_appcache_response());
388 EXPECT_FALSE(job->is_delivering_network_response());
389 EXPECT_FALSE(job->is_delivering_error_response());
390 EXPECT_FALSE(job->has_been_started());
391 EXPECT_FALSE(job->has_been_killed());
392 EXPECT_EQ(GURL(), job->manifest_url());
393 EXPECT_EQ(kNoCacheId, job->cache_id());
394 EXPECT_FALSE(job->entry().has_response_id());
396 TestFinished();
399 // DeliveryOrders -----------------------------------------------------
400 void DeliveryOrders() {
401 AppCacheStorage* storage = service_->storage();
402 net::URLRequest request(GURL("http://blah/"), NULL, &empty_context_);
403 scoped_refptr<AppCacheURLRequestJob> job;
405 // Create an instance, give it a delivery order and see that
406 // it looks as expected.
408 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL);
409 job->DeliverErrorResponse();
410 EXPECT_TRUE(job->is_delivering_error_response());
411 EXPECT_FALSE(job->has_been_started());
413 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL);
414 job->DeliverNetworkResponse();
415 EXPECT_TRUE(job->is_delivering_network_response());
416 EXPECT_FALSE(job->has_been_started());
418 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL);
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,
424 kEntry, false);
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());
434 TestFinished();
437 // DeliverNetworkResponse --------------------------------------------------
439 void DeliverNetworkResponse() {
440 // This test has async steps.
441 PushNextTask(
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(), NULL, storage, NULL);
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.
458 request_->Start();
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);
468 TestFinished();
471 // DeliverErrorResponse --------------------------------------------------
473 void DeliverErrorResponse() {
474 // This test has async steps.
475 PushNextTask(
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(), NULL, storage, NULL);
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.
492 request_->Start();
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);
501 TestFinished();
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)));
517 PushNextTask(
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();
524 // Continues async
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(), NULL, storage, NULL));
537 if (start_after_delivery_orders) {
538 job->DeliverAppCachedResponse(
539 GURL(), 0, 111,
540 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
541 false);
542 EXPECT_TRUE(job->is_delivering_appcache_response());
545 // Start the request.
546 EXPECT_FALSE(job->has_been_started());
547 mock_factory_job_ = job.get();
548 request_->Start();
549 EXPECT_FALSE(mock_factory_job_);
550 EXPECT_TRUE(job->has_been_started());
552 if (!start_after_delivery_orders) {
553 job->DeliverAppCachedResponse(
554 GURL(), 0, 111,
555 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
556 false);
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)));
572 TestFinished();
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();
594 // Continues async
597 void WriteLargeResponse() {
598 // 3, 1k blocks
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(
607 MakeHttpResponseInfo(raw_headers), body.get(), kBlockSize * 3);
610 void VerifyDeliverLargeAppCachedResponse() {
611 EXPECT_TRUE(request_->status().is_success());
612 EXPECT_TRUE(CompareHttpResponseInfos(
613 write_info_buffer_->http_info.get(),
614 &url_request_delegate_->received_info_));
615 EXPECT_EQ(3072, url_request_delegate_->amount_received_);
616 char* p = url_request_delegate_->received_data_->data();
617 for (int i = 0; i < 3; ++i, p += kBlockSize)
618 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
619 TestFinished();
622 // DeliverPartialResponse --------------------------------------
624 void DeliverPartialResponse() {
625 // This test has several async steps.
626 // 1. Write a small response to response storage.
627 // 2. Use net::URLRequest to retrieve it a subset using a range request
628 // 3. Verify we received what we expected to receive.
629 PushNextTask(base::Bind(
630 &AppCacheURLRequestJobTest::VerifyDeliverPartialResponse,
631 base::Unretained(this)));
632 PushNextTask(base::Bind(
633 &AppCacheURLRequestJobTest::MakeRangeRequest, base::Unretained(this)));
634 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
635 written_response_id_ = writer_->response_id();
636 WriteBasicResponse();
637 // Continues async
640 void MakeRangeRequest() {
641 AppCacheStorage* storage = service_->storage();
642 request_.reset(empty_context_.CreateRequest(
643 GURL("http://blah/"), url_request_delegate_.get()));
645 // Request a range, the 3 middle chars out of 'Hello'
646 net::HttpRequestHeaders extra_headers;
647 extra_headers.SetHeader("Range", "bytes= 1-3");
648 request_->SetExtraRequestHeaders(extra_headers);
650 // Create job with orders to deliver an appcached entry.
651 scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
652 request_.get(), NULL, storage, NULL));
653 job->DeliverAppCachedResponse(
654 GURL(), 0, 111,
655 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
656 false);
657 EXPECT_TRUE(job->is_delivering_appcache_response());
659 // Start the request.
660 EXPECT_FALSE(job->has_been_started());
661 mock_factory_job_ = job.get();
662 request_->Start();
663 EXPECT_FALSE(mock_factory_job_);
664 EXPECT_TRUE(job->has_been_started());
665 // Completion is async.
668 void VerifyDeliverPartialResponse() {
669 EXPECT_TRUE(request_->status().is_success());
670 EXPECT_EQ(3, url_request_delegate_->amount_received_);
671 EXPECT_EQ(0, memcmp(kHttpBasicBody + 1,
672 url_request_delegate_->received_data_->data(),
673 3));
674 net::HttpResponseHeaders* headers =
675 url_request_delegate_->received_info_.headers.get();
676 EXPECT_EQ(206, headers->response_code());
677 EXPECT_EQ(3, headers->GetContentLength());
678 int64 range_start, range_end, object_size;
679 EXPECT_TRUE(
680 headers->GetContentRange(&range_start, &range_end, &object_size));
681 EXPECT_EQ(1, range_start);
682 EXPECT_EQ(3, range_end);
683 EXPECT_EQ(5, object_size);
684 TestFinished();
687 // CancelRequest --------------------------------------
689 void CancelRequest() {
690 // This test has several async steps.
691 // 1. Write a large response to response storage.
692 // 2. Use net::URLRequest to retrieve it.
693 // 3. Cancel the request after data starts coming in.
695 PushNextTask(base::Bind(
696 &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this)));
697 PushNextTask(base::Bind(
698 &AppCacheURLRequestJobTest::RequestAppCachedResource,
699 base::Unretained(this), true));
701 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
702 written_response_id_ = writer_->response_id();
703 WriteLargeResponse();
705 url_request_delegate_->kill_after_amount_received_ = kBlockSize;
706 url_request_delegate_->kill_with_io_pending_ = false;
707 // Continues async
710 void VerifyCancel() {
711 EXPECT_EQ(net::URLRequestStatus::CANCELED,
712 request_->status().status());
713 TestFinished();
716 // CancelRequestWithIOPending --------------------------------------
718 void CancelRequestWithIOPending() {
719 // This test has several async steps.
720 // 1. Write a large response to response storage.
721 // 2. Use net::URLRequest to retrieve it.
722 // 3. Cancel the request after data starts coming in.
724 PushNextTask(base::Bind(
725 &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this)));
726 PushNextTask(base::Bind(
727 &AppCacheURLRequestJobTest::RequestAppCachedResource,
728 base::Unretained(this), true));
730 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
731 written_response_id_ = writer_->response_id();
732 WriteLargeResponse();
734 url_request_delegate_->kill_after_amount_received_ = kBlockSize;
735 url_request_delegate_->kill_with_io_pending_ = true;
736 // Continues async
740 // Data members --------------------------------------------------------
742 scoped_ptr<base::WaitableEvent> test_finished_event_;
743 scoped_ptr<MockStorageDelegate> storage_delegate_;
744 scoped_ptr<MockAppCacheService> service_;
745 std::stack<std::pair<base::Closure, bool> > task_stack_;
747 scoped_ptr<AppCacheResponseReader> reader_;
748 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
749 scoped_refptr<IOBuffer> read_buffer_;
750 int expected_read_result_;
751 int reader_deletion_count_down_;
753 int64 written_response_id_;
754 scoped_ptr<AppCacheResponseWriter> writer_;
755 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
756 scoped_refptr<IOBuffer> write_buffer_;
757 int expected_write_result_;
758 int writer_deletion_count_down_;
760 net::URLRequest::ProtocolFactory* orig_http_factory_;
761 net::URLRequestContext empty_context_;
762 scoped_ptr<net::URLRequest> request_;
763 scoped_ptr<MockURLRequestDelegate> url_request_delegate_;
765 static scoped_ptr<base::Thread> io_thread_;
766 static AppCacheURLRequestJob* mock_factory_job_;
769 // static
770 scoped_ptr<base::Thread> AppCacheURLRequestJobTest::io_thread_;
771 AppCacheURLRequestJob* AppCacheURLRequestJobTest::mock_factory_job_ = NULL;
773 TEST_F(AppCacheURLRequestJobTest, Basic) {
774 RunTestOnIOThread(&AppCacheURLRequestJobTest::Basic);
777 TEST_F(AppCacheURLRequestJobTest, DeliveryOrders) {
778 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliveryOrders);
781 TEST_F(AppCacheURLRequestJobTest, DeliverNetworkResponse) {
782 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverNetworkResponse);
785 TEST_F(AppCacheURLRequestJobTest, DeliverErrorResponse) {
786 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverErrorResponse);
789 TEST_F(AppCacheURLRequestJobTest, DeliverSmallAppCachedResponse) {
790 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverSmallAppCachedResponse);
793 TEST_F(AppCacheURLRequestJobTest, DeliverLargeAppCachedResponse) {
794 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverLargeAppCachedResponse);
797 TEST_F(AppCacheURLRequestJobTest, DeliverPartialResponse) {
798 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverPartialResponse);
801 TEST_F(AppCacheURLRequestJobTest, CancelRequest) {
802 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequest);
805 TEST_F(AppCacheURLRequestJobTest, CancelRequestWithIOPending) {
806 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequestWithIOPending);
809 } // namespace appcache