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

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: asan fix 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 }
199
200 ~FakeFileStreamReader() override {}
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),
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_;
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());
michaeln 2015/09/23 18:52:45 What is the purpose of the GetLenghtImpl helper? S
dmurph 2015/09/25 17:11:43 Yeah I'll just return size.
234 }
235 }
236 if (async_task_runner_.get()) {
237 async_task_runner_->PostTask(
238 FROM_HERE,
239 base::Bind(size_callback, static_cast<int64_t>(net_error_)));
240 return net::ERR_IO_PENDING;
241 }
242 return net_error_;
243 }
244
245 private:
246 int ReadImpl(scoped_refptr<net::IOBuffer> buf,
247 int buf_length,
248 const net::CompletionCallback& done) {
249 CHECK_GE(buf_length, 0);
250 int length = std::min(buf_length, buffer_->BytesRemaining());
251 memcpy(buf->data(), buffer_->data(), length);
252 buffer_->DidConsume(length);
253 if (done.is_null()) {
254 return length;
255 }
256 done.Run(length);
257 return net::ERR_IO_PENDING;
258 }
259
260 int64 GetLengthImpl(const net::Int64CompletionCallback& size_callback) {
261 if (size_callback.is_null()) {
262 return size_;
263 }
264 size_callback.Run(size_);
265 return net::ERR_IO_PENDING;
michaeln 2015/09/23 18:52:45 looks odd to be calling the callback and returning
dmurph 2015/09/25 17:11:43 Yeah, I'll only use this as a callback, and switch
266 }
267
268 scoped_refptr<net::DrainableIOBuffer> buffer_;
269 scoped_refptr<base::SingleThreadTaskRunner> async_task_runner_;
270 int net_error_;
271 uint64_t size_;
272
273 DISALLOW_COPY_AND_ASSIGN(FakeFileStreamReader);
274 };
275
276 class MockFileStreamReaderProvider
277 : public BlobReader::FileStreamReaderProvider {
278 public:
279 ~MockFileStreamReaderProvider() override {}
280
281 MOCK_METHOD4(CreateForLocalFileMock,
282 FileStreamReader*(base::TaskRunner* task_runner,
283 const FilePath& file_path,
284 int64_t initial_offset,
285 const base::Time& expected_modification_time));
286 MOCK_METHOD4(CreateFileStreamReaderMock,
287 FileStreamReader*(const GURL& filesystem_url,
288 int64_t offset,
289 int64_t max_bytes_to_read,
290 const base::Time& expected_modification_time));
291 // Since we're returning a move-only type, we have to do some delegation for
292 // gmock.
293 scoped_ptr<FileStreamReader> CreateForLocalFile(
294 base::TaskRunner* task_runner,
295 const base::FilePath& file_path,
296 int64_t initial_offset,
297 const base::Time& expected_modification_time) override {
298 return make_scoped_ptr(CreateForLocalFileMock(
299 task_runner, file_path, initial_offset, expected_modification_time));
300 }
301
302 scoped_ptr<FileStreamReader> CreateFileStreamReader(
303 const GURL& filesystem_url,
304 int64_t offset,
305 int64_t max_bytes_to_read,
306 const base::Time& expected_modification_time) override {
307 return make_scoped_ptr(CreateFileStreamReaderMock(
308 filesystem_url, offset, max_bytes_to_read, expected_modification_time));
309 }
310 };
311
312 } // namespace
313
314 class BlobReaderTest : public ::testing::Test {
315 public:
316 BlobReaderTest() {}
317 ~BlobReaderTest() override {}
318
319 void TearDown() override {
320 reader_.reset();
321 blob_handle_.reset();
322 message_loop_.RunUntilIdle();
323 base::RunLoop().RunUntilIdle();
324 }
325
326 protected:
327 void InitializeReader(BlobDataBuilder* builder) {
328 blob_handle_ = builder ? context_.AddFinishedBlob(builder).Pass() : nullptr;
329 provider_ = new MockFileStreamReaderProvider();
330 scoped_ptr<BlobReader::FileStreamReaderProvider> temp_ptr(provider_);
331 reader_.reset(new BlobReader(blob_handle_.get(), temp_ptr.Pass(),
332 message_loop_.task_runner().get()));
333 }
334
335 // Takes ownership of the file reader (the blob reader takes ownership).
336 void ExpectLocalFileCall(const FilePath& file_path,
337 base::Time modification_time,
338 uint64_t initial_offset,
339 FakeFileStreamReader* reader) {
340 EXPECT_CALL(*provider_, CreateForLocalFileMock(
341 message_loop_.task_runner().get(), file_path,
342 initial_offset, modification_time))
343 .WillOnce(testing::Return(reader));
344 }
345
346 // Takes ownership of the file reader (the blob reader takes ownership).
347 void ExpectFileSystemCall(const GURL& filesystem_url,
348 int64_t offset,
349 int64_t max_bytes_to_read,
350 base::Time expected_modification_time,
351 FakeFileStreamReader* reader) {
352 EXPECT_CALL(*provider_, CreateFileStreamReaderMock(
353 filesystem_url, offset, max_bytes_to_read,
354 expected_modification_time))
355 .WillOnce(testing::Return(reader));
356 }
357
358 void CheckSizeCalculatedSynchronously(size_t expected_size, int async_size) {
359 EXPECT_EQ(-1, async_size);
360 EXPECT_EQ(net::OK, reader_->net_error());
361 EXPECT_EQ(expected_size, reader_->total_size());
362 EXPECT_TRUE(reader_->total_size_calculated());
363 }
364
365 void CheckSizeNotCalculatedYet(int async_size) {
366 EXPECT_EQ(-1, async_size);
367 EXPECT_EQ(net::OK, reader_->net_error());
368 EXPECT_FALSE(reader_->total_size_calculated());
369 }
370
371 void CheckSizeCalculatedAsynchronously(size_t expected_size,
372 int async_result) {
373 EXPECT_EQ(net::OK, async_result);
374 EXPECT_EQ(net::OK, reader_->net_error());
375 EXPECT_EQ(expected_size, reader_->total_size());
376 EXPECT_TRUE(reader_->total_size_calculated());
377 }
378
379 scoped_refptr<net::IOBuffer> CreateBuffer(uint64_t size) {
380 return scoped_refptr<net::IOBuffer>(
381 new net::IOBuffer(static_cast<size_t>(size)));
382 }
383
384 bool IsReaderTotalSizeCalculated() {
385 return reader_->total_size_calculated();
386 }
387
388 BlobStorageContext context_;
389 scoped_ptr<BlobDataHandle> blob_handle_;
390 MockFileStreamReaderProvider* provider_ = nullptr;
391 base::MessageLoop message_loop_;
392 scoped_ptr<BlobReader> reader_;
393
394 private:
395 DISALLOW_COPY_AND_ASSIGN(BlobReaderTest);
396 };
397
398 namespace {
399
400 TEST_F(BlobReaderTest, BasicMemory) {
401 BlobDataBuilder b("uuid");
402 const std::string kData("Hello!!!");
403 const size_t kDataSize = 8ul;
404 b.AppendData(kData);
405 this->InitializeReader(&b);
406
407 int size_result = -1;
408 EXPECT_FALSE(IsReaderTotalSizeCalculated());
409 EXPECT_EQ(BlobReader::Status::DONE,
410 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
411 CheckSizeCalculatedSynchronously(kDataSize, size_result);
412
413 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
414
415 int bytes_read = 0;
416 int async_bytes_read = 0;
417 EXPECT_EQ(BlobReader::Status::DONE,
418 reader_->Read(buffer.get(), kDataSize, &bytes_read,
419 base::Bind(&SetValue<int>, &async_bytes_read)));
420 EXPECT_EQ(net::OK, reader_->net_error());
421 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
422 EXPECT_EQ(0, async_bytes_read);
423 EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
424 }
425
426 TEST_F(BlobReaderTest, BasicFile) {
427 BlobDataBuilder b("uuid");
428 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
429 const std::string kData = "FileData!!!";
430 const base::Time kTime = base::Time::Now();
431 b.AppendFile(kPath, 0, kData.size(), kTime);
432 this->InitializeReader(&b);
433
434 // Non-async reader.
435 ExpectLocalFileCall(kPath, kTime, 0, new FakeFileStreamReader(kData));
436
437 int size_result = -1;
438 EXPECT_FALSE(IsReaderTotalSizeCalculated());
439 EXPECT_EQ(BlobReader::Status::DONE,
440 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
441 CheckSizeCalculatedSynchronously(kData.size(), size_result);
442
443 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
444
445 int bytes_read = 0;
446 int async_bytes_read = 0;
447 EXPECT_EQ(BlobReader::Status::DONE,
448 reader_->Read(buffer.get(), kData.size(), &bytes_read,
449 base::Bind(&SetValue<int>, &async_bytes_read)));
450 EXPECT_EQ(net::OK, reader_->net_error());
451 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
452 EXPECT_EQ(0, async_bytes_read);
453 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
454 }
455
456 TEST_F(BlobReaderTest, BasicFileSystem) {
457 BlobDataBuilder b("uuid");
458 const GURL kURL("file://test_file/here.txt");
459 const std::string kData = "FileData!!!";
460 const base::Time kTime = base::Time::Now();
461 b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
462 this->InitializeReader(&b);
463
464 // Non-async reader.
465 ExpectFileSystemCall(kURL, 0, kData.size(), kTime,
466 new FakeFileStreamReader(kData));
467
468 int size_result = -1;
469 EXPECT_FALSE(IsReaderTotalSizeCalculated());
470 EXPECT_EQ(BlobReader::Status::DONE,
471 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
472 CheckSizeCalculatedSynchronously(kData.size(), size_result);
473
474 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
475
476 int bytes_read = 0;
477 int async_bytes_read = 0;
478 EXPECT_EQ(BlobReader::Status::DONE,
479 reader_->Read(buffer.get(), kData.size(), &bytes_read,
480 base::Bind(&SetValue<int>, &async_bytes_read)));
481 EXPECT_EQ(net::OK, reader_->net_error());
482 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
483 EXPECT_EQ(0, async_bytes_read);
484 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
485 }
486
487 TEST_F(BlobReaderTest, BasicDiskCache) {
488 scoped_ptr<disk_cache::Backend> cache =
489 CreateInMemoryDiskCache(message_loop_.task_runner());
490 ASSERT_TRUE(cache);
491
492 BlobDataBuilder b("uuid");
493 const std::string kData = "Test Blob Data";
494 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
495 new EmptyDataHandle();
496 disk_cache::ScopedEntryPtr entry =
497 CreateDiskCacheEntry(cache.get(), "test entry", kData);
498 b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
499 this->InitializeReader(&b);
500
501 int size_result = -1;
502 EXPECT_FALSE(IsReaderTotalSizeCalculated());
503 EXPECT_EQ(BlobReader::Status::DONE,
504 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
505 CheckSizeCalculatedSynchronously(kData.size(), size_result);
506
507 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
508
509 int bytes_read = 0;
510 int async_bytes_read = 0;
511 EXPECT_EQ(BlobReader::Status::DONE,
512 reader_->Read(buffer.get(), kData.size(), &bytes_read,
513 base::Bind(&SetValue<int>, &async_bytes_read)));
514 EXPECT_EQ(net::OK, reader_->net_error());
515 EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
516 EXPECT_EQ(0, async_bytes_read);
517 EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
518 }
519
520 TEST_F(BlobReaderTest, BufferLargerThanMemory) {
521 BlobDataBuilder b("uuid");
522 const std::string kData("Hello!!!");
523 const size_t kDataSize = 8ul;
524 const size_t kBufferSize = 10ul;
525 b.AppendData(kData);
526 this->InitializeReader(&b);
527
528 int size_result = -1;
529 EXPECT_FALSE(IsReaderTotalSizeCalculated());
530 EXPECT_EQ(BlobReader::Status::DONE,
531 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
532 CheckSizeCalculatedSynchronously(kData.size(), size_result);
533
534 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
535
536 int bytes_read = 0;
537 int async_bytes_read = 0;
538 EXPECT_EQ(BlobReader::Status::DONE,
539 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
540 base::Bind(&SetValue<int>, &async_bytes_read)));
541 EXPECT_EQ(net::OK, reader_->net_error());
542 EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
543 EXPECT_EQ(0, async_bytes_read);
544 EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
545 }
546
547 TEST_F(BlobReaderTest, MemoryRange) {
548 BlobDataBuilder b("uuid");
549 const std::string kData("Hello!!!");
550 const size_t kDataSize = 8ul;
551 const size_t kSeekOffset = 2ul;
552 const uint64_t kReadLength = 4ull;
553 b.AppendData(kData);
554 this->InitializeReader(&b);
555
556 int size_result = -1;
557 EXPECT_FALSE(IsReaderTotalSizeCalculated());
558 EXPECT_EQ(BlobReader::Status::DONE,
559 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
560 CheckSizeCalculatedSynchronously(kData.size(), size_result);
561
562 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
563
564 reader_->SetReadRange(kSeekOffset, kReadLength);
565 int bytes_read = 0;
566 int async_bytes_read = 0;
567 EXPECT_EQ(BlobReader::Status::DONE,
568 reader_->Read(buffer.get(), kDataSize - kSeekOffset, &bytes_read,
569 base::Bind(&SetValue<int>, &async_bytes_read)));
570 EXPECT_EQ(net::OK, reader_->net_error());
571 EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
572 EXPECT_EQ(0, async_bytes_read);
573 EXPECT_EQ(0, memcmp(buffer->data(), "llo!", kReadLength));
574 }
575
576 TEST_F(BlobReaderTest, BufferSmallerThanMemory) {
577 BlobDataBuilder b("uuid");
578 const std::string kData("Hello!!!");
579 const size_t kBufferSize = 4ul;
580 b.AppendData(kData);
581 this->InitializeReader(&b);
582
583 int size_result = -1;
584 EXPECT_FALSE(IsReaderTotalSizeCalculated());
585 EXPECT_EQ(BlobReader::Status::DONE,
586 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
587 CheckSizeCalculatedSynchronously(kData.size(), size_result);
588
589 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
590
591 int bytes_read = 0;
592 int async_bytes_read = 0;
593 EXPECT_EQ(BlobReader::Status::DONE,
594 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
595 base::Bind(&SetValue<int>, &async_bytes_read)));
596 EXPECT_EQ(net::OK, reader_->net_error());
597 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
598 EXPECT_EQ(0, async_bytes_read);
599 EXPECT_EQ(0, memcmp(buffer->data(), "Hell", kBufferSize));
600
601 bytes_read = 0;
602 EXPECT_EQ(BlobReader::Status::DONE,
603 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
604 base::Bind(&SetValue<int>, &async_bytes_read)));
605 EXPECT_EQ(net::OK, reader_->net_error());
606 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
607 EXPECT_EQ(0, async_bytes_read);
608 EXPECT_EQ(0, memcmp(buffer->data(), "o!!!", kBufferSize));
609 }
610
611 TEST_F(BlobReaderTest, SegmentedBufferAndMemory) {
612 BlobDataBuilder b("uuid");
613 const size_t kNumItems = 10;
614 const size_t kItemSize = 6;
615 const size_t kBufferSize = 10;
616 const size_t kTotalSize = kNumItems * kItemSize;
617 char current_value = 0;
618 for (size_t i = 0; i < kNumItems; i++) {
619 char buf[kItemSize];
620 for (size_t j = 0; j < kItemSize; j++) {
621 buf[j] = current_value++;
622 }
623 b.AppendData(buf, kItemSize);
624 }
625 this->InitializeReader(&b);
626
627 int size_result = -1;
628 EXPECT_FALSE(IsReaderTotalSizeCalculated());
629 EXPECT_EQ(BlobReader::Status::DONE,
630 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
631 CheckSizeCalculatedSynchronously(kTotalSize, size_result);
632
633 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
634
635 current_value = 0;
636 for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
637 int bytes_read = 0;
638 int async_bytes_read = 0;
639 EXPECT_EQ(BlobReader::Status::DONE,
640 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
641 base::Bind(&SetValue<int>, &async_bytes_read)));
642 EXPECT_EQ(net::OK, reader_->net_error());
643 EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
644 EXPECT_EQ(0, async_bytes_read);
645 for (size_t j = 0; j < kBufferSize; j++) {
646 EXPECT_EQ(current_value, buffer->data()[j]);
647 current_value++;
648 }
649 }
650 }
651
652 TEST_F(BlobReaderTest, FileAsync) {
653 BlobDataBuilder b("uuid");
654 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
655 const std::string kData = "FileData!!!";
656 const base::Time kTime = base::Time::Now();
657 b.AppendFile(kPath, 0, kData.size(), kTime);
658 this->InitializeReader(&b);
659
660 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
661 reader->DoAsync(message_loop_.task_runner().get());
662
663 ExpectLocalFileCall(kPath, kTime, 0, reader.release());
664
665 int size_result = -1;
666 EXPECT_FALSE(IsReaderTotalSizeCalculated());
667 EXPECT_EQ(BlobReader::Status::IO_PENDING,
668 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
669 CheckSizeNotCalculatedYet(size_result);
670 message_loop_.RunUntilIdle();
671 CheckSizeCalculatedAsynchronously(kData.size(), size_result);
672
673 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
674
675 int bytes_read = 0;
676 int async_bytes_read = 0;
677 EXPECT_EQ(BlobReader::Status::IO_PENDING,
678 reader_->Read(buffer.get(), kData.size(), &bytes_read,
679 base::Bind(&SetValue<int>, &async_bytes_read)));
680 message_loop_.RunUntilIdle();
681 EXPECT_EQ(net::OK, reader_->net_error());
682 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
683 EXPECT_EQ(0, bytes_read);
684 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
685 }
686
687 TEST_F(BlobReaderTest, FileSystemAsync) {
688 BlobDataBuilder b("uuid");
689 const GURL kURL("file://test_file/here.txt");
690 const std::string kData = "FileData!!!";
691 const base::Time kTime = base::Time::Now();
692 b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
693 this->InitializeReader(&b);
694
695 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
696 reader->DoAsync(message_loop_.task_runner().get());
697
698 ExpectFileSystemCall(kURL, 0, kData.size(), kTime, reader.release());
699
700 int size_result = -1;
701 EXPECT_FALSE(IsReaderTotalSizeCalculated());
702 EXPECT_EQ(BlobReader::Status::IO_PENDING,
703 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
704 CheckSizeNotCalculatedYet(size_result);
705 message_loop_.RunUntilIdle();
706 CheckSizeCalculatedAsynchronously(kData.size(), size_result);
707
708 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
709
710 int bytes_read = 0;
711 int async_bytes_read = 0;
712 EXPECT_EQ(BlobReader::Status::IO_PENDING,
713 reader_->Read(buffer.get(), kData.size(), &bytes_read,
714 base::Bind(&SetValue<int>, &async_bytes_read)));
715 message_loop_.RunUntilIdle();
716 EXPECT_EQ(net::OK, reader_->net_error());
717 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
718 EXPECT_EQ(0, bytes_read);
719 EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
720 }
721
722 TEST_F(BlobReaderTest, DiskCacheAsync) {
723 scoped_ptr<disk_cache::Backend> cache =
724 CreateInMemoryDiskCache(message_loop_.task_runner());
725 ASSERT_TRUE(cache);
726
727 BlobDataBuilder b("uuid");
728 const std::string kData = "Test Blob Data";
729 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
730 new EmptyDataHandle();
731 scoped_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry(
732 CreateDiskCacheEntry(cache.get(), "test entry", kData).Pass()));
733 b.AppendDiskCacheEntry(data_handle, delayed_read_entry.get(),
734 kTestDiskCacheStreamIndex);
735 this->InitializeReader(&b);
736
737 int size_result = -1;
738 EXPECT_FALSE(IsReaderTotalSizeCalculated());
739 EXPECT_EQ(BlobReader::Status::DONE,
740 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
741 CheckSizeCalculatedSynchronously(kData.size(), size_result);
742
743 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
744
745 int bytes_read = 0;
746 int async_bytes_read = 0;
747 EXPECT_EQ(BlobReader::Status::IO_PENDING,
748 reader_->Read(buffer.get(), kData.size(), &bytes_read,
749 base::Bind(&SetValue<int>, &async_bytes_read)));
750 EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
751 delayed_read_entry->RunPendingReadCallbacks();
752 EXPECT_EQ(net::OK, reader_->net_error());
753 EXPECT_EQ(0, bytes_read);
754 EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
755 EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
756 }
757
758 TEST_F(BlobReaderTest, FileRange) {
759 BlobDataBuilder b("uuid");
760 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
761 // We check the offset in the ExpectLocalFileCall mock.
762 const std::string kRangeData = "leD";
763 const std::string kData = "FileData!!!";
764 const uint64_t kOffset = 2;
765 const uint64_t kReadLength = 3;
766 const base::Time kTime = base::Time::Now();
767 b.AppendFile(kPath, 0, kData.size(), kTime);
768 this->InitializeReader(&b);
769
770 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
771 reader->DoAsync(message_loop_.task_runner().get());
772 ExpectLocalFileCall(kPath, kTime, 0, reader.release());
773
774 // We create the reader again with the offset after the seek.
775 reader.reset(new FakeFileStreamReader(kRangeData));
776 reader->DoAsync(message_loop_.task_runner().get());
777 ExpectLocalFileCall(kPath, kTime, kOffset, reader.release());
778
779 int size_result = -1;
780 EXPECT_EQ(BlobReader::Status::IO_PENDING,
781 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
782 message_loop_.RunUntilIdle();
783
784 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
785 EXPECT_EQ(BlobReader::Status::DONE,
786 reader_->SetReadRange(kOffset, kReadLength));
787
788 int bytes_read = 0;
789 int async_bytes_read = 0;
790 EXPECT_EQ(BlobReader::Status::IO_PENDING,
791 reader_->Read(buffer.get(), kReadLength, &bytes_read,
792 base::Bind(&SetValue<int>, &async_bytes_read)));
793 message_loop_.RunUntilIdle();
794 EXPECT_EQ(net::OK, reader_->net_error());
795 EXPECT_EQ(kReadLength, static_cast<size_t>(async_bytes_read));
796 EXPECT_EQ(0, bytes_read);
797 EXPECT_EQ(0, memcmp(buffer->data(), "leD", kReadLength));
798 }
799
800 TEST_F(BlobReaderTest, DiskCacheRange) {
801 scoped_ptr<disk_cache::Backend> cache =
802 CreateInMemoryDiskCache(message_loop_.task_runner());
803 ASSERT_TRUE(cache);
804
805 BlobDataBuilder b("uuid");
806 const std::string kData = "Test Blob Data";
807 const uint64_t kOffset = 2;
808 const uint64_t kReadLength = 3;
809 scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
810 new EmptyDataHandle();
811 disk_cache::ScopedEntryPtr entry =
812 CreateDiskCacheEntry(cache.get(), "test entry", kData);
813 b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
814 this->InitializeReader(&b);
815
816 int size_result = -1;
817 EXPECT_EQ(BlobReader::Status::DONE,
818 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
819
820 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
821 EXPECT_EQ(BlobReader::Status::DONE,
822 reader_->SetReadRange(kOffset, kReadLength));
823
824 int bytes_read = 0;
825 int async_bytes_read = 0;
826 EXPECT_EQ(BlobReader::Status::DONE,
827 reader_->Read(buffer.get(), kReadLength, &bytes_read,
828 base::Bind(&SetValue<int>, &async_bytes_read)));
829 EXPECT_EQ(net::OK, reader_->net_error());
830 EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
831 EXPECT_EQ(0, async_bytes_read);
832 EXPECT_EQ(0, memcmp(buffer->data(), "st ", kReadLength));
833 }
834
835 TEST_F(BlobReaderTest, FileSomeAsyncSegmentedOffsetsUnknownSizes) {
836 // This tests includes:
837 // * Unknown file sizes (item length of uint64::max) for every other item.
838 // * Offsets for every 3rd file item.
839 // * Non-async reader for every 4th file item.
840 BlobDataBuilder b("uuid");
841 const FilePath kPathBase = FilePath::FromUTF8Unsafe("/fake/file.txt");
842 const base::Time kTime = base::Time::Now();
843 const size_t kNumItems = 10;
844 const size_t kItemSize = 6;
845 const size_t kBufferSize = 10;
846 const size_t kTotalSize = kNumItems * kItemSize;
847 char current_value = 0;
848 // Create blob and reader.
849 for (size_t i = 0; i < kNumItems; i++) {
850 current_value += kItemSize;
851 FilePath path = kPathBase.Append(
852 FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
853 uint64_t offset = i % 3 == 0 ? 1 : 0;
854 uint64_t size =
855 i % 2 == 0 ? kItemSize : std::numeric_limits<uint64_t>::max();
856 b.AppendFile(path, offset, size, kTime);
857 }
858 this->InitializeReader(&b);
859
860 // Set expectations.
861 current_value = 0;
862 for (size_t i = 0; i < kNumItems; i++) {
863 uint64_t offset = i % 3 == 0 ? 1 : 0;
864 scoped_ptr<char[]> buf(new char[kItemSize + offset]);
865 if (offset > 0) {
866 memset(buf.get(), 7, offset);
867 }
868 for (size_t j = 0; j < kItemSize; j++) {
869 buf.get()[j + offset] = current_value++;
870 }
871 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(
872 std::string(buf.get() + offset, kItemSize), kItemSize + offset));
873 if (i % 4 != 0) {
874 reader->DoAsync(message_loop_.task_runner().get());
875 }
876 FilePath path = kPathBase.Append(
877 FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
878 ExpectLocalFileCall(path, kTime, offset, reader.release());
879 }
880
881 int size_result = -1;
882 EXPECT_FALSE(IsReaderTotalSizeCalculated());
883 EXPECT_EQ(BlobReader::Status::IO_PENDING,
884 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
885 CheckSizeNotCalculatedYet(size_result);
886 message_loop_.RunUntilIdle();
887 CheckSizeCalculatedAsynchronously(kTotalSize, size_result);
888
889 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
890
891 current_value = 0;
892 for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
893 int bytes_read = 0;
894 int async_bytes_read = 0;
895 EXPECT_EQ(BlobReader::Status::IO_PENDING,
896 reader_->Read(buffer.get(), kBufferSize, &bytes_read,
897 base::Bind(&SetValue<int>, &async_bytes_read)));
898 message_loop_.RunUntilIdle();
899 EXPECT_EQ(net::OK, reader_->net_error());
900 EXPECT_EQ(0, bytes_read);
901 EXPECT_EQ(kBufferSize, static_cast<size_t>(async_bytes_read));
902 for (size_t j = 0; j < kBufferSize; j++) {
903 EXPECT_EQ(current_value, buffer->data()[j]);
904 current_value++;
905 }
906 }
907 }
908
909 TEST_F(BlobReaderTest, MixedContent) {
910 // Includes data, a file, and a disk cache entry.
911 scoped_ptr<disk_cache::Backend> cache =
912 CreateInMemoryDiskCache(message_loop_.task_runner());
913 ASSERT_TRUE(cache);
914
915 BlobDataBuilder b("uuid");
916 const std::string kData1("Hello ");
917 const std::string kData2("there. ");
918 const std::string kData3("This ");
919 const std::string kData4("is multi-content.");
920 const uint64_t kDataSize = 35;
921
922 const base::Time kTime = base::Time::Now();
923 const FilePath kData1Path = FilePath::FromUTF8Unsafe("/fake/file.txt");
924
925 disk_cache::ScopedEntryPtr entry3 =
926 CreateDiskCacheEntry(cache.get(), "test entry", kData3);
927
928 b.AppendFile(kData1Path, 0, kData1.size(), kTime);
929 b.AppendData(kData2);
930 b.AppendDiskCacheEntry(
931 scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()),
932 entry3.get(), kTestDiskCacheStreamIndex);
933 b.AppendData(kData4);
934
935 this->InitializeReader(&b);
936
937 scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData1));
938 reader->DoAsync(message_loop_.task_runner().get());
939 ExpectLocalFileCall(kData1Path, kTime, 0, reader.release());
940
941 int size_result = -1;
942 EXPECT_FALSE(IsReaderTotalSizeCalculated());
943 EXPECT_EQ(BlobReader::Status::IO_PENDING,
944 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
945 CheckSizeNotCalculatedYet(size_result);
946 message_loop_.RunUntilIdle();
947 CheckSizeCalculatedAsynchronously(kDataSize, size_result);
948
949 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
950
951 int bytes_read = 0;
952 int async_bytes_read = 0;
953 EXPECT_EQ(BlobReader::Status::IO_PENDING,
954 reader_->Read(buffer.get(), kDataSize, &bytes_read,
955 base::Bind(&SetValue<int>, &async_bytes_read)));
956 EXPECT_EQ(0, async_bytes_read);
957 message_loop_.RunUntilIdle();
958 EXPECT_EQ(net::OK, reader_->net_error());
959 EXPECT_EQ(0, bytes_read);
960 EXPECT_EQ(kDataSize, static_cast<size_t>(async_bytes_read));
961 EXPECT_EQ(0, memcmp(buffer->data(), "Hello there. This is multi-content.",
962 kDataSize));
963 }
964
965 TEST_F(BlobReaderTest, StateErrors) {
966 // Test common variables
967 int bytes_read = -1;
968 int async_bytes_read = -1;
969 int size_result = -1;
970 const std::string kData("Hello!!!");
971
972 // Case: Blob handle is a nullptr.
973 InitializeReader(nullptr);
974 EXPECT_EQ(BlobReader::Status::NET_ERROR,
975 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
976 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
977 EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10));
978 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
979 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(10);
980 EXPECT_EQ(BlobReader::Status::NET_ERROR,
981 reader_->Read(buffer.get(), 10, &bytes_read,
982 base::Bind(&SetValue<int>, &async_bytes_read)));
983 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
984
985 // Case: Not calling CalculateSize before SetReadRange.
986 BlobDataBuilder builder1("uuid1");
987 builder1.AppendData(kData);
988 InitializeReader(&builder1);
989 EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10));
990 EXPECT_EQ(net::ERR_FAILED, reader_->net_error());
991 EXPECT_EQ(BlobReader::Status::NET_ERROR,
992 reader_->Read(buffer.get(), 10, &bytes_read,
993 base::Bind(&SetValue<int>, &async_bytes_read)));
994 EXPECT_EQ(net::ERR_FAILED, reader_->net_error());
995 EXPECT_EQ(0, bytes_read);
996
997 // Case: Not calling CalculateSize before Read.
998 BlobDataBuilder builder2("uuid2");
999 builder2.AppendData(kData);
1000 InitializeReader(&builder2);
1001 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1002 reader_->Read(buffer.get(), 10, &bytes_read,
1003 base::Bind(&SetValue<int>, &async_bytes_read)));
1004 EXPECT_EQ(net::ERR_FAILED, reader_->net_error());
1005 EXPECT_EQ(0, bytes_read);
1006 }
1007
1008 TEST_F(BlobReaderTest, FileErrorsSync) {
1009 int size_result = -1;
1010 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
1011 const std::string kData = "FileData!!!";
1012 const base::Time kTime = base::Time::Now();
1013
1014 // Case: Error on length query.
1015 BlobDataBuilder builder1("uuid1");
1016 builder1.AppendFile(kPath, 0, kData.size(), kTime);
1017 this->InitializeReader(&builder1);
1018 FakeFileStreamReader* reader = new FakeFileStreamReader(kData);
1019 reader->ReturnError(net::ERR_FILE_NOT_FOUND);
1020 ExpectLocalFileCall(kPath, kTime, 0, reader);
1021
1022 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1023 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1024 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1025
1026 // Case: Error on read.
1027 BlobDataBuilder builder2("uuid2");
1028 builder2.AppendFile(kPath, 0, kData.size(), kTime);
1029 this->InitializeReader(&builder2);
1030 reader = new FakeFileStreamReader(kData);
1031 ExpectLocalFileCall(kPath, kTime, 0, reader);
1032 EXPECT_EQ(BlobReader::Status::DONE,
1033 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1034 reader->ReturnError(net::ERR_FILE_NOT_FOUND);
1035
1036 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
1037 int bytes_read = 0;
1038 int async_bytes_read = 0;
1039 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1040 reader_->Read(buffer.get(), kData.size(), &bytes_read,
1041 base::Bind(&SetValue<int>, &async_bytes_read)));
1042 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1043 }
1044
1045 TEST_F(BlobReaderTest, FileErrorsAsync) {
1046 int size_result = -1;
1047 const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
1048 const std::string kData = "FileData!!!";
1049 const base::Time kTime = base::Time::Now();
1050
1051 // Case: Error on length query.
1052 BlobDataBuilder builder1("uuid1");
1053 builder1.AppendFile(kPath, 0, kData.size(), kTime);
1054 this->InitializeReader(&builder1);
1055 FakeFileStreamReader* reader = new FakeFileStreamReader(kData);
1056 reader->DoAsync(message_loop_.task_runner().get());
1057 reader->ReturnError(net::ERR_FILE_NOT_FOUND);
1058 ExpectLocalFileCall(kPath, kTime, 0, reader);
1059
1060 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1061 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1062 EXPECT_EQ(net::OK, reader_->net_error());
1063 message_loop_.RunUntilIdle();
1064 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, size_result);
1065 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1066
1067 // Case: Error on read.
1068 BlobDataBuilder builder2("uuid2");
1069 builder2.AppendFile(kPath, 0, kData.size(), kTime);
1070 this->InitializeReader(&builder2);
1071 reader = new FakeFileStreamReader(kData);
1072 ExpectLocalFileCall(kPath, kTime, 0, reader);
1073 EXPECT_EQ(BlobReader::Status::DONE,
1074 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1075 reader->ReturnError(net::ERR_FILE_NOT_FOUND);
1076 reader->DoAsync(message_loop_.task_runner().get());
1077
1078 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
1079 int bytes_read = 0;
1080 int async_bytes_read = 0;
1081 EXPECT_EQ(BlobReader::Status::IO_PENDING,
1082 reader_->Read(buffer.get(), kData.size(), &bytes_read,
1083 base::Bind(&SetValue<int>, &async_bytes_read)));
1084 EXPECT_EQ(net::OK, reader_->net_error());
1085 message_loop_.RunUntilIdle();
1086 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, async_bytes_read);
1087 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1088 }
1089
1090 TEST_F(BlobReaderTest, RangeError) {
1091 const std::string kData("Hello!!!");
1092 const size_t kDataSize = 8ul;
1093 const uint64_t kReadLength = 4ull;
1094
1095 // Case: offset too high.
1096 BlobDataBuilder b("uuid1");
1097 b.AppendData(kData);
1098 this->InitializeReader(&b);
1099 int size_result = -1;
1100 EXPECT_EQ(BlobReader::Status::DONE,
1101 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1102 scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
1103 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1104 reader_->SetReadRange(kDataSize + 1, kReadLength));
1105 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1106
1107 // Case: length too long.
1108 BlobDataBuilder b2("uuid2");
1109 b2.AppendData(kData);
1110 this->InitializeReader(&b2);
1111 size_result = -1;
1112 EXPECT_EQ(BlobReader::Status::DONE,
1113 reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
1114 buffer = CreateBuffer(kDataSize + 1);
1115 EXPECT_EQ(BlobReader::Status::NET_ERROR,
1116 reader_->SetReadRange(0, kDataSize + 1));
1117 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
1118 }
1119
1120 } // namespace
1121 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698