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 |