copy_operation_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "base/task_runner_util.h"
9#include "chrome/browser/chromeos/drive/file_cache.h"
10#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
11#include "chrome/browser/chromeos/drive/file_system_util.h"
12#include "chrome/browser/drive/drive_api_util.h"
13#include "chrome/browser/drive/fake_drive_service.h"
14#include "google_apis/drive/test_util.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace drive {
18namespace file_system {
19
20class CopyOperationTest : public OperationTestBase {
21 protected:
22  virtual void SetUp() OVERRIDE {
23   OperationTestBase::SetUp();
24   operation_.reset(new CopyOperation(
25       blocking_task_runner(),
26       observer(),
27       scheduler(),
28       metadata(),
29       cache(),
30       util::GetIdentityResourceIdCanonicalizer()));
31  }
32
33  scoped_ptr<CopyOperation> operation_;
34};
35
36TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_RegularFile) {
37  const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
38  const base::FilePath remote_dest_path(
39      FILE_PATH_LITERAL("drive/root/remote.txt"));
40
41  // Prepare a local file.
42  ASSERT_TRUE(
43      google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
44  // Confirm that the remote file does not exist.
45  ResourceEntry entry;
46  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
47            GetLocalResourceEntry(remote_dest_path, &entry));
48
49  // Transfer the local file to Drive.
50  FileError error = FILE_ERROR_FAILED;
51  operation_->TransferFileFromLocalToRemote(
52      local_src_path,
53      remote_dest_path,
54      google_apis::test_util::CreateCopyResultCallback(&error));
55  test_util::RunBlockingPoolTask();
56  EXPECT_EQ(FILE_ERROR_OK, error);
57
58  // TransferFileFromLocalToRemote stores a copy of the local file in the cache,
59  // marks it dirty and requests the observer to upload the file.
60  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
61  EXPECT_EQ(1U, observer()->updated_local_ids().count(
62      GetLocalId(remote_dest_path)));
63  FileCacheEntry cache_entry;
64  bool found = false;
65  base::PostTaskAndReplyWithResult(
66      blocking_task_runner(),
67      FROM_HERE,
68      base::Bind(&internal::FileCache::GetCacheEntry,
69                 base::Unretained(cache()),
70                 GetLocalId(remote_dest_path),
71                 &cache_entry),
72      google_apis::test_util::CreateCopyResultCallback(&found));
73  test_util::RunBlockingPoolTask();
74  EXPECT_TRUE(found);
75  EXPECT_TRUE(cache_entry.is_present());
76  EXPECT_TRUE(cache_entry.is_dirty());
77
78  EXPECT_EQ(1U, observer()->get_changed_paths().size());
79  EXPECT_TRUE(observer()->get_changed_paths().count(
80      remote_dest_path.DirName()));
81}
82
83TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_Overwrite) {
84  const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
85  const base::FilePath remote_dest_path(
86      FILE_PATH_LITERAL("drive/root/File 1.txt"));
87
88  // Prepare a local file.
89  EXPECT_TRUE(
90      google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
91  // Confirm that the remote file exists.
92  ResourceEntry entry;
93  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
94
95  // Transfer the local file to Drive.
96  FileError error = FILE_ERROR_FAILED;
97  operation_->TransferFileFromLocalToRemote(
98      local_src_path,
99      remote_dest_path,
100      google_apis::test_util::CreateCopyResultCallback(&error));
101  test_util::RunBlockingPoolTask();
102  EXPECT_EQ(FILE_ERROR_OK, error);
103
104  // TransferFileFromLocalToRemote stores a copy of the local file in the cache,
105  // marks it dirty and requests the observer to upload the file.
106  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
107  EXPECT_EQ(1U, observer()->updated_local_ids().count(entry.local_id()));
108  FileCacheEntry cache_entry;
109  bool found = false;
110  base::PostTaskAndReplyWithResult(
111      blocking_task_runner(),
112      FROM_HERE,
113      base::Bind(&internal::FileCache::GetCacheEntry,
114                 base::Unretained(cache()), entry.local_id(), &cache_entry),
115      google_apis::test_util::CreateCopyResultCallback(&found));
116  test_util::RunBlockingPoolTask();
117  EXPECT_TRUE(found);
118  EXPECT_TRUE(cache_entry.is_present());
119  EXPECT_TRUE(cache_entry.is_dirty());
120
121  EXPECT_EQ(1U, observer()->get_changed_paths().size());
122  EXPECT_TRUE(observer()->get_changed_paths().count(
123      remote_dest_path.DirName()));
124}
125
126TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_HostedDocument) {
127  const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
128  const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
129      "drive/root/Directory 1/Document 1 excludeDir-test.gdoc"));
130
131  // Prepare a local file, which is a json file of a hosted document, which
132  // matches "Document 1" in root_feed.json.
133  ASSERT_TRUE(util::CreateGDocFile(
134      local_src_path,
135      GURL("https://3_document_self_link/document:5_document_resource_id"),
136      "document:5_document_resource_id"));
137
138  ResourceEntry entry;
139  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
140            GetLocalResourceEntry(remote_dest_path, &entry));
141
142  // Transfer the local file to Drive.
143  FileError error = FILE_ERROR_FAILED;
144  operation_->TransferFileFromLocalToRemote(
145      local_src_path,
146      remote_dest_path,
147      google_apis::test_util::CreateCopyResultCallback(&error));
148  test_util::RunBlockingPoolTask();
149  EXPECT_EQ(FILE_ERROR_OK, error);
150
151  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
152
153  EXPECT_EQ(1U, observer()->get_changed_paths().size());
154  EXPECT_TRUE(
155      observer()->get_changed_paths().count(remote_dest_path.DirName()));
156}
157
158
159TEST_F(CopyOperationTest, CopyNotExistingFile) {
160  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/Dummy file.txt"));
161  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Test.log"));
162
163  ResourceEntry entry;
164  ASSERT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
165
166  FileError error = FILE_ERROR_OK;
167  operation_->Copy(src_path,
168                   dest_path,
169                   false,
170                   google_apis::test_util::CreateCopyResultCallback(&error));
171  test_util::RunBlockingPoolTask();
172  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
173
174  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
175  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
176  EXPECT_TRUE(observer()->get_changed_paths().empty());
177}
178
179TEST_F(CopyOperationTest, CopyFileToNonExistingDirectory) {
180  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
181  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Dummy/Test.log"));
182
183  ResourceEntry entry;
184  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
185  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
186            GetLocalResourceEntry(dest_path.DirName(), &entry));
187
188  FileError error = FILE_ERROR_OK;
189  operation_->Copy(src_path,
190                   dest_path,
191                   false,
192                   google_apis::test_util::CreateCopyResultCallback(&error));
193  test_util::RunBlockingPoolTask();
194  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
195
196  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
197  EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
198  EXPECT_TRUE(observer()->get_changed_paths().empty());
199}
200
201// Test the case where the parent of the destination path is an existing file,
202// not a directory.
203TEST_F(CopyOperationTest, CopyFileToInvalidPath) {
204  base::FilePath src_path(FILE_PATH_LITERAL(
205      "drive/root/Document 1 excludeDir-test.gdoc"));
206  base::FilePath dest_path(FILE_PATH_LITERAL(
207      "drive/root/Duplicate Name.txt/Document 1 excludeDir-test.gdoc"));
208
209  ResourceEntry entry;
210  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
211  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path.DirName(), &entry));
212  ASSERT_FALSE(entry.file_info().is_directory());
213
214  FileError error = FILE_ERROR_OK;
215  operation_->Copy(src_path,
216                   dest_path,
217                   false,
218                   google_apis::test_util::CreateCopyResultCallback(&error));
219  test_util::RunBlockingPoolTask();
220  EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
221
222  EXPECT_EQ(FILE_ERROR_OK, 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, CopyDirtyFile) {
228  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
229  base::FilePath dest_path(FILE_PATH_LITERAL(
230      "drive/root/Directory 1/New File.txt"));
231
232  ResourceEntry src_entry;
233  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
234
235  // Store a dirty cache file.
236  base::FilePath temp_file;
237  EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir(), &temp_file));
238  std::string contents = "test content";
239  EXPECT_TRUE(google_apis::test_util::WriteStringToFile(temp_file, contents));
240  FileError error = FILE_ERROR_FAILED;
241  base::PostTaskAndReplyWithResult(
242      blocking_task_runner(),
243      FROM_HERE,
244      base::Bind(&internal::FileCache::Store,
245                 base::Unretained(cache()),
246                 src_entry.local_id(),
247                 std::string(),
248                 temp_file,
249                 internal::FileCache::FILE_OPERATION_MOVE),
250      google_apis::test_util::CreateCopyResultCallback(&error));
251  test_util::RunBlockingPoolTask();
252  EXPECT_EQ(FILE_ERROR_OK, error);
253
254  // Copy.
255  operation_->Copy(src_path,
256                   dest_path,
257                   false,
258                   google_apis::test_util::CreateCopyResultCallback(&error));
259  test_util::RunBlockingPoolTask();
260  EXPECT_EQ(FILE_ERROR_OK, error);
261
262  ResourceEntry dest_entry;
263  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &dest_entry));
264  EXPECT_EQ(ResourceEntry::DIRTY, dest_entry.metadata_edit_state());
265
266  EXPECT_EQ(1u, observer()->updated_local_ids().size());
267  EXPECT_TRUE(observer()->updated_local_ids().count(dest_entry.local_id()));
268  EXPECT_EQ(1u, observer()->get_changed_paths().size());
269  EXPECT_TRUE(observer()->get_changed_paths().count(dest_path.DirName()));
270
271  // Copied cache file should be dirty.
272  bool success = false;
273  FileCacheEntry cache_entry;
274  base::PostTaskAndReplyWithResult(
275      blocking_task_runner(),
276      FROM_HERE,
277      base::Bind(&internal::FileCache::GetCacheEntry,
278                 base::Unretained(cache()),
279                 dest_entry.local_id(),
280                 &cache_entry),
281      google_apis::test_util::CreateCopyResultCallback(&success));
282  test_util::RunBlockingPoolTask();
283  EXPECT_TRUE(success);
284  EXPECT_TRUE(cache_entry.is_dirty());
285
286  // File contents should match.
287  base::FilePath cache_file_path;
288  base::PostTaskAndReplyWithResult(
289      blocking_task_runner(),
290      FROM_HERE,
291      base::Bind(&internal::FileCache::GetFile,
292                 base::Unretained(cache()),
293                 dest_entry.local_id(),
294                 &cache_file_path),
295      google_apis::test_util::CreateCopyResultCallback(&error));
296  test_util::RunBlockingPoolTask();
297  EXPECT_EQ(FILE_ERROR_OK, error);
298
299  std::string copied_contents;
300  EXPECT_TRUE(base::ReadFileToString(cache_file_path, &copied_contents));
301  EXPECT_EQ(contents, copied_contents);
302}
303
304TEST_F(CopyOperationTest, CopyFileOverwriteFile) {
305  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
306  base::FilePath dest_path(FILE_PATH_LITERAL(
307      "drive/root/Directory 1/SubDirectory File 1.txt"));
308
309  ResourceEntry old_dest_entry;
310  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &old_dest_entry));
311
312  FileError error = FILE_ERROR_OK;
313  operation_->Copy(src_path,
314                   dest_path,
315                   false,
316                   google_apis::test_util::CreateCopyResultCallback(&error));
317  test_util::RunBlockingPoolTask();
318  EXPECT_EQ(FILE_ERROR_OK, error);
319
320  ResourceEntry new_dest_entry;
321  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &new_dest_entry));
322
323  EXPECT_EQ(1u, observer()->updated_local_ids().size());
324  EXPECT_TRUE(observer()->updated_local_ids().count(old_dest_entry.local_id()));
325  EXPECT_EQ(1u, observer()->get_changed_paths().size());
326  EXPECT_TRUE(observer()->get_changed_paths().count(dest_path.DirName()));
327}
328
329TEST_F(CopyOperationTest, CopyFileOverwriteDirectory) {
330  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
331  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Directory 1"));
332
333  FileError error = FILE_ERROR_OK;
334  operation_->Copy(src_path,
335                   dest_path,
336                   false,
337                   google_apis::test_util::CreateCopyResultCallback(&error));
338  test_util::RunBlockingPoolTask();
339  EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
340}
341
342TEST_F(CopyOperationTest, CopyDirectory) {
343  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/Directory 1"));
344  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/New Directory"));
345
346  ResourceEntry entry;
347  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
348  ASSERT_TRUE(entry.file_info().is_directory());
349  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path.DirName(), &entry));
350  ASSERT_TRUE(entry.file_info().is_directory());
351
352  FileError error = FILE_ERROR_OK;
353  operation_->Copy(src_path,
354                   dest_path,
355                   false,
356                   google_apis::test_util::CreateCopyResultCallback(&error));
357  test_util::RunBlockingPoolTask();
358  EXPECT_EQ(FILE_ERROR_NOT_A_FILE, error);
359}
360
361TEST_F(CopyOperationTest, PreserveLastModified) {
362  base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
363  base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/File 2.txt"));
364
365  ResourceEntry entry;
366  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
367  ASSERT_EQ(FILE_ERROR_OK,
368            GetLocalResourceEntry(dest_path.DirName(), &entry));
369
370  FileError error = FILE_ERROR_OK;
371  operation_->Copy(src_path,
372                   dest_path,
373                   true,  // Preserve last modified.
374                   google_apis::test_util::CreateCopyResultCallback(&error));
375  test_util::RunBlockingPoolTask();
376  EXPECT_EQ(FILE_ERROR_OK, error);
377
378  ResourceEntry entry2;
379  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
380  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &entry2));
381  EXPECT_EQ(entry.file_info().last_modified(),
382            entry2.file_info().last_modified());
383}
384
385}  // namespace file_system
386}  // namespace drive
387