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

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

Powered by Google App Engine
This is Rietveld 408576698