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