Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / drive_file_stream_reader_unittest.cc
blob89bf9971faa9d80f58df1ded750fe47196161475
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"
7 #include <string>
9 #include "base/bind.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 "content/public/test/test_browser_thread_bundle.h"
20 #include "google_apis/drive/gdata_wapi_parser.h"
21 #include "google_apis/drive/test_util.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/test_completion_callback.h"
25 #include "net/http/http_byte_range.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace drive {
29 namespace internal {
30 namespace {
32 // Increments the |num_called|, when this method is invoked.
33 void IncrementCallback(int* num_called) {
34 DCHECK(num_called);
35 ++*num_called;
38 } // namespace
40 class LocalReaderProxyTest : public ::testing::Test {
41 protected:
42 LocalReaderProxyTest()
43 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
46 virtual void SetUp() OVERRIDE {
47 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
48 ASSERT_TRUE(google_apis::test_util::CreateFileOfSpecifiedSize(
49 temp_dir_.path(), 1024, &file_path_, &file_content_));
51 worker_thread_.reset(new base::Thread("ReaderProxyTest"));
52 ASSERT_TRUE(worker_thread_->Start());
55 content::TestBrowserThreadBundle thread_bundle_;
57 base::ScopedTempDir temp_dir_;
58 base::FilePath file_path_;
59 std::string file_content_;
61 scoped_ptr<base::Thread> worker_thread_;
64 TEST_F(LocalReaderProxyTest, Read) {
65 // Open the file first.
66 scoped_ptr<util::LocalFileReader> file_reader(
67 new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
68 net::TestCompletionCallback callback;
69 file_reader->Open(file_path_, 0, callback.callback());
70 ASSERT_EQ(net::OK, callback.WaitForResult());
72 // Test instance.
73 LocalReaderProxy proxy(file_reader.Pass(), file_content_.size());
75 // Make sure the read content is as same as the file.
76 std::string content;
77 ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
78 EXPECT_EQ(file_content_, content);
81 TEST_F(LocalReaderProxyTest, ReadWithLimit) {
82 // This test case, we only read first half of the file.
83 const std::string expected_content =
84 file_content_.substr(0, file_content_.size() / 2);
86 // Open the file first.
87 scoped_ptr<util::LocalFileReader> file_reader(
88 new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
89 net::TestCompletionCallback callback;
90 file_reader->Open(file_path_, 0, callback.callback());
91 ASSERT_EQ(net::OK, callback.WaitForResult());
93 // Test instance.
94 LocalReaderProxy proxy(file_reader.Pass(), expected_content.size());
96 // Make sure the read content is as same as the file.
97 std::string content;
98 ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
99 EXPECT_EQ(expected_content, content);
102 class NetworkReaderProxyTest : public ::testing::Test {
103 protected:
104 NetworkReaderProxyTest()
105 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
108 content::TestBrowserThreadBundle thread_bundle_;
111 TEST_F(NetworkReaderProxyTest, EmptyFile) {
112 NetworkReaderProxy proxy(0, 0, base::Bind(&base::DoNothing));
114 net::TestCompletionCallback callback;
115 const int kBufferSize = 10;
116 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
117 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
119 // For empty file, Read() should return 0 immediately.
120 EXPECT_EQ(0, result);
123 TEST_F(NetworkReaderProxyTest, Read) {
124 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
126 net::TestCompletionCallback callback;
127 const int kBufferSize = 3;
128 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
130 // If no data is available yet, ERR_IO_PENDING should be returned.
131 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
132 EXPECT_EQ(net::ERR_IO_PENDING, result);
134 // And when the data is supplied, the callback will be called.
135 scoped_ptr<std::string> data(new std::string("abcde"));
136 proxy.OnGetContent(data.Pass());
138 // The returned data should be fit to the buffer size.
139 result = callback.GetResult(result);
140 EXPECT_EQ(3, result);
141 EXPECT_EQ("abc", std::string(buffer->data(), result));
143 // The next Read should return immediately because there is pending data
144 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
145 EXPECT_EQ(2, result);
146 EXPECT_EQ("de", std::string(buffer->data(), result));
148 // Supply the data before calling Read operation.
149 data.reset(new std::string("fg"));
150 proxy.OnGetContent(data.Pass());
151 data.reset(new std::string("hij"));
152 proxy.OnGetContent(data.Pass()); // Now 10 bytes are supplied.
154 // The data should be concatenated if possible.
155 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
156 EXPECT_EQ(3, result);
157 EXPECT_EQ("fgh", std::string(buffer->data(), result));
159 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
160 EXPECT_EQ(2, result);
161 EXPECT_EQ("ij", std::string(buffer->data(), result));
163 // The whole data is read, so Read() should return 0 immediately by then.
164 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
165 EXPECT_EQ(0, result);
168 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
169 NetworkReaderProxy proxy(10, 10, base::Bind(&base::DoNothing));
171 net::TestCompletionCallback callback;
172 const int kBufferSize = 3;
173 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
175 // If no data is available yet, ERR_IO_PENDING should be returned.
176 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
177 EXPECT_EQ(net::ERR_IO_PENDING, result);
179 // And when the data is supplied, the callback will be called.
180 scoped_ptr<std::string> data(new std::string("abcde"));
181 proxy.OnGetContent(data.Pass());
182 data.reset(new std::string("fgh"));
183 proxy.OnGetContent(data.Pass());
184 data.reset(new std::string("ijklmno"));
185 proxy.OnGetContent(data.Pass());
187 // The returned data should be fit to the buffer size.
188 result = callback.GetResult(result);
189 EXPECT_EQ(3, result);
190 EXPECT_EQ("klm", std::string(buffer->data(), result));
192 // The next Read should return immediately because there is pending data
193 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
194 EXPECT_EQ(2, result);
195 EXPECT_EQ("no", std::string(buffer->data(), result));
197 // Supply the data before calling Read operation.
198 data.reset(new std::string("pqrs"));
199 proxy.OnGetContent(data.Pass());
200 data.reset(new std::string("tuvwxyz"));
201 proxy.OnGetContent(data.Pass()); // 't' is the 20-th byte.
203 // The data should be concatenated if possible.
204 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
205 EXPECT_EQ(3, result);
206 EXPECT_EQ("pqr", std::string(buffer->data(), result));
208 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
209 EXPECT_EQ(2, result);
210 EXPECT_EQ("st", std::string(buffer->data(), result));
212 // The whole data is read, so Read() should return 0 immediately by then.
213 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
214 EXPECT_EQ(0, result);
217 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
218 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
220 net::TestCompletionCallback callback;
221 const int kBufferSize = 3;
222 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
224 // Set pending callback.
225 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
226 EXPECT_EQ(net::ERR_IO_PENDING, result);
228 // Emulate that an error is found. The callback should be called internally.
229 proxy.OnCompleted(FILE_ERROR_FAILED);
230 result = callback.GetResult(result);
231 EXPECT_EQ(net::ERR_FAILED, result);
233 // The next Read call should also return the same error code.
234 EXPECT_EQ(net::ERR_FAILED,
235 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
238 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
239 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
241 net::TestCompletionCallback callback;
242 const int kBufferSize = 3;
243 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
245 // Supply the data before an error.
246 scoped_ptr<std::string> data(new std::string("abcde"));
247 proxy.OnGetContent(data.Pass());
249 // Emulate that an error is found.
250 proxy.OnCompleted(FILE_ERROR_FAILED);
252 // The next Read call should return the error code, even if there is
253 // pending data (the pending data should be released in OnCompleted.
254 EXPECT_EQ(net::ERR_FAILED,
255 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
258 TEST_F(NetworkReaderProxyTest, CancelJob) {
259 int num_called = 0;
261 NetworkReaderProxy proxy(
262 0, 0, base::Bind(&IncrementCallback, &num_called));
263 proxy.OnCompleted(FILE_ERROR_OK);
264 // Destroy the instance after the network operation is completed.
265 // The cancelling callback shouldn't be called.
267 EXPECT_EQ(0, num_called);
269 num_called = 0;
271 NetworkReaderProxy proxy(
272 0, 0, base::Bind(&IncrementCallback, &num_called));
273 // Destroy the instance before the network operation is completed.
274 // The cancelling callback should be called.
276 EXPECT_EQ(1, num_called);
279 } // namespace internal
281 class DriveFileStreamReaderTest : public ::testing::Test {
282 protected:
283 DriveFileStreamReaderTest()
284 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
287 virtual void SetUp() OVERRIDE {
288 worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
289 ASSERT_TRUE(worker_thread_->Start());
291 // Initialize FakeDriveService.
292 fake_drive_service_.reset(new FakeDriveService);
293 fake_drive_service_->LoadResourceListForWapi(
294 "gdata/root_feed.json");
295 fake_drive_service_->LoadAccountMetadataForWapi(
296 "gdata/account_metadata.json");
298 // Create a testee instance.
299 fake_file_system_.reset(
300 new test_util::FakeFileSystem(fake_drive_service_.get()));
303 FileSystemInterface* GetFileSystem() {
304 return fake_file_system_.get();
307 DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
308 return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
309 base::Unretained(this));
312 content::TestBrowserThreadBundle thread_bundle_;
314 scoped_ptr<base::Thread> worker_thread_;
316 scoped_ptr<FakeDriveService> fake_drive_service_;
317 scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
320 TEST_F(DriveFileStreamReaderTest, Read) {
321 const base::FilePath kDriveFile =
322 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
323 // Create the reader, and initialize it.
324 // In this case, the file is not yet locally cached.
325 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
326 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
327 EXPECT_FALSE(reader->IsInitialized());
329 int error = net::ERR_FAILED;
330 scoped_ptr<ResourceEntry> entry;
332 base::RunLoop run_loop;
333 reader->Initialize(
334 kDriveFile,
335 net::HttpByteRange(),
336 google_apis::test_util::CreateQuitCallback(
337 &run_loop,
338 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
339 run_loop.Run();
341 EXPECT_EQ(net::OK, error);
342 ASSERT_TRUE(entry);
343 EXPECT_TRUE(reader->IsInitialized());
344 size_t content_size = entry->file_info().size();
346 // Read data from the reader.
347 std::string first_content;
348 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
349 EXPECT_EQ(content_size, first_content.size());
351 // Create second instance and initialize it.
352 // In this case, the file should be cached one.
353 reader.reset(new DriveFileStreamReader(
354 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
355 EXPECT_FALSE(reader->IsInitialized());
357 error = net::ERR_FAILED;
358 entry.reset();
360 base::RunLoop run_loop;
361 reader->Initialize(
362 kDriveFile,
363 net::HttpByteRange(),
364 google_apis::test_util::CreateQuitCallback(
365 &run_loop,
366 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
367 run_loop.Run();
369 EXPECT_EQ(net::OK, error);
370 ASSERT_TRUE(entry);
371 EXPECT_TRUE(reader->IsInitialized());
373 // The size should be same.
374 EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
376 // Read data from the reader, again.
377 std::string second_content;
378 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
380 // The same content is expected.
381 EXPECT_EQ(first_content, second_content);
384 TEST_F(DriveFileStreamReaderTest, ReadRange) {
385 // In this test case, we just confirm that the part of file is read.
386 const int64 kRangeOffset = 3;
387 const int64 kRangeLength = 4;
389 const base::FilePath kDriveFile =
390 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
391 // Create the reader, and initialize it.
392 // In this case, the file is not yet locally cached.
393 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
394 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
395 EXPECT_FALSE(reader->IsInitialized());
397 int error = net::ERR_FAILED;
398 scoped_ptr<ResourceEntry> entry;
399 net::HttpByteRange byte_range;
400 byte_range.set_first_byte_position(kRangeOffset);
401 // Last byte position is inclusive.
402 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
404 base::RunLoop run_loop;
405 reader->Initialize(
406 kDriveFile,
407 byte_range,
408 google_apis::test_util::CreateQuitCallback(
409 &run_loop,
410 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
411 run_loop.Run();
413 EXPECT_EQ(net::OK, error);
414 ASSERT_TRUE(entry);
415 EXPECT_TRUE(reader->IsInitialized());
417 // Read data from the reader.
418 std::string first_content;
419 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
421 // The length should be equal to range length.
422 EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
424 // Create second instance and initialize it.
425 // In this case, the file should be cached one.
426 reader.reset(new DriveFileStreamReader(
427 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
428 EXPECT_FALSE(reader->IsInitialized());
430 error = net::ERR_FAILED;
431 entry.reset();
433 base::RunLoop run_loop;
434 reader->Initialize(
435 kDriveFile,
436 byte_range,
437 google_apis::test_util::CreateQuitCallback(
438 &run_loop,
439 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
440 run_loop.Run();
442 EXPECT_EQ(net::OK, error);
443 ASSERT_TRUE(entry);
444 EXPECT_TRUE(reader->IsInitialized());
446 // Read data from the reader, again.
447 std::string second_content;
448 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
450 // The same content is expected.
451 EXPECT_EQ(first_content, second_content);
454 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
455 const int64 kRangeOffset = 1000000; // Out of range.
456 const int64 kRangeLength = 4;
458 const base::FilePath kDriveFile =
459 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
460 // Create the reader, and initialize it.
461 // In this case, the file is not yet locally cached.
462 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
463 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
464 EXPECT_FALSE(reader->IsInitialized());
466 int error = net::ERR_FAILED;
467 scoped_ptr<ResourceEntry> entry;
468 net::HttpByteRange byte_range;
469 byte_range.set_first_byte_position(kRangeOffset);
470 // Last byte position is inclusive.
471 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
473 base::RunLoop run_loop;
474 reader->Initialize(
475 kDriveFile,
476 byte_range,
477 google_apis::test_util::CreateQuitCallback(
478 &run_loop,
479 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
480 run_loop.Run();
482 EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
483 EXPECT_FALSE(entry);
486 TEST_F(DriveFileStreamReaderTest, ZeroByteFileRead) {
487 // Prepare an empty file
489 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
490 scoped_ptr<google_apis::ResourceEntry> entry;
491 fake_drive_service_->AddNewFile(
492 "text/plain",
493 "", // empty
494 fake_drive_service_->GetRootResourceId(),
495 "EmptyFile.txt",
496 false, // shared_with_me
497 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
498 drive::test_util::RunBlockingPoolTask();
499 ASSERT_EQ(google_apis::HTTP_CREATED, error);
500 ASSERT_TRUE(entry);
501 ASSERT_EQ(0, entry->file_size());
504 const base::FilePath kDriveFile =
505 util::GetDriveMyDriveRootPath().AppendASCII("EmptyFile.txt");
506 // Create the reader, and initialize it.
507 // In this case, the file is not yet locally cached.
508 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
509 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
510 EXPECT_FALSE(reader->IsInitialized());
512 int error = net::ERR_FAILED;
513 scoped_ptr<ResourceEntry> entry;
515 base::RunLoop run_loop;
516 reader->Initialize(
517 kDriveFile,
518 net::HttpByteRange(),
519 google_apis::test_util::CreateQuitCallback(
520 &run_loop,
521 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
522 run_loop.Run();
524 EXPECT_EQ(net::OK, error);
525 ASSERT_TRUE(entry);
526 ASSERT_EQ(0u, entry->file_info().size()); // It's a zero-byte file.
527 EXPECT_TRUE(reader->IsInitialized());
529 // Read data from the reader. Check that it successfuly reads empty data.
530 std::string first_content;
531 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
532 EXPECT_EQ(0u, first_content.size());
534 // Create second instance and initialize it.
535 // In this case, the file should be cached one.
536 reader.reset(new DriveFileStreamReader(
537 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
538 EXPECT_FALSE(reader->IsInitialized());
540 error = net::ERR_FAILED;
541 entry.reset();
543 base::RunLoop run_loop;
544 reader->Initialize(
545 kDriveFile,
546 net::HttpByteRange(),
547 google_apis::test_util::CreateQuitCallback(
548 &run_loop,
549 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
550 run_loop.Run();
552 EXPECT_EQ(net::OK, error);
553 ASSERT_TRUE(entry);
554 EXPECT_TRUE(reader->IsInitialized());
556 // Read data from the reader, again.
557 std::string second_content;
558 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
559 EXPECT_EQ(0u, second_content.size());
562 } // namespace drive