Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / drive_file_stream_reader_unittest.cc
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.
4
5 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
6
7 #include <string>
8
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 "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"
28
29 namespace drive {
30 namespace internal {
31 namespace {
32
33 // Increments the |num_called|, when this method is invoked.
34 void IncrementCallback(int* num_called) {
35   DCHECK(num_called);
36   ++*num_called;
37 }
38
39 }  // namespace
40
41 class LocalReaderProxyTest : public ::testing::Test {
42  protected:
43   LocalReaderProxyTest()
44       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
45   }
46
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_));
51
52     worker_thread_.reset(new base::Thread("ReaderProxyTest"));
53     ASSERT_TRUE(worker_thread_->Start());
54   }
55
56   content::TestBrowserThreadBundle thread_bundle_;
57
58   base::ScopedTempDir temp_dir_;
59   base::FilePath file_path_;
60   std::string file_content_;
61
62   scoped_ptr<base::Thread> worker_thread_;
63 };
64
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());
72
73   // Test instance.
74   LocalReaderProxy proxy(file_reader.Pass(), file_content_.size());
75
76   // Make sure the read content is as same as the file.
77   std::string content;
78   ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
79   EXPECT_EQ(file_content_, content);
80 }
81
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);
86
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());
93
94   // Test instance.
95   LocalReaderProxy proxy(file_reader.Pass(), expected_content.size());
96
97   // Make sure the read content is as same as the file.
98   std::string content;
99   ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
100   EXPECT_EQ(expected_content, content);
101 }
102
103 class NetworkReaderProxyTest : public ::testing::Test {
104  protected:
105   NetworkReaderProxyTest()
106       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
107   }
108
109   content::TestBrowserThreadBundle thread_bundle_;
110 };
111
112 TEST_F(NetworkReaderProxyTest, EmptyFile) {
113   NetworkReaderProxy proxy(0, 0, base::Bind(&base::DoNothing));
114
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());
119
120   // For empty file, Read() should return 0 immediately.
121   EXPECT_EQ(0, result);
122 }
123
124 TEST_F(NetworkReaderProxyTest, Read) {
125   NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
126
127   net::TestCompletionCallback callback;
128   const int kBufferSize = 3;
129   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
130
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);
134
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());
138
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));
143
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));
148
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.
154
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));
159
160   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
161   EXPECT_EQ(2, result);
162   EXPECT_EQ("ij", std::string(buffer->data(), result));
163
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);
167 }
168
169 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
170   NetworkReaderProxy proxy(10, 10, base::Bind(&base::DoNothing));
171
172   net::TestCompletionCallback callback;
173   const int kBufferSize = 3;
174   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
175
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);
179
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());
187
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));
192
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));
197
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.
203
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));
208
209   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
210   EXPECT_EQ(2, result);
211   EXPECT_EQ("st", std::string(buffer->data(), result));
212
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);
216 }
217
218 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
219   NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
220
221   net::TestCompletionCallback callback;
222   const int kBufferSize = 3;
223   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
224
225   // Set pending callback.
226   int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
227   EXPECT_EQ(net::ERR_IO_PENDING, result);
228
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);
233
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()));
237 }
238
239 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
240   NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
241
242   net::TestCompletionCallback callback;
243   const int kBufferSize = 3;
244   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
245
246   // Supply the data before an error.
247   scoped_ptr<std::string> data(new std::string("abcde"));
248   proxy.OnGetContent(data.Pass());
249
250   // Emulate that an error is found.
251   proxy.OnCompleted(FILE_ERROR_FAILED);
252
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()));
257 }
258
259 TEST_F(NetworkReaderProxyTest, CancelJob) {
260   int num_called = 0;
261   {
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.
267   }
268   EXPECT_EQ(0, num_called);
269
270   num_called = 0;
271   {
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.
276   }
277   EXPECT_EQ(1, num_called);
278 }
279
280 }  // namespace internal
281
282 class DriveFileStreamReaderTest : public ::testing::Test {
283  protected:
284   DriveFileStreamReaderTest()
285       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
286   }
287
288   virtual void SetUp() OVERRIDE {
289     worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
290     ASSERT_TRUE(worker_thread_->Start());
291
292     // Initialize FakeDriveService.
293     fake_drive_service_.reset(new FakeDriveService);
294     ASSERT_TRUE(test_util::SetUpTestEntries(fake_drive_service_.get()));
295
296     // Create a testee instance.
297     fake_file_system_.reset(
298         new test_util::FakeFileSystem(fake_drive_service_.get()));
299   }
300
301   FileSystemInterface* GetFileSystem() {
302     return fake_file_system_.get();
303   }
304
305   DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
306     return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
307                       base::Unretained(this));
308   }
309
310   content::TestBrowserThreadBundle thread_bundle_;
311
312   scoped_ptr<base::Thread> worker_thread_;
313
314   scoped_ptr<FakeDriveService> fake_drive_service_;
315   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
316 };
317
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());
326
327   int error = net::ERR_FAILED;
328   scoped_ptr<ResourceEntry> entry;
329   {
330     base::RunLoop run_loop;
331     reader->Initialize(
332         kDriveFile,
333         net::HttpByteRange(),
334         google_apis::test_util::CreateQuitCallback(
335             &run_loop,
336             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
337     run_loop.Run();
338   }
339   EXPECT_EQ(net::OK, error);
340   ASSERT_TRUE(entry);
341   EXPECT_TRUE(reader->IsInitialized());
342   size_t content_size = entry->file_info().size();
343
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());
348
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());
354
355   error = net::ERR_FAILED;
356   entry.reset();
357   {
358     base::RunLoop run_loop;
359     reader->Initialize(
360         kDriveFile,
361         net::HttpByteRange(),
362         google_apis::test_util::CreateQuitCallback(
363             &run_loop,
364             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
365     run_loop.Run();
366   }
367   EXPECT_EQ(net::OK, error);
368   ASSERT_TRUE(entry);
369   EXPECT_TRUE(reader->IsInitialized());
370
371   // The size should be same.
372   EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
373
374   // Read data from the reader, again.
375   std::string second_content;
376   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
377
378   // The same content is expected.
379   EXPECT_EQ(first_content, second_content);
380 }
381
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;
386
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());
394
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);
401   {
402     base::RunLoop run_loop;
403     reader->Initialize(
404         kDriveFile,
405         byte_range,
406         google_apis::test_util::CreateQuitCallback(
407             &run_loop,
408             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
409     run_loop.Run();
410   }
411   EXPECT_EQ(net::OK, error);
412   ASSERT_TRUE(entry);
413   EXPECT_TRUE(reader->IsInitialized());
414
415   // Read data from the reader.
416   std::string first_content;
417   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
418
419   // The length should be equal to range length.
420   EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
421
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());
427
428   error = net::ERR_FAILED;
429   entry.reset();
430   {
431     base::RunLoop run_loop;
432     reader->Initialize(
433         kDriveFile,
434         byte_range,
435         google_apis::test_util::CreateQuitCallback(
436             &run_loop,
437             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
438     run_loop.Run();
439   }
440   EXPECT_EQ(net::OK, error);
441   ASSERT_TRUE(entry);
442   EXPECT_TRUE(reader->IsInitialized());
443
444   // Read data from the reader, again.
445   std::string second_content;
446   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
447
448   // The same content is expected.
449   EXPECT_EQ(first_content, second_content);
450 }
451
452 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
453   const int64 kRangeOffset = 1000000;  // Out of range.
454   const int64 kRangeLength = 4;
455
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());
463
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);
470   {
471     base::RunLoop run_loop;
472     reader->Initialize(
473         kDriveFile,
474         byte_range,
475         google_apis::test_util::CreateQuitCallback(
476             &run_loop,
477             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
478     run_loop.Run();
479   }
480   EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
481   EXPECT_FALSE(entry);
482 }
483
484 TEST_F(DriveFileStreamReaderTest, ZeroByteFileRead) {
485   // Prepare an empty file
486   {
487     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
488     scoped_ptr<google_apis::ResourceEntry> entry;
489     fake_drive_service_->AddNewFile(
490         "text/plain",
491         "",  // empty
492         fake_drive_service_->GetRootResourceId(),
493         "EmptyFile.txt",
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);
498     ASSERT_TRUE(entry);
499     ASSERT_EQ(0, entry->file_size());
500   }
501
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());
509
510   int error = net::ERR_FAILED;
511   scoped_ptr<ResourceEntry> entry;
512   {
513     base::RunLoop run_loop;
514     reader->Initialize(
515         kDriveFile,
516         net::HttpByteRange(),
517         google_apis::test_util::CreateQuitCallback(
518             &run_loop,
519             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
520     run_loop.Run();
521   }
522   EXPECT_EQ(net::OK, error);
523   ASSERT_TRUE(entry);
524   ASSERT_EQ(0u, entry->file_info().size());  // It's a zero-byte file.
525   EXPECT_TRUE(reader->IsInitialized());
526
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());
531
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());
537
538   error = net::ERR_FAILED;
539   entry.reset();
540   {
541     base::RunLoop run_loop;
542     reader->Initialize(
543         kDriveFile,
544         net::HttpByteRange(),
545         google_apis::test_util::CreateQuitCallback(
546             &run_loop,
547             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
548     run_loop.Run();
549   }
550   EXPECT_EQ(net::OK, error);
551   ASSERT_TRUE(entry);
552   EXPECT_TRUE(reader->IsInitialized());
553
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());
558 }
559
560 }  // namespace drive