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

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

Powered by Google App Engine
This is Rietveld 408576698