| OLD | NEW |
| 1 // Copyright (c) 2011 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 <shellapi.h> | 9 #include <shellapi.h> |
| 10 #include <shlobj.h> | 10 #include <shlobj.h> |
| 11 #include <tchar.h> | 11 #include <tchar.h> |
| 12 #include <winioctl.h> | 12 #include <winioctl.h> |
| 13 #endif | 13 #endif |
| 14 | 14 |
| 15 #include <algorithm> | 15 #include <algorithm> |
| 16 #include <fstream> | 16 #include <fstream> |
| 17 #include <set> | 17 #include <set> |
| 18 | 18 |
| 19 #include "base/base_paths.h" | 19 #include "base/base_paths.h" |
| 20 #include "base/file_path.h" | 20 #include "base/file_path.h" |
| 21 #include "base/file_util.h" | 21 #include "base/file_util.h" |
| 22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
| 23 #include "base/scoped_temp_dir.h" | 23 #include "base/scoped_temp_dir.h" |
| 24 #include "base/threading/platform_thread.h" | 24 #include "base/threading/platform_thread.h" |
| 25 #include "base/utf_string_conversions.h" | 25 #include "base/utf_string_conversions.h" |
| 26 #include "testing/gmock/include/gmock/gmock.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 27 #include "testing/platform_test.h" | 28 #include "testing/platform_test.h" |
| 28 | 29 |
| 29 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
| 30 #include "base/win/scoped_handle.h" | 31 #include "base/win/scoped_handle.h" |
| 32 #include "base/win/win_api_interface.h" |
| 31 #endif | 33 #endif |
| 32 | 34 |
| 33 // This macro helps avoid wrapped lines in the test structs. | 35 // This macro helps avoid wrapped lines in the test structs. |
| 34 #define FPL(x) FILE_PATH_LITERAL(x) | 36 #define FPL(x) FILE_PATH_LITERAL(x) |
| 35 | 37 |
| 38 using ::testing::_; |
| 39 using ::testing::DoAll; |
| 40 using ::testing::Invoke; |
| 41 using ::testing::Return; |
| 42 using ::testing::SetArrayArgument; |
| 43 using ::testing::StrictMock; |
| 44 |
| 36 namespace { | 45 namespace { |
| 37 | 46 |
| 38 // To test that file_util::Normalize FilePath() deals with NTFS reparse points | 47 // To test that file_util::Normalize FilePath() deals with NTFS reparse points |
| 39 // correctly, we need functions to create and delete reparse points. | 48 // correctly, we need functions to create and delete reparse points. |
| 40 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
| 41 typedef struct _REPARSE_DATA_BUFFER { | 50 typedef struct _REPARSE_DATA_BUFFER { |
| 42 ULONG ReparseTag; | 51 ULONG ReparseTag; |
| 43 USHORT ReparseDataLength; | 52 USHORT ReparseDataLength; |
| 44 USHORT Reserved; | 53 USHORT Reserved; |
| 45 union { | 54 union { |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. | 601 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. |
| 593 NULL)); | 602 NULL)); |
| 594 ASSERT_TRUE(dir.IsValid()); | 603 ASSERT_TRUE(dir.IsValid()); |
| 595 base::PlatformFileInfo info; | 604 base::PlatformFileInfo info; |
| 596 EXPECT_TRUE(base::GetPlatformFileInfo(dir.Get(), &info)); | 605 EXPECT_TRUE(base::GetPlatformFileInfo(dir.Get(), &info)); |
| 597 EXPECT_TRUE(info.is_directory); | 606 EXPECT_TRUE(info.is_directory); |
| 598 EXPECT_FALSE(info.is_symbolic_link); | 607 EXPECT_FALSE(info.is_symbolic_link); |
| 599 EXPECT_EQ(0, info.size); | 608 EXPECT_EQ(0, info.size); |
| 600 } | 609 } |
| 601 | 610 |
| 611 namespace { |
| 612 |
| 613 #if defined(OS_WIN) |
| 614 class MockWindowsApi : public base::win::WinApiInterface { |
| 615 public: |
| 616 MOCK_METHOD3(QueryDosDevice, DWORD (LPCTSTR lpDeviceName, |
| 617 LPTSTR lpTargetPath, |
| 618 DWORD ucchMax)); |
| 619 MOCK_METHOD2(GetLogicalDriveStrings, DWORD (DWORD nBufferLength, |
| 620 LPTSTR lpBuffer)); |
| 621 }; |
| 622 #endif // defined(OS_WIN) |
| 623 |
| 624 } // namespace |
| 625 |
| 626 TEST_F(FileUtilTest, DevicePathToDriveLetter) { |
| 627 FilePath drive_letter_path; |
| 628 const FilePath kDevicePath(FPL("\\Device\\HardDiskVolume12\\foo\\bar")); |
| 629 |
| 630 const TCHAR kEmptyDriveMapping[] = _TEXT("\0\0"); |
| 631 const int kEmptyDriveMappingLength = arraysize(kEmptyDriveMapping); |
| 632 const TCHAR kSampleDriveMapping[] = _TEXT("G:\\\0H:\\\0I:\\\0\0"); |
| 633 const int kSampleDriveMappingLength = arraysize(kSampleDriveMapping); |
| 634 |
| 635 const TCHAR kDeviceNoMatch[] = _TEXT("\\Device\\no_match"); |
| 636 const int kDeviceNoMatchLength = arraysize(kDeviceNoMatch); |
| 637 |
| 638 const TCHAR kDeviceSubstring[] = _TEXT("\\Device\\HardDiskVolume1"); |
| 639 const int kDeviceSubstringLength = arraysize(kDeviceSubstring); |
| 640 |
| 641 const TCHAR kDeviceShouldMatch[] = _TEXT("\\Device\\HardDiskVolume12"); |
| 642 const int kDeviceShouldMatchLength = arraysize(kDeviceShouldMatch); |
| 643 |
| 644 { |
| 645 // Fake failure of GetLogicalDriveStrings(). |
| 646 StrictMock<MockWindowsApi> mock_win_api; |
| 647 EXPECT_CALL(mock_win_api, GetLogicalDriveStrings(_, _)).WillOnce(DoAll( |
| 648 SetArrayArgument<1>(kEmptyDriveMapping, |
| 649 kEmptyDriveMapping + kEmptyDriveMappingLength), |
| 650 Return(0))); |
| 651 |
| 652 ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(mock_win_api, |
| 653 kDevicePath, |
| 654 &drive_letter_path)); |
| 655 } |
| 656 { |
| 657 // Fake an empty set of mapped drives. |
| 658 StrictMock<MockWindowsApi> mock_win_api; |
| 659 EXPECT_CALL(mock_win_api, GetLogicalDriveStrings(_, _)).WillOnce(DoAll( |
| 660 SetArrayArgument<1>(kEmptyDriveMapping, |
| 661 kEmptyDriveMapping + kEmptyDriveMappingLength), |
| 662 Return(1))); |
| 663 |
| 664 ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(mock_win_api, |
| 665 kDevicePath, |
| 666 &drive_letter_path)); |
| 667 } |
| 668 { |
| 669 // QueryDosDevice always fails. |
| 670 StrictMock<MockWindowsApi> mock_win_api; |
| 671 EXPECT_CALL(mock_win_api, GetLogicalDriveStrings(_, _)).WillOnce(DoAll( |
| 672 SetArrayArgument<1>(kSampleDriveMapping, |
| 673 kSampleDriveMapping + kSampleDriveMappingLength), |
| 674 Return(1))); |
| 675 |
| 676 EXPECT_CALL(mock_win_api, QueryDosDevice(_, _, _)).Times(3) |
| 677 .WillRepeatedly(Return(0)); |
| 678 |
| 679 ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(mock_win_api, |
| 680 kDevicePath, |
| 681 &drive_letter_path)); |
| 682 } |
| 683 { |
| 684 // QueryDosDevice succeeds, but no DOS device matches the NT path. |
| 685 StrictMock<MockWindowsApi> mock_win_api; |
| 686 |
| 687 EXPECT_CALL(mock_win_api, GetLogicalDriveStrings(_, _)).WillOnce(DoAll( |
| 688 SetArrayArgument<1>(kSampleDriveMapping, |
| 689 kSampleDriveMapping + kSampleDriveMappingLength), |
| 690 Return(1))); |
| 691 |
| 692 EXPECT_CALL(mock_win_api, QueryDosDevice(_, _, _)).Times(3) |
| 693 .WillRepeatedly(DoAll( |
| 694 SetArrayArgument<1>(kDeviceNoMatch, |
| 695 kDeviceNoMatch + kDeviceNoMatchLength), |
| 696 Return(1))); |
| 697 |
| 698 ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(mock_win_api, |
| 699 kDevicePath, |
| 700 &drive_letter_path)); |
| 701 } |
| 702 { |
| 703 // QueryDosDevice matches the third item in the list of devices. |
| 704 StrictMock<MockWindowsApi> mock_win_api; |
| 705 |
| 706 EXPECT_CALL(mock_win_api, GetLogicalDriveStrings(_, _)).WillOnce(DoAll( |
| 707 SetArrayArgument<1>(kSampleDriveMapping, |
| 708 kSampleDriveMapping + kSampleDriveMappingLength), |
| 709 Return(1))); |
| 710 |
| 711 EXPECT_CALL(mock_win_api, QueryDosDevice(_, _, _)).Times(3) |
| 712 // First drive letter does not match. |
| 713 .WillOnce(DoAll( |
| 714 SetArrayArgument<1>(kDeviceNoMatch, |
| 715 kDeviceNoMatch + kDeviceNoMatchLength), |
| 716 Return(1))) |
| 717 // Second drive letter has a path that is a substring of the correct |
| 718 // path. Should not match. |
| 719 .WillOnce(DoAll( |
| 720 SetArrayArgument<1>(kDeviceSubstring, |
| 721 kDeviceSubstring + kDeviceSubstringLength), |
| 722 Return(1))) |
| 723 // Third drive letter matches. Should return this one. |
| 724 .WillOnce(DoAll( |
| 725 SetArrayArgument<1>(kDeviceShouldMatch, |
| 726 kDeviceShouldMatch + kDeviceShouldMatchLength), |
| 727 Return(1))); |
| 728 |
| 729 ASSERT_TRUE(file_util::DevicePathToDriveLetterPath(mock_win_api, |
| 730 kDevicePath, |
| 731 &drive_letter_path)); |
| 732 ASSERT_EQ(FPL("I:\\foo\\bar"), drive_letter_path.value()); |
| 733 } |
| 734 { |
| 735 // Match a path to a drive letter, with no extra path. |
| 736 StrictMock<MockWindowsApi> mock_win_api; |
| 737 |
| 738 EXPECT_CALL(mock_win_api, GetLogicalDriveStrings(_, _)).WillOnce(DoAll( |
| 739 SetArrayArgument<1>(kSampleDriveMapping, |
| 740 kSampleDriveMapping + kSampleDriveMappingLength), |
| 741 Return(1))); |
| 742 |
| 743 EXPECT_CALL(mock_win_api, QueryDosDevice(_, _, _)).Times(2) |
| 744 // First call to QueryDosDevice fails. Shoudl keep going. |
| 745 .WillOnce(Return(0)) |
| 746 |
| 747 // Next call matches a drive letter. Should return this one. |
| 748 .WillOnce(DoAll( |
| 749 SetArrayArgument<1>(kDeviceShouldMatch, |
| 750 kDeviceShouldMatch + kDeviceShouldMatchLength), |
| 751 Return(1))); |
| 752 // After matching, QueryDosDevice should not be called again. |
| 753 |
| 754 const FilePath kNtPathToDriveI(FPL("\\Device\\HardDiskVolume12")); |
| 755 ASSERT_TRUE(file_util::DevicePathToDriveLetterPath(mock_win_api, |
| 756 kNtPathToDriveI, |
| 757 &drive_letter_path)); |
| 758 ASSERT_EQ(FPL("H:"), drive_letter_path.value()); |
| 759 } |
| 760 } |
| 761 |
| 602 #endif // defined(OS_WIN) | 762 #endif // defined(OS_WIN) |
| 603 | 763 |
| 604 #if defined(OS_POSIX) | 764 #if defined(OS_POSIX) |
| 605 | 765 |
| 606 TEST_F(FileUtilTest, CreateAndReadSymlinks) { | 766 TEST_F(FileUtilTest, CreateAndReadSymlinks) { |
| 607 FilePath link_from = temp_dir_.path().Append(FPL("from_file")); | 767 FilePath link_from = temp_dir_.path().Append(FPL("from_file")); |
| 608 FilePath link_to = temp_dir_.path().Append(FPL("to_file")); | 768 FilePath link_to = temp_dir_.path().Append(FPL("to_file")); |
| 609 CreateTextFile(link_to, bogus_content); | 769 CreateTextFile(link_to, bogus_content); |
| 610 | 770 |
| 611 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from)) | 771 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from)) |
| (...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2216 file_util::VerifyPathControlledByUser( | 2376 file_util::VerifyPathControlledByUser( |
| 2217 base_dir_, text_file_, uid_, ok_gids_)); | 2377 base_dir_, text_file_, uid_, ok_gids_)); |
| 2218 EXPECT_TRUE( | 2378 EXPECT_TRUE( |
| 2219 file_util::VerifyPathControlledByUser( | 2379 file_util::VerifyPathControlledByUser( |
| 2220 sub_dir_, text_file_, uid_, ok_gids_)); | 2380 sub_dir_, text_file_, uid_, ok_gids_)); |
| 2221 } | 2381 } |
| 2222 | 2382 |
| 2223 #endif // defined(OS_POSIX) | 2383 #endif // defined(OS_POSIX) |
| 2224 | 2384 |
| 2225 } // namespace | 2385 } // namespace |
| OLD | NEW |