Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Side by Side Diff: chrome/installer/util/copy_tree_work_item_unittest.cc

Issue 9700038: ScopedProcessInformation protects against process/thread handle leaks from CreateProcess calls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove changes from another CL. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <windows.h> 5 #include <windows.h>
6 6
7 #include <fstream> 7 #include <fstream>
8 8
9 #include "base/base_paths.h" 9 #include "base/base_paths.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/path_service.h" 13 #include "base/path_service.h"
14 #include "base/process_util.h" 14 #include "base/process_util.h"
15 #include "base/scoped_temp_dir.h" 15 #include "base/scoped_temp_dir.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/threading/platform_thread.h" 17 #include "base/threading/platform_thread.h"
18 #include "base/win/scoped_process_information.h"
18 #include "chrome/installer/util/copy_tree_work_item.h" 19 #include "chrome/installer/util/copy_tree_work_item.h"
19 #include "chrome/installer/util/work_item.h" 20 #include "chrome/installer/util/work_item.h"
20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
21 22
22 namespace { 23 namespace {
23 class CopyTreeWorkItemTest : public testing::Test { 24 class CopyTreeWorkItemTest : public testing::Test {
24 protected: 25 protected:
25 virtual void SetUp() { 26 virtual void SetUp() {
26 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 27 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
27 ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); 28 ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 FilePath file_name_to(dir_name_to); 339 FilePath file_name_to(dir_name_to);
339 file_name_to = file_name_to.AppendASCII("File_To"); 340 file_name_to = file_name_to.AppendASCII("File_To");
340 file_util::CopyFile(exe_full_path, file_name_to); 341 file_util::CopyFile(exe_full_path, file_name_to);
341 ASSERT_TRUE(file_util::PathExists(file_name_to)); 342 ASSERT_TRUE(file_util::PathExists(file_name_to));
342 343
343 VLOG(1) << "copy ourself from " << exe_full_path.value() 344 VLOG(1) << "copy ourself from " << exe_full_path.value()
344 << " to " << file_name_to.value(); 345 << " to " << file_name_to.value();
345 346
346 // Run the executable in destination path 347 // Run the executable in destination path
347 STARTUPINFOW si = {sizeof(si)}; 348 STARTUPINFOW si = {sizeof(si)};
348 PROCESS_INFORMATION pi = {0}; 349 base::win::ScopedProcessInformation pi;
349 ASSERT_TRUE( 350 ASSERT_TRUE(
350 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()), 351 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()),
351 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 352 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
352 NULL, NULL, &si, &pi)); 353 NULL, NULL, &si, pi.Receive()));
353 354
354 // test Do(). 355 // test Do().
355 scoped_ptr<CopyTreeWorkItem> work_item( 356 scoped_ptr<CopyTreeWorkItem> work_item(
356 WorkItem::CreateCopyTreeWorkItem(file_name_from, 357 WorkItem::CreateCopyTreeWorkItem(file_name_from,
357 file_name_to, 358 file_name_to,
358 temp_dir_.path(), 359 temp_dir_.path(),
359 WorkItem::IF_DIFFERENT, 360 WorkItem::IF_DIFFERENT,
360 FilePath())); 361 FilePath()));
361 362
362 EXPECT_TRUE(work_item->Do()); 363 EXPECT_TRUE(work_item->Do());
(...skipping 14 matching lines...) Expand all
377 // test rollback() 378 // test rollback()
378 work_item->Rollback(); 379 work_item->Rollback();
379 380
380 EXPECT_TRUE(file_util::PathExists(file_name_from)); 381 EXPECT_TRUE(file_util::PathExists(file_name_from));
381 EXPECT_TRUE(file_util::PathExists(file_name_to)); 382 EXPECT_TRUE(file_util::PathExists(file_name_to));
382 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 383 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 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
384 // the backup file should be gone after rollback 385 // the backup file should be gone after rollback
385 EXPECT_FALSE(file_util::PathExists(backup_file)); 386 EXPECT_FALSE(file_util::PathExists(backup_file));
386 387
387 TerminateProcess(pi.hProcess, 0); 388 TerminateProcess(pi.Get().hProcess, 0);
388 // make sure the handle is closed. 389 EXPECT_TRUE(WaitForSingleObject(pi.Get().hProcess, 10000) == WAIT_OBJECT_0);
389 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
390 CloseHandle(pi.hProcess);
391 CloseHandle(pi.hThread);
392 } 390 }
393 391
394 // Test overwrite option NEW_NAME_IF_IN_USE: 392 // Test overwrite option NEW_NAME_IF_IN_USE:
395 // 1. If destination file is in use, the source should be copied with the 393 // 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 394 // new name after Do() and this new name file should be deleted
397 // after rollback. 395 // after rollback.
398 // 2. If destination file is not in use, the source should be copied in the 396 // 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(). 397 // destination folder after Do() and should be rolled back after Rollback().
400 TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) { 398 TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) {
401 // Create source file 399 // Create source file
(...skipping 16 matching lines...) Expand all
418 file_name_to = file_name_to.AppendASCII("File_To"); 416 file_name_to = file_name_to.AppendASCII("File_To");
419 alternate_to = alternate_to.AppendASCII("Alternate_To"); 417 alternate_to = alternate_to.AppendASCII("Alternate_To");
420 file_util::CopyFile(exe_full_path, file_name_to); 418 file_util::CopyFile(exe_full_path, file_name_to);
421 ASSERT_TRUE(file_util::PathExists(file_name_to)); 419 ASSERT_TRUE(file_util::PathExists(file_name_to));
422 420
423 VLOG(1) << "copy ourself from " << exe_full_path.value() 421 VLOG(1) << "copy ourself from " << exe_full_path.value()
424 << " to " << file_name_to.value(); 422 << " to " << file_name_to.value();
425 423
426 // Run the executable in destination path 424 // Run the executable in destination path
427 STARTUPINFOW si = {sizeof(si)}; 425 STARTUPINFOW si = {sizeof(si)};
428 PROCESS_INFORMATION pi = {0}; 426 base::win::ScopedProcessInformation pi;
429 ASSERT_TRUE( 427 ASSERT_TRUE(
430 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()), 428 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()),
431 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 429 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
432 NULL, NULL, &si, &pi)); 430 NULL, NULL, &si, pi.Receive()));
433 431
434 // test Do(). 432 // test Do().
435 scoped_ptr<CopyTreeWorkItem> work_item( 433 scoped_ptr<CopyTreeWorkItem> work_item(
436 WorkItem::CreateCopyTreeWorkItem(file_name_from, 434 WorkItem::CreateCopyTreeWorkItem(file_name_from,
437 file_name_to, 435 file_name_to,
438 temp_dir_.path(), 436 temp_dir_.path(),
439 WorkItem::NEW_NAME_IF_IN_USE, 437 WorkItem::NEW_NAME_IF_IN_USE,
440 alternate_to)); 438 alternate_to));
441 439
442 EXPECT_TRUE(work_item->Do()); 440 EXPECT_TRUE(work_item->Do());
(...skipping 10 matching lines...) Expand all
453 work_item->Rollback(); 451 work_item->Rollback();
454 452
455 EXPECT_TRUE(file_util::PathExists(file_name_from)); 453 EXPECT_TRUE(file_util::PathExists(file_name_from));
456 EXPECT_TRUE(file_util::PathExists(file_name_to)); 454 EXPECT_TRUE(file_util::PathExists(file_name_to));
457 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1)); 455 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
458 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to)); 456 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
459 EXPECT_TRUE(work_item->backup_path_.path().empty()); 457 EXPECT_TRUE(work_item->backup_path_.path().empty());
460 // the alternate file should be gone after rollback 458 // the alternate file should be gone after rollback
461 EXPECT_FALSE(file_util::PathExists(alternate_to)); 459 EXPECT_FALSE(file_util::PathExists(alternate_to));
462 460
463 TerminateProcess(pi.hProcess, 0); 461 TerminateProcess(pi.Get().hProcess, 0);
464 // make sure the handle is closed. 462 EXPECT_TRUE(WaitForSingleObject(pi.Get().hProcess, 10000) == WAIT_OBJECT_0);
465 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
466 CloseHandle(pi.hProcess);
467 CloseHandle(pi.hThread);
468 463
469 // Now the process has terminated, lets try overwriting the file again 464 // Now the process has terminated, lets try overwriting the file again
470 work_item.reset(WorkItem::CreateCopyTreeWorkItem( 465 work_item.reset(WorkItem::CreateCopyTreeWorkItem(
471 file_name_from, file_name_to, 466 file_name_from, file_name_to,
472 temp_dir_.path(), WorkItem::NEW_NAME_IF_IN_USE, 467 temp_dir_.path(), WorkItem::NEW_NAME_IF_IN_USE,
473 alternate_to)); 468 alternate_to));
474 if (IsFileInUse(file_name_to)) 469 if (IsFileInUse(file_name_to))
475 base::PlatformThread::Sleep(2000); 470 base::PlatformThread::Sleep(2000);
476 // If file is still in use, the rest of the test will fail. 471 // If file is still in use, the rest of the test will fail.
477 ASSERT_FALSE(IsFileInUse(file_name_to)); 472 ASSERT_FALSE(IsFileInUse(file_name_to));
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 FilePath file_name_to(dir_name_to); 605 FilePath file_name_to(dir_name_to);
611 file_name_to = file_name_to.AppendASCII("File_To"); 606 file_name_to = file_name_to.AppendASCII("File_To");
612 file_util::CopyFile(exe_full_path, file_name_to); 607 file_util::CopyFile(exe_full_path, file_name_to);
613 ASSERT_TRUE(file_util::PathExists(file_name_to)); 608 ASSERT_TRUE(file_util::PathExists(file_name_to));
614 609
615 VLOG(1) << "copy ourself from " << exe_full_path.value() 610 VLOG(1) << "copy ourself from " << exe_full_path.value()
616 << " to " << file_name_to.value(); 611 << " to " << file_name_to.value();
617 612
618 // Run the executable in destination path 613 // Run the executable in destination path
619 STARTUPINFOW si = {sizeof(si)}; 614 STARTUPINFOW si = {sizeof(si)};
620 PROCESS_INFORMATION pi = {0}; 615 base::win::ScopedProcessInformation pi;
621 ASSERT_TRUE( 616 ASSERT_TRUE(
622 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()), 617 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()),
623 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 618 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
624 NULL, NULL, &si, &pi)); 619 NULL, NULL, &si, pi.Receive()));
625 620
626 FilePath backup_file; 621 FilePath backup_file;
627 622
628 // test Do(). 623 // test Do().
629 { 624 {
630 scoped_ptr<CopyTreeWorkItem> work_item( 625 scoped_ptr<CopyTreeWorkItem> work_item(
631 WorkItem::CreateCopyTreeWorkItem(file_name_from, 626 WorkItem::CreateCopyTreeWorkItem(file_name_from,
632 file_name_to, 627 file_name_to,
633 temp_dir_.path(), 628 temp_dir_.path(),
634 WorkItem::IF_DIFFERENT, 629 WorkItem::IF_DIFFERENT,
(...skipping 12 matching lines...) Expand all
647 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1)); 642 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
648 // verify the file in used is moved to backup place. 643 // verify the file in used is moved to backup place.
649 EXPECT_TRUE(file_util::PathExists(backup_file)); 644 EXPECT_TRUE(file_util::PathExists(backup_file));
650 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, backup_file)); 645 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, backup_file));
651 } 646 }
652 647
653 // verify the file in used should be still at the backup place. 648 // verify the file in used should be still at the backup place.
654 EXPECT_TRUE(file_util::PathExists(backup_file)); 649 EXPECT_TRUE(file_util::PathExists(backup_file));
655 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, backup_file)); 650 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, backup_file));
656 651
657 TerminateProcess(pi.hProcess, 0); 652 TerminateProcess(pi.Get().hProcess, 0);
658 // make sure the handle is closed. 653 EXPECT_TRUE(WaitForSingleObject(pi.Get().hProcess, 10000) == WAIT_OBJECT_0);
659 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
660 CloseHandle(pi.hProcess);
661 CloseHandle(pi.hThread);
662 } 654 }
663 655
664 // Copy a tree from source to destination. 656 // Copy a tree from source to destination.
665 // Flaky, http://crbug.com/59784. 657 // Flaky, http://crbug.com/59784.
666 TEST_F(CopyTreeWorkItemTest, DISABLED_CopyTree) { 658 TEST_F(CopyTreeWorkItemTest, DISABLED_CopyTree) {
667 // Create source tree 659 // Create source tree
668 FilePath dir_name_from(test_dir_.path()); 660 FilePath dir_name_from(test_dir_.path());
669 dir_name_from = dir_name_from.AppendASCII("from"); 661 dir_name_from = dir_name_from.AppendASCII("from");
670 file_util::CreateDirectory(dir_name_from); 662 file_util::CreateDirectory(dir_name_from);
671 ASSERT_TRUE(file_util::PathExists(dir_name_from)); 663 ASSERT_TRUE(file_util::PathExists(dir_name_from));
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 EXPECT_TRUE(file_util::ContentsEqual(file_name_from_1, file_name_to_1)); 706 EXPECT_TRUE(file_util::ContentsEqual(file_name_from_1, file_name_to_1));
715 707
716 FilePath file_name_to_2(dir_name_to); 708 FilePath file_name_to_2(dir_name_to);
717 file_name_to_2 = file_name_to_2.AppendASCII("2"); 709 file_name_to_2 = file_name_to_2.AppendASCII("2");
718 file_name_to_2 = file_name_to_2.AppendASCII("File_2.txt"); 710 file_name_to_2 = file_name_to_2.AppendASCII("File_2.txt");
719 EXPECT_TRUE(file_util::PathExists(file_name_to_2)); 711 EXPECT_TRUE(file_util::PathExists(file_name_to_2));
720 VLOG(1) << "compare " << file_name_from_2.value() 712 VLOG(1) << "compare " << file_name_from_2.value()
721 << " and " << file_name_to_2.value(); 713 << " and " << file_name_to_2.value();
722 EXPECT_TRUE(file_util::ContentsEqual(file_name_from_2, file_name_to_2)); 714 EXPECT_TRUE(file_util::ContentsEqual(file_name_from_2, file_name_to_2));
723 } 715 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698