blob: 8e633c1f84ff092b402eac16b8d973f4193a119c [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
avib7348942015-12-25 20:57:105#include <stdint.h>
avi66a07722015-12-25 23:38:126#include <string.h>
avib7348942015-12-25 20:57:107
[email protected]b7243c42010-07-23 05:23:138#include <stack>
9#include <string>
10#include <utility>
11
[email protected]8336aaf42011-11-11 21:05:4912#include "base/bind.h"
13#include "base/bind_helpers.h"
14#include "base/callback.h"
[email protected]073aabe2009-10-21 18:09:3315#include "base/compiler_specific.h"
skyostil95082a62015-06-05 19:53:0716#include "base/location.h"
avib7348942015-12-25 20:57:1017#include "base/macros.h"
[email protected]073aabe2009-10-21 18:09:3318#include "base/pickle.h"
skyostil95082a62015-06-05 19:53:0719#include "base/single_thread_task_runner.h"
[email protected]44f9c952011-01-02 06:05:3920#include "base/synchronization/waitable_event.h"
[email protected]d5b2fdf2013-06-05 09:36:5521#include "base/threading/thread.h"
gab30f26df2016-05-11 19:37:5522#include "base/threading/thread_task_runner_handle.h"
[email protected]98d6d4562014-06-25 20:57:5523#include "content/browser/appcache/appcache_response.h"
[email protected]71fe3d12014-04-22 00:32:3824#include "content/browser/appcache/mock_appcache_service.h"
[email protected]073aabe2009-10-21 18:09:3325#include "net/base/io_buffer.h"
[email protected]80d42812010-02-09 10:30:2526#include "net/base/net_errors.h"
[email protected]277d5942010-08-11 21:02:3527#include "net/http/http_response_headers.h"
[email protected]073aabe2009-10-21 18:09:3328#include "testing/gtest/include/gtest/gtest.h"
[email protected]073aabe2009-10-21 18:09:3329
30using net::IOBuffer;
[email protected]3367fc1d2009-11-09 00:09:2131using net::WrappedIOBuffer;
[email protected]073aabe2009-10-21 18:09:3332
[email protected]a507b822014-04-12 05:10:2433namespace content {
[email protected]073aabe2009-10-21 18:09:3334
[email protected]dda06f82009-10-21 18:38:5135static const int kNumBlocks = 4;
36static const int kBlockSize = 1024;
37static const int kNoSuchResponseId = 123;
38
[email protected]073aabe2009-10-21 18:09:3339class AppCacheResponseTest : public testing::Test {
40 public:
[email protected]073aabe2009-10-21 18:09:3341 // Test Harness -------------------------------------------------------------
42
43 // Helper class used to verify test results
44 class MockStorageDelegate : public AppCacheStorage::Delegate {
45 public:
46 explicit MockStorageDelegate(AppCacheResponseTest* test)
47 : loaded_info_id_(0), test_(test) {
48 }
49
dchengc2282aa2014-10-21 12:07:5850 void OnResponseInfoLoaded(AppCacheResponseInfo* info,
avib7348942015-12-25 20:57:1051 int64_t response_id) override {
[email protected]073aabe2009-10-21 18:09:3352 loaded_info_ = info;
53 loaded_info_id_ = response_id;
54 test_->ScheduleNextTask();
55 }
56
57 scoped_refptr<AppCacheResponseInfo> loaded_info_;
avib7348942015-12-25 20:57:1058 int64_t loaded_info_id_;
[email protected]073aabe2009-10-21 18:09:3359 AppCacheResponseTest* test_;
60 };
61
[email protected]72a3ce52011-12-22 05:10:2462 // Helper callback to run a test on our io_thread. The io_thread is spun up
63 // once and reused for all tests.
[email protected]073aabe2009-10-21 18:09:3364 template <class Method>
[email protected]72a3ce52011-12-22 05:10:2465 void MethodWrapper(Method method) {
66 SetUpTest();
67 (this->*method)();
68 }
[email protected]073aabe2009-10-21 18:09:3369
70 static void SetUpTestCase() {
71 io_thread_.reset(new base::Thread("AppCacheResponseTest Thread"));
[email protected]4cc586b2013-05-07 12:43:3272 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
[email protected]073aabe2009-10-21 18:09:3373 io_thread_->StartWithOptions(options);
74 }
75
76 static void TearDownTestCase() {
77 io_thread_.reset(NULL);
78 }
79
[email protected]50304162011-12-21 17:51:3080 AppCacheResponseTest() {}
[email protected]073aabe2009-10-21 18:09:3381
82 template <class Method>
83 void RunTestOnIOThread(Method method) {
gabd6f9bff2016-06-02 13:48:2084 test_finished_event_.reset(new base::WaitableEvent(
85 base::WaitableEvent::ResetPolicy::AUTOMATIC,
86 base::WaitableEvent::InitialState::NOT_SIGNALED));
skyostil95082a62015-06-05 19:53:0787 io_thread_->task_runner()->PostTask(
[email protected]72a3ce52011-12-22 05:10:2488 FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
89 base::Unretained(this), method));
[email protected]073aabe2009-10-21 18:09:3390 test_finished_event_->Wait();
91 }
92
93 void SetUpTest() {
fdoraye94d8642016-07-07 19:19:0194 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
[email protected]073aabe2009-10-21 18:09:3395 DCHECK(task_stack_.empty());
96 storage_delegate_.reset(new MockStorageDelegate(this));
97 service_.reset(new MockAppCacheService());
98 expected_read_result_ = 0;
99 expected_write_result_ = 0;
100 written_response_id_ = 0;
101 should_delete_reader_in_completion_callback_ = false;
102 should_delete_writer_in_completion_callback_ = false;
103 reader_deletion_count_down_ = 0;
104 writer_deletion_count_down_ = 0;
105 read_callback_was_called_ = false;
106 write_callback_was_called_ = false;
107 }
108
109 void TearDownTest() {
fdoraye94d8642016-07-07 19:19:01110 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
[email protected]8336aaf42011-11-11 21:05:49111 while (!task_stack_.empty())
[email protected]073aabe2009-10-21 18:09:33112 task_stack_.pop();
[email protected]8336aaf42011-11-11 21:05:49113
[email protected]073aabe2009-10-21 18:09:33114 reader_.reset();
115 read_buffer_ = NULL;
116 read_info_buffer_ = NULL;
117 writer_.reset();
118 write_buffer_ = NULL;
119 write_info_buffer_ = NULL;
120 storage_delegate_.reset();
121 service_.reset();
122 }
123
124 void TestFinished() {
125 // We unwind the stack prior to finishing up to let stack
126 // based objects get deleted.
fdoraye94d8642016-07-07 19:19:01127 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
skyostil95082a62015-06-05 19:53:07128 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]8336aaf42011-11-11 21:05:49129 FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound,
130 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33131 }
132
133 void TestFinishedUnwound() {
134 TearDownTest();
135 test_finished_event_->Signal();
136 }
137
[email protected]8336aaf42011-11-11 21:05:49138 void PushNextTask(const base::Closure& task) {
139 task_stack_.push(std::pair<base::Closure, bool>(task, false));
[email protected]073aabe2009-10-21 18:09:33140 }
141
[email protected]8336aaf42011-11-11 21:05:49142 void PushNextTaskAsImmediate(const base::Closure& task) {
143 task_stack_.push(std::pair<base::Closure, bool>(task, true));
[email protected]073aabe2009-10-21 18:09:33144 }
145
146 void ScheduleNextTask() {
fdoraye94d8642016-07-07 19:19:01147 DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
[email protected]073aabe2009-10-21 18:09:33148 if (task_stack_.empty()) {
149 TestFinished();
150 return;
151 }
[email protected]8336aaf42011-11-11 21:05:49152 base::Closure task = task_stack_.top().first;
[email protected]073aabe2009-10-21 18:09:33153 bool immediate = task_stack_.top().second;
154 task_stack_.pop();
155 if (immediate)
[email protected]8336aaf42011-11-11 21:05:49156 task.Run();
[email protected]073aabe2009-10-21 18:09:33157 else
skyostil95082a62015-06-05 19:53:07158 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
[email protected]073aabe2009-10-21 18:09:33159 }
160
161 // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
162
163 void WriteBasicResponse() {
[email protected]3367fc1d2009-11-09 00:09:21164 static const char kHttpHeaders[] =
165 "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
[email protected]e2a8b0e2014-08-21 08:49:53166 static const char kHttpBody[] = "Hello";
[email protected]ad8e04a2010-11-01 04:16:27167 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
[email protected]3367fc1d2009-11-09 00:09:21168 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
[email protected]ff875be52013-06-02 23:47:38169 WriteResponse(
170 MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBody));
[email protected]073aabe2009-10-21 18:09:33171 }
172
[email protected]fd2885a2010-03-17 22:02:28173 int basic_response_size() { return 5; } // should match kHttpBody above
174
[email protected]3367fc1d2009-11-09 00:09:21175 void WriteResponse(net::HttpResponseInfo* head,
176 IOBuffer* body, int body_len) {
177 DCHECK(body);
178 scoped_refptr<IOBuffer> body_ref(body);
[email protected]8336aaf42011-11-11 21:05:49179 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseBody,
180 base::Unretained(this), body_ref, body_len));
[email protected]073aabe2009-10-21 18:09:33181 WriteResponseHead(head);
182 }
183
184 void WriteResponseHead(net::HttpResponseInfo* head) {
185 EXPECT_FALSE(writer_->IsWritePending());
186 expected_write_result_ = GetHttpResponseInfoSize(head);
187 write_info_buffer_ = new HttpResponseInfoIOBuffer(head);
[email protected]ff875be52013-06-02 23:47:38188 writer_->WriteInfo(write_info_buffer_.get(),
189 base::Bind(&AppCacheResponseTest::OnWriteInfoComplete,
190 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33191 }
192
193 void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
194 EXPECT_FALSE(writer_->IsWritePending());
195 write_buffer_ = io_buffer;
196 expected_write_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38197 writer_->WriteData(write_buffer_.get(),
198 buf_len,
199 base::Bind(&AppCacheResponseTest::OnWriteComplete,
200 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33201 }
202
horoa9500072015-02-18 05:08:15203 void WriteResponseMetadata(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
204 EXPECT_FALSE(metadata_writer_->IsWritePending());
205 write_buffer_ = io_buffer;
206 expected_write_result_ = buf_len;
207 metadata_writer_->WriteMetadata(
208 write_buffer_.get(), buf_len,
209 base::Bind(&AppCacheResponseTest::OnMetadataWriteComplete,
210 base::Unretained(this)));
211 }
212
[email protected]073aabe2009-10-21 18:09:33213 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
214 EXPECT_FALSE(reader_->IsReadPending());
215 read_buffer_ = io_buffer;
216 expected_read_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38217 reader_->ReadData(read_buffer_.get(),
218 buf_len,
219 base::Bind(&AppCacheResponseTest::OnReadComplete,
220 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33221 }
222
223 // AppCacheResponseReader / Writer completion callbacks
224
225 void OnWriteInfoComplete(int result) {
226 EXPECT_FALSE(writer_->IsWritePending());
227 EXPECT_EQ(expected_write_result_, result);
228 ScheduleNextTask();
229 }
230
231 void OnWriteComplete(int result) {
232 EXPECT_FALSE(writer_->IsWritePending());
233 write_callback_was_called_ = true;
234 EXPECT_EQ(expected_write_result_, result);
235 if (should_delete_writer_in_completion_callback_ &&
236 --writer_deletion_count_down_ == 0) {
237 writer_.reset();
238 }
239 ScheduleNextTask();
240 }
241
horoa9500072015-02-18 05:08:15242 void OnMetadataWriteComplete(int result) {
243 EXPECT_FALSE(metadata_writer_->IsWritePending());
244 EXPECT_EQ(expected_write_result_, result);
245 ScheduleNextTask();
246 }
247
[email protected]073aabe2009-10-21 18:09:33248 void OnReadInfoComplete(int result) {
249 EXPECT_FALSE(reader_->IsReadPending());
250 EXPECT_EQ(expected_read_result_, result);
251 ScheduleNextTask();
252 }
253
254 void OnReadComplete(int result) {
255 EXPECT_FALSE(reader_->IsReadPending());
256 read_callback_was_called_ = true;
257 EXPECT_EQ(expected_read_result_, result);
258 if (should_delete_reader_in_completion_callback_ &&
259 --reader_deletion_count_down_ == 0) {
260 reader_.reset();
261 }
262 ScheduleNextTask();
263 }
264
265 // Helpers to work with HttpResponseInfo objects
266
[email protected]3367fc1d2009-11-09 00:09:21267 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
[email protected]073aabe2009-10-21 18:09:33268 net::HttpResponseInfo* info = new net::HttpResponseInfo;
269 info->request_time = base::Time::Now();
270 info->response_time = base::Time::Now();
271 info->was_cached = false;
272 info->headers = new net::HttpResponseHeaders(raw_headers);
273 return info;
274 }
275
276 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
brettwbd4d7112015-06-03 04:29:25277 base::Pickle pickle;
[email protected]073aabe2009-10-21 18:09:33278 return PickleHttpResonseInfo(&pickle, info);
279 }
280
281 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
282 const net::HttpResponseInfo* info2) {
brettwbd4d7112015-06-03 04:29:25283 base::Pickle pickle1;
284 base::Pickle pickle2;
[email protected]073aabe2009-10-21 18:09:33285 PickleHttpResonseInfo(&pickle1, info1);
286 PickleHttpResonseInfo(&pickle2, info2);
287 return (pickle1.size() == pickle2.size()) &&
288 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
289 }
290
brettwbd4d7112015-06-03 04:29:25291 int PickleHttpResonseInfo(base::Pickle* pickle,
292 const net::HttpResponseInfo* info) {
[email protected]073aabe2009-10-21 18:09:33293 const bool kSkipTransientHeaders = true;
294 const bool kTruncated = false;
295 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
296 return pickle->size();
297 }
298
299 // Helpers to fill and verify blocks of memory with a value
300
301 void FillData(char value, char* data, int data_len) {
302 memset(data, value, data_len);
303 }
304
305 bool CheckData(char value, const char* data, int data_len) {
306 for (int i = 0; i < data_len; ++i, ++data) {
307 if (*data != value)
308 return false;
309 }
310 return true;
311 }
312
313 // Individual Tests ---------------------------------------------------------
314 // Most of the individual tests involve multiple async steps. Each test
315 // is delineated with a section header.
316
[email protected]073aabe2009-10-21 18:09:33317
318 // ReadNonExistentResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33319 void ReadNonExistentResponse() {
320 // 1. Attempt to ReadInfo
321 // 2. Attempt to ReadData
322
lukasza9cb60b72016-04-19 22:59:48323 reader_.reset(
324 service_->storage()->CreateResponseReader(GURL(), kNoSuchResponseId));
[email protected]073aabe2009-10-21 18:09:33325
326 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49327 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
328 base::Unretained(this)));
329 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
330 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33331 ScheduleNextTask();
332 }
333
334 void ReadNonExistentInfo() {
335 EXPECT_FALSE(reader_->IsReadPending());
336 read_info_buffer_ = new HttpResponseInfoIOBuffer();
[email protected]ff875be52013-06-02 23:47:38337 reader_->ReadInfo(read_info_buffer_.get(),
338 base::Bind(&AppCacheResponseTest::OnReadInfoComplete,
339 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33340 EXPECT_TRUE(reader_->IsReadPending());
341 expected_read_result_ = net::ERR_CACHE_MISS;
342 }
343
344 void ReadNonExistentData() {
345 EXPECT_FALSE(reader_->IsReadPending());
346 read_buffer_ = new IOBuffer(kBlockSize);
[email protected]ff875be52013-06-02 23:47:38347 reader_->ReadData(read_buffer_.get(),
348 kBlockSize,
349 base::Bind(&AppCacheResponseTest::OnReadComplete,
350 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33351 EXPECT_TRUE(reader_->IsReadPending());
352 expected_read_result_ = net::ERR_CACHE_MISS;
353 }
354
355 // LoadResponseInfo_Miss ----------------------------------------------------
356 void LoadResponseInfo_Miss() {
[email protected]8336aaf42011-11-11 21:05:49357 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
358 base::Unretained(this)));
lukasza9cb60b72016-04-19 22:59:48359 service_->storage()->LoadResponseInfo(GURL(), kNoSuchResponseId,
[email protected]073aabe2009-10-21 18:09:33360 storage_delegate_.get());
361 }
362
363 void LoadResponseInfo_Miss_Verify() {
[email protected]dda06f82009-10-21 18:38:51364 EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_);
[email protected]073aabe2009-10-21 18:09:33365 EXPECT_TRUE(!storage_delegate_->loaded_info_.get());
366 TestFinished();
367 }
368
369 // LoadResponseInfo_Hit ----------------------------------------------------
370 void LoadResponseInfo_Hit() {
371 // This tests involves multiple async steps.
372 // 1. Write a response headers and body to storage
373 // a. headers
374 // b. body
375 // 2. Use LoadResponseInfo to read the response headers back out
[email protected]8336aaf42011-11-11 21:05:49376 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
377 base::Unretained(this)));
lukasza9cb60b72016-04-19 22:59:48378 writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
[email protected]073aabe2009-10-21 18:09:33379 written_response_id_ = writer_->response_id();
380 WriteBasicResponse();
381 }
382
383 void LoadResponseInfo_Hit_Step2() {
384 writer_.reset();
[email protected]8336aaf42011-11-11 21:05:49385 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
386 base::Unretained(this)));
lukasza9cb60b72016-04-19 22:59:48387 service_->storage()->LoadResponseInfo(GURL(), written_response_id_,
[email protected]073aabe2009-10-21 18:09:33388 storage_delegate_.get());
389 }
390
391 void LoadResponseInfo_Hit_Verify() {
392 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
393 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
394 EXPECT_TRUE(CompareHttpResponseInfos(
395 write_info_buffer_->http_info.get(),
396 storage_delegate_->loaded_info_->http_response_info()));
[email protected]fd2885a2010-03-17 22:02:28397 EXPECT_EQ(basic_response_size(),
398 storage_delegate_->loaded_info_->response_data_size());
[email protected]073aabe2009-10-21 18:09:33399 TestFinished();
400 }
401
horoa9500072015-02-18 05:08:15402 // Metadata -------------------------------------------------
403 void Metadata() {
404 // This tests involves multiple async steps.
405 // 1. Write a response headers and body to storage
406 // a. headers
407 // b. body
408 // 2. Write metadata "Metadata First" using AppCacheResponseMetadataWriter.
409 // 3. Check metadata was written.
410 // 4. Write metadata "Second".
411 // 5. Check metadata was written and was truncated .
412 // 6. Write metadata "".
413 // 7. Check metadata was deleted.
414
415 // Push tasks in reverse order.
416 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
417 base::Unretained(this), ""));
418 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
419 base::Unretained(this)));
420 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
421 base::Unretained(this), ""));
422 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
423 base::Unretained(this), "Second"));
424 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
425 base::Unretained(this)));
426 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
427 base::Unretained(this), "Second"));
428 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
429 base::Unretained(this), "Metadata First"));
430 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
431 base::Unretained(this)));
432 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
433 base::Unretained(this), "Metadata First"));
434 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_ResetWriter,
435 base::Unretained(this)));
lukasza9cb60b72016-04-19 22:59:48436 writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
horoa9500072015-02-18 05:08:15437 written_response_id_ = writer_->response_id();
438 WriteBasicResponse();
439 }
440
441 void Metadata_ResetWriter() {
442 writer_.reset();
443 ScheduleNextTask();
444 }
445
446 void Metadata_WriteMetadata(const char* metadata) {
447 metadata_writer_.reset(service_->storage()->CreateResponseMetadataWriter(
lukasza9cb60b72016-04-19 22:59:48448 written_response_id_));
horoa9500072015-02-18 05:08:15449 scoped_refptr<IOBuffer> buffer(new WrappedIOBuffer(metadata));
450 WriteResponseMetadata(buffer.get(), strlen(metadata));
451 }
452
453 void Metadata_LoadResponseInfo() {
454 metadata_writer_.reset();
455 storage_delegate_.reset(new MockStorageDelegate(this));
lukasza9cb60b72016-04-19 22:59:48456 service_->storage()->LoadResponseInfo(GURL(), written_response_id_,
horoa9500072015-02-18 05:08:15457 storage_delegate_.get());
458 }
459
460 void Metadata_VerifyMetadata(const char* metadata) {
461 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
462 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
463 const net::HttpResponseInfo* read_head =
464 storage_delegate_->loaded_info_->http_response_info();
465 EXPECT_TRUE(read_head);
466 const int metadata_size = strlen(metadata);
467 if (metadata_size) {
468 EXPECT_TRUE(read_head->metadata.get());
469 EXPECT_EQ(metadata_size, read_head->metadata->size());
470 EXPECT_EQ(0,
471 memcmp(metadata, read_head->metadata->data(), metadata_size));
472 } else {
473 EXPECT_FALSE(read_head->metadata.get());
474 }
475 EXPECT_TRUE(CompareHttpResponseInfos(
476 write_info_buffer_->http_info.get(),
477 storage_delegate_->loaded_info_->http_response_info()));
478 EXPECT_EQ(basic_response_size(),
479 storage_delegate_->loaded_info_->response_data_size());
480 ScheduleNextTask();
481 }
482
[email protected]0dfeec32010-01-06 22:25:33483 // AmountWritten ----------------------------------------------------
484
485 void AmountWritten() {
[email protected]e2a8b0e2014-08-21 08:49:53486 static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
[email protected]0dfeec32010-01-06 22:25:33487 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
488 net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
489 int expected_amount_written =
490 GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
491
492 // Push tasks in reverse order.
[email protected]8336aaf42011-11-11 21:05:49493 PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
494 base::Unretained(this), expected_amount_written));
[email protected]0dfeec32010-01-06 22:25:33495 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49496 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
497 base::Unretained(this), kNumBlocks - i));
[email protected]0dfeec32010-01-06 22:25:33498 }
[email protected]8336aaf42011-11-11 21:05:49499 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
500 base::Unretained(this), head));
[email protected]0dfeec32010-01-06 22:25:33501
lukasza9cb60b72016-04-19 22:59:48502 writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
[email protected]0dfeec32010-01-06 22:25:33503 written_response_id_ = writer_->response_id();
504 ScheduleNextTask();
505 }
506
507 void Verify_AmountWritten(int expected_amount_written) {
508 EXPECT_EQ(expected_amount_written, writer_->amount_written());
509 TestFinished();
510 }
511
512
[email protected]073aabe2009-10-21 18:09:33513 // WriteThenVariouslyReadResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33514
515 void WriteThenVariouslyReadResponse() {
516 // This tests involves multiple async steps.
517 // 1. First, write a large body using multiple writes, we don't bother
518 // with a response head for this test.
519 // 2. Read the entire body, using multiple reads
520 // 3. Read the entire body, using one read.
521 // 4. Attempt to read beyond the EOF.
522 // 5. Read just a range.
523 // 6. Attempt to read beyond EOF of a range.
524
525 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49526 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
527 base::Unretained(this)));
528 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
529 base::Unretained(this)));
530 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
531 base::Unretained(this)));
532 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
533 base::Unretained(this)));
534 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
535 base::Unretained(this)));
536 PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
537 base::Unretained(this)));
538 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
539 base::Unretained(this)));
540 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
541 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33542
543 // Get them going.
544 ScheduleNextTask();
545 }
546
547 void WriteOutBlocks() {
lukasza9cb60b72016-04-19 22:59:48548 writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
[email protected]073aabe2009-10-21 18:09:33549 written_response_id_ = writer_->response_id();
550 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49551 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
552 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33553 }
554 ScheduleNextTask();
555 }
556
557 void WriteOneBlock(int block_number) {
[email protected]ad8e04a2010-11-01 04:16:27558 scoped_refptr<IOBuffer> io_buffer(
559 new IOBuffer(kBlockSize));
[email protected]073aabe2009-10-21 18:09:33560 FillData(block_number, io_buffer->data(), kBlockSize);
561 WriteResponseBody(io_buffer, kBlockSize);
562 }
563
564 void ReadInBlocks() {
565 writer_.reset();
566 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48567 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33568 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49569 PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
570 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33571 }
572 ScheduleNextTask();
573 }
574
575 void ReadOneBlock(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49576 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
577 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33578 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
579 }
580
581 void VerifyOneBlock(int block_number) {
582 EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
583 ScheduleNextTask();
584 }
585
586 void ReadAllAtOnce() {
[email protected]8336aaf42011-11-11 21:05:49587 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
588 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33589 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48590 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33591 int big_size = kNumBlocks * kBlockSize;
592 ReadResponseBody(new IOBuffer(big_size), big_size);
593 }
594
595 void VerifyAllAtOnce() {
596 char* p = read_buffer_->data();
597 for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
598 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
599 ScheduleNextTask();
600 }
601
602 void ReadPastEOF() {
603 EXPECT_FALSE(reader_->IsReadPending());
604 read_buffer_ = new IOBuffer(kBlockSize);
605 expected_read_result_ = 0;
[email protected]ff875be52013-06-02 23:47:38606 reader_->ReadData(read_buffer_.get(),
607 kBlockSize,
608 base::Bind(&AppCacheResponseTest::OnReadComplete,
609 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33610 }
611
612 void ReadRange() {
[email protected]8336aaf42011-11-11 21:05:49613 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
614 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33615 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48616 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33617 reader_->SetReadRange(kBlockSize, kBlockSize);
618 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
619 }
620
621 void VerifyRange() {
622 EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
623 ScheduleNextTask(); // ReadPastEOF is scheduled next
624 }
625
626 void ReadRangePartiallyBeyondEOF() {
[email protected]8336aaf42011-11-11 21:05:49627 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
628 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33629 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48630 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33631 reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
632 ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
633 kNumBlocks * kBlockSize);
634 expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
635 }
636
637 void VerifyRangeBeyondEOF() {
638 // Just verify the first 1k
639 VerifyRange();
640 }
641
642 void ReadRangeFullyBeyondEOF() {
643 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48644 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33645 reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
646 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
647 expected_read_result_ = 0;
648 }
649
650 // IOChaining -------------------------------------------
651 void IOChaining() {
652 // 1. Write several blocks out initiating the subsequent write
653 // from within the completion callback of the previous write.
654 // 2. Read and verify several blocks in similarly chaining reads.
655
656 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49657 PushNextTaskAsImmediate(
658 base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately,
659 base::Unretained(this)));
660 PushNextTaskAsImmediate(
661 base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately,
662 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33663
664 // Get them going.
665 ScheduleNextTask();
666 }
667
668 void WriteOutBlocksImmediately() {
lukasza9cb60b72016-04-19 22:59:48669 writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
[email protected]073aabe2009-10-21 18:09:33670 written_response_id_ = writer_->response_id();
671 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49672 PushNextTaskAsImmediate(
673 base::Bind(&AppCacheResponseTest::WriteOneBlock,
674 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33675 }
676 ScheduleNextTask();
677 }
678
679 void ReadInBlocksImmediately() {
680 writer_.reset();
681 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48682 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33683 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49684 PushNextTaskAsImmediate(
685 base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately,
686 base::Unretained(this),
[email protected]79b15b22010-05-19 00:38:56687 kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33688 }
689 ScheduleNextTask();
690 }
691
692 void ReadOneBlockImmediately(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49693 PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
694 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33695 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
696 }
697
698 // DeleteWithinCallbacks -------------------------------------------
699 void DeleteWithinCallbacks() {
700 // 1. Write out a few blocks normally, and upon
701 // completion of the last write, delete the writer.
702 // 2. Read in a few blocks normally, and upon completion
703 // of the last read, delete the reader.
704
705 should_delete_reader_in_completion_callback_ = true;
706 reader_deletion_count_down_ = kNumBlocks;
707 should_delete_writer_in_completion_callback_ = true;
708 writer_deletion_count_down_ = kNumBlocks;
709
[email protected]8336aaf42011-11-11 21:05:49710 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
711 base::Unretained(this)));
712 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
713 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33714 ScheduleNextTask();
715 }
716
717 // DeleteWithIOPending -------------------------------------------
718 void DeleteWithIOPending() {
719 // 1. Write a few blocks normally.
720 // 2. Start a write, delete with it pending.
721 // 3. Start a read, delete with it pending.
[email protected]8336aaf42011-11-11 21:05:49722 PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
723 base::Unretained(this)));
724 PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
725 base::Unretained(this)));
726 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
727 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33728 ScheduleNextTask();
729 }
730
731 void WriteThenDelete() {
732 write_callback_was_called_ = false;
733 WriteOneBlock(5);
734 EXPECT_TRUE(writer_->IsWritePending());
735 writer_.reset();
736 ScheduleNextTask();
737 }
738
739 void ReadThenDelete() {
740 read_callback_was_called_ = false;
741 reader_.reset(service_->storage()->CreateResponseReader(
lukasza9cb60b72016-04-19 22:59:48742 GURL(), written_response_id_));
[email protected]073aabe2009-10-21 18:09:33743 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
744 EXPECT_TRUE(reader_->IsReadPending());
745 reader_.reset();
746
747 // Wait a moment to verify no callbacks.
skyostil95082a62015-06-05 19:53:07748 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
[email protected]8336aaf42011-11-11 21:05:49749 FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
750 base::Unretained(this)),
[email protected]6f35f4e2012-03-03 21:02:28751 base::TimeDelta::FromMilliseconds(10));
[email protected]073aabe2009-10-21 18:09:33752 }
753
754 void VerifyNoCallbacks() {
755 EXPECT_TRUE(!write_callback_was_called_);
756 EXPECT_TRUE(!read_callback_was_called_);
757 TestFinished();
758 }
759
760 // Data members
761
dcheng59716272016-04-09 05:19:08762 std::unique_ptr<base::WaitableEvent> test_finished_event_;
763 std::unique_ptr<MockStorageDelegate> storage_delegate_;
764 std::unique_ptr<MockAppCacheService> service_;
[email protected]8336aaf42011-11-11 21:05:49765 std::stack<std::pair<base::Closure, bool> > task_stack_;
[email protected]073aabe2009-10-21 18:09:33766
dcheng59716272016-04-09 05:19:08767 std::unique_ptr<AppCacheResponseReader> reader_;
[email protected]073aabe2009-10-21 18:09:33768 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
769 scoped_refptr<IOBuffer> read_buffer_;
770 int expected_read_result_;
[email protected]073aabe2009-10-21 18:09:33771 bool should_delete_reader_in_completion_callback_;
772 int reader_deletion_count_down_;
773 bool read_callback_was_called_;
774
avib7348942015-12-25 20:57:10775 int64_t written_response_id_;
dcheng59716272016-04-09 05:19:08776 std::unique_ptr<AppCacheResponseWriter> writer_;
777 std::unique_ptr<AppCacheResponseMetadataWriter> metadata_writer_;
[email protected]073aabe2009-10-21 18:09:33778 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
779 scoped_refptr<IOBuffer> write_buffer_;
780 int expected_write_result_;
[email protected]073aabe2009-10-21 18:09:33781 bool should_delete_writer_in_completion_callback_;
782 int writer_deletion_count_down_;
783 bool write_callback_was_called_;
784
dcheng59716272016-04-09 05:19:08785 static std::unique_ptr<base::Thread> io_thread_;
[email protected]073aabe2009-10-21 18:09:33786};
787
788// static
dcheng59716272016-04-09 05:19:08789std::unique_ptr<base::Thread> AppCacheResponseTest::io_thread_;
[email protected]073aabe2009-10-21 18:09:33790
[email protected]073aabe2009-10-21 18:09:33791TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
792 RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
793}
794
795TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
796 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
797}
798
799TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
800 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
801}
802
horoa9500072015-02-18 05:08:15803TEST_F(AppCacheResponseTest, Metadata) {
804 RunTestOnIOThread(&AppCacheResponseTest::Metadata);
805}
806
[email protected]0dfeec32010-01-06 22:25:33807TEST_F(AppCacheResponseTest, AmountWritten) {
808 RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
809}
810
[email protected]073aabe2009-10-21 18:09:33811TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
812 RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
813}
814
815TEST_F(AppCacheResponseTest, IOChaining) {
816 RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
817}
818
819TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
820 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
821}
822
823TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
824 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
825}
826
[email protected]a507b822014-04-12 05:10:24827} // namespace content