Index: base/file_util_unittest.cc |
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc |
index e523920431f6517d46a48ffacf4af9a1db93ba76..787b6d50ba7df6f1472a59371fee4070c13c9da4 100644 |
--- a/base/file_util_unittest.cc |
+++ b/base/file_util_unittest.cc |
@@ -30,6 +30,7 @@ |
#if defined(OS_WIN) |
#include "base/win/scoped_handle.h" |
+#include "base/win/windows_version.h" |
#endif |
// This macro helps avoid wrapped lines in the test structs. |
@@ -116,6 +117,36 @@ bool DeleteReparsePoint(HANDLE source) { |
} |
return true; |
} |
+ |
+// Manages a reparse point for a test. |
+class ReparsePoint { |
+ public: |
+ // Creates a reparse point from |source| (an empty directory) to |target|. |
+ ReparsePoint(const FilePath& source, const FilePath& target) { |
+ dir_.Set( |
+ ::CreateFile(source.value().c_str(), |
+ FILE_ALL_ACCESS, |
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
+ NULL, |
+ OPEN_EXISTING, |
+ FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. |
+ NULL)); |
+ created_ = dir_.IsValid() && SetReparsePoint(dir_, target); |
+ } |
+ |
+ ~ReparsePoint() { |
+ if (created_) |
+ DeleteReparsePoint(dir_); |
+ } |
+ |
+ bool IsValid() { return created_; } |
+ |
+ private: |
+ base::win::ScopedHandle dir_; |
+ bool created_; |
+ DISALLOW_COPY_AND_ASSIGN(ReparsePoint); |
+}; |
+ |
#endif |
#if defined(OS_POSIX) |
@@ -431,86 +462,61 @@ TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) { |
FilePath to_sub_a = base_b.Append(FPL("to_sub_a")); |
ASSERT_TRUE(file_util::CreateDirectory(to_sub_a)); |
- base::win::ScopedHandle reparse_to_sub_a( |
- ::CreateFile(to_sub_a.value().c_str(), |
- FILE_ALL_ACCESS, |
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
- NULL, |
- OPEN_EXISTING, |
- FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. |
- NULL)); |
- ASSERT_TRUE(reparse_to_sub_a.IsValid()); |
- ASSERT_TRUE(SetReparsePoint(reparse_to_sub_a, sub_a)); |
- |
- FilePath to_base_b = base_b.Append(FPL("to_base_b")); |
- ASSERT_TRUE(file_util::CreateDirectory(to_base_b)); |
- base::win::ScopedHandle reparse_to_base_b( |
- ::CreateFile(to_base_b.value().c_str(), |
- FILE_ALL_ACCESS, |
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
- NULL, |
- OPEN_EXISTING, |
- FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. |
- NULL)); |
- ASSERT_TRUE(reparse_to_base_b.IsValid()); |
- ASSERT_TRUE(SetReparsePoint(reparse_to_base_b, base_b)); |
- |
- FilePath to_sub_long = base_b.Append(FPL("to_sub_long")); |
- ASSERT_TRUE(file_util::CreateDirectory(to_sub_long)); |
- base::win::ScopedHandle reparse_to_sub_long( |
- ::CreateFile(to_sub_long.value().c_str(), |
- FILE_ALL_ACCESS, |
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
- NULL, |
- OPEN_EXISTING, |
- FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. |
- NULL)); |
- ASSERT_TRUE(reparse_to_sub_long.IsValid()); |
- ASSERT_TRUE(SetReparsePoint(reparse_to_sub_long, sub_long)); |
- |
- // Normalize a junction free path: base_a\sub_a\file.txt . |
FilePath normalized_path; |
- ASSERT_TRUE(file_util::NormalizeFilePath(file_txt, &normalized_path)); |
- ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str()); |
- |
- // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude |
- // the junction to_sub_a. |
- ASSERT_TRUE(file_util::NormalizeFilePath(to_sub_a.Append(FPL("file.txt")), |
- &normalized_path)); |
- ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str()); |
- |
- // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be |
- // normalized to exclude junctions to_base_b and to_sub_a . |
- ASSERT_TRUE(file_util::NormalizeFilePath(base_b.Append(FPL("to_base_b")) |
- .Append(FPL("to_base_b")) |
- .Append(FPL("to_sub_a")) |
- .Append(FPL("file.txt")), |
- &normalized_path)); |
- ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str()); |
- |
- // A long enough path will cause NormalizeFilePath() to fail. Make a long |
- // path using to_base_b many times, and check that paths long enough to fail |
- // do not cause a crash. |
- FilePath long_path = base_b; |
- const int kLengthLimit = MAX_PATH + 200; |
- while (long_path.value().length() <= kLengthLimit) { |
- long_path = long_path.Append(FPL("to_base_b")); |
- } |
- long_path = long_path.Append(FPL("to_sub_a")) |
- .Append(FPL("file.txt")); |
+ { |
+ ReparsePoint reparse_to_sub_a(to_sub_a, sub_a); |
+ ASSERT_TRUE(reparse_to_sub_a.IsValid()); |
+ |
+ FilePath to_base_b = base_b.Append(FPL("to_base_b")); |
+ ASSERT_TRUE(file_util::CreateDirectory(to_base_b)); |
+ ReparsePoint reparse_to_base_b(to_base_b, base_b); |
+ ASSERT_TRUE(reparse_to_base_b.IsValid()); |
+ |
+ FilePath to_sub_long = base_b.Append(FPL("to_sub_long")); |
+ ASSERT_TRUE(file_util::CreateDirectory(to_sub_long)); |
+ ReparsePoint reparse_to_sub_long(to_sub_long, sub_long); |
+ ASSERT_TRUE(reparse_to_sub_long.IsValid()); |
+ |
+ // Normalize a junction free path: base_a\sub_a\file.txt . |
+ ASSERT_TRUE(file_util::NormalizeFilePath(file_txt, &normalized_path)); |
+ ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str()); |
+ |
+ // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude |
+ // the junction to_sub_a. |
+ ASSERT_TRUE(file_util::NormalizeFilePath(to_sub_a.Append(FPL("file.txt")), |
+ &normalized_path)); |
+ ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str()); |
+ |
+ // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be |
+ // normalized to exclude junctions to_base_b and to_sub_a . |
+ ASSERT_TRUE(file_util::NormalizeFilePath(base_b.Append(FPL("to_base_b")) |
+ .Append(FPL("to_base_b")) |
+ .Append(FPL("to_sub_a")) |
+ .Append(FPL("file.txt")), |
+ &normalized_path)); |
+ ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str()); |
+ |
+ // A long enough path will cause NormalizeFilePath() to fail. Make a long |
+ // path using to_base_b many times, and check that paths long enough to fail |
+ // do not cause a crash. |
+ FilePath long_path = base_b; |
+ const int kLengthLimit = MAX_PATH + 200; |
+ while (long_path.value().length() <= kLengthLimit) { |
+ long_path = long_path.Append(FPL("to_base_b")); |
+ } |
+ long_path = long_path.Append(FPL("to_sub_a")) |
+ .Append(FPL("file.txt")); |
- ASSERT_FALSE(file_util::NormalizeFilePath(long_path, &normalized_path)); |
+ ASSERT_FALSE(file_util::NormalizeFilePath(long_path, &normalized_path)); |
- // Normalizing the junction to deep.txt should fail, because the expanded |
- // path to deep.txt is longer than MAX_PATH. |
- ASSERT_FALSE(file_util::NormalizeFilePath(to_sub_long.Append(deep_txt), |
- &normalized_path)); |
+ // Normalizing the junction to deep.txt should fail, because the expanded |
+ // path to deep.txt is longer than MAX_PATH. |
+ ASSERT_FALSE(file_util::NormalizeFilePath(to_sub_long.Append(deep_txt), |
+ &normalized_path)); |
- // Delete the reparse points, and see that NormalizeFilePath() fails |
- // to traverse them. |
- ASSERT_TRUE(DeleteReparsePoint(reparse_to_sub_a)); |
- ASSERT_TRUE(DeleteReparsePoint(reparse_to_base_b)); |
- ASSERT_TRUE(DeleteReparsePoint(reparse_to_sub_long)); |
+ // Delete the reparse points, and see that NormalizeFilePath() fails |
+ // to traverse them. |
+ } |
ASSERT_FALSE(file_util::NormalizeFilePath(to_sub_a.Append(FPL("file.txt")), |
&normalized_path)); |
@@ -1821,36 +1827,35 @@ TEST_F(FileUtilTest, DetectDirectoryTest) { |
TEST_F(FileUtilTest, FileEnumeratorTest) { |
// Test an empty directory. |
FileEnumerator f0(temp_dir_.path(), true, FILES_AND_DIRECTORIES); |
- EXPECT_EQ(f0.Next().value(), FILE_PATH_LITERAL("")); |
- EXPECT_EQ(f0.Next().value(), FILE_PATH_LITERAL("")); |
+ EXPECT_EQ(f0.Next().value(), FPL("")); |
+ EXPECT_EQ(f0.Next().value(), FPL("")); |
// Test an empty directory, non-recursively, including "..". |
FileEnumerator f0_dotdot(temp_dir_.path(), false, |
FILES_AND_DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT); |
- EXPECT_EQ(temp_dir_.path().Append(FILE_PATH_LITERAL("..")).value(), |
- f0_dotdot.Next().value()); |
- EXPECT_EQ(FILE_PATH_LITERAL(""), |
+ EXPECT_EQ(temp_dir_.path().Append(FPL("..")).value(), |
f0_dotdot.Next().value()); |
+ EXPECT_EQ(FPL(""), f0_dotdot.Next().value()); |
// create the directories |
- FilePath dir1 = temp_dir_.path().Append(FILE_PATH_LITERAL("dir1")); |
+ FilePath dir1 = temp_dir_.path().Append(FPL("dir1")); |
EXPECT_TRUE(file_util::CreateDirectory(dir1)); |
- FilePath dir2 = temp_dir_.path().Append(FILE_PATH_LITERAL("dir2")); |
+ FilePath dir2 = temp_dir_.path().Append(FPL("dir2")); |
EXPECT_TRUE(file_util::CreateDirectory(dir2)); |
- FilePath dir2inner = dir2.Append(FILE_PATH_LITERAL("inner")); |
+ FilePath dir2inner = dir2.Append(FPL("inner")); |
EXPECT_TRUE(file_util::CreateDirectory(dir2inner)); |
// create the files |
- FilePath dir2file = dir2.Append(FILE_PATH_LITERAL("dir2file.txt")); |
+ FilePath dir2file = dir2.Append(FPL("dir2file.txt")); |
CreateTextFile(dir2file, std::wstring()); |
- FilePath dir2innerfile = dir2inner.Append(FILE_PATH_LITERAL("innerfile.txt")); |
+ FilePath dir2innerfile = dir2inner.Append(FPL("innerfile.txt")); |
CreateTextFile(dir2innerfile, std::wstring()); |
- FilePath file1 = temp_dir_.path().Append(FILE_PATH_LITERAL("file1.txt")); |
+ FilePath file1 = temp_dir_.path().Append(FPL("file1.txt")); |
CreateTextFile(file1, std::wstring()); |
FilePath file2_rel = dir2.Append(FilePath::kParentDirectory) |
- .Append(FILE_PATH_LITERAL("file2.txt")); |
+ .Append(FPL("file2.txt")); |
CreateTextFile(file2_rel, std::wstring()); |
- FilePath file2_abs = temp_dir_.path().Append(FILE_PATH_LITERAL("file2.txt")); |
+ FilePath file2_abs = temp_dir_.path().Append(FPL("file2.txt")); |
// Only enumerate files. |
FileEnumerator f1(temp_dir_.path(), true, FileEnumerator::FILES); |
@@ -1884,8 +1889,7 @@ TEST_F(FileUtilTest, FileEnumeratorTest) { |
FindResultCollector c2_dotdot(f2_dotdot); |
EXPECT_TRUE(c2_dotdot.HasFile(dir1)); |
EXPECT_TRUE(c2_dotdot.HasFile(dir2)); |
- EXPECT_TRUE(c2_dotdot.HasFile( |
- temp_dir_.path().Append(FILE_PATH_LITERAL("..")))); |
+ EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.path().Append(FPL("..")))); |
EXPECT_EQ(c2_dotdot.size(), 3); |
// Enumerate files and directories. |
@@ -1910,8 +1914,7 @@ TEST_F(FileUtilTest, FileEnumeratorTest) { |
EXPECT_EQ(c4.size(), 4); |
// Enumerate with a pattern. |
- FileEnumerator f5(temp_dir_.path(), true, FILES_AND_DIRECTORIES, |
- FILE_PATH_LITERAL("dir*")); |
+ FileEnumerator f5(temp_dir_.path(), true, FILES_AND_DIRECTORIES, FPL("dir*")); |
FindResultCollector c5(f5); |
EXPECT_TRUE(c5.HasFile(dir1)); |
EXPECT_TRUE(c5.HasFile(dir2)); |
@@ -1920,10 +1923,52 @@ TEST_F(FileUtilTest, FileEnumeratorTest) { |
EXPECT_TRUE(c5.HasFile(dir2innerfile)); |
EXPECT_EQ(c5.size(), 5); |
+#if defined(OS_WIN) |
+ { |
+ // Make dir1 point to dir2. |
+ ReparsePoint reparse_point(dir1, dir2); |
+ EXPECT_TRUE(reparse_point.IsValid()); |
+ |
+ if ((base::win::GetVersion() >= base::win::VERSION_VISTA)) { |
+ // There can be a delay for the enumeration code to see the change on |
+ // the file system so skip this test for XP. |
+ // Enumerate the reparse point. |
+ FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES); |
+ FindResultCollector c6(f6); |
+ FilePath inner2 = dir1.Append(FPL("inner")); |
+ EXPECT_TRUE(c6.HasFile(inner2)); |
+ EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt")))); |
+ EXPECT_TRUE(c6.HasFile(dir1.Append(FPL("dir2file.txt")))); |
+ EXPECT_EQ(c6.size(), 3); |
+ } |
+ |
+ // No changes for non recursive operation. |
+ FileEnumerator f7(temp_dir_.path(), false, FILES_AND_DIRECTORIES); |
+ FindResultCollector c7(f7); |
+ EXPECT_TRUE(c7.HasFile(dir2)); |
+ EXPECT_TRUE(c7.HasFile(dir2)); |
+ EXPECT_TRUE(c7.HasFile(file1)); |
+ EXPECT_TRUE(c7.HasFile(file2_abs)); |
+ EXPECT_EQ(c7.size(), 4); |
+ |
+ // Should not enumerate inside dir1 when using recursion. |
+ FileEnumerator f8(temp_dir_.path(), true, FILES_AND_DIRECTORIES); |
+ FindResultCollector c8(f8); |
+ EXPECT_TRUE(c8.HasFile(dir1)); |
+ EXPECT_TRUE(c8.HasFile(dir2)); |
+ EXPECT_TRUE(c8.HasFile(file1)); |
+ EXPECT_TRUE(c8.HasFile(file2_abs)); |
+ EXPECT_TRUE(c8.HasFile(dir2file)); |
+ EXPECT_TRUE(c8.HasFile(dir2inner)); |
+ EXPECT_TRUE(c8.HasFile(dir2innerfile)); |
+ EXPECT_EQ(c8.size(), 7); |
+ } |
+#endif |
+ |
// Make sure the destructor closes the find handle while in the middle of a |
// query to allow TearDown to delete the directory. |
- FileEnumerator f6(temp_dir_.path(), true, FILES_AND_DIRECTORIES); |
- EXPECT_FALSE(f6.Next().value().empty()); // Should have found something |
+ FileEnumerator f9(temp_dir_.path(), true, FILES_AND_DIRECTORIES); |
+ EXPECT_FALSE(f9.Next().value().empty()); // Should have found something |
// (we don't care what). |
} |