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/gdata_wapi_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, 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 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
127 net::TestCompletionCallback callback;
128 const int kBufferSize = 3;
129 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
131 // If no data is available yet, ERR_IO_PENDING should be returned.
132 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
133 EXPECT_EQ(net::ERR_IO_PENDING, result);
135 // And when the data is supplied, the callback will be called.
136 scoped_ptr<std::string> data(new std::string("abcde"));
137 proxy.OnGetContent(data.Pass());
139 // The returned data should be fit to the buffer size.
140 result = callback.GetResult(result);
141 EXPECT_EQ(3, result);
142 EXPECT_EQ("abc", std::string(buffer->data(), result));
144 // The next Read should return immediately because there is pending data
145 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
146 EXPECT_EQ(2, result);
147 EXPECT_EQ("de", std::string(buffer->data(), result));
149 // Supply the data before calling Read operation.
150 data.reset(new std::string("fg"));
151 proxy.OnGetContent(data.Pass());
152 data.reset(new std::string("hij"));
153 proxy.OnGetContent(data.Pass()); // Now 10 bytes are supplied.
155 // The data should be concatenated if possible.
156 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
157 EXPECT_EQ(3, result);
158 EXPECT_EQ("fgh", std::string(buffer->data(), result));
160 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
161 EXPECT_EQ(2, result);
162 EXPECT_EQ("ij", std::string(buffer->data(), result));
164 // The whole data is read, so Read() should return 0 immediately by then.
165 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
166 EXPECT_EQ(0, result);
169 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
170 NetworkReaderProxy proxy(10, 10, base::Bind(&base::DoNothing));
172 net::TestCompletionCallback callback;
173 const int kBufferSize = 3;
174 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
176 // If no data is available yet, ERR_IO_PENDING should be returned.
177 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
178 EXPECT_EQ(net::ERR_IO_PENDING, result);
180 // And when the data is supplied, the callback will be called.
181 scoped_ptr<std::string> data(new std::string("abcde"));
182 proxy.OnGetContent(data.Pass());
183 data.reset(new std::string("fgh"));
184 proxy.OnGetContent(data.Pass());
185 data.reset(new std::string("ijklmno"));
186 proxy.OnGetContent(data.Pass());
188 // The returned data should be fit to the buffer size.
189 result = callback.GetResult(result);
190 EXPECT_EQ(3, result);
191 EXPECT_EQ("klm", std::string(buffer->data(), result));
193 // The next Read should return immediately because there is pending data
194 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
195 EXPECT_EQ(2, result);
196 EXPECT_EQ("no", std::string(buffer->data(), result));
198 // Supply the data before calling Read operation.
199 data.reset(new std::string("pqrs"));
200 proxy.OnGetContent(data.Pass());
201 data.reset(new std::string("tuvwxyz"));
202 proxy.OnGetContent(data.Pass()); // 't' is the 20-th byte.
204 // The data should be concatenated if possible.
205 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
206 EXPECT_EQ(3, result);
207 EXPECT_EQ("pqr", std::string(buffer->data(), result));
209 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
210 EXPECT_EQ(2, result);
211 EXPECT_EQ("st", std::string(buffer->data(), result));
213 // The whole data is read, so Read() should return 0 immediately by then.
214 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
215 EXPECT_EQ(0, result);
218 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
219 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
221 net::TestCompletionCallback callback;
222 const int kBufferSize = 3;
223 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
225 // Set pending callback.
226 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
227 EXPECT_EQ(net::ERR_IO_PENDING, result);
229 // Emulate that an error is found. The callback should be called internally.
230 proxy.OnCompleted(FILE_ERROR_FAILED);
231 result = callback.GetResult(result);
232 EXPECT_EQ(net::ERR_FAILED, result);
234 // The next Read call should also return the same error code.
235 EXPECT_EQ(net::ERR_FAILED,
236 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
239 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
240 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
242 net::TestCompletionCallback callback;
243 const int kBufferSize = 3;
244 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
246 // Supply the data before an error.
247 scoped_ptr<std::string> data(new std::string("abcde"));
248 proxy.OnGetContent(data.Pass());
250 // Emulate that an error is found.
251 proxy.OnCompleted(FILE_ERROR_FAILED);
253 // The next Read call should return the error code, even if there is
254 // pending data (the pending data should be released in OnCompleted.
255 EXPECT_EQ(net::ERR_FAILED,
256 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
259 TEST_F(NetworkReaderProxyTest, CancelJob) {
262 NetworkReaderProxy proxy(
263 0, 0, base::Bind(&IncrementCallback, &num_called));
264 proxy.OnCompleted(FILE_ERROR_OK);
265 // Destroy the instance after the network operation is completed.
266 // The cancelling callback shouldn't be called.
268 EXPECT_EQ(0, num_called);
272 NetworkReaderProxy proxy(
273 0, 0, base::Bind(&IncrementCallback, &num_called));
274 // Destroy the instance before the network operation is completed.
275 // The cancelling callback should be called.
277 EXPECT_EQ(1, num_called);
280 } // namespace internal
282 class DriveFileStreamReaderTest : public ::testing::Test {
284 DriveFileStreamReaderTest()
285 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
288 virtual void SetUp() OVERRIDE {
289 worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
290 ASSERT_TRUE(worker_thread_->Start());
292 // Initialize FakeDriveService.
293 fake_drive_service_.reset(new FakeDriveService);
294 ASSERT_TRUE(test_util::SetUpTestEntries(fake_drive_service_.get()));
296 // Create a testee instance.
297 fake_file_system_.reset(
298 new test_util::FakeFileSystem(fake_drive_service_.get()));
301 FileSystemInterface* GetFileSystem() {
302 return fake_file_system_.get();
305 DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
306 return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
307 base::Unretained(this));
310 content::TestBrowserThreadBundle thread_bundle_;
312 scoped_ptr<base::Thread> worker_thread_;
314 scoped_ptr<FakeDriveService> fake_drive_service_;
315 scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
318 TEST_F(DriveFileStreamReaderTest, Read) {
319 const base::FilePath kDriveFile =
320 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
321 // Create the reader, and initialize it.
322 // In this case, the file is not yet locally cached.
323 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
324 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
325 EXPECT_FALSE(reader->IsInitialized());
327 int error = net::ERR_FAILED;
328 scoped_ptr<ResourceEntry> entry;
330 base::RunLoop run_loop;
333 net::HttpByteRange(),
334 google_apis::test_util::CreateQuitCallback(
336 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
339 EXPECT_EQ(net::OK, error);
341 EXPECT_TRUE(reader->IsInitialized());
342 size_t content_size = entry->file_info().size();
344 // Read data from the reader.
345 std::string first_content;
346 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
347 EXPECT_EQ(content_size, first_content.size());
349 // Create second instance and initialize it.
350 // In this case, the file should be cached one.
351 reader.reset(new DriveFileStreamReader(
352 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
353 EXPECT_FALSE(reader->IsInitialized());
355 error = net::ERR_FAILED;
358 base::RunLoop run_loop;
361 net::HttpByteRange(),
362 google_apis::test_util::CreateQuitCallback(
364 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
367 EXPECT_EQ(net::OK, error);
369 EXPECT_TRUE(reader->IsInitialized());
371 // The size should be same.
372 EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
374 // Read data from the reader, again.
375 std::string second_content;
376 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
378 // The same content is expected.
379 EXPECT_EQ(first_content, second_content);
382 TEST_F(DriveFileStreamReaderTest, ReadRange) {
383 // In this test case, we just confirm that the part of file is read.
384 const int64 kRangeOffset = 3;
385 const int64 kRangeLength = 4;
387 const base::FilePath kDriveFile =
388 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
389 // Create the reader, and initialize it.
390 // In this case, the file is not yet locally cached.
391 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
392 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
393 EXPECT_FALSE(reader->IsInitialized());
395 int error = net::ERR_FAILED;
396 scoped_ptr<ResourceEntry> entry;
397 net::HttpByteRange byte_range;
398 byte_range.set_first_byte_position(kRangeOffset);
399 // Last byte position is inclusive.
400 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
402 base::RunLoop run_loop;
406 google_apis::test_util::CreateQuitCallback(
408 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
411 EXPECT_EQ(net::OK, error);
413 EXPECT_TRUE(reader->IsInitialized());
415 // Read data from the reader.
416 std::string first_content;
417 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
419 // The length should be equal to range length.
420 EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
422 // Create second instance and initialize it.
423 // In this case, the file should be cached one.
424 reader.reset(new DriveFileStreamReader(
425 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
426 EXPECT_FALSE(reader->IsInitialized());
428 error = net::ERR_FAILED;
431 base::RunLoop run_loop;
435 google_apis::test_util::CreateQuitCallback(
437 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
440 EXPECT_EQ(net::OK, error);
442 EXPECT_TRUE(reader->IsInitialized());
444 // Read data from the reader, again.
445 std::string second_content;
446 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
448 // The same content is expected.
449 EXPECT_EQ(first_content, second_content);
452 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
453 const int64 kRangeOffset = 1000000; // Out of range.
454 const int64 kRangeLength = 4;
456 const base::FilePath kDriveFile =
457 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
458 // Create the reader, and initialize it.
459 // In this case, the file is not yet locally cached.
460 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
461 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
462 EXPECT_FALSE(reader->IsInitialized());
464 int error = net::ERR_FAILED;
465 scoped_ptr<ResourceEntry> entry;
466 net::HttpByteRange byte_range;
467 byte_range.set_first_byte_position(kRangeOffset);
468 // Last byte position is inclusive.
469 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
471 base::RunLoop run_loop;
475 google_apis::test_util::CreateQuitCallback(
477 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
480 EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
484 TEST_F(DriveFileStreamReaderTest, ZeroByteFileRead) {
485 // Prepare an empty file
487 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
488 scoped_ptr<google_apis::ResourceEntry> entry;
489 fake_drive_service_->AddNewFile(
492 fake_drive_service_->GetRootResourceId(),
494 false, // shared_with_me
495 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
496 drive::test_util::RunBlockingPoolTask();
497 ASSERT_EQ(google_apis::HTTP_CREATED, error);
499 ASSERT_EQ(0, entry->file_size());
502 const base::FilePath kDriveFile =
503 util::GetDriveMyDriveRootPath().AppendASCII("EmptyFile.txt");
504 // Create the reader, and initialize it.
505 // In this case, the file is not yet locally cached.
506 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
507 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
508 EXPECT_FALSE(reader->IsInitialized());
510 int error = net::ERR_FAILED;
511 scoped_ptr<ResourceEntry> entry;
513 base::RunLoop run_loop;
516 net::HttpByteRange(),
517 google_apis::test_util::CreateQuitCallback(
519 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
522 EXPECT_EQ(net::OK, error);
524 ASSERT_EQ(0u, entry->file_info().size()); // It's a zero-byte file.
525 EXPECT_TRUE(reader->IsInitialized());
527 // Read data from the reader. Check that it successfuly reads empty data.
528 std::string first_content;
529 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
530 EXPECT_EQ(0u, first_content.size());
532 // Create second instance and initialize it.
533 // In this case, the file should be cached one.
534 reader.reset(new DriveFileStreamReader(
535 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
536 EXPECT_FALSE(reader->IsInitialized());
538 error = net::ERR_FAILED;
541 base::RunLoop run_loop;
544 net::HttpByteRange(),
545 google_apis::test_util::CreateQuitCallback(
547 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
550 EXPECT_EQ(net::OK, error);
552 EXPECT_TRUE(reader->IsInitialized());
554 // Read data from the reader, again.
555 std::string second_content;
556 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
557 EXPECT_EQ(0u, second_content.size());