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 |