- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system / download_operation_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/file_system/download_operation.h"
6
7 #include "base/file_util.h"
8 #include "base/task_runner_util.h"
9 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
10 #include "chrome/browser/chromeos/drive/file_cache.h"
11 #include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
12 #include "chrome/browser/chromeos/drive/file_system_util.h"
13 #include "chrome/browser/drive/fake_drive_service.h"
14 #include "chrome/browser/google_apis/test_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace drive {
18 namespace file_system {
19
20 class DownloadOperationTest : public OperationTestBase {
21  protected:
22   virtual void SetUp() OVERRIDE {
23     OperationTestBase::SetUp();
24
25     operation_.reset(new DownloadOperation(
26         blocking_task_runner(), observer(), scheduler(), metadata(), cache(),
27         temp_dir()));
28   }
29
30   scoped_ptr<DownloadOperation> operation_;
31 };
32
33 TEST_F(DownloadOperationTest,
34        EnsureFileDownloadedByPath_FromServer_EnoughSpace) {
35   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
36   ResourceEntry src_entry;
37   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
38   const int64 file_size = src_entry.file_info().size();
39
40   // Pretend we have enough space.
41   fake_free_disk_space_getter()->set_default_value(
42       file_size + internal::kMinFreeSpace);
43
44   FileError error = FILE_ERROR_FAILED;
45   base::FilePath file_path;
46   scoped_ptr<ResourceEntry> entry;
47   operation_->EnsureFileDownloadedByPath(
48       file_in_root,
49       ClientContext(USER_INITIATED),
50       GetFileContentInitializedCallback(),
51       google_apis::GetContentCallback(),
52       google_apis::test_util::CreateCopyResultCallback(
53           &error, &file_path, &entry));
54   test_util::RunBlockingPoolTask();
55
56   EXPECT_EQ(FILE_ERROR_OK, error);
57   ASSERT_TRUE(entry);
58   EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
59
60   // The transfered file is cached and the change of "offline available"
61   // attribute is notified.
62   EXPECT_EQ(1U, observer()->get_changed_paths().size());
63   EXPECT_EQ(1U, observer()->get_changed_paths().count(file_in_root.DirName()));
64
65   // Verify that readable permission is set.
66   int permission = 0;
67   EXPECT_TRUE(file_util::GetPosixFilePermissions(file_path, &permission));
68   EXPECT_EQ(file_util::FILE_PERMISSION_READ_BY_USER |
69             file_util::FILE_PERMISSION_WRITE_BY_USER |
70             file_util::FILE_PERMISSION_READ_BY_GROUP |
71             file_util::FILE_PERMISSION_READ_BY_OTHERS, permission);
72 }
73
74 TEST_F(DownloadOperationTest,
75        EnsureFileDownloadedByPath_FromServer_NoSpaceAtAll) {
76   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
77
78   // Pretend we have no space at all.
79   fake_free_disk_space_getter()->set_default_value(0);
80
81   FileError error = FILE_ERROR_OK;
82   base::FilePath file_path;
83   scoped_ptr<ResourceEntry> entry;
84   operation_->EnsureFileDownloadedByPath(
85       file_in_root,
86       ClientContext(USER_INITIATED),
87       GetFileContentInitializedCallback(),
88       google_apis::GetContentCallback(),
89       google_apis::test_util::CreateCopyResultCallback(
90           &error, &file_path, &entry));
91   test_util::RunBlockingPoolTask();
92
93   EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, error);
94 }
95
96 TEST_F(DownloadOperationTest,
97        EnsureFileDownloadedByPath_FromServer_NoEnoughSpaceButCanFreeUp) {
98   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
99   ResourceEntry src_entry;
100   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
101   const int64 file_size = src_entry.file_info().size();
102
103   // Pretend we have no space first (checked before downloading a file),
104   // but then start reporting we have space. This is to emulate that
105   // the disk space was freed up by removing temporary files.
106   fake_free_disk_space_getter()->PushFakeValue(
107       file_size + internal::kMinFreeSpace);
108   fake_free_disk_space_getter()->PushFakeValue(0);
109   fake_free_disk_space_getter()->set_default_value(
110       file_size + internal::kMinFreeSpace);
111
112   // Store something of the file size in the temporary cache directory.
113   const std::string content(file_size, 'x');
114   base::ScopedTempDir temp_dir;
115   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
116   const base::FilePath tmp_file =
117       temp_dir.path().AppendASCII("something.txt");
118   ASSERT_TRUE(google_apis::test_util::WriteStringToFile(tmp_file, content));
119
120   FileError error = FILE_ERROR_FAILED;
121   base::PostTaskAndReplyWithResult(
122       blocking_task_runner(),
123       FROM_HERE,
124       base::Bind(&internal::FileCache::Store,
125                  base::Unretained(cache()),
126                  "<id>", "<md5>", tmp_file,
127                  internal::FileCache::FILE_OPERATION_COPY),
128       google_apis::test_util::CreateCopyResultCallback(&error));
129   test_util::RunBlockingPoolTask();
130   EXPECT_EQ(FILE_ERROR_OK, error);
131
132   base::FilePath file_path;
133   scoped_ptr<ResourceEntry> entry;
134   operation_->EnsureFileDownloadedByPath(
135       file_in_root,
136       ClientContext(USER_INITIATED),
137       GetFileContentInitializedCallback(),
138       google_apis::GetContentCallback(),
139       google_apis::test_util::CreateCopyResultCallback(
140           &error, &file_path, &entry));
141   test_util::RunBlockingPoolTask();
142
143   EXPECT_EQ(FILE_ERROR_OK, error);
144   ASSERT_TRUE(entry);
145   EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
146
147   // The transfered file is cached and the change of "offline available"
148   // attribute is notified.
149   EXPECT_EQ(1U, observer()->get_changed_paths().size());
150   EXPECT_EQ(1U, observer()->get_changed_paths().count(file_in_root.DirName()));
151
152   // The cache entry should be removed in order to free up space.
153   FileCacheEntry cache_entry;
154   bool result = true;
155   base::PostTaskAndReplyWithResult(
156       blocking_task_runner(),
157       FROM_HERE,
158       base::Bind(&internal::FileCache::GetCacheEntry,
159                  base::Unretained(cache()),
160                  "<id>",
161                  &cache_entry),
162       google_apis::test_util::CreateCopyResultCallback(&result));
163   test_util::RunBlockingPoolTask();
164   ASSERT_FALSE(result);
165 }
166
167 TEST_F(DownloadOperationTest,
168        EnsureFileDownloadedByPath_FromServer_EnoughSpaceButBecomeFull) {
169   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
170   ResourceEntry src_entry;
171   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
172   const int64 file_size = src_entry.file_info().size();
173
174   // Pretend we have enough space first (checked before downloading a file),
175   // but then start reporting we have not enough space. This is to emulate that
176   // the disk space becomes full after the file is downloaded for some reason
177   // (ex. the actual file was larger than the expected size).
178   fake_free_disk_space_getter()->PushFakeValue(
179       file_size + internal::kMinFreeSpace);
180   fake_free_disk_space_getter()->set_default_value(
181       internal::kMinFreeSpace - 1);
182
183   FileError error = FILE_ERROR_OK;
184   base::FilePath file_path;
185   scoped_ptr<ResourceEntry> entry;
186   operation_->EnsureFileDownloadedByPath(
187       file_in_root,
188       ClientContext(USER_INITIATED),
189       GetFileContentInitializedCallback(),
190       google_apis::GetContentCallback(),
191       google_apis::test_util::CreateCopyResultCallback(
192           &error, &file_path, &entry));
193   test_util::RunBlockingPoolTask();
194
195   EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, error);
196 }
197
198 TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_FromCache) {
199   base::FilePath temp_file;
200   ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir(), &temp_file));
201
202   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
203   ResourceEntry src_entry;
204   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
205
206   // Store something as cached version of this file.
207   FileError error = FILE_ERROR_OK;
208   base::PostTaskAndReplyWithResult(
209       blocking_task_runner(),
210       FROM_HERE,
211       base::Bind(&internal::FileCache::Store,
212                  base::Unretained(cache()),
213                  GetLocalId(file_in_root),
214                  src_entry.file_specific_info().md5(),
215                  temp_file,
216                  internal::FileCache::FILE_OPERATION_COPY),
217       google_apis::test_util::CreateCopyResultCallback(&error));
218   test_util::RunBlockingPoolTask();
219   EXPECT_EQ(FILE_ERROR_OK, error);
220
221   base::FilePath file_path;
222   scoped_ptr<ResourceEntry> entry;
223   operation_->EnsureFileDownloadedByPath(
224       file_in_root,
225       ClientContext(USER_INITIATED),
226       GetFileContentInitializedCallback(),
227       google_apis::GetContentCallback(),
228       google_apis::test_util::CreateCopyResultCallback(
229           &error, &file_path, &entry));
230   test_util::RunBlockingPoolTask();
231
232   EXPECT_EQ(FILE_ERROR_OK, error);
233   ASSERT_TRUE(entry);
234   EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
235 }
236
237 TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_HostedDocument) {
238   base::FilePath file_in_root(FILE_PATH_LITERAL(
239       "drive/root/Document 1 excludeDir-test.gdoc"));
240
241   FileError error = FILE_ERROR_FAILED;
242   base::FilePath file_path;
243   scoped_ptr<ResourceEntry> entry;
244   operation_->EnsureFileDownloadedByPath(
245       file_in_root,
246       ClientContext(USER_INITIATED),
247       GetFileContentInitializedCallback(),
248       google_apis::GetContentCallback(),
249       google_apis::test_util::CreateCopyResultCallback(
250           &error, &file_path, &entry));
251   test_util::RunBlockingPoolTask();
252
253   EXPECT_EQ(FILE_ERROR_OK, error);
254   ASSERT_TRUE(entry);
255   EXPECT_TRUE(entry->file_specific_info().is_hosted_document());
256   EXPECT_FALSE(file_path.empty());
257
258   EXPECT_EQ(GURL(entry->file_specific_info().alternate_url()),
259             util::ReadUrlFromGDocFile(file_path));
260   EXPECT_EQ(entry->resource_id(), util::ReadResourceIdFromGDocFile(file_path));
261 }
262
263 TEST_F(DownloadOperationTest, EnsureFileDownloadedByLocalId) {
264   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
265   ResourceEntry src_entry;
266   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
267
268   FileError error = FILE_ERROR_OK;
269   base::FilePath file_path;
270   scoped_ptr<ResourceEntry> entry;
271   operation_->EnsureFileDownloadedByLocalId(
272       GetLocalId(file_in_root),
273       ClientContext(USER_INITIATED),
274       GetFileContentInitializedCallback(),
275       google_apis::GetContentCallback(),
276       google_apis::test_util::CreateCopyResultCallback(
277           &error, &file_path, &entry));
278   test_util::RunBlockingPoolTask();
279
280   EXPECT_EQ(FILE_ERROR_OK, error);
281   ASSERT_TRUE(entry);
282   EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
283
284   // The transfered file is cached and the change of "offline available"
285   // attribute is notified.
286   EXPECT_EQ(1U, observer()->get_changed_paths().size());
287   EXPECT_EQ(1U, observer()->get_changed_paths().count(file_in_root.DirName()));
288 }
289
290 TEST_F(DownloadOperationTest,
291        EnsureFileDownloadedByPath_WithGetContentCallback) {
292   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
293
294   {
295     FileError initialized_error = FILE_ERROR_FAILED;
296     scoped_ptr<ResourceEntry> entry, entry_dontcare;
297     base::FilePath local_path, local_path_dontcare;
298     base::Closure cancel_download;
299     google_apis::test_util::TestGetContentCallback get_content_callback;
300
301     FileError completion_error = FILE_ERROR_FAILED;
302
303     operation_->EnsureFileDownloadedByPath(
304         file_in_root,
305         ClientContext(USER_INITIATED),
306         google_apis::test_util::CreateCopyResultCallback(
307             &initialized_error, &entry, &local_path, &cancel_download),
308         get_content_callback.callback(),
309         google_apis::test_util::CreateCopyResultCallback(
310             &completion_error, &local_path_dontcare, &entry_dontcare));
311     test_util::RunBlockingPoolTask();
312
313     // For the first time, file is downloaded from the remote server.
314     // In this case, |local_path| is empty while |cancel_download| is not.
315     EXPECT_EQ(FILE_ERROR_OK, initialized_error);
316     ASSERT_TRUE(entry);
317     ASSERT_TRUE(local_path.empty());
318     EXPECT_TRUE(!cancel_download.is_null());
319     // Content is available through the second callback argument.
320     EXPECT_EQ(static_cast<size_t>(entry->file_info().size()),
321               get_content_callback.GetConcatenatedData().size());
322     EXPECT_EQ(FILE_ERROR_OK, completion_error);
323
324     // The transfered file is cached and the change of "offline available"
325     // attribute is notified.
326     EXPECT_EQ(1U, observer()->get_changed_paths().size());
327     EXPECT_EQ(1U,
328               observer()->get_changed_paths().count(file_in_root.DirName()));
329   }
330
331   {
332     FileError initialized_error = FILE_ERROR_FAILED;
333     scoped_ptr<ResourceEntry> entry, entry_dontcare;
334     base::FilePath local_path, local_path_dontcare;
335     base::Closure cancel_download;
336     google_apis::test_util::TestGetContentCallback get_content_callback;
337
338     FileError completion_error = FILE_ERROR_FAILED;
339
340     operation_->EnsureFileDownloadedByPath(
341         file_in_root,
342         ClientContext(USER_INITIATED),
343         google_apis::test_util::CreateCopyResultCallback(
344             &initialized_error, &entry, &local_path, &cancel_download),
345         get_content_callback.callback(),
346         google_apis::test_util::CreateCopyResultCallback(
347             &completion_error, &local_path_dontcare, &entry_dontcare));
348     test_util::RunBlockingPoolTask();
349
350     // Try second download. In this case, the file should be cached, so
351     // |local_path| should not be empty while |cancel_download| is empty.
352     EXPECT_EQ(FILE_ERROR_OK, initialized_error);
353     ASSERT_TRUE(entry);
354     ASSERT_TRUE(!local_path.empty());
355     EXPECT_TRUE(cancel_download.is_null());
356     // The content is available from the cache file.
357     EXPECT_TRUE(get_content_callback.data().empty());
358     int64 local_file_size = 0;
359     file_util::GetFileSize(local_path, &local_file_size);
360     EXPECT_EQ(entry->file_info().size(), local_file_size);
361     EXPECT_EQ(FILE_ERROR_OK, completion_error);
362   }
363 }
364
365 TEST_F(DownloadOperationTest, EnsureFileDownloadedByLocalId_FromCache) {
366   base::FilePath temp_file;
367   ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir(), &temp_file));
368
369   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
370   ResourceEntry src_entry;
371   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
372
373   // Store something as cached version of this file.
374   FileError error = FILE_ERROR_FAILED;
375   base::PostTaskAndReplyWithResult(
376       blocking_task_runner(),
377       FROM_HERE,
378       base::Bind(&internal::FileCache::Store,
379                  base::Unretained(cache()),
380                  GetLocalId(file_in_root),
381                  src_entry.file_specific_info().md5(),
382                  temp_file,
383                  internal::FileCache::FILE_OPERATION_COPY),
384       google_apis::test_util::CreateCopyResultCallback(&error));
385   test_util::RunBlockingPoolTask();
386   EXPECT_EQ(FILE_ERROR_OK, error);
387
388   // The file is obtained from the cache.
389   // Hence the downloading should work even if the drive service is offline.
390   fake_service()->set_offline(true);
391
392   base::FilePath file_path;
393   scoped_ptr<ResourceEntry> entry;
394   operation_->EnsureFileDownloadedByLocalId(
395       GetLocalId(file_in_root),
396       ClientContext(USER_INITIATED),
397       GetFileContentInitializedCallback(),
398       google_apis::GetContentCallback(),
399       google_apis::test_util::CreateCopyResultCallback(
400           &error, &file_path, &entry));
401   test_util::RunBlockingPoolTask();
402
403   EXPECT_EQ(FILE_ERROR_OK, error);
404   ASSERT_TRUE(entry);
405   EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
406 }
407
408 TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_DirtyCache) {
409   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
410   ResourceEntry src_entry;
411   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
412
413   // Prepare a dirty file to store to cache that has a different size than
414   // stored in resource metadata.
415   base::FilePath dirty_file = temp_dir().AppendASCII("dirty.txt");
416   size_t dirty_size = src_entry.file_info().size() + 10;
417   google_apis::test_util::WriteStringToFile(dirty_file,
418                                             std::string(dirty_size, 'x'));
419
420   // Store the file as a cache, marking it to be dirty.
421   FileError error = FILE_ERROR_FAILED;
422   base::PostTaskAndReplyWithResult(
423       blocking_task_runner(),
424       FROM_HERE,
425       base::Bind(&internal::FileCache::Store,
426                  base::Unretained(cache()),
427                  GetLocalId(file_in_root),
428                  src_entry.file_specific_info().md5(),
429                  dirty_file,
430                  internal::FileCache::FILE_OPERATION_COPY),
431       google_apis::test_util::CreateCopyResultCallback(&error));
432   test_util::RunBlockingPoolTask();
433   EXPECT_EQ(FILE_ERROR_OK, error);
434   base::PostTaskAndReplyWithResult(
435       blocking_task_runner(),
436       FROM_HERE,
437       base::Bind(&internal::FileCache::MarkDirty,
438                  base::Unretained(cache()),
439                  GetLocalId(file_in_root)),
440       google_apis::test_util::CreateCopyResultCallback(&error));
441   test_util::RunBlockingPoolTask();
442   EXPECT_EQ(FILE_ERROR_OK, error);
443
444   // Record values passed to GetFileContentInitializedCallback().
445   FileError init_error;
446   base::FilePath init_path;
447   scoped_ptr<ResourceEntry> init_entry;
448   base::Closure cancel_callback;
449
450   base::FilePath file_path;
451   scoped_ptr<ResourceEntry> entry;
452   operation_->EnsureFileDownloadedByPath(
453       file_in_root,
454       ClientContext(USER_INITIATED),
455       google_apis::test_util::CreateCopyResultCallback(
456           &init_error, &init_entry, &init_path, &cancel_callback),
457       google_apis::GetContentCallback(),
458       google_apis::test_util::CreateCopyResultCallback(
459           &error, &file_path, &entry));
460   test_util::RunBlockingPoolTask();
461
462   EXPECT_EQ(FILE_ERROR_OK, error);
463   // Check that the result of local modification is propagated.
464   EXPECT_EQ(static_cast<int64>(dirty_size), init_entry->file_info().size());
465   EXPECT_EQ(static_cast<int64>(dirty_size), entry->file_info().size());
466 }
467
468 }  // namespace file_system
469 }  // namespace drive