1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/run_loop.h"
13 #include "base/threading/thread.h"
14 #include "chrome/browser/chromeos/drive/fake_file_system.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/drive/local_file_reader.h"
17 #include "chrome/browser/chromeos/drive/test_util.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/drive/test_util.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "google_apis/drive/drive_api_parser.h"
22 #include "google_apis/drive/test_util.h"
23 #include "net/base/io_buffer.h"
24 #include "net/base/net_errors.h"
25 #include "net/base/test_completion_callback.h"
26 #include "net/http/http_byte_range.h"
27 #include "testing/gtest/include/gtest/gtest.h"
33 // Increments the |num_called|, when this method is invoked.
34 void IncrementCallback(int* num_called) {
41 class LocalReaderProxyTest : public ::testing::Test {
43 LocalReaderProxyTest()
44 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
47 virtual void SetUp() OVERRIDE {
48 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
49 ASSERT_TRUE(google_apis::test_util::CreateFileOfSpecifiedSize(
50 temp_dir_.path(), 1024, &file_path_, &file_content_));
52 worker_thread_.reset(new base::Thread("ReaderProxyTest"));
53 ASSERT_TRUE(worker_thread_->Start());
56 content::TestBrowserThreadBundle thread_bundle_;
58 base::ScopedTempDir temp_dir_;
59 base::FilePath file_path_;
60 std::string file_content_;
62 scoped_ptr<base::Thread> worker_thread_;
65 TEST_F(LocalReaderProxyTest, Read) {
66 // Open the file first.
67 scoped_ptr<util::LocalFileReader> file_reader(
68 new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
69 net::TestCompletionCallback callback;
70 file_reader->Open(file_path_, 0, callback.callback());
71 ASSERT_EQ(net::OK, callback.WaitForResult());
74 LocalReaderProxy proxy(file_reader.Pass(), file_content_.size());
76 // Make sure the read content is as same as the file.
78 ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
79 EXPECT_EQ(file_content_, content);
82 TEST_F(LocalReaderProxyTest, ReadWithLimit) {
83 // This test case, we only read first half of the file.
84 const std::string expected_content =
85 file_content_.substr(0, file_content_.size() / 2);
87 // Open the file first.
88 scoped_ptr<util::LocalFileReader> file_reader(
89 new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
90 net::TestCompletionCallback callback;
91 file_reader->Open(file_path_, 0, callback.callback());
92 ASSERT_EQ(net::OK, callback.WaitForResult());
95 LocalReaderProxy proxy(file_reader.Pass(), expected_content.size());
97 // Make sure the read content is as same as the file.
99 ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
100 EXPECT_EQ(expected_content, content);
103 class NetworkReaderProxyTest : public ::testing::Test {
105 NetworkReaderProxyTest()
106 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
109 content::TestBrowserThreadBundle thread_bundle_;
112 TEST_F(NetworkReaderProxyTest, EmptyFile) {
113 NetworkReaderProxy proxy(0, 0, 0, base::Bind(&base::DoNothing));
115 net::TestCompletionCallback callback;
116 const int kBufferSize = 10;
117 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
118 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
120 // For empty file, Read() should return 0 immediately.
121 EXPECT_EQ(0, result);
124 TEST_F(NetworkReaderProxyTest, Read) {
125 int cancel_called = 0;
127 NetworkReaderProxy proxy(0, 10, 10,
128 base::Bind(&IncrementCallback, &cancel_called));
130 net::TestCompletionCallback callback;
131 const int kBufferSize = 3;
132 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
134 // If no data is available yet, ERR_IO_PENDING should be returned.
135 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
136 EXPECT_EQ(net::ERR_IO_PENDING, result);
138 // And when the data is supplied, the callback will be called.
139 scoped_ptr<std::string> data(new std::string("abcde"));
140 proxy.OnGetContent(data.Pass());
142 // The returned data should be fit to the buffer size.
143 result = callback.GetResult(result);
144 EXPECT_EQ(3, result);
145 EXPECT_EQ("abc", std::string(buffer->data(), result));
147 // The next Read should return immediately because there is pending data
148 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
149 EXPECT_EQ(2, result);
150 EXPECT_EQ("de", std::string(buffer->data(), result));
152 // Supply the data before calling Read operation.
153 data.reset(new std::string("fg"));
154 proxy.OnGetContent(data.Pass());
155 data.reset(new std::string("hij"));
156 proxy.OnGetContent(data.Pass()); // Now 10 bytes are supplied.
158 // The data should be concatenated if possible.
159 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
160 EXPECT_EQ(3, result);
161 EXPECT_EQ("fgh", std::string(buffer->data(), result));
163 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
164 EXPECT_EQ(2, result);
165 EXPECT_EQ("ij", std::string(buffer->data(), result));
167 // The whole data is read, so Read() should return 0 immediately by then.
168 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
169 EXPECT_EQ(0, result);
172 // Proxy is deleted without any called to OnCompleted(). Even in the case,
173 // cancel callback should not be invoked.
174 EXPECT_EQ(0, cancel_called);
177 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
178 NetworkReaderProxy proxy(10, 10, 10, base::Bind(&base::DoNothing));
180 net::TestCompletionCallback callback;
181 const int kBufferSize = 3;
182 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
184 // If no data is available yet, ERR_IO_PENDING should be returned.
185 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
186 EXPECT_EQ(net::ERR_IO_PENDING, result);
188 // And when the data is supplied, the callback will be called.
189 scoped_ptr<std::string> data(new std::string("abcde"));
190 proxy.OnGetContent(data.Pass());
191 data.reset(new std::string("fgh"));
192 proxy.OnGetContent(data.Pass());
193 data.reset(new std::string("ijklmno"));
194 proxy.OnGetContent(data.Pass());
196 // The returned data should be fit to the buffer size.
197 result = callback.GetResult(result);
198 EXPECT_EQ(3, result);
199 EXPECT_EQ("klm", std::string(buffer->data(), result));
201 // The next Read should return immediately because there is pending data
202 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
203 EXPECT_EQ(2, result);
204 EXPECT_EQ("no", std::string(buffer->data(), result));
206 // Supply the data before calling Read operation.
207 data.reset(new std::string("pqrs"));
208 proxy.OnGetContent(data.Pass());
209 data.reset(new std::string("tuvwxyz"));
210 proxy.OnGetContent(data.Pass()); // 't' is the 20-th byte.
212 // The data should be concatenated if possible.
213 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
214 EXPECT_EQ(3, result);
215 EXPECT_EQ("pqr", std::string(buffer->data(), result));
217 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
218 EXPECT_EQ(2, result);
219 EXPECT_EQ("st", std::string(buffer->data(), result));
221 // The whole data is read, so Read() should return 0 immediately by then.
222 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
223 EXPECT_EQ(0, result);
226 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
227 NetworkReaderProxy proxy(0, 10, 10, base::Bind(&base::DoNothing));
229 net::TestCompletionCallback callback;
230 const int kBufferSize = 3;
231 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
233 // Set pending callback.
234 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
235 EXPECT_EQ(net::ERR_IO_PENDING, result);
237 // Emulate that an error is found. The callback should be called internally.
238 proxy.OnCompleted(FILE_ERROR_FAILED);
239 result = callback.GetResult(result);
240 EXPECT_EQ(net::ERR_FAILED, result);
242 // The next Read call should also return the same error code.
243 EXPECT_EQ(net::ERR_FAILED,
244 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
247 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
248 NetworkReaderProxy proxy(0, 10, 10, base::Bind(&base::DoNothing));
250 net::TestCompletionCallback callback;
251 const int kBufferSize = 3;
252 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
254 // Supply the data before an error.
255 scoped_ptr<std::string> data(new std::string("abcde"));
256 proxy.OnGetContent(data.Pass());
258 // Emulate that an error is found.
259 proxy.OnCompleted(FILE_ERROR_FAILED);
261 // The next Read call should return the error code, even if there is
262 // pending data (the pending data should be released in OnCompleted.
263 EXPECT_EQ(net::ERR_FAILED,
264 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
267 TEST_F(NetworkReaderProxyTest, CancelJob) {
270 NetworkReaderProxy proxy(
271 0, 0, 0, base::Bind(&IncrementCallback, &num_called));
272 proxy.OnCompleted(FILE_ERROR_OK);
273 // Destroy the instance after the network operation is completed.
274 // The cancelling callback shouldn't be called.
276 EXPECT_EQ(0, num_called);
280 NetworkReaderProxy proxy(
281 0, 0, 0, base::Bind(&IncrementCallback, &num_called));
282 // Destroy the instance before the network operation is completed.
283 // The cancelling callback should be called.
285 EXPECT_EQ(1, num_called);
288 } // namespace internal
290 class DriveFileStreamReaderTest : public ::testing::Test {
292 DriveFileStreamReaderTest()
293 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
296 virtual void SetUp() OVERRIDE {
297 worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
298 ASSERT_TRUE(worker_thread_->Start());
300 // Initialize FakeDriveService.
301 fake_drive_service_.reset(new FakeDriveService);
302 ASSERT_TRUE(test_util::SetUpTestEntries(fake_drive_service_.get()));
304 // Create a testee instance.
305 fake_file_system_.reset(
306 new test_util::FakeFileSystem(fake_drive_service_.get()));
309 FileSystemInterface* GetFileSystem() {
310 return fake_file_system_.get();
313 DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
314 return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
315 base::Unretained(this));
318 content::TestBrowserThreadBundle thread_bundle_;
320 scoped_ptr<base::Thread> worker_thread_;
322 scoped_ptr<FakeDriveService> fake_drive_service_;
323 scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
326 TEST_F(DriveFileStreamReaderTest, Read) {
327 const base::FilePath kDriveFile =
328 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
329 // Create the reader, and initialize it.
330 // In this case, the file is not yet locally cached.
331 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
332 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
333 EXPECT_FALSE(reader->IsInitialized());
335 int error = net::ERR_FAILED;
336 scoped_ptr<ResourceEntry> entry;
338 base::RunLoop run_loop;
341 net::HttpByteRange(),
342 google_apis::test_util::CreateQuitCallback(
344 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
347 EXPECT_EQ(net::OK, error);
349 EXPECT_TRUE(reader->IsInitialized());
350 size_t content_size = entry->file_info().size();
352 // Read data from the reader.
353 std::string first_content;
354 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
355 EXPECT_EQ(content_size, first_content.size());
357 // Create second instance and initialize it.
358 // In this case, the file should be cached one.
359 reader.reset(new DriveFileStreamReader(
360 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
361 EXPECT_FALSE(reader->IsInitialized());
363 error = net::ERR_FAILED;
366 base::RunLoop run_loop;
369 net::HttpByteRange(),
370 google_apis::test_util::CreateQuitCallback(
372 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
375 EXPECT_EQ(net::OK, error);
377 EXPECT_TRUE(reader->IsInitialized());
379 // The size should be same.
380 EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
382 // Read data from the reader, again.
383 std::string second_content;
384 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
386 // The same content is expected.
387 EXPECT_EQ(first_content, second_content);
390 TEST_F(DriveFileStreamReaderTest, ReadRange) {
391 // In this test case, we just confirm that the part of file is read.
392 const int64 kRangeOffset = 3;
393 const int64 kRangeLength = 4;
395 const base::FilePath kDriveFile =
396 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
397 // Create the reader, and initialize it.
398 // In this case, the file is not yet locally cached.
399 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
400 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
401 EXPECT_FALSE(reader->IsInitialized());
403 int error = net::ERR_FAILED;
404 scoped_ptr<ResourceEntry> entry;
405 net::HttpByteRange byte_range;
406 byte_range.set_first_byte_position(kRangeOffset);
407 // Last byte position is inclusive.
408 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
410 base::RunLoop run_loop;
414 google_apis::test_util::CreateQuitCallback(
416 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
419 EXPECT_EQ(net::OK, error);
421 EXPECT_TRUE(reader->IsInitialized());
423 // Read data from the reader.
424 std::string first_content;
425 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
427 // The length should be equal to range length.
428 EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
430 // Create second instance and initialize it.
431 // In this case, the file should be cached one.
432 reader.reset(new DriveFileStreamReader(
433 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
434 EXPECT_FALSE(reader->IsInitialized());
436 error = net::ERR_FAILED;
439 base::RunLoop run_loop;
443 google_apis::test_util::CreateQuitCallback(
445 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
448 EXPECT_EQ(net::OK, error);
450 EXPECT_TRUE(reader->IsInitialized());
452 // Read data from the reader, again.
453 std::string second_content;
454 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
456 // The same content is expected.
457 EXPECT_EQ(first_content, second_content);
460 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
461 const int64 kRangeOffset = 1000000; // Out of range.
462 const int64 kRangeLength = 4;
464 const base::FilePath kDriveFile =
465 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
466 // Create the reader, and initialize it.
467 // In this case, the file is not yet locally cached.
468 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
469 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
470 EXPECT_FALSE(reader->IsInitialized());
472 int error = net::ERR_FAILED;
473 scoped_ptr<ResourceEntry> entry;
474 net::HttpByteRange byte_range;
475 byte_range.set_first_byte_position(kRangeOffset);
476 // Last byte position is inclusive.
477 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
479 base::RunLoop run_loop;
483 google_apis::test_util::CreateQuitCallback(
485 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
488 EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
492 TEST_F(DriveFileStreamReaderTest, ZeroByteFileRead) {
493 // Prepare an empty file
495 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
496 scoped_ptr<google_apis::FileResource> entry;
497 fake_drive_service_->AddNewFile(
500 fake_drive_service_->GetRootResourceId(),
502 false, // shared_with_me
503 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
504 drive::test_util::RunBlockingPoolTask();
505 ASSERT_EQ(google_apis::HTTP_CREATED, error);
507 ASSERT_EQ(0, entry->file_size());
510 const base::FilePath kDriveFile =
511 util::GetDriveMyDriveRootPath().AppendASCII("EmptyFile.txt");
512 // Create the reader, and initialize it.
513 // In this case, the file is not yet locally cached.
514 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
515 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
516 EXPECT_FALSE(reader->IsInitialized());
518 int error = net::ERR_FAILED;
519 scoped_ptr<ResourceEntry> entry;
521 base::RunLoop run_loop;
524 net::HttpByteRange(),
525 google_apis::test_util::CreateQuitCallback(
527 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
530 EXPECT_EQ(net::OK, error);
532 ASSERT_EQ(0u, entry->file_info().size()); // It's a zero-byte file.
533 EXPECT_TRUE(reader->IsInitialized());
535 // Read data from the reader. Check that it successfuly reads empty data.
536 std::string first_content;
537 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
538 EXPECT_EQ(0u, first_content.size());
540 // Create second instance and initialize it.
541 // In this case, the file should be cached one.
542 reader.reset(new DriveFileStreamReader(
543 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
544 EXPECT_FALSE(reader->IsInitialized());
546 error = net::ERR_FAILED;
549 base::RunLoop run_loop;
552 net::HttpByteRange(),
553 google_apis::test_util::CreateQuitCallback(
555 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
558 EXPECT_EQ(net::OK, error);
560 EXPECT_TRUE(reader->IsInitialized());
562 // Read data from the reader, again.
563 std::string second_content;
564 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
565 EXPECT_EQ(0u, second_content.size());