| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "build/build_config.h" | 5 #include "build/build_config.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <objbase.h> |
| 9 #include <shellapi.h> | 10 #include <shellapi.h> |
| 10 #include <shlobj.h> | 11 #include <shlobj.h> |
| 11 #include <tchar.h> | 12 #include <tchar.h> |
| 12 #include <winioctl.h> | 13 #include <winioctl.h> |
| 13 #endif | 14 #endif |
| 14 | 15 |
| 15 #include <algorithm> | 16 #include <algorithm> |
| 16 #include <fstream> | 17 #include <fstream> |
| 17 #include <set> | 18 #include <set> |
| 18 | 19 |
| 19 #include "base/base_paths.h" | 20 #include "base/base_paths.h" |
| 20 #include "base/file_path.h" | 21 #include "base/file_path.h" |
| 21 #include "base/file_util.h" | 22 #include "base/file_util.h" |
| 22 #include "base/path_service.h" | 23 #include "base/path_service.h" |
| 23 #include "base/scoped_temp_dir.h" | 24 #include "base/scoped_temp_dir.h" |
| 25 #include "base/memory/scoped_ptr.h" |
| 26 #include "base/test/test_file_util.h" |
| 24 #include "base/threading/platform_thread.h" | 27 #include "base/threading/platform_thread.h" |
| 25 #include "base/utf_string_conversions.h" | 28 #include "base/utf_string_conversions.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
| 27 #include "testing/platform_test.h" | 30 #include "testing/platform_test.h" |
| 28 | 31 |
| 29 #if defined(OS_WIN) | 32 #if defined(OS_WIN) |
| 30 #include "base/win/scoped_handle.h" | 33 #include "base/win/scoped_handle.h" |
| 31 #endif | 34 #endif |
| 32 | 35 |
| 33 // This macro helps avoid wrapped lines in the test structs. | 36 // This macro helps avoid wrapped lines in the test structs. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 mode &= ~mode_bits_to_clear; | 129 mode &= ~mode_bits_to_clear; |
| 127 ASSERT_TRUE(file_util::SetPosixFilePermissions(path, mode)); | 130 ASSERT_TRUE(file_util::SetPosixFilePermissions(path, mode)); |
| 128 } | 131 } |
| 129 #endif // defined(OS_POSIX) | 132 #endif // defined(OS_POSIX) |
| 130 | 133 |
| 131 const wchar_t bogus_content[] = L"I'm cannon fodder."; | 134 const wchar_t bogus_content[] = L"I'm cannon fodder."; |
| 132 | 135 |
| 133 const int FILES_AND_DIRECTORIES = | 136 const int FILES_AND_DIRECTORIES = |
| 134 file_util::FileEnumerator::FILES | file_util::FileEnumerator::DIRECTORIES; | 137 file_util::FileEnumerator::FILES | file_util::FileEnumerator::DIRECTORIES; |
| 135 | 138 |
| 136 // file_util winds up using autoreleased objects on the Mac, so this needs | |
| 137 // to be a PlatformTest | |
| 138 class FileUtilTest : public PlatformTest { | |
| 139 protected: | |
| 140 virtual void SetUp() OVERRIDE { | |
| 141 PlatformTest::SetUp(); | |
| 142 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 143 } | |
| 144 | |
| 145 ScopedTempDir temp_dir_; | |
| 146 }; | |
| 147 | |
| 148 // Collects all the results from the given file enumerator, and provides an | 139 // Collects all the results from the given file enumerator, and provides an |
| 149 // interface to query whether a given file is present. | 140 // interface to query whether a given file is present. |
| 150 class FindResultCollector { | 141 class FindResultCollector { |
| 151 public: | 142 public: |
| 152 explicit FindResultCollector(file_util::FileEnumerator& enumerator) { | 143 explicit FindResultCollector(file_util::FileEnumerator& enumerator) { |
| 153 FilePath cur_file; | 144 FilePath cur_file; |
| 154 while (!(cur_file = enumerator.Next()).value().empty()) { | 145 while (!(cur_file = enumerator.Next()).value().empty()) { |
| 155 FilePath::StringType path = cur_file.value(); | 146 FilePath::StringType path = cur_file.value(); |
| 156 // The file should not be returned twice. | 147 // The file should not be returned twice. |
| 157 EXPECT_TRUE(files_.end() == files_.find(path)) | 148 EXPECT_TRUE(files_.end() == files_.find(path)) |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 {L"/foo/bar/", L"/foo/bar"}, | 291 {L"/foo/bar/", L"/foo/bar"}, |
| 301 {L"/foo/bar//", L"/foo/bar"}, | 292 {L"/foo/bar//", L"/foo/bar"}, |
| 302 {L"/foo/bar", L"/foo"}, | 293 {L"/foo/bar", L"/foo"}, |
| 303 {L"/foo/bar./", L"/foo/bar."}, | 294 {L"/foo/bar./", L"/foo/bar."}, |
| 304 {L"/", L"/"}, | 295 {L"/", L"/"}, |
| 305 {L".", L"."}, | 296 {L".", L"."}, |
| 306 {L"..", L"."}, // yes, ".." technically lives in "." | 297 {L"..", L"."}, // yes, ".." technically lives in "." |
| 307 #endif | 298 #endif |
| 308 }; | 299 }; |
| 309 | 300 |
| 301 // file_util winds up using autoreleased objects on the Mac, so this needs |
| 302 // to be a PlatformTest |
| 303 class FileUtilTest : public PlatformTest { |
| 304 protected: |
| 305 virtual void SetUp() OVERRIDE { |
| 306 PlatformTest::SetUp(); |
| 307 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 308 ASSERT_TRUE(temp_dir_2_.CreateUniqueTempDir()); |
| 309 } |
| 310 |
| 311 ScopedTempDir temp_dir_; |
| 312 ScopedTempDir temp_dir_2_; |
| 313 }; |
| 314 |
| 310 TEST_F(FileUtilTest, CountFilesCreatedAfter) { | 315 TEST_F(FileUtilTest, CountFilesCreatedAfter) { |
| 311 FilePath file_name = | 316 FilePath file_name = |
| 312 temp_dir_.path().Append(FILE_PATH_LITERAL("f.txt")); | 317 temp_dir_.path().Append(FILE_PATH_LITERAL("f.txt")); |
| 313 CreateTextFile(file_name, L"test"); | 318 CreateTextFile(file_name, L"test"); |
| 314 | 319 |
| 315 base::PlatformFileInfo info; | 320 base::PlatformFileInfo info; |
| 316 file_util::GetFileInfo(file_name, &info); | 321 file_util::GetFileInfo(file_name, &info); |
| 317 base::Time file_time = info.creation_time; | 322 base::Time file_time = info.creation_time; |
| 318 | 323 |
| 319 base::TimeDelta two_secs = base::TimeDelta::FromSeconds(2); | 324 base::TimeDelta two_secs = base::TimeDelta::FromSeconds(2); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 | 395 |
| 391 // Beacuse this test created |dir_path|, we know it is not a link | 396 // Beacuse this test created |dir_path|, we know it is not a link |
| 392 // or junction. So, the real path of the directory holding file a | 397 // or junction. So, the real path of the directory holding file a |
| 393 // must be the parent of the path holding file b. | 398 // must be the parent of the path holding file b. |
| 394 ASSERT_TRUE(normalized_file_a_path.DirName() | 399 ASSERT_TRUE(normalized_file_a_path.DirName() |
| 395 .IsParent(normalized_file_b_path.DirName())); | 400 .IsParent(normalized_file_b_path.DirName())); |
| 396 } | 401 } |
| 397 | 402 |
| 398 #if defined(OS_WIN) | 403 #if defined(OS_WIN) |
| 399 | 404 |
| 405 class FileUtilShortcutTest : public FileUtilTest { |
| 406 protected: |
| 407 virtual void SetUp() OVERRIDE { |
| 408 FileUtilTest::SetUp(); |
| 409 |
| 410 EXPECT_EQ(S_OK, CoInitialize(NULL)); |
| 411 |
| 412 link_file_ = temp_dir_.path().Append(L"My Link.lnk"); |
| 413 |
| 414 // Shortcut 1's properties |
| 415 { |
| 416 file_contents_ = string16(L"This is a target."); |
| 417 const FilePath target_file(temp_dir_.path().Append(L"Target 1.txt")); |
| 418 CreateTextFile(target_file, file_contents_); |
| 419 |
| 420 link_properties_.set_target(target_file.value()); |
| 421 link_properties_.set_working_dir(temp_dir_.path().value()); |
| 422 link_properties_.set_arguments(L"--magic --awesome"); |
| 423 link_properties_.set_description(L"Chrome is awesome."); |
| 424 link_properties_.set_icon(link_properties_.target, 4); |
| 425 link_properties_.set_app_id(L"Chrome"); |
| 426 link_properties_.set_dual_mode(false); |
| 427 } |
| 428 |
| 429 // Shortcut 2's properties (all different from properties of shortcut 1). |
| 430 { |
| 431 file_contents_2_ = string16(L"This is another target."); |
| 432 const FilePath target_file_2(temp_dir_.path().Append(L"Target 2.txt")); |
| 433 CreateTextFile(target_file_2, file_contents_2_); |
| 434 |
| 435 const FilePath icon_path_2(temp_dir_.path().Append(L"icon.ico")); |
| 436 CreateTextFile(icon_path_2, L"A fake icon"); |
| 437 |
| 438 link_properties_2_.set_target(target_file_2.value()); |
| 439 link_properties_2_.set_working_dir(temp_dir_2_.path().value()); |
| 440 link_properties_2_.set_arguments(L"--super --crazy"); |
| 441 link_properties_2_.set_description(L"The best in the west."); |
| 442 link_properties_2_.set_icon(icon_path_2.value(), 0); |
| 443 link_properties_2_.set_app_id(L"Chrome.UserLevelCrazySuffix"); |
| 444 link_properties_2_.set_dual_mode(true); |
| 445 } |
| 446 } |
| 447 |
| 448 virtual void TearDown() OVERRIDE { |
| 449 CoUninitialize(); |
| 450 } |
| 451 |
| 452 // The link file to be created/updated in the shortcut tests below. |
| 453 FilePath link_file_; |
| 454 |
| 455 // Properties for the created shortcut. |
| 456 string16 file_contents_; |
| 457 file_util::ShortcutProperties link_properties_; |
| 458 |
| 459 // Properties for the updated shortcut. |
| 460 string16 file_contents_2_; |
| 461 file_util::ShortcutProperties link_properties_2_; |
| 462 }; |
| 463 |
| 464 TEST_F(FileUtilShortcutTest, CreateShortcut) { |
| 465 file_util::ShortcutProperties only_target_properties; |
| 466 only_target_properties.set_target(link_properties_.target); |
| 467 |
| 468 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 469 link_file_.value().c_str(), only_target_properties, |
| 470 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 471 |
| 472 FilePath resolved_name; |
| 473 EXPECT_TRUE(file_util::ResolveShortcut(link_file_, &resolved_name, NULL)); |
| 474 const string16 read_contents(ReadTextFile(resolved_name)); |
| 475 EXPECT_EQ(file_contents_, read_contents); |
| 476 } |
| 477 |
| 478 TEST_F(FileUtilShortcutTest, CreateShortcutWithOnlySomeProperties) { |
| 479 file_util::ShortcutProperties target_and_args_properties; |
| 480 target_and_args_properties.set_target(link_properties_.target); |
| 481 target_and_args_properties.set_arguments(link_properties_.arguments); |
| 482 |
| 483 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 484 link_file_.value().c_str(), target_and_args_properties, |
| 485 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 486 |
| 487 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, |
| 488 file_util::VerifyShortcut(link_file_.value(), |
| 489 target_and_args_properties)); |
| 490 } |
| 491 |
| 492 TEST_F(FileUtilShortcutTest, CreateShortcutVerifyProperties) { |
| 493 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 494 link_file_.value().c_str(), link_properties_, |
| 495 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 496 |
| 497 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, |
| 498 file_util::VerifyShortcut(link_file_.value(), link_properties_)); |
| 499 } |
| 500 |
| 501 TEST_F(FileUtilShortcutTest, UpdateShortcutVerifyProperties) { |
| 502 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 503 link_file_.value().c_str(), link_properties_, |
| 504 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 505 |
| 506 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 507 link_file_.value().c_str(), link_properties_2_, |
| 508 file_util::SHORTCUT_UPDATE_EXISTING)); |
| 509 |
| 510 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, |
| 511 file_util::VerifyShortcut(link_file_.value(), link_properties_2_)); |
| 512 } |
| 513 |
| 514 TEST_F(FileUtilShortcutTest, UpdateShortcutUpdateOnlyTarget) { |
| 515 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 516 link_file_.value().c_str(), link_properties_, |
| 517 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 518 |
| 519 file_util::ShortcutProperties update_only_target_properties; |
| 520 update_only_target_properties.set_target(link_properties_2_.target); |
| 521 |
| 522 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 523 link_file_.value().c_str(), update_only_target_properties, |
| 524 file_util::SHORTCUT_UPDATE_EXISTING)); |
| 525 |
| 526 file_util::ShortcutProperties expected_properties = link_properties_; |
| 527 expected_properties.set_target(link_properties_2_.target); |
| 528 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, |
| 529 file_util::VerifyShortcut(link_file_.value(), expected_properties)); |
| 530 } |
| 531 |
| 532 TEST_F(FileUtilShortcutTest, UpdateShortcutMakeDualMode) { |
| 533 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 534 link_file_.value().c_str(), link_properties_, |
| 535 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 536 |
| 537 file_util::ShortcutProperties make_dual_mode_properties; |
| 538 make_dual_mode_properties.set_dual_mode(true); |
| 539 |
| 540 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 541 link_file_.value().c_str(), make_dual_mode_properties, |
| 542 file_util::SHORTCUT_UPDATE_EXISTING)); |
| 543 |
| 544 file_util::ShortcutProperties expected_properties = link_properties_; |
| 545 expected_properties.set_dual_mode(true); |
| 546 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, |
| 547 file_util::VerifyShortcut(link_file_.value(), expected_properties)); |
| 548 } |
| 549 |
| 550 TEST_F(FileUtilShortcutTest, UpdateShortcutRemoveDualMode) { |
| 551 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 552 link_file_.value().c_str(), link_properties_2_, |
| 553 file_util::SHORTCUT_CREATE_ALWAYS)); |
| 554 |
| 555 file_util::ShortcutProperties remove_dual_mode_properties; |
| 556 remove_dual_mode_properties.set_dual_mode(false); |
| 557 |
| 558 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( |
| 559 link_file_.value().c_str(), remove_dual_mode_properties, |
| 560 file_util::SHORTCUT_UPDATE_EXISTING)); |
| 561 |
| 562 file_util::ShortcutProperties expected_properties = link_properties_2_; |
| 563 expected_properties.set_dual_mode(false); |
| 564 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, |
| 565 file_util::VerifyShortcut(link_file_.value(), expected_properties)); |
| 566 } |
| 567 |
| 400 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) { | 568 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) { |
| 401 // Build the following directory structure: | 569 // Build the following directory structure: |
| 402 // | 570 // |
| 403 // temp_dir | 571 // temp_dir |
| 404 // |-> base_a | 572 // |-> base_a |
| 405 // | |-> sub_a | 573 // | |-> sub_a |
| 406 // | |-> file.txt | 574 // | |-> file.txt |
| 407 // | |-> long_name___... (Very long name.) | 575 // | |-> long_name___... (Very long name.) |
| 408 // | |-> sub_long | 576 // | |-> sub_long |
| 409 // | |-> deep.txt | 577 // | |-> deep.txt |
| (...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1632 std::wstring contents; | 1800 std::wstring contents; |
| 1633 contents = ReadTextFile(link_file); | 1801 contents = ReadTextFile(link_file); |
| 1634 EXPECT_EQ(L"This is the target.", contents); | 1802 EXPECT_EQ(L"This is the target.", contents); |
| 1635 | 1803 |
| 1636 // Cleaning | 1804 // Cleaning |
| 1637 DeleteFile(target_file.value().c_str()); | 1805 DeleteFile(target_file.value().c_str()); |
| 1638 DeleteFile(link_file.value().c_str()); | 1806 DeleteFile(link_file.value().c_str()); |
| 1639 CoUninitialize(); | 1807 CoUninitialize(); |
| 1640 } | 1808 } |
| 1641 | 1809 |
| 1642 TEST_F(FileUtilTest, CreateShortcutTest) { | |
| 1643 const wchar_t* file_contents = L"This is another target."; | |
| 1644 FilePath target_file = temp_dir_.path().Append(L"Target1.txt"); | |
| 1645 CreateTextFile(target_file, file_contents); | |
| 1646 | |
| 1647 FilePath link_file = temp_dir_.path().Append(L"Link1.lnk"); | |
| 1648 | |
| 1649 CoInitialize(NULL); | |
| 1650 EXPECT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 1651 target_file.value().c_str(), link_file.value().c_str(), NULL, | |
| 1652 NULL, NULL, NULL, 0, NULL, | |
| 1653 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 1654 FilePath resolved_name; | |
| 1655 EXPECT_TRUE(file_util::ResolveShortcut(link_file, &resolved_name, NULL)); | |
| 1656 std::wstring read_contents = ReadTextFile(resolved_name); | |
| 1657 EXPECT_EQ(file_contents, read_contents); | |
| 1658 | |
| 1659 DeleteFile(target_file.value().c_str()); | |
| 1660 DeleteFile(link_file.value().c_str()); | |
| 1661 CoUninitialize(); | |
| 1662 } | |
| 1663 | |
| 1664 TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) { | 1810 TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) { |
| 1665 // Create a directory | 1811 // Create a directory |
| 1666 FilePath dir_name_from = | 1812 FilePath dir_name_from = |
| 1667 temp_dir_.path().Append(FILE_PATH_LITERAL("CopyAndDelete_From_Subdir")); | 1813 temp_dir_.path().Append(FILE_PATH_LITERAL("CopyAndDelete_From_Subdir")); |
| 1668 file_util::CreateDirectory(dir_name_from); | 1814 file_util::CreateDirectory(dir_name_from); |
| 1669 ASSERT_TRUE(file_util::PathExists(dir_name_from)); | 1815 ASSERT_TRUE(file_util::PathExists(dir_name_from)); |
| 1670 | 1816 |
| 1671 // Create a file under the directory | 1817 // Create a file under the directory |
| 1672 FilePath file_name_from = | 1818 FilePath file_name_from = |
| 1673 dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt")); | 1819 dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt")); |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2458 file_util::VerifyPathControlledByUser( | 2604 file_util::VerifyPathControlledByUser( |
| 2459 base_dir_, text_file_, uid_, ok_gids_)); | 2605 base_dir_, text_file_, uid_, ok_gids_)); |
| 2460 EXPECT_TRUE( | 2606 EXPECT_TRUE( |
| 2461 file_util::VerifyPathControlledByUser( | 2607 file_util::VerifyPathControlledByUser( |
| 2462 sub_dir_, text_file_, uid_, ok_gids_)); | 2608 sub_dir_, text_file_, uid_, ok_gids_)); |
| 2463 } | 2609 } |
| 2464 | 2610 |
| 2465 #endif // defined(OS_POSIX) | 2611 #endif // defined(OS_POSIX) |
| 2466 | 2612 |
| 2467 } // namespace | 2613 } // namespace |
| OLD | NEW |