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

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

Issue 2368913003: Populate storage_unittests target. (Closed)
Patch Set: Removed unnecessary include from storage/browser/blob/blob_storage_context_unittest.cc. Created 4 years, 2 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 <stddef.h>
6 #include <stdint.h>
7 #include <string.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback.h"
15 #include "base/files/file_path.h"
16 #include "base/location.h"
17 #include "base/macros.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/message_loop/message_loop.h"
20 #include "base/run_loop.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/task_runner.h"
23 #include "base/time/time.h"
24 #include "content/public/test/async_file_test_helper.h"
25 #include "content/public/test/test_file_system_context.h"
26 #include "net/base/completion_callback.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/test_completion_callback.h"
30 #include "net/disk_cache/disk_cache.h"
31 #include "storage/browser/blob/blob_data_builder.h"
32 #include "storage/browser/blob/blob_data_handle.h"
33 #include "storage/browser/blob/blob_reader.h"
34 #include "storage/browser/blob/blob_storage_context.h"
35 #include "storage/browser/fileapi/file_stream_reader.h"
36 #include "storage/browser/fileapi/file_system_context.h"
37 #include "storage/browser/fileapi/file_system_file_util.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40 #include "url/gurl.h"
41
42 using base::FilePath;
43 using content::AsyncFileTestHelper;
44 using net::DrainableIOBuffer;
45 using net::IOBuffer;
46
47 namespace storage {
48 namespace {
49
50 const int kTestDiskCacheStreamIndex = 0;
51 const int kTestDiskCacheSideStreamIndex = 1;
52
53 // Our disk cache tests don't need a real data handle since the tests themselves
54 // scope the disk cache and entries.
55 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
56 private:
57 ~EmptyDataHandle() override {}
58 };
59
60 // A disk_cache::Entry that arbitrarily delays the completion of a read
61 // operation to allow testing some races without flake. This is particularly
62 // relevant in this unit test, which uses the always-synchronous MEMORY_CACHE.
63 class DelayedReadEntry : public disk_cache::Entry {
64 public:
65 explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry)
66 : entry_(std::move(entry)) {}
67 ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); }
68
69 bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); }
70
71 void RunPendingReadCallbacks() {
72 std::vector<base::Callback<void(void)>> callbacks;
73 pending_read_callbacks_.swap(callbacks);
74 for (const auto& callback : callbacks)
75 callback.Run();
76 }
77
78 // From disk_cache::Entry:
79 void Doom() override { entry_->Doom(); }
80
81 void Close() override { delete this; } // Note this is required by the API.
82
83 std::string GetKey() const override { return entry_->GetKey(); }
84
85 base::Time GetLastUsed() const override { return entry_->GetLastUsed(); }
86
87 base::Time GetLastModified() const override {
88 return entry_->GetLastModified();
89 }
90
91 int32_t GetDataSize(int index) const override {
92 return entry_->GetDataSize(index);
93 }
94
95 int ReadData(int index,
96 int offset,
97 IOBuffer* buf,
98 int buf_len,
99 const CompletionCallback& original_callback) override {
100 net::TestCompletionCallback callback;
101 int rv = entry_->ReadData(index, offset, buf, buf_len, callback.callback());
102 DCHECK_NE(rv, net::ERR_IO_PENDING)
103 << "Test expects to use a MEMORY_CACHE instance, which is synchronous.";
104 pending_read_callbacks_.push_back(base::Bind(original_callback, rv));
105 return net::ERR_IO_PENDING;
106 }
107
108 int WriteData(int index,
109 int offset,
110 IOBuffer* buf,
111 int buf_len,
112 const CompletionCallback& callback,
113 bool truncate) override {
114 return entry_->WriteData(index, offset, buf, buf_len, callback, truncate);
115 }
116
117 int ReadSparseData(int64_t offset,
118 IOBuffer* buf,
119 int buf_len,
120 const CompletionCallback& callback) override {
121 return entry_->ReadSparseData(offset, buf, buf_len, callback);
122 }
123
124 int WriteSparseData(int64_t offset,
125 IOBuffer* buf,
126 int buf_len,
127 const CompletionCallback& callback) override {
128 return entry_->WriteSparseData(offset, buf, buf_len, callback);
129 }
130
131 int GetAvailableRange(int64_t offset,
132 int len,
133 int64_t* start,
134 const CompletionCallback& callback) override {
135 return entry_->GetAvailableRange(offset, len, start, callback);
136 }
137
138 bool CouldBeSparse() const override { return entry_->CouldBeSparse(); }
139
140 void CancelSparseIO() override { entry_->CancelSparseIO(); }
141
142 int ReadyForSparseIO(const CompletionCallback& callback) override {
143 return entry_->ReadyForSparseIO(callback);
144 }
145
146 private:
147 disk_cache::ScopedEntryPtr entry_;
148 std::vector<base::Callback<void(void)>> pending_read_callbacks_;
149 };
150
151 std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache(
152 const scoped_refptr<base::SingleThreadTaskRunner>& thread) {
153 std::unique_ptr<disk_cache::Backend> cache;
154 net::TestCompletionCallback callback;
155 int rv = disk_cache::CreateCacheBackend(
156 net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, FilePath(), 0, false,
157 thread, nullptr, &cache, callback.callback());
158 EXPECT_EQ(net::OK, callback.GetResult(rv));
159
160 return cache;
161 }
162
163 disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
164 const char* key,
165 const std::string& data) {
166 disk_cache::Entry* temp_entry = nullptr;
167 net::TestCompletionCallback callback;
168 int rv = cache->CreateEntry(key, &temp_entry, callback.callback());
169 if (callback.GetResult(rv) != net::OK)
170 return nullptr;
171 disk_cache::ScopedEntryPtr entry(temp_entry);
172
173 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data);
174 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
175 iobuffer->size(), callback.callback(), false);
176 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
177 return entry;
178 }
179
180 disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
181 disk_cache::Backend* cache,
182 const char* key,
183 const std::string& data,
184 const std::string& side_data) {
185 disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data);
186 scoped_refptr<net::StringIOBuffer> iobuffer =
187 new net::StringIOBuffer(side_data);
188 net::TestCompletionCallback callback;
189 int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(),
190 iobuffer->size(), callback.callback(), false);
191 EXPECT_EQ(static_cast<int>(side_data.size()), callback.GetResult(rv));
192 return entry;
193 }
194
195 template <typename T>
196 void SetValue(T* address, T value) {
197 *address = value;
198 }
199
200 class FakeFileStreamReader : public FileStreamReader {
201 public:
202 explicit FakeFileStreamReader(const std::string& contents)
203 : buffer_(new DrainableIOBuffer(
204 new net::StringIOBuffer(
205 std::unique_ptr<std::string>(new std::string(contents))),
206 contents.size())),
207 net_error_(net::OK),
208 size_(contents.size()) {}
209 FakeFileStreamReader(const std::string& contents, uint64_t size)
210 : buffer_(new DrainableIOBuffer(
211 new net::StringIOBuffer(
212 std::unique_ptr<std::string>(new std::string(contents))),
213 contents.size())),
214 net_error_(net::OK),
215 size_(size) {}
216
217 ~FakeFileStreamReader() override {}
218
219 void SetReturnError(int net_error) { net_error_ = net_error; }
220
221 void SetAsyncRunner(base::SingleThreadTaskRunner* runner) {
222 async_task_runner_ = runner;
223 }
224
225 int Read(net::IOBuffer* buf,
226 int buf_length,
227 const net::CompletionCallback& done) override {
228 DCHECK(buf);
229 // When async_task_runner_ is not set, return synchronously.
230 if (!async_task_runner_.get()) {
231 if (net_error_ == net::OK) {
232 return ReadImpl(buf, buf_length, net::CompletionCallback());
233 } else {
234 return net_error_;
235 }
236 }
237
238 // Otherwise always return asynchronously.
239 if (net_error_ == net::OK) {
240 async_task_runner_->PostTask(
241 FROM_HERE,
242 base::Bind(base::IgnoreResult(&FakeFileStreamReader::ReadImpl),
243 base::Unretained(this), make_scoped_refptr(buf),
244 buf_length, done));
245 } else {
246 async_task_runner_->PostTask(FROM_HERE, base::Bind(done, net_error_));
247 }
248 return net::ERR_IO_PENDING;
249 }
250
251 int64_t GetLength(
252 const net::Int64CompletionCallback& size_callback) override {
253 // When async_task_runner_ is not set, return synchronously.
254 if (!async_task_runner_.get()) {
255 if (net_error_ == net::OK) {
256 return size_;
257 } else {
258 return net_error_;
259 }
260 }
261 if (net_error_ == net::OK) {
262 async_task_runner_->PostTask(FROM_HERE, base::Bind(size_callback, size_));
263 } else {
264 async_task_runner_->PostTask(
265 FROM_HERE,
266 base::Bind(size_callback, static_cast<int64_t>(net_error_)));
267 }
268 return net::ERR_IO_PENDING;
269 }
270
271 private:
272 int ReadImpl(scoped_refptr<net::IOBuffer> buf,
273 int buf_length,
274 const net::CompletionCallback& done) {
275 CHECK_GE(buf_length, 0);
276 int length = std::min(buf_length, buffer_->BytesRemaining());
277 memcpy(buf->data(), buffer_->data(), length);
278 buffer_->DidConsume(length);
279 if (done.is_null()) {
280 return length;
281 }
282 done.Run(length);
283 return net::ERR_IO_PENDING;
284 }
285
286 scoped_refptr<net::DrainableIOBuffer> buffer_;
287 scoped_refptr<base::SingleThreadTaskRunner> async_task_runner_;
288 int net_error_;
289 uint64_t size_;
290
291 DISALLOW_COPY_AND_ASSIGN(FakeFileStreamReader);
292 };
293
294 class MockFileStreamReaderProvider
295 : public BlobReader::FileStreamReaderProvider {
296 public:
297 ~MockFileStreamReaderProvider() override {}
298
299 MOCK_METHOD4(CreateForLocalFileMock,
300 FileStreamReader*(base::TaskRunner* task_runner,
301 const FilePath& file_path,
302 int64_t initial_offset,
303 const base::Time& expected_modification_time));
304 MOCK_METHOD4(CreateFileStreamReaderMock,
305 FileStreamReader*(const GURL& filesystem_url,
306 int64_t offset,
307 int64_t max_bytes_to_read,
308 const base::Time& expected_modification_time));
309 // Since we're returning a move-only type, we have to do some delegation for
310 // gmock.
311 std::unique_ptr<FileStreamReader> CreateForLocalFile(
312 base::TaskRunner* task_runner,
313 const base::FilePath& file_path,
314 int64_t initial_offset,
315 const base::Time& expected_modification_time) override {
316 return base::WrapUnique(CreateForLocalFileMock(
317 task_runner, file_path, initial_offset, expected_modification_time));
318 }
319
320 std::unique_ptr<FileStreamReader> CreateFileStreamReader(
321 const GURL& filesystem_url,
322 int64_t offset,
323 int64_t max_bytes_to_read,
324 const base::Time& expected_modification_time) override {
325 return base::WrapUnique(CreateFileStreamReaderMock(
326 filesystem_url, offset, max_bytes_to_read, expected_modification_time));
327 }
328 };
329
330 } // namespace
331
332 class BlobReaderTest : public ::testing::Test {
333 public:
334 BlobReaderTest() {}
335 ~BlobReaderTest() override {}
336
337 void TearDown() override {
338 reader_.reset();
339 blob_handle_.reset();
340 base::RunLoop().RunUntilIdle();
341 base::RunLoop().RunUntilIdle();
342 }
343
344 protected:
345 void InitializeReader(BlobDataBuilder* builder) {
346 blob_handle_ = builder ? context_.AddFinishedBlob(builder) : nullptr;
347 provider_ = new MockFileStreamReaderProvider();
348 reader_.reset(new BlobReader(blob_handle_.get(),
349 base::WrapUnique(provider_),
350 message_loop_.task_runner().get()));
351 }
352
353 // Takes ownership of the file reader (the blob reader takes ownership).
354 void ExpectLocalFileCall(const FilePath& file_path,
355 base::Time modification_time,
356 uint64_t initial_offset,
357 FakeFileStreamReader* reader) {
358 EXPECT_CALL(*provider_, CreateForLocalFileMock(
359 message_loop_.task_runner().get(), file_path,
360 initial_offset, modification_time))
361 .WillOnce(testing::Return(reader));
362 }
363
364 // Takes ownership of the file reader (the blob reader takes ownership).
365 void ExpectFileSystemCall(const GURL& filesystem_url,
366 int64_t offset,
367 int64_t max_bytes_to_read,
368 base::Time expected_modification_time,
369 FakeFileStreamReader* reader) {
370 EXPECT_CALL(*provider_, CreateFileStreamReaderMock(
371 filesystem_url, offset, max_bytes_to_read,
372 expected_modification_time))
373 .WillOnce(testing::Return(reader));
374 }
375
376 void CheckSizeCalculatedSynchronously(size_t expected_size, int async_size) {
377 EXPECT_EQ(-1, async_size);
378 EXPECT_EQ(net::OK, reader_->net_error());
379 EXPECT_EQ(expected_size, reader_->total_size());
380 EXPECT_TRUE(reader_->total_size_calculated());
381 }
382
383 void CheckSizeNotCalculatedYet(int async_size) {
384 EXPECT_EQ(-1, async_size);
385 EXPECT_EQ(net::OK, reader_->net_error());
386 EXPECT_FALSE(reader_->total_size_calculated());
387 }
388
389 void CheckSizeCalculatedAsynchronously(size_t expected_size,
390 int async_result) {
391 EXPECT_EQ(net::OK, async_result);
392 EXPECT_EQ(net::OK, reader_->net_error());
393 EXPECT_EQ(expected_size, reader_->total_size());
394 EXPECT_TRUE(reader_->total_size_calculated());
395 }
396
397 scoped_refptr<net::IOBuffer> CreateBuffer(uint64_t size) {
398 return scoped_refptr<net::IOBuffer>(
399 new net::IOBuffer(static_cast<size_t>(size)));
400 }
401
402 bool IsReaderTotalSizeCalculated() {
403 return reader_->total_size_calculated();
404 }
405
406 BlobStorageContext context_;
407 std::unique_ptr<BlobDataHandle> blob_handle_;
408 MockFileStreamReaderProvider* provider_ = nullptr;
409 base::MessageLoop message_loop_;
410 std::unique_ptr<BlobReader> reader_;
411
412 private:
413 DISALLOW_COPY_AND_ASSIGN(BlobReaderTest);
414 };
415
416 TEST_F(BlobReaderTest, BasicMemory) {
417 BlobDataBuilder b("uuid");
418 const std::string kData("Hello!!!");
419 const size_t kDataSize = 8ul;
420 b.AppendData(kData);
421 this->InitializeReader(&b);
422
423 int size_result = -1;
424 EXPECT_FALSE(IsReaderTotalSizeCalculated());
425 EXPECT_EQ(BlobReader::Status::DONE,
426 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
427 EXPECT_TRUE(reader_->IsInMemory());
428 CheckSizeCalculatedSynchronously(kDataSize, size_result);
429
430 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
431
432 int bytes_read = 0;
433 int async_bytes_read = 0;
434 EXPECT_EQ(BlobReader::Status::DONE,
435 reader_->Read(buffer.get(), kDataSize, &bytes_read,
436 base::Bind(&SetValue<int>, &async_bytes_read)));
437 EXPECT_EQ(net::OK, reader_->net_error());
438 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
439 EXPECT_EQ(0, async_bytes_read);
440 EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
441 }
442
443 TEST_F(BlobReaderTest, BasicFile) {
444 BlobDataBuilder b("uuid");
445 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
446 const std::string kData = "FileData!!!";
447 const base::Time kTime = base::Time::Now();
448 b.AppendFile(kPath, 0, kData.size(), kTime);
449 this->InitializeReader(&b);
450
451 // Non-async reader.
452 ExpectLocalFileCall(kPath, kTime, 0, new FakeFileStreamReader(kData));
453
454 int size_result = -1;
455 EXPECT_FALSE(IsReaderTotalSizeCalculated());
456 EXPECT_EQ(BlobReader::Status::DONE,
457 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
458 EXPECT_FALSE(reader_->IsInMemory());
459 CheckSizeCalculatedSynchronously(kData.size(), size_result);
460
461 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
462
463 int bytes_read = 0;
464 int async_bytes_read = 0;
465 EXPECT_EQ(BlobReader::Status::DONE,
466 reader_->Read(buffer.get(), kData.size(), &bytes_read,
467 base::Bind(&SetValue<int>, &async_bytes_read)));
468 EXPECT_EQ(net::OK, reader_->net_error());
469 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
470 EXPECT_EQ(0, async_bytes_read);
471 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
472 }
473
474 TEST_F(BlobReaderTest, BasicFileSystem) {
475 BlobDataBuilder b("uuid");
476 const GURL kURL("file://test_file/here.txt");
477 const std::string kData = "FileData!!!";
478 const base::Time kTime = base::Time::Now();
479 b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
480 this->InitializeReader(&b);
481 // Non-async reader.
482 ExpectFileSystemCall(kURL, 0, kData.size(), kTime,
483 new FakeFileStreamReader(kData));
484
485 int size_result = -1;
486 EXPECT_FALSE(IsReaderTotalSizeCalculated());
487 EXPECT_EQ(BlobReader::Status::DONE,
488 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
489 EXPECT_FALSE(reader_->IsInMemory());
490
491 CheckSizeCalculatedSynchronously(kData.size(), size_result);
492
493 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
494
495 int bytes_read = 0;
496 int async_bytes_read = 0;
497 EXPECT_EQ(BlobReader::Status::DONE,
498 reader_->Read(buffer.get(), kData.size(), &bytes_read,
499 base::Bind(&SetValue<int>, &async_bytes_read)));
500 EXPECT_EQ(net::OK, reader_->net_error());
501 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
502 EXPECT_EQ(0, async_bytes_read);
503 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
504 }
505
506 TEST_F(BlobReaderTest, BasicDiskCache) {
507 std::unique_ptr<disk_cache::Backend> cache =
508 CreateInMemoryDiskCache(message_loop_.task_runner());
509 ASSERT_TRUE(cache);
510
511 BlobDataBuilder b("uuid");
512 const std::string kData = "Test Blob Data";
513 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
514 new EmptyDataHandle();
515 disk_cache::ScopedEntryPtr entry =
516 CreateDiskCacheEntry(cache.get(), "test entry", kData);
517 b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
518 this->InitializeReader(&b);
519
520 int size_result = -1;
521 EXPECT_FALSE(IsReaderTotalSizeCalculated());
522 EXPECT_EQ(BlobReader::Status::DONE,
523 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
524 CheckSizeCalculatedSynchronously(kData.size(), size_result);
525
526 EXPECT_FALSE(reader_->has_side_data());
527
528 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
529
530 int bytes_read = 0;
531 int async_bytes_read = 0;
532 EXPECT_EQ(BlobReader::Status::DONE,
533 reader_->Read(buffer.get(), kData.size(), &bytes_read,
534 base::Bind(&SetValue<int>, &async_bytes_read)));
535 EXPECT_EQ(net::OK, reader_->net_error());
536 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
537 EXPECT_EQ(0, async_bytes_read);
538 EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
539 }
540
541 TEST_F(BlobReaderTest, DiskCacheWithSideData) {
542 std::unique_ptr<disk_cache::Backend> cache =
543 CreateInMemoryDiskCache(message_loop_.task_runner());
544 ASSERT_TRUE(cache);
545
546 BlobDataBuilder b("uuid");
547 const std::string kData = "Test Blob Data";
548 const std::string kSideData = "Test side data";
549 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
550 new EmptyDataHandle();
551 disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntryWithSideData(
552 cache.get(), "test entry", kData, kSideData);
553 b.AppendDiskCacheEntryWithSideData(data_handle, entry.get(),
554 kTestDiskCacheStreamIndex,
555 kTestDiskCacheSideStreamIndex);
556 this->InitializeReader(&b);
557
558 int size_result = -1;
559 EXPECT_FALSE(IsReaderTotalSizeCalculated());
560 EXPECT_EQ(BlobReader::Status::DONE,
561 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
562 CheckSizeCalculatedSynchronously(kData.size(), size_result);
563
564 EXPECT_TRUE(reader_->has_side_data());
565 BlobReader::Status status = BlobReader::Status::DONE;
566 EXPECT_EQ(BlobReader::Status::DONE,
567 reader_->ReadSideData(
568 base::Bind(&SetValue<BlobReader::Status>, &status)));
569 EXPECT_EQ(net::OK, reader_->net_error());
570 EXPECT_TRUE(reader_->side_data());
571 std::string result(reader_->side_data()->data(),
572 reader_->side_data()->size());
573 EXPECT_EQ(kSideData, result);
574 }
575
576 TEST_F(BlobReaderTest, BufferLargerThanMemory) {
577 BlobDataBuilder b("uuid");
578 const std::string kData("Hello!!!");
579 const size_t kDataSize = 8ul;
580 const size_t kBufferSize = 10ul;
581 b.AppendData(kData);
582 this->InitializeReader(&b);
583
584 int size_result = -1;
585 EXPECT_FALSE(IsReaderTotalSizeCalculated());
586 EXPECT_EQ(BlobReader::Status::DONE,
587 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
588 CheckSizeCalculatedSynchronously(kData.size(), size_result);
589
590 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
591
592 int bytes_read = 0;
593 int async_bytes_read = 0;
594 EXPECT_EQ(BlobReader::Status::DONE,
595 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
596 base::Bind(&SetValue<int>, &async_bytes_read)));
597 EXPECT_EQ(net::OK, reader_->net_error());
598 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
599 EXPECT_EQ(0, async_bytes_read);
600 EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
601 }
602
603 TEST_F(BlobReaderTest, MemoryRange) {
604 BlobDataBuilder b("uuid");
605 const std::string kData("Hello!!!");
606 const size_t kDataSize = 8ul;
607 const size_t kSeekOffset = 2ul;
608 const uint64_t kReadLength = 4ull;
609 b.AppendData(kData);
610 this->InitializeReader(&b);
611
612 int size_result = -1;
613 EXPECT_FALSE(IsReaderTotalSizeCalculated());
614 EXPECT_EQ(BlobReader::Status::DONE,
615 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
616 CheckSizeCalculatedSynchronously(kData.size(), size_result);
617
618 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
619
620 reader_->SetReadRange(kSeekOffset, kReadLength);
621 int bytes_read = 0;
622 int async_bytes_read = 0;
623 EXPECT_EQ(BlobReader::Status::DONE,
624 reader_->Read(buffer.get(), kDataSize - kSeekOffset, &bytes_read,
625 base::Bind(&SetValue<int>, &async_bytes_read)));
626 EXPECT_EQ(net::OK, reader_->net_error());
627 EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
628 EXPECT_EQ(0, async_bytes_read);
629 EXPECT_EQ(0, memcmp(buffer->data(), "llo!", kReadLength));
630 }
631
632 TEST_F(BlobReaderTest, BufferSmallerThanMemory) {
633 BlobDataBuilder b("uuid");
634 const std::string kData("Hello!!!");
635 const size_t kBufferSize = 4ul;
636 b.AppendData(kData);
637 this->InitializeReader(&b);
638
639 int size_result = -1;
640 EXPECT_FALSE(IsReaderTotalSizeCalculated());
641 EXPECT_EQ(BlobReader::Status::DONE,
642 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
643 CheckSizeCalculatedSynchronously(kData.size(), size_result);
644
645 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
646
647 int bytes_read = 0;
648 int async_bytes_read = 0;
649 EXPECT_EQ(BlobReader::Status::DONE,
650 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
651 base::Bind(&SetValue<int>, &async_bytes_read)));
652 EXPECT_EQ(net::OK, reader_->net_error());
653 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
654 EXPECT_EQ(0, async_bytes_read);
655 EXPECT_EQ(0, memcmp(buffer->data(), "Hell", kBufferSize));
656
657 bytes_read = 0;
658 EXPECT_EQ(BlobReader::Status::DONE,
659 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
660 base::Bind(&SetValue<int>, &async_bytes_read)));
661 EXPECT_EQ(net::OK, reader_->net_error());
662 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
663 EXPECT_EQ(0, async_bytes_read);
664 EXPECT_EQ(0, memcmp(buffer->data(), "o!!!", kBufferSize));
665 }
666
667 TEST_F(BlobReaderTest, SegmentedBufferAndMemory) {
668 BlobDataBuilder b("uuid");
669 const size_t kNumItems = 10;
670 const size_t kItemSize = 6;
671 const size_t kBufferSize = 10;
672 const size_t kTotalSize = kNumItems * kItemSize;
673 char current_value = 0;
674 for (size_t i = 0; i < kNumItems; i++) {
675 char buf[kItemSize];
676 for (size_t j = 0; j < kItemSize; j++) {
677 buf[j] = current_value++;
678 }
679 b.AppendData(buf, kItemSize);
680 }
681 this->InitializeReader(&b);
682
683 int size_result = -1;
684 EXPECT_FALSE(IsReaderTotalSizeCalculated());
685 EXPECT_EQ(BlobReader::Status::DONE,
686 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
687 CheckSizeCalculatedSynchronously(kTotalSize, size_result);
688
689 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
690
691 current_value = 0;
692 for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
693 int bytes_read = 0;
694 int async_bytes_read = 0;
695 EXPECT_EQ(BlobReader::Status::DONE,
696 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
697 base::Bind(&SetValue<int>, &async_bytes_read)));
698 EXPECT_EQ(net::OK, reader_->net_error());
699 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
700 EXPECT_EQ(0, async_bytes_read);
701 for (size_t j = 0; j < kBufferSize; j++) {
702 EXPECT_EQ(current_value, buffer->data()[j]);
703 current_value++;
704 }
705 }
706 }
707
708 TEST_F(BlobReaderTest, FileAsync) {
709 BlobDataBuilder b("uuid");
710 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
711 const std::string kData = "FileData!!!";
712 const base::Time kTime = base::Time::Now();
713 b.AppendFile(kPath, 0, kData.size(), kTime);
714 this->InitializeReader(&b);
715
716 std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
717 reader->SetAsyncRunner(message_loop_.task_runner().get());
718
719 ExpectLocalFileCall(kPath, kTime, 0, reader.release());
720
721 int size_result = -1;
722 EXPECT_FALSE(IsReaderTotalSizeCalculated());
723 EXPECT_EQ(BlobReader::Status::IO_PENDING,
724 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
725 EXPECT_FALSE(reader_->IsInMemory());
726 CheckSizeNotCalculatedYet(size_result);
727 base::RunLoop().RunUntilIdle();
728 CheckSizeCalculatedAsynchronously(kData.size(), size_result);
729
730 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
731
732 int bytes_read = 0;
733 int async_bytes_read = 0;
734 EXPECT_EQ(BlobReader::Status::IO_PENDING,
735 reader_->Read(buffer.get(), kData.size(), &bytes_read,
736 base::Bind(&SetValue<int>, &async_bytes_read)));
737 base::RunLoop().RunUntilIdle();
738 EXPECT_EQ(net::OK, reader_->net_error());
739 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
740 EXPECT_EQ(0, bytes_read);
741 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
742 }
743
744 TEST_F(BlobReaderTest, FileSystemAsync) {
745 BlobDataBuilder b("uuid");
746 const GURL kURL("file://test_file/here.txt");
747 const std::string kData = "FileData!!!";
748 const base::Time kTime = base::Time::Now();
749 b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
750 this->InitializeReader(&b);
751
752 std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
753 reader->SetAsyncRunner(message_loop_.task_runner().get());
754
755 ExpectFileSystemCall(kURL, 0, kData.size(), kTime, reader.release());
756
757 int size_result = -1;
758 EXPECT_FALSE(IsReaderTotalSizeCalculated());
759 EXPECT_EQ(BlobReader::Status::IO_PENDING,
760 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
761 CheckSizeNotCalculatedYet(size_result);
762 EXPECT_FALSE(reader_->IsInMemory());
763 base::RunLoop().RunUntilIdle();
764 CheckSizeCalculatedAsynchronously(kData.size(), size_result);
765
766 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
767
768 int bytes_read = 0;
769 int async_bytes_read = 0;
770 EXPECT_EQ(BlobReader::Status::IO_PENDING,
771 reader_->Read(buffer.get(), kData.size(), &bytes_read,
772 base::Bind(&SetValue<int>, &async_bytes_read)));
773 base::RunLoop().RunUntilIdle();
774 EXPECT_EQ(net::OK, reader_->net_error());
775 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
776 EXPECT_EQ(0, bytes_read);
777 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
778 }
779
780 TEST_F(BlobReaderTest, DiskCacheAsync) {
781 std::unique_ptr<disk_cache::Backend> cache =
782 CreateInMemoryDiskCache(message_loop_.task_runner());
783 ASSERT_TRUE(cache);
784
785 BlobDataBuilder b("uuid");
786 const std::string kData = "Test Blob Data";
787 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
788 new EmptyDataHandle();
789 std::unique_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry(
790 CreateDiskCacheEntry(cache.get(), "test entry", kData)));
791 b.AppendDiskCacheEntry(data_handle, delayed_read_entry.get(),
792 kTestDiskCacheStreamIndex);
793 this->InitializeReader(&b);
794
795 int size_result = -1;
796 EXPECT_FALSE(IsReaderTotalSizeCalculated());
797 EXPECT_EQ(BlobReader::Status::DONE,
798 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
799 CheckSizeCalculatedSynchronously(kData.size(), size_result);
800
801 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
802
803 int bytes_read = 0;
804 int async_bytes_read = 0;
805 EXPECT_EQ(BlobReader::Status::IO_PENDING,
806 reader_->Read(buffer.get(), kData.size(), &bytes_read,
807 base::Bind(&SetValue<int>, &async_bytes_read)));
808 EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
809 delayed_read_entry->RunPendingReadCallbacks();
810 EXPECT_EQ(net::OK, reader_->net_error());
811 EXPECT_EQ(0, bytes_read);
812 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
813 EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
814 }
815
816 TEST_F(BlobReaderTest, FileRange) {
817 BlobDataBuilder b("uuid");
818 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
819 // We check the offset in the ExpectLocalFileCall mock.
820 const std::string kRangeData = "leD";
821 const std::string kData = "FileData!!!";
822 const uint64_t kOffset = 2;
823 const uint64_t kReadLength = 3;
824 const base::Time kTime = base::Time::Now();
825 b.AppendFile(kPath, 0, kData.size(), kTime);
826 this->InitializeReader(&b);
827
828 std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
829 reader->SetAsyncRunner(message_loop_.task_runner().get());
830 ExpectLocalFileCall(kPath, kTime, 0, reader.release());
831
832 // We create the reader again with the offset after the seek.
833 reader.reset(new FakeFileStreamReader(kRangeData));
834 reader->SetAsyncRunner(message_loop_.task_runner().get());
835 ExpectLocalFileCall(kPath, kTime, kOffset, reader.release());
836
837 int size_result = -1;
838 EXPECT_EQ(BlobReader::Status::IO_PENDING,
839 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
840 base::RunLoop().RunUntilIdle();
841
842 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
843 EXPECT_EQ(BlobReader::Status::DONE,
844 reader_->SetReadRange(kOffset, kReadLength));
845
846 int bytes_read = 0;
847 int async_bytes_read = 0;
848 EXPECT_EQ(BlobReader::Status::IO_PENDING,
849 reader_->Read(buffer.get(), kReadLength, &bytes_read,
850 base::Bind(&SetValue<int>, &async_bytes_read)));
851 base::RunLoop().RunUntilIdle();
852 EXPECT_EQ(net::OK, reader_->net_error());
853 EXPECT_EQ(kReadLength, static_cast<size_t>(async_bytes_read));
854 EXPECT_EQ(0, bytes_read);
855 EXPECT_EQ(0, memcmp(buffer->data(), "leD", kReadLength));
856 }
857
858 TEST_F(BlobReaderTest, DiskCacheRange) {
859 std::unique_ptr<disk_cache::Backend> cache =
860 CreateInMemoryDiskCache(message_loop_.task_runner());
861 ASSERT_TRUE(cache);
862
863 BlobDataBuilder b("uuid");
864 const std::string kData = "Test Blob Data";
865 const uint64_t kOffset = 2;
866 const uint64_t kReadLength = 3;
867 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
868 new EmptyDataHandle();
869 disk_cache::ScopedEntryPtr entry =
870 CreateDiskCacheEntry(cache.get(), "test entry", kData);
871 b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
872 this->InitializeReader(&b);
873
874 int size_result = -1;
875 EXPECT_EQ(BlobReader::Status::DONE,
876 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
877
878 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
879 EXPECT_EQ(BlobReader::Status::DONE,
880 reader_->SetReadRange(kOffset, kReadLength));
881
882 int bytes_read = 0;
883 int async_bytes_read = 0;
884 EXPECT_EQ(BlobReader::Status::DONE,
885 reader_->Read(buffer.get(), kReadLength, &bytes_read,
886 base::Bind(&SetValue<int>, &async_bytes_read)));
887 EXPECT_EQ(net::OK, reader_->net_error());
888 EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
889 EXPECT_EQ(0, async_bytes_read);
890 EXPECT_EQ(0, memcmp(buffer->data(), "st ", kReadLength));
891 }
892
893 TEST_F(BlobReaderTest, FileSomeAsyncSegmentedOffsetsUnknownSizes) {
894 // This tests includes:
895 // * Unknown file sizes (item length of uint64_t::max) for every other item.
896 // * Offsets for every 3rd file item.
897 // * Non-async reader for every 4th file item.
898 BlobDataBuilder b("uuid");
899 const FilePath kPathBase = FilePath::FromUTF8Unsafe("/fake/file.txt");
900 const base::Time kTime = base::Time::Now();
901 const size_t kNumItems = 10;
902 const size_t kItemSize = 6;
903 const size_t kBufferSize = 10;
904 const size_t kTotalSize = kNumItems * kItemSize;
905 char current_value = 0;
906 // Create blob and reader.
907 for (size_t i = 0; i < kNumItems; i++) {
908 current_value += kItemSize;
909 FilePath path = kPathBase.Append(
910 FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
911 uint64_t offset = i % 3 == 0 ? 1 : 0;
912 uint64_t size =
913 i % 2 == 0 ? kItemSize : std::numeric_limits<uint64_t>::max();
914 b.AppendFile(path, offset, size, kTime);
915 }
916 this->InitializeReader(&b);
917
918 // Set expectations.
919 current_value = 0;
920 for (size_t i = 0; i < kNumItems; i++) {
921 uint64_t offset = i % 3 == 0 ? 1 : 0;
922 std::unique_ptr<char[]> buf(new char[kItemSize + offset]);
923 if (offset > 0) {
924 memset(buf.get(), 7, offset);
925 }
926 for (size_t j = 0; j < kItemSize; j++) {
927 buf.get()[j + offset] = current_value++;
928 }
929 std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(
930 std::string(buf.get() + offset, kItemSize), kItemSize + offset));
931 if (i % 4 != 0) {
932 reader->SetAsyncRunner(message_loop_.task_runner().get());
933 }
934 FilePath path = kPathBase.Append(
935 FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
936 ExpectLocalFileCall(path, kTime, offset, reader.release());
937 }
938
939 int size_result = -1;
940 EXPECT_FALSE(IsReaderTotalSizeCalculated());
941 EXPECT_EQ(BlobReader::Status::IO_PENDING,
942 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
943 CheckSizeNotCalculatedYet(size_result);
944 base::RunLoop().RunUntilIdle();
945 CheckSizeCalculatedAsynchronously(kTotalSize, size_result);
946
947 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
948
949 current_value = 0;
950 for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
951 int bytes_read = 0;
952 int async_bytes_read = 0;
953 EXPECT_EQ(BlobReader::Status::IO_PENDING,
954 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
955 base::Bind(&SetValue<int>, &async_bytes_read)));
956 base::RunLoop().RunUntilIdle();
957 EXPECT_EQ(net::OK, reader_->net_error());
958 EXPECT_EQ(0, bytes_read);
959 EXPECT_EQ(kBufferSize, static_cast<size_t>(async_bytes_read));
960 for (size_t j = 0; j < kBufferSize; j++) {
961 EXPECT_EQ(current_value, buffer->data()[j]);
962 current_value++;
963 }
964 }
965 }
966
967 TEST_F(BlobReaderTest, MixedContent) {
968 // Includes data, a file, and a disk cache entry.
969 std::unique_ptr<disk_cache::Backend> cache =
970 CreateInMemoryDiskCache(message_loop_.task_runner());
971 ASSERT_TRUE(cache);
972
973 BlobDataBuilder b("uuid");
974 const std::string kData1("Hello ");
975 const std::string kData2("there. ");
976 const std::string kData3("This ");
977 const std::string kData4("is multi-content.");
978 const uint64_t kDataSize = 35;
979
980 const base::Time kTime = base::Time::Now();
981 const FilePath kData1Path = FilePath::FromUTF8Unsafe("/fake/file.txt");
982
983 disk_cache::ScopedEntryPtr entry3 =
984 CreateDiskCacheEntry(cache.get(), "test entry", kData3);
985
986 b.AppendFile(kData1Path, 0, kData1.size(), kTime);
987 b.AppendData(kData2);
988 b.AppendDiskCacheEntry(
989 scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()),
990 entry3.get(), kTestDiskCacheStreamIndex);
991 b.AppendData(kData4);
992
993 this->InitializeReader(&b);
994
995 std::unique_ptr<FakeFileStreamReader> reader(
996 new FakeFileStreamReader(kData1));
997 reader->SetAsyncRunner(message_loop_.task_runner().get());
998 ExpectLocalFileCall(kData1Path, kTime, 0, reader.release());
999
1000 int size_result = -1;
1001 EXPECT_FALSE(IsReaderTotalSizeCalculated());
1002 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1003 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1004 CheckSizeNotCalculatedYet(size_result);
1005 base::RunLoop().RunUntilIdle();
1006 CheckSizeCalculatedAsynchronously(kDataSize, size_result);
1007
1008 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
1009
1010 int bytes_read = 0;
1011 int async_bytes_read = 0;
1012 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1013 reader_->Read(buffer.get(), kDataSize, &bytes_read,
1014 base::Bind(&SetValue<int>, &async_bytes_read)));
1015 EXPECT_EQ(0, async_bytes_read);
1016 base::RunLoop().RunUntilIdle();
1017 EXPECT_EQ(net::OK, reader_->net_error());
1018 EXPECT_EQ(0, bytes_read);
1019 EXPECT_EQ(kDataSize, static_cast<size_t>(async_bytes_read));
1020 EXPECT_EQ(0, memcmp(buffer->data(), "Hello there. This is multi-content.",
1021 kDataSize));
1022 }
1023
1024 TEST_F(BlobReaderTest, StateErrors) {
1025 // Test common variables
1026 int bytes_read = -1;
1027 int async_bytes_read = -1;
1028 int size_result = -1;
1029 const std::string kData("Hello!!!");
1030
1031 // Case: Blob handle is a nullptr.
1032 InitializeReader(nullptr);
1033 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1034 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1035 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1036 EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10));
1037 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1038 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(10);
1039 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1040 reader_->Read(buffer.get(), 10, &bytes_read,
1041 base::Bind(&SetValue<int>, &async_bytes_read)));
1042 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1043
1044 // Case: Not calling CalculateSize before SetReadRange.
1045 BlobDataBuilder builder1("uuid1");
1046 builder1.AppendData(kData);
1047 InitializeReader(&builder1);
1048 EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10));
1049 EXPECT_EQ(net::ERR_FAILED, reader_->net_error());
1050 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1051 reader_->Read(buffer.get(), 10, &bytes_read,
1052 base::Bind(&SetValue<int>, &async_bytes_read)));
1053
1054 // Case: Not calling CalculateSize before Read.
1055 BlobDataBuilder builder2("uuid2");
1056 builder2.AppendData(kData);
1057 InitializeReader(&builder2);
1058 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1059 reader_->Read(buffer.get(), 10, &bytes_read,
1060 base::Bind(&SetValue<int>, &async_bytes_read)));
1061 }
1062
1063 TEST_F(BlobReaderTest, FileErrorsSync) {
1064 int size_result = -1;
1065 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
1066 const std::string kData = "FileData!!!";
1067 const base::Time kTime = base::Time::Now();
1068
1069 // Case: Error on length query.
1070 BlobDataBuilder builder1("uuid1");
1071 builder1.AppendFile(kPath, 0, kData.size(), kTime);
1072 this->InitializeReader(&builder1);
1073 FakeFileStreamReader* reader = new FakeFileStreamReader(kData);
1074 reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
1075 ExpectLocalFileCall(kPath, kTime, 0, reader);
1076
1077 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1078 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1079 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1080
1081 // Case: Error on read.
1082 BlobDataBuilder builder2("uuid2");
1083 builder2.AppendFile(kPath, 0, kData.size(), kTime);
1084 this->InitializeReader(&builder2);
1085 reader = new FakeFileStreamReader(kData);
1086 ExpectLocalFileCall(kPath, kTime, 0, reader);
1087 EXPECT_EQ(BlobReader::Status::DONE,
1088 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1089 reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
1090
1091 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
1092 int bytes_read = 0;
1093 int async_bytes_read = 0;
1094 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1095 reader_->Read(buffer.get(), kData.size(), &bytes_read,
1096 base::Bind(&SetValue<int>, &async_bytes_read)));
1097 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1098 }
1099
1100 TEST_F(BlobReaderTest, FileErrorsAsync) {
1101 int size_result = -1;
1102 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
1103 const std::string kData = "FileData!!!";
1104 const base::Time kTime = base::Time::Now();
1105
1106 // Case: Error on length query.
1107 BlobDataBuilder builder1("uuid1");
1108 builder1.AppendFile(kPath, 0, kData.size(), kTime);
1109 this->InitializeReader(&builder1);
1110 FakeFileStreamReader* reader = new FakeFileStreamReader(kData);
1111 reader->SetAsyncRunner(message_loop_.task_runner().get());
1112 reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
1113 ExpectLocalFileCall(kPath, kTime, 0, reader);
1114
1115 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1116 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1117 EXPECT_EQ(net::OK, reader_->net_error());
1118 base::RunLoop().RunUntilIdle();
1119 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, size_result);
1120 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1121
1122 // Case: Error on read.
1123 BlobDataBuilder builder2("uuid2");
1124 builder2.AppendFile(kPath, 0, kData.size(), kTime);
1125 this->InitializeReader(&builder2);
1126 reader = new FakeFileStreamReader(kData);
1127 ExpectLocalFileCall(kPath, kTime, 0, reader);
1128 EXPECT_EQ(BlobReader::Status::DONE,
1129 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1130 reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
1131 reader->SetAsyncRunner(message_loop_.task_runner().get());
1132
1133 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
1134 int bytes_read = 0;
1135 int async_bytes_read = 0;
1136 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1137 reader_->Read(buffer.get(), kData.size(), &bytes_read,
1138 base::Bind(&SetValue<int>, &async_bytes_read)));
1139 EXPECT_EQ(net::OK, reader_->net_error());
1140 base::RunLoop().RunUntilIdle();
1141 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, async_bytes_read);
1142 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1143 }
1144
1145 TEST_F(BlobReaderTest, RangeError) {
1146 const std::string kData("Hello!!!");
1147 const size_t kDataSize = 8ul;
1148 const uint64_t kReadLength = 4ull;
1149
1150 // Case: offset too high.
1151 BlobDataBuilder b("uuid1");
1152 b.AppendData(kData);
1153 this->InitializeReader(&b);
1154 int size_result = -1;
1155 EXPECT_EQ(BlobReader::Status::DONE,
1156 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1157 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
1158 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1159 reader_->SetReadRange(kDataSize + 1, kReadLength));
1160 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1161
1162 // Case: length too long.
1163 BlobDataBuilder b2("uuid2");
1164 b2.AppendData(kData);
1165 this->InitializeReader(&b2);
1166 size_result = -1;
1167 EXPECT_EQ(BlobReader::Status::DONE,
1168 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1169 buffer = CreateBuffer(kDataSize + 1);
1170 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1171 reader_->SetReadRange(0, kDataSize + 1));
1172 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1173 }
1174
1175 TEST_F(BlobReaderTest, HandleBeforeAsyncCancel) {
1176 const std::string kUuid("uuid1");
1177
1178 context_.CreatePendingBlob(kUuid, "", "");
1179 blob_handle_ = context_.GetBlobDataFromUUID(kUuid);
1180 provider_ = new MockFileStreamReaderProvider();
1181 reader_.reset(new BlobReader(blob_handle_.get(), base::WrapUnique(provider_),
1182 message_loop_.task_runner().get()));
1183 int size_result = -1;
1184 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1185 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1186 EXPECT_FALSE(reader_->IsInMemory());
1187 context_.CancelPendingBlob(kUuid, IPCBlobCreationCancelCode::UNKNOWN);
1188 base::RunLoop().RunUntilIdle();
1189 EXPECT_EQ(net::ERR_FAILED, size_result);
1190 }
1191
1192 TEST_F(BlobReaderTest, ReadFromIncompleteBlob) {
1193 const std::string kUuid("uuid1");
1194 const std::string kData("Hello!!!");
1195 const size_t kDataSize = 8ul;
1196
1197 BlobDataBuilder b(kUuid);
1198 b.AppendData(kData);
1199 context_.CreatePendingBlob(kUuid, "", "");
1200 blob_handle_ = context_.GetBlobDataFromUUID(kUuid);
1201 provider_ = new MockFileStreamReaderProvider();
1202 reader_.reset(new BlobReader(blob_handle_.get(), base::WrapUnique(provider_),
1203 message_loop_.task_runner().get()));
1204 int size_result = -1;
1205 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1206 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1207 EXPECT_FALSE(reader_->IsInMemory());
1208 context_.CompletePendingBlob(b);
1209 base::RunLoop().RunUntilIdle();
1210 CheckSizeCalculatedAsynchronously(kDataSize, size_result);
1211 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
1212
1213 int bytes_read = 0;
1214 int async_bytes_read = 0;
1215 EXPECT_EQ(BlobReader::Status::DONE,
1216 reader_->Read(buffer.get(), kDataSize, &bytes_read,
1217 base::Bind(&SetValue<int>, &async_bytes_read)));
1218 EXPECT_EQ(net::OK, reader_->net_error());
1219 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
1220 EXPECT_EQ(0, async_bytes_read);
1221 EXPECT_EQ(kData, std::string(buffer->data(), kDataSize));
1222 EXPECT_EQ(net::OK, size_result);
1223 }
1224
1225 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698