Upstream version 9.38.198.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 "content/public/test/test_utils.h"
22 #include "google_apis/drive/drive_api_parser.h"
23 #include "google_apis/drive/test_util.h"
24 #include "net/base/io_buffer.h"
25 #include "net/base/net_errors.h"
26 #include "net/base/test_completion_callback.h"
27 #include "net/http/http_byte_range.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 namespace drive {
31 namespace internal {
32 namespace {
33
34 // Increments the |num_called|, when this method is invoked.
35 void IncrementCallback(int* num_called) {
36   DCHECK(num_called);
37   ++*num_called;
38 }
39
40 }  // namespace
41
42 class LocalReaderProxyTest : public ::testing::Test {
43  protected:
44   LocalReaderProxyTest()
45       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
46   }
47
48   virtual void SetUp() OVERRIDE {
49     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
50     ASSERT_TRUE(google_apis::test_util::CreateFileOfSpecifiedSize(
51         temp_dir_.path(), 1024, &file_path_, &file_content_));
52
53     worker_thread_.reset(new base::Thread("ReaderProxyTest"));
54     ASSERT_TRUE(worker_thread_->Start());
55   }
56
57   content::TestBrowserThreadBundle thread_bundle_;
58
59   base::ScopedTempDir temp_dir_;
60   base::FilePath file_path_;
61   std::string file_content_;
62
63   scoped_ptr<base::Thread> worker_thread_;
64 };
65
66 TEST_F(LocalReaderProxyTest, Read) {
67   // Open the file first.
68   scoped_ptr<util::LocalFileReader> file_reader(
69       new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
70   net::TestCompletionCallback callback;
71   file_reader->Open(file_path_, 0, callback.callback());
72   ASSERT_EQ(net::OK, callback.WaitForResult());
73
74   // Test instance.
75   LocalReaderProxy proxy(file_reader.Pass(), file_content_.size());
76
77   // Make sure the read content is as same as the file.
78   std::string content;
79   ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
80   EXPECT_EQ(file_content_, content);
81 }
82
83 TEST_F(LocalReaderProxyTest, ReadWithLimit) {
84   // This test case, we only read first half of the file.
85   const std::string expected_content =
86       file_content_.substr(0, file_content_.size() / 2);
87
88   // Open the file first.
89   scoped_ptr<util::LocalFileReader> file_reader(
90       new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
91   net::TestCompletionCallback callback;
92   file_reader->Open(file_path_, 0, callback.callback());
93   ASSERT_EQ(net::OK, callback.WaitForResult());
94
95   // Test instance.
96   LocalReaderProxy proxy(file_reader.Pass(), expected_content.size());
97
98   // Make sure the read content is as same as the file.
99   std::string content;
100   ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
101   EXPECT_EQ(expected_content, content);
102 }
103
104 class NetworkReaderProxyTest : public ::testing::Test {
105  protected:
106   NetworkReaderProxyTest()
107       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
108   }
109
110   content::TestBrowserThreadBundle thread_bundle_;
111 };
112
113 TEST_F(NetworkReaderProxyTest, EmptyFile) {
114   NetworkReaderProxy proxy(0, 0, 0, base::Bind(&base::DoNothing));
115
116   net::TestCompletionCallback callback;
117   const int kBufferSize = 10;
118   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
119   int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
120
121   // For empty file, Read() should return 0 immediately.
122   EXPECT_EQ(0, result);
123 }
124
125 TEST_F(NetworkReaderProxyTest, Read) {
126   int cancel_called = 0;
127   {
128     NetworkReaderProxy proxy(0, 10, 10,
129                              base::Bind(&IncrementCallback, &cancel_called));
130
131     net::TestCompletionCallback callback;
132     const int kBufferSize = 3;
133     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
134
135     // If no data is available yet, ERR_IO_PENDING should be returned.
136     int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
137     EXPECT_EQ(net::ERR_IO_PENDING, result);
138
139     // And when the data is supplied, the callback will be called.
140     scoped_ptr<std::string> data(new std::string("abcde"));
141     proxy.OnGetContent(data.Pass());
142
143     // The returned data should be fit to the buffer size.
144     result = callback.GetResult(result);
145     EXPECT_EQ(3, result);
146     EXPECT_EQ("abc", std::string(buffer->data(), result));
147
148     // The next Read should return immediately because there is pending data
149     result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
150     EXPECT_EQ(2, result);
151     EXPECT_EQ("de", std::string(buffer->data(), result));
152
153     // Supply the data before calling Read operation.
154     data.reset(new std::string("fg"));
155     proxy.OnGetContent(data.Pass());
156     data.reset(new std::string("hij"));
157     proxy.OnGetContent(data.Pass());  // Now 10 bytes are supplied.
158
159     // The data should be concatenated if possible.
160     result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
161     EXPECT_EQ(3, result);
162     EXPECT_EQ("fgh", std::string(buffer->data(), result));
163
164     result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
165     EXPECT_EQ(2, result);
166     EXPECT_EQ("ij", std::string(buffer->data(), result));
167
168     // The whole data is read, so Read() should return 0 immediately by then.
169     result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
170     EXPECT_EQ(0, result);
171   }
172
173   // Proxy is deleted without any called to OnCompleted(). Even in the case,
174   // cancel callback should not be invoked.
175   EXPECT_EQ(0, cancel_called);
176 }
177
178 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
179   NetworkReaderProxy proxy(10, 10, 10, base::Bind(&base::DoNothing));
180
181   net::TestCompletionCallback callback;
182   const int kBufferSize = 3;
183   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
184
185   // If no data is available yet, ERR_IO_PENDING should be returned.
186   int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
187   EXPECT_EQ(net::ERR_IO_PENDING, result);
188
189   // And when the data is supplied, the callback will be called.
190   scoped_ptr<std::string> data(new std::string("abcde"));
191   proxy.OnGetContent(data.Pass());
192   data.reset(new std::string("fgh"));
193   proxy.OnGetContent(data.Pass());
194   data.reset(new std::string("ijklmno"));
195   proxy.OnGetContent(data.Pass());
196
197   // The returned data should be fit to the buffer size.
198   result = callback.GetResult(result);
199   EXPECT_EQ(3, result);
200   EXPECT_EQ("klm", std::string(buffer->data(), result));
201
202   // The next Read should return immediately because there is pending data
203   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
204   EXPECT_EQ(2, result);
205   EXPECT_EQ("no", std::string(buffer->data(), result));
206
207   // Supply the data before calling Read operation.
208   data.reset(new std::string("pqrs"));
209   proxy.OnGetContent(data.Pass());
210   data.reset(new std::string("tuvwxyz"));
211   proxy.OnGetContent(data.Pass());  // 't' is the 20-th byte.
212
213   // The data should be concatenated if possible.
214   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
215   EXPECT_EQ(3, result);
216   EXPECT_EQ("pqr", std::string(buffer->data(), result));
217
218   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
219   EXPECT_EQ(2, result);
220   EXPECT_EQ("st", std::string(buffer->data(), result));
221
222   // The whole data is read, so Read() should return 0 immediately by then.
223   result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
224   EXPECT_EQ(0, result);
225 }
226
227 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
228   NetworkReaderProxy proxy(0, 10, 10, base::Bind(&base::DoNothing));
229
230   net::TestCompletionCallback callback;
231   const int kBufferSize = 3;
232   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
233
234   // Set pending callback.
235   int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
236   EXPECT_EQ(net::ERR_IO_PENDING, result);
237
238   // Emulate that an error is found. The callback should be called internally.
239   proxy.OnCompleted(FILE_ERROR_FAILED);
240   result = callback.GetResult(result);
241   EXPECT_EQ(net::ERR_FAILED, result);
242
243   // The next Read call should also return the same error code.
244   EXPECT_EQ(net::ERR_FAILED,
245             proxy.Read(buffer.get(), kBufferSize, callback.callback()));
246 }
247
248 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
249   NetworkReaderProxy proxy(0, 10, 10, base::Bind(&base::DoNothing));
250
251   net::TestCompletionCallback callback;
252   const int kBufferSize = 3;
253   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
254
255   // Supply the data before an error.
256   scoped_ptr<std::string> data(new std::string("abcde"));
257   proxy.OnGetContent(data.Pass());
258
259   // Emulate that an error is found.
260   proxy.OnCompleted(FILE_ERROR_FAILED);
261
262   // The next Read call should return the error code, even if there is
263   // pending data (the pending data should be released in OnCompleted.
264   EXPECT_EQ(net::ERR_FAILED,
265             proxy.Read(buffer.get(), kBufferSize, callback.callback()));
266 }
267
268 TEST_F(NetworkReaderProxyTest, CancelJob) {
269   int num_called = 0;
270   {
271     NetworkReaderProxy proxy(
272         0, 0, 0, base::Bind(&IncrementCallback, &num_called));
273     proxy.OnCompleted(FILE_ERROR_OK);
274     // Destroy the instance after the network operation is completed.
275     // The cancelling callback shouldn't be called.
276   }
277   EXPECT_EQ(0, num_called);
278
279   num_called = 0;
280   {
281     NetworkReaderProxy proxy(
282         0, 0, 0, base::Bind(&IncrementCallback, &num_called));
283     // Destroy the instance before the network operation is completed.
284     // The cancelling callback should be called.
285   }
286   EXPECT_EQ(1, num_called);
287 }
288
289 }  // namespace internal
290
291 class DriveFileStreamReaderTest : public ::testing::Test {
292  protected:
293   DriveFileStreamReaderTest()
294       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
295   }
296
297   virtual void SetUp() OVERRIDE {
298     worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
299     ASSERT_TRUE(worker_thread_->Start());
300
301     // Initialize FakeDriveService.
302     fake_drive_service_.reset(new FakeDriveService);
303     ASSERT_TRUE(test_util::SetUpTestEntries(fake_drive_service_.get()));
304
305     // Create a testee instance.
306     fake_file_system_.reset(
307         new test_util::FakeFileSystem(fake_drive_service_.get()));
308   }
309
310   FileSystemInterface* GetFileSystem() {
311     return fake_file_system_.get();
312   }
313
314   DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
315     return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
316                       base::Unretained(this));
317   }
318
319   content::TestBrowserThreadBundle thread_bundle_;
320
321   scoped_ptr<base::Thread> worker_thread_;
322
323   scoped_ptr<FakeDriveService> fake_drive_service_;
324   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
325 };
326
327 TEST_F(DriveFileStreamReaderTest, Read) {
328   const base::FilePath kDriveFile =
329       util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
330   // Create the reader, and initialize it.
331   // In this case, the file is not yet locally cached.
332   scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
333       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
334   EXPECT_FALSE(reader->IsInitialized());
335
336   int error = net::ERR_FAILED;
337   scoped_ptr<ResourceEntry> entry;
338   {
339     base::RunLoop run_loop;
340     reader->Initialize(
341         kDriveFile,
342         net::HttpByteRange(),
343         google_apis::test_util::CreateQuitCallback(
344             &run_loop,
345             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
346     run_loop.Run();
347   }
348   EXPECT_EQ(net::OK, error);
349   ASSERT_TRUE(entry);
350   EXPECT_TRUE(reader->IsInitialized());
351   size_t content_size = entry->file_info().size();
352
353   // Read data from the reader.
354   std::string first_content;
355   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
356   EXPECT_EQ(content_size, first_content.size());
357
358   // Create second instance and initialize it.
359   // In this case, the file should be cached one.
360   reader.reset(new DriveFileStreamReader(
361       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
362   EXPECT_FALSE(reader->IsInitialized());
363
364   error = net::ERR_FAILED;
365   entry.reset();
366   {
367     base::RunLoop run_loop;
368     reader->Initialize(
369         kDriveFile,
370         net::HttpByteRange(),
371         google_apis::test_util::CreateQuitCallback(
372             &run_loop,
373             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
374     run_loop.Run();
375   }
376   EXPECT_EQ(net::OK, error);
377   ASSERT_TRUE(entry);
378   EXPECT_TRUE(reader->IsInitialized());
379
380   // The size should be same.
381   EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
382
383   // Read data from the reader, again.
384   std::string second_content;
385   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
386
387   // The same content is expected.
388   EXPECT_EQ(first_content, second_content);
389 }
390
391 TEST_F(DriveFileStreamReaderTest, ReadRange) {
392   // In this test case, we just confirm that the part of file is read.
393   const int64 kRangeOffset = 3;
394   const int64 kRangeLength = 4;
395
396   const base::FilePath kDriveFile =
397       util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
398   // Create the reader, and initialize it.
399   // In this case, the file is not yet locally cached.
400   scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
401       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
402   EXPECT_FALSE(reader->IsInitialized());
403
404   int error = net::ERR_FAILED;
405   scoped_ptr<ResourceEntry> entry;
406   net::HttpByteRange byte_range;
407   byte_range.set_first_byte_position(kRangeOffset);
408   // Last byte position is inclusive.
409   byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
410   {
411     base::RunLoop run_loop;
412     reader->Initialize(
413         kDriveFile,
414         byte_range,
415         google_apis::test_util::CreateQuitCallback(
416             &run_loop,
417             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
418     run_loop.Run();
419   }
420   EXPECT_EQ(net::OK, error);
421   ASSERT_TRUE(entry);
422   EXPECT_TRUE(reader->IsInitialized());
423
424   // Read data from the reader.
425   std::string first_content;
426   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
427
428   // The length should be equal to range length.
429   EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
430
431   // Create second instance and initialize it.
432   // In this case, the file should be cached one.
433   reader.reset(new DriveFileStreamReader(
434       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
435   EXPECT_FALSE(reader->IsInitialized());
436
437   error = net::ERR_FAILED;
438   entry.reset();
439   {
440     base::RunLoop run_loop;
441     reader->Initialize(
442         kDriveFile,
443         byte_range,
444         google_apis::test_util::CreateQuitCallback(
445             &run_loop,
446             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
447     run_loop.Run();
448   }
449   EXPECT_EQ(net::OK, error);
450   ASSERT_TRUE(entry);
451   EXPECT_TRUE(reader->IsInitialized());
452
453   // Read data from the reader, again.
454   std::string second_content;
455   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
456
457   // The same content is expected.
458   EXPECT_EQ(first_content, second_content);
459 }
460
461 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
462   const int64 kRangeOffset = 1000000;  // Out of range.
463   const int64 kRangeLength = 4;
464
465   const base::FilePath kDriveFile =
466       util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
467   // Create the reader, and initialize it.
468   // In this case, the file is not yet locally cached.
469   scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
470       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
471   EXPECT_FALSE(reader->IsInitialized());
472
473   int error = net::ERR_FAILED;
474   scoped_ptr<ResourceEntry> entry;
475   net::HttpByteRange byte_range;
476   byte_range.set_first_byte_position(kRangeOffset);
477   // Last byte position is inclusive.
478   byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
479   {
480     base::RunLoop run_loop;
481     reader->Initialize(
482         kDriveFile,
483         byte_range,
484         google_apis::test_util::CreateQuitCallback(
485             &run_loop,
486             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
487     run_loop.Run();
488   }
489   EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);
490   EXPECT_FALSE(entry);
491 }
492
493 TEST_F(DriveFileStreamReaderTest, ZeroByteFileRead) {
494   // Prepare an empty file
495   {
496     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
497     scoped_ptr<google_apis::FileResource> entry;
498     fake_drive_service_->AddNewFile(
499         "text/plain",
500         "",  // empty
501         fake_drive_service_->GetRootResourceId(),
502         "EmptyFile.txt",
503         false,  // shared_with_me
504         google_apis::test_util::CreateCopyResultCallback(&error, &entry));
505     content::RunAllBlockingPoolTasksUntilIdle();
506     ASSERT_EQ(google_apis::HTTP_CREATED, error);
507     ASSERT_TRUE(entry);
508     ASSERT_EQ(0, entry->file_size());
509   }
510
511   const base::FilePath kDriveFile =
512       util::GetDriveMyDriveRootPath().AppendASCII("EmptyFile.txt");
513   // Create the reader, and initialize it.
514   // In this case, the file is not yet locally cached.
515   scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
516       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
517   EXPECT_FALSE(reader->IsInitialized());
518
519   int error = net::ERR_FAILED;
520   scoped_ptr<ResourceEntry> entry;
521   {
522     base::RunLoop run_loop;
523     reader->Initialize(
524         kDriveFile,
525         net::HttpByteRange(),
526         google_apis::test_util::CreateQuitCallback(
527             &run_loop,
528             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
529     run_loop.Run();
530   }
531   EXPECT_EQ(net::OK, error);
532   ASSERT_TRUE(entry);
533   ASSERT_EQ(0u, entry->file_info().size());  // It's a zero-byte file.
534   EXPECT_TRUE(reader->IsInitialized());
535
536   // Read data from the reader. Check that it successfuly reads empty data.
537   std::string first_content;
538   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
539   EXPECT_EQ(0u, first_content.size());
540
541   // Create second instance and initialize it.
542   // In this case, the file should be cached one.
543   reader.reset(new DriveFileStreamReader(
544       GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
545   EXPECT_FALSE(reader->IsInitialized());
546
547   error = net::ERR_FAILED;
548   entry.reset();
549   {
550     base::RunLoop run_loop;
551     reader->Initialize(
552         kDriveFile,
553         net::HttpByteRange(),
554         google_apis::test_util::CreateQuitCallback(
555             &run_loop,
556             google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
557     run_loop.Run();
558   }
559   EXPECT_EQ(net::OK, error);
560   ASSERT_TRUE(entry);
561   EXPECT_TRUE(reader->IsInitialized());
562
563   // Read data from the reader, again.
564   std::string second_content;
565   ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
566   EXPECT_EQ(0u, second_content.size());
567 }
568
569 }  // namespace drive