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.
5 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
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"
18 namespace file_system {
20 class CopyOperationTest : public OperationTestBase {
22 virtual void SetUp() OVERRIDE {
23 OperationTestBase::SetUp();
24 operation_.reset(new CopyOperation(
25 blocking_task_runner(),
30 util::GetIdentityResourceIdCanonicalizer()));
33 scoped_ptr<CopyOperation> operation_;
36 TEST_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"));
41 // Prepare a local file.
43 google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
44 // Confirm that the remote file does not exist.
46 ASSERT_EQ(FILE_ERROR_NOT_FOUND,
47 GetLocalResourceEntry(remote_dest_path, &entry));
49 // Transfer the local file to Drive.
50 FileError error = FILE_ERROR_FAILED;
51 operation_->TransferFileFromLocalToRemote(
54 google_apis::test_util::CreateCopyResultCallback(&error));
55 test_util::RunBlockingPoolTask();
56 EXPECT_EQ(FILE_ERROR_OK, error);
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;
65 base::PostTaskAndReplyWithResult(
66 blocking_task_runner(),
68 base::Bind(&internal::FileCache::GetCacheEntry,
69 base::Unretained(cache()),
70 GetLocalId(remote_dest_path),
72 google_apis::test_util::CreateCopyResultCallback(&found));
73 test_util::RunBlockingPoolTask();
75 EXPECT_TRUE(cache_entry.is_present());
76 EXPECT_TRUE(cache_entry.is_dirty());
78 EXPECT_EQ(1U, observer()->get_changed_paths().size());
79 EXPECT_TRUE(observer()->get_changed_paths().count(
80 remote_dest_path.DirName()));
83 TEST_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"));
88 // Prepare a local file.
90 google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
91 // Confirm that the remote file exists.
93 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
95 // Transfer the local file to Drive.
96 FileError error = FILE_ERROR_FAILED;
97 operation_->TransferFileFromLocalToRemote(
100 google_apis::test_util::CreateCopyResultCallback(&error));
101 test_util::RunBlockingPoolTask();
102 EXPECT_EQ(FILE_ERROR_OK, error);
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;
110 base::PostTaskAndReplyWithResult(
111 blocking_task_runner(),
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();
118 EXPECT_TRUE(cache_entry.is_present());
119 EXPECT_TRUE(cache_entry.is_dirty());
121 EXPECT_EQ(1U, observer()->get_changed_paths().size());
122 EXPECT_TRUE(observer()->get_changed_paths().count(
123 remote_dest_path.DirName()));
126 TEST_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"));
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(
135 GURL("https://3_document_self_link/document:5_document_resource_id"),
136 "document:5_document_resource_id"));
139 ASSERT_EQ(FILE_ERROR_NOT_FOUND,
140 GetLocalResourceEntry(remote_dest_path, &entry));
142 // Transfer the local file to Drive.
143 FileError error = FILE_ERROR_FAILED;
144 operation_->TransferFileFromLocalToRemote(
147 google_apis::test_util::CreateCopyResultCallback(&error));
148 test_util::RunBlockingPoolTask();
149 EXPECT_EQ(FILE_ERROR_OK, error);
151 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
153 EXPECT_EQ(1U, observer()->get_changed_paths().size());
155 observer()->get_changed_paths().count(remote_dest_path.DirName()));
159 TEST_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"));
164 ASSERT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
166 FileError error = FILE_ERROR_OK;
167 operation_->Copy(src_path,
170 google_apis::test_util::CreateCopyResultCallback(&error));
171 test_util::RunBlockingPoolTask();
172 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
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());
179 TEST_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"));
184 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
185 ASSERT_EQ(FILE_ERROR_NOT_FOUND,
186 GetLocalResourceEntry(dest_path.DirName(), &entry));
188 FileError error = FILE_ERROR_OK;
189 operation_->Copy(src_path,
192 google_apis::test_util::CreateCopyResultCallback(&error));
193 test_util::RunBlockingPoolTask();
194 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
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());
201 // Test the case where the parent of the destination path is an existing file,
203 TEST_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"));
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());
214 FileError error = FILE_ERROR_OK;
215 operation_->Copy(src_path,
218 google_apis::test_util::CreateCopyResultCallback(&error));
219 test_util::RunBlockingPoolTask();
220 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
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());
227 TEST_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"));
232 ResourceEntry src_entry;
233 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
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(),
244 base::Bind(&internal::FileCache::Store,
245 base::Unretained(cache()),
246 src_entry.local_id(),
249 internal::FileCache::FILE_OPERATION_MOVE),
250 google_apis::test_util::CreateCopyResultCallback(&error));
251 test_util::RunBlockingPoolTask();
252 EXPECT_EQ(FILE_ERROR_OK, error);
255 operation_->Copy(src_path,
258 google_apis::test_util::CreateCopyResultCallback(&error));
259 test_util::RunBlockingPoolTask();
260 EXPECT_EQ(FILE_ERROR_OK, error);
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());
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()));
271 // Copied cache file should be dirty.
272 bool success = false;
273 FileCacheEntry cache_entry;
274 base::PostTaskAndReplyWithResult(
275 blocking_task_runner(),
277 base::Bind(&internal::FileCache::GetCacheEntry,
278 base::Unretained(cache()),
279 dest_entry.local_id(),
281 google_apis::test_util::CreateCopyResultCallback(&success));
282 test_util::RunBlockingPoolTask();
283 EXPECT_TRUE(success);
284 EXPECT_TRUE(cache_entry.is_dirty());
286 // File contents should match.
287 base::FilePath cache_file_path;
288 base::PostTaskAndReplyWithResult(
289 blocking_task_runner(),
291 base::Bind(&internal::FileCache::GetFile,
292 base::Unretained(cache()),
293 dest_entry.local_id(),
295 google_apis::test_util::CreateCopyResultCallback(&error));
296 test_util::RunBlockingPoolTask();
297 EXPECT_EQ(FILE_ERROR_OK, error);
299 std::string copied_contents;
300 EXPECT_TRUE(base::ReadFileToString(cache_file_path, &copied_contents));
301 EXPECT_EQ(contents, copied_contents);
304 TEST_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"));
309 ResourceEntry old_dest_entry;
310 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &old_dest_entry));
312 FileError error = FILE_ERROR_OK;
313 operation_->Copy(src_path,
316 google_apis::test_util::CreateCopyResultCallback(&error));
317 test_util::RunBlockingPoolTask();
318 EXPECT_EQ(FILE_ERROR_OK, error);
320 ResourceEntry new_dest_entry;
321 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &new_dest_entry));
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()));
329 TEST_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"));
333 FileError error = FILE_ERROR_OK;
334 operation_->Copy(src_path,
337 google_apis::test_util::CreateCopyResultCallback(&error));
338 test_util::RunBlockingPoolTask();
339 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
342 TEST_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"));
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());
352 FileError error = FILE_ERROR_OK;
353 operation_->Copy(src_path,
356 google_apis::test_util::CreateCopyResultCallback(&error));
357 test_util::RunBlockingPoolTask();
358 EXPECT_EQ(FILE_ERROR_NOT_A_FILE, error);
361 TEST_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"));
366 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
367 ASSERT_EQ(FILE_ERROR_OK,
368 GetLocalResourceEntry(dest_path.DirName(), &entry));
370 FileError error = FILE_ERROR_OK;
371 operation_->Copy(src_path,
373 true, // Preserve last modified.
374 google_apis::test_util::CreateCopyResultCallback(&error));
375 test_util::RunBlockingPoolTask();
376 EXPECT_EQ(FILE_ERROR_OK, error);
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());
385 } // namespace file_system