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