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