copy_tree_work_item_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright (c) 2012 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 <windows.h> 6 7#include <fstream> 8 9#include "base/base_paths.h" 10#include "base/files/file_util.h" 11#include "base/files/scoped_temp_dir.h" 12#include "base/logging.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/path_service.h" 15#include "base/strings/string_util.h" 16#include "base/threading/platform_thread.h" 17#include "chrome/installer/util/copy_tree_work_item.h" 18#include "chrome/installer/util/work_item.h" 19#include "testing/gtest/include/gtest/gtest.h" 20 21namespace { 22 23class CopyTreeWorkItemTest : public testing::Test { 24 protected: 25 virtual void SetUp() { 26 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 27 ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); 28 } 29 30 virtual void TearDown() { 31 logging::CloseLogFile(); 32 } 33 34 // the path to temporary directory used to contain the test operations 35 base::ScopedTempDir test_dir_; 36 base::ScopedTempDir temp_dir_; 37}; 38 39// Simple function to dump some text into a new file. 40void CreateTextFile(const std::wstring& filename, 41 const std::wstring& contents) { 42 std::ofstream file; 43 file.open(filename.c_str()); 44 ASSERT_TRUE(file.is_open()); 45 file << contents; 46 file.close(); 47} 48 49bool IsFileInUse(const base::FilePath& path) { 50 if (!base::PathExists(path)) 51 return false; 52 53 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS, 54 NULL, NULL, OPEN_EXISTING, NULL, NULL); 55 if (handle == INVALID_HANDLE_VALUE) 56 return true; 57 58 CloseHandle(handle); 59 return false; 60} 61 62// Simple function to read text from a file. 63std::wstring ReadTextFile(const std::wstring& filename) { 64 WCHAR contents[64]; 65 std::wifstream file; 66 file.open(filename.c_str()); 67 EXPECT_TRUE(file.is_open()); 68 file.getline(contents, 64); 69 file.close(); 70 return std::wstring(contents); 71} 72 73const wchar_t text_content_1[] = L"Gooooooooooooooooooooogle"; 74const wchar_t text_content_2[] = L"Overwrite Me"; 75 76} // namespace 77 78// Copy one file from source to destination. 79TEST_F(CopyTreeWorkItemTest, CopyFile) { 80 // Create source file 81 base::FilePath file_name_from(test_dir_.path()); 82 file_name_from = file_name_from.AppendASCII("File_From.txt"); 83 CreateTextFile(file_name_from.value(), text_content_1); 84 ASSERT_TRUE(base::PathExists(file_name_from)); 85 86 // Create destination path 87 base::FilePath dir_name_to(test_dir_.path()); 88 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 89 base::CreateDirectory(dir_name_to); 90 ASSERT_TRUE(base::PathExists(dir_name_to)); 91 92 base::FilePath file_name_to(dir_name_to); 93 file_name_to = file_name_to.AppendASCII("File_To.txt"); 94 95 // test Do() 96 scoped_ptr<CopyTreeWorkItem> work_item( 97 WorkItem::CreateCopyTreeWorkItem(file_name_from, 98 file_name_to, 99 temp_dir_.path(), 100 WorkItem::ALWAYS, 101 base::FilePath())); 102 103 EXPECT_TRUE(work_item->Do()); 104 105 EXPECT_TRUE(base::PathExists(file_name_from)); 106 EXPECT_TRUE(base::PathExists(file_name_to)); 107 EXPECT_TRUE(base::ContentsEqual(file_name_from, file_name_to)); 108 109 // test rollback() 110 work_item->Rollback(); 111 112 EXPECT_FALSE(base::PathExists(file_name_to)); 113 EXPECT_TRUE(base::PathExists(file_name_from)); 114} 115 116// Copy one file, overwriting the existing one in destination. 117// Test with always_overwrite being true or false. The file is overwritten 118// regardless since the content at destination file is different from source. 119TEST_F(CopyTreeWorkItemTest, CopyFileOverwrite) { 120 // Create source file 121 base::FilePath file_name_from(test_dir_.path()); 122 file_name_from = file_name_from.AppendASCII("File_From.txt"); 123 CreateTextFile(file_name_from.value(), text_content_1); 124 ASSERT_TRUE(base::PathExists(file_name_from)); 125 126 // Create destination file 127 base::FilePath dir_name_to(test_dir_.path()); 128 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 129 base::CreateDirectory(dir_name_to); 130 ASSERT_TRUE(base::PathExists(dir_name_to)); 131 132 base::FilePath file_name_to(dir_name_to); 133 file_name_to = file_name_to.AppendASCII("File_To.txt"); 134 CreateTextFile(file_name_to.value(), text_content_2); 135 ASSERT_TRUE(base::PathExists(file_name_to)); 136 137 // test Do() with always_overwrite being true. 138 scoped_ptr<CopyTreeWorkItem> work_item( 139 WorkItem::CreateCopyTreeWorkItem(file_name_from, 140 file_name_to, 141 temp_dir_.path(), 142 WorkItem::ALWAYS, 143 base::FilePath())); 144 145 EXPECT_TRUE(work_item->Do()); 146 147 EXPECT_TRUE(base::PathExists(file_name_from)); 148 EXPECT_TRUE(base::PathExists(file_name_to)); 149 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 150 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 151 152 // test rollback() 153 work_item->Rollback(); 154 155 EXPECT_TRUE(base::PathExists(file_name_from)); 156 EXPECT_TRUE(base::PathExists(file_name_to)); 157 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 158 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_2)); 159 160 // test Do() with always_overwrite being false. 161 // the file is still overwritten since the content is different. 162 work_item.reset( 163 WorkItem::CreateCopyTreeWorkItem(file_name_from, 164 file_name_to, 165 temp_dir_.path(), 166 WorkItem::IF_DIFFERENT, 167 base::FilePath())); 168 169 EXPECT_TRUE(work_item->Do()); 170 171 EXPECT_TRUE(base::PathExists(file_name_from)); 172 EXPECT_TRUE(base::PathExists(file_name_to)); 173 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 174 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 175 176 // test rollback() 177 work_item->Rollback(); 178 179 EXPECT_TRUE(base::PathExists(file_name_from)); 180 EXPECT_TRUE(base::PathExists(file_name_to)); 181 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 182 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_2)); 183} 184 185// Copy one file, with the existing one in destination having the same 186// content. 187// If always_overwrite being true, the file is overwritten. 188// If always_overwrite being false, the file is unchanged. 189TEST_F(CopyTreeWorkItemTest, CopyFileSameContent) { 190 // Create source file 191 base::FilePath file_name_from(test_dir_.path()); 192 file_name_from = file_name_from.AppendASCII("File_From.txt"); 193 CreateTextFile(file_name_from.value(), text_content_1); 194 ASSERT_TRUE(base::PathExists(file_name_from)); 195 196 // Create destination file 197 base::FilePath dir_name_to(test_dir_.path()); 198 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 199 base::CreateDirectory(dir_name_to); 200 ASSERT_TRUE(base::PathExists(dir_name_to)); 201 202 base::FilePath file_name_to(dir_name_to); 203 file_name_to = file_name_to.AppendASCII("File_To.txt"); 204 CreateTextFile(file_name_to.value(), text_content_1); 205 ASSERT_TRUE(base::PathExists(file_name_to)); 206 207 // test Do() with always_overwrite being true. 208 scoped_ptr<CopyTreeWorkItem> work_item( 209 WorkItem::CreateCopyTreeWorkItem(file_name_from, 210 file_name_to, 211 temp_dir_.path(), 212 WorkItem::ALWAYS, 213 base::FilePath())); 214 215 EXPECT_TRUE(work_item->Do()); 216 217 // Get the path of backup file 218 base::FilePath backup_file(work_item->backup_path_.path()); 219 EXPECT_FALSE(backup_file.empty()); 220 backup_file = backup_file.AppendASCII("File_To.txt"); 221 222 EXPECT_TRUE(base::PathExists(file_name_from)); 223 EXPECT_TRUE(base::PathExists(file_name_to)); 224 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 225 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 226 // we verify the file is overwritten by checking the existence of backup 227 // file. 228 EXPECT_TRUE(base::PathExists(backup_file)); 229 EXPECT_EQ(0, ReadTextFile(backup_file.value()).compare(text_content_1)); 230 231 // test rollback() 232 work_item->Rollback(); 233 234 EXPECT_TRUE(base::PathExists(file_name_from)); 235 EXPECT_TRUE(base::PathExists(file_name_to)); 236 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 237 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 238 // the backup file should be gone after rollback 239 EXPECT_FALSE(base::PathExists(backup_file)); 240 241 // test Do() with always_overwrite being false. nothing should change. 242 work_item.reset( 243 WorkItem::CreateCopyTreeWorkItem(file_name_from, 244 file_name_to, 245 temp_dir_.path(), 246 WorkItem::IF_DIFFERENT, 247 base::FilePath())); 248 249 EXPECT_TRUE(work_item->Do()); 250 251 EXPECT_TRUE(base::PathExists(file_name_from)); 252 EXPECT_TRUE(base::PathExists(file_name_to)); 253 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 254 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 255 // we verify the file is not overwritten by checking that the backup 256 // file does not exist. 257 EXPECT_FALSE(base::PathExists(backup_file)); 258 259 // test rollback(). nothing should happen here. 260 work_item->Rollback(); 261 262 EXPECT_TRUE(base::PathExists(file_name_from)); 263 EXPECT_TRUE(base::PathExists(file_name_to)); 264 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 265 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 266 EXPECT_FALSE(base::PathExists(backup_file)); 267} 268 269// Copy one file and without rollback. Verify all temporary files are deleted. 270TEST_F(CopyTreeWorkItemTest, CopyFileAndCleanup) { 271 // Create source file 272 base::FilePath file_name_from(test_dir_.path()); 273 file_name_from = file_name_from.AppendASCII("File_From.txt"); 274 CreateTextFile(file_name_from.value(), text_content_1); 275 ASSERT_TRUE(base::PathExists(file_name_from)); 276 277 // Create destination file 278 base::FilePath dir_name_to(test_dir_.path()); 279 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 280 base::CreateDirectory(dir_name_to); 281 ASSERT_TRUE(base::PathExists(dir_name_to)); 282 283 base::FilePath file_name_to(dir_name_to); 284 file_name_to = file_name_to.AppendASCII("File_To.txt"); 285 CreateTextFile(file_name_to.value(), text_content_2); 286 ASSERT_TRUE(base::PathExists(file_name_to)); 287 288 base::FilePath backup_file; 289 290 { 291 // test Do(). 292 scoped_ptr<CopyTreeWorkItem> work_item( 293 WorkItem::CreateCopyTreeWorkItem(file_name_from, 294 file_name_to, 295 temp_dir_.path(), 296 WorkItem::IF_DIFFERENT, 297 base::FilePath())); 298 299 EXPECT_TRUE(work_item->Do()); 300 301 // Get the path of backup file 302 backup_file = work_item->backup_path_.path(); 303 EXPECT_FALSE(backup_file.empty()); 304 backup_file = backup_file.AppendASCII("File_To.txt"); 305 306 EXPECT_TRUE(base::PathExists(file_name_from)); 307 EXPECT_TRUE(base::PathExists(file_name_to)); 308 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 309 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 310 // verify the file is moved to backup place. 311 EXPECT_TRUE(base::PathExists(backup_file)); 312 EXPECT_EQ(0, ReadTextFile(backup_file.value()).compare(text_content_2)); 313 } 314 315 // verify the backup file is cleaned up as well. 316 EXPECT_FALSE(base::PathExists(backup_file)); 317} 318 319// Copy one file, with the existing one in destination being used with 320// overwrite option as IF_DIFFERENT. This destination-file-in-use should 321// be moved to backup location after Do() and moved back after Rollback(). 322TEST_F(CopyTreeWorkItemTest, CopyFileInUse) { 323 // Create source file 324 base::FilePath file_name_from(test_dir_.path()); 325 file_name_from = file_name_from.AppendASCII("File_From"); 326 CreateTextFile(file_name_from.value(), text_content_1); 327 ASSERT_TRUE(base::PathExists(file_name_from)); 328 329 // Create an executable in destination path by copying ourself to it. 330 wchar_t exe_full_path_str[MAX_PATH]; 331 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH); 332 base::FilePath exe_full_path(exe_full_path_str); 333 334 base::FilePath dir_name_to(test_dir_.path()); 335 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 336 base::CreateDirectory(dir_name_to); 337 ASSERT_TRUE(base::PathExists(dir_name_to)); 338 339 base::FilePath file_name_to(dir_name_to); 340 file_name_to = file_name_to.AppendASCII("File_To"); 341 base::CopyFile(exe_full_path, file_name_to); 342 ASSERT_TRUE(base::PathExists(file_name_to)); 343 344 VLOG(1) << "copy ourself from " << exe_full_path.value() 345 << " to " << file_name_to.value(); 346 347 // Run the executable in destination path 348 STARTUPINFOW si = {sizeof(si)}; 349 PROCESS_INFORMATION pi = {0}; 350 ASSERT_TRUE( 351 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()), 352 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 353 NULL, NULL, &si, &pi)); 354 355 // test Do(). 356 scoped_ptr<CopyTreeWorkItem> work_item( 357 WorkItem::CreateCopyTreeWorkItem(file_name_from, 358 file_name_to, 359 temp_dir_.path(), 360 WorkItem::IF_DIFFERENT, 361 base::FilePath())); 362 363 EXPECT_TRUE(work_item->Do()); 364 365 // Get the path of backup file 366 base::FilePath backup_file(work_item->backup_path_.path()); 367 EXPECT_FALSE(backup_file.empty()); 368 backup_file = backup_file.AppendASCII("File_To"); 369 370 EXPECT_TRUE(base::PathExists(file_name_from)); 371 EXPECT_TRUE(base::PathExists(file_name_to)); 372 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 373 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 374 // verify the file in used is moved to backup place. 375 EXPECT_TRUE(base::PathExists(backup_file)); 376 EXPECT_TRUE(base::ContentsEqual(exe_full_path, backup_file)); 377 378 // test rollback() 379 work_item->Rollback(); 380 381 EXPECT_TRUE(base::PathExists(file_name_from)); 382 EXPECT_TRUE(base::PathExists(file_name_to)); 383 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 384 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to)); 385 // the backup file should be gone after rollback 386 EXPECT_FALSE(base::PathExists(backup_file)); 387 388 TerminateProcess(pi.hProcess, 0); 389 // make sure the handle is closed. 390 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0); 391 CloseHandle(pi.hProcess); 392 CloseHandle(pi.hThread); 393} 394 395// Test overwrite option NEW_NAME_IF_IN_USE: 396// 1. If destination file is in use, the source should be copied with the 397// new name after Do() and this new name file should be deleted 398// after rollback. 399// 2. If destination file is not in use, the source should be copied in the 400// destination folder after Do() and should be rolled back after Rollback(). 401TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) { 402 // Create source file 403 base::FilePath file_name_from(test_dir_.path()); 404 file_name_from = file_name_from.AppendASCII("File_From"); 405 CreateTextFile(file_name_from.value(), text_content_1); 406 ASSERT_TRUE(base::PathExists(file_name_from)); 407 408 // Create an executable in destination path by copying ourself to it. 409 wchar_t exe_full_path_str[MAX_PATH]; 410 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH); 411 base::FilePath exe_full_path(exe_full_path_str); 412 413 base::FilePath dir_name_to(test_dir_.path()); 414 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 415 base::CreateDirectory(dir_name_to); 416 ASSERT_TRUE(base::PathExists(dir_name_to)); 417 418 base::FilePath file_name_to(dir_name_to), alternate_to(dir_name_to); 419 file_name_to = file_name_to.AppendASCII("File_To"); 420 alternate_to = alternate_to.AppendASCII("Alternate_To"); 421 base::CopyFile(exe_full_path, file_name_to); 422 ASSERT_TRUE(base::PathExists(file_name_to)); 423 424 VLOG(1) << "copy ourself from " << exe_full_path.value() 425 << " to " << file_name_to.value(); 426 427 // Run the executable in destination path 428 STARTUPINFOW si = {sizeof(si)}; 429 PROCESS_INFORMATION pi = {0}; 430 ASSERT_TRUE( 431 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()), 432 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 433 NULL, NULL, &si, &pi)); 434 435 // test Do(). 436 scoped_ptr<CopyTreeWorkItem> work_item( 437 WorkItem::CreateCopyTreeWorkItem(file_name_from, 438 file_name_to, 439 temp_dir_.path(), 440 WorkItem::NEW_NAME_IF_IN_USE, 441 alternate_to)); 442 443 EXPECT_TRUE(work_item->Do()); 444 445 EXPECT_TRUE(base::PathExists(file_name_from)); 446 EXPECT_TRUE(base::PathExists(file_name_to)); 447 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 448 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to)); 449 // verify that the backup path does not exist 450 EXPECT_TRUE(work_item->backup_path_.path().empty()); 451 EXPECT_TRUE(base::ContentsEqual(file_name_from, alternate_to)); 452 453 // test rollback() 454 work_item->Rollback(); 455 456 EXPECT_TRUE(base::PathExists(file_name_from)); 457 EXPECT_TRUE(base::PathExists(file_name_to)); 458 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 459 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to)); 460 EXPECT_TRUE(work_item->backup_path_.path().empty()); 461 // the alternate file should be gone after rollback 462 EXPECT_FALSE(base::PathExists(alternate_to)); 463 464 TerminateProcess(pi.hProcess, 0); 465 // make sure the handle is closed. 466 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0); 467 CloseHandle(pi.hProcess); 468 CloseHandle(pi.hThread); 469 470 // Now the process has terminated, lets try overwriting the file again 471 work_item.reset(WorkItem::CreateCopyTreeWorkItem( 472 file_name_from, file_name_to, 473 temp_dir_.path(), WorkItem::NEW_NAME_IF_IN_USE, 474 alternate_to)); 475 if (IsFileInUse(file_name_to)) 476 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2)); 477 // If file is still in use, the rest of the test will fail. 478 ASSERT_FALSE(IsFileInUse(file_name_to)); 479 EXPECT_TRUE(work_item->Do()); 480 481 // Get the path of backup file 482 base::FilePath backup_file(work_item->backup_path_.path()); 483 EXPECT_FALSE(backup_file.empty()); 484 backup_file = backup_file.AppendASCII("File_To"); 485 486 EXPECT_TRUE(base::PathExists(file_name_from)); 487 EXPECT_TRUE(base::PathExists(file_name_to)); 488 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 489 EXPECT_TRUE(base::ContentsEqual(file_name_from, file_name_to)); 490 // verify that the backup path does exist 491 EXPECT_TRUE(base::PathExists(backup_file)); 492 EXPECT_FALSE(base::PathExists(alternate_to)); 493 494 // test rollback() 495 work_item->Rollback(); 496 497 EXPECT_TRUE(base::PathExists(file_name_from)); 498 EXPECT_TRUE(base::PathExists(file_name_to)); 499 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 500 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to)); 501 // the backup file should be gone after rollback 502 EXPECT_FALSE(base::PathExists(backup_file)); 503 EXPECT_FALSE(base::PathExists(alternate_to)); 504} 505 506// Test overwrite option IF_NOT_PRESENT: 507// 1. If destination file/directory exist, the source should not be copied 508// 2. If destination file/directory do not exist, the source should be copied 509// in the destination folder after Do() and should be rolled back after 510// Rollback(). 511// Flaky, http://crbug.com/59785. 512TEST_F(CopyTreeWorkItemTest, DISABLED_IfNotPresentTest) { 513 // Create source file 514 base::FilePath file_name_from(test_dir_.path()); 515 file_name_from = file_name_from.AppendASCII("File_From"); 516 CreateTextFile(file_name_from.value(), text_content_1); 517 ASSERT_TRUE(base::PathExists(file_name_from)); 518 519 // Create an executable in destination path by copying ourself to it. 520 wchar_t exe_full_path_str[MAX_PATH]; 521 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH); 522 base::FilePath exe_full_path(exe_full_path_str); 523 524 base::FilePath dir_name_to(test_dir_.path()); 525 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 526 base::CreateDirectory(dir_name_to); 527 ASSERT_TRUE(base::PathExists(dir_name_to)); 528 base::FilePath file_name_to(dir_name_to); 529 file_name_to = file_name_to.AppendASCII("File_To"); 530 base::CopyFile(exe_full_path, file_name_to); 531 ASSERT_TRUE(base::PathExists(file_name_to)); 532 533 // Get the path of backup file 534 base::FilePath backup_file(temp_dir_.path()); 535 backup_file = backup_file.AppendASCII("File_To"); 536 537 // test Do(). 538 scoped_ptr<CopyTreeWorkItem> work_item( 539 WorkItem::CreateCopyTreeWorkItem( 540 file_name_from, 541 file_name_to, temp_dir_.path(), 542 WorkItem::IF_NOT_PRESENT, 543 base::FilePath())); 544 EXPECT_TRUE(work_item->Do()); 545 546 // verify that the source, destination have not changed and backup path 547 // does not exist 548 EXPECT_TRUE(base::PathExists(file_name_from)); 549 EXPECT_TRUE(base::PathExists(file_name_to)); 550 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 551 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to)); 552 EXPECT_FALSE(base::PathExists(backup_file)); 553 554 // test rollback() 555 work_item->Rollback(); 556 557 // verify that the source, destination have not changed and backup path 558 // does not exist after rollback also 559 EXPECT_TRUE(base::PathExists(file_name_from)); 560 EXPECT_TRUE(base::PathExists(file_name_to)); 561 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 562 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to)); 563 EXPECT_FALSE(base::PathExists(backup_file)); 564 565 // Now delete the destination and try copying the file again. 566 base::DeleteFile(file_name_to, true); 567 work_item.reset(WorkItem::CreateCopyTreeWorkItem( 568 file_name_from, file_name_to, 569 temp_dir_.path(), WorkItem::IF_NOT_PRESENT, 570 base::FilePath())); 571 EXPECT_TRUE(work_item->Do()); 572 573 // verify that the source, destination are the same and backup path 574 // does not exist 575 EXPECT_TRUE(base::PathExists(file_name_from)); 576 EXPECT_TRUE(base::PathExists(file_name_to)); 577 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 578 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 579 EXPECT_FALSE(base::PathExists(backup_file)); 580 581 // test rollback() 582 work_item->Rollback(); 583 584 // verify that the destination does not exist anymore 585 EXPECT_TRUE(base::PathExists(file_name_from)); 586 EXPECT_FALSE(base::PathExists(file_name_to)); 587 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 588 EXPECT_FALSE(base::PathExists(backup_file)); 589} 590 591// Copy one file without rollback. The existing one in destination is in use. 592// Verify it is moved to backup location and stays there. 593// Flaky, http://crbug.com/59783. 594TEST_F(CopyTreeWorkItemTest, DISABLED_CopyFileInUseAndCleanup) { 595 // Create source file 596 base::FilePath file_name_from(test_dir_.path()); 597 file_name_from = file_name_from.AppendASCII("File_From"); 598 CreateTextFile(file_name_from.value(), text_content_1); 599 ASSERT_TRUE(base::PathExists(file_name_from)); 600 601 // Create an executable in destination path by copying ourself to it. 602 wchar_t exe_full_path_str[MAX_PATH]; 603 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH); 604 base::FilePath exe_full_path(exe_full_path_str); 605 606 base::FilePath dir_name_to(test_dir_.path()); 607 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir"); 608 base::CreateDirectory(dir_name_to); 609 ASSERT_TRUE(base::PathExists(dir_name_to)); 610 611 base::FilePath file_name_to(dir_name_to); 612 file_name_to = file_name_to.AppendASCII("File_To"); 613 base::CopyFile(exe_full_path, file_name_to); 614 ASSERT_TRUE(base::PathExists(file_name_to)); 615 616 VLOG(1) << "copy ourself from " << exe_full_path.value() 617 << " to " << file_name_to.value(); 618 619 // Run the executable in destination path 620 STARTUPINFOW si = {sizeof(si)}; 621 PROCESS_INFORMATION pi = {0}; 622 ASSERT_TRUE( 623 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()), 624 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 625 NULL, NULL, &si, &pi)); 626 627 base::FilePath backup_file; 628 629 // test Do(). 630 { 631 scoped_ptr<CopyTreeWorkItem> work_item( 632 WorkItem::CreateCopyTreeWorkItem(file_name_from, 633 file_name_to, 634 temp_dir_.path(), 635 WorkItem::IF_DIFFERENT, 636 base::FilePath())); 637 638 EXPECT_TRUE(work_item->Do()); 639 640 // Get the path of backup file 641 backup_file = work_item->backup_path_.path(); 642 EXPECT_FALSE(backup_file.empty()); 643 backup_file = backup_file.AppendASCII("File_To"); 644 645 EXPECT_TRUE(base::PathExists(file_name_from)); 646 EXPECT_TRUE(base::PathExists(file_name_to)); 647 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 648 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 649 // verify the file in used is moved to backup place. 650 EXPECT_TRUE(base::PathExists(backup_file)); 651 EXPECT_TRUE(base::ContentsEqual(exe_full_path, backup_file)); 652 } 653 654 // verify the file in used should be still at the backup place. 655 EXPECT_TRUE(base::PathExists(backup_file)); 656 EXPECT_TRUE(base::ContentsEqual(exe_full_path, backup_file)); 657 658 TerminateProcess(pi.hProcess, 0); 659 // make sure the handle is closed. 660 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0); 661 CloseHandle(pi.hProcess); 662 CloseHandle(pi.hThread); 663} 664 665// Copy a tree from source to destination. 666// Flaky, http://crbug.com/59784. 667TEST_F(CopyTreeWorkItemTest, DISABLED_CopyTree) { 668 // Create source tree 669 base::FilePath dir_name_from(test_dir_.path()); 670 dir_name_from = dir_name_from.AppendASCII("from"); 671 base::CreateDirectory(dir_name_from); 672 ASSERT_TRUE(base::PathExists(dir_name_from)); 673 674 base::FilePath dir_name_from_1(dir_name_from); 675 dir_name_from_1 = dir_name_from_1.AppendASCII("1"); 676 base::CreateDirectory(dir_name_from_1); 677 ASSERT_TRUE(base::PathExists(dir_name_from_1)); 678 679 base::FilePath dir_name_from_2(dir_name_from); 680 dir_name_from_2 = dir_name_from_2.AppendASCII("2"); 681 base::CreateDirectory(dir_name_from_2); 682 ASSERT_TRUE(base::PathExists(dir_name_from_2)); 683 684 base::FilePath file_name_from_1(dir_name_from_1); 685 file_name_from_1 = file_name_from_1.AppendASCII("File_1.txt"); 686 CreateTextFile(file_name_from_1.value(), text_content_1); 687 ASSERT_TRUE(base::PathExists(file_name_from_1)); 688 689 base::FilePath file_name_from_2(dir_name_from_2); 690 file_name_from_2 = file_name_from_2.AppendASCII("File_2.txt"); 691 CreateTextFile(file_name_from_2.value(), text_content_1); 692 ASSERT_TRUE(base::PathExists(file_name_from_2)); 693 694 base::FilePath dir_name_to(test_dir_.path()); 695 dir_name_to = dir_name_to.AppendASCII("to"); 696 697 // test Do() 698 { 699 scoped_ptr<CopyTreeWorkItem> work_item( 700 WorkItem::CreateCopyTreeWorkItem(dir_name_from, 701 dir_name_to, 702 temp_dir_.path(), 703 WorkItem::ALWAYS, 704 base::FilePath())); 705 706 EXPECT_TRUE(work_item->Do()); 707 } 708 709 base::FilePath file_name_to_1(dir_name_to); 710 file_name_to_1 = file_name_to_1.AppendASCII("1"); 711 file_name_to_1 = file_name_to_1.AppendASCII("File_1.txt"); 712 EXPECT_TRUE(base::PathExists(file_name_to_1)); 713 VLOG(1) << "compare " << file_name_from_1.value() 714 << " and " << file_name_to_1.value(); 715 EXPECT_TRUE(base::ContentsEqual(file_name_from_1, file_name_to_1)); 716 717 base::FilePath file_name_to_2(dir_name_to); 718 file_name_to_2 = file_name_to_2.AppendASCII("2"); 719 file_name_to_2 = file_name_to_2.AppendASCII("File_2.txt"); 720 EXPECT_TRUE(base::PathExists(file_name_to_2)); 721 VLOG(1) << "compare " << file_name_from_2.value() 722 << " and " << file_name_to_2.value(); 723 EXPECT_TRUE(base::ContentsEqual(file_name_from_2, file_name_to_2)); 724} 725