blob: 9d5e97330d77fe588aeecf246c34bb750a403437 [file] [log] [blame]
[email protected]6f35f4e2012-03-03 21:02:281// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]073aabe2009-10-21 18:09:332// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]b7243c42010-07-23 05:23:135#include <stack>
6#include <string>
7#include <utility>
8
[email protected]8336aaf42011-11-11 21:05:499#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/callback.h"
[email protected]073aabe2009-10-21 18:09:3312#include "base/compiler_specific.h"
13#include "base/pickle.h"
[email protected]34b99632011-01-01 01:01:0614#include "base/threading/thread.h"
[email protected]44f9c952011-01-02 06:05:3915#include "base/synchronization/waitable_event.h"
[email protected]073aabe2009-10-21 18:09:3316#include "net/base/io_buffer.h"
[email protected]80d42812010-02-09 10:30:2517#include "net/base/net_errors.h"
[email protected]277d5942010-08-11 21:02:3518#include "net/http/http_response_headers.h"
[email protected]073aabe2009-10-21 18:09:3319#include "testing/gtest/include/gtest/gtest.h"
20#include "webkit/appcache/appcache_response.h"
21#include "webkit/appcache/mock_appcache_service.h"
22
23using net::IOBuffer;
[email protected]3367fc1d2009-11-09 00:09:2124using net::WrappedIOBuffer;
[email protected]073aabe2009-10-21 18:09:3325
26namespace appcache {
27
[email protected]dda06f82009-10-21 18:38:5128static const int kNumBlocks = 4;
29static const int kBlockSize = 1024;
30static const int kNoSuchResponseId = 123;
31
[email protected]073aabe2009-10-21 18:09:3332class AppCacheResponseTest : public testing::Test {
33 public:
34
35 // Test Harness -------------------------------------------------------------
36
37 // Helper class used to verify test results
38 class MockStorageDelegate : public AppCacheStorage::Delegate {
39 public:
40 explicit MockStorageDelegate(AppCacheResponseTest* test)
41 : loaded_info_id_(0), test_(test) {
42 }
43
44 virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
[email protected]7fd8fa4f2013-02-07 05:43:5045 int64 response_id) OVERRIDE {
[email protected]073aabe2009-10-21 18:09:3346 loaded_info_ = info;
47 loaded_info_id_ = response_id;
48 test_->ScheduleNextTask();
49 }
50
51 scoped_refptr<AppCacheResponseInfo> loaded_info_;
52 int64 loaded_info_id_;
53 AppCacheResponseTest* test_;
54 };
55
[email protected]72a3ce52011-12-22 05:10:2456 // Helper callback to run a test on our io_thread. The io_thread is spun up
57 // once and reused for all tests.
[email protected]073aabe2009-10-21 18:09:3358 template <class Method>
[email protected]72a3ce52011-12-22 05:10:2459 void MethodWrapper(Method method) {
60 SetUpTest();
61 (this->*method)();
62 }
[email protected]073aabe2009-10-21 18:09:3363
64 static void SetUpTestCase() {
65 io_thread_.reset(new base::Thread("AppCacheResponseTest Thread"));
[email protected]4cc586b2013-05-07 12:43:3266 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
[email protected]073aabe2009-10-21 18:09:3367 io_thread_->StartWithOptions(options);
68 }
69
70 static void TearDownTestCase() {
71 io_thread_.reset(NULL);
72 }
73
[email protected]50304162011-12-21 17:51:3074 AppCacheResponseTest() {}
[email protected]073aabe2009-10-21 18:09:3375
76 template <class Method>
77 void RunTestOnIOThread(Method method) {
78 test_finished_event_ .reset(new base::WaitableEvent(false, false));
79 io_thread_->message_loop()->PostTask(
[email protected]72a3ce52011-12-22 05:10:2480 FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
81 base::Unretained(this), method));
[email protected]073aabe2009-10-21 18:09:3382 test_finished_event_->Wait();
83 }
84
85 void SetUpTest() {
[email protected]4cc586b2013-05-07 12:43:3286 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]073aabe2009-10-21 18:09:3387 DCHECK(task_stack_.empty());
88 storage_delegate_.reset(new MockStorageDelegate(this));
89 service_.reset(new MockAppCacheService());
90 expected_read_result_ = 0;
91 expected_write_result_ = 0;
92 written_response_id_ = 0;
93 should_delete_reader_in_completion_callback_ = false;
94 should_delete_writer_in_completion_callback_ = false;
95 reader_deletion_count_down_ = 0;
96 writer_deletion_count_down_ = 0;
97 read_callback_was_called_ = false;
98 write_callback_was_called_ = false;
99 }
100
101 void TearDownTest() {
[email protected]4cc586b2013-05-07 12:43:32102 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]8336aaf42011-11-11 21:05:49103 while (!task_stack_.empty())
[email protected]073aabe2009-10-21 18:09:33104 task_stack_.pop();
[email protected]8336aaf42011-11-11 21:05:49105
[email protected]073aabe2009-10-21 18:09:33106 reader_.reset();
107 read_buffer_ = NULL;
108 read_info_buffer_ = NULL;
109 writer_.reset();
110 write_buffer_ = NULL;
111 write_info_buffer_ = NULL;
112 storage_delegate_.reset();
113 service_.reset();
114 }
115
116 void TestFinished() {
117 // We unwind the stack prior to finishing up to let stack
118 // based objects get deleted.
[email protected]4cc586b2013-05-07 12:43:32119 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
120 base::MessageLoop::current()->PostTask(
[email protected]8336aaf42011-11-11 21:05:49121 FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound,
122 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33123 }
124
125 void TestFinishedUnwound() {
126 TearDownTest();
127 test_finished_event_->Signal();
128 }
129
[email protected]8336aaf42011-11-11 21:05:49130 void PushNextTask(const base::Closure& task) {
131 task_stack_.push(std::pair<base::Closure, bool>(task, false));
[email protected]073aabe2009-10-21 18:09:33132 }
133
[email protected]8336aaf42011-11-11 21:05:49134 void PushNextTaskAsImmediate(const base::Closure& task) {
135 task_stack_.push(std::pair<base::Closure, bool>(task, true));
[email protected]073aabe2009-10-21 18:09:33136 }
137
138 void ScheduleNextTask() {
[email protected]4cc586b2013-05-07 12:43:32139 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]073aabe2009-10-21 18:09:33140 if (task_stack_.empty()) {
141 TestFinished();
142 return;
143 }
[email protected]8336aaf42011-11-11 21:05:49144 base::Closure task = task_stack_.top().first;
[email protected]073aabe2009-10-21 18:09:33145 bool immediate = task_stack_.top().second;
146 task_stack_.pop();
147 if (immediate)
[email protected]8336aaf42011-11-11 21:05:49148 task.Run();
[email protected]073aabe2009-10-21 18:09:33149 else
[email protected]4cc586b2013-05-07 12:43:32150 base::MessageLoop::current()->PostTask(FROM_HERE, task);
[email protected]073aabe2009-10-21 18:09:33151 }
152
153 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
154
155 void WriteBasicResponse() {
[email protected]3367fc1d2009-11-09 00:09:21156 static const char kHttpHeaders[] =
157 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
158 static const char* kHttpBody = "Hello";
[email protected]ad8e04a2010-11-01 04:16:27159 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
[email protected]3367fc1d2009-11-09 00:09:21160 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
161 WriteResponse(MakeHttpResponseInfo(raw_headers), body, strlen(kHttpBody));
[email protected]073aabe2009-10-21 18:09:33162 }
163
[email protected]fd2885a2010-03-17 22:02:28164 int basic_response_size() { return 5; } // should match kHttpBody above
165
[email protected]3367fc1d2009-11-09 00:09:21166 void WriteResponse(net::HttpResponseInfo* head,
167 IOBuffer* body, int body_len) {
168 DCHECK(body);
169 scoped_refptr<IOBuffer> body_ref(body);
[email protected]8336aaf42011-11-11 21:05:49170 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseBody,
171 base::Unretained(this), body_ref, body_len));
[email protected]073aabe2009-10-21 18:09:33172 WriteResponseHead(head);
173 }
174
175 void WriteResponseHead(net::HttpResponseInfo* head) {
176 EXPECT_FALSE(writer_->IsWritePending());
177 expected_write_result_ = GetHttpResponseInfoSize(head);
178 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
[email protected]50304162011-12-21 17:51:30179 writer_->WriteInfo(
180 write_info_buffer_,
181 base::Bind(&AppCacheResponseTest::OnWriteInfoComplete,
182 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33183 }
184
185 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
186 EXPECT_FALSE(writer_->IsWritePending());
187 write_buffer_ = io_buffer;
188 expected_write_result_ = buf_len;
189 writer_->WriteData(
[email protected]50304162011-12-21 17:51:30190 write_buffer_, buf_len,
191 base::Bind(&AppCacheResponseTest::OnWriteComplete,
192 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33193 }
194
195 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
196 EXPECT_FALSE(reader_->IsReadPending());
197 read_buffer_ = io_buffer;
198 expected_read_result_ = buf_len;
199 reader_->ReadData(
[email protected]50304162011-12-21 17:51:30200 read_buffer_, buf_len,
201 base::Bind(&AppCacheResponseTest::OnReadComplete,
202 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33203 }
204
205 // AppCacheResponseReader / Writer completion callbacks
206
207 void OnWriteInfoComplete(int result) {
208 EXPECT_FALSE(writer_->IsWritePending());
209 EXPECT_EQ(expected_write_result_, result);
210 ScheduleNextTask();
211 }
212
213 void OnWriteComplete(int result) {
214 EXPECT_FALSE(writer_->IsWritePending());
215 write_callback_was_called_ = true;
216 EXPECT_EQ(expected_write_result_, result);
217 if (should_delete_writer_in_completion_callback_ &&
218 --writer_deletion_count_down_ == 0) {
219 writer_.reset();
220 }
221 ScheduleNextTask();
222 }
223
224 void OnReadInfoComplete(int result) {
225 EXPECT_FALSE(reader_->IsReadPending());
226 EXPECT_EQ(expected_read_result_, result);
227 ScheduleNextTask();
228 }
229
230 void OnReadComplete(int result) {
231 EXPECT_FALSE(reader_->IsReadPending());
232 read_callback_was_called_ = true;
233 EXPECT_EQ(expected_read_result_, result);
234 if (should_delete_reader_in_completion_callback_ &&
235 --reader_deletion_count_down_ == 0) {
236 reader_.reset();
237 }
238 ScheduleNextTask();
239 }
240
241 // Helpers to work with HttpResponseInfo objects
242
[email protected]3367fc1d2009-11-09 00:09:21243 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
[email protected]073aabe2009-10-21 18:09:33244 net::HttpResponseInfo* info = new net::HttpResponseInfo;
245 info->request_time = base::Time::Now();
246 info->response_time = base::Time::Now();
247 info->was_cached = false;
248 info->headers = new net::HttpResponseHeaders(raw_headers);
249 return info;
250 }
251
252 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
253 Pickle pickle;
254 return PickleHttpResonseInfo(&pickle, info);
255 }
256
257 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
258 const net::HttpResponseInfo* info2) {
259 Pickle pickle1;
260 Pickle pickle2;
261 PickleHttpResonseInfo(&pickle1, info1);
262 PickleHttpResonseInfo(&pickle2, info2);
263 return (pickle1.size() == pickle2.size()) &&
264 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
265 }
266
267 int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) {
268 const bool kSkipTransientHeaders = true;
269 const bool kTruncated = false;
270 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
271 return pickle->size();
272 }
273
274 // Helpers to fill and verify blocks of memory with a value
275
276 void FillData(char value, char* data, int data_len) {
277 memset(data, value, data_len);
278 }
279
280 bool CheckData(char value, const char* data, int data_len) {
281 for (int i = 0; i < data_len; ++i, ++data) {
282 if (*data != value)
283 return false;
284 }
285 return true;
286 }
287
288 // Individual Tests ---------------------------------------------------------
289 // Most of the individual tests involve multiple async steps. Each test
290 // is delineated with a section header.
291
[email protected]073aabe2009-10-21 18:09:33292
293 // ReadNonExistentResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33294 void ReadNonExistentResponse() {
295 // 1. Attempt to ReadInfo
296 // 2. Attempt to ReadData
297
298 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36299 GURL(), 0, kNoSuchResponseId));
[email protected]073aabe2009-10-21 18:09:33300
301 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49302 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
303 base::Unretained(this)));
304 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
305 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33306 ScheduleNextTask();
307 }
308
309 void ReadNonExistentInfo() {
310 EXPECT_FALSE(reader_->IsReadPending());
311 read_info_buffer_ = new HttpResponseInfoIOBuffer();
[email protected]50304162011-12-21 17:51:30312 reader_->ReadInfo(
313 read_info_buffer_,
314 base::Bind(&AppCacheResponseTest::OnReadInfoComplete,
315 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33316 EXPECT_TRUE(reader_->IsReadPending());
317 expected_read_result_ = net::ERR_CACHE_MISS;
318 }
319
320 void ReadNonExistentData() {
321 EXPECT_FALSE(reader_->IsReadPending());
322 read_buffer_ = new IOBuffer(kBlockSize);
[email protected]50304162011-12-21 17:51:30323 reader_->ReadData(
324 read_buffer_, kBlockSize,
325 base::Bind(&AppCacheResponseTest::OnReadComplete,
326 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33327 EXPECT_TRUE(reader_->IsReadPending());
328 expected_read_result_ = net::ERR_CACHE_MISS;
329 }
330
331 // LoadResponseInfo_Miss ----------------------------------------------------
332 void LoadResponseInfo_Miss() {
[email protected]8336aaf42011-11-11 21:05:49333 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
334 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36335 service_->storage()->LoadResponseInfo(GURL(), 0, kNoSuchResponseId,
[email protected]073aabe2009-10-21 18:09:33336 storage_delegate_.get());
337 }
338
339 void LoadResponseInfo_Miss_Verify() {
[email protected]dda06f82009-10-21 18:38:51340 EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_);
[email protected]073aabe2009-10-21 18:09:33341 EXPECT_TRUE(!storage_delegate_->loaded_info_.get());
342 TestFinished();
343 }
344
345 // LoadResponseInfo_Hit ----------------------------------------------------
346 void LoadResponseInfo_Hit() {
347 // This tests involves multiple async steps.
348 // 1. Write a response headers and body to storage
349 // a. headers
350 // b. body
351 // 2. Use LoadResponseInfo to read the response headers back out
[email protected]8336aaf42011-11-11 21:05:49352 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
353 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36354 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33355 written_response_id_ = writer_->response_id();
356 WriteBasicResponse();
357 }
358
359 void LoadResponseInfo_Hit_Step2() {
360 writer_.reset();
[email protected]8336aaf42011-11-11 21:05:49361 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
362 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36363 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
[email protected]073aabe2009-10-21 18:09:33364 storage_delegate_.get());
365 }
366
367 void LoadResponseInfo_Hit_Verify() {
368 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
369 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
370 EXPECT_TRUE(CompareHttpResponseInfos(
371 write_info_buffer_->http_info.get(),
372 storage_delegate_->loaded_info_->http_response_info()));
[email protected]fd2885a2010-03-17 22:02:28373 EXPECT_EQ(basic_response_size(),
374 storage_delegate_->loaded_info_->response_data_size());
[email protected]073aabe2009-10-21 18:09:33375 TestFinished();
376 }
377
[email protected]0dfeec32010-01-06 22:25:33378 // AmountWritten ----------------------------------------------------
379
380 void AmountWritten() {
381 static const char kHttpHeaders[] =
382 "HTTP/1.0 200 OK\0\0";
383 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
384 net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
385 int expected_amount_written =
386 GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
387
388 // Push tasks in reverse order.
[email protected]8336aaf42011-11-11 21:05:49389 PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
390 base::Unretained(this), expected_amount_written));
[email protected]0dfeec32010-01-06 22:25:33391 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49392 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
393 base::Unretained(this), kNumBlocks - i));
[email protected]0dfeec32010-01-06 22:25:33394 }
[email protected]8336aaf42011-11-11 21:05:49395 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
396 base::Unretained(this), head));
[email protected]0dfeec32010-01-06 22:25:33397
[email protected]4252f602011-10-21 19:18:36398 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]0dfeec32010-01-06 22:25:33399 written_response_id_ = writer_->response_id();
400 ScheduleNextTask();
401 }
402
403 void Verify_AmountWritten(int expected_amount_written) {
404 EXPECT_EQ(expected_amount_written, writer_->amount_written());
405 TestFinished();
406 }
407
408
[email protected]073aabe2009-10-21 18:09:33409 // WriteThenVariouslyReadResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33410
411 void WriteThenVariouslyReadResponse() {
412 // This tests involves multiple async steps.
413 // 1. First, write a large body using multiple writes, we don't bother
414 // with a response head for this test.
415 // 2. Read the entire body, using multiple reads
416 // 3. Read the entire body, using one read.
417 // 4. Attempt to read beyond the EOF.
418 // 5. Read just a range.
419 // 6. Attempt to read beyond EOF of a range.
420
421 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49422 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
423 base::Unretained(this)));
424 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
425 base::Unretained(this)));
426 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
427 base::Unretained(this)));
428 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
429 base::Unretained(this)));
430 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
431 base::Unretained(this)));
432 PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
433 base::Unretained(this)));
434 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
435 base::Unretained(this)));
436 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
437 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33438
439 // Get them going.
440 ScheduleNextTask();
441 }
442
443 void WriteOutBlocks() {
[email protected]4252f602011-10-21 19:18:36444 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33445 written_response_id_ = writer_->response_id();
446 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49447 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
448 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33449 }
450 ScheduleNextTask();
451 }
452
453 void WriteOneBlock(int block_number) {
[email protected]ad8e04a2010-11-01 04:16:27454 scoped_refptr<IOBuffer> io_buffer(
455 new IOBuffer(kBlockSize));
[email protected]073aabe2009-10-21 18:09:33456 FillData(block_number, io_buffer->data(), kBlockSize);
457 WriteResponseBody(io_buffer, kBlockSize);
458 }
459
460 void ReadInBlocks() {
461 writer_.reset();
462 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36463 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33464 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49465 PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
466 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33467 }
468 ScheduleNextTask();
469 }
470
471 void ReadOneBlock(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49472 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
473 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33474 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
475 }
476
477 void VerifyOneBlock(int block_number) {
478 EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
479 ScheduleNextTask();
480 }
481
482 void ReadAllAtOnce() {
[email protected]8336aaf42011-11-11 21:05:49483 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
484 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33485 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36486 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33487 int big_size = kNumBlocks * kBlockSize;
488 ReadResponseBody(new IOBuffer(big_size), big_size);
489 }
490
491 void VerifyAllAtOnce() {
492 char* p = read_buffer_->data();
493 for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
494 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
495 ScheduleNextTask();
496 }
497
498 void ReadPastEOF() {
499 EXPECT_FALSE(reader_->IsReadPending());
500 read_buffer_ = new IOBuffer(kBlockSize);
501 expected_read_result_ = 0;
502 reader_->ReadData(
[email protected]50304162011-12-21 17:51:30503 read_buffer_, kBlockSize,
504 base::Bind(&AppCacheResponseTest::OnReadComplete,
505 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33506 }
507
508 void ReadRange() {
[email protected]8336aaf42011-11-11 21:05:49509 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
510 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33511 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36512 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33513 reader_->SetReadRange(kBlockSize, kBlockSize);
514 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
515 }
516
517 void VerifyRange() {
518 EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
519 ScheduleNextTask(); // ReadPastEOF is scheduled next
520 }
521
522 void ReadRangePartiallyBeyondEOF() {
[email protected]8336aaf42011-11-11 21:05:49523 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
524 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33525 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36526 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33527 reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
528 ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
529 kNumBlocks * kBlockSize);
530 expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
531 }
532
533 void VerifyRangeBeyondEOF() {
534 // Just verify the first 1k
535 VerifyRange();
536 }
537
538 void ReadRangeFullyBeyondEOF() {
539 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36540 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33541 reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
542 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
543 expected_read_result_ = 0;
544 }
545
546 // IOChaining -------------------------------------------
547 void IOChaining() {
548 // 1. Write several blocks out initiating the subsequent write
549 // from within the completion callback of the previous write.
550 // 2. Read and verify several blocks in similarly chaining reads.
551
552 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49553 PushNextTaskAsImmediate(
554 base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately,
555 base::Unretained(this)));
556 PushNextTaskAsImmediate(
557 base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately,
558 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33559
560 // Get them going.
561 ScheduleNextTask();
562 }
563
564 void WriteOutBlocksImmediately() {
[email protected]4252f602011-10-21 19:18:36565 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33566 written_response_id_ = writer_->response_id();
567 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49568 PushNextTaskAsImmediate(
569 base::Bind(&AppCacheResponseTest::WriteOneBlock,
570 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33571 }
572 ScheduleNextTask();
573 }
574
575 void ReadInBlocksImmediately() {
576 writer_.reset();
577 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36578 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33579 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49580 PushNextTaskAsImmediate(
581 base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately,
582 base::Unretained(this),
[email protected]79b15b22010-05-19 00:38:56583 kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33584 }
585 ScheduleNextTask();
586 }
587
588 void ReadOneBlockImmediately(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49589 PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
590 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33591 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
592 }
593
594 // DeleteWithinCallbacks -------------------------------------------
595 void DeleteWithinCallbacks() {
596 // 1. Write out a few blocks normally, and upon
597 // completion of the last write, delete the writer.
598 // 2. Read in a few blocks normally, and upon completion
599 // of the last read, delete the reader.
600
601 should_delete_reader_in_completion_callback_ = true;
602 reader_deletion_count_down_ = kNumBlocks;
603 should_delete_writer_in_completion_callback_ = true;
604 writer_deletion_count_down_ = kNumBlocks;
605
[email protected]8336aaf42011-11-11 21:05:49606 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
607 base::Unretained(this)));
608 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
609 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33610 ScheduleNextTask();
611 }
612
613 // DeleteWithIOPending -------------------------------------------
614 void DeleteWithIOPending() {
615 // 1. Write a few blocks normally.
616 // 2. Start a write, delete with it pending.
617 // 3. Start a read, delete with it pending.
[email protected]8336aaf42011-11-11 21:05:49618 PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
619 base::Unretained(this)));
620 PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
621 base::Unretained(this)));
622 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
623 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33624 ScheduleNextTask();
625 }
626
627 void WriteThenDelete() {
628 write_callback_was_called_ = false;
629 WriteOneBlock(5);
630 EXPECT_TRUE(writer_->IsWritePending());
631 writer_.reset();
632 ScheduleNextTask();
633 }
634
635 void ReadThenDelete() {
636 read_callback_was_called_ = false;
637 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36638 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33639 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
640 EXPECT_TRUE(reader_->IsReadPending());
641 reader_.reset();
642
643 // Wait a moment to verify no callbacks.
[email protected]4cc586b2013-05-07 12:43:32644 base::MessageLoop::current()->PostDelayedTask(
[email protected]8336aaf42011-11-11 21:05:49645 FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
646 base::Unretained(this)),
[email protected]6f35f4e2012-03-03 21:02:28647 base::TimeDelta::FromMilliseconds(10));
[email protected]073aabe2009-10-21 18:09:33648 }
649
650 void VerifyNoCallbacks() {
651 EXPECT_TRUE(!write_callback_was_called_);
652 EXPECT_TRUE(!read_callback_was_called_);
653 TestFinished();
654 }
655
656 // Data members
657
[email protected]073aabe2009-10-21 18:09:33658 scoped_ptr<base::WaitableEvent> test_finished_event_;
659 scoped_ptr<MockStorageDelegate> storage_delegate_;
660 scoped_ptr<MockAppCacheService> service_;
[email protected]8336aaf42011-11-11 21:05:49661 std::stack<std::pair<base::Closure, bool> > task_stack_;
[email protected]073aabe2009-10-21 18:09:33662
663 scoped_ptr<AppCacheResponseReader> reader_;
664 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
665 scoped_refptr<IOBuffer> read_buffer_;
666 int expected_read_result_;
[email protected]073aabe2009-10-21 18:09:33667 bool should_delete_reader_in_completion_callback_;
668 int reader_deletion_count_down_;
669 bool read_callback_was_called_;
670
671 int64 written_response_id_;
672 scoped_ptr<AppCacheResponseWriter> writer_;
673 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
674 scoped_refptr<IOBuffer> write_buffer_;
675 int expected_write_result_;
[email protected]073aabe2009-10-21 18:09:33676 bool should_delete_writer_in_completion_callback_;
677 int writer_deletion_count_down_;
678 bool write_callback_was_called_;
679
680 static scoped_ptr<base::Thread> io_thread_;
681};
682
683// static
684scoped_ptr<base::Thread> AppCacheResponseTest::io_thread_;
685
[email protected]073aabe2009-10-21 18:09:33686TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
687 RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
688}
689
690TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
691 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
692}
693
694TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
695 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
696}
697
[email protected]0dfeec32010-01-06 22:25:33698TEST_F(AppCacheResponseTest, AmountWritten) {
699 RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
700}
701
[email protected]073aabe2009-10-21 18:09:33702TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
703 RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
704}
705
706TEST_F(AppCacheResponseTest, IOChaining) {
707 RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
708}
709
710TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
711 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
712}
713
714TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
715 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
716}
717
718} // namespace appcache