blob: 935fd7cd773317229720807c2c3e25f65eb0c525 [file] [log] [blame]
[email protected]a507b822014-04-12 05:10:241// Copyright 2014 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]44f9c952011-01-02 06:05:3914#include "base/synchronization/waitable_event.h"
[email protected]d5b2fdf2013-06-05 09:36:5515#include "base/threading/thread.h"
[email protected]71fe3d12014-04-22 00:32:3816#include "content/browser/appcache/mock_appcache_service.h"
[email protected]073aabe2009-10-21 18:09:3317#include "net/base/io_buffer.h"
[email protected]80d42812010-02-09 10:30:2518#include "net/base/net_errors.h"
[email protected]277d5942010-08-11 21:02:3519#include "net/http/http_response_headers.h"
[email protected]073aabe2009-10-21 18:09:3320#include "testing/gtest/include/gtest/gtest.h"
[email protected]d5b2fdf2013-06-05 09:36:5521#include "webkit/browser/appcache/appcache_response.h"
[email protected]073aabe2009-10-21 18:09:3322
[email protected]a507b822014-04-12 05:10:2423using appcache::AppCacheStorage;
24using appcache::AppCacheResponseInfo;
25using appcache::AppCacheResponseReader;
26using appcache::AppCacheResponseWriter;
27using appcache::HttpResponseInfoIOBuffer;
[email protected]073aabe2009-10-21 18:09:3328using net::IOBuffer;
[email protected]3367fc1d2009-11-09 00:09:2129using net::WrappedIOBuffer;
[email protected]073aabe2009-10-21 18:09:3330
[email protected]a507b822014-04-12 05:10:2431namespace content {
[email protected]073aabe2009-10-21 18:09:3332
[email protected]dda06f82009-10-21 18:38:5133static const int kNumBlocks = 4;
34static const int kBlockSize = 1024;
35static const int kNoSuchResponseId = 123;
36
[email protected]073aabe2009-10-21 18:09:3337class AppCacheResponseTest : public testing::Test {
38 public:
39
40 // Test Harness -------------------------------------------------------------
41
42 // Helper class used to verify test results
43 class MockStorageDelegate : public AppCacheStorage::Delegate {
44 public:
45 explicit MockStorageDelegate(AppCacheResponseTest* test)
46 : loaded_info_id_(0), test_(test) {
47 }
48
49 virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
[email protected]7fd8fa4f2013-02-07 05:43:5050 int64 response_id) OVERRIDE {
[email protected]073aabe2009-10-21 18:09:3351 loaded_info_ = info;
52 loaded_info_id_ = response_id;
53 test_->ScheduleNextTask();
54 }
55
56 scoped_refptr<AppCacheResponseInfo> loaded_info_;
57 int64 loaded_info_id_;
58 AppCacheResponseTest* test_;
59 };
60
[email protected]72a3ce52011-12-22 05:10:2461 // Helper callback to run a test on our io_thread. The io_thread is spun up
62 // once and reused for all tests.
[email protected]073aabe2009-10-21 18:09:3363 template <class Method>
[email protected]72a3ce52011-12-22 05:10:2464 void MethodWrapper(Method method) {
65 SetUpTest();
66 (this->*method)();
67 }
[email protected]073aabe2009-10-21 18:09:3368
69 static void SetUpTestCase() {
70 io_thread_.reset(new base::Thread("AppCacheResponseTest Thread"));
[email protected]4cc586b2013-05-07 12:43:3271 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
[email protected]073aabe2009-10-21 18:09:3372 io_thread_->StartWithOptions(options);
73 }
74
75 static void TearDownTestCase() {
76 io_thread_.reset(NULL);
77 }
78
[email protected]50304162011-12-21 17:51:3079 AppCacheResponseTest() {}
[email protected]073aabe2009-10-21 18:09:3380
81 template <class Method>
82 void RunTestOnIOThread(Method method) {
83 test_finished_event_ .reset(new base::WaitableEvent(false, false));
84 io_thread_->message_loop()->PostTask(
[email protected]72a3ce52011-12-22 05:10:2485 FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
86 base::Unretained(this), method));
[email protected]073aabe2009-10-21 18:09:3387 test_finished_event_->Wait();
88 }
89
90 void SetUpTest() {
[email protected]4cc586b2013-05-07 12:43:3291 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]073aabe2009-10-21 18:09:3392 DCHECK(task_stack_.empty());
93 storage_delegate_.reset(new MockStorageDelegate(this));
94 service_.reset(new MockAppCacheService());
95 expected_read_result_ = 0;
96 expected_write_result_ = 0;
97 written_response_id_ = 0;
98 should_delete_reader_in_completion_callback_ = false;
99 should_delete_writer_in_completion_callback_ = false;
100 reader_deletion_count_down_ = 0;
101 writer_deletion_count_down_ = 0;
102 read_callback_was_called_ = false;
103 write_callback_was_called_ = false;
104 }
105
106 void TearDownTest() {
[email protected]4cc586b2013-05-07 12:43:32107 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]8336aaf42011-11-11 21:05:49108 while (!task_stack_.empty())
[email protected]073aabe2009-10-21 18:09:33109 task_stack_.pop();
[email protected]8336aaf42011-11-11 21:05:49110
[email protected]073aabe2009-10-21 18:09:33111 reader_.reset();
112 read_buffer_ = NULL;
113 read_info_buffer_ = NULL;
114 writer_.reset();
115 write_buffer_ = NULL;
116 write_info_buffer_ = NULL;
117 storage_delegate_.reset();
118 service_.reset();
119 }
120
121 void TestFinished() {
122 // We unwind the stack prior to finishing up to let stack
123 // based objects get deleted.
[email protected]4cc586b2013-05-07 12:43:32124 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
125 base::MessageLoop::current()->PostTask(
[email protected]8336aaf42011-11-11 21:05:49126 FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound,
127 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33128 }
129
130 void TestFinishedUnwound() {
131 TearDownTest();
132 test_finished_event_->Signal();
133 }
134
[email protected]8336aaf42011-11-11 21:05:49135 void PushNextTask(const base::Closure& task) {
136 task_stack_.push(std::pair<base::Closure, bool>(task, false));
[email protected]073aabe2009-10-21 18:09:33137 }
138
[email protected]8336aaf42011-11-11 21:05:49139 void PushNextTaskAsImmediate(const base::Closure& task) {
140 task_stack_.push(std::pair<base::Closure, bool>(task, true));
[email protected]073aabe2009-10-21 18:09:33141 }
142
143 void ScheduleNextTask() {
[email protected]4cc586b2013-05-07 12:43:32144 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]073aabe2009-10-21 18:09:33145 if (task_stack_.empty()) {
146 TestFinished();
147 return;
148 }
[email protected]8336aaf42011-11-11 21:05:49149 base::Closure task = task_stack_.top().first;
[email protected]073aabe2009-10-21 18:09:33150 bool immediate = task_stack_.top().second;
151 task_stack_.pop();
152 if (immediate)
[email protected]8336aaf42011-11-11 21:05:49153 task.Run();
[email protected]073aabe2009-10-21 18:09:33154 else
[email protected]4cc586b2013-05-07 12:43:32155 base::MessageLoop::current()->PostTask(FROM_HERE, task);
[email protected]073aabe2009-10-21 18:09:33156 }
157
158 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
159
160 void WriteBasicResponse() {
[email protected]3367fc1d2009-11-09 00:09:21161 static const char kHttpHeaders[] =
162 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
163 static const char* kHttpBody = "Hello";
[email protected]ad8e04a2010-11-01 04:16:27164 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
[email protected]3367fc1d2009-11-09 00:09:21165 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
[email protected]ff875be52013-06-02 23:47:38166 WriteResponse(
167 MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBody));
[email protected]073aabe2009-10-21 18:09:33168 }
169
[email protected]fd2885a2010-03-17 22:02:28170 int basic_response_size() { return 5; } // should match kHttpBody above
171
[email protected]3367fc1d2009-11-09 00:09:21172 void WriteResponse(net::HttpResponseInfo* head,
173 IOBuffer* body, int body_len) {
174 DCHECK(body);
175 scoped_refptr<IOBuffer> body_ref(body);
[email protected]8336aaf42011-11-11 21:05:49176 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseBody,
177 base::Unretained(this), body_ref, body_len));
[email protected]073aabe2009-10-21 18:09:33178 WriteResponseHead(head);
179 }
180
181 void WriteResponseHead(net::HttpResponseInfo* head) {
182 EXPECT_FALSE(writer_->IsWritePending());
183 expected_write_result_ = GetHttpResponseInfoSize(head);
184 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
[email protected]ff875be52013-06-02 23:47:38185 writer_->WriteInfo(write_info_buffer_.get(),
186 base::Bind(&AppCacheResponseTest::OnWriteInfoComplete,
187 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33188 }
189
190 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
191 EXPECT_FALSE(writer_->IsWritePending());
192 write_buffer_ = io_buffer;
193 expected_write_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38194 writer_->WriteData(write_buffer_.get(),
195 buf_len,
196 base::Bind(&AppCacheResponseTest::OnWriteComplete,
197 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33198 }
199
200 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
201 EXPECT_FALSE(reader_->IsReadPending());
202 read_buffer_ = io_buffer;
203 expected_read_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38204 reader_->ReadData(read_buffer_.get(),
205 buf_len,
206 base::Bind(&AppCacheResponseTest::OnReadComplete,
207 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33208 }
209
210 // AppCacheResponseReader / Writer completion callbacks
211
212 void OnWriteInfoComplete(int result) {
213 EXPECT_FALSE(writer_->IsWritePending());
214 EXPECT_EQ(expected_write_result_, result);
215 ScheduleNextTask();
216 }
217
218 void OnWriteComplete(int result) {
219 EXPECT_FALSE(writer_->IsWritePending());
220 write_callback_was_called_ = true;
221 EXPECT_EQ(expected_write_result_, result);
222 if (should_delete_writer_in_completion_callback_ &&
223 --writer_deletion_count_down_ == 0) {
224 writer_.reset();
225 }
226 ScheduleNextTask();
227 }
228
229 void OnReadInfoComplete(int result) {
230 EXPECT_FALSE(reader_->IsReadPending());
231 EXPECT_EQ(expected_read_result_, result);
232 ScheduleNextTask();
233 }
234
235 void OnReadComplete(int result) {
236 EXPECT_FALSE(reader_->IsReadPending());
237 read_callback_was_called_ = true;
238 EXPECT_EQ(expected_read_result_, result);
239 if (should_delete_reader_in_completion_callback_ &&
240 --reader_deletion_count_down_ == 0) {
241 reader_.reset();
242 }
243 ScheduleNextTask();
244 }
245
246 // Helpers to work with HttpResponseInfo objects
247
[email protected]3367fc1d2009-11-09 00:09:21248 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
[email protected]073aabe2009-10-21 18:09:33249 net::HttpResponseInfo* info = new net::HttpResponseInfo;
250 info->request_time = base::Time::Now();
251 info->response_time = base::Time::Now();
252 info->was_cached = false;
253 info->headers = new net::HttpResponseHeaders(raw_headers);
254 return info;
255 }
256
257 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
258 Pickle pickle;
259 return PickleHttpResonseInfo(&pickle, info);
260 }
261
262 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
263 const net::HttpResponseInfo* info2) {
264 Pickle pickle1;
265 Pickle pickle2;
266 PickleHttpResonseInfo(&pickle1, info1);
267 PickleHttpResonseInfo(&pickle2, info2);
268 return (pickle1.size() == pickle2.size()) &&
269 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
270 }
271
272 int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) {
273 const bool kSkipTransientHeaders = true;
274 const bool kTruncated = false;
275 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
276 return pickle->size();
277 }
278
279 // Helpers to fill and verify blocks of memory with a value
280
281 void FillData(char value, char* data, int data_len) {
282 memset(data, value, data_len);
283 }
284
285 bool CheckData(char value, const char* data, int data_len) {
286 for (int i = 0; i < data_len; ++i, ++data) {
287 if (*data != value)
288 return false;
289 }
290 return true;
291 }
292
293 // Individual Tests ---------------------------------------------------------
294 // Most of the individual tests involve multiple async steps. Each test
295 // is delineated with a section header.
296
[email protected]073aabe2009-10-21 18:09:33297
298 // ReadNonExistentResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33299 void ReadNonExistentResponse() {
300 // 1. Attempt to ReadInfo
301 // 2. Attempt to ReadData
302
303 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36304 GURL(), 0, kNoSuchResponseId));
[email protected]073aabe2009-10-21 18:09:33305
306 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49307 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
308 base::Unretained(this)));
309 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
310 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33311 ScheduleNextTask();
312 }
313
314 void ReadNonExistentInfo() {
315 EXPECT_FALSE(reader_->IsReadPending());
316 read_info_buffer_ = new HttpResponseInfoIOBuffer();
[email protected]ff875be52013-06-02 23:47:38317 reader_->ReadInfo(read_info_buffer_.get(),
318 base::Bind(&AppCacheResponseTest::OnReadInfoComplete,
319 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33320 EXPECT_TRUE(reader_->IsReadPending());
321 expected_read_result_ = net::ERR_CACHE_MISS;
322 }
323
324 void ReadNonExistentData() {
325 EXPECT_FALSE(reader_->IsReadPending());
326 read_buffer_ = new IOBuffer(kBlockSize);
[email protected]ff875be52013-06-02 23:47:38327 reader_->ReadData(read_buffer_.get(),
328 kBlockSize,
329 base::Bind(&AppCacheResponseTest::OnReadComplete,
330 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33331 EXPECT_TRUE(reader_->IsReadPending());
332 expected_read_result_ = net::ERR_CACHE_MISS;
333 }
334
335 // LoadResponseInfo_Miss ----------------------------------------------------
336 void LoadResponseInfo_Miss() {
[email protected]8336aaf42011-11-11 21:05:49337 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
338 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36339 service_->storage()->LoadResponseInfo(GURL(), 0, kNoSuchResponseId,
[email protected]073aabe2009-10-21 18:09:33340 storage_delegate_.get());
341 }
342
343 void LoadResponseInfo_Miss_Verify() {
[email protected]dda06f82009-10-21 18:38:51344 EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_);
[email protected]073aabe2009-10-21 18:09:33345 EXPECT_TRUE(!storage_delegate_->loaded_info_.get());
346 TestFinished();
347 }
348
349 // LoadResponseInfo_Hit ----------------------------------------------------
350 void LoadResponseInfo_Hit() {
351 // This tests involves multiple async steps.
352 // 1. Write a response headers and body to storage
353 // a. headers
354 // b. body
355 // 2. Use LoadResponseInfo to read the response headers back out
[email protected]8336aaf42011-11-11 21:05:49356 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
357 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36358 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33359 written_response_id_ = writer_->response_id();
360 WriteBasicResponse();
361 }
362
363 void LoadResponseInfo_Hit_Step2() {
364 writer_.reset();
[email protected]8336aaf42011-11-11 21:05:49365 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
366 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36367 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
[email protected]073aabe2009-10-21 18:09:33368 storage_delegate_.get());
369 }
370
371 void LoadResponseInfo_Hit_Verify() {
372 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
373 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
374 EXPECT_TRUE(CompareHttpResponseInfos(
375 write_info_buffer_->http_info.get(),
376 storage_delegate_->loaded_info_->http_response_info()));
[email protected]fd2885a2010-03-17 22:02:28377 EXPECT_EQ(basic_response_size(),
378 storage_delegate_->loaded_info_->response_data_size());
[email protected]073aabe2009-10-21 18:09:33379 TestFinished();
380 }
381
[email protected]0dfeec32010-01-06 22:25:33382 // AmountWritten ----------------------------------------------------
383
384 void AmountWritten() {
385 static const char kHttpHeaders[] =
386 "HTTP/1.0 200 OK\0\0";
387 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
388 net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
389 int expected_amount_written =
390 GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
391
392 // Push tasks in reverse order.
[email protected]8336aaf42011-11-11 21:05:49393 PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
394 base::Unretained(this), expected_amount_written));
[email protected]0dfeec32010-01-06 22:25:33395 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49396 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
397 base::Unretained(this), kNumBlocks - i));
[email protected]0dfeec32010-01-06 22:25:33398 }
[email protected]8336aaf42011-11-11 21:05:49399 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
400 base::Unretained(this), head));
[email protected]0dfeec32010-01-06 22:25:33401
[email protected]4252f602011-10-21 19:18:36402 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]0dfeec32010-01-06 22:25:33403 written_response_id_ = writer_->response_id();
404 ScheduleNextTask();
405 }
406
407 void Verify_AmountWritten(int expected_amount_written) {
408 EXPECT_EQ(expected_amount_written, writer_->amount_written());
409 TestFinished();
410 }
411
412
[email protected]073aabe2009-10-21 18:09:33413 // WriteThenVariouslyReadResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33414
415 void WriteThenVariouslyReadResponse() {
416 // This tests involves multiple async steps.
417 // 1. First, write a large body using multiple writes, we don't bother
418 // with a response head for this test.
419 // 2. Read the entire body, using multiple reads
420 // 3. Read the entire body, using one read.
421 // 4. Attempt to read beyond the EOF.
422 // 5. Read just a range.
423 // 6. Attempt to read beyond EOF of a range.
424
425 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49426 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
427 base::Unretained(this)));
428 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
429 base::Unretained(this)));
430 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
431 base::Unretained(this)));
432 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
433 base::Unretained(this)));
434 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
435 base::Unretained(this)));
436 PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
437 base::Unretained(this)));
438 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
439 base::Unretained(this)));
440 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
441 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33442
443 // Get them going.
444 ScheduleNextTask();
445 }
446
447 void WriteOutBlocks() {
[email protected]4252f602011-10-21 19:18:36448 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33449 written_response_id_ = writer_->response_id();
450 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49451 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
452 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33453 }
454 ScheduleNextTask();
455 }
456
457 void WriteOneBlock(int block_number) {
[email protected]ad8e04a2010-11-01 04:16:27458 scoped_refptr<IOBuffer> io_buffer(
459 new IOBuffer(kBlockSize));
[email protected]073aabe2009-10-21 18:09:33460 FillData(block_number, io_buffer->data(), kBlockSize);
461 WriteResponseBody(io_buffer, kBlockSize);
462 }
463
464 void ReadInBlocks() {
465 writer_.reset();
466 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36467 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33468 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49469 PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
470 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33471 }
472 ScheduleNextTask();
473 }
474
475 void ReadOneBlock(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49476 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
477 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33478 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
479 }
480
481 void VerifyOneBlock(int block_number) {
482 EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
483 ScheduleNextTask();
484 }
485
486 void ReadAllAtOnce() {
[email protected]8336aaf42011-11-11 21:05:49487 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
488 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33489 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36490 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33491 int big_size = kNumBlocks * kBlockSize;
492 ReadResponseBody(new IOBuffer(big_size), big_size);
493 }
494
495 void VerifyAllAtOnce() {
496 char* p = read_buffer_->data();
497 for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
498 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
499 ScheduleNextTask();
500 }
501
502 void ReadPastEOF() {
503 EXPECT_FALSE(reader_->IsReadPending());
504 read_buffer_ = new IOBuffer(kBlockSize);
505 expected_read_result_ = 0;
[email protected]ff875be52013-06-02 23:47:38506 reader_->ReadData(read_buffer_.get(),
507 kBlockSize,
508 base::Bind(&AppCacheResponseTest::OnReadComplete,
509 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33510 }
511
512 void ReadRange() {
[email protected]8336aaf42011-11-11 21:05:49513 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
514 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33515 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36516 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33517 reader_->SetReadRange(kBlockSize, kBlockSize);
518 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
519 }
520
521 void VerifyRange() {
522 EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
523 ScheduleNextTask(); // ReadPastEOF is scheduled next
524 }
525
526 void ReadRangePartiallyBeyondEOF() {
[email protected]8336aaf42011-11-11 21:05:49527 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
528 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33529 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36530 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33531 reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
532 ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
533 kNumBlocks * kBlockSize);
534 expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
535 }
536
537 void VerifyRangeBeyondEOF() {
538 // Just verify the first 1k
539 VerifyRange();
540 }
541
542 void ReadRangeFullyBeyondEOF() {
543 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36544 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33545 reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
546 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
547 expected_read_result_ = 0;
548 }
549
550 // IOChaining -------------------------------------------
551 void IOChaining() {
552 // 1. Write several blocks out initiating the subsequent write
553 // from within the completion callback of the previous write.
554 // 2. Read and verify several blocks in similarly chaining reads.
555
556 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49557 PushNextTaskAsImmediate(
558 base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately,
559 base::Unretained(this)));
560 PushNextTaskAsImmediate(
561 base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately,
562 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33563
564 // Get them going.
565 ScheduleNextTask();
566 }
567
568 void WriteOutBlocksImmediately() {
[email protected]4252f602011-10-21 19:18:36569 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33570 written_response_id_ = writer_->response_id();
571 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49572 PushNextTaskAsImmediate(
573 base::Bind(&AppCacheResponseTest::WriteOneBlock,
574 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33575 }
576 ScheduleNextTask();
577 }
578
579 void ReadInBlocksImmediately() {
580 writer_.reset();
581 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36582 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33583 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49584 PushNextTaskAsImmediate(
585 base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately,
586 base::Unretained(this),
[email protected]79b15b22010-05-19 00:38:56587 kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33588 }
589 ScheduleNextTask();
590 }
591
592 void ReadOneBlockImmediately(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49593 PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
594 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33595 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
596 }
597
598 // DeleteWithinCallbacks -------------------------------------------
599 void DeleteWithinCallbacks() {
600 // 1. Write out a few blocks normally, and upon
601 // completion of the last write, delete the writer.
602 // 2. Read in a few blocks normally, and upon completion
603 // of the last read, delete the reader.
604
605 should_delete_reader_in_completion_callback_ = true;
606 reader_deletion_count_down_ = kNumBlocks;
607 should_delete_writer_in_completion_callback_ = true;
608 writer_deletion_count_down_ = kNumBlocks;
609
[email protected]8336aaf42011-11-11 21:05:49610 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
611 base::Unretained(this)));
612 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
613 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33614 ScheduleNextTask();
615 }
616
617 // DeleteWithIOPending -------------------------------------------
618 void DeleteWithIOPending() {
619 // 1. Write a few blocks normally.
620 // 2. Start a write, delete with it pending.
621 // 3. Start a read, delete with it pending.
[email protected]8336aaf42011-11-11 21:05:49622 PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
623 base::Unretained(this)));
624 PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
625 base::Unretained(this)));
626 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
627 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33628 ScheduleNextTask();
629 }
630
631 void WriteThenDelete() {
632 write_callback_was_called_ = false;
633 WriteOneBlock(5);
634 EXPECT_TRUE(writer_->IsWritePending());
635 writer_.reset();
636 ScheduleNextTask();
637 }
638
639 void ReadThenDelete() {
640 read_callback_was_called_ = false;
641 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36642 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33643 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
644 EXPECT_TRUE(reader_->IsReadPending());
645 reader_.reset();
646
647 // Wait a moment to verify no callbacks.
[email protected]4cc586b2013-05-07 12:43:32648 base::MessageLoop::current()->PostDelayedTask(
[email protected]8336aaf42011-11-11 21:05:49649 FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
650 base::Unretained(this)),
[email protected]6f35f4e2012-03-03 21:02:28651 base::TimeDelta::FromMilliseconds(10));
[email protected]073aabe2009-10-21 18:09:33652 }
653
654 void VerifyNoCallbacks() {
655 EXPECT_TRUE(!write_callback_was_called_);
656 EXPECT_TRUE(!read_callback_was_called_);
657 TestFinished();
658 }
659
660 // Data members
661
[email protected]073aabe2009-10-21 18:09:33662 scoped_ptr<base::WaitableEvent> test_finished_event_;
663 scoped_ptr<MockStorageDelegate> storage_delegate_;
664 scoped_ptr<MockAppCacheService> service_;
[email protected]8336aaf42011-11-11 21:05:49665 std::stack<std::pair<base::Closure, bool> > task_stack_;
[email protected]073aabe2009-10-21 18:09:33666
667 scoped_ptr<AppCacheResponseReader> reader_;
668 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
669 scoped_refptr<IOBuffer> read_buffer_;
670 int expected_read_result_;
[email protected]073aabe2009-10-21 18:09:33671 bool should_delete_reader_in_completion_callback_;
672 int reader_deletion_count_down_;
673 bool read_callback_was_called_;
674
675 int64 written_response_id_;
676 scoped_ptr<AppCacheResponseWriter> writer_;
677 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
678 scoped_refptr<IOBuffer> write_buffer_;
679 int expected_write_result_;
[email protected]073aabe2009-10-21 18:09:33680 bool should_delete_writer_in_completion_callback_;
681 int writer_deletion_count_down_;
682 bool write_callback_was_called_;
683
684 static scoped_ptr<base::Thread> io_thread_;
685};
686
687// static
688scoped_ptr<base::Thread> AppCacheResponseTest::io_thread_;
689
[email protected]073aabe2009-10-21 18:09:33690TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
691 RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
692}
693
694TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
695 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
696}
697
698TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
699 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
700}
701
[email protected]0dfeec32010-01-06 22:25:33702TEST_F(AppCacheResponseTest, AmountWritten) {
703 RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
704}
705
[email protected]073aabe2009-10-21 18:09:33706TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
707 RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
708}
709
710TEST_F(AppCacheResponseTest, IOChaining) {
711 RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
712}
713
714TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
715 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
716}
717
718TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
719 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
720}
721
[email protected]a507b822014-04-12 05:10:24722} // namespace content