Save running SW instance info, including its SiteInstance, into the ProcessManager.
[chromium-blink-merge.git] / content / browser / appcache / appcache_url_request_job_unittest.cc
blob5636aacae99621e683cbad09984f0b30c6a18760
1 // Copyright 2014 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 "content/browser/appcache/mock_appcache_service.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/request_priority.h"
19 #include "net/http/http_response_headers.h"
20 #include "net/url_request/url_request.h"
21 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_error_job.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "webkit/browser/appcache/appcache_response.h"
25 #include "webkit/browser/appcache/appcache_url_request_job.h"
27 using appcache::AppCacheEntry;
28 using appcache::AppCacheStorage;
29 using appcache::AppCacheResponseInfo;
30 using appcache::AppCacheResponseReader;
31 using appcache::AppCacheResponseWriter;
32 using appcache::AppCacheURLRequestJob;
33 using appcache::HttpResponseInfoIOBuffer;
34 using appcache::kNoCacheId;
35 using net::IOBuffer;
36 using net::WrappedIOBuffer;
38 namespace content {
40 static const char kHttpBasicHeaders[] =
41 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
42 static const char kHttpBasicBody[] = "Hello";
44 static const int kNumBlocks = 4;
45 static const int kBlockSize = 1024;
47 class AppCacheURLRequestJobTest : public testing::Test {
48 public:
50 // Test Harness -------------------------------------------------------------
51 // TODO(michaeln): share this test harness with AppCacheResponseTest
53 class MockStorageDelegate : public AppCacheStorage::Delegate {
54 public:
55 explicit MockStorageDelegate(AppCacheURLRequestJobTest* test)
56 : loaded_info_id_(0), test_(test) {
59 virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
60 int64 response_id) OVERRIDE {
61 loaded_info_ = info;
62 loaded_info_id_ = response_id;
63 test_->ScheduleNextTask();
66 scoped_refptr<AppCacheResponseInfo> loaded_info_;
67 int64 loaded_info_id_;
68 AppCacheURLRequestJobTest* test_;
71 class MockURLRequestDelegate : public net::URLRequest::Delegate {
72 public:
73 explicit MockURLRequestDelegate(AppCacheURLRequestJobTest* test)
74 : test_(test),
75 received_data_(new net::IOBuffer(kNumBlocks * kBlockSize)),
76 did_receive_headers_(false), amount_received_(0),
77 kill_after_amount_received_(0), kill_with_io_pending_(false) {
80 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
81 amount_received_ = 0;
82 did_receive_headers_ = false;
83 if (request->status().is_success()) {
84 EXPECT_TRUE(request->response_headers());
85 did_receive_headers_ = true;
86 received_info_ = request->response_info();
87 ReadSome(request);
88 } else {
89 RequestComplete();
93 virtual void OnReadCompleted(net::URLRequest* request,
94 int bytes_read) OVERRIDE {
95 if (bytes_read > 0) {
96 amount_received_ += bytes_read;
98 if (kill_after_amount_received_ && !kill_with_io_pending_) {
99 if (amount_received_ >= kill_after_amount_received_) {
100 request->Cancel();
101 return;
105 ReadSome(request);
107 if (kill_after_amount_received_ && kill_with_io_pending_) {
108 if (amount_received_ >= kill_after_amount_received_) {
109 request->Cancel();
110 return;
113 } else {
114 RequestComplete();
118 void ReadSome(net::URLRequest* request) {
119 DCHECK(amount_received_ + kBlockSize <= kNumBlocks * kBlockSize);
120 scoped_refptr<IOBuffer> wrapped_buffer(
121 new net::WrappedIOBuffer(received_data_->data() + amount_received_));
122 int bytes_read = 0;
123 EXPECT_FALSE(
124 request->Read(wrapped_buffer.get(), kBlockSize, &bytes_read));
125 EXPECT_EQ(0, bytes_read);
128 void RequestComplete() {
129 test_->ScheduleNextTask();
132 AppCacheURLRequestJobTest* test_;
133 net::HttpResponseInfo received_info_;
134 scoped_refptr<net::IOBuffer> received_data_;
135 bool did_receive_headers_;
136 int amount_received_;
137 int kill_after_amount_received_;
138 bool kill_with_io_pending_;
141 static net::URLRequestJob* MockHttpJobFactory(
142 net::URLRequest* request,
143 net::NetworkDelegate* network_delegate,
144 const std::string& scheme) {
145 if (mock_factory_job_) {
146 net::URLRequestJob* temp = mock_factory_job_;
147 mock_factory_job_ = NULL;
148 return temp;
149 } else {
150 return new net::URLRequestErrorJob(request,
151 network_delegate,
152 net::ERR_INTERNET_DISCONNECTED);
156 // Helper callback to run a test on our io_thread. The io_thread is spun up
157 // once and reused for all tests.
158 template <class Method>
159 void MethodWrapper(Method method) {
160 SetUpTest();
161 (this->*method)();
164 static void SetUpTestCase() {
165 io_thread_.reset(new base::Thread("AppCacheURLRequestJobTest Thread"));
166 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
167 io_thread_->StartWithOptions(options);
170 static void TearDownTestCase() {
171 io_thread_.reset(NULL);
174 AppCacheURLRequestJobTest() {}
176 template <class Method>
177 void RunTestOnIOThread(Method method) {
178 test_finished_event_ .reset(new base::WaitableEvent(false, false));
179 io_thread_->message_loop()->PostTask(
180 FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper<Method>,
181 base::Unretained(this), method));
182 test_finished_event_->Wait();
185 void SetUpTest() {
186 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
187 DCHECK(task_stack_.empty());
188 orig_http_factory_ = net::URLRequest::Deprecated::RegisterProtocolFactory(
189 "http", MockHttpJobFactory);
190 url_request_delegate_.reset(new MockURLRequestDelegate(this));
191 storage_delegate_.reset(new MockStorageDelegate(this));
192 service_.reset(new MockAppCacheService());
193 expected_read_result_ = 0;
194 expected_write_result_ = 0;
195 written_response_id_ = 0;
196 reader_deletion_count_down_ = 0;
197 writer_deletion_count_down_ = 0;
200 void TearDownTest() {
201 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
202 net::URLRequest::Deprecated::RegisterProtocolFactory("http",
203 orig_http_factory_);
204 orig_http_factory_ = NULL;
205 request_.reset();
206 url_request_delegate_.reset();
207 DCHECK(!mock_factory_job_);
209 while (!task_stack_.empty())
210 task_stack_.pop();
212 reader_.reset();
213 read_buffer_ = NULL;
214 read_info_buffer_ = NULL;
215 writer_.reset();
216 write_buffer_ = NULL;
217 write_info_buffer_ = NULL;
218 storage_delegate_.reset();
219 service_.reset();
222 void TestFinished() {
223 // We unwind the stack prior to finishing up to let stack
224 // based objects get deleted.
225 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
226 base::MessageLoop::current()->PostTask(
227 FROM_HERE,
228 base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound,
229 base::Unretained(this)));
232 void TestFinishedUnwound() {
233 TearDownTest();
234 test_finished_event_->Signal();
237 void PushNextTask(const base::Closure& task) {
238 task_stack_.push(std::pair<base::Closure, bool>(task, false));
241 void PushNextTaskAsImmediate(const base::Closure& task) {
242 task_stack_.push(std::pair<base::Closure, bool>(task, true));
245 void ScheduleNextTask() {
246 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
247 if (task_stack_.empty()) {
248 TestFinished();
249 return;
251 base::Closure task =task_stack_.top().first;
252 bool immediate = task_stack_.top().second;
253 task_stack_.pop();
254 if (immediate)
255 task.Run();
256 else
257 base::MessageLoop::current()->PostTask(FROM_HERE, task);
260 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
262 void WriteBasicResponse() {
263 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBasicBody));
264 std::string raw_headers(kHttpBasicHeaders, arraysize(kHttpBasicHeaders));
265 WriteResponse(
266 MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBasicBody));
269 void WriteResponse(net::HttpResponseInfo* head,
270 IOBuffer* body, int body_len) {
271 DCHECK(body);
272 scoped_refptr<IOBuffer> body_ref(body);
273 PushNextTask(base::Bind(&AppCacheURLRequestJobTest::WriteResponseBody,
274 base::Unretained(this), body_ref, body_len));
275 WriteResponseHead(head);
278 void WriteResponseHead(net::HttpResponseInfo* head) {
279 EXPECT_FALSE(writer_->IsWritePending());
280 expected_write_result_ = GetHttpResponseInfoSize(head);
281 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
282 writer_->WriteInfo(
283 write_info_buffer_.get(),
284 base::Bind(&AppCacheURLRequestJobTest::OnWriteInfoComplete,
285 base::Unretained(this)));
288 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
289 EXPECT_FALSE(writer_->IsWritePending());
290 write_buffer_ = io_buffer;
291 expected_write_result_ = buf_len;
292 writer_->WriteData(write_buffer_.get(),
293 buf_len,
294 base::Bind(&AppCacheURLRequestJobTest::OnWriteComplete,
295 base::Unretained(this)));
298 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
299 EXPECT_FALSE(reader_->IsReadPending());
300 read_buffer_ = io_buffer;
301 expected_read_result_ = buf_len;
302 reader_->ReadData(read_buffer_.get(),
303 buf_len,
304 base::Bind(&AppCacheURLRequestJobTest::OnReadComplete,
305 base::Unretained(this)));
308 // AppCacheResponseReader / Writer completion callbacks
310 void OnWriteInfoComplete(int result) {
311 EXPECT_FALSE(writer_->IsWritePending());
312 EXPECT_EQ(expected_write_result_, result);
313 ScheduleNextTask();
316 void OnWriteComplete(int result) {
317 EXPECT_FALSE(writer_->IsWritePending());
318 EXPECT_EQ(expected_write_result_, result);
319 ScheduleNextTask();
322 void OnReadInfoComplete(int result) {
323 EXPECT_FALSE(reader_->IsReadPending());
324 EXPECT_EQ(expected_read_result_, result);
325 ScheduleNextTask();
328 void OnReadComplete(int result) {
329 EXPECT_FALSE(reader_->IsReadPending());
330 EXPECT_EQ(expected_read_result_, result);
331 ScheduleNextTask();
334 // Helpers to work with HttpResponseInfo objects
336 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
337 net::HttpResponseInfo* info = new net::HttpResponseInfo;
338 info->request_time = base::Time::Now();
339 info->response_time = base::Time::Now();
340 info->was_cached = false;
341 info->headers = new net::HttpResponseHeaders(raw_headers);
342 return info;
345 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
346 Pickle pickle;
347 return PickleHttpResonseInfo(&pickle, info);
350 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
351 const net::HttpResponseInfo* info2) {
352 Pickle pickle1;
353 Pickle pickle2;
354 PickleHttpResonseInfo(&pickle1, info1);
355 PickleHttpResonseInfo(&pickle2, info2);
356 return (pickle1.size() == pickle2.size()) &&
357 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
360 int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) {
361 const bool kSkipTransientHeaders = true;
362 const bool kTruncated = false;
363 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
364 return pickle->size();
367 // Helpers to fill and verify blocks of memory with a value
369 void FillData(char value, char* data, int data_len) {
370 memset(data, value, data_len);
373 bool CheckData(char value, const char* data, int data_len) {
374 for (int i = 0; i < data_len; ++i, ++data) {
375 if (*data != value)
376 return false;
378 return true;
381 // Individual Tests ---------------------------------------------------------
382 // Some of the individual tests involve multiple async steps. Each test
383 // is delineated with a section header.
385 // Basic -------------------------------------------------------------------
386 void Basic() {
387 AppCacheStorage* storage = service_->storage();
388 net::URLRequest request(
389 GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, &empty_context_);
390 scoped_refptr<AppCacheURLRequestJob> job;
392 // Create an instance and see that it looks as expected.
394 job = new AppCacheURLRequestJob(
395 &request, NULL, storage, NULL, false);
396 EXPECT_TRUE(job->is_waiting());
397 EXPECT_FALSE(job->is_delivering_appcache_response());
398 EXPECT_FALSE(job->is_delivering_network_response());
399 EXPECT_FALSE(job->is_delivering_error_response());
400 EXPECT_FALSE(job->has_been_started());
401 EXPECT_FALSE(job->has_been_killed());
402 EXPECT_EQ(GURL(), job->manifest_url());
403 EXPECT_EQ(kNoCacheId, job->cache_id());
404 EXPECT_FALSE(job->entry().has_response_id());
406 TestFinished();
409 // DeliveryOrders -----------------------------------------------------
410 void DeliveryOrders() {
411 AppCacheStorage* storage = service_->storage();
412 net::URLRequest request(
413 GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, &empty_context_);
414 scoped_refptr<AppCacheURLRequestJob> job;
416 // Create an instance, give it a delivery order and see that
417 // it looks as expected.
419 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
420 job->DeliverErrorResponse();
421 EXPECT_TRUE(job->is_delivering_error_response());
422 EXPECT_FALSE(job->has_been_started());
424 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
425 job->DeliverNetworkResponse();
426 EXPECT_TRUE(job->is_delivering_network_response());
427 EXPECT_FALSE(job->has_been_started());
429 job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
430 const GURL kManifestUrl("http://blah/");
431 const int64 kCacheId(1);
432 const int64 kGroupId(1);
433 const AppCacheEntry kEntry(AppCacheEntry::EXPLICIT, 1);
434 job->DeliverAppCachedResponse(kManifestUrl, kCacheId, kGroupId,
435 kEntry, false);
436 EXPECT_FALSE(job->is_waiting());
437 EXPECT_TRUE(job->is_delivering_appcache_response());
438 EXPECT_FALSE(job->has_been_started());
439 EXPECT_EQ(kManifestUrl, job->manifest_url());
440 EXPECT_EQ(kCacheId, job->cache_id());
441 EXPECT_EQ(kGroupId, job->group_id());
442 EXPECT_EQ(kEntry.types(), job->entry().types());
443 EXPECT_EQ(kEntry.response_id(), job->entry().response_id());
445 TestFinished();
448 // DeliverNetworkResponse --------------------------------------------------
450 void DeliverNetworkResponse() {
451 // This test has async steps.
452 PushNextTask(
453 base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverNetworkResponse,
454 base::Unretained(this)));
456 AppCacheStorage* storage = service_->storage();
457 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
458 net::DEFAULT_PRIORITY,
459 url_request_delegate_.get(),
460 NULL);
462 // Setup to create an AppCacheURLRequestJob with orders to deliver
463 // a network response.
464 mock_factory_job_ = new AppCacheURLRequestJob(
465 request_.get(), NULL, storage, NULL, false);
466 mock_factory_job_->DeliverNetworkResponse();
467 EXPECT_TRUE(mock_factory_job_->is_delivering_network_response());
468 EXPECT_FALSE(mock_factory_job_->has_been_started());
470 // Start the request.
471 request_->Start();
473 // The job should have been picked up.
474 EXPECT_FALSE(mock_factory_job_);
475 // Completion is async.
478 void VerifyDeliverNetworkResponse() {
479 EXPECT_EQ(request_->status().error(),
480 net::ERR_INTERNET_DISCONNECTED);
481 TestFinished();
484 // DeliverErrorResponse --------------------------------------------------
486 void DeliverErrorResponse() {
487 // This test has async steps.
488 PushNextTask(
489 base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverErrorResponse,
490 base::Unretained(this)));
492 AppCacheStorage* storage = service_->storage();
493 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
494 net::DEFAULT_PRIORITY,
495 url_request_delegate_.get(),
496 NULL);
498 // Setup to create an AppCacheURLRequestJob with orders to deliver
499 // a network response.
500 mock_factory_job_ = new AppCacheURLRequestJob(
501 request_.get(), NULL, storage, NULL, false);
502 mock_factory_job_->DeliverErrorResponse();
503 EXPECT_TRUE(mock_factory_job_->is_delivering_error_response());
504 EXPECT_FALSE(mock_factory_job_->has_been_started());
506 // Start the request.
507 request_->Start();
509 // The job should have been picked up.
510 EXPECT_FALSE(mock_factory_job_);
511 // Completion is async.
514 void VerifyDeliverErrorResponse() {
515 EXPECT_EQ(request_->status().error(), net::ERR_FAILED);
516 TestFinished();
519 // DeliverSmallAppCachedResponse --------------------------------------
520 // "Small" being small enough to read completely in a single
521 // request->Read call.
523 void DeliverSmallAppCachedResponse() {
524 // This test has several async steps.
525 // 1. Write a small response to response storage.
526 // 2. Use net::URLRequest to retrieve it.
527 // 3. Verify we received what we expected to receive.
529 PushNextTask(base::Bind(
530 &AppCacheURLRequestJobTest::VerifyDeliverSmallAppCachedResponse,
531 base::Unretained(this)));
532 PushNextTask(
533 base::Bind(&AppCacheURLRequestJobTest::RequestAppCachedResource,
534 base::Unretained(this), false));
536 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
537 written_response_id_ = writer_->response_id();
538 WriteBasicResponse();
539 // Continues async
542 void RequestAppCachedResource(bool start_after_delivery_orders) {
543 AppCacheStorage* storage = service_->storage();
544 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
545 net::DEFAULT_PRIORITY,
546 url_request_delegate_.get(),
547 NULL);
549 // Setup to create an AppCacheURLRequestJob with orders to deliver
550 // a network response.
551 scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
552 request_.get(), NULL, storage, NULL, false));
554 if (start_after_delivery_orders) {
555 job->DeliverAppCachedResponse(
556 GURL(), 0, 111,
557 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
558 false);
559 EXPECT_TRUE(job->is_delivering_appcache_response());
562 // Start the request.
563 EXPECT_FALSE(job->has_been_started());
564 mock_factory_job_ = job.get();
565 request_->Start();
566 EXPECT_FALSE(mock_factory_job_);
567 EXPECT_TRUE(job->has_been_started());
569 if (!start_after_delivery_orders) {
570 job->DeliverAppCachedResponse(
571 GURL(), 0, 111,
572 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
573 false);
574 EXPECT_TRUE(job->is_delivering_appcache_response());
577 // Completion is async.
580 void VerifyDeliverSmallAppCachedResponse() {
581 EXPECT_TRUE(request_->status().is_success());
582 EXPECT_TRUE(CompareHttpResponseInfos(
583 write_info_buffer_->http_info.get(),
584 &url_request_delegate_->received_info_));
585 EXPECT_EQ(5, url_request_delegate_->amount_received_);
586 EXPECT_EQ(0, memcmp(kHttpBasicBody,
587 url_request_delegate_->received_data_->data(),
588 strlen(kHttpBasicBody)));
589 TestFinished();
592 // DeliverLargeAppCachedResponse --------------------------------------
593 // "Large" enough to require multiple calls to request->Read to complete.
595 void DeliverLargeAppCachedResponse() {
596 // This test has several async steps.
597 // 1. Write a large response to response storage.
598 // 2. Use net::URLRequest to retrieve it.
599 // 3. Verify we received what we expected to receive.
601 PushNextTask(base::Bind(
602 &AppCacheURLRequestJobTest::VerifyDeliverLargeAppCachedResponse,
603 base::Unretained(this)));
604 PushNextTask(base::Bind(
605 &AppCacheURLRequestJobTest::RequestAppCachedResource,
606 base::Unretained(this), true));
608 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
609 written_response_id_ = writer_->response_id();
610 WriteLargeResponse();
611 // Continues async
614 void WriteLargeResponse() {
615 // 3, 1k blocks
616 static const char kHttpHeaders[] =
617 "HTTP/1.0 200 OK\0Content-Length: 3072\0\0";
618 scoped_refptr<IOBuffer> body(new IOBuffer(kBlockSize * 3));
619 char* p = body->data();
620 for (int i = 0; i < 3; ++i, p += kBlockSize)
621 FillData(i + 1, p, kBlockSize);
622 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
623 WriteResponse(
624 MakeHttpResponseInfo(raw_headers), body.get(), kBlockSize * 3);
627 void VerifyDeliverLargeAppCachedResponse() {
628 EXPECT_TRUE(request_->status().is_success());
629 EXPECT_TRUE(CompareHttpResponseInfos(
630 write_info_buffer_->http_info.get(),
631 &url_request_delegate_->received_info_));
632 EXPECT_EQ(3072, url_request_delegate_->amount_received_);
633 char* p = url_request_delegate_->received_data_->data();
634 for (int i = 0; i < 3; ++i, p += kBlockSize)
635 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
636 TestFinished();
639 // DeliverPartialResponse --------------------------------------
641 void DeliverPartialResponse() {
642 // This test has several async steps.
643 // 1. Write a small response to response storage.
644 // 2. Use net::URLRequest to retrieve it a subset using a range request
645 // 3. Verify we received what we expected to receive.
646 PushNextTask(base::Bind(
647 &AppCacheURLRequestJobTest::VerifyDeliverPartialResponse,
648 base::Unretained(this)));
649 PushNextTask(base::Bind(
650 &AppCacheURLRequestJobTest::MakeRangeRequest, base::Unretained(this)));
651 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
652 written_response_id_ = writer_->response_id();
653 WriteBasicResponse();
654 // Continues async
657 void MakeRangeRequest() {
658 AppCacheStorage* storage = service_->storage();
659 request_ = empty_context_.CreateRequest(GURL("http://blah/"),
660 net::DEFAULT_PRIORITY,
661 url_request_delegate_.get(),
662 NULL);
664 // Request a range, the 3 middle chars out of 'Hello'
665 net::HttpRequestHeaders extra_headers;
666 extra_headers.SetHeader("Range", "bytes= 1-3");
667 request_->SetExtraRequestHeaders(extra_headers);
669 // Create job with orders to deliver an appcached entry.
670 scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
671 request_.get(), NULL, storage, NULL, false));
672 job->DeliverAppCachedResponse(
673 GURL(), 0, 111,
674 AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
675 false);
676 EXPECT_TRUE(job->is_delivering_appcache_response());
678 // Start the request.
679 EXPECT_FALSE(job->has_been_started());
680 mock_factory_job_ = job.get();
681 request_->Start();
682 EXPECT_FALSE(mock_factory_job_);
683 EXPECT_TRUE(job->has_been_started());
684 // Completion is async.
687 void VerifyDeliverPartialResponse() {
688 EXPECT_TRUE(request_->status().is_success());
689 EXPECT_EQ(3, url_request_delegate_->amount_received_);
690 EXPECT_EQ(0, memcmp(kHttpBasicBody + 1,
691 url_request_delegate_->received_data_->data(),
692 3));
693 net::HttpResponseHeaders* headers =
694 url_request_delegate_->received_info_.headers.get();
695 EXPECT_EQ(206, headers->response_code());
696 EXPECT_EQ(3, headers->GetContentLength());
697 int64 range_start, range_end, object_size;
698 EXPECT_TRUE(
699 headers->GetContentRange(&range_start, &range_end, &object_size));
700 EXPECT_EQ(1, range_start);
701 EXPECT_EQ(3, range_end);
702 EXPECT_EQ(5, object_size);
703 TestFinished();
706 // CancelRequest --------------------------------------
708 void CancelRequest() {
709 // This test has several async steps.
710 // 1. Write a large response to response storage.
711 // 2. Use net::URLRequest to retrieve it.
712 // 3. Cancel the request after data starts coming in.
714 PushNextTask(base::Bind(
715 &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this)));
716 PushNextTask(base::Bind(
717 &AppCacheURLRequestJobTest::RequestAppCachedResource,
718 base::Unretained(this), true));
720 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
721 written_response_id_ = writer_->response_id();
722 WriteLargeResponse();
724 url_request_delegate_->kill_after_amount_received_ = kBlockSize;
725 url_request_delegate_->kill_with_io_pending_ = false;
726 // Continues async
729 void VerifyCancel() {
730 EXPECT_EQ(net::URLRequestStatus::CANCELED,
731 request_->status().status());
732 TestFinished();
735 // CancelRequestWithIOPending --------------------------------------
737 void CancelRequestWithIOPending() {
738 // This test has several async steps.
739 // 1. Write a large response to response storage.
740 // 2. Use net::URLRequest to retrieve it.
741 // 3. Cancel the request after data starts coming in.
743 PushNextTask(base::Bind(
744 &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this)));
745 PushNextTask(base::Bind(
746 &AppCacheURLRequestJobTest::RequestAppCachedResource,
747 base::Unretained(this), true));
749 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
750 written_response_id_ = writer_->response_id();
751 WriteLargeResponse();
753 url_request_delegate_->kill_after_amount_received_ = kBlockSize;
754 url_request_delegate_->kill_with_io_pending_ = true;
755 // Continues async
759 // Data members --------------------------------------------------------
761 scoped_ptr<base::WaitableEvent> test_finished_event_;
762 scoped_ptr<MockStorageDelegate> storage_delegate_;
763 scoped_ptr<MockAppCacheService> service_;
764 std::stack<std::pair<base::Closure, bool> > task_stack_;
766 scoped_ptr<AppCacheResponseReader> reader_;
767 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
768 scoped_refptr<IOBuffer> read_buffer_;
769 int expected_read_result_;
770 int reader_deletion_count_down_;
772 int64 written_response_id_;
773 scoped_ptr<AppCacheResponseWriter> writer_;
774 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
775 scoped_refptr<IOBuffer> write_buffer_;
776 int expected_write_result_;
777 int writer_deletion_count_down_;
779 net::URLRequest::ProtocolFactory* orig_http_factory_;
780 net::URLRequestContext empty_context_;
781 scoped_ptr<net::URLRequest> request_;
782 scoped_ptr<MockURLRequestDelegate> url_request_delegate_;
784 static scoped_ptr<base::Thread> io_thread_;
785 static AppCacheURLRequestJob* mock_factory_job_;
788 // static
789 scoped_ptr<base::Thread> AppCacheURLRequestJobTest::io_thread_;
790 AppCacheURLRequestJob* AppCacheURLRequestJobTest::mock_factory_job_ = NULL;
792 TEST_F(AppCacheURLRequestJobTest, Basic) {
793 RunTestOnIOThread(&AppCacheURLRequestJobTest::Basic);
796 TEST_F(AppCacheURLRequestJobTest, DeliveryOrders) {
797 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliveryOrders);
800 TEST_F(AppCacheURLRequestJobTest, DeliverNetworkResponse) {
801 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverNetworkResponse);
804 TEST_F(AppCacheURLRequestJobTest, DeliverErrorResponse) {
805 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverErrorResponse);
808 TEST_F(AppCacheURLRequestJobTest, DeliverSmallAppCachedResponse) {
809 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverSmallAppCachedResponse);
812 TEST_F(AppCacheURLRequestJobTest, DeliverLargeAppCachedResponse) {
813 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverLargeAppCachedResponse);
816 TEST_F(AppCacheURLRequestJobTest, DeliverPartialResponse) {
817 RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverPartialResponse);
820 TEST_F(AppCacheURLRequestJobTest, CancelRequest) {
821 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequest);
824 TEST_F(AppCacheURLRequestJobTest, CancelRequestWithIOPending) {
825 RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequestWithIOPending);
828 } // namespace content