Upstream version 8.37.180.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/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"
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, 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   int cancel_called = 0;
126   {
127     NetworkReaderProxy proxy(0, 10, 10,
128                              base::Bind(&IncrementCallback, &cancel_called));
129
130     net::TestCompletionCallback callback;
131     const int kBufferSize = 3;
132     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
133
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);
137
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());
141
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));
146
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));
151
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.
157
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));
162
163     result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
164     EXPECT_EQ(2, result);
165     EXPECT_EQ("ij", std::string(buffer->data(), result));
166
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);
170   }
171
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);
175 }
176
177 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
178   NetworkReaderProxy proxy(10, 10, 10, base::Bind(&base::DoNothing));
179
180   net::TestCompletionCallback callback;
181   const int kBufferSize = 3;
182   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
183
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);
187
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());
195
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));
200
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));
205
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.
211
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));
216
217   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
218   EXPECT_EQ(2, result);
219   EXPECT_EQ("st", std::string(buffer->data(), result));
220
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);
224 }
225
226 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
227   NetworkReaderProxy proxy(0, 10, 10, base::Bind(&base::DoNothing));
228
229   net::TestCompletionCallback callback;
230   const int kBufferSize = 3;
231   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
232
233   // Set pending callback.
234   int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
235   EXPECT_EQ(net::ERR_IO_PENDING, result);
236
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);
241
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()));
245 }
246
247 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
248   NetworkReaderProxy proxy(0, 10, 10, base::Bind(&base::DoNothing));
249
250   net::TestCompletionCallback callback;
251   const int kBufferSize = 3;
252   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
253
254   // Supply the data before an error.
255   scoped_ptr<std::string> data(new std::string("abcde"));
256   proxy.OnGetContent(data.Pass());
257
258   // Emulate that an error is found.
259   proxy.OnCompleted(FILE_ERROR_FAILED);
260
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()));
265 }
266
267 TEST_F(NetworkReaderProxyTest, CancelJob) {
268   int num_called = 0;
269   {
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.
275   }
276   EXPECT_EQ(0, num_called);
277
278   num_called = 0;
279   {
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.
284   }
285   EXPECT_EQ(1, num_called);
286 }
287
288 }  // namespace internal
289
290 class DriveFileStreamReaderTest : public ::testing::Test {
291  protected:
292   DriveFileStreamReaderTest()
293       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
294   }
295
296   virtual void SetUp() OVERRIDE {
297     worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
298     ASSERT_TRUE(worker_thread_->Start());
299
300     // Initialize FakeDriveService.
301     fake_drive_service_.reset(new FakeDriveService);
302     ASSERT_TRUE(test_util::SetUpTestEntries(fake_drive_service_.get()));
303
304     // Create a testee instance.
305     fake_file_system_.reset(
306         new test_util::FakeFileSystem(fake_drive_service_.get()));
307   }
308
309   FileSystemInterface* GetFileSystem() {
310     return fake_file_system_.get();
311   }
312
313   DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
314     return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
315                       base::Unretained(this));
316   }
317
318   content::TestBrowserThreadBundle thread_bundle_;
319
320   scoped_ptr<base::Thread> worker_thread_;
321
322   scoped_ptr<FakeDriveService> fake_drive_service_;
323   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
324 };
325
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());
334
335   int error = net::ERR_FAILED;
336   scoped_ptr<ResourceEntry> entry;
337   {
338     base::RunLoop run_loop;
339     reader->Initialize(
340         kDriveFile,
341         net::HttpByteRange(),
342         google_apis::test_util::CreateQuitCallback(
343             &run_loop,
344             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
345     run_loop.Run();
346   }
347   EXPECT_EQ(net::OK, error);
348   ASSERT_TRUE(entry);
349   EXPECT_TRUE(reader->IsInitialized());
350   size_t content_size = entry->file_info().size();
351
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());
356
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());
362
363   error = net::ERR_FAILED;
364   entry.reset();
365   {
366     base::RunLoop run_loop;
367     reader->Initialize(
368         kDriveFile,
369         net::HttpByteRange(),
370         google_apis::test_util::CreateQuitCallback(
371             &run_loop,
372             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
373     run_loop.Run();
374   }
375   EXPECT_EQ(net::OK, error);
376   ASSERT_TRUE(entry);
377   EXPECT_TRUE(reader->IsInitialized());
378
379   // The size should be same.
380   EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
381
382   // Read data from the reader, again.
383   std::string second_content;
384   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
385
386   // The same content is expected.
387   EXPECT_EQ(first_content, second_content);
388 }
389
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;
394
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());
402
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);
409   {
410     base::RunLoop run_loop;
411     reader->Initialize(
412         kDriveFile,
413         byte_range,
414         google_apis::test_util::CreateQuitCallback(
415             &run_loop,
416             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
417     run_loop.Run();
418   }
419   EXPECT_EQ(net::OK, error);
420   ASSERT_TRUE(entry);
421   EXPECT_TRUE(reader->IsInitialized());
422
423   // Read data from the reader.
424   std::string first_content;
425   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
426
427   // The length should be equal to range length.
428   EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
429
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());
435
436   error = net::ERR_FAILED;
437   entry.reset();
438   {
439     base::RunLoop run_loop;
440     reader->Initialize(
441         kDriveFile,
442         byte_range,
443         google_apis::test_util::CreateQuitCallback(
444             &run_loop,
445             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
446     run_loop.Run();
447   }
448   EXPECT_EQ(net::OK, error);
449   ASSERT_TRUE(entry);
450   EXPECT_TRUE(reader->IsInitialized());
451
452   // Read data from the reader, again.
453   std::string second_content;
454   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
455
456   // The same content is expected.
457   EXPECT_EQ(first_content, second_content);
458 }
459
460 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
461   const int64 kRangeOffset = 1000000;  // Out of range.
462   const int64 kRangeLength = 4;
463
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());
471
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);
478   {
479     base::RunLoop run_loop;
480     reader->Initialize(
481         kDriveFile,
482         byte_range,
483         google_apis::test_util::CreateQuitCallback(
484             &run_loop,
485             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
486     run_loop.Run();
487   }
488   EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
489   EXPECT_FALSE(entry);
490 }
491
492 TEST_F(DriveFileStreamReaderTest, ZeroByteFileRead) {
493   // Prepare an empty file
494   {
495     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
496     scoped_ptr<google_apis::FileResource> entry;
497     fake_drive_service_->AddNewFile(
498         "text/plain",
499         "",  // empty
500         fake_drive_service_->GetRootResourceId(),
501         "EmptyFile.txt",
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);
506     ASSERT_TRUE(entry);
507     ASSERT_EQ(0, entry->file_size());
508   }
509
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());
517
518   int error = net::ERR_FAILED;
519   scoped_ptr<ResourceEntry> entry;
520   {
521     base::RunLoop run_loop;
522     reader->Initialize(
523         kDriveFile,
524         net::HttpByteRange(),
525         google_apis::test_util::CreateQuitCallback(
526             &run_loop,
527             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
528     run_loop.Run();
529   }
530   EXPECT_EQ(net::OK, error);
531   ASSERT_TRUE(entry);
532   ASSERT_EQ(0u, entry->file_info().size());  // It's a zero-byte file.
533   EXPECT_TRUE(reader->IsInitialized());
534
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());
539
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());
545
546   error = net::ERR_FAILED;
547   entry.reset();
548   {
549     base::RunLoop run_loop;
550     reader->Initialize(
551         kDriveFile,
552         net::HttpByteRange(),
553         google_apis::test_util::CreateQuitCallback(
554             &run_loop,
555             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
556     run_loop.Run();
557   }
558   EXPECT_EQ(net::OK, error);
559   ASSERT_TRUE(entry);
560   EXPECT_TRUE(reader->IsInitialized());
561
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());
566 }
567
568 }  // namespace drive