diff options
author | Laszlo Csomor <laszlocsomor@google.com> | 2018-07-09 04:32:32 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-07-09 04:33:56 -0700 |
commit | c2b70f1e28b8fbc002efbac16d555f941c7d59a3 (patch) | |
tree | 79b2ab5eb0e1a7e4d971b94ba01e6415f7e6b5cd /src/test/native | |
parent | 4304542a7438acaeb09559e71a971e56fbecc4e5 (diff) |
Windows,JNI: more robust nativeCreateJunction
Rewrite the CreateJunction function in the Windows
JNI library.
The new implementation's improvements:
- succeeds if the junction already exists with the
desired target; hopefully this will fix issue
https://github.com/bazelbuild/bazel/issues/5433
- tolerant to concurrent filesystem modifications,
e.g. if the junction's path suddenly disappears,
the function reports the error correctly
Fixes https://github.com/bazelbuild/bazel/issues/5433
Change-Id: I58a2314a00f6edaa7c36c35ba54616168b44eb7d
Closes #5528.
Change-Id: I9f5dc9237b70a433d0d8c2578a826de3d462d110
PiperOrigin-RevId: 203744515
Diffstat (limited to 'src/test/native')
-rw-r--r-- | src/test/native/windows/file_test.cc | 114 |
1 files changed, 105 insertions, 9 deletions
diff --git a/src/test/native/windows/file_test.cc b/src/test/native/windows/file_test.cc index cfbb5d2f4a..4624fec39c 100644 --- a/src/test/native/windows/file_test.cc +++ b/src/test/native/windows/file_test.cc @@ -30,7 +30,8 @@ namespace bazel { namespace windows { -#define TOSTRING(x) #x +#define TOSTRING1(x) #x +#define TOSTRING(x) TOSTRING1(x) #define TOWSTRING1(x) L##x #define TOWSTRING(x) TOWSTRING1(x) #define WLINE TOWSTRING(TOSTRING(__LINE__)) @@ -61,10 +62,14 @@ TEST_F(WindowsFileOperationsTest, TestCreateJunction) { // Create junctions from all combinations of UNC-prefixed or non-prefixed name // and target paths. - ASSERT_EQ(L"", CreateJunction(name + L"1", target)); - ASSERT_EQ(L"", CreateJunction(name + L"2", target.substr(4))); - ASSERT_EQ(L"", CreateJunction(name.substr(4) + L"3", target)); - ASSERT_EQ(L"", CreateJunction(name.substr(4) + L"4", target.substr(4))); + ASSERT_EQ(CreateJunction(name + L"1", target, nullptr), + CreateJunctionResult::kSuccess); + ASSERT_EQ(CreateJunction(name + L"2", target.substr(4), nullptr), + CreateJunctionResult::kSuccess); + ASSERT_EQ(CreateJunction(name.substr(4) + L"3", target, nullptr), + CreateJunctionResult::kSuccess); + ASSERT_EQ(CreateJunction(name.substr(4) + L"4", target.substr(4), nullptr), + CreateJunctionResult::kSuccess); // Assert creation of the junctions. ASSERT_EQ(IS_JUNCTION_YES, @@ -113,6 +118,92 @@ TEST_F(WindowsFileOperationsTest, TestCreateJunction) { ::GetFileAttributesW((name + L"4\\bar").c_str())); } +TEST_F(WindowsFileOperationsTest, TestCanCreateNonDanglingJunction) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_TRUE(CreateDirectoryW(target.c_str(), NULL)); + ASSERT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); +} + +TEST_F(WindowsFileOperationsTest, TestCanCreateDanglingJunction) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + ASSERT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); +} + +TEST_F(WindowsFileOperationsTest, TestCreateJunctionChecksExistingJunction) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); + + ASSERT_EQ(CreateJunction(name, target + WLINE, nullptr), + CreateJunctionResult::kAlreadyExistsWithDifferentTarget); + ASSERT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); +} + +TEST_F(WindowsFileOperationsTest, TestCannotCreateJunctionFromEmptyDirectory) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_TRUE(CreateDirectoryW(name.c_str(), NULL)); + ASSERT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kAlreadyExistsButNotJunction); +} + +TEST_F(WindowsFileOperationsTest, + TestCannotCreateJunctionFromNonEmptyDirectory) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_TRUE(CreateDirectoryW(name.c_str(), NULL)); + EXPECT_TRUE(blaze_util::CreateDummyFile(name + L"\\hello.txt")); + ASSERT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kAlreadyExistsButNotJunction); +} + +TEST_F(WindowsFileOperationsTest, TestCannotCreateJunctionFromExistingFile) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_TRUE(blaze_util::CreateDummyFile(name)); + ASSERT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kAlreadyExistsButNotJunction); +} + +TEST_F(WindowsFileOperationsTest, TestCannotCreateJunctionIfNameIsBusy) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_TRUE(CreateDirectoryW(name.c_str(), NULL)); + HANDLE h = CreateFileW( + name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + EXPECT_NE(h, INVALID_HANDLE_VALUE); + int actual = CreateJunction(name, target, nullptr); + CloseHandle(h); + ASSERT_EQ(actual, CreateJunctionResult::kAccessDenied); +} + +TEST_F(WindowsFileOperationsTest, TestCanCreateJunctionIfTargetIsBusy) { + wstring tmp(kUncPrefix + GetTestTmpDirW()); + wstring name = tmp + L"\\junc" WLINE; + wstring target = tmp + L"\\target" WLINE; + EXPECT_TRUE(CreateDirectoryW(target.c_str(), NULL)); + HANDLE h = CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + EXPECT_NE(h, INVALID_HANDLE_VALUE); + int actual = CreateJunction(name, target, nullptr); + CloseHandle(h); + ASSERT_EQ(actual, CreateJunctionResult::kSuccess); +} + TEST_F(WindowsFileOperationsTest, TestCanDeleteExistingFile) { wstring tmp(kUncPrefix + GetTestTmpDirW()); wstring path = tmp + L"\\file" WLINE; @@ -132,7 +223,8 @@ TEST_F(WindowsFileOperationsTest, TestCanDeleteExistingJunction) { wstring name = tmp + L"\\junc" WLINE; wstring target = tmp + L"\\target" WLINE; EXPECT_TRUE(CreateDirectoryW(target.c_str(), NULL)); - EXPECT_EQ(L"", CreateJunction(name, target)); + EXPECT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); ASSERT_EQ(DeletePath(name.c_str(), nullptr), DELETE_PATH_SUCCESS); } @@ -141,7 +233,8 @@ TEST_F(WindowsFileOperationsTest, TestCanDeleteExistingJunctionWithoutTarget) { wstring name = tmp + L"\\junc" WLINE; wstring target = tmp + L"\\target" WLINE; EXPECT_TRUE(CreateDirectoryW(target.c_str(), NULL)); - EXPECT_EQ(L"", CreateJunction(name, target)); + EXPECT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); EXPECT_TRUE(RemoveDirectoryW(target.c_str())); // The junction still exists, its target does not. EXPECT_NE(GetFileAttributesW(name.c_str()), INVALID_FILE_ATTRIBUTES); @@ -204,7 +297,8 @@ TEST_F(WindowsFileOperationsTest, TestCannotDeleteBusyJunction) { wstring name = tmp + L"\\junc" WLINE; wstring target = tmp + L"\\target" WLINE; EXPECT_TRUE(CreateDirectoryW(target.c_str(), NULL)); - EXPECT_EQ(L"", CreateJunction(name, target)); + EXPECT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); // Open the junction itself (do not follow symlinks). HANDLE h = CreateFileW( name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, @@ -220,7 +314,8 @@ TEST_F(WindowsFileOperationsTest, TestCanDeleteJunctionWhoseTargetIsBusy) { wstring name = tmp + L"\\junc" WLINE; wstring target = tmp + L"\\target" WLINE; EXPECT_TRUE(CreateDirectoryW(target.c_str(), NULL)); - EXPECT_EQ(L"", CreateJunction(name, target)); + EXPECT_EQ(CreateJunction(name, target, nullptr), + CreateJunctionResult::kSuccess); // Open the junction's target (follow symlinks). HANDLE h = CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); @@ -230,6 +325,7 @@ TEST_F(WindowsFileOperationsTest, TestCanDeleteJunctionWhoseTargetIsBusy) { ASSERT_EQ(actual, DELETE_PATH_SUCCESS); } +#undef TOSTRING1 #undef TOSTRING #undef TOWSTRING1 #undef TOWSTRING |