blob: cdce8e69813dbb72e21f4204a4f81a349902af45 [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>
6
[email protected]b7243c42010-07-23 05:23:137#include <stack>
8#include <string>
9#include <utility>
10
[email protected]8336aaf42011-11-11 21:05:4911#include "base/bind.h"
12#include "base/bind_helpers.h"
13#include "base/callback.h"
[email protected]073aabe2009-10-21 18:09:3314#include "base/compiler_specific.h"
skyostil95082a62015-06-05 19:53:0715#include "base/location.h"
avib7348942015-12-25 20:57:1016#include "base/macros.h"
[email protected]073aabe2009-10-21 18:09:3317#include "base/pickle.h"
skyostil95082a62015-06-05 19:53:0718#include "base/single_thread_task_runner.h"
[email protected]44f9c952011-01-02 06:05:3919#include "base/synchronization/waitable_event.h"
skyostil95082a62015-06-05 19:53:0720#include "base/thread_task_runner_handle.h"
[email protected]d5b2fdf2013-06-05 09:36:5521#include "base/threading/thread.h"
[email protected]98d6d4562014-06-25 20:57:5522#include "content/browser/appcache/appcache_response.h"
[email protected]71fe3d12014-04-22 00:32:3823#include "content/browser/appcache/mock_appcache_service.h"
[email protected]073aabe2009-10-21 18:09:3324#include "net/base/io_buffer.h"
[email protected]80d42812010-02-09 10:30:2525#include "net/base/net_errors.h"
[email protected]277d5942010-08-11 21:02:3526#include "net/http/http_response_headers.h"
[email protected]073aabe2009-10-21 18:09:3327#include "testing/gtest/include/gtest/gtest.h"
[email protected]073aabe2009-10-21 18:09:3328
29using net::IOBuffer;
[email protected]3367fc1d2009-11-09 00:09:2130using net::WrappedIOBuffer;
[email protected]073aabe2009-10-21 18:09:3331
[email protected]a507b822014-04-12 05:10:2432namespace content {
[email protected]073aabe2009-10-21 18:09:3333
[email protected]dda06f82009-10-21 18:38:5134static const int kNumBlocks = 4;
35static const int kBlockSize = 1024;
36static const int kNoSuchResponseId = 123;
37
[email protected]073aabe2009-10-21 18:09:3338class AppCacheResponseTest : public testing::Test {
39 public:
[email protected]073aabe2009-10-21 18:09:3340 // 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
dchengc2282aa2014-10-21 12:07:5849 void OnResponseInfoLoaded(AppCacheResponseInfo* info,
avib7348942015-12-25 20:57:1050 int64_t 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_;
avib7348942015-12-25 20:57:1057 int64_t loaded_info_id_;
[email protected]073aabe2009-10-21 18:09:3358 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));
skyostil95082a62015-06-05 19:53:0784 io_thread_->task_runner()->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());
skyostil95082a62015-06-05 19:53:07125 base::ThreadTaskRunnerHandle::Get()->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
skyostil95082a62015-06-05 19:53:07155 base::ThreadTaskRunnerHandle::Get()->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";
[email protected]e2a8b0e2014-08-21 08:49:53163 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
horoa9500072015-02-18 05:08:15200 void WriteResponseMetadata(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
201 EXPECT_FALSE(metadata_writer_->IsWritePending());
202 write_buffer_ = io_buffer;
203 expected_write_result_ = buf_len;
204 metadata_writer_->WriteMetadata(
205 write_buffer_.get(), buf_len,
206 base::Bind(&AppCacheResponseTest::OnMetadataWriteComplete,
207 base::Unretained(this)));
208 }
209
[email protected]073aabe2009-10-21 18:09:33210 void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) {
211 EXPECT_FALSE(reader_->IsReadPending());
212 read_buffer_ = io_buffer;
213 expected_read_result_ = buf_len;
[email protected]ff875be52013-06-02 23:47:38214 reader_->ReadData(read_buffer_.get(),
215 buf_len,
216 base::Bind(&AppCacheResponseTest::OnReadComplete,
217 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33218 }
219
220 // AppCacheResponseReader / Writer completion callbacks
221
222 void OnWriteInfoComplete(int result) {
223 EXPECT_FALSE(writer_->IsWritePending());
224 EXPECT_EQ(expected_write_result_, result);
225 ScheduleNextTask();
226 }
227
228 void OnWriteComplete(int result) {
229 EXPECT_FALSE(writer_->IsWritePending());
230 write_callback_was_called_ = true;
231 EXPECT_EQ(expected_write_result_, result);
232 if (should_delete_writer_in_completion_callback_ &&
233 --writer_deletion_count_down_ == 0) {
234 writer_.reset();
235 }
236 ScheduleNextTask();
237 }
238
horoa9500072015-02-18 05:08:15239 void OnMetadataWriteComplete(int result) {
240 EXPECT_FALSE(metadata_writer_->IsWritePending());
241 EXPECT_EQ(expected_write_result_, result);
242 ScheduleNextTask();
243 }
244
[email protected]073aabe2009-10-21 18:09:33245 void OnReadInfoComplete(int result) {
246 EXPECT_FALSE(reader_->IsReadPending());
247 EXPECT_EQ(expected_read_result_, result);
248 ScheduleNextTask();
249 }
250
251 void OnReadComplete(int result) {
252 EXPECT_FALSE(reader_->IsReadPending());
253 read_callback_was_called_ = true;
254 EXPECT_EQ(expected_read_result_, result);
255 if (should_delete_reader_in_completion_callback_ &&
256 --reader_deletion_count_down_ == 0) {
257 reader_.reset();
258 }
259 ScheduleNextTask();
260 }
261
262 // Helpers to work with HttpResponseInfo objects
263
[email protected]3367fc1d2009-11-09 00:09:21264 net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
[email protected]073aabe2009-10-21 18:09:33265 net::HttpResponseInfo* info = new net::HttpResponseInfo;
266 info->request_time = base::Time::Now();
267 info->response_time = base::Time::Now();
268 info->was_cached = false;
269 info->headers = new net::HttpResponseHeaders(raw_headers);
270 return info;
271 }
272
273 int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) {
brettwbd4d7112015-06-03 04:29:25274 base::Pickle pickle;
[email protected]073aabe2009-10-21 18:09:33275 return PickleHttpResonseInfo(&pickle, info);
276 }
277
278 bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1,
279 const net::HttpResponseInfo* info2) {
brettwbd4d7112015-06-03 04:29:25280 base::Pickle pickle1;
281 base::Pickle pickle2;
[email protected]073aabe2009-10-21 18:09:33282 PickleHttpResonseInfo(&pickle1, info1);
283 PickleHttpResonseInfo(&pickle2, info2);
284 return (pickle1.size() == pickle2.size()) &&
285 (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
286 }
287
brettwbd4d7112015-06-03 04:29:25288 int PickleHttpResonseInfo(base::Pickle* pickle,
289 const net::HttpResponseInfo* info) {
[email protected]073aabe2009-10-21 18:09:33290 const bool kSkipTransientHeaders = true;
291 const bool kTruncated = false;
292 info->Persist(pickle, kSkipTransientHeaders, kTruncated);
293 return pickle->size();
294 }
295
296 // Helpers to fill and verify blocks of memory with a value
297
298 void FillData(char value, char* data, int data_len) {
299 memset(data, value, data_len);
300 }
301
302 bool CheckData(char value, const char* data, int data_len) {
303 for (int i = 0; i < data_len; ++i, ++data) {
304 if (*data != value)
305 return false;
306 }
307 return true;
308 }
309
310 // Individual Tests ---------------------------------------------------------
311 // Most of the individual tests involve multiple async steps. Each test
312 // is delineated with a section header.
313
[email protected]073aabe2009-10-21 18:09:33314
315 // ReadNonExistentResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33316 void ReadNonExistentResponse() {
317 // 1. Attempt to ReadInfo
318 // 2. Attempt to ReadData
319
320 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36321 GURL(), 0, kNoSuchResponseId));
[email protected]073aabe2009-10-21 18:09:33322
323 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49324 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
325 base::Unretained(this)));
326 PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
327 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33328 ScheduleNextTask();
329 }
330
331 void ReadNonExistentInfo() {
332 EXPECT_FALSE(reader_->IsReadPending());
333 read_info_buffer_ = new HttpResponseInfoIOBuffer();
[email protected]ff875be52013-06-02 23:47:38334 reader_->ReadInfo(read_info_buffer_.get(),
335 base::Bind(&AppCacheResponseTest::OnReadInfoComplete,
336 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33337 EXPECT_TRUE(reader_->IsReadPending());
338 expected_read_result_ = net::ERR_CACHE_MISS;
339 }
340
341 void ReadNonExistentData() {
342 EXPECT_FALSE(reader_->IsReadPending());
343 read_buffer_ = new IOBuffer(kBlockSize);
[email protected]ff875be52013-06-02 23:47:38344 reader_->ReadData(read_buffer_.get(),
345 kBlockSize,
346 base::Bind(&AppCacheResponseTest::OnReadComplete,
347 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33348 EXPECT_TRUE(reader_->IsReadPending());
349 expected_read_result_ = net::ERR_CACHE_MISS;
350 }
351
352 // LoadResponseInfo_Miss ----------------------------------------------------
353 void LoadResponseInfo_Miss() {
[email protected]8336aaf42011-11-11 21:05:49354 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
355 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36356 service_->storage()->LoadResponseInfo(GURL(), 0, kNoSuchResponseId,
[email protected]073aabe2009-10-21 18:09:33357 storage_delegate_.get());
358 }
359
360 void LoadResponseInfo_Miss_Verify() {
[email protected]dda06f82009-10-21 18:38:51361 EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_);
[email protected]073aabe2009-10-21 18:09:33362 EXPECT_TRUE(!storage_delegate_->loaded_info_.get());
363 TestFinished();
364 }
365
366 // LoadResponseInfo_Hit ----------------------------------------------------
367 void LoadResponseInfo_Hit() {
368 // This tests involves multiple async steps.
369 // 1. Write a response headers and body to storage
370 // a. headers
371 // b. body
372 // 2. Use LoadResponseInfo to read the response headers back out
[email protected]8336aaf42011-11-11 21:05:49373 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
374 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36375 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33376 written_response_id_ = writer_->response_id();
377 WriteBasicResponse();
378 }
379
380 void LoadResponseInfo_Hit_Step2() {
381 writer_.reset();
[email protected]8336aaf42011-11-11 21:05:49382 PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
383 base::Unretained(this)));
[email protected]4252f602011-10-21 19:18:36384 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
[email protected]073aabe2009-10-21 18:09:33385 storage_delegate_.get());
386 }
387
388 void LoadResponseInfo_Hit_Verify() {
389 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
390 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
391 EXPECT_TRUE(CompareHttpResponseInfos(
392 write_info_buffer_->http_info.get(),
393 storage_delegate_->loaded_info_->http_response_info()));
[email protected]fd2885a2010-03-17 22:02:28394 EXPECT_EQ(basic_response_size(),
395 storage_delegate_->loaded_info_->response_data_size());
[email protected]073aabe2009-10-21 18:09:33396 TestFinished();
397 }
398
horoa9500072015-02-18 05:08:15399 // Metadata -------------------------------------------------
400 void Metadata() {
401 // This tests involves multiple async steps.
402 // 1. Write a response headers and body to storage
403 // a. headers
404 // b. body
405 // 2. Write metadata "Metadata First" using AppCacheResponseMetadataWriter.
406 // 3. Check metadata was written.
407 // 4. Write metadata "Second".
408 // 5. Check metadata was written and was truncated .
409 // 6. Write metadata "".
410 // 7. Check metadata was deleted.
411
412 // Push tasks in reverse order.
413 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
414 base::Unretained(this), ""));
415 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
416 base::Unretained(this)));
417 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
418 base::Unretained(this), ""));
419 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
420 base::Unretained(this), "Second"));
421 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
422 base::Unretained(this)));
423 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
424 base::Unretained(this), "Second"));
425 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
426 base::Unretained(this), "Metadata First"));
427 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
428 base::Unretained(this)));
429 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
430 base::Unretained(this), "Metadata First"));
431 PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_ResetWriter,
432 base::Unretained(this)));
433 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
434 written_response_id_ = writer_->response_id();
435 WriteBasicResponse();
436 }
437
438 void Metadata_ResetWriter() {
439 writer_.reset();
440 ScheduleNextTask();
441 }
442
443 void Metadata_WriteMetadata(const char* metadata) {
444 metadata_writer_.reset(service_->storage()->CreateResponseMetadataWriter(
445 0, written_response_id_));
446 scoped_refptr<IOBuffer> buffer(new WrappedIOBuffer(metadata));
447 WriteResponseMetadata(buffer.get(), strlen(metadata));
448 }
449
450 void Metadata_LoadResponseInfo() {
451 metadata_writer_.reset();
452 storage_delegate_.reset(new MockStorageDelegate(this));
453 service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_,
454 storage_delegate_.get());
455 }
456
457 void Metadata_VerifyMetadata(const char* metadata) {
458 EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_);
459 EXPECT_TRUE(storage_delegate_->loaded_info_.get());
460 const net::HttpResponseInfo* read_head =
461 storage_delegate_->loaded_info_->http_response_info();
462 EXPECT_TRUE(read_head);
463 const int metadata_size = strlen(metadata);
464 if (metadata_size) {
465 EXPECT_TRUE(read_head->metadata.get());
466 EXPECT_EQ(metadata_size, read_head->metadata->size());
467 EXPECT_EQ(0,
468 memcmp(metadata, read_head->metadata->data(), metadata_size));
469 } else {
470 EXPECT_FALSE(read_head->metadata.get());
471 }
472 EXPECT_TRUE(CompareHttpResponseInfos(
473 write_info_buffer_->http_info.get(),
474 storage_delegate_->loaded_info_->http_response_info()));
475 EXPECT_EQ(basic_response_size(),
476 storage_delegate_->loaded_info_->response_data_size());
477 ScheduleNextTask();
478 }
479
[email protected]0dfeec32010-01-06 22:25:33480 // AmountWritten ----------------------------------------------------
481
482 void AmountWritten() {
[email protected]e2a8b0e2014-08-21 08:49:53483 static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
[email protected]0dfeec32010-01-06 22:25:33484 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
485 net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
486 int expected_amount_written =
487 GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
488
489 // Push tasks in reverse order.
[email protected]8336aaf42011-11-11 21:05:49490 PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
491 base::Unretained(this), expected_amount_written));
[email protected]0dfeec32010-01-06 22:25:33492 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49493 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
494 base::Unretained(this), kNumBlocks - i));
[email protected]0dfeec32010-01-06 22:25:33495 }
[email protected]8336aaf42011-11-11 21:05:49496 PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
497 base::Unretained(this), head));
[email protected]0dfeec32010-01-06 22:25:33498
[email protected]4252f602011-10-21 19:18:36499 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]0dfeec32010-01-06 22:25:33500 written_response_id_ = writer_->response_id();
501 ScheduleNextTask();
502 }
503
504 void Verify_AmountWritten(int expected_amount_written) {
505 EXPECT_EQ(expected_amount_written, writer_->amount_written());
506 TestFinished();
507 }
508
509
[email protected]073aabe2009-10-21 18:09:33510 // WriteThenVariouslyReadResponse -------------------------------------------
[email protected]073aabe2009-10-21 18:09:33511
512 void WriteThenVariouslyReadResponse() {
513 // This tests involves multiple async steps.
514 // 1. First, write a large body using multiple writes, we don't bother
515 // with a response head for this test.
516 // 2. Read the entire body, using multiple reads
517 // 3. Read the entire body, using one read.
518 // 4. Attempt to read beyond the EOF.
519 // 5. Read just a range.
520 // 6. Attempt to read beyond EOF of a range.
521
522 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49523 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
524 base::Unretained(this)));
525 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
526 base::Unretained(this)));
527 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
528 base::Unretained(this)));
529 PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
530 base::Unretained(this)));
531 PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
532 base::Unretained(this)));
533 PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
534 base::Unretained(this)));
535 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
536 base::Unretained(this)));
537 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
538 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33539
540 // Get them going.
541 ScheduleNextTask();
542 }
543
544 void WriteOutBlocks() {
[email protected]4252f602011-10-21 19:18:36545 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33546 written_response_id_ = writer_->response_id();
547 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49548 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
549 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33550 }
551 ScheduleNextTask();
552 }
553
554 void WriteOneBlock(int block_number) {
[email protected]ad8e04a2010-11-01 04:16:27555 scoped_refptr<IOBuffer> io_buffer(
556 new IOBuffer(kBlockSize));
[email protected]073aabe2009-10-21 18:09:33557 FillData(block_number, io_buffer->data(), kBlockSize);
558 WriteResponseBody(io_buffer, kBlockSize);
559 }
560
561 void ReadInBlocks() {
562 writer_.reset();
563 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36564 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33565 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49566 PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
567 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33568 }
569 ScheduleNextTask();
570 }
571
572 void ReadOneBlock(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49573 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
574 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33575 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
576 }
577
578 void VerifyOneBlock(int block_number) {
579 EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
580 ScheduleNextTask();
581 }
582
583 void ReadAllAtOnce() {
[email protected]8336aaf42011-11-11 21:05:49584 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
585 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33586 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36587 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33588 int big_size = kNumBlocks * kBlockSize;
589 ReadResponseBody(new IOBuffer(big_size), big_size);
590 }
591
592 void VerifyAllAtOnce() {
593 char* p = read_buffer_->data();
594 for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
595 EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
596 ScheduleNextTask();
597 }
598
599 void ReadPastEOF() {
600 EXPECT_FALSE(reader_->IsReadPending());
601 read_buffer_ = new IOBuffer(kBlockSize);
602 expected_read_result_ = 0;
[email protected]ff875be52013-06-02 23:47:38603 reader_->ReadData(read_buffer_.get(),
604 kBlockSize,
605 base::Bind(&AppCacheResponseTest::OnReadComplete,
606 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33607 }
608
609 void ReadRange() {
[email protected]8336aaf42011-11-11 21:05:49610 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
611 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33612 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36613 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33614 reader_->SetReadRange(kBlockSize, kBlockSize);
615 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
616 }
617
618 void VerifyRange() {
619 EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
620 ScheduleNextTask(); // ReadPastEOF is scheduled next
621 }
622
623 void ReadRangePartiallyBeyondEOF() {
[email protected]8336aaf42011-11-11 21:05:49624 PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
625 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33626 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36627 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33628 reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
629 ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
630 kNumBlocks * kBlockSize);
631 expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
632 }
633
634 void VerifyRangeBeyondEOF() {
635 // Just verify the first 1k
636 VerifyRange();
637 }
638
639 void ReadRangeFullyBeyondEOF() {
640 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36641 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33642 reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
643 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
644 expected_read_result_ = 0;
645 }
646
647 // IOChaining -------------------------------------------
648 void IOChaining() {
649 // 1. Write several blocks out initiating the subsequent write
650 // from within the completion callback of the previous write.
651 // 2. Read and verify several blocks in similarly chaining reads.
652
653 // Push tasks in reverse order
[email protected]8336aaf42011-11-11 21:05:49654 PushNextTaskAsImmediate(
655 base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately,
656 base::Unretained(this)));
657 PushNextTaskAsImmediate(
658 base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately,
659 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33660
661 // Get them going.
662 ScheduleNextTask();
663 }
664
665 void WriteOutBlocksImmediately() {
[email protected]4252f602011-10-21 19:18:36666 writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0));
[email protected]073aabe2009-10-21 18:09:33667 written_response_id_ = writer_->response_id();
668 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49669 PushNextTaskAsImmediate(
670 base::Bind(&AppCacheResponseTest::WriteOneBlock,
671 base::Unretained(this), kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33672 }
673 ScheduleNextTask();
674 }
675
676 void ReadInBlocksImmediately() {
677 writer_.reset();
678 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36679 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33680 for (int i = 0; i < kNumBlocks; ++i) {
[email protected]8336aaf42011-11-11 21:05:49681 PushNextTaskAsImmediate(
682 base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately,
683 base::Unretained(this),
[email protected]79b15b22010-05-19 00:38:56684 kNumBlocks - i));
[email protected]073aabe2009-10-21 18:09:33685 }
686 ScheduleNextTask();
687 }
688
689 void ReadOneBlockImmediately(int block_number) {
[email protected]8336aaf42011-11-11 21:05:49690 PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
691 base::Unretained(this), block_number));
[email protected]073aabe2009-10-21 18:09:33692 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
693 }
694
695 // DeleteWithinCallbacks -------------------------------------------
696 void DeleteWithinCallbacks() {
697 // 1. Write out a few blocks normally, and upon
698 // completion of the last write, delete the writer.
699 // 2. Read in a few blocks normally, and upon completion
700 // of the last read, delete the reader.
701
702 should_delete_reader_in_completion_callback_ = true;
703 reader_deletion_count_down_ = kNumBlocks;
704 should_delete_writer_in_completion_callback_ = true;
705 writer_deletion_count_down_ = kNumBlocks;
706
[email protected]8336aaf42011-11-11 21:05:49707 PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
708 base::Unretained(this)));
709 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
710 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33711 ScheduleNextTask();
712 }
713
714 // DeleteWithIOPending -------------------------------------------
715 void DeleteWithIOPending() {
716 // 1. Write a few blocks normally.
717 // 2. Start a write, delete with it pending.
718 // 3. Start a read, delete with it pending.
[email protected]8336aaf42011-11-11 21:05:49719 PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
720 base::Unretained(this)));
721 PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
722 base::Unretained(this)));
723 PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
724 base::Unretained(this)));
[email protected]073aabe2009-10-21 18:09:33725 ScheduleNextTask();
726 }
727
728 void WriteThenDelete() {
729 write_callback_was_called_ = false;
730 WriteOneBlock(5);
731 EXPECT_TRUE(writer_->IsWritePending());
732 writer_.reset();
733 ScheduleNextTask();
734 }
735
736 void ReadThenDelete() {
737 read_callback_was_called_ = false;
738 reader_.reset(service_->storage()->CreateResponseReader(
[email protected]4252f602011-10-21 19:18:36739 GURL(), 0, written_response_id_));
[email protected]073aabe2009-10-21 18:09:33740 ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
741 EXPECT_TRUE(reader_->IsReadPending());
742 reader_.reset();
743
744 // Wait a moment to verify no callbacks.
skyostil95082a62015-06-05 19:53:07745 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
[email protected]8336aaf42011-11-11 21:05:49746 FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
747 base::Unretained(this)),
[email protected]6f35f4e2012-03-03 21:02:28748 base::TimeDelta::FromMilliseconds(10));
[email protected]073aabe2009-10-21 18:09:33749 }
750
751 void VerifyNoCallbacks() {
752 EXPECT_TRUE(!write_callback_was_called_);
753 EXPECT_TRUE(!read_callback_was_called_);
754 TestFinished();
755 }
756
757 // Data members
758
[email protected]073aabe2009-10-21 18:09:33759 scoped_ptr<base::WaitableEvent> test_finished_event_;
760 scoped_ptr<MockStorageDelegate> storage_delegate_;
761 scoped_ptr<MockAppCacheService> service_;
[email protected]8336aaf42011-11-11 21:05:49762 std::stack<std::pair<base::Closure, bool> > task_stack_;
[email protected]073aabe2009-10-21 18:09:33763
764 scoped_ptr<AppCacheResponseReader> reader_;
765 scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
766 scoped_refptr<IOBuffer> read_buffer_;
767 int expected_read_result_;
[email protected]073aabe2009-10-21 18:09:33768 bool should_delete_reader_in_completion_callback_;
769 int reader_deletion_count_down_;
770 bool read_callback_was_called_;
771
avib7348942015-12-25 20:57:10772 int64_t written_response_id_;
[email protected]073aabe2009-10-21 18:09:33773 scoped_ptr<AppCacheResponseWriter> writer_;
horoa9500072015-02-18 05:08:15774 scoped_ptr<AppCacheResponseMetadataWriter> metadata_writer_;
[email protected]073aabe2009-10-21 18:09:33775 scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
776 scoped_refptr<IOBuffer> write_buffer_;
777 int expected_write_result_;
[email protected]073aabe2009-10-21 18:09:33778 bool should_delete_writer_in_completion_callback_;
779 int writer_deletion_count_down_;
780 bool write_callback_was_called_;
781
782 static scoped_ptr<base::Thread> io_thread_;
783};
784
785// static
786scoped_ptr<base::Thread> AppCacheResponseTest::io_thread_;
787
[email protected]073aabe2009-10-21 18:09:33788TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
789 RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
790}
791
792TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
793 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
794}
795
796TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
797 RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
798}
799
horoa9500072015-02-18 05:08:15800TEST_F(AppCacheResponseTest, Metadata) {
801 RunTestOnIOThread(&AppCacheResponseTest::Metadata);
802}
803
[email protected]0dfeec32010-01-06 22:25:33804TEST_F(AppCacheResponseTest, AmountWritten) {
805 RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
806}
807
[email protected]073aabe2009-10-21 18:09:33808TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
809 RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
810}
811
812TEST_F(AppCacheResponseTest, IOChaining) {
813 RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
814}
815
816TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
817 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
818}
819
820TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
821 RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
822}
823
[email protected]a507b822014-04-12 05:10:24824} // namespace content