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

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

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

Powered by Google App Engine
This is Rietveld 408576698