blob: 815e69789c850d500b4584cde68ce37b8950fd55 [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]98d6d4562014-06-25 20:57:5516#include "content/browser/appcache/appcache_response.h"
[email protected]71fe3d12014-04-22 00:32:3817#include "content/browser/appcache/mock_appcache_service.h"
[email protected]073aabe2009-10-21 18:09:3318#include "net/base/io_buffer.h"
[email protected]80d42812010-02-09 10:30:2519#include "net/base/net_errors.h"
[email protected]277d5942010-08-11 21:02:3520#include "net/http/http_response_headers.h"
[email protected]073aabe2009-10-21 18:09:3321#include "testing/gtest/include/gtest/gtest.h"
[email protected]073aabe2009-10-21 18:09:3322
[email protected]073aabe2009-10-21 18:09:3323using net::IOBuffer;
[email protected]3367fc1d2009-11-09 00:09:2124using net::WrappedIOBuffer;
[email protected]073aabe2009-10-21 18:09:3325
[email protected]a507b822014-04-12 05:10:2426namespace content {
[email protected]073aabe2009-10-21 18:09:3327
[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:
[email protected]073aabe2009-10-21 18:09:3334 // Test Harness -------------------------------------------------------------
35
36 // Helper class used to verify test results
37 class MockStorageDelegate : public AppCacheStorage::Delegate {
38 public:
39 explicit MockStorageDelegate(AppCacheResponseTest* test)
40 : loaded_info_id_(0), test_(test) {
41 }
42
dchengc2282aa2014-10-21 12:07:5843 void OnResponseInfoLoaded(AppCacheResponseInfo* info,
44 int64 response_id) override {
[email protected]073aabe2009-10-21 18:09:3345 loaded_info_ = info;
46 loaded_info_id_ = response_id;
47 test_->ScheduleNextTask();
48 }
49
50 scoped_refptr<AppCacheResponseInfo> loaded_info_;
51 int64 loaded_info_id_;
52 AppCacheResponseTest* test_;
53 };
54
[email protected]72a3ce52011-12-22 05:10:2455 // Helper callback to run a test on our io_thread. The io_thread is spun up
56 // once and reused for all tests.
[email protected]073aabe2009-10-21 18:09:3357 template <class Method>
[email protected]72a3ce52011-12-22 05:10:2458 void MethodWrapper(Method method) {
59 SetUpTest();
60 (this->*method)();
61 }
[email protected]073aabe2009-10-21 18:09:3362
63 static void SetUpTestCase() {
64 io_thread_.reset(new base::Thread("AppCacheResponseTest Thread"));
[email protected]4cc586b2013-05-07 12:43:3265 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
[email protected]073aabe2009-10-21 18:09:3366 io_thread_->StartWithOptions(options);
67 }
68
69 static void TearDownTestCase() {
70 io_thread_.reset(NULL);
71 }
72
[email protected]50304162011-12-21 17:51:3073 AppCacheResponseTest() {}
[email protected]073aabe2009-10-21 18:09:3374
75 template <class Method>
76 void RunTestOnIOThread(Method method) {
77 test_finished_event_ .reset(new base::WaitableEvent(false, false));
78 io_thread_->message_loop()->PostTask(
[email protected]72a3ce52011-12-22 05:10:2479 FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
80 base::Unretained(this), method));
[email protected]073aabe2009-10-21 18:09:3381 test_finished_event_->Wait();
82 }
83
84 void SetUpTest() {
[email protected]4cc586b2013-05-07 12:43:3285 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]073aabe2009-10-21 18:09:3386 DCHECK(task_stack_.empty());
87 storage_delegate_.reset(new MockStorageDelegate(this));
88 service_.reset(new MockAppCacheService());
89 expected_read_result_ = 0;
90 expected_write_result_ = 0;
91 written_response_id_ = 0;
92 should_delete_reader_in_completion_callback_ = false;
93 should_delete_writer_in_completion_callback_ = false;
94 reader_deletion_count_down_ = 0;
95 writer_deletion_count_down_ = 0;
96 read_callback_was_called_ = false;
97 write_callback_was_called_ = false;
98 }
99
100 void TearDownTest() {
[email protected]4cc586b2013-05-07 12:43:32101 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]8336aaf42011-11-11 21:05:49102 while (!task_stack_.empty())
[email protected]073aabe2009-10-21 18:09:33103 task_stack_.pop();
[email protected]8336aaf42011-11-11 21:05:49104
[email protected]073aabe2009-10-21 18:09:33105 reader_.reset();
106 read_buffer_ = NULL;
107 read_info_buffer_ = NULL;
108 writer_.reset();
109 write_buffer_ = NULL;
110 write_info_buffer_ = NULL;
111 storage_delegate_.reset();
112 service_.reset();
113 }
114
115 void TestFinished() {
116 // We unwind the stack prior to finishing up to let stack
117 // based objects get deleted.
[email protected]4cc586b2013-05-07 12:43:32118 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
119 base::MessageLoop::current()->PostTask(
[email protected]8336aaf42011-11-11 21:05:49120 FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound,
121 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33122 }
123
124 void TestFinishedUnwound() {
125 TearDownTest();
126 test_finished_event_->Signal();
127 }
128
[email protected]8336aaf42011-11-11 21:05:49129 void PushNextTask(const base::Closure& task) {
130 task_stack_.push(std::pair<base::Closure, bool>(task, false));
[email protected]073aabe2009-10-21 18:09:33131 }
132
[email protected]8336aaf42011-11-11 21:05:49133 void PushNextTaskAsImmediate(const base::Closure& task) {
134 task_stack_.push(std::pair<base::Closure, bool>(task, true));
[email protected]073aabe2009-10-21 18:09:33135 }
136
137 void ScheduleNextTask() {
[email protected]4cc586b2013-05-07 12:43:32138 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
[email protected]073aabe2009-10-21 18:09:33139 if (task_stack_.empty()) {
140 TestFinished();
141 return;
142 }
[email protected]8336aaf42011-11-11 21:05:49143 base::Closure task = task_stack_.top().first;
[email protected]073aabe2009-10-21 18:09:33144 bool immediate = task_stack_.top().second;
145 task_stack_.pop();
146 if (immediate)
[email protected]8336aaf42011-11-11 21:05:49147 task.Run();
[email protected]073aabe2009-10-21 18:09:33148 else
[email protected]4cc586b2013-05-07 12:43:32149 base::MessageLoop::current()->PostTask(FROM_HERE, task);
[email protected]073aabe2009-10-21 18:09:33150 }
151
152 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
153
154 void WriteBasicResponse() {
[email protected]3367fc1d2009-11-09 00:09:21155 static const char kHttpHeaders[] =
156 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
[email protected]e2a8b0e2014-08-21 08:49:53157 static const char kHttpBody[] = "Hello";
[email protected]ad8e04a2010-11-01 04:16:27158 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
[email protected]3367fc1d2009-11-09 00:09:21159 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
[email protected]ff875be52013-06-02 23:47:38160 WriteResponse(
161 MakeHttpResponseInfo(raw_headers), body.get(), 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]ff875be52013-06-02 23:47:38179 writer_->WriteInfo(write_info_buffer_.get(),
180 base::Bind(&AppCacheResponseTest::OnWriteInfoComplete,
181 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33182 }
183
184 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
185 EXPECT_FALSE(writer_->IsWritePending());
186 write_buffer_ = io_buffer;
187 expected_write_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38188 writer_->WriteData(write_buffer_.get(),
189 buf_len,
190 base::Bind(&AppCacheResponseTest::OnWriteComplete,
191 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33192 }
193
194 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
195 EXPECT_FALSE(reader_->IsReadPending());
196 read_buffer_ = io_buffer;
197 expected_read_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38198 reader_->ReadData(read_buffer_.get(),
199 buf_len,
200 base::Bind(&AppCacheResponseTest::OnReadComplete,
201 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33202 }
203
204 // AppCacheResponseReader / Writer completion callbacks
205
206 void OnWriteInfoComplete(int result) {
207 EXPECT_FALSE(writer_->IsWritePending());
208 EXPECT_EQ(expected_write_result_, result);
209 ScheduleNextTask();
210 }
211
212 void OnWriteComplete(int result) {
213 EXPECT_FALSE(writer_->IsWritePending());
214 write_callback_was_called_ = true;
215 EXPECT_EQ(expected_write_result_, result);
216 if (should_delete_writer_in_completion_callback_ &&
217 --writer_deletion_count_down_ == 0) {
218 writer_.reset();
219 }
220 ScheduleNextTask();
221 }
222
223 void OnReadInfoComplete(int result) {
224 EXPECT_FALSE(reader_->IsReadPending());
225 EXPECT_EQ(expected_read_result_, result);
226 ScheduleNextTask();
227 }
228
229 void OnReadComplete(int result) {
230 EXPECT_FALSE(reader_->IsReadPending());
231 read_callback_was_called_ = true;
232 EXPECT_EQ(expected_read_result_, result);
233 if (should_delete_reader_in_completion_callback_ &&
234 --reader_deletion_count_down_ == 0) {
235 reader_.reset();
236 }
237 ScheduleNextTask();
238 }
239
240 // Helpers to work with HttpResponseInfo objects
241
[email protected]3367fc1d2009-11-09 00:09:21242 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
[email protected]073aabe2009-10-21 18:09:33243 net::HttpResponseInfo* info = new net::HttpResponseInfo;
244 info->request_time = base::Time::Now();
245 info->response_time = base::Time::Now();
246 info->was_cached = false;
247 info->headers = new net::HttpResponseHeaders(raw_headers);
248 return info;
249 }
250
251 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
252 Pickle pickle;
253 return PickleHttpResonseInfo(&pickle, info);
254 }
255
256 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
257 const net::HttpResponseInfo* info2) {
258 Pickle pickle1;
259 Pickle pickle2;
260 PickleHttpResonseInfo(&pickle1, info1);
261 PickleHttpResonseInfo(&pickle2, info2);
262 return (pickle1.size() == pickle2.size()) &&
263 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
264 }
265
266 int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) {
267 const bool kSkipTransientHeaders = true;
268 const bool kTruncated = false;
269 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
270 return pickle->size();
271 }
272
273 // Helpers to fill and verify blocks of memory with a value
274
275 void FillData(char value, char* data, int data_len) {
276 memset(data, value, data_len);
277 }
278
279 bool CheckData(char value, const char* data, int data_len) {
280 for (int i = 0; i < data_len; ++i, ++data) {
281 if (*data != value)
282 return false;
283 }
284 return true;
285 }
286
287 // Individual Tests ---------------------------------------------------------
288 // Most of the individual tests involve multiple async steps. Each test
289 // is delineated with a section header.
290
[email protected]073aabe2009-10-21 18:09:33291
292 // ReadNonExistentResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33293 void ReadNonExistentResponse() {
294 // 1. Attempt to ReadInfo
295 // 2. Attempt to ReadData
296
297 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36298 GURL(), 0, kNoSuchResponseId));
[email protected]073aabe2009-10-21 18:09:33299
300 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49301 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
302 base::Unretained(this)));
303 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
304 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33305 ScheduleNextTask();
306 }
307
308 void ReadNonExistentInfo() {
309 EXPECT_FALSE(reader_->IsReadPending());
310 read_info_buffer_ = new HttpResponseInfoIOBuffer();
[email protected]ff875be52013-06-02 23:47:38311 reader_->ReadInfo(read_info_buffer_.get(),
312 base::Bind(&AppCacheResponseTest::OnReadInfoComplete,
313 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33314 EXPECT_TRUE(reader_->IsReadPending());
315 expected_read_result_ = net::ERR_CACHE_MISS;
316 }
317
318 void ReadNonExistentData() {
319 EXPECT_FALSE(reader_->IsReadPending());
320 read_buffer_ = new IOBuffer(kBlockSize);
[email protected]ff875be52013-06-02 23:47:38321 reader_->ReadData(read_buffer_.get(),
322 kBlockSize,
323 base::Bind(&AppCacheResponseTest::OnReadComplete,
324 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33325 EXPECT_TRUE(reader_->IsReadPending());
326 expected_read_result_ = net::ERR_CACHE_MISS;
327 }
328
329 // LoadResponseInfo_Miss ----------------------------------------------------
330 void LoadResponseInfo_Miss() {
[email protected]8336aaf42011-11-11 21:05:49331 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
332 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36333 service_->storage()->LoadResponseInfo(GURL(), 0, kNoSuchResponseId,
[email protected]073aabe2009-10-21 18:09:33334 storage_delegate_.get());
335 }
336
337 void LoadResponseInfo_Miss_Verify() {
[email protected]dda06f82009-10-21 18:38:51338 EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_);
[email protected]073aabe2009-10-21 18:09:33339 EXPECT_TRUE(!storage_delegate_->loaded_info_.get());
340 TestFinished();
341 }
342
343 // LoadResponseInfo_Hit ----------------------------------------------------
344 void LoadResponseInfo_Hit() {
345 // This tests involves multiple async steps.
346 // 1. Write a response headers and body to storage
347 // a. headers
348 // b. body
349 // 2. Use LoadResponseInfo to read the response headers back out
[email protected]8336aaf42011-11-11 21:05:49350 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
351 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36352 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33353 written_response_id_ = writer_->response_id();
354 WriteBasicResponse();
355 }
356
357 void LoadResponseInfo_Hit_Step2() {
358 writer_.reset();
[email protected]8336aaf42011-11-11 21:05:49359 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
360 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36361 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
[email protected]073aabe2009-10-21 18:09:33362 storage_delegate_.get());
363 }
364
365 void LoadResponseInfo_Hit_Verify() {
366 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
367 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
368 EXPECT_TRUE(CompareHttpResponseInfos(
369 write_info_buffer_->http_info.get(),
370 storage_delegate_->loaded_info_->http_response_info()));
[email protected]fd2885a2010-03-17 22:02:28371 EXPECT_EQ(basic_response_size(),
372 storage_delegate_->loaded_info_->response_data_size());
[email protected]073aabe2009-10-21 18:09:33373 TestFinished();
374 }
375
[email protected]0dfeec32010-01-06 22:25:33376 // AmountWritten ----------------------------------------------------
377
378 void AmountWritten() {
[email protected]e2a8b0e2014-08-21 08:49:53379 static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
[email protected]0dfeec32010-01-06 22:25:33380 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
381 net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
382 int expected_amount_written =
383 GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
384
385 // Push tasks in reverse order.
[email protected]8336aaf42011-11-11 21:05:49386 PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
387 base::Unretained(this), expected_amount_written));
[email protected]0dfeec32010-01-06 22:25:33388 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49389 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
390 base::Unretained(this), kNumBlocks - i));
[email protected]0dfeec32010-01-06 22:25:33391 }
[email protected]8336aaf42011-11-11 21:05:49392 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
393 base::Unretained(this), head));
[email protected]0dfeec32010-01-06 22:25:33394
[email protected]4252f602011-10-21 19:18:36395 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]0dfeec32010-01-06 22:25:33396 written_response_id_ = writer_->response_id();
397 ScheduleNextTask();
398 }
399
400 void Verify_AmountWritten(int expected_amount_written) {
401 EXPECT_EQ(expected_amount_written, writer_->amount_written());
402 TestFinished();
403 }
404
405
[email protected]073aabe2009-10-21 18:09:33406 // WriteThenVariouslyReadResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33407
408 void WriteThenVariouslyReadResponse() {
409 // This tests involves multiple async steps.
410 // 1. First, write a large body using multiple writes, we don't bother
411 // with a response head for this test.
412 // 2. Read the entire body, using multiple reads
413 // 3. Read the entire body, using one read.
414 // 4. Attempt to read beyond the EOF.
415 // 5. Read just a range.
416 // 6. Attempt to read beyond EOF of a range.
417
418 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49419 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
420 base::Unretained(this)));
421 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
422 base::Unretained(this)));
423 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
424 base::Unretained(this)));
425 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
426 base::Unretained(this)));
427 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
428 base::Unretained(this)));
429 PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
430 base::Unretained(this)));
431 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
432 base::Unretained(this)));
433 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
434 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33435
436 // Get them going.
437 ScheduleNextTask();
438 }
439
440 void WriteOutBlocks() {
[email protected]4252f602011-10-21 19:18:36441 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33442 written_response_id_ = writer_->response_id();
443 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49444 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
445 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33446 }
447 ScheduleNextTask();
448 }
449
450 void WriteOneBlock(int block_number) {
[email protected]ad8e04a2010-11-01 04:16:27451 scoped_refptr<IOBuffer> io_buffer(
452 new IOBuffer(kBlockSize));
[email protected]073aabe2009-10-21 18:09:33453 FillData(block_number, io_buffer->data(), kBlockSize);
454 WriteResponseBody(io_buffer, kBlockSize);
455 }
456
457 void ReadInBlocks() {
458 writer_.reset();
459 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36460 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33461 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49462 PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
463 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33464 }
465 ScheduleNextTask();
466 }
467
468 void ReadOneBlock(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49469 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
470 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33471 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
472 }
473
474 void VerifyOneBlock(int block_number) {
475 EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
476 ScheduleNextTask();
477 }
478
479 void ReadAllAtOnce() {
[email protected]8336aaf42011-11-11 21:05:49480 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
481 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33482 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36483 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33484 int big_size = kNumBlocks * kBlockSize;
485 ReadResponseBody(new IOBuffer(big_size), big_size);
486 }
487
488 void VerifyAllAtOnce() {
489 char* p = read_buffer_->data();
490 for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
491 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
492 ScheduleNextTask();
493 }
494
495 void ReadPastEOF() {
496 EXPECT_FALSE(reader_->IsReadPending());
497 read_buffer_ = new IOBuffer(kBlockSize);
498 expected_read_result_ = 0;
[email protected]ff875be52013-06-02 23:47:38499 reader_->ReadData(read_buffer_.get(),
500 kBlockSize,
501 base::Bind(&AppCacheResponseTest::OnReadComplete,
502 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33503 }
504
505 void ReadRange() {
[email protected]8336aaf42011-11-11 21:05:49506 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
507 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33508 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36509 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33510 reader_->SetReadRange(kBlockSize, kBlockSize);
511 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
512 }
513
514 void VerifyRange() {
515 EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
516 ScheduleNextTask(); // ReadPastEOF is scheduled next
517 }
518
519 void ReadRangePartiallyBeyondEOF() {
[email protected]8336aaf42011-11-11 21:05:49520 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
521 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33522 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36523 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33524 reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
525 ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
526 kNumBlocks * kBlockSize);
527 expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
528 }
529
530 void VerifyRangeBeyondEOF() {
531 // Just verify the first 1k
532 VerifyRange();
533 }
534
535 void ReadRangeFullyBeyondEOF() {
536 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36537 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33538 reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
539 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
540 expected_read_result_ = 0;
541 }
542
543 // IOChaining -------------------------------------------
544 void IOChaining() {
545 // 1. Write several blocks out initiating the subsequent write
546 // from within the completion callback of the previous write.
547 // 2. Read and verify several blocks in similarly chaining reads.
548
549 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49550 PushNextTaskAsImmediate(
551 base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately,
552 base::Unretained(this)));
553 PushNextTaskAsImmediate(
554 base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately,
555 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33556
557 // Get them going.
558 ScheduleNextTask();
559 }
560
561 void WriteOutBlocksImmediately() {
[email protected]4252f602011-10-21 19:18:36562 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33563 written_response_id_ = writer_->response_id();
564 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49565 PushNextTaskAsImmediate(
566 base::Bind(&AppCacheResponseTest::WriteOneBlock,
567 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33568 }
569 ScheduleNextTask();
570 }
571
572 void ReadInBlocksImmediately() {
573 writer_.reset();
574 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36575 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33576 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49577 PushNextTaskAsImmediate(
578 base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately,
579 base::Unretained(this),
[email protected]79b15b22010-05-19 00:38:56580 kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33581 }
582 ScheduleNextTask();
583 }
584
585 void ReadOneBlockImmediately(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49586 PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
587 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33588 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
589 }
590
591 // DeleteWithinCallbacks -------------------------------------------
592 void DeleteWithinCallbacks() {
593 // 1. Write out a few blocks normally, and upon
594 // completion of the last write, delete the writer.
595 // 2. Read in a few blocks normally, and upon completion
596 // of the last read, delete the reader.
597
598 should_delete_reader_in_completion_callback_ = true;
599 reader_deletion_count_down_ = kNumBlocks;
600 should_delete_writer_in_completion_callback_ = true;
601 writer_deletion_count_down_ = kNumBlocks;
602
[email protected]8336aaf42011-11-11 21:05:49603 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
604 base::Unretained(this)));
605 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
606 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33607 ScheduleNextTask();
608 }
609
610 // DeleteWithIOPending -------------------------------------------
611 void DeleteWithIOPending() {
612 // 1. Write a few blocks normally.
613 // 2. Start a write, delete with it pending.
614 // 3. Start a read, delete with it pending.
[email protected]8336aaf42011-11-11 21:05:49615 PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
616 base::Unretained(this)));
617 PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
618 base::Unretained(this)));
619 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
620 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33621 ScheduleNextTask();
622 }
623
624 void WriteThenDelete() {
625 write_callback_was_called_ = false;
626 WriteOneBlock(5);
627 EXPECT_TRUE(writer_->IsWritePending());
628 writer_.reset();
629 ScheduleNextTask();
630 }
631
632 void ReadThenDelete() {
633 read_callback_was_called_ = false;
634 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36635 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33636 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
637 EXPECT_TRUE(reader_->IsReadPending());
638 reader_.reset();
639
640 // Wait a moment to verify no callbacks.
[email protected]4cc586b2013-05-07 12:43:32641 base::MessageLoop::current()->PostDelayedTask(
[email protected]8336aaf42011-11-11 21:05:49642 FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
643 base::Unretained(this)),
[email protected]6f35f4e2012-03-03 21:02:28644 base::TimeDelta::FromMilliseconds(10));
[email protected]073aabe2009-10-21 18:09:33645 }
646
647 void VerifyNoCallbacks() {
648 EXPECT_TRUE(!write_callback_was_called_);
649 EXPECT_TRUE(!read_callback_was_called_);
650 TestFinished();
651 }
652
653 // Data members
654
[email protected]073aabe2009-10-21 18:09:33655 scoped_ptr<base::WaitableEvent> test_finished_event_;
656 scoped_ptr<MockStorageDelegate> storage_delegate_;
657 scoped_ptr<MockAppCacheService> service_;
[email protected]8336aaf42011-11-11 21:05:49658 std::stack<std::pair<base::Closure, bool> > task_stack_;
[email protected]073aabe2009-10-21 18:09:33659
660 scoped_ptr<AppCacheResponseReader> reader_;
661 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
662 scoped_refptr<IOBuffer> read_buffer_;
663 int expected_read_result_;
[email protected]073aabe2009-10-21 18:09:33664 bool should_delete_reader_in_completion_callback_;
665 int reader_deletion_count_down_;
666 bool read_callback_was_called_;
667
668 int64 written_response_id_;
669 scoped_ptr<AppCacheResponseWriter> writer_;
670 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
671 scoped_refptr<IOBuffer> write_buffer_;
672 int expected_write_result_;
[email protected]073aabe2009-10-21 18:09:33673 bool should_delete_writer_in_completion_callback_;
674 int writer_deletion_count_down_;
675 bool write_callback_was_called_;
676
677 static scoped_ptr<base::Thread> io_thread_;
678};
679
680// static
681scoped_ptr<base::Thread> AppCacheResponseTest::io_thread_;
682
[email protected]073aabe2009-10-21 18:09:33683TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
684 RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
685}
686
687TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
688 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
689}
690
691TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
692 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
693}
694
[email protected]0dfeec32010-01-06 22:25:33695TEST_F(AppCacheResponseTest, AmountWritten) {
696 RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
697}
698
[email protected]073aabe2009-10-21 18:09:33699TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
700 RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
701}
702
703TEST_F(AppCacheResponseTest, IOChaining) {
704 RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
705}
706
707TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
708 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
709}
710
711TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
712 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
713}
714
[email protected]a507b822014-04-12 05:10:24715} // namespace content