diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTree.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTree.java
index c610492bd69..5881c153842 100644
--- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTree.java
+++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTree.java
@@ -438,9 +438,6 @@ private static class PatternHolder {
//Pattern: A UNIX or Windows relative path that just points backward
static final Pattern TRIVIAL_SYMLINK_PATTERN = Pattern.compile( //
Platform.OS.isWindows() ? "\\.[.\\\\]*" : "\\.[./]*"); //$NON-NLS-1$//$NON-NLS-2$
-
- static final Pattern REPEATING_BACKWARDS_PATTERN = Pattern.compile( //
- Platform.OS.isWindows() ? "(\\.\\.\\\\)+.*" : "(\\.\\./)+.*"); //$NON-NLS-1$//$NON-NLS-2$
}
/**
@@ -522,20 +519,10 @@ private boolean isRecursiveLink(IFileStore parentStore, IFileInfo localInfo) {
Path realParentPath = parent.toRealPath();
if (disable_advanced_recursive_link_checks) {
// Multiple ../ backwards links can go outside the project tree
- if (linkTarget != null && PatternHolder.REPEATING_BACKWARDS_PATTERN.matcher(linkTarget).matches()) {
- Path targetPath = parent.resolve(linkTarget).normalize();
-
- // Recursive if literal target points to the literal parent of this tree
- if (parent.normalize().startsWith(targetPath)) {
+ if (linkTarget != null) {
+ if (isRecursiveBackwardsLink(realParentPath, linkTarget)) {
return true;
}
-
- // Recursive if resolved target points to the resolved parent of this tree
- Path realTargetPath = targetPath.toRealPath();
- if (realParentPath.startsWith(realTargetPath)) {
- return true;
- }
-
// If link is outside the project tree, consider as non recursive
// The link still can create recursion in the tree, but we can't detect it here.
}
@@ -573,6 +560,51 @@ private boolean isRecursiveLink(IFileStore parentStore, IFileInfo localInfo) {
return false;
}
+ /**
+ * @param realParentPath real parent path object obtained as a result
+ * of @code{Path.toRealPath()}
+ * @param linkTarget the link target path as a string, may be relative or
+ * absolute
+ * @return true if the given target points backwards recursively to the given
+ * parent path
+ * @throws IOException
+ */
+ private static boolean isRecursiveBackwardsLink(Path realParentPath, String linkTarget)
+ throws IOException {
+ // Cheap test first: literal target points to the literal parent
+ Path normalizedLink = realParentPath.resolve(linkTarget).normalize();
+ if (realParentPath.startsWith(normalizedLink)) {
+ return true;
+ }
+ // Next check costs more time because it does real IO when resolving paths
+ Path realTarget = normalizedLink.toRealPath();
+ if (realParentPath.startsWith(realTarget)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Disable or enable advanced recursive link checks. Advanced link checks may
+ * hide valid directories in some cases, see bug 537449.
+ *
+ * @param enable true to enable advanced recursive link checks,
+ * false to disable them.
+ */
+ public static void enableAdvancedRecursiveLinkChecks(boolean enable) {
+ disable_advanced_recursive_link_checks = !enable;
+ }
+
+ /**
+ * Returns whether advanced recursive link checks are enabled.
+ *
+ * @return true if advanced recursive link checks are enabled,
+ * false otherwise.
+ */
+ public static boolean isAdvancedRecursiveLinkChecksEnabled() {
+ return !disable_advanced_recursive_link_checks;
+ }
+
protected boolean isValidLevel(int currentLevel, int depth) {
return switch (depth) {
case IResource.DEPTH_INFINITE -> true;
diff --git a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/SymlinkResourceTest.java b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/SymlinkResourceTest.java
index 7f7310fb29f..d121db58b7a 100644
--- a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/SymlinkResourceTest.java
+++ b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/SymlinkResourceTest.java
@@ -21,28 +21,33 @@
import static org.eclipse.core.tests.resources.ResourceTestUtil.createInWorkspace;
import static org.eclipse.core.tests.resources.ResourceTestUtil.createTestMonitor;
import static org.eclipse.core.tests.resources.ResourceTestUtil.waitForRefresh;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.internal.localstore.UnifiedTree;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.tests.resources.WorkspaceTestRule;
-import org.junit.Rule;
-import org.junit.Test;
-
+import org.eclipse.core.runtime.Platform.OS;
+import org.eclipse.core.tests.resources.util.WorkspaceResetExtension;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+@ExtendWith(WorkspaceResetExtension.class)
public class SymlinkResourceTest {
- @Rule
- public WorkspaceTestRule workspaceRule = new WorkspaceTestRule();
-
private void mkLink(IFileStore dir, String src, String tgt, boolean isDir) throws CoreException, IOException {
createSymLink(dir.toLocalFile(EFS.NONE, createTestMonitor()), src, tgt, isDir);
}
@@ -70,6 +75,88 @@ protected void createBug358830Structure(IFileStore rootDir) throws CoreException
mkLink(folderA, "link", IPath.fromOSString("../").toOSString(), true);
}
+ /**
+ * Test a case of both recursive and non recursive symbolic links that uncovered
+ * issue described in GitHub bug
+ * 2220.
+ *
+ *
{@code
+ * /A/B -> /X/Y/Z (B is symbolic link as precondition)
+ * /A/B/C/D -> ../../D (non-recursive)
+ * /A/B/C/E -> ../../Z (recursive)
+ * }
+ *
+ * The starting path /A/B/C is already based on link. The real path of start is
+ * /X/Y/Z/C so ../../Z points (recursive) to /X/Y/Z. /X/Y/D and /X/Y/Z is what
+ * we expect to resolve but we fail in both cases with NoSuchFileException.
+ */
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void testGithubBug2220(boolean useAdvancedLinkCheck) throws Exception {
+ assumeTrue(canCreateSymLinks(), "only relevant for platforms supporting symbolic links");
+ assumeTrue(!OS.isWindows(), "Windows file system handles recursive links differently");
+ final boolean originalValue = UnifiedTree.isAdvancedRecursiveLinkChecksEnabled();
+ try {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(useAdvancedLinkCheck);
+ IProject project = getWorkspace().getRoot().getProject("testGithubBug2220");
+ createInWorkspace(project);
+
+ /* Re-use projects which are cleaned up automatically */
+ getWorkspace().run((IWorkspaceRunnable) monitor -> {
+ /* delete open project because we must re-open with BACKGROUND_REFRESH */
+ project.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, createTestMonitor());
+ project.create(null);
+ try {
+ createGithubBug2220Structure(EFS.getStore(project.getLocationURI()));
+ } catch (IOException e) {
+ throw new IllegalStateException("unexpected IOException occurred", e);
+ }
+ // Bug only happens with BACKGROUND_REFRESH.
+ project.open(IResource.BACKGROUND_REFRESH, createTestMonitor());
+ }, null);
+
+ // wait for BACKGROUND_REFRESH to complete.
+ waitForRefresh();
+ project.accept(new IResourceVisitor() {
+ int resourceCount = 0;
+
+ @Override
+ public boolean visit(IResource resource) {
+ resourceCount++;
+ // We have 1 root + .settings + prefs + + .project + 10 elements --> 14 elements
+ // to visit at most
+ System.out.println(resourceCount + " visited: " + resource.getFullPath());
+ assertTrue(resourceCount <= 15, "Expected max 15 elements to visit, got: " + resourceCount);
+ return true;
+ }
+ });
+ } finally {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(originalValue);
+ }
+ }
+
+ /**
+ * {@code
+ * /A/B -> /X/Y/Z (B is symbolic link as precondition)
+ * /A/B/C/D -> ../../D (non-recursive)
+ * /A/B/C/E -> ../../Z (recursive)
+ * }
+ *
+ * The starting path /A/B/C is already based on link. The real path of start is
+ * /X/Y/Z/C so ../../Z points (recursive) to /X/Y/Z.
+ */
+ protected void createGithubBug2220Structure(IFileStore rootDir) throws CoreException, IOException {
+ Path root = rootDir.toLocalFile(EFS.NONE, createTestMonitor()).toPath();
+ Files.createDirectories(root.resolve("A"));
+ Files.createDirectories(root.resolve("X/Y/Z"));
+ Files.createDirectories(root.resolve("X/Y/D"));
+ Files.createSymbolicLink(root.resolve("A/B"), root.resolve("X/Y/Z"));
+ Files.createDirectories(root.resolve("A/B/C"));
+ Files.createSymbolicLink(root.resolve("A/B/C/D"), Paths.get("../../D"));
+ Files.createSymbolicLink(root.resolve("A/B/C/E"), Paths.get("../../Z"));
+ }
+
/**
* Test a very specific case of mutually recursive symbolic links:
* {@code
@@ -85,7 +172,7 @@ protected void createBug358830Structure(IFileStore rootDir) throws CoreException
*/
@Test
public void testBug232426() throws Exception {
- assumeTrue("only relevant for platforms supporting symbolic links", canCreateSymLinks());
+ assumeTrue(canCreateSymLinks(), "only relevant for platforms supporting symbolic links");
IProject project = getWorkspace().getRoot().getProject("Project");
createInWorkspace(project);
@@ -118,36 +205,42 @@ public boolean visit(IResource resource) {
});
}
- @Test
- public void testBug358830() throws Exception {
- assumeTrue("only relevant for platforms supporting symbolic links", canCreateSymLinks());
-
- IProject project = getWorkspace().getRoot().getProject("Project");
- createInWorkspace(project);
- /* Re-use projects which are cleaned up automatically */
- getWorkspace().run((IWorkspaceRunnable) monitor -> {
- /* delete open project because we must re-open with BACKGROUND_REFRESH */
- project.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, createTestMonitor());
- project.create(null);
- try {
- createBug358830Structure(EFS.getStore(project.getLocationURI()));
- } catch (IOException e) {
- throw new IllegalStateException("unexpected IOException occurred", e);
- }
- project.open(IResource.BACKGROUND_REFRESH, createTestMonitor());
- }, null);
-
- //wait for BACKGROUND_REFRESH to complete.
- waitForRefresh();
- final int resourceCount[] = new int[] {0};
- project.accept(resource -> {
- resourceCount[0]++;
- return true;
- });
- // We have 1 root + 1 folder + 1 file (.project)
- // + .settings / resources prefs
- // --> 5 elements to visit
- assertEquals(5, resourceCount[0]);
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void testBug358830(boolean useAdvancedLinkCheck) throws Exception {
+ assumeTrue(canCreateSymLinks(), "only relevant for platforms supporting symbolic links");
+ final boolean originalValue = UnifiedTree.isAdvancedRecursiveLinkChecksEnabled();
+ try {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(useAdvancedLinkCheck);
+ IProject project = getWorkspace().getRoot().getProject("Project");
+ createInWorkspace(project);
+ /* Re-use projects which are cleaned up automatically */
+ getWorkspace().run((IWorkspaceRunnable) monitor -> {
+ /* delete open project because we must re-open with BACKGROUND_REFRESH */
+ project.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, createTestMonitor());
+ project.create(null);
+ try {
+ createBug358830Structure(EFS.getStore(project.getLocationURI()));
+ } catch (IOException e) {
+ throw new IllegalStateException("unexpected IOException occurred", e);
+ }
+ project.open(IResource.BACKGROUND_REFRESH, createTestMonitor());
+ }, null);
+
+ // wait for BACKGROUND_REFRESH to complete.
+ waitForRefresh();
+ final int resourceCount[] = new int[] { 0 };
+ project.accept(resource -> {
+ resourceCount[0]++;
+ return true;
+ });
+ // We have 1 root + 1 folder + 1 file (.project)
+ // + .settings / resources prefs
+ // --> 5 elements to visit
+ assertEquals(5, resourceCount[0]);
+ } finally {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(originalValue);
+ }
}
}
diff --git a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_LinuxTests.java b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_LinuxTests.java
index 274fe6913c9..c4dce863533 100644
--- a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_LinuxTests.java
+++ b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_LinuxTests.java
@@ -11,10 +11,10 @@
package org.eclipse.core.tests.resources.regression;
import static org.eclipse.core.tests.resources.ResourceTestUtil.createTestMonitor;
-import static org.junit.Assume.assumeTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.io.File;
import java.io.IOException;
@@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.eclipse.core.internal.localstore.UnifiedTree;
import org.eclipse.core.internal.resources.ProjectDescription;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
@@ -38,10 +39,11 @@
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.core.tests.resources.util.WorkspaceResetExtension;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
/**
* Test cases for symbolic links in projects.
@@ -56,7 +58,7 @@ public class Bug_185247_LinuxTests {
@BeforeEach
public void setUp(TestInfo testInfo) throws Exception {
- assumeTrue("only relevant on Linux", OS.isLinux());
+ assumeTrue(OS.isLinux(), "only relevant on Linux");
testMethodName = testInfo.getTestMethod().get().getName();
IPath randomLocation = IPath.fromPath(tempDirectory);
@@ -74,34 +76,45 @@ private void extractTestCasesArchive(IPath outputLocation) throws Exception {
unzip(archive, outputLocation.toFile());
}
- @Test
- public void test1_trivial() throws Exception {
- runProjectTestCase();
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test1_trivial(boolean useAdvancedLinkCheck) throws Exception {
+ runProjectTestCase(useAdvancedLinkCheck);
}
- @Test
- public void test2_mutual() throws Exception {
- runProjectTestCase();
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test2_mutual(boolean useAdvancedLinkCheck) throws Exception {
+ runProjectTestCase(useAdvancedLinkCheck);
}
- @Test
- public void test3_outside_tree() throws Exception {
- runProjectTestCase();
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test3_outside_tree(boolean useAdvancedLinkCheck) throws Exception {
+ runProjectTestCase(useAdvancedLinkCheck);
}
- @Test
- public void test5_transitive_mutual() throws Exception {
- runProjectTestCase();
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test5_transitive_mutual(boolean useAdvancedLinkCheck) throws Exception {
+ runProjectTestCase(useAdvancedLinkCheck);
}
- @Test
- public void test6_nonrecursive() throws Exception {
- runProjectTestCase();
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test6_nonrecursive(boolean useAdvancedLinkCheck) throws Exception {
+ runProjectTestCase(useAdvancedLinkCheck);
}
- private void runProjectTestCase() throws Exception {
- // refresh should hang, if bug 105554 re-occurs
- importProjectAndRefresh(testMethodName);
+ private void runProjectTestCase(boolean useAdvancedLinkCheck) throws Exception {
+ final boolean originalValue = UnifiedTree.isAdvancedRecursiveLinkChecksEnabled();
+ try {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(useAdvancedLinkCheck);
+ // refresh should hang, if bug 105554 re-occurs
+ importProjectAndRefresh(testMethodName);
+ } finally {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(originalValue);
+ }
}
private void importProjectAndRefresh(String projectName) throws Exception {
diff --git a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_recursiveLinks.java b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_recursiveLinks.java
index 34487877e93..3875bb952b1 100644
--- a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_recursiveLinks.java
+++ b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/Bug_185247_recursiveLinks.java
@@ -13,8 +13,8 @@
import static org.eclipse.core.tests.harness.FileSystemHelper.canCreateSymLinks;
import static org.eclipse.core.tests.harness.FileSystemHelper.createSymLink;
import static org.eclipse.core.tests.resources.ResourceTestUtil.createTestMonitor;
-import static org.junit.Assume.assumeTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.io.File;
import java.io.IOException;
@@ -22,6 +22,7 @@
import java.net.URI;
import java.nio.file.Path;
import org.eclipse.core.filesystem.URIUtil;
+import org.eclipse.core.internal.localstore.UnifiedTree;
import org.eclipse.core.internal.resources.ProjectDescription;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
@@ -30,10 +31,11 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.tests.resources.util.WorkspaceResetExtension;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
/**
* Tests for recursive symbolic links in projects.
@@ -47,7 +49,7 @@ public class Bug_185247_recursiveLinks {
@BeforeEach
public void requireCanCreateSymlinks(TestInfo testInfo) throws IOException {
- assumeTrue("only relevant for platforms supporting symbolic links", canCreateSymLinks());
+ assumeTrue(canCreateSymLinks(), "only relevant for platforms supporting symbolic links");
testMethodName = testInfo.getTestMethod().get().getName();
}
@@ -62,13 +64,14 @@ public void requireCanCreateSymlinks(TestInfo testInfo) throws IOException {
* |-- link_current -> ./ (links "directory")
*
*/
- @Test
- public void test1_linkCurrentDirectory() throws Exception {
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test1_linkCurrentDirectory(boolean useAdvancedLinkCheck) throws Exception {
CreateTestProjectStructure createSymlinks = directory -> {
createSymlink(directory, "link_current", "./");
};
- runTest(createSymlinks);
+ runTest(createSymlinks, useAdvancedLinkCheck);
}
/**
@@ -82,13 +85,14 @@ public void test1_linkCurrentDirectory() throws Exception {
* |-- link_parent -> ../ (links "project root")
*
*/
- @Test
- public void test2_linkParentDirectory() throws Exception {
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test2_linkParentDirectory(boolean useAdvancedLinkCheck) throws Exception {
CreateTestProjectStructure createSymlinks = directory -> {
createSymlink(directory, "link_parent", "../");
};
- runTest(createSymlinks);
+ runTest(createSymlinks, useAdvancedLinkCheck);
}
/**
@@ -104,15 +108,16 @@ public void test2_linkParentDirectory() throws Exception {
* |-- link_grandparent -> ../../ (links "project root")
*
*/
- @Test
- public void test3_linkGrandparentDirectory() throws Exception {
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test3_linkGrandparentDirectory(boolean useAdvancedLinkCheck) throws Exception {
CreateTestProjectStructure createSymlinks = directory -> {
File subdirectory = new File(directory, "subdirectory");
createDirectory(subdirectory);
createSymlink(subdirectory, "link_grandparent", "../../");
};
- runTest(createSymlinks);
+ runTest(createSymlinks, useAdvancedLinkCheck);
}
/**
@@ -132,8 +137,9 @@ public void test3_linkGrandparentDirectory() throws Exception {
* |-- link_parent -> ../ (links directory)
*
*/
- @Test
- public void test4_linkParentDirectoryTwice() throws Exception {
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test4_linkParentDirectoryTwice(boolean useAdvancedLinkCheck) throws Exception {
CreateTestProjectStructure createSymlinks = directory -> {
String[] subdirectoryNames = { "subdirectory1", "subdirectory2" };
for (String subdirectoryName : subdirectoryNames) {
@@ -143,7 +149,7 @@ public void test4_linkParentDirectoryTwice() throws Exception {
}
};
- runTest(createSymlinks);
+ runTest(createSymlinks, useAdvancedLinkCheck);
}
/**
@@ -163,8 +169,9 @@ public void test4_linkParentDirectoryTwice() throws Exception {
* |-- link_parent -> /tmp/<random string>/bug185247recursive/test5_linkParentDirectoyTwiceWithAbsolutePath/directory
*
*/
- @Test
- public void test5_linkParentDirectoyTwiceWithAbsolutePath() throws Exception {
+ @ParameterizedTest
+ @ValueSource(booleans = { false, true })
+ public void test5_linkParentDirectoyTwiceWithAbsolutePath(boolean useAdvancedLinkCheck) throws Exception {
CreateTestProjectStructure createSymlinks = directory -> {
String[] subdirectoryNames = { "subdirectory1", "subdirectory2" };
for (String subdirectoryName : subdirectoryNames) {
@@ -174,22 +181,28 @@ public void test5_linkParentDirectoyTwiceWithAbsolutePath() throws Exception {
}
};
- runTest(createSymlinks);
+ runTest(createSymlinks, useAdvancedLinkCheck);
}
- private void runTest(CreateTestProjectStructure createSymlinks) throws MalformedURLException, Exception {
- String projectName = testMethodName;
- IPath testRoot = IPath.fromPath(tempDirectory);
- IPath projectRoot = testRoot.append("bug185247recursive").append(projectName);
- File directory = projectRoot.append("directory").toFile();
- createDirectory(directory);
-
- createSymlinks.accept(directory);
-
-
- URI projectRootLocation = URIUtil.toURI((projectRoot));
- // refreshing the project with recursive symlinks should not hang
- importProjectAndRefresh(projectName, projectRootLocation);
+ private void runTest(CreateTestProjectStructure createSymlinks, boolean useAdvancedLinkCheck)
+ throws MalformedURLException, Exception {
+ final boolean originalValue = UnifiedTree.isAdvancedRecursiveLinkChecksEnabled();
+ try {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(useAdvancedLinkCheck);
+ String projectName = testMethodName;
+ IPath testRoot = IPath.fromPath(tempDirectory);
+ IPath projectRoot = testRoot.append("bug185247recursive").append(projectName);
+ File directory = projectRoot.append("directory").toFile();
+ createDirectory(directory);
+
+ createSymlinks.accept(directory);
+
+ URI projectRootLocation = URIUtil.toURI((projectRoot));
+ // refreshing the project with recursive symlinks should not hang
+ importProjectAndRefresh(projectName, projectRootLocation);
+ } finally {
+ UnifiedTree.enableAdvancedRecursiveLinkChecks(originalValue);
+ }
}
private static void createDirectory(File directory) {
diff --git a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/util/WorkspaceResetExtension.java b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/util/WorkspaceResetExtension.java
index 937eeb73c1b..81af73f6faf 100644
--- a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/util/WorkspaceResetExtension.java
+++ b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/util/WorkspaceResetExtension.java
@@ -40,7 +40,7 @@ public class WorkspaceResetExtension implements AfterEachCallback, BeforeEachCal
public void beforeEach(ExtensionContext context) throws Exception {
// Wait for any pending refresh operation, in particular from startup
waitForRefresh();
- TestUtil.log(IStatus.INFO, context.getDisplayName(), "setUp");
+ TestUtil.log(IStatus.INFO, getTestName(context), "setUp");
assertNotNull(getWorkspace(), "Workspace was not set up");
FreezeMonitor.expectCompletionInAMinute();
waitForRefresh();
@@ -48,7 +48,7 @@ public void beforeEach(ExtensionContext context) throws Exception {
@Override
public void afterEach(ExtensionContext context) throws Exception {
- TestUtil.log(IStatus.INFO, context.getDisplayName(), "tearDown");
+ TestUtil.log(IStatus.INFO, getTestName(context), "tearDown");
try {
restoreCleanWorkspace();
} finally {
@@ -57,6 +57,16 @@ public void afterEach(ExtensionContext context) throws Exception {
}
}
+ private String getTestName(ExtensionContext context) {
+ String className = context.getRequiredTestClass().getSimpleName();
+ String methodName = context.getRequiredTestMethod().getName();
+ String displayName = context.getDisplayName();
+ if (!displayName.contains(methodName)) {
+ methodName += displayName;
+ }
+ return className + "." + methodName;
+ }
+
private void restoreCleanWorkspace() {
List