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