Chromium Code Reviews| 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 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 target_file_2_ = temp_dir_.path().Append(L"Target 2.txt"); | |
| 433 CreateTextFile(target_file_2_, file_contents_2_); | |
| 434 | |
| 435 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 private: | |
| 464 // Keep these paths around for the life of this fixture as they contain | |
| 465 // strings pointed to by |link_properties_*| above. | |
|
robertshield
2012/09/06 02:37:34
nit: "strings pointed to" -> "paths referenced by"
gab
2012/09/06 04:20:02
Oops, thanks for catching this, this is actually n
| |
| 466 FilePath target_file_; | |
| 467 FilePath target_file_2_; | |
| 468 FilePath icon_path_2_; | |
| 469 }; | |
| 470 | |
| 471 TEST_F(FileUtilShortcutTest, CreateShortcut) { | |
| 472 file_util::ShortcutProperties only_target_properties; | |
| 473 only_target_properties.set_target(link_properties_.target); | |
| 474 | |
| 475 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 476 link_file_.value().c_str(), only_target_properties, | |
| 477 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 478 | |
| 479 FilePath resolved_name; | |
| 480 EXPECT_TRUE(file_util::ResolveShortcut(link_file_, &resolved_name, NULL)); | |
| 481 const string16 read_contents(ReadTextFile(resolved_name)); | |
| 482 EXPECT_EQ(file_contents_, read_contents); | |
| 483 } | |
| 484 | |
| 485 TEST_F(FileUtilShortcutTest, CreateShortcutWithOnlySomeProperties) { | |
| 486 file_util::ShortcutProperties target_and_args_properties; | |
| 487 target_and_args_properties.set_target(link_properties_.target); | |
| 488 target_and_args_properties.set_arguments(link_properties_.arguments); | |
| 489 | |
| 490 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 491 link_file_.value().c_str(), target_and_args_properties, | |
| 492 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 493 | |
| 494 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, | |
| 495 file_util::VerifyShortcut(link_file_.value(), | |
| 496 target_and_args_properties)); | |
| 497 } | |
| 498 | |
| 499 TEST_F(FileUtilShortcutTest, CreateShortcutVerifyProperties) { | |
| 500 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 501 link_file_.value().c_str(), link_properties_, | |
| 502 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 503 | |
| 504 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, | |
| 505 file_util::VerifyShortcut(link_file_.value(), link_properties_)); | |
| 506 } | |
| 507 | |
| 508 TEST_F(FileUtilShortcutTest, UpdateShortcutVerifyProperties) { | |
| 509 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 510 link_file_.value().c_str(), link_properties_, | |
| 511 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 512 | |
| 513 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 514 link_file_.value().c_str(), link_properties_2_, | |
| 515 file_util::SHORTCUT_UPDATE_EXISTING)); | |
| 516 | |
| 517 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, | |
| 518 file_util::VerifyShortcut(link_file_.value(), link_properties_2_)); | |
| 519 } | |
| 520 | |
| 521 TEST_F(FileUtilShortcutTest, UpdateShortcutUpdateOnlyTarget) { | |
| 522 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 523 link_file_.value().c_str(), link_properties_, | |
| 524 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 525 | |
| 526 file_util::ShortcutProperties update_only_target_properties; | |
| 527 update_only_target_properties.set_target(link_properties_2_.target); | |
| 528 | |
| 529 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 530 link_file_.value().c_str(), update_only_target_properties, | |
| 531 file_util::SHORTCUT_UPDATE_EXISTING)); | |
| 532 | |
| 533 file_util::ShortcutProperties expected_properties = link_properties_; | |
| 534 expected_properties.set_target(link_properties_2_.target); | |
| 535 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, | |
| 536 file_util::VerifyShortcut(link_file_.value(), expected_properties)); | |
| 537 } | |
| 538 | |
| 539 TEST_F(FileUtilShortcutTest, UpdateShortcutMakeDualMode) { | |
| 540 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 541 link_file_.value().c_str(), link_properties_, | |
| 542 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 543 | |
| 544 file_util::ShortcutProperties make_dual_mode_properties; | |
| 545 make_dual_mode_properties.set_dual_mode(true); | |
| 546 | |
| 547 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 548 link_file_.value().c_str(), make_dual_mode_properties, | |
| 549 file_util::SHORTCUT_UPDATE_EXISTING)); | |
| 550 | |
| 551 file_util::ShortcutProperties expected_properties = link_properties_; | |
| 552 expected_properties.set_dual_mode(true); | |
| 553 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, | |
| 554 file_util::VerifyShortcut(link_file_.value(), expected_properties)); | |
| 555 } | |
| 556 | |
| 557 TEST_F(FileUtilShortcutTest, UpdateShortcutRemoveDualMode) { | |
| 558 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 559 link_file_.value().c_str(), link_properties_2_, | |
| 560 file_util::SHORTCUT_CREATE_ALWAYS)); | |
| 561 | |
| 562 file_util::ShortcutProperties remove_dual_mode_properties; | |
| 563 remove_dual_mode_properties.set_dual_mode(false); | |
| 564 | |
| 565 ASSERT_TRUE(file_util::CreateOrUpdateShortcutLink( | |
| 566 link_file_.value().c_str(), remove_dual_mode_properties, | |
| 567 file_util::SHORTCUT_UPDATE_EXISTING)); | |
| 568 | |
| 569 file_util::ShortcutProperties expected_properties = link_properties_2_; | |
| 570 expected_properties.set_dual_mode(false); | |
| 571 ASSERT_EQ(file_util::VERIFY_SHORTCUT_SUCCESS, | |
| 572 file_util::VerifyShortcut(link_file_.value(), expected_properties)); | |
| 573 } | |
| 574 | |
| 400 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) { | 575 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) { |
| 401 // Build the following directory structure: | 576 // Build the following directory structure: |
| 402 // | 577 // |
| 403 // temp_dir | 578 // temp_dir |
| 404 // |-> base_a | 579 // |-> base_a |
| 405 // | |-> sub_a | 580 // | |-> sub_a |
| 406 // | |-> file.txt | 581 // | |-> file.txt |
| 407 // | |-> long_name___... (Very long name.) | 582 // | |-> long_name___... (Very long name.) |
| 408 // | |-> sub_long | 583 // | |-> sub_long |
| 409 // | |-> deep.txt | 584 // | |-> deep.txt |
| (...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1632 std::wstring contents; | 1807 std::wstring contents; |
| 1633 contents = ReadTextFile(link_file); | 1808 contents = ReadTextFile(link_file); |
| 1634 EXPECT_EQ(L"This is the target.", contents); | 1809 EXPECT_EQ(L"This is the target.", contents); |
| 1635 | 1810 |
| 1636 // Cleaning | 1811 // Cleaning |
| 1637 DeleteFile(target_file.value().c_str()); | 1812 DeleteFile(target_file.value().c_str()); |
| 1638 DeleteFile(link_file.value().c_str()); | 1813 DeleteFile(link_file.value().c_str()); |
| 1639 CoUninitialize(); | 1814 CoUninitialize(); |
| 1640 } | 1815 } |
| 1641 | 1816 |
| 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) { | 1817 TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) { |
| 1665 // Create a directory | 1818 // Create a directory |
| 1666 FilePath dir_name_from = | 1819 FilePath dir_name_from = |
| 1667 temp_dir_.path().Append(FILE_PATH_LITERAL("CopyAndDelete_From_Subdir")); | 1820 temp_dir_.path().Append(FILE_PATH_LITERAL("CopyAndDelete_From_Subdir")); |
| 1668 file_util::CreateDirectory(dir_name_from); | 1821 file_util::CreateDirectory(dir_name_from); |
| 1669 ASSERT_TRUE(file_util::PathExists(dir_name_from)); | 1822 ASSERT_TRUE(file_util::PathExists(dir_name_from)); |
| 1670 | 1823 |
| 1671 // Create a file under the directory | 1824 // Create a file under the directory |
| 1672 FilePath file_name_from = | 1825 FilePath file_name_from = |
| 1673 dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt")); | 1826 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( | 2611 file_util::VerifyPathControlledByUser( |
| 2459 base_dir_, text_file_, uid_, ok_gids_)); | 2612 base_dir_, text_file_, uid_, ok_gids_)); |
| 2460 EXPECT_TRUE( | 2613 EXPECT_TRUE( |
| 2461 file_util::VerifyPathControlledByUser( | 2614 file_util::VerifyPathControlledByUser( |
| 2462 sub_dir_, text_file_, uid_, ok_gids_)); | 2615 sub_dir_, text_file_, uid_, ok_gids_)); |
| 2463 } | 2616 } |
| 2464 | 2617 |
| 2465 #endif // defined(OS_POSIX) | 2618 #endif // defined(OS_POSIX) |
| 2466 | 2619 |
| 2467 } // namespace | 2620 } // namespace |
| OLD | NEW |