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

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

Powered by Google App Engine
This is Rietveld 408576698