Update V8 to version 4.6.55.
[chromium-blink-merge.git] / content / browser / appcache / appcache_response_unittest.cc
blob743a624556f4bdde57993f289e669aa92e7c66db
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 <string>
7 #include <utility>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/pickle.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/threading/thread.h"
19 #include "content/browser/appcache/appcache_response.h"
20 #include "content/browser/appcache/mock_appcache_service.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 #include "net/http/http_response_headers.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using net::IOBuffer;
27 using net::WrappedIOBuffer;
29 namespace content {
31 static const int kNumBlocks = 4;
32 static const int kBlockSize = 1024;
33 static const int kNoSuchResponseId = 123;
35 class AppCacheResponseTest : public testing::Test {
36 public:
37 // Test Harness -------------------------------------------------------------
39 // Helper class used to verify test results
40 class MockStorageDelegate : public AppCacheStorage::Delegate {
41 public:
42 explicit MockStorageDelegate(AppCacheResponseTest* test)
43 : loaded_info_id_(0), test_(test) {
46 void OnResponseInfoLoaded(AppCacheResponseInfo* info,
47 int64 response_id) override {
48 loaded_info_ = info;
49 loaded_info_id_ = response_id;
50 test_->ScheduleNextTask();
53 scoped_refptr<AppCacheResponseInfo> loaded_info_;
54 int64 loaded_info_id_;
55 AppCacheResponseTest* test_;
58 // Helper callback to run a test on our io_thread. The io_thread is spun up
59 // once and reused for all tests.
60 template <class Method>
61 void MethodWrapper(Method method) {
62 SetUpTest();
63 (this->*method)();
66 static void SetUpTestCase() {
67 io_thread_.reset(new base::Thread("AppCacheResponseTest Thread"));
68 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
69 io_thread_->StartWithOptions(options);
72 static void TearDownTestCase() {
73 io_thread_.reset(NULL);
76 AppCacheResponseTest() {}
78 template <class Method>
79 void RunTestOnIOThread(Method method) {
80 test_finished_event_ .reset(new base::WaitableEvent(false, false));
81 io_thread_->task_runner()->PostTask(
82 FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
83 base::Unretained(this), method));
84 test_finished_event_->Wait();
87 void SetUpTest() {
88 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
89 DCHECK(task_stack_.empty());
90 storage_delegate_.reset(new MockStorageDelegate(this));
91 service_.reset(new MockAppCacheService());
92 expected_read_result_ = 0;
93 expected_write_result_ = 0;
94 written_response_id_ = 0;
95 should_delete_reader_in_completion_callback_ = false;
96 should_delete_writer_in_completion_callback_ = false;
97 reader_deletion_count_down_ = 0;
98 writer_deletion_count_down_ = 0;
99 read_callback_was_called_ = false;
100 write_callback_was_called_ = false;
103 void TearDownTest() {
104 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
105 while (!task_stack_.empty())
106 task_stack_.pop();
108 reader_.reset();
109 read_buffer_ = NULL;
110 read_info_buffer_ = NULL;
111 writer_.reset();
112 write_buffer_ = NULL;
113 write_info_buffer_ = NULL;
114 storage_delegate_.reset();
115 service_.reset();
118 void TestFinished() {
119 // We unwind the stack prior to finishing up to let stack
120 // based objects get deleted.
121 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
122 base::ThreadTaskRunnerHandle::Get()->PostTask(
123 FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound,
124 base::Unretained(this)));
127 void TestFinishedUnwound() {
128 TearDownTest();
129 test_finished_event_->Signal();
132 void PushNextTask(const base::Closure& task) {
133 task_stack_.push(std::pair<base::Closure, bool>(task, false));
136 void PushNextTaskAsImmediate(const base::Closure& task) {
137 task_stack_.push(std::pair<base::Closure, bool>(task, true));
140 void ScheduleNextTask() {
141 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
142 if (task_stack_.empty()) {
143 TestFinished();
144 return;
146 base::Closure task = task_stack_.top().first;
147 bool immediate = task_stack_.top().second;
148 task_stack_.pop();
149 if (immediate)
150 task.Run();
151 else
152 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
155 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
157 void WriteBasicResponse() {
158 static const char kHttpHeaders[] =
159 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
160 static const char kHttpBody[] = "Hello";
161 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
162 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
163 WriteResponse(
164 MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBody));
167 int basic_response_size() { return 5; } // should match kHttpBody above
169 void WriteResponse(net::HttpResponseInfo* head,
170 IOBuffer* body, int body_len) {
171 DCHECK(body);
172 scoped_refptr<IOBuffer> body_ref(body);
173 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseBody,
174 base::Unretained(this), body_ref, body_len));
175 WriteResponseHead(head);
178 void WriteResponseHead(net::HttpResponseInfo* head) {
179 EXPECT_FALSE(writer_->IsWritePending());
180 expected_write_result_ = GetHttpResponseInfoSize(head);
181 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
182 writer_->WriteInfo(write_info_buffer_.get(),
183 base::Bind(&AppCacheResponseTest::OnWriteInfoComplete,
184 base::Unretained(this)));
187 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
188 EXPECT_FALSE(writer_->IsWritePending());
189 write_buffer_ = io_buffer;
190 expected_write_result_ = buf_len;
191 writer_->WriteData(write_buffer_.get(),
192 buf_len,
193 base::Bind(&AppCacheResponseTest::OnWriteComplete,
194 base::Unretained(this)));
197 void WriteResponseMetadata(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
198 EXPECT_FALSE(metadata_writer_->IsWritePending());
199 write_buffer_ = io_buffer;
200 expected_write_result_ = buf_len;
201 metadata_writer_->WriteMetadata(
202 write_buffer_.get(), buf_len,
203 base::Bind(&AppCacheResponseTest::OnMetadataWriteComplete,
204 base::Unretained(this)));
207 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
208 EXPECT_FALSE(reader_->IsReadPending());
209 read_buffer_ = io_buffer;
210 expected_read_result_ = buf_len;
211 reader_->ReadData(read_buffer_.get(),
212 buf_len,
213 base::Bind(&AppCacheResponseTest::OnReadComplete,
214 base::Unretained(this)));
217 // AppCacheResponseReader / Writer completion callbacks
219 void OnWriteInfoComplete(int result) {
220 EXPECT_FALSE(writer_->IsWritePending());
221 EXPECT_EQ(expected_write_result_, result);
222 ScheduleNextTask();
225 void OnWriteComplete(int result) {
226 EXPECT_FALSE(writer_->IsWritePending());
227 write_callback_was_called_ = true;
228 EXPECT_EQ(expected_write_result_, result);
229 if (should_delete_writer_in_completion_callback_ &&
230 --writer_deletion_count_down_ == 0) {
231 writer_.reset();
233 ScheduleNextTask();
236 void OnMetadataWriteComplete(int result) {
237 EXPECT_FALSE(metadata_writer_->IsWritePending());
238 EXPECT_EQ(expected_write_result_, result);
239 ScheduleNextTask();
242 void OnReadInfoComplete(int result) {
243 EXPECT_FALSE(reader_->IsReadPending());
244 EXPECT_EQ(expected_read_result_, result);
245 ScheduleNextTask();
248 void OnReadComplete(int result) {
249 EXPECT_FALSE(reader_->IsReadPending());
250 read_callback_was_called_ = true;
251 EXPECT_EQ(expected_read_result_, result);
252 if (should_delete_reader_in_completion_callback_ &&
253 --reader_deletion_count_down_ == 0) {
254 reader_.reset();
256 ScheduleNextTask();
259 // Helpers to work with HttpResponseInfo objects
261 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
262 net::HttpResponseInfo* info = new net::HttpResponseInfo;
263 info->request_time = base::Time::Now();
264 info->response_time = base::Time::Now();
265 info->was_cached = false;
266 info->headers = new net::HttpResponseHeaders(raw_headers);
267 return info;
270 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
271 base::Pickle pickle;
272 return PickleHttpResonseInfo(&pickle, info);
275 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
276 const net::HttpResponseInfo* info2) {
277 base::Pickle pickle1;
278 base::Pickle pickle2;
279 PickleHttpResonseInfo(&pickle1, info1);
280 PickleHttpResonseInfo(&pickle2, info2);
281 return (pickle1.size() == pickle2.size()) &&
282 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
285 int PickleHttpResonseInfo(base::Pickle* pickle,
286 const net::HttpResponseInfo* info) {
287 const bool kSkipTransientHeaders = true;
288 const bool kTruncated = false;
289 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
290 return pickle->size();
293 // Helpers to fill and verify blocks of memory with a value
295 void FillData(char value, char* data, int data_len) {
296 memset(data, value, data_len);
299 bool CheckData(char value, const char* data, int data_len) {
300 for (int i = 0; i < data_len; ++i, ++data) {
301 if (*data != value)
302 return false;
304 return true;
307 // Individual Tests ---------------------------------------------------------
308 // Most of the individual tests involve multiple async steps. Each test
309 // is delineated with a section header.
312 // ReadNonExistentResponse -------------------------------------------
313 void ReadNonExistentResponse() {
314 // 1. Attempt to ReadInfo
315 // 2. Attempt to ReadData
317 reader_.reset(service_->storage()->CreateResponseReader(
318 GURL(), 0, kNoSuchResponseId));
320 // Push tasks in reverse order
321 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
322 base::Unretained(this)));
323 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
324 base::Unretained(this)));
325 ScheduleNextTask();
328 void ReadNonExistentInfo() {
329 EXPECT_FALSE(reader_->IsReadPending());
330 read_info_buffer_ = new HttpResponseInfoIOBuffer();
331 reader_->ReadInfo(read_info_buffer_.get(),
332 base::Bind(&AppCacheResponseTest::OnReadInfoComplete,
333 base::Unretained(this)));
334 EXPECT_TRUE(reader_->IsReadPending());
335 expected_read_result_ = net::ERR_CACHE_MISS;
338 void ReadNonExistentData() {
339 EXPECT_FALSE(reader_->IsReadPending());
340 read_buffer_ = new IOBuffer(kBlockSize);
341 reader_->ReadData(read_buffer_.get(),
342 kBlockSize,
343 base::Bind(&AppCacheResponseTest::OnReadComplete,
344 base::Unretained(this)));
345 EXPECT_TRUE(reader_->IsReadPending());
346 expected_read_result_ = net::ERR_CACHE_MISS;
349 // LoadResponseInfo_Miss ----------------------------------------------------
350 void LoadResponseInfo_Miss() {
351 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
352 base::Unretained(this)));
353 service_->storage()->LoadResponseInfo(GURL(), 0, kNoSuchResponseId,
354 storage_delegate_.get());
357 void LoadResponseInfo_Miss_Verify() {
358 EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_);
359 EXPECT_TRUE(!storage_delegate_->loaded_info_.get());
360 TestFinished();
363 // LoadResponseInfo_Hit ----------------------------------------------------
364 void LoadResponseInfo_Hit() {
365 // This tests involves multiple async steps.
366 // 1. Write a response headers and body to storage
367 // a. headers
368 // b. body
369 // 2. Use LoadResponseInfo to read the response headers back out
370 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
371 base::Unretained(this)));
372 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
373 written_response_id_ = writer_->response_id();
374 WriteBasicResponse();
377 void LoadResponseInfo_Hit_Step2() {
378 writer_.reset();
379 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
380 base::Unretained(this)));
381 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
382 storage_delegate_.get());
385 void LoadResponseInfo_Hit_Verify() {
386 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
387 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
388 EXPECT_TRUE(CompareHttpResponseInfos(
389 write_info_buffer_->http_info.get(),
390 storage_delegate_->loaded_info_->http_response_info()));
391 EXPECT_EQ(basic_response_size(),
392 storage_delegate_->loaded_info_->response_data_size());
393 TestFinished();
396 // Metadata -------------------------------------------------
397 void Metadata() {
398 // This tests involves multiple async steps.
399 // 1. Write a response headers and body to storage
400 // a. headers
401 // b. body
402 // 2. Write metadata "Metadata First" using AppCacheResponseMetadataWriter.
403 // 3. Check metadata was written.
404 // 4. Write metadata "Second".
405 // 5. Check metadata was written and was truncated .
406 // 6. Write metadata "".
407 // 7. Check metadata was deleted.
409 // Push tasks in reverse order.
410 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
411 base::Unretained(this), ""));
412 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
413 base::Unretained(this)));
414 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
415 base::Unretained(this), ""));
416 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
417 base::Unretained(this), "Second"));
418 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
419 base::Unretained(this)));
420 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
421 base::Unretained(this), "Second"));
422 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
423 base::Unretained(this), "Metadata First"));
424 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
425 base::Unretained(this)));
426 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
427 base::Unretained(this), "Metadata First"));
428 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_ResetWriter,
429 base::Unretained(this)));
430 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
431 written_response_id_ = writer_->response_id();
432 WriteBasicResponse();
435 void Metadata_ResetWriter() {
436 writer_.reset();
437 ScheduleNextTask();
440 void Metadata_WriteMetadata(const char* metadata) {
441 metadata_writer_.reset(service_->storage()->CreateResponseMetadataWriter(
442 0, written_response_id_));
443 scoped_refptr<IOBuffer> buffer(new WrappedIOBuffer(metadata));
444 WriteResponseMetadata(buffer.get(), strlen(metadata));
447 void Metadata_LoadResponseInfo() {
448 metadata_writer_.reset();
449 storage_delegate_.reset(new MockStorageDelegate(this));
450 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
451 storage_delegate_.get());
454 void Metadata_VerifyMetadata(const char* metadata) {
455 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
456 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
457 const net::HttpResponseInfo* read_head =
458 storage_delegate_->loaded_info_->http_response_info();
459 EXPECT_TRUE(read_head);
460 const int metadata_size = strlen(metadata);
461 if (metadata_size) {
462 EXPECT_TRUE(read_head->metadata.get());
463 EXPECT_EQ(metadata_size, read_head->metadata->size());
464 EXPECT_EQ(0,
465 memcmp(metadata, read_head->metadata->data(), metadata_size));
466 } else {
467 EXPECT_FALSE(read_head->metadata.get());
469 EXPECT_TRUE(CompareHttpResponseInfos(
470 write_info_buffer_->http_info.get(),
471 storage_delegate_->loaded_info_->http_response_info()));
472 EXPECT_EQ(basic_response_size(),
473 storage_delegate_->loaded_info_->response_data_size());
474 ScheduleNextTask();
477 // AmountWritten ----------------------------------------------------
479 void AmountWritten() {
480 static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
481 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
482 net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
483 int expected_amount_written =
484 GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
486 // Push tasks in reverse order.
487 PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
488 base::Unretained(this), expected_amount_written));
489 for (int i = 0; i < kNumBlocks; ++i) {
490 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
491 base::Unretained(this), kNumBlocks - i));
493 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
494 base::Unretained(this), head));
496 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
497 written_response_id_ = writer_->response_id();
498 ScheduleNextTask();
501 void Verify_AmountWritten(int expected_amount_written) {
502 EXPECT_EQ(expected_amount_written, writer_->amount_written());
503 TestFinished();
507 // WriteThenVariouslyReadResponse -------------------------------------------
509 void WriteThenVariouslyReadResponse() {
510 // This tests involves multiple async steps.
511 // 1. First, write a large body using multiple writes, we don't bother
512 // with a response head for this test.
513 // 2. Read the entire body, using multiple reads
514 // 3. Read the entire body, using one read.
515 // 4. Attempt to read beyond the EOF.
516 // 5. Read just a range.
517 // 6. Attempt to read beyond EOF of a range.
519 // Push tasks in reverse order
520 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
521 base::Unretained(this)));
522 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
523 base::Unretained(this)));
524 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
525 base::Unretained(this)));
526 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
527 base::Unretained(this)));
528 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
529 base::Unretained(this)));
530 PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
531 base::Unretained(this)));
532 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
533 base::Unretained(this)));
534 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
535 base::Unretained(this)));
537 // Get them going.
538 ScheduleNextTask();
541 void WriteOutBlocks() {
542 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
543 written_response_id_ = writer_->response_id();
544 for (int i = 0; i < kNumBlocks; ++i) {
545 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
546 base::Unretained(this), kNumBlocks - i));
548 ScheduleNextTask();
551 void WriteOneBlock(int block_number) {
552 scoped_refptr<IOBuffer> io_buffer(
553 new IOBuffer(kBlockSize));
554 FillData(block_number, io_buffer->data(), kBlockSize);
555 WriteResponseBody(io_buffer, kBlockSize);
558 void ReadInBlocks() {
559 writer_.reset();
560 reader_.reset(service_->storage()->CreateResponseReader(
561 GURL(), 0, written_response_id_));
562 for (int i = 0; i < kNumBlocks; ++i) {
563 PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
564 base::Unretained(this), kNumBlocks - i));
566 ScheduleNextTask();
569 void ReadOneBlock(int block_number) {
570 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
571 base::Unretained(this), block_number));
572 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
575 void VerifyOneBlock(int block_number) {
576 EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
577 ScheduleNextTask();
580 void ReadAllAtOnce() {
581 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
582 base::Unretained(this)));
583 reader_.reset(service_->storage()->CreateResponseReader(
584 GURL(), 0, written_response_id_));
585 int big_size = kNumBlocks * kBlockSize;
586 ReadResponseBody(new IOBuffer(big_size), big_size);
589 void VerifyAllAtOnce() {
590 char* p = read_buffer_->data();
591 for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
592 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
593 ScheduleNextTask();
596 void ReadPastEOF() {
597 EXPECT_FALSE(reader_->IsReadPending());
598 read_buffer_ = new IOBuffer(kBlockSize);
599 expected_read_result_ = 0;
600 reader_->ReadData(read_buffer_.get(),
601 kBlockSize,
602 base::Bind(&AppCacheResponseTest::OnReadComplete,
603 base::Unretained(this)));
606 void ReadRange() {
607 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
608 base::Unretained(this)));
609 reader_.reset(service_->storage()->CreateResponseReader(
610 GURL(), 0, written_response_id_));
611 reader_->SetReadRange(kBlockSize, kBlockSize);
612 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
615 void VerifyRange() {
616 EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
617 ScheduleNextTask(); // ReadPastEOF is scheduled next
620 void ReadRangePartiallyBeyondEOF() {
621 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
622 base::Unretained(this)));
623 reader_.reset(service_->storage()->CreateResponseReader(
624 GURL(), 0, written_response_id_));
625 reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
626 ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
627 kNumBlocks * kBlockSize);
628 expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
631 void VerifyRangeBeyondEOF() {
632 // Just verify the first 1k
633 VerifyRange();
636 void ReadRangeFullyBeyondEOF() {
637 reader_.reset(service_->storage()->CreateResponseReader(
638 GURL(), 0, written_response_id_));
639 reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
640 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
641 expected_read_result_ = 0;
644 // IOChaining -------------------------------------------
645 void IOChaining() {
646 // 1. Write several blocks out initiating the subsequent write
647 // from within the completion callback of the previous write.
648 // 2. Read and verify several blocks in similarly chaining reads.
650 // Push tasks in reverse order
651 PushNextTaskAsImmediate(
652 base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately,
653 base::Unretained(this)));
654 PushNextTaskAsImmediate(
655 base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately,
656 base::Unretained(this)));
658 // Get them going.
659 ScheduleNextTask();
662 void WriteOutBlocksImmediately() {
663 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
664 written_response_id_ = writer_->response_id();
665 for (int i = 0; i < kNumBlocks; ++i) {
666 PushNextTaskAsImmediate(
667 base::Bind(&AppCacheResponseTest::WriteOneBlock,
668 base::Unretained(this), kNumBlocks - i));
670 ScheduleNextTask();
673 void ReadInBlocksImmediately() {
674 writer_.reset();
675 reader_.reset(service_->storage()->CreateResponseReader(
676 GURL(), 0, written_response_id_));
677 for (int i = 0; i < kNumBlocks; ++i) {
678 PushNextTaskAsImmediate(
679 base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately,
680 base::Unretained(this),
681 kNumBlocks - i));
683 ScheduleNextTask();
686 void ReadOneBlockImmediately(int block_number) {
687 PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
688 base::Unretained(this), block_number));
689 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
692 // DeleteWithinCallbacks -------------------------------------------
693 void DeleteWithinCallbacks() {
694 // 1. Write out a few blocks normally, and upon
695 // completion of the last write, delete the writer.
696 // 2. Read in a few blocks normally, and upon completion
697 // of the last read, delete the reader.
699 should_delete_reader_in_completion_callback_ = true;
700 reader_deletion_count_down_ = kNumBlocks;
701 should_delete_writer_in_completion_callback_ = true;
702 writer_deletion_count_down_ = kNumBlocks;
704 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
705 base::Unretained(this)));
706 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
707 base::Unretained(this)));
708 ScheduleNextTask();
711 // DeleteWithIOPending -------------------------------------------
712 void DeleteWithIOPending() {
713 // 1. Write a few blocks normally.
714 // 2. Start a write, delete with it pending.
715 // 3. Start a read, delete with it pending.
716 PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
717 base::Unretained(this)));
718 PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
719 base::Unretained(this)));
720 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
721 base::Unretained(this)));
722 ScheduleNextTask();
725 void WriteThenDelete() {
726 write_callback_was_called_ = false;
727 WriteOneBlock(5);
728 EXPECT_TRUE(writer_->IsWritePending());
729 writer_.reset();
730 ScheduleNextTask();
733 void ReadThenDelete() {
734 read_callback_was_called_ = false;
735 reader_.reset(service_->storage()->CreateResponseReader(
736 GURL(), 0, written_response_id_));
737 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
738 EXPECT_TRUE(reader_->IsReadPending());
739 reader_.reset();
741 // Wait a moment to verify no callbacks.
742 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
743 FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
744 base::Unretained(this)),
745 base::TimeDelta::FromMilliseconds(10));
748 void VerifyNoCallbacks() {
749 EXPECT_TRUE(!write_callback_was_called_);
750 EXPECT_TRUE(!read_callback_was_called_);
751 TestFinished();
754 // Data members
756 scoped_ptr<base::WaitableEvent> test_finished_event_;
757 scoped_ptr<MockStorageDelegate> storage_delegate_;
758 scoped_ptr<MockAppCacheService> service_;
759 std::stack<std::pair<base::Closure, bool> > task_stack_;
761 scoped_ptr<AppCacheResponseReader> reader_;
762 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
763 scoped_refptr<IOBuffer> read_buffer_;
764 int expected_read_result_;
765 bool should_delete_reader_in_completion_callback_;
766 int reader_deletion_count_down_;
767 bool read_callback_was_called_;
769 int64 written_response_id_;
770 scoped_ptr<AppCacheResponseWriter> writer_;
771 scoped_ptr<AppCacheResponseMetadataWriter> metadata_writer_;
772 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
773 scoped_refptr<IOBuffer> write_buffer_;
774 int expected_write_result_;
775 bool should_delete_writer_in_completion_callback_;
776 int writer_deletion_count_down_;
777 bool write_callback_was_called_;
779 static scoped_ptr<base::Thread> io_thread_;
782 // static
783 scoped_ptr<base::Thread> AppCacheResponseTest::io_thread_;
785 TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
786 RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
789 TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
790 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
793 TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
794 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
797 TEST_F(AppCacheResponseTest, Metadata) {
798 RunTestOnIOThread(&AppCacheResponseTest::Metadata);
801 TEST_F(AppCacheResponseTest, AmountWritten) {
802 RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
805 TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
806 RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
809 TEST_F(AppCacheResponseTest, IOChaining) {
810 RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
813 TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
814 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
817 TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
818 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
821 } // namespace content