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/copy_operation.h"
6
7#include "base/file_util.h"
8#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
9#include "chrome/browser/chromeos/drive/file_system_util.h"
10#include "chrome/browser/drive/fake_drive_service.h"
11#include "chrome/browser/google_apis/test_util.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace drive {
15namespace file_system {
16
17class CopyOperationTest : public OperationTestBase {
18 protected:
19  virtual void SetUp() OVERRIDE {
20   OperationTestBase::SetUp();
21   operation_.reset(new CopyOperation(blocking_task_runner(),
22                                      observer(),
23                                      scheduler(),
24                                      metadata(),
25                                      cache(),
26                                      fake_service(),
27                                      temp_dir()));
28  }
29
30  scoped_ptr<CopyOperation> operation_;
31};
32
33TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_RegularFile) {
34  const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
35  const base::FilePath remote_dest_path(
36      FILE_PATH_LITERAL("drive/root/remote.txt"));
37
38  // Prepare a local file.
39  ASSERT_TRUE(
40      google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
41  // Confirm that the remote file does not exist.
42  ResourceEntry entry;
43  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
44            GetLocalResourceEntry(remote_dest_path, &entry));
45
46  // Transfer the local file to Drive.
47  FileError error = FILE_ERROR_FAILED;
48  operation_->TransferFileFromLocalToRemote(
49      local_src_path,
50      remote_dest_path,
51      google_apis::test_util::CreateCopyResultCallback(&error));
52  test_util::RunBlockingPoolTask();
53  EXPECT_EQ(FILE_ERROR_OK, error);
54
55  // TransferFileFromLocalToRemote stores a copy of the local file in the cache,
56  // marks it dirty and requests the observer to upload the file.
57  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
58  EXPECT_EQ(1U, observer()->upload_needed_resource_ids().count(
59      entry.resource_id()));
60  FileCacheEntry cache_entry;
61  bool found = false;
62  cache()->GetCacheEntryOnUIThread(
63      entry.resource_id(),
64      google_apis::test_util::CreateCopyResultCallback(&found, &cache_entry));
65  test_util::RunBlockingPoolTask();
66  EXPECT_TRUE(found);
67  EXPECT_TRUE(cache_entry.is_present());
68  EXPECT_TRUE(cache_entry.is_dirty());
69
70  EXPECT_EQ(1U, observer()->get_changed_paths().size());
71  EXPECT_TRUE(observer()->get_changed_paths().count(
72      remote_dest_path.DirName()));
73}
74
75TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_QuotaCheck) {
76  const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
77  const base::FilePath remote_dest_path(
78      FILE_PATH_LITERAL("drive/root/remote.txt"));
79
80  const size_t kFileSize = 10;
81
82  // Prepare a local file.
83  ASSERT_TRUE(
84      google_apis::test_util::WriteStringToFile(local_src_path,
85                                                std::string(kFileSize, 'a')));
86
87  // Set insufficient quota.
88  fake_service()->SetQuotaValue(100, 100 + kFileSize - 1);
89
90  // Transfer the local file to Drive.
91  FileError error = FILE_ERROR_FAILED;
92  operation_->TransferFileFromLocalToRemote(
93      local_src_path,
94      remote_dest_path,
95      google_apis::test_util::CreateCopyResultCallback(&error));
96  test_util::RunBlockingPoolTask();
97  EXPECT_EQ(FILE_ERROR_NO_SERVER_SPACE, error);
98
99  // Set sufficient quota.
100  fake_service()->SetQuotaValue(100, 100 + kFileSize);
101
102  // Transfer the local file to Drive.
103  error = FILE_ERROR_FAILED;
104  operation_->TransferFileFromLocalToRemote(
105      local_src_path,
106      remote_dest_path,
107      google_apis::test_util::CreateCopyResultCallback(&error));
108  test_util::RunBlockingPoolTask();
109  EXPECT_EQ(FILE_ERROR_OK, error);
110}
111
112TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_HostedDocument) {
113  const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
114  const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
115      "drive/root/Directory 1/Document 1 excludeDir-test.gdoc"));
116
117  // Prepare a local file, which is a json file of a hosted document, which
118  // matches "Document 1" in root_feed.json.
119  ASSERT_TRUE(util::CreateGDocFile(
120      local_src_path,
121      GURL("https://3_document_self_link/document:5_document_resource_id"),
122      "document:5_document_resource_id"));
123
124  ResourceEntry entry;
125  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
126            GetLocalResourceEntry(remote_dest_path, &entry));
127
128  // Transfer the local file to Drive.
129  FileError error = FILE_ERROR_FAILED;
130  operation_->TransferFileFromLocalToRemote(
131      local_src_path,
132      remote_dest_path,
133      google_apis::test_util::CreateCopyResultCallback(&error));
134  test_util::RunBlockingPoolTask();
135  EXPECT_EQ(FILE_ERROR_OK, error);
136
137  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
138
139  // We added a file to the Drive root and then moved to "Directory 1".
140  EXPECT_EQ(2U, observer()->get_changed_paths().size());
141  EXPECT_TRUE(observer()->get_changed_paths().count(
142      base::FilePath(FILE_PATH_LITERAL("drive/root"))));
143  EXPECT_TRUE(observer()->get_changed_paths().count(
144      remote_dest_path.DirName()));
145}
146
147TEST_F(CopyOperationTest, TransferFileFromRemoteToLocal_RegularFile) {
148  base::FilePath remote_src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
149  base::FilePath local_dest_path = temp_dir().AppendASCII("local_copy.txt");
150
151  ResourceEntry entry;
152  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_src_path, &entry));
153
154  FileError error = FILE_ERROR_FAILED;
155  operation_->TransferFileFromRemoteToLocal(
156      remote_src_path,
157      local_dest_path,
158      google_apis::test_util::CreateCopyResultCallback(&error));
159  test_util::RunBlockingPoolTask();
160  EXPECT_EQ(FILE_ERROR_OK, error);
161
162  // The content is "x"s of the file size.
163  base::FilePath cache_path;
164  cache()->GetFileOnUIThread(entry.resource_id(),
165                             google_apis::test_util::CreateCopyResultCallback(
166                                 &error, &cache_path));
167  test_util::RunBlockingPoolTask();
168  EXPECT_EQ(FILE_ERROR_OK, error);
169
170  const std::string kExpectedContent = "This is some test content.";
171  std::string cache_file_data;
172  EXPECT_TRUE(file_util::ReadFileToString(cache_path, &cache_file_data));
173  EXPECT_EQ(kExpectedContent, cache_file_data);
174
175  std::string local_dest_file_data;
176  EXPECT_TRUE(file_util::ReadFileToString(local_dest_path,
177                                          &local_dest_file_data));
178  EXPECT_EQ(kExpectedContent, local_dest_file_data);
179
180  // The transfered file is cached and the change of "offline available"
181  // attribute is notified.
182  EXPECT_EQ(1U, observer()->get_changed_paths().size());
183  EXPECT_TRUE(observer()->get_changed_paths().count(remote_src_path.DirName()));
184}
185
186TEST_F(CopyOperationTest, TransferFileFromRemoteToLocal_HostedDocument) {
187  base::FilePath local_dest_path = temp_dir().AppendASCII("local_copy.txt");
188  base::FilePath remote_src_path(
189      FILE_PATH_LITERAL("drive/root/Document 1 excludeDir-test.gdoc"));
190
191  FileError error = FILE_ERROR_FAILED;
192  operation_->TransferFileFromRemoteToLocal(
193      remote_src_path,
194      local_dest_path,
195      google_apis::test_util::CreateCopyResultCallback(&error));
196  test_util::RunBlockingPoolTask();
197  EXPECT_EQ(FILE_ERROR_OK, error);
198
199  ResourceEntry entry;
200  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_src_path, &entry));
201  EXPECT_EQ(GURL(entry.file_specific_info().alternate_url()),
202            util::ReadUrlFromGDocFile(local_dest_path));
203  EXPECT_EQ(entry.resource_id(),
204            util::ReadResourceIdFromGDocFile(local_dest_path));
205  EXPECT_TRUE(observer()->get_changed_paths().empty());
206}
207
208TEST_F(CopyOperationTest, CopyNotExistingFile) {
209  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/Dummy file.txt"));
210  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Test.log"));
211
212  ResourceEntry entry;
213  ASSERT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
214
215  FileError error = FILE_ERROR_OK;
216  operation_->Copy(src_path,
217                   dest_path,
218                   google_apis::test_util::CreateCopyResultCallback(&error));
219  test_util::RunBlockingPoolTask();
220  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
221
222  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
223  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
224  EXPECT_TRUE(observer()->get_changed_paths().empty());
225}
226
227TEST_F(CopyOperationTest, CopyFileToNonExistingDirectory) {
228  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
229  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Dummy/Test.log"));
230
231  ResourceEntry entry;
232  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
233  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
234            GetLocalResourceEntry(dest_path.DirName(), &entry));
235
236  FileError error = FILE_ERROR_OK;
237  operation_->Copy(src_path,
238                   dest_path,
239                   google_apis::test_util::CreateCopyResultCallback(&error));
240  test_util::RunBlockingPoolTask();
241  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
242
243  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
244  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
245  EXPECT_TRUE(observer()->get_changed_paths().empty());
246}
247
248// Test the case where the parent of the destination path is an existing file,
249// not a directory.
250TEST_F(CopyOperationTest, CopyFileToInvalidPath) {
251  base::FilePath src_path(FILE_PATH_LITERAL(
252      "drive/root/Document 1 excludeDir-test.gdoc"));
253  base::FilePath dest_path(FILE_PATH_LITERAL(
254      "drive/root/Duplicate Name.txt/Document 1 excludeDir-test.gdoc"));
255
256  ResourceEntry entry;
257  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
258  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path.DirName(), &entry));
259  ASSERT_FALSE(entry.file_info().is_directory());
260
261  FileError error = FILE_ERROR_OK;
262  operation_->Copy(src_path,
263                   dest_path,
264                   google_apis::test_util::CreateCopyResultCallback(&error));
265  test_util::RunBlockingPoolTask();
266  EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
267
268  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
269  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
270  EXPECT_TRUE(observer()->get_changed_paths().empty());
271}
272
273}  // namespace file_system
274}  // namespace drive
275