Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(342)

Side by Side Diff: content/browser/fileapi/blob_reader_unittest.cc

Issue 1337153002: [Blob] BlobReader class & tests, and removal of all redundant reading. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Trybot fixes Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "storage/browser/blob/blob_reader.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/files/file_path.h"
11 #include "base/location.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/task_runner.h"
16 #include "base/time/time.h"
17 #include "content/public/test/async_file_test_helper.h"
18 #include "content/public/test/test_file_system_context.h"
19 #include "net/base/completion_callback.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/test_completion_callback.h"
23 #include "net/disk_cache/disk_cache.h"
24 #include "storage/browser/blob/blob_data_builder.h"
25 #include "storage/browser/blob/blob_data_handle.h"
26 #include "storage/browser/blob/blob_storage_context.h"
27 #include "storage/browser/fileapi/file_stream_reader.h"
28 #include "storage/browser/fileapi/file_system_context.h"
29 #include "storage/browser/fileapi/file_system_file_util.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "url/gurl.h"
33
34 using content::AsyncFileTestHelper;
35 using net::DrainableIOBuffer;
36 using net::IOBuffer;
37
38 namespace storage {
39 namespace {
40
41 const int kTestDiskCacheStreamIndex = 0;
42
43 // Our disk cache tests don't need a real data handle since the tests themselves
44 // scope the disk cache and entries.
45 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
46 private:
47 ~EmptyDataHandle() override {}
48 };
49
50 // A disk_cache::Entry that arbitrarily delays the completion of a read
51 // operation to allow testing some races without flake. This is particularly
52 // relevant in this unit test, which uses the always-synchronous MEMORY_CACHE.
53 class DelayedReadEntry : public disk_cache::Entry {
54 public:
55 explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry)
56 : entry_(entry.Pass()) {}
57 ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); }
58
59 bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); }
60
61 void RunPendingReadCallbacks() {
62 std::vector<base::Callback<void(void)>> callbacks;
63 pending_read_callbacks_.swap(callbacks);
64 for (const auto& callback : callbacks)
65 callback.Run();
66 }
67
68 // From disk_cache::Entry:
69 void Doom() override { entry_->Doom(); }
70
71 void Close() override { delete this; } // Note this is required by the API.
72
73 std::string GetKey() const override { return entry_->GetKey(); }
74
75 base::Time GetLastUsed() const override { return entry_->GetLastUsed(); }
76
77 base::Time GetLastModified() const override {
78 return entry_->GetLastModified();
79 }
80
81 int32 GetDataSize(int index) const override {
82 return entry_->GetDataSize(index);
83 }
84
85 int ReadData(int index,
86 int offset,
87 IOBuffer* buf,
88 int buf_len,
89 const CompletionCallback& original_callback) override {
90 net::TestCompletionCallback callback;
91 int rv = entry_->ReadData(index, offset, buf, buf_len, callback.callback());
92 DCHECK_NE(rv, net::ERR_IO_PENDING)
93 << "Test expects to use a MEMORY_CACHE instance, which is synchronous.";
94 pending_read_callbacks_.push_back(base::Bind(original_callback, rv));
95 return net::ERR_IO_PENDING;
96 }
97
98 int WriteData(int index,
99 int offset,
100 IOBuffer* buf,
101 int buf_len,
102 const CompletionCallback& callback,
103 bool truncate) override {
104 return entry_->WriteData(index, offset, buf, buf_len, callback, truncate);
105 }
106
107 int ReadSparseData(int64 offset,
108 IOBuffer* buf,
109 int buf_len,
110 const CompletionCallback& callback) override {
111 return entry_->ReadSparseData(offset, buf, buf_len, callback);
112 }
113
114 int WriteSparseData(int64 offset,
115 IOBuffer* buf,
116 int buf_len,
117 const CompletionCallback& callback) override {
118 return entry_->WriteSparseData(offset, buf, buf_len, callback);
119 }
120
121 int GetAvailableRange(int64 offset,
122 int len,
123 int64* start,
124 const CompletionCallback& callback) override {
125 return entry_->GetAvailableRange(offset, len, start, callback);
126 }
127
128 bool CouldBeSparse() const override { return entry_->CouldBeSparse(); }
129
130 void CancelSparseIO() override { entry_->CancelSparseIO(); }
131
132 int ReadyForSparseIO(const CompletionCallback& callback) override {
133 return entry_->ReadyForSparseIO(callback);
134 }
135
136 private:
137 disk_cache::ScopedEntryPtr entry_;
138 std::vector<base::Callback<void(void)>> pending_read_callbacks_;
139 };
140
141 scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache(
142 const scoped_refptr<base::SingleThreadTaskRunner>& thread) {
143 scoped_ptr<disk_cache::Backend> cache;
144 net::TestCompletionCallback callback;
145 int rv = disk_cache::CreateCacheBackend(
146 net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(), 0, false,
147 thread, nullptr, &cache, callback.callback());
148 EXPECT_EQ(net::OK, callback.GetResult(rv));
149
150 return cache.Pass();
151 }
152
153 disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
154 const char* key,
155 const std::string& data) {
156 disk_cache::Entry* temp_entry = nullptr;
157 net::TestCompletionCallback callback;
158 int rv = cache->CreateEntry(key, &temp_entry, callback.callback());
159 if (callback.GetResult(rv) != net::OK)
160 return nullptr;
161 disk_cache::ScopedEntryPtr entry(temp_entry);
162
163 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data);
164 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
165 iobuffer->size(), callback.callback(), false);
166 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
167 return entry.Pass();
168 }
169
170 template <typename T>
171 void SetValue(T* address, T value) {
172 *address = value;
173 }
174
175 class FakeFileStreamReader : public FileStreamReader {
176 public:
177 explicit FakeFileStreamReader(const std::string& contents)
178 : buffer_(new DrainableIOBuffer(
179 new net::StringIOBuffer(
180 scoped_ptr<std::string>(new std::string(contents))),
181 contents.size())),
182 net_error_(net::OK),
183 size_(contents.size()) {}
184 FakeFileStreamReader(const std::string& contents, uint64_t size)
185 : buffer_(new DrainableIOBuffer(
186 new net::StringIOBuffer(
187 scoped_ptr<std::string>(new std::string(contents))),
188 contents.size())),
189 net_error_(net::OK),
190 size_(size) {}
191
192 void ReturnError(int net_error) { net_error_ = net_error; }
193
194 void DoAsync(base::SingleThreadTaskRunner* runner) {
195 async_task_runner_ = runner;
196 }
197
198 ~FakeFileStreamReader() override {}
199
200 int Read(net::IOBuffer* buf,
201 int buf_length,
202 const net::CompletionCallback& done) override {
203 if (net_error_ == net::OK) {
204 if (async_task_runner_.get()) {
205 async_task_runner_->PostTask(
206 FROM_HERE,
207 base::Bind(base::IgnoreResult(&FakeFileStreamReader::ReadImpl),
208 base::Unretained(this), scoped_refptr<IOBuffer>(buf),
209 buf_length, done));
210 return net::ERR_IO_PENDING;
211 } else {
212 return ReadImpl(buf, buf_length, net::CompletionCallback());
213 }
214 }
215 if (async_task_runner_.get()) {
216 async_task_runner_->PostTask(
217 FROM_HERE, base::Bind(&net::CompletionCallback::Run,
218 base::Unretained(&done), net_error_));
219 return net::ERR_IO_PENDING;
220 }
221 return net_error_;
222 }
223
224 int64 GetLength(const net::Int64CompletionCallback& size_callback) override {
225 if (net_error_ == net::OK) {
226 if (async_task_runner_.get()) {
227 async_task_runner_->PostTask(
228 FROM_HERE,
229 base::Bind(base::IgnoreResult(&FakeFileStreamReader::GetLengthImpl),
230 base::Unretained(this), size_callback));
231 return net::ERR_IO_PENDING;
232 } else {
233 return GetLengthImpl(net::Int64CompletionCallback());
234 }
235 }
236 if (async_task_runner_.get()) {
237 async_task_runner_->PostTask(
238 FROM_HERE, base::Bind(&net::Int64CompletionCallback::Run,
239 base::Unretained(&size_callback),
240 static_cast<int64_t>(net_error_)));
241 return net::ERR_IO_PENDING;
242 }
243 return net_error_;
244 }
245
246 private:
247 int ReadImpl(scoped_refptr<net::IOBuffer> buf,
248 int buf_length,
249 const net::CompletionCallback& done) {
250 CHECK_GE(buf_length, 0);
251 int length = std::min(buf_length, buffer_->BytesRemaining());
252 memcpy(buf->data(), buffer_->data(), length);
253 buffer_->DidConsume(length);
254 if (done.is_null()) {
255 return length;
256 }
257 done.Run(length);
258 return net::ERR_IO_PENDING;
259 }
260
261 int64 GetLengthImpl(const net::Int64CompletionCallback& size_callback) {
262 if (size_callback.is_null()) {
263 return size_;
264 }
265 size_callback.Run(size_);
266 return net::ERR_IO_PENDING;
267 }
268
269 scoped_refptr<net::DrainableIOBuffer> buffer_;
270 scoped_refptr<base::SingleThreadTaskRunner> async_task_runner_;
271 int net_error_;
272 uint64_t size_;
273
274 DISALLOW_COPY_AND_ASSIGN(FakeFileStreamReader);
275 };
276
277 class MockFileStreamReaderProvider
278 : public BlobReader::FileStreamReaderProvider {
279 public:
280 ~MockFileStreamReaderProvider() override {}
281
282 MOCK_METHOD4(CreateForLocalFile,
283 FileStreamReader*(base::TaskRunner* task_runner,
284 const base::FilePath& file_path,
285 int64_t initial_offset,
286 const base::Time& expected_modification_time));
287 MOCK_METHOD4(CreateFileStreamReader,
288 FileStreamReader*(const GURL& filesystem_url,
289 int64_t offset,
290 int64_t max_bytes_to_read,
291 const base::Time& expected_modification_time));
292 };
293
294 } // namespace
295
296 class BlobReaderTest : public ::testing::Test {
297 public:
298 BlobReaderTest() {}
299 ~BlobReaderTest() override {}
300
301 protected:
302 void InitializeReader(BlobDataBuilder* builder) {
303 blob_handle_ = context_.AddFinishedBlob(builder).Pass();
304 provider_ = new MockFileStreamReaderProvider();
305 scoped_ptr<BlobReader::FileStreamReaderProvider> temp_ptr(provider_);
306 reader_.reset(new BlobReader(blob_handle_.get(), temp_ptr.Pass(),
307 message_loop_.task_runner().get()));
308 }
309
310 // Takes ownership of the file reader (the blob reader takes ownership).
311 void ExpectLocalFileCall(const base::FilePath& file_path,
312 base::Time modification_time,
313 uint64_t initial_offset,
314 FakeFileStreamReader* reader) {
315 EXPECT_CALL(*provider_,
316 CreateForLocalFile(message_loop_.task_runner().get(), file_path,
317 initial_offset, modification_time))
318 .WillOnce(testing::Return(reader));
319 }
320
321 // Takes ownership of the file reader (the blob reader takes ownership).
322 void ExpectFileSystemCall(const GURL& filesystem_url,
323 int64_t offset,
324 int64_t max_bytes_to_read,
325 base::Time expected_modification_time,
326 FakeFileStreamReader* reader) {
327 EXPECT_CALL(*provider_, CreateFileStreamReader(filesystem_url, offset,
328 max_bytes_to_read,
329 expected_modification_time))
330 .WillOnce(testing::Return(reader));
331 }
332
333 void CheckSizeCalculatedSynchronously(size_t expected_size, int async_size) {
334 EXPECT_EQ(-1, async_size);
335 EXPECT_EQ(net::OK, reader_->net_error());
336 EXPECT_EQ(expected_size, reader_->total_size());
337 EXPECT_TRUE(reader_->total_size_calculated());
338 }
339
340 void CheckSizeNotCalculatedYet(int async_size) {
341 EXPECT_EQ(-1, async_size);
342 EXPECT_EQ(net::OK, reader_->net_error());
343 EXPECT_FALSE(reader_->total_size_calculated());
344 }
345
346 void CheckSizeCalculatedAsynchronously(size_t expected_size, int async_size) {
347 EXPECT_EQ(expected_size, static_cast<size_t>(async_size));
348 EXPECT_EQ(net::OK, reader_->net_error());
349 EXPECT_EQ(expected_size, reader_->total_size());
350 EXPECT_TRUE(reader_->total_size_calculated());
351 }
352
353 scoped_refptr<net::IOBuffer> CreateBuffer(uint64_t size) {
354 return scoped_refptr<net::IOBuffer>(
355 new net::IOBuffer(static_cast<size_t>(size)));
356 }
357
358 BlobStorageContext context_;
359 scoped_ptr<BlobDataHandle> blob_handle_;
360 MockFileStreamReaderProvider* provider_ = nullptr;
361 base::MessageLoop message_loop_;
362 scoped_ptr<BlobReader> reader_;
363
364 private:
365 DISALLOW_COPY_AND_ASSIGN(BlobReaderTest);
366 };
367
368 namespace {
369
370 TEST_F(BlobReaderTest, BasicMemory) {
371 BlobDataBuilder b("uuid");
372 const std::string kData("Hello!!!");
373 const size_t kDataSize = 8ul;
374 b.AppendData(kData);
375 this->InitializeReader(&b);
376
377 int calculated_size = -1;
378 EXPECT_FALSE(reader_->total_size_calculated());
379 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
380 &SetValue<int>, &calculated_size)));
381 CheckSizeCalculatedSynchronously(kDataSize, calculated_size);
382
383 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
384
385 int bytes_read = 0;
386 int async_bytes_read = 0;
387 EXPECT_EQ(BlobReader::Status::DONE,
388 reader_->Read(buffer.get(), kDataSize, &bytes_read,
389 base::Bind(&SetValue<int>, &async_bytes_read)));
390 EXPECT_EQ(net::OK, reader_->net_error());
391 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
392 EXPECT_EQ(0, async_bytes_read);
393 EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
394 }
395
396 TEST_F(BlobReaderTest, BasicFile) {
397 BlobDataBuilder b("uuid");
398 const base::FilePath kPath = base::FilePath::FromUTF8Unsafe("/fake/file.txt");
399 const std::string kData = "FileData!!!";
400 const base::Time kTime = base::Time::Now();
401 b.AppendFile(kPath, 0, kData.size(), kTime);
402 this->InitializeReader(&b);
403
404 // Non-async reader.
405 ExpectLocalFileCall(kPath, kTime, 0, new FakeFileStreamReader(kData));
406
407 int calculated_size = -1;
408 EXPECT_FALSE(reader_->total_size_calculated());
409 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
410 &SetValue<int>, &calculated_size)));
411 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
412
413 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
414
415 int bytes_read = 0;
416 int async_bytes_read = 0;
417 EXPECT_EQ(BlobReader::Status::DONE,
418 reader_->Read(buffer.get(), kData.size(), &bytes_read,
419 base::Bind(&SetValue<int>, &async_bytes_read)));
420 EXPECT_EQ(net::OK, reader_->net_error());
421 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
422 EXPECT_EQ(0, async_bytes_read);
423 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
424 }
425
426 TEST_F(BlobReaderTest, BasicFileSystem) {
427 BlobDataBuilder b("uuid");
428 const GURL kURL("file://test_file/here.txt");
429 const std::string kData = "FileData!!!";
430 const base::Time kTime = base::Time::Now();
431 b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
432 this->InitializeReader(&b);
433
434 // Non-async reader.
435 ExpectFileSystemCall(kURL, 0, kData.size(), kTime,
436 new FakeFileStreamReader(kData));
437
438 int calculated_size = -1;
439 EXPECT_FALSE(reader_->total_size_calculated());
440 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
441 &SetValue<int>, &calculated_size)));
442 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
443
444 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
445
446 int bytes_read = 0;
447 int async_bytes_read = 0;
448 EXPECT_EQ(BlobReader::Status::DONE,
449 reader_->Read(buffer.get(), kData.size(), &bytes_read,
450 base::Bind(&SetValue<int>, &async_bytes_read)));
451 EXPECT_EQ(net::OK, reader_->net_error());
452 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
453 EXPECT_EQ(0, async_bytes_read);
454 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
455 }
456
457 TEST_F(BlobReaderTest, BasicDiskCache) {
458 scoped_ptr<disk_cache::Backend> cache =
459 CreateInMemoryDiskCache(message_loop_.task_runner());
460 ASSERT_TRUE(cache);
461
462 BlobDataBuilder b("uuid");
463 const std::string kData = "Test Blob Data";
464 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
465 new EmptyDataHandle();
466 disk_cache::ScopedEntryPtr entry =
467 CreateDiskCacheEntry(cache.get(), "test entry", kData);
468 b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
469 this->InitializeReader(&b);
470
471 int calculated_size = -1;
472 EXPECT_FALSE(reader_->total_size_calculated());
473 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
474 &SetValue<int>, &calculated_size)));
475 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
476
477 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
478
479 int bytes_read = 0;
480 int async_bytes_read = 0;
481 EXPECT_EQ(BlobReader::Status::DONE,
482 reader_->Read(buffer.get(), kData.size(), &bytes_read,
483 base::Bind(&SetValue<int>, &async_bytes_read)));
484 EXPECT_EQ(net::OK, reader_->net_error());
485 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
486 EXPECT_EQ(0, async_bytes_read);
487 EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
488 }
489
490 TEST_F(BlobReaderTest, BufferLargerThanMemory) {
491 BlobDataBuilder b("uuid");
492 const std::string kData("Hello!!!");
493 const size_t kDataSize = 8ul;
494 const size_t kBufferSize = 10ul;
495 b.AppendData(kData);
496 this->InitializeReader(&b);
497
498 int calculated_size = -1;
499 EXPECT_FALSE(reader_->total_size_calculated());
500 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
501 &SetValue<int>, &calculated_size)));
502 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
503
504 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
505
506 int bytes_read = 0;
507 int async_bytes_read = 0;
508 EXPECT_EQ(BlobReader::Status::DONE,
509 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
510 base::Bind(&SetValue<int>, &async_bytes_read)));
511 EXPECT_EQ(net::OK, reader_->net_error());
512 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
513 EXPECT_EQ(0, async_bytes_read);
514 EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
515 }
516
517 TEST_F(BlobReaderTest, MemoryRange) {
518 BlobDataBuilder b("uuid");
519 const std::string kData("Hello!!!");
520 const size_t kDataSize = 8ul;
521 const size_t kSeekOffset = 2ul;
522 const uint64_t kReadLength = 4ull;
523 b.AppendData(kData);
524 this->InitializeReader(&b);
525
526 int calculated_size = -1;
527 EXPECT_FALSE(reader_->total_size_calculated());
528 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
529 &SetValue<int>, &calculated_size)));
530 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
531
532 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
533
534 reader_->SetReadRange(kSeekOffset, kReadLength);
535 int bytes_read = 0;
536 int async_bytes_read = 0;
537 EXPECT_EQ(BlobReader::Status::DONE,
538 reader_->Read(buffer.get(), kDataSize - kSeekOffset, &bytes_read,
539 base::Bind(&SetValue<int>, &async_bytes_read)));
540 EXPECT_EQ(net::OK, reader_->net_error());
541 EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
542 EXPECT_EQ(0, async_bytes_read);
543 EXPECT_EQ(0, memcmp(buffer->data(), "llo!", kReadLength));
544 }
545
546 TEST_F(BlobReaderTest, BufferSmallerThanMemory) {
547 BlobDataBuilder b("uuid");
548 const std::string kData("Hello!!!");
549 const size_t kBufferSize = 4ul;
550 b.AppendData(kData);
551 this->InitializeReader(&b);
552
553 int calculated_size = -1;
554 EXPECT_FALSE(reader_->total_size_calculated());
555 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
556 &SetValue<int>, &calculated_size)));
557 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
558
559 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
560
561 int bytes_read = 0;
562 int async_bytes_read = 0;
563 EXPECT_EQ(BlobReader::Status::DONE,
564 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
565 base::Bind(&SetValue<int>, &async_bytes_read)));
566 EXPECT_EQ(net::OK, reader_->net_error());
567 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
568 EXPECT_EQ(0, async_bytes_read);
569 EXPECT_EQ(0, memcmp(buffer->data(), "Hell", kBufferSize));
570
571 bytes_read = 0;
572 EXPECT_EQ(BlobReader::Status::DONE,
573 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
574 base::Bind(&SetValue<int>, &async_bytes_read)));
575 EXPECT_EQ(net::OK, reader_->net_error());
576 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
577 EXPECT_EQ(0, async_bytes_read);
578 EXPECT_EQ(0, memcmp(buffer->data(), "o!!!", kBufferSize));
579 }
580
581 TEST_F(BlobReaderTest, SegmentedBufferAndMemory) {
582 BlobDataBuilder b("uuid");
583 const size_t kNumItems = 10;
584 const size_t kItemSize = 6;
585 const size_t kBufferSize = 10;
586 const size_t kTotalSize = kNumItems * kItemSize;
587 char current_value = 0;
588 for (size_t i = 0; i < kNumItems; i++) {
589 char buf[kItemSize];
590 for (size_t j = 0; j < kItemSize; j++) {
591 buf[j] = current_value++;
592 }
593 b.AppendData(buf, kItemSize);
594 }
595 this->InitializeReader(&b);
596
597 int calculated_size = -1;
598 EXPECT_FALSE(reader_->total_size_calculated());
599 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
600 &SetValue<int>, &calculated_size)));
601 CheckSizeCalculatedSynchronously(kTotalSize, calculated_size);
602
603 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
604
605 current_value = 0;
606 for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
607 int bytes_read = 0;
608 int async_bytes_read = 0;
609 EXPECT_EQ(BlobReader::Status::DONE,
610 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
611 base::Bind(&SetValue<int>, &async_bytes_read)));
612 EXPECT_EQ(net::OK, reader_->net_error());
613 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
614 EXPECT_EQ(0, async_bytes_read);
615 for (size_t j = 0; j < kBufferSize; j++) {
616 EXPECT_EQ(current_value, buffer->data()[j]);
617 current_value++;
618 }
619 }
620 }
621
622 TEST_F(BlobReaderTest, FileAsync) {
623 BlobDataBuilder b("uuid");
624 const base::FilePath kPath = base::FilePath::FromUTF8Unsafe("/fake/file.txt");
625 const std::string kData = "FileData!!!";
626 const base::Time kTime = base::Time::Now();
627 b.AppendFile(kPath, 0, kData.size(), kTime);
628 this->InitializeReader(&b);
629
630 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
631 reader->DoAsync(message_loop_.task_runner().get());
632
633 ExpectLocalFileCall(kPath, kTime, 0, reader.release());
634
635 int calculated_size = -1;
636 EXPECT_FALSE(reader_->total_size_calculated());
637 EXPECT_EQ(
638 BlobReader::Status::PENDING_IO,
639 reader_->CalculateSize(base::Bind(&SetValue<int>, &calculated_size)));
640 CheckSizeNotCalculatedYet(calculated_size);
641 message_loop_.RunUntilIdle();
642 CheckSizeCalculatedAsynchronously(kData.size(), calculated_size);
643
644 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
645
646 int bytes_read = 0;
647 int async_bytes_read = 0;
648 EXPECT_EQ(BlobReader::Status::PENDING_IO,
649 reader_->Read(buffer.get(), kData.size(), &bytes_read,
650 base::Bind(&SetValue<int>, &async_bytes_read)));
651 message_loop_.RunUntilIdle();
652 EXPECT_EQ(net::OK, reader_->net_error());
653 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
654 EXPECT_EQ(0, bytes_read);
655 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
656 }
657
658 TEST_F(BlobReaderTest, FileSystemAsync) {
659 BlobDataBuilder b("uuid");
660 const GURL kURL("file://test_file/here.txt");
661 const std::string kData = "FileData!!!";
662 const base::Time kTime = base::Time::Now();
663 b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
664 this->InitializeReader(&b);
665
666 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
667 reader->DoAsync(message_loop_.task_runner().get());
668
669 ExpectFileSystemCall(kURL, 0, kData.size(), kTime, reader.release());
670
671 int calculated_size = -1;
672 EXPECT_FALSE(reader_->total_size_calculated());
673 EXPECT_EQ(
674 BlobReader::Status::PENDING_IO,
675 reader_->CalculateSize(base::Bind(&SetValue<int>, &calculated_size)));
676 CheckSizeNotCalculatedYet(calculated_size);
677 message_loop_.RunUntilIdle();
678 CheckSizeCalculatedAsynchronously(kData.size(), calculated_size);
679
680 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
681
682 int bytes_read = 0;
683 int async_bytes_read = 0;
684 EXPECT_EQ(BlobReader::Status::PENDING_IO,
685 reader_->Read(buffer.get(), kData.size(), &bytes_read,
686 base::Bind(&SetValue<int>, &async_bytes_read)));
687 message_loop_.RunUntilIdle();
688 EXPECT_EQ(net::OK, reader_->net_error());
689 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
690 EXPECT_EQ(0, bytes_read);
691 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
692 }
693
694 TEST_F(BlobReaderTest, DiskCacheAsync) {
695 scoped_ptr<disk_cache::Backend> cache =
696 CreateInMemoryDiskCache(message_loop_.task_runner());
697 ASSERT_TRUE(cache);
698
699 BlobDataBuilder b("uuid");
700 const std::string kData = "Test Blob Data";
701 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
702 new EmptyDataHandle();
703 scoped_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry(
704 CreateDiskCacheEntry(cache.get(), "test entry", kData).Pass()));
705 b.AppendDiskCacheEntry(data_handle, delayed_read_entry.get(),
706 kTestDiskCacheStreamIndex);
707 this->InitializeReader(&b);
708
709 int calculated_size = -1;
710 EXPECT_FALSE(reader_->total_size_calculated());
711 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
712 &SetValue<int>, &calculated_size)));
713 CheckSizeCalculatedSynchronously(kData.size(), calculated_size);
714
715 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
716
717 int bytes_read = 0;
718 int async_bytes_read = 0;
719 EXPECT_EQ(BlobReader::Status::PENDING_IO,
720 reader_->Read(buffer.get(), kData.size(), &bytes_read,
721 base::Bind(&SetValue<int>, &async_bytes_read)));
722 EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
723 delayed_read_entry->RunPendingReadCallbacks();
724 EXPECT_EQ(net::OK, reader_->net_error());
725 EXPECT_EQ(0, bytes_read);
726 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
727 EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
728 }
729
730 TEST_F(BlobReaderTest, FileRange) {
731 BlobDataBuilder b("uuid");
732 const base::FilePath kPath = base::FilePath::FromUTF8Unsafe("/fake/file.txt");
733 // We check the offset in the ExpectLocalFileCall mock.
734 const std::string kRangeData = "leD";
735 const std::string kData = "FileData!!!";
736 const uint64_t kOffset = 2;
737 const uint64_t kReadLength = 3;
738 const base::Time kTime = base::Time::Now();
739 b.AppendFile(kPath, 0, kData.size(), kTime);
740 this->InitializeReader(&b);
741
742 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
743 reader->DoAsync(message_loop_.task_runner().get());
744 ExpectLocalFileCall(kPath, kTime, 0, reader.release());
745
746 // We create the reader again with the offset after the seek.
747 reader.reset(new FakeFileStreamReader(kRangeData));
748 reader->DoAsync(message_loop_.task_runner().get());
749 ExpectLocalFileCall(kPath, kTime, kOffset, reader.release());
750
751 int calculated_size = -1;
752 EXPECT_EQ(
753 BlobReader::Status::PENDING_IO,
754 reader_->CalculateSize(base::Bind(&SetValue<int>, &calculated_size)));
755 message_loop_.RunUntilIdle();
756
757 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
758 EXPECT_EQ(BlobReader::Status::DONE,
759 reader_->SetReadRange(kOffset, kReadLength));
760
761 int bytes_read = 0;
762 int async_bytes_read = 0;
763 EXPECT_EQ(BlobReader::Status::PENDING_IO,
764 reader_->Read(buffer.get(), kReadLength, &bytes_read,
765 base::Bind(&SetValue<int>, &async_bytes_read)));
766 message_loop_.RunUntilIdle();
767 EXPECT_EQ(net::OK, reader_->net_error());
768 EXPECT_EQ(kReadLength, static_cast<size_t>(async_bytes_read));
769 EXPECT_EQ(0, bytes_read);
770 EXPECT_EQ(0, memcmp(buffer->data(), "leD", kReadLength));
771 }
772
773 TEST_F(BlobReaderTest, DiskCacheRange) {
774 scoped_ptr<disk_cache::Backend> cache =
775 CreateInMemoryDiskCache(message_loop_.task_runner());
776 ASSERT_TRUE(cache);
777
778 BlobDataBuilder b("uuid");
779 const std::string kData = "Test Blob Data";
780 const uint64_t kOffset = 2;
781 const uint64_t kReadLength = 3;
782 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
783 new EmptyDataHandle();
784 disk_cache::ScopedEntryPtr entry =
785 CreateDiskCacheEntry(cache.get(), "test entry", kData);
786 b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
787 this->InitializeReader(&b);
788
789 int calculated_size = -1;
790 EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(
791 &SetValue<int>, &calculated_size)));
792
793 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
794 EXPECT_EQ(BlobReader::Status::DONE,
795 reader_->SetReadRange(kOffset, kReadLength));
796
797 int bytes_read = 0;
798 int async_bytes_read = 0;
799 EXPECT_EQ(BlobReader::Status::DONE,
800 reader_->Read(buffer.get(), kReadLength, &bytes_read,
801 base::Bind(&SetValue<int>, &async_bytes_read)));
802 EXPECT_EQ(net::OK, reader_->net_error());
803 EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
804 EXPECT_EQ(0, async_bytes_read);
805 EXPECT_EQ(0, memcmp(buffer->data(), "st ", kReadLength));
806 }
807
808 TEST_F(BlobReaderTest, FileSomeAsyncSegmentedOffsetsUnknownSizes) {
809 // This tests includes:
810 // * Unknown file sizes (item length of uint64::max) for every other item.
811 // * Offsets for every 3rd file item.
812 // * Non-async reader for every 4th file item.
813 BlobDataBuilder b("uuid");
814 const base::FilePath kPathBase =
815 base::FilePath::FromUTF8Unsafe("/fake/file.txt");
816 const base::Time kTime = base::Time::Now();
817 const size_t kNumItems = 10;
818 const size_t kItemSize = 6;
819 const size_t kBufferSize = 10;
820 const size_t kTotalSize = kNumItems * kItemSize;
821 char current_value = 0;
822 // Create blob and reader.
823 for (size_t i = 0; i < kNumItems; i++) {
824 current_value += kItemSize;
825 base::FilePath path =
826 kPathBase.Append(base::StringPrintf("%d", current_value));
827 uint64_t offset = i % 3 == 0 ? 1 : 0;
828 uint64_t size =
829 i % 2 == 0 ? kItemSize : std::numeric_limits<uint64_t>::max();
830 b.AppendFile(path, offset, size, kTime);
831 }
832 this->InitializeReader(&b);
833
834 // Set expectations.
835 current_value = 0;
836 for (size_t i = 0; i < kNumItems; i++) {
837 uint64_t offset = i % 3 == 0 ? 1 : 0;
838 char buf[kItemSize + offset];
839 if (offset > 0) {
840 memset(buf, 7, offset);
841 }
842 for (size_t j = 0; j < kItemSize; j++) {
843 buf[j + offset] = current_value++;
844 }
845 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(
846 std::string(buf + offset, kItemSize), kItemSize + offset));
847 if (i % 4 != 0) {
848 reader->DoAsync(message_loop_.task_runner().get());
849 }
850 base::FilePath path =
851 kPathBase.Append(base::StringPrintf("%d", current_value));
852 ExpectLocalFileCall(path, kTime, offset, reader.release());
853 }
854
855 int calculated_size = -1;
856 EXPECT_FALSE(reader_->total_size_calculated());
857 EXPECT_EQ(
858 BlobReader::Status::PENDING_IO,
859 reader_->CalculateSize(base::Bind(&SetValue<int>, &calculated_size)));
860 CheckSizeNotCalculatedYet(calculated_size);
861 message_loop_.RunUntilIdle();
862 CheckSizeCalculatedAsynchronously(kTotalSize, calculated_size);
863
864 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
865
866 current_value = 0;
867 for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
868 int bytes_read = 0;
869 int async_bytes_read = 0;
870 EXPECT_EQ(BlobReader::Status::PENDING_IO,
871 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
872 base::Bind(&SetValue<int>, &async_bytes_read)));
873 message_loop_.RunUntilIdle();
874 EXPECT_EQ(net::OK, reader_->net_error());
875 EXPECT_EQ(0, bytes_read);
876 EXPECT_EQ(kBufferSize, static_cast<size_t>(async_bytes_read));
877 for (size_t j = 0; j < kBufferSize; j++) {
878 EXPECT_EQ(current_value, buffer->data()[j]);
879 current_value++;
880 }
881 }
882 }
883
884 TEST_F(BlobReaderTest, MixedContent) {
885 // Includes data, a file, and a disk cache entry.
886 scoped_ptr<disk_cache::Backend> cache =
887 CreateInMemoryDiskCache(message_loop_.task_runner());
888 ASSERT_TRUE(cache);
889
890 BlobDataBuilder b("uuid");
891 const std::string kData1("Hello ");
892 const std::string kData2("there. ");
893 const std::string kData3("This ");
894 const std::string kData4("is multi-content.");
895 const uint64_t kDataSize = 35;
896
897 const base::Time kTime = base::Time::Now();
898 const base::FilePath kData1Path =
899 base::FilePath::FromUTF8Unsafe("/fake/file.txt");
900
901 disk_cache::ScopedEntryPtr entry3 =
902 CreateDiskCacheEntry(cache.get(), "test entry", kData3);
903
904 b.AppendFile(kData1Path, 0, kData1.size(), kTime);
905 b.AppendData(kData2);
906 b.AppendDiskCacheEntry(
907 scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()),
908 entry3.get(), kTestDiskCacheStreamIndex);
909 b.AppendData(kData4);
910
911 this->InitializeReader(&b);
912
913 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData1));
914 reader->DoAsync(message_loop_.task_runner().get());
915 ExpectLocalFileCall(kData1Path, kTime, 0, reader.release());
916
917 int calculated_size = -1;
918 EXPECT_FALSE(reader_->total_size_calculated());
919 EXPECT_EQ(
920 BlobReader::Status::PENDING_IO,
921 reader_->CalculateSize(base::Bind(&SetValue<int>, &calculated_size)));
922 CheckSizeNotCalculatedYet(calculated_size);
923 message_loop_.RunUntilIdle();
924 CheckSizeCalculatedAsynchronously(kDataSize, calculated_size);
925
926 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
927
928 int bytes_read = 0;
929 int async_bytes_read = 0;
930 EXPECT_EQ(BlobReader::Status::PENDING_IO,
931 reader_->Read(buffer.get(), kDataSize, &bytes_read,
932 base::Bind(&SetValue<int>, &async_bytes_read)));
933 EXPECT_EQ(0, async_bytes_read);
934 message_loop_.RunUntilIdle();
935 EXPECT_EQ(net::OK, reader_->net_error());
936 EXPECT_EQ(0, bytes_read);
937 EXPECT_EQ(kDataSize, static_cast<size_t>(async_bytes_read));
938 EXPECT_EQ(0, memcmp(buffer->data(), "Hello there. This is multi-content.",
939 kDataSize));
940 }
941
942 } // namespace
943 } // namespace storage
OLDNEW
« no previous file with comments | « no previous file | content/browser/fileapi/blob_url_request_job_unittest.cc » ('j') | net/base/upload_element_reader.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698