/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sergey Prigogin (Google) - [338010] Resource.createLink() does not preserve symbolic links
 *******************************************************************************/
package org.eclipse.core.tests.resources;

import java.io.*;
import java.io.File;
import java.net.URI;
import java.util.HashMap;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.utils.FileUtil;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.tests.harness.CancelingProgressMonitor;
import org.eclipse.core.tests.harness.FussyProgressMonitor;

/**
 * Tests the following API methods:
 *  IFile#createLink
 * 	IFolder#createLink
 *
 * This test supports both variable-based and non-variable-based locations.
 * Although the method used for creating random locations
 * <code>ResourceTest#getRandomLocation()</code> never returns variable-
 * based paths, this method is overwritten in the derived class
 * <code>LinkedResourceWithPathVariable</code> to always return variable-based
 * paths.
 *
 * To support variable-based paths wherever a file system location is used, it
 * is mandatory first to resolve it and only then using it, except in calls to
 * <code>IFile#createLink</code> and <code>IFolder#createLink</code> and when
 * the location is obtained using <code>IResource#getLocation()</code>.
 */
public class LinkedResourceTest extends ResourceTest {
	protected String childName = "File.txt";
	protected IProject closedProject;
	protected IFile existingFileInExistingProject;
	protected IFolder existingFolderInExistingFolder;
	protected IFolder existingFolderInExistingProject;
	protected IProject existingProject;
	protected IProject existingProjectInSubDirectory;
	protected IPath localFile;
	protected IPath localFolder;
	protected IFile nonExistingFileInExistingFolder;
	protected IFile nonExistingFileInExistingProject;
	protected IFile nonExistingFileInOtherExistingProject;
	protected IFolder nonExistingFolderInExistingFolder;
	protected IFolder nonExistingFolderInExistingProject;
	protected IFolder nonExistingFolderInNonExistingFolder;
	protected IFolder nonExistingFolderInNonExistingProject;
	protected IFolder nonExistingFolderInOtherExistingProject;
	protected IPath nonExistingLocation;
	protected IProject nonExistingProject;
	protected IProject otherExistingProject;

	public static Test suite() {
		return new TestSuite(LinkedResourceTest.class);
		//						TestSuite suite = new TestSuite();
		//						suite.addTest(new LinkedResourceTest("testFindFilesForLocationCaseVariant"));
		//						return suite;
	}

	public LinkedResourceTest() {
		super();
	}

	public LinkedResourceTest(String name) {
		super(name);
	}

	protected void doCleanup() throws Exception {
		ensureExistsInWorkspace(new IResource[] {existingProject, otherExistingProject, closedProject, existingFolderInExistingProject, existingFolderInExistingFolder, existingFileInExistingProject}, true);
		closedProject.close(getMonitor());
		ensureDoesNotExistInWorkspace(new IResource[] {nonExistingProject, nonExistingFolderInExistingProject, nonExistingFolderInExistingFolder, nonExistingFolderInOtherExistingProject, nonExistingFolderInNonExistingProject, nonExistingFolderInNonExistingFolder, nonExistingFileInExistingProject, nonExistingFileInOtherExistingProject, nonExistingFileInExistingFolder});
		ensureDoesNotExistInFileSystem(resolve(nonExistingLocation).toFile());
		resolve(localFolder).toFile().mkdirs();
		createFileInFileSystem(resolve(localFile), getRandomContents());
	}

	private byte[] getFileContents(IFile file) throws CoreException {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		transferData(new BufferedInputStream(file.getContents()), bout);
		return bout.toByteArray();
	}

	/**
	 * Maybe overridden in subclasses that use path variables.
	 */
	protected IPath resolve(IPath path) {
		return path;
	}

	/**
	 * Maybe overridden in subclasses that use path variables.
	 */
	protected URI resolve(URI uri) {
		return uri;
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		existingProject = getWorkspace().getRoot().getProject("ExistingProject");
		existingProjectInSubDirectory = getWorkspace().getRoot().getProject("ExistingProjectInSubDirectory");
		otherExistingProject = getWorkspace().getRoot().getProject("OtherExistingProject");
		closedProject = getWorkspace().getRoot().getProject("ClosedProject");
		existingFolderInExistingProject = existingProject.getFolder("existingFolderInExistingProject");
		existingFolderInExistingFolder = existingFolderInExistingProject.getFolder("existingFolderInExistingFolder");
		nonExistingFolderInExistingProject = existingProject.getFolder("nonExistingFolderInExistingProject");
		nonExistingFolderInOtherExistingProject = otherExistingProject.getFolder("nonExistingFolderInOtherExistingProject");
		nonExistingFolderInNonExistingFolder = nonExistingFolderInExistingProject.getFolder("nonExistingFolderInNonExistingFolder");
		nonExistingFolderInExistingFolder = existingFolderInExistingProject.getFolder("nonExistingFolderInExistingFolder");

		nonExistingProject = getWorkspace().getRoot().getProject("NonProject");
		nonExistingFolderInNonExistingProject = nonExistingProject.getFolder("nonExistingFolderInNonExistingProject");

		existingFileInExistingProject = existingProject.getFile("existingFileInExistingProject");
		nonExistingFileInExistingProject = existingProject.getFile("nonExistingFileInExistingProject");
		nonExistingFileInOtherExistingProject = otherExistingProject.getFile("nonExistingFileInOtherExistingProject");
		nonExistingFileInExistingFolder = existingFolderInExistingProject.getFile("nonExistingFileInExistingFolder");
		localFolder = getRandomLocation();
		nonExistingLocation = getRandomLocation();
		localFile = localFolder.append(childName);
		doCleanup();

		if (!existingProjectInSubDirectory.exists()) {
			IProjectDescription desc = getWorkspace().newProjectDescription(existingProjectInSubDirectory.getName());
			File dir = existingProject.getLocation().toFile();
			dir = dir.getParentFile();
			dir = new File(dir + File.separator + "sub" + File.separator + "dir" + File.separator + "more" + File.separator + "proj");
			dir.mkdirs();
			desc.setLocation(Path.fromOSString(dir.getAbsolutePath()));
			existingProjectInSubDirectory.create(desc, getMonitor());
		}
		if (!existingProjectInSubDirectory.isOpen()) {
			existingProjectInSubDirectory.open(getMonitor());
		}
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		Workspace.clear(resolve(localFolder).toFile());
		Workspace.clear(resolve(nonExistingLocation).toFile());
	}

	/**
	 * Tests creation of a linked resource whose corresponding file system
	 * path does not exist. This should succeed but no operations will be
	 * available on the resulting resource.
	 */
	public void testAllowMissingLocal() {
		//get a non-existing location
		IPath location = getRandomLocation();
		IFolder folder = nonExistingFolderInExistingProject;

		//try to create without the flag (should fail)
		try {
			folder.createLink(location, IResource.NONE, getMonitor());
			fail("1.0");
		} catch (CoreException e) {
			//should fail
		}

		//now try to create with the flag (should succeed)
		try {
			folder.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}
		assertEquals("1.2", resolve(location), folder.getLocation());
		assertTrue("1.3", !resolve(location).toFile().exists());
		//getting children should succeed (and be empty)
		try {
			assertEquals("1.4", 0, folder.members().length);
		} catch (CoreException e) {
			fail("1.5", e);
		}
		//delete should succeed
		try {
			folder.delete(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.6", e);
		}

		//try to create with local path that can never exist
		if (isWindows()) {
			location = new Path("b:\\does\\not\\exist");
		} else {
			location = new Path("/dev/null/does/not/exist");
		}
		location = FileUtil.canonicalPath(location);
		try {
			folder.createLink(location, IResource.NONE, getMonitor());
			fail("2.1");
		} catch (CoreException e) {
			//should fail
		}
		try {
			folder.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("2.2", e);
		}
		assertEquals("2.3", location, folder.getLocation());
		assertTrue("2.4", !location.toFile().exists());
		// creating child should fail
		try {
			folder.getFile("abc.txt").create(getRandomContents(), IResource.NONE, getMonitor());
			fail("2.5");
		} catch (CoreException e) {
			//should fail
		}
	}

	/**
	 * Tests case where a resource in the file system cannot be added to the workspace
	 * because it is blocked by a linked resource of the same name.
	 */
	public void testBlockedFolder() {
		//create local folder that will be blocked
		ensureExistsInFileSystem(nonExistingFolderInExistingProject);
		IFile blockedFile = nonExistingFolderInExistingProject.getFile("BlockedFile");
		createFileInFileSystem(blockedFile.getLocation(), getRandomContents());
		try {
			//link the folder elsewhere
			nonExistingFolderInExistingProject.createLink(localFolder, IResource.NONE, getMonitor());
			//refresh the project
			existingProject.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}

		//the blocked file should not exist in the workspace
		assertTrue("1.2", !blockedFile.exists());
		assertTrue("1.3", nonExistingFolderInExistingProject.exists());
		assertTrue("1.4", nonExistingFolderInExistingProject.getFile(childName).exists());
		assertEquals("1.5", nonExistingFolderInExistingProject.getLocation(), resolve(localFolder));

		//now delete the link
		try {
			nonExistingFolderInExistingProject.delete(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		//the blocked file and the linked folder should not exist in the workspace
		assertTrue("2.0", !blockedFile.exists());
		assertTrue("2.1", !nonExistingFolderInExistingProject.exists());
		assertTrue("2.2", !nonExistingFolderInExistingProject.getFile(childName).exists());
		assertEquals("2.3", nonExistingFolderInExistingProject.getLocation(), existingProject.getLocation().append(nonExistingFolderInExistingProject.getName()));

		//now refresh again to discover the blocked resource
		try {
			existingProject.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}

		//the blocked file should now exist
		assertTrue("3.0", blockedFile.exists());
		assertTrue("3.1", nonExistingFolderInExistingProject.exists());
		assertTrue("3.2", !nonExistingFolderInExistingProject.getFile(childName).exists());
		assertEquals("3.3", nonExistingFolderInExistingProject.getLocation(), existingProject.getLocation().append(nonExistingFolderInExistingProject.getName()));

		//attempting to link again will fail because the folder exists in the workspace
		try {
			nonExistingFolderInExistingProject.createLink(localFolder, IResource.NONE, getMonitor());
			fail("3.4");
		} catch (CoreException e) {
			//expected
		}
	}

	/**
	 * This test creates a linked folder resource, then changes the directory in
	 * the file system to be a file.  On refresh, the linked resource should
	 * still exist, should have the correct gender, and still be a linked
	 * resource.
	 */
	public void testChangeLinkGender() {
		IFolder folder = nonExistingFolderInExistingProject;
		IFile file = folder.getProject().getFile(folder.getProjectRelativePath());
		IPath resolvedLocation = resolve(localFolder);
		try {
			folder.createLink(localFolder, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("0.99", e);
		}
		ensureDoesNotExistInFileSystem(resolvedLocation.toFile());
		createFileInFileSystem(resolvedLocation, getRandomContents());
		try {
			folder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}

		assertTrue("3.0", !folder.exists());
		assertTrue("3.1", file.exists());
		assertTrue("3.2", file.isLinked());
		assertEquals("3.3", resolvedLocation, file.getLocation());

		//change back to folder
		ensureDoesNotExistInFileSystem(resolvedLocation.toFile());
		resolvedLocation.toFile().mkdirs();

		try {
			folder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("3.99", e);
		}
		assertTrue("4.0", folder.exists());
		assertTrue("4.1", !file.exists());
		assertTrue("4.2", folder.isLinked());
		assertEquals("4.3", resolvedLocation, folder.getLocation());
	}

	public void testCopyFile() {
		IResource[] sources = new IResource[] {nonExistingFileInExistingProject, nonExistingFileInExistingFolder};
		IResource[] destinationResources = new IResource[] {existingProject, closedProject, nonExistingFileInOtherExistingProject, nonExistingFileInExistingFolder};
		Boolean[] deepCopy = new Boolean[] {Boolean.TRUE, Boolean.FALSE};
		IProgressMonitor[] monitors = new IProgressMonitor[] {new FussyProgressMonitor(), new CancelingProgressMonitor(), null};
		Object[][] inputs = new Object[][] {sources, destinationResources, deepCopy, monitors};
		new TestPerformer("LinkedResourceTest.testCopyFile") {
			protected static final String CANCELED = "canceled";

			@Override
			public void cleanUp(Object[] args, int count) {
				super.cleanUp(args, count);
				try {
					doCleanup();
				} catch (Exception e) {
					fail("invocation " + count + " failed to cleanup", e);
				}
			}

			@Override
			public Object invokeMethod(Object[] args, int count) throws Exception {
				IFile source = (IFile) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).prepare();
				}
				try {
					source.createLink(localFile, IResource.NONE, null);
					source.copy(destination.getFullPath(), isDeep ? IResource.NONE : IResource.SHALLOW, monitor);
				} catch (OperationCanceledException e) {
					return CANCELED;
				}
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).sanityCheck();
				}
				return null;
			}

			@Override
			public boolean shouldFail(Object[] args, int count) {
				IFile source = (IFile) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (monitor instanceof CancelingProgressMonitor) {
					return false;
				}
				if (source.equals(destination)) {
					return true;
				}
				IResource parent = destination.getParent();
				if (!isDeep && parent == null) {
					return true;
				}
				if (!parent.isAccessible()) {
					return true;
				}
				if (destination.exists()) {
					return true;
				}
				//passed all failure cases so it should succeed
				return false;
			}

			@Override
			public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
				IFile source = (IFile) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (result == CANCELED) {
					return monitor instanceof CancelingProgressMonitor;
				}
				if (!destination.exists()) {
					return false;
				}
				//destination should only be linked for a shallow copy
				if (isDeep) {
					if (destination.isLinked()) {
						return false;
					}
					if (source.getLocation().equals(destination.getLocation())) {
						return false;
					}
					if (!destination.getProject().getLocation().isPrefixOf(destination.getLocation())) {
						return false;
					}
				} else {
					if (!destination.isLinked()) {
						return false;
					}
					if (!source.getLocation().equals(destination.getLocation())) {
						return false;
					}
					if (!source.getRawLocation().equals(destination.getRawLocation())) {
						return false;
					}
					if (!source.getLocationURI().equals(destination.getLocationURI())) {
						return false;
					}
				}
				return true;
			}
		}.performTest(inputs);
	}

	public void testCopyFolder() {
		IFolder[] sources = new IFolder[] {nonExistingFolderInExistingProject, nonExistingFolderInExistingFolder};
		IResource[] destinations = new IResource[] {existingProject, closedProject, nonExistingProject, existingFolderInExistingProject, nonExistingFolderInOtherExistingProject, nonExistingFolderInExistingFolder};
		Boolean[] deepCopy = new Boolean[] {Boolean.TRUE, Boolean.FALSE};
		IProgressMonitor[] monitors = new IProgressMonitor[] {new FussyProgressMonitor(), new CancelingProgressMonitor(), null};
		Object[][] inputs = new Object[][] {sources, destinations, deepCopy, monitors};
		new TestPerformer("LinkedResourceTest.testCopyFolder") {
			protected static final String CANCELED = "canceled";

			@Override
			public void cleanUp(Object[] args, int count) {
				super.cleanUp(args, count);
				try {
					doCleanup();
				} catch (Exception e) {
					fail("invocation " + count + " failed to cleanup", e);
				}
			}

			@Override
			public Object invokeMethod(Object[] args, int count) throws Exception {
				IFolder source = (IFolder) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).prepare();
				}
				try {
					source.createLink(localFolder, IResource.NONE, null);
					source.copy(destination.getFullPath(), isDeep ? IResource.NONE : IResource.SHALLOW, monitor);
				} catch (OperationCanceledException e) {
					return CANCELED;
				}
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).sanityCheck();
				}
				return null;
			}

			@Override
			public boolean shouldFail(Object[] args, int count) {
				IFolder source = (IFolder) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (monitor instanceof CancelingProgressMonitor) {
					return false;
				}
				IResource parent = destination.getParent();
				if (destination.getType() == IResource.PROJECT) {
					return true;
				}
				if (source.equals(destination)) {
					return true;
				}
				if (!isDeep && parent == null) {
					return true;
				}
				if (!parent.isAccessible()) {
					return true;
				}
				if (destination.exists()) {
					return true;
				}
				//passed all failure case so it should succeed
				return false;
			}

			@Override
			public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
				IFolder source = (IFolder) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (result == CANCELED) {
					return monitor instanceof CancelingProgressMonitor;
				}
				if (!destination.exists()) {
					return false;
				}
				//destination should only be linked for a shallow copy
				if (isDeep) {
					if (destination.isLinked()) {
						return false;
					}
					if (source.getLocation().equals(destination.getLocation())) {
						return false;
					}
					if (!destination.getProject().getLocation().isPrefixOf(destination.getLocation())) {
						return false;
					}
				} else {
					if (!destination.isLinked()) {
						return false;
					}
					if (!source.getLocation().equals(destination.getLocation())) {
						return false;
					}
					if (!source.getLocationURI().equals(destination.getLocationURI())) {
						return false;
					}
					if (!source.getRawLocation().equals(destination.getRawLocation())) {
						return false;
					}
				}
				return true;
			}
		}.performTest(inputs);
	}

	/**
	 * Tests copying a linked file resource that doesn't exist in the file system
	 */
	public void testCopyMissingFile() {
		IPath location = getRandomLocation();
		IFile linkedFile = nonExistingFileInExistingProject;
		try {
			linkedFile.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		IFile dest = existingProject.getFile("FailedCopyDest");
		try {
			linkedFile.copy(dest.getFullPath(), IResource.NONE, getMonitor());
			fail("2.0");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.1", !dest.exists());
		try {
			linkedFile.copy(dest.getFullPath(), IResource.FORCE, getMonitor());
			fail("2.2");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.3", !dest.exists());
	}

	/**
	 * Tests copying a linked folder that doesn't exist in the file system
	 */
	public void testCopyMissingFolder() {
		IPath location = getRandomLocation();
		IFolder linkedFolder = nonExistingFolderInExistingProject;
		try {
			linkedFolder.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		IFolder dest = existingProject.getFolder("FailedCopyDest");
		try {
			linkedFolder.copy(dest.getFullPath(), IResource.NONE, getMonitor());
			fail("2.0");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.1", !dest.exists());
		try {
			linkedFolder.copy(dest.getFullPath(), IResource.FORCE, getMonitor());
			fail("2.2");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.3", !dest.exists());
	}

	public void testCopyProjectWithLinks() {
		IPath fileLocation = getRandomLocation();
		IFile linkedFile = nonExistingFileInExistingProject;
		IFolder linkedFolder = nonExistingFolderInExistingProject;
		try {
			try {
				createFileInFileSystem(resolve(fileLocation), getRandomContents());
				linkedFolder.createLink(localFolder, IResource.NONE, getMonitor());
				linkedFile.createLink(fileLocation, IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("1.0", e);
			}

			//copy the project
			IProject destination = getWorkspace().getRoot().getProject("CopyTargetProject");
			try {
				existingProject.copy(destination.getFullPath(), IResource.SHALLOW, getMonitor());
			} catch (CoreException e) {
				fail("2.0", e);
			}

			IFile newFile = destination.getFile(linkedFile.getProjectRelativePath());
			assertTrue("3.0", newFile.isLinked());
			assertEquals("3.1", linkedFile.getLocation(), newFile.getLocation());

			IFolder newFolder = destination.getFolder(linkedFolder.getProjectRelativePath());
			assertTrue("4.0", newFolder.isLinked());
			assertEquals("4.1", linkedFolder.getLocation(), newFolder.getLocation());

			//test project deep copy
			try {
				destination.delete(IResource.NONE, getMonitor());
				existingProject.copy(destination.getFullPath(), IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("5.0", e);
			}
			assertTrue("5.1", !newFile.isLinked());
			assertEquals("5.2", destination.getLocation().append(newFile.getProjectRelativePath()), newFile.getLocation());
			assertTrue("5.3", !newFolder.isLinked());
			assertEquals("5.4", destination.getLocation().append(newFolder.getProjectRelativePath()), newFolder.getLocation());

			//test copy project when linked resources don't exist with force=false
			try {
				destination.delete(IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("5.99", e);
			}
			assertTrue("6.0", resolve(fileLocation).toFile().delete());

			try {
				existingProject.copy(destination.getFullPath(), IResource.NONE, getMonitor());
				fail("6.1");
			} catch (CoreException e) {
				//should fail
			}
			//all members except the missing link should have been copied
			assertTrue("6.2", destination.exists());
			assertTrue("6.2.1", !destination.getFile(linkedFile.getName()).exists());
			try {
				IResource[] srcChildren = existingProject.members();
				for (int i = 0; i < srcChildren.length; i++) {
					if (!srcChildren[i].equals(linkedFile)) {
						assertNotNull("6.3." + i, destination.findMember(srcChildren[i].getProjectRelativePath()));
					}
				}
			} catch (CoreException e) {
				fail("6.4", e);
			}
			//test copy project when linked resources don't exist with force=true
			//this should mostly succeed, but still throw an exception indicating
			//a resource could not be copied because its location was missing
			try {
				destination.delete(IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("6.5", e);
			}
			try {
				existingProject.copy(destination.getFullPath(), IResource.FORCE, getMonitor());
				fail("6.6");
			} catch (CoreException e) {
				//should fail
			}
			assertTrue("6.7", destination.exists());
			assertTrue("6.7.1", !destination.getFile(linkedFile.getName()).exists());
			//all members except the missing link should have been copied
			try {
				IResource[] srcChildren = existingProject.members();
				for (int i = 0; i < srcChildren.length; i++) {
					if (!srcChildren[i].equals(linkedFile)) {
						assertNotNull("6.8." + i, destination.findMember(srcChildren[i].getProjectRelativePath()));
					}
				}
			} catch (CoreException e) {
				fail("6.99", e);
			}
		} finally {
			Workspace.clear(resolve(fileLocation).toFile());
		}
	}

	/**
	 * Tests creating a linked folder and performing refresh in the background
	 */
	public void testCreateFolderInBackground() throws CoreException {
		final IFileStore rootStore = getTempStore();
		rootStore.mkdir(IResource.NONE, getMonitor());
		IFileStore childStore = rootStore.getChild("file.txt");
		createFileInFileSystem(childStore);

		IFolder link = nonExistingFolderInExistingProject;
		link.createLink(rootStore.toURI(), IResource.BACKGROUND_REFRESH, getMonitor());
		waitForRefresh();
		IFile linkChild = link.getFile(childStore.getName());
		assertTrue("1.0", link.exists());
		assertTrue("1.1", link.isSynchronized(IResource.DEPTH_INFINITE));
		assertTrue("1.2", linkChild.exists());
		assertTrue("1.3", linkChild.isSynchronized(IResource.DEPTH_INFINITE));
	}

	/**
	 * Tests creating a linked resource with the same name but different
	 * case as an existing resource.  On case insensitive platforms this should fail.
	 */
	public void testCreateLinkCaseVariant() {
		IFolder link = nonExistingFolderInExistingProject;
		IFolder variant = link.getParent().getFolder(new Path(link.getName().toUpperCase()));
		ensureExistsInWorkspace(variant, true);

		try {
			link.createLink(localFolder, IResource.NONE, getMonitor());
			//should fail on case insensitive platforms
			if (!isCaseSensitive(variant)) {
				fail("1.0");
			}
		} catch (CoreException e) {
			//should not fail on case sensitive platforms
			if (isCaseSensitive(variant)) {
				fail("1.1", e);
			}
		}

	}

	/**
	 * Tests creating a linked resource by modifying the .project file directly.
	 * This is a regression test for bug 63331.
	 */
	public void testCreateLinkInDotProject() {
		final IFile dotProject = existingProject.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
		IFile link = nonExistingFileInExistingProject;
		byte[] oldContents = null;
		try {
			//create a linked file
			link.createLink(localFile, IResource.NONE, getMonitor());
			//copy the .project file contents
			oldContents = getFileContents(dotProject);
			//delete linked file
			link.delete(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		final byte[] finalContents = oldContents;
		try {
			//recreate the link in a workspace runnable with create scheduling rule
			getWorkspace().run((IWorkspaceRunnable) monitor -> dotProject.setContents(new ByteArrayInputStream(finalContents), IResource.NONE, getMonitor()), getWorkspace().getRuleFactory().modifyRule(dotProject), IResource.NONE, getMonitor());
		} catch (CoreException e1) {
			fail("2.99", e1);
		}
	}

	/**
	 * Tests creating a project whose .project file already defines links at
	 * depth greater than one. See bug 121322.
	 */
	public void testCreateProjectWithDeepLinks() {
		IProject project = existingProject;
		IFolder parent = existingFolderInExistingProject;
		IFolder folder = nonExistingFolderInExistingFolder;
		try {
			folder.createLink(localFolder, IResource.NONE, getMonitor());
			//delete and recreate the project
			project.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, getMonitor());
			project.create(getMonitor());
			project.open(IResource.BACKGROUND_REFRESH, getMonitor());
			assertTrue("1.0", folder.exists());
			assertTrue("1.1", parent.exists());
			assertTrue("1.2", parent.isLocal(IResource.DEPTH_INFINITE));
		} catch (CoreException e) {
			fail("1.99", e);
		}
	}

	/**
	 * Tests whether {@link IFile#createLink} and {@link IFolder#createLink}
	 * handle {@link IResource#HIDDEN} flag properly.
	 */
	public void testCreateHiddenLinkedResources() {
		IFolder folder = existingProject.getFolder("folder");
		IFile file = existingProject.getFile("file.txt");

		try {
			folder.createLink(localFolder, IResource.HIDDEN, getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}

		try {
			file.createLink(localFile, IResource.HIDDEN, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}

		assertTrue("3.0", folder.isHidden());
		assertTrue("4.0", file.isHidden());
	}

	public void testDeepMoveProjectWithLinks() {
		IPath fileLocation = getRandomLocation();
		IFile file = nonExistingFileInExistingProject;
		IFolder folder = nonExistingFolderInExistingProject;
		IFile childFile = folder.getFile(childName);
		IResource[] oldResources = new IResource[] {file, folder, existingProject, childFile};
		try {
			try {
				createFileInFileSystem(resolve(fileLocation));
				folder.createLink(localFolder, IResource.NONE, getMonitor());
				file.createLink(fileLocation, IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("1.0", e);
			}

			//move the project
			IProject destination = getWorkspace().getRoot().getProject("MoveTargetProject");
			IFile newFile = destination.getFile(file.getProjectRelativePath());
			IFolder newFolder = destination.getFolder(folder.getProjectRelativePath());
			IFile newChildFile = newFolder.getFile(childName);
			IResource[] newResources = new IResource[] {destination, newFile, newFolder, newChildFile};

			assertDoesNotExistInWorkspace("2.0", destination);

			try {
				existingProject.move(destination.getFullPath(), IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("2.1", e);
			}
			assertExistsInWorkspace("3.0", newResources);
			assertDoesNotExistInWorkspace("3.1", oldResources);
			assertTrue("3.2", existingProject.isSynchronized(IResource.DEPTH_INFINITE));
			assertTrue("3.3", destination.isSynchronized(IResource.DEPTH_INFINITE));

			assertTrue("3.4", !newFile.isLinked());
			assertEquals("3.5", destination.getLocation().append(newFile.getProjectRelativePath()), newFile.getLocation());

			assertTrue("3.6", !newFolder.isLinked());
			assertEquals("3.7", destination.getLocation().append(newFolder.getProjectRelativePath()), newFolder.getLocation());

			assertTrue("3.8", destination.isSynchronized(IResource.DEPTH_INFINITE));
		} finally {
			Workspace.clear(resolve(fileLocation).toFile());
		}
	}

	/**
	 * Tests deleting the parent of a linked resource.
	 */
	public void testDeleteLinkParent() {
		IFolder link = nonExistingFolderInExistingFolder;
		IFolder linkParent = existingFolderInExistingProject;
		IFile linkChild = link.getFile("child.txt");
		IFileStore childStore = null;
		try {
			link.createLink(localFolder, IResource.NONE, getMonitor());
			ensureExistsInWorkspace(linkChild, true);
			childStore = EFS.getStore(linkChild.getLocationURI());
		} catch (CoreException e) {
			fail("0.99", e);
		}

		//everything should exist at this point
		assertTrue("1.0", linkParent.exists());
		assertTrue("1.1", link.exists());
		assertTrue("1.2", linkChild.exists());

		//delete the parent of the link
		try {
			linkParent.delete(IResource.KEEP_HISTORY, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		//resources should not exist, but link content should exist on disk
		assertTrue("2.0", !linkParent.exists());
		assertTrue("2.1", !link.exists());
		assertTrue("2.2", !linkChild.exists());
		assertTrue("2.3", childStore.fetchInfo().exists());
	}

	/**
	 * Tests deleting and then recreating a project
	 */
	public void testDeleteProjectWithLinks() {
		IFolder link = nonExistingFolderInExistingProject;
		try {
			link.createLink(localFolder, IResource.NONE, getMonitor());
			existingProject.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, getMonitor());
			existingProject.create(getMonitor());
		} catch (CoreException e) {
			fail("0.99", e);
		}

		//link should not exist until the project is open
		assertTrue("1.0", !link.exists());

		try {
			existingProject.open(getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		//link should now exist
		assertTrue("2.0", link.exists());
		assertTrue("2.1", link.isLinked());
		assertEquals("2.2", resolve(localFolder), link.getLocation());
	}

	/**
	 * Tests deleting a linked resource when .project is read-only
	 */
	public void testDeleteLink_Bug351823() throws CoreException {
		IProject project = existingProject;

		IFile link = project.getFile(getUniqueString());
		link.createLink(localFile, IResource.NONE, getMonitor());

		// set .project read-only
		IFile descriptionFile = project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
		ResourceAttributes attrs = descriptionFile.getResourceAttributes();
		attrs.setReadOnly(true);
		descriptionFile.setResourceAttributes(attrs);

		try {
			try {
				link.delete(false, getMonitor());
				fail("1.0");
			} catch (CoreException e1) {
				// should fail
			}

			assertTrue("2.0", link.exists());
			assertTrue("3.0", link.isLinked());

			HashMap<IPath, LinkDescription> links = ((Project) project).internalGetDescription().getLinks();
			assertNotNull("4.0", links);
			assertEquals("5.0", 1, links.size());

			LinkDescription linkDesc = links.values().iterator().next();
			assertEquals("6.0", link.getProjectRelativePath(), linkDesc.getProjectRelativePath());

			// try to delete again
			// if the project description in memory is ok, it should fail
			try {
				link.delete(false, getMonitor());
				fail("7.0");
			} catch (CoreException e1) {
				// should fail
			}
		} finally {
			// set .project writable
			attrs = descriptionFile.getResourceAttributes();
			attrs.setReadOnly(false);
			descriptionFile.setResourceAttributes(attrs);
		}
	}

	/**
	 * Tests bug 209175.
	 */
	public void testDeleteFolderWithLinks() {
		IProject project = existingProject;
		IFolder folder = existingFolderInExistingProject;
		IFile file1 = folder.getFile(getUniqueString());
		IFile file2 = project.getFile(getUniqueString());
		try {
			file1.createLink(localFile, IResource.NONE, getMonitor());
			file2.createLink(localFile, IResource.NONE, getMonitor());

			HashMap<IPath, LinkDescription> links = ((Project) project).internalGetDescription().getLinks();
			LinkDescription linkDescription1 = links.get(file1.getProjectRelativePath());
			assertNotNull("1.0", linkDescription1);
			assertEquals("1.1", URIUtil.toURI(localFile), linkDescription1.getLocationURI());
			LinkDescription linkDescription2 = links.get(file2.getProjectRelativePath());
			assertNotNull("2.0", linkDescription2);
			assertEquals("2.1", URIUtil.toURI(localFile), linkDescription2.getLocationURI());

			folder.delete(true, getMonitor());

			links = ((Project) project).internalGetDescription().getLinks();
			linkDescription1 = links.get(file1.getProjectRelativePath());
			assertNull("3.0", linkDescription1);
			linkDescription2 = links.get(file2.getProjectRelativePath());
			assertNotNull("4.0", linkDescription2);
			assertEquals("4.1", URIUtil.toURI(localFile), linkDescription2.getLocationURI());
		} catch (CoreException e) {
			fail("5.0", e);
		}
	}

	/**
	 * Tests that IWorkspaceRoot.findFilesForLocation works correctly
	 * in presence of a linked resource that does not match the case in the file system
	 */
	public void testFindFilesForLocationCaseVariant() {
		//this test only applies to file systems with a device in the path
		if (!isWindows()) {
			return;
		}
		IFolder link = nonExistingFolderInExistingProject;
		IPath localLocation = resolve(localFolder);
		IPath upperCase = localLocation.setDevice(localLocation.getDevice().toUpperCase());
		IPath lowerCase = localLocation.setDevice(localLocation.getDevice().toLowerCase());

		try {
			link.createLink(upperCase, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		IPath lowerCaseFilePath = lowerCase.append("file.txt");
		IFile[] files = getWorkspace().getRoot().findFilesForLocation(lowerCaseFilePath);
		assertEquals("1.0", 1, files.length);
	}

	/**
	 * Tests the {@link org.eclipse.core.resources.IResource#isLinked(int)} method.
	 */
	public void testIsLinked() {
		//initially nothing is linked
		IResource[] toTest = new IResource[] {closedProject, existingFileInExistingProject, existingFolderInExistingFolder, existingFolderInExistingProject, existingProject, nonExistingFileInExistingFolder, nonExistingFileInExistingProject, nonExistingFileInOtherExistingProject, nonExistingFolderInExistingFolder, nonExistingFolderInExistingProject, nonExistingFolderInNonExistingFolder, nonExistingFolderInNonExistingProject, nonExistingFolderInOtherExistingProject, nonExistingProject, otherExistingProject};
		for (int i = 0; i < toTest.length; i++) {
			assertTrue("1.0 " + toTest[i], !toTest[i].isLinked());
			assertTrue("1.1 " + toTest[i], !toTest[i].isLinked(IResource.NONE));
			assertTrue("1.2 " + toTest[i], !toTest[i].isLinked(IResource.CHECK_ANCESTORS));
		}
		// create a link
		IFolder link = nonExistingFolderInExistingProject;
		try {
			link.createLink(localFolder, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		IFile child = link.getFile(childName);
		assertTrue("2.0", child.exists());
		assertTrue("2.1", link.isLinked());
		assertTrue("2.2", link.isLinked(IResource.NONE));
		assertTrue("2.3", link.isLinked(IResource.CHECK_ANCESTORS));
		assertTrue("2.1", !child.isLinked());
		assertTrue("2.2", !child.isLinked(IResource.NONE));
		assertTrue("2.3", child.isLinked(IResource.CHECK_ANCESTORS));

	}

	/**
	 * Tests the
	 * {@link org.eclipse.core.resources.IResource#setLinkLocation(URI , int , IProgressMonitor )}
	 * method.
	 */
	public void testsetLinkLocation() {
		// initially nothing is linked
		IResource[] toTest = new IResource[] {closedProject, existingFileInExistingProject, existingFolderInExistingFolder, existingFolderInExistingProject, existingProject, nonExistingFileInExistingFolder, nonExistingFileInExistingProject, nonExistingFileInOtherExistingProject, nonExistingFolderInExistingFolder, nonExistingFolderInExistingProject, nonExistingFolderInNonExistingFolder, nonExistingFolderInNonExistingProject, nonExistingFolderInOtherExistingProject, nonExistingProject, otherExistingProject};
		for (int i = 0; i < toTest.length; i++) {
			assertTrue("1.0 " + toTest[i], !toTest[i].isLinked());
			assertTrue("1.1 " + toTest[i], !toTest[i].isLinked(IResource.NONE));
			assertTrue("1.2 " + toTest[i], !toTest[i].isLinked(IResource.CHECK_ANCESTORS));
		}
		// create a link
		IFolder link = nonExistingFolderInExistingProject;
		try {
			link.createLink(localFolder, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		IFile child = link.getFile(childName);
		assertTrue("2.0", child.exists());
		assertTrue("2.1", link.isLinked());
		assertTrue("2.2", link.isLinked(IResource.NONE));
		assertTrue("2.3", link.isLinked(IResource.CHECK_ANCESTORS));
		assertTrue("2.1", !child.isLinked());
		assertTrue("2.2", !child.isLinked(IResource.NONE));
		assertTrue("2.3", child.isLinked(IResource.CHECK_ANCESTORS));

		try {
			link.createLink(existingFileInExistingProject.getLocationURI(), IResource.REPLACE, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		assertTrue("3.1", link.isLinked());
		assertTrue("3.2", link.isLinked(IResource.NONE));
		assertTrue("3.3", link.isLinked(IResource.CHECK_ANCESTORS));
		assertTrue("3.4", link.getLocation().equals(existingFileInExistingProject.getLocation()));
	}

	/**
	 * Tests swapping the link location.
	 * This is a regression test for bug 268507
	 */
	public void testSetLinkLocationSwapLinkedResource() {
		final IPath parentLoc = existingFolderInExistingProject.getLocation();
		final IPath childLoc = existingFolderInExistingFolder.getLocation();

		try {
			nonExistingFolderInExistingProject.createLink(parentLoc, IResource.NONE, getMonitor());
			nonExistingFolderInOtherExistingProject.createLink(childLoc, IResource.NONE, getMonitor());
			create(nonExistingFolderInOtherExistingProject.getFile("foo"), true);

			assertTrue("2.0", existingFolderInExistingFolder.members().length == 1);
			assertTrue("3.0", existingFolderInExistingFolder.members()[0].getName().equals("foo"));
			assertTrue("2.0", nonExistingFolderInOtherExistingProject.members().length == 1);
			assertTrue("3.0", nonExistingFolderInOtherExistingProject.members()[0].getName().equals("foo"));

			assertTrue("4.0", nonExistingFolderInExistingProject.members().length == 1);
			assertTrue("5.0", nonExistingFolderInExistingProject.members()[0].getName().equals(existingFolderInExistingFolder.getName()));
		} catch (CoreException e) {
			fail("1.0", e);
		}

		// Swap links around
		try {
			nonExistingFolderInExistingProject.createLink(childLoc, IResource.REPLACE, getMonitor());
			nonExistingFolderInOtherExistingProject.createLink(parentLoc, IResource.REPLACE, getMonitor());

			assertTrue("2.0", existingFolderInExistingFolder.members().length == 1);
			assertTrue("3.0", existingFolderInExistingFolder.members()[0].getName().equals("foo"));
			assertTrue(nonExistingFolderInExistingProject.getLocation().equals(childLoc));
			assertTrue("2.0", nonExistingFolderInExistingProject.members().length == 1);
			assertTrue("3.0", nonExistingFolderInExistingProject.members()[0].getName().equals("foo"));

			assertTrue("4.0", nonExistingFolderInOtherExistingProject.members().length == 1);
			assertTrue("5.0", nonExistingFolderInOtherExistingProject.members()[0].getName().equals(existingFolderInExistingFolder.getName()));
		} catch (CoreException e) {
			fail("1.0", e);
		}
	}

	/**
	 * Tests the
	 * {@link org.eclipse.core.resources.IResource#setLinkLocation(IPath, int , IProgressMonitor )}
	 * method.
	 */
	public void testsetLinkLocationPath() {
		//initially nothing is linked
		IResource[] toTest = new IResource[] {closedProject, existingFileInExistingProject, existingFolderInExistingFolder, existingFolderInExistingProject, existingProject, nonExistingFileInExistingFolder, nonExistingFileInExistingProject, nonExistingFileInOtherExistingProject, nonExistingFolderInExistingFolder, nonExistingFolderInExistingProject, nonExistingFolderInNonExistingFolder, nonExistingFolderInNonExistingProject, nonExistingFolderInOtherExistingProject, nonExistingProject, otherExistingProject};
		for (int i = 0; i < toTest.length; i++) {
			assertTrue("1.0 " + toTest[i], !toTest[i].isLinked());
			assertTrue("1.1 " + toTest[i], !toTest[i].isLinked(IResource.NONE));
			assertTrue("1.2 " + toTest[i], !toTest[i].isLinked(IResource.CHECK_ANCESTORS));
		}
		//create a link
		IFolder link = nonExistingFolderInExistingProject;
		try {
			link.createLink(localFolder, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		IFile child = link.getFile(childName);
		assertTrue("2.0", child.exists());
		assertTrue("2.1", link.isLinked());
		assertTrue("2.2", link.isLinked(IResource.NONE));
		assertTrue("2.3", link.isLinked(IResource.CHECK_ANCESTORS));
		assertTrue("2.1", !child.isLinked());
		assertTrue("2.2", !child.isLinked(IResource.NONE));
		assertTrue("2.3", child.isLinked(IResource.CHECK_ANCESTORS));

		try {
			link.createLink(existingFileInExistingProject.getLocation(), IResource.REPLACE, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		assertTrue("3.1", link.isLinked());
		assertTrue("3.2", link.isLinked(IResource.NONE));
		assertTrue("3.3", link.isLinked(IResource.CHECK_ANCESTORS));
		assertTrue("3.4", link.getLocation().equals(existingFileInExistingProject.getLocation()));
	}

	/**
	 * Specific testing of links within links.
	 */
	public void testLinkedFileInLinkedFolder() {
		//setup handles
		IProject project = existingProject;
		IFolder top = project.getFolder("topFolder");
		IFolder linkedFolder = top.getFolder("linkedFolder");
		IFolder subFolder = linkedFolder.getFolder("subFolder");
		IFile linkedFile = subFolder.getFile("Link.txt");
		IFileStore folderStore = getTempStore();
		IFileStore subFolderStore = folderStore.getChild(subFolder.getName());
		IFileStore fileStore = getTempStore();
		IPath folderLocation = URIUtil.toPath(folderStore.toURI());
		IPath fileLocation = URIUtil.toPath(fileStore.toURI());

		try {
			//create the structure on disk
			subFolderStore.mkdir(EFS.NONE, getMonitor());
			fileStore.openOutputStream(EFS.NONE, getMonitor()).close();

			//create the structure in the workspace
			ensureExistsInWorkspace(top, true);
			linkedFolder.createLink(folderStore.toURI(), IResource.NONE, getMonitor());
			linkedFile.createLink(fileStore.toURI(), IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("4.99", e);
		} catch (IOException e) {
			fail("4.99", e);
		}

		//assert locations
		assertEquals("1.0", folderLocation, linkedFolder.getLocation());
		assertEquals("1.1", folderLocation.append(subFolder.getName()), subFolder.getLocation());
		assertEquals("1.2", fileLocation, linkedFile.getLocation());
		//assert URIs
		assertEquals("1.0", folderStore.toURI(), linkedFolder.getLocationURI());
		assertEquals("1.1", subFolderStore.toURI(), subFolder.getLocationURI());
		assertEquals("1.2", fileStore.toURI(), linkedFile.getLocationURI());

	}

	/**
	 * Automated test of IFile#createLink
	 */
	public void testLinkFile() {
		IResource[] interestingResources = new IResource[] {existingFileInExistingProject, nonExistingFileInExistingProject, nonExistingFileInExistingFolder};
		IPath[] interestingLocations = new IPath[] {localFile, localFolder, nonExistingLocation};
		IProgressMonitor[] monitors = new IProgressMonitor[] {new FussyProgressMonitor(), new CancelingProgressMonitor(), null};
		Object[][] inputs = new Object[][] {interestingResources, interestingLocations, monitors};
		new TestPerformer("LinkedResourceTest.testLinkFile") {
			protected static final String CANCELED = "canceled";

			@Override
			public void cleanUp(Object[] args, int count) {
				super.cleanUp(args, count);
				try {
					doCleanup();
				} catch (Exception e) {
					fail("invocation " + count + " failed to cleanup", e);
				}
			}

			@Override
			public Object invokeMethod(Object[] args, int count) throws Exception {
				IFile file = (IFile) args[0];
				IPath location = (IPath) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).prepare();
				}
				try {
					file.createLink(location, IResource.NONE, monitor);
				} catch (OperationCanceledException e) {
					return CANCELED;
				}
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).sanityCheck();
				}
				return null;
			}

			@Override
			public boolean shouldFail(Object[] args, int count) {
				IResource resource = (IResource) args[0];
				IPath location = (IPath) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (monitor instanceof CancelingProgressMonitor) {
					return false;
				}
				//This resource already exists in the workspace
				if (resource.exists()) {
					return true;
				}
				IPath resolvedLocation = resolve(location);
				//The corresponding location in the local file system does not exist.
				if (!resolvedLocation.toFile().exists()) {
					return true;
				}
				//The workspace contains a resource of a different type at the same path as this resource
				if (getWorkspace().getRoot().findMember(resource.getFullPath()) != null) {
					return true;
				}
				//The parent of this resource does not exist.
				if (!resource.getParent().isAccessible()) {
					return true;
				}
				//The name of this resource is not valid (according to IWorkspace.validateName)
				if (!getWorkspace().validateName(resource.getName(), IResource.FOLDER).isOK()) {
					return true;
				}
				//The corresponding location in the local file system is occupied by a directory (as opposed to a file)
				if (resolvedLocation.toFile().isDirectory()) {
					return true;
				}
				//passed all failure case so it should succeed
				return false;
			}

			@Override
			public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
				IFile resource = (IFile) args[0];
				IPath location = (IPath) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (result == CANCELED) {
					return monitor instanceof CancelingProgressMonitor;
				}
				IPath resolvedLocation = resolve(location);
				if (!resource.exists() || !resolvedLocation.toFile().exists()) {
					return false;
				}
				if (!resource.getLocation().equals(resolvedLocation)) {
					return false;
				}
				if (!resource.isSynchronized(IResource.DEPTH_INFINITE)) {
					return false;
				}
				return true;
			}
		}.performTest(inputs);
	}

	/**
	 * Automated test of IFolder#createLink
	 */
	public void testLinkFolder() {
		IResource[] interestingResources = new IResource[] {existingFolderInExistingProject, existingFolderInExistingFolder, nonExistingFolderInExistingProject, nonExistingFolderInNonExistingProject, nonExistingFolderInNonExistingFolder, nonExistingFolderInExistingFolder};
		IPath[] interestingLocations = new IPath[] {localFile, localFolder, nonExistingLocation};
		IProgressMonitor[] monitors = new IProgressMonitor[] {new FussyProgressMonitor(), new CancelingProgressMonitor(), null};
		Object[][] inputs = new Object[][] {interestingResources, interestingLocations, monitors};
		new TestPerformer("LinkedResourceTest.testLinkFolder") {
			protected static final String CANCELED = "canceled";

			@Override
			public void cleanUp(Object[] args, int count) {
				super.cleanUp(args, count);
				try {
					doCleanup();
				} catch (Exception e) {
					fail("invocation " + count + " failed to cleanup", e);
				}
			}

			@Override
			public Object invokeMethod(Object[] args, int count) throws Exception {
				IFolder folder = (IFolder) args[0];
				IPath location = (IPath) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).prepare();
				}
				try {
					folder.createLink(location, IResource.NONE, monitor);
				} catch (OperationCanceledException e) {
					return CANCELED;
				}
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).sanityCheck();
				}
				return null;
			}

			@Override
			public boolean shouldFail(Object[] args, int count) {
				IResource resource = (IResource) args[0];
				IPath location = (IPath) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (monitor instanceof CancelingProgressMonitor) {
					return false;
				}
				//This resource already exists in the workspace
				if (resource.exists()) {
					return true;
				}
				//The corresponding location in the local file system does not exist.
				if (!resolve(location).toFile().exists()) {
					return true;
				}
				//The workspace contains a resource of a different type at the same path as this resource
				if (getWorkspace().getRoot().findMember(resource.getFullPath()) != null) {
					return true;
				}
				//The parent of this resource does not exist.
				if (!resource.getParent().isAccessible()) {
					return true;
				}
				//The name of this resource is not valid (according to IWorkspace.validateName)
				if (!getWorkspace().validateName(resource.getName(), IResource.FOLDER).isOK()) {
					return true;
				}
				//The corresponding location in the local file system is occupied by a file (as opposed to a directory)
				if (resolve(location).toFile().isFile()) {
					return true;
				}
				//passed all failure case so it should succeed
				return false;
			}

			@Override
			public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
				IFolder resource = (IFolder) args[0];
				IPath location = (IPath) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (result == CANCELED) {
					return monitor instanceof CancelingProgressMonitor;
				}
				IPath resolvedLocation = resolve(location);
				if (!resource.exists() || !resolvedLocation.toFile().exists()) {
					return false;
				}
				if (!resource.getLocation().equals(resolvedLocation)) {
					return false;
				}
				//ensure child exists
				if (!resource.getFile(childName).exists()) {
					return false;
				}
				return true;
			}
		}.performTest(inputs);

	}

	/**
	 * Automated test of IWorkspace#validateLinkLocation and IWorkspace#validateLinkLocationURI with empty location
	 * This is a regression test for bug 266662
	 */
	public void testValidateEmptyLinkLocation() {
		IFolder folder = nonExistingFolderInExistingProject;
		IPath newLocation = new Path("");
		URI newLocationURI = URIUtil.toURI(newLocation);
		try {
			IStatus linkedResourceStatus = getWorkspace().validateLinkLocation(folder, newLocation);
			assertEquals("1.0", IStatus.ERROR, linkedResourceStatus.getSeverity());
			linkedResourceStatus = getWorkspace().validateLinkLocationURI(folder, newLocationURI);
			assertEquals("1.1", IStatus.ERROR, linkedResourceStatus.getSeverity());
		} catch (Exception e) {
			fail("1.99", e);
		}
	}

	/**
	 * Tests creating a linked resource whose location contains a colon character.
	 */
	public void testLocationWithColon() {
		//windows does not allow a location with colon in the name
		if (isWindows()) {
			return;
		}
		IFolder folder = nonExistingFolderInExistingProject;
		try {
			//Note that on *nix, "c:/temp" is a relative path with two segments
			//so this is treated as relative to an undefined path variable called "c:".
			IPath location = new Path("c:/temp");
			folder.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
			assertEquals("1.0", location, folder.getRawLocation());
		} catch (CoreException e) {
			fail("1.99", e);
		}
	}

	/**
	 * Tests the timestamp of a linked file when the local file is created or
	 * deleted. See bug 34150 for more details.
	 */
	public void testModificationStamp() {
		IPath location = getRandomLocation();
		IFile linkedFile = nonExistingFileInExistingProject;
		try {
			try {
				linkedFile.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
			} catch (CoreException e) {
				fail("1.99", e);
			}
			assertEquals("1.0", IResource.NULL_STAMP, linkedFile.getModificationStamp());
			//create local file
			try {
				resolve(location).toFile().createNewFile();
				linkedFile.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			} catch (CoreException e) {
				fail("2.91", e);
			} catch (IOException e) {
				fail("2.92", e);
			}
			assertTrue("2.0", linkedFile.getModificationStamp() >= 0);

			//delete local file
			ensureDoesNotExistInFileSystem(resolve(location).toFile());
			try {
				linkedFile.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			} catch (CoreException e) {
				fail("3.99", e);
			}
			assertEquals("4.0", IResource.NULL_STAMP, linkedFile.getModificationStamp());
		} finally {
			Workspace.clear(resolve(location).toFile());
		}
	}

	public void testMoveFile() {
		IResource[] sources = new IResource[] {nonExistingFileInExistingProject, nonExistingFileInExistingFolder};
		IResource[] destinations = new IResource[] {existingProject, closedProject, nonExistingFileInOtherExistingProject, nonExistingFileInExistingFolder};
		Boolean[] deepCopy = new Boolean[] {Boolean.TRUE, Boolean.FALSE};
		IProgressMonitor[] monitors = new IProgressMonitor[] {new FussyProgressMonitor(), new CancelingProgressMonitor(), null};
		Object[][] inputs = new Object[][] {sources, destinations, deepCopy, monitors};
		new TestPerformer("LinkedResourceTest.testMoveFile") {
			protected static final String CANCELED = "canceled";

			@Override
			public void cleanUp(Object[] args, int count) {
				super.cleanUp(args, count);
				try {
					doCleanup();
				} catch (Exception e) {
					fail("invocation " + count + " failed to cleanup", e);
				}
			}

			@Override
			public Object invokeMethod(Object[] args, int count) throws Exception {
				IFile source = (IFile) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).prepare();
				}
				try {
					source.createLink(localFile, IResource.NONE, null);
					source.move(destination.getFullPath(), isDeep ? IResource.NONE : IResource.SHALLOW, monitor);
				} catch (OperationCanceledException e) {
					return CANCELED;
				}
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).sanityCheck();
				}
				return null;
			}

			@Override
			public boolean shouldFail(Object[] args, int count) {
				IFile source = (IFile) args[0];
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				if (monitor instanceof CancelingProgressMonitor) {
					return false;
				}
				IResource parent = destination.getParent();
				if (!isDeep && parent == null) {
					return true;
				}
				if (!parent.isAccessible()) {
					return true;
				}
				if (source.equals(destination)) {
					return true;
				}
				if (source.getType() != destination.getType()) {
					return true;
				}
				if (destination.exists()) {
					return true;
				}
				//passed all failure case so it should succeed
				return false;
			}

			@Override
			public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
				IResource destination = (IResource) args[1];
				boolean isDeep = ((Boolean) args[2]).booleanValue();
				IProgressMonitor monitor = (IProgressMonitor) args[3];
				IPath sourceLocation = resolve(localFile);
				URI sourceLocationURI = URIUtil.toURI(sourceLocation);
				if (result == CANCELED) {
					return monitor instanceof CancelingProgressMonitor;
				}
				if (!destination.exists()) {
					return false;
				}
				//destination should only be linked for a shallow move
				if (isDeep) {
					if (destination.isLinked()) {
						return false;
					}
					if (resolve(localFile).equals(destination.getLocation())) {
						return false;
					}
					if (!destination.getProject().getLocation().isPrefixOf(destination.getLocation())) {
						return false;
					}
				} else {
					if (!destination.isLinked()) {
						return false;
					}
					if (!sourceLocation.equals(destination.getLocation())) {
						return false;
					}
					if (!sourceLocationURI.equals(destination.getLocationURI())) {
						return false;
					}
				}
				return true;
			}
		}.performTest(inputs);
	}

	public void testMoveFolder() {
		IResource[] sourceResources = new IResource[] {nonExistingFolderInExistingProject, nonExistingFolderInExistingFolder};
		IResource[] destinationResources = new IResource[] {existingProject, closedProject, nonExistingProject, existingFolderInExistingProject, nonExistingFolderInOtherExistingProject, nonExistingFolderInExistingFolder};
		IProgressMonitor[] monitors = new IProgressMonitor[] {new FussyProgressMonitor(), new CancelingProgressMonitor(), null};
		Object[][] inputs = new Object[][] {sourceResources, destinationResources, monitors};
		new TestPerformer("LinkedResourceTest.testMoveFolder") {
			protected static final String CANCELED = "canceled";

			@Override
			public void cleanUp(Object[] args, int count) {
				super.cleanUp(args, count);
				try {
					doCleanup();
				} catch (Exception e) {
					fail("invocation " + count + " failed to cleanup", e);
				}
			}

			@Override
			public Object invokeMethod(Object[] args, int count) throws Exception {
				IFolder source = (IFolder) args[0];
				IResource destination = (IResource) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).prepare();
				}
				try {
					source.createLink(localFolder, IResource.NONE, null);
					source.move(destination.getFullPath(), IResource.SHALLOW, monitor);
				} catch (OperationCanceledException e) {
					return CANCELED;
				}
				if (monitor instanceof FussyProgressMonitor) {
					((FussyProgressMonitor) monitor).sanityCheck();
				}
				return null;
			}

			@Override
			public boolean shouldFail(Object[] args, int count) {
				IFolder source = (IFolder) args[0];
				IResource destination = (IResource) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (monitor instanceof CancelingProgressMonitor) {
					return false;
				}
				IResource parent = destination.getParent();
				if (parent == null) {
					return true;
				}
				if (source.equals(destination)) {
					return true;
				}
				if (source.getType() != destination.getType()) {
					return true;
				}
				if (!parent.isAccessible()) {
					return true;
				}
				if (destination.exists()) {
					return true;
				}
				//passed all failure case so it should succeed
				return false;
			}

			@Override
			public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
				IResource destination = (IResource) args[1];
				IProgressMonitor monitor = (IProgressMonitor) args[2];
				if (result == CANCELED) {
					return monitor instanceof CancelingProgressMonitor;
				}
				if (!destination.exists()) {
					return false;
				}
				if (!destination.isLinked()) {
					return false;
				}
				if (!resolve(localFolder).equals(destination.getLocation())) {
					return false;
				}
				return true;
			}
		}.performTest(inputs);
	}

	/**
	 * Tests moving a linked file resource that doesn't exist in the file system
	 */
	public void testMoveMissingFile() {
		IPath location = getRandomLocation();
		IFile linkedFile = nonExistingFileInExistingProject;
		try {
			linkedFile.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		IFile dest = existingProject.getFile("FailedMoveDest");
		try {
			linkedFile.move(dest.getFullPath(), IResource.NONE, getMonitor());
			fail("2.0");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.1", !dest.exists());
		try {
			linkedFile.move(dest.getFullPath(), IResource.FORCE, getMonitor());
			fail("2.2");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.3", !dest.exists());
	}

	/**
	 * Tests moving a linked folder that doesn't exist in the file system
	 */
	public void testMoveMissingFolder() {
		IPath location = getRandomLocation();
		IFolder linkedFolder = nonExistingFolderInExistingProject;
		try {
			linkedFolder.createLink(location, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		IFolder dest = existingProject.getFolder("FailedMoveDest");
		try {
			linkedFolder.move(dest.getFullPath(), IResource.NONE, getMonitor());
			fail("2.0");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.1", !dest.exists());
		try {
			linkedFolder.move(dest.getFullPath(), IResource.FORCE, getMonitor());
			fail("2.2");
		} catch (CoreException e1) {
			//should fail
		}
		assertTrue("2.3", !dest.exists());
	}

	public void testMoveProjectWithLinks() {
		IPath fileLocation = getRandomLocation();
		IFile file = nonExistingFileInExistingProject;
		IFolder folder = nonExistingFolderInExistingProject;
		IFile childFile = folder.getFile(childName);
		IResource[] oldResources = new IResource[] {file, folder, existingProject, childFile};
		try {
			try {
				createFileInFileSystem(resolve(fileLocation));
				folder.createLink(localFolder, IResource.NONE, getMonitor());
				file.createLink(fileLocation, IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("1.0", e);
			}

			//move the project
			IProject destination = getWorkspace().getRoot().getProject("MoveTargetProject");
			IFile newFile = destination.getFile(file.getProjectRelativePath());
			IFolder newFolder = destination.getFolder(folder.getProjectRelativePath());
			IFile newChildFile = newFolder.getFile(childName);
			IResource[] newResources = new IResource[] {destination, newFile, newFolder, newChildFile};

			assertDoesNotExistInWorkspace("2.0", destination);

			try {
				existingProject.move(destination.getFullPath(), IResource.SHALLOW, getMonitor());
			} catch (CoreException e) {
				fail("2.1", e);
			}
			assertExistsInWorkspace("3.0", newResources);
			assertDoesNotExistInWorkspace("3.1", oldResources);

			assertTrue("3.2", newFile.isLinked());
			assertEquals("3.3", resolve(fileLocation), newFile.getLocation());

			assertTrue("3.4", newFolder.isLinked());
			assertEquals("3.5", resolve(localFolder), newFolder.getLocation());

			assertTrue("3.6", destination.isSynchronized(IResource.DEPTH_INFINITE));

			//now do a deep move back to the original project
			try {
				destination.move(existingProject.getFullPath(), IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("5.0", e);
			}
			assertExistsInWorkspace("5.1", oldResources);
			assertDoesNotExistInWorkspace("5.2", newResources);
			assertTrue("5.3", !file.isLinked());
			assertTrue("5.4", !folder.isLinked());
			assertEquals("5.5", existingProject.getLocation().append(file.getProjectRelativePath()), file.getLocation());
			assertEquals("5.6", existingProject.getLocation().append(folder.getProjectRelativePath()), folder.getLocation());
			assertTrue("5.7", existingProject.isSynchronized(IResource.DEPTH_INFINITE));
			assertTrue("5.8", destination.isSynchronized(IResource.DEPTH_INFINITE));
		} finally {
			Workspace.clear(resolve(fileLocation).toFile());
		}
	}

	/**
	 * Tests bug 117402.
	 */
	public void testMoveProjectWithLinks2() {
		IPath fileLocation = getRandomLocation();
		IFile linkedFile = existingProject.getFile("(test)");
		try {
			try {
				createFileInFileSystem(resolve(fileLocation), getRandomContents());
				linkedFile.createLink(fileLocation, IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("1.0", e);
			}

			//move the project
			IProject destination = getWorkspace().getRoot().getProject("CopyTargetProject");
			try {
				existingProject.move(destination.getFullPath(), IResource.SHALLOW, getMonitor());
			} catch (CoreException e) {
				fail("2.0", e);
			}

			IFile newFile = destination.getFile(linkedFile.getProjectRelativePath());
			assertTrue("3.0", newFile.isLinked());
			assertEquals("3.1", resolve(fileLocation), newFile.getLocation());
		} finally {
			Workspace.clear(resolve(fileLocation).toFile());
		}
	}

	/**
	 * Tests bug 298849.
	 */
	public void testMoveFolderWithLinks() {
		// create a folder
		IFolder folderWithLinks = existingProject.getFolder(getUniqueString());
		try {
			folderWithLinks.create(true, true, getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}

		IPath fileLocation = getRandomLocation();
		try {
			createFileInFileSystem(resolve(fileLocation), getRandomContents());

			// create a linked file in the folder
			IFile linkedFile = folderWithLinks.getFile(getUniqueString());
			try {
				linkedFile.createLink(fileLocation, IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("2.0", e);
			}

			// there should be an entry in .project for the linked file
			String string = readStringInFileSystem(existingProject.getFile(".project"));
			assertTrue("3.0", string.indexOf(linkedFile.getProjectRelativePath().toString()) != -1);

			// move the folder
			try {
				folderWithLinks.move(otherExistingProject.getFolder(getUniqueString()).getFullPath(), IResource.SHALLOW | IResource.ALLOW_MISSING_LOCAL, getMonitor());
			} catch (CoreException e) {
				fail("4.0", e);
			}

			// both the folder and link in the source project should not exist
			assertFalse("5.0", folderWithLinks.exists());
			assertFalse("6.0", linkedFile.exists());

			// the project description should not contain links
			HashMap<IPath, LinkDescription> links = null;
			try {
				links = ((ProjectDescription) existingProject.getDescription()).getLinks();
			} catch (CoreException e) {
				fail("7.0", e);
			}
			assertNull("8.0", links);

			// and the entry from .project should be removed
			string = readStringInFileSystem(existingProject.getFile(".project"));
			assertEquals("9.0", -1, string.indexOf(linkedFile.getProjectRelativePath().toString()));
		} finally {
			Workspace.clear(resolve(fileLocation).toFile());
		}
	}

	public void testNatureVeto() {
		//note: simpleNature has the link veto turned on.

		//test create link on project with nature veto
		try {
			IProjectDescription description = existingProject.getDescription();
			description.setNatureIds(new String[] {NATURE_SIMPLE});
			existingProject.setDescription(description, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		try {
			nonExistingFolderInExistingProject.createLink(localFolder, IResource.NONE, getMonitor());
			fail("1.1");
		} catch (CoreException e) {
			//should fail
		}
		try {
			nonExistingFileInExistingProject.createLink(localFile, IResource.NONE, getMonitor());
			fail("1.2");
		} catch (CoreException e) {
			//should fail
		}

		//test add nature with veto to project that already has link
		try {
			existingProject.delete(IResource.FORCE, getMonitor());
			existingProject.create(getMonitor());
			existingProject.open(getMonitor());
			nonExistingFolderInExistingProject.createLink(localFolder, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		try {
			IProjectDescription description = existingProject.getDescription();
			description.setNatureIds(new String[] {NATURE_SIMPLE});
			existingProject.setDescription(description, IResource.NONE, getMonitor());
			fail("3.0");
		} catch (CoreException e) {
			//should fail
		}
	}

	/**
	 * Tests creating a link within a link, and ensuring that both links still
	 * exist when the project is closed/opened (bug 177367).
	 */
	public void testNestedLink() {
		final IFileStore store1 = getTempStore();
		final IFileStore store2 = getTempStore();
		URI location1 = store1.toURI();
		URI location2 = store2.toURI();
		//folder names are important here, because we want a certain order in the link hash map
		IFolder link = existingProject.getFolder("aA");
		IFolder linkChild = link.getFolder("b");
		try {
			store1.mkdir(EFS.NONE, getMonitor());
			store2.mkdir(EFS.NONE, getMonitor());
			link.createLink(location1, IResource.NONE, getMonitor());
			linkChild.createLink(location2, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("0.99", e);
		}
		assertTrue("1.0", link.exists());
		assertTrue("1.1", link.isLinked());
		assertTrue("1.2", linkChild.exists());
		assertTrue("1.3", linkChild.isLinked());
		assertEquals("1.4", location1, link.getLocationURI());
		assertEquals("1.5", location2, linkChild.getLocationURI());

		//now delete and recreate the project
		try {
			existingProject.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, getMonitor());
			existingProject.create(getMonitor());
			existingProject.open(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		assertTrue("2.0", link.exists());
		assertTrue("2.1", link.isLinked());
		assertTrue("2.2", linkChild.exists());
		assertTrue("2.3", linkChild.isLinked());
		assertEquals("2.4", location1, link.getLocationURI());
		assertEquals("2.5", location2, linkChild.getLocationURI());

	}

	/**
	 * Create a project with a linked resource at depth > 2, and refresh it.
	 */
	public void testRefreshDeepLink() {
		IFolder link = nonExistingFolderInExistingFolder;
		IPath linkLocation = localFolder;
		IPath localChild = linkLocation.append("Child");
		IFile linkChild = link.getFile(localChild.lastSegment());
		createFileInFileSystem(resolve(localChild));
		try {
			link.createLink(linkLocation, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("0.99", e);
		}
		assertTrue("1.0", link.exists());
		assertTrue("1.1", linkChild.exists());

		try {
			IProject project = link.getProject();
			project.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}

		assertTrue("2.0", link.exists());
		assertTrue("2.1", linkChild.exists());
	}

	public void testLinkedFolderWithOverlappingLocation_Bug293935_() {
		IWorkspace workspace = getWorkspace();

		IPath projectLocation = existingProject.getLocation();
		IFolder folderByIPath = existingProject.getFolder("overlappingLinkedFolderByIPath");
		assertTrue("1.1", !workspace.validateLinkLocation(folderByIPath, projectLocation).isOK());
		try {
			folderByIPath.createLink(projectLocation, IResource.NONE, getMonitor());
			fail("1.2");
		} catch (CoreException e) {
			// expected to fail
		}

		URI projectLocationURI = existingProject.getLocationURI();
		IFolder folderByURI = existingProject.getFolder("overlappingLinkedFolderByURI");
		assertTrue("2.1", !workspace.validateLinkLocationURI(folderByURI, projectLocationURI).isOK());
		try {
			folderByURI.createLink(projectLocationURI, IResource.NONE, getMonitor());
			fail("2.2");
		} catch (CoreException e) {
			// expected to fail just like when creating link by IPath
		}

		// device is missing

		IPath projectLocationWithoutDevice = projectLocation.setDevice(null);
		IFolder folderByUnixLikeIPath = existingProject.getFolder("overlappingLinkedFolderByUnixLikeIPath");
		assertTrue("3.1", !workspace.validateLinkLocation(folderByUnixLikeIPath, projectLocationWithoutDevice).isOK());
		try {
			folderByUnixLikeIPath.createLink(projectLocationWithoutDevice, IResource.NONE, getMonitor());
			fail("3.2");
		} catch (CoreException e) {
			// expected to fail
		}

		URI projectLocationURIWithoutDevice = URIUtil.toURI(projectLocationWithoutDevice.toString());
		IFolder folderByUnixLikeURI = existingProject.getFolder("overlappingLinkedFolderByUnixLikeURI");
		assertTrue("4.1", !workspace.validateLinkLocationURI(folderByUnixLikeURI, projectLocationURIWithoutDevice).isOK());
		try {
			folderByUnixLikeURI.createLink(projectLocationURIWithoutDevice, IResource.NONE, getMonitor());
			fail("4.2");
		} catch (CoreException e) {
			// expected to fail
		}
	}

	public void testLinkedFolderWithSymlink_Bug338010() {
		// Only activate this test if testing of symbolic links is possible.
		if (!canCreateSymLinks()) {
			return;
		}
		IPath baseLocation = getRandomLocation();
		IPath resolvedBaseLocation = resolve(baseLocation);
		deleteOnTearDown(resolvedBaseLocation);
		IPath symlinkTarget = resolvedBaseLocation.append("dir1/target");
		symlinkTarget.toFile().mkdirs();
		createSymLink(resolvedBaseLocation.toFile(), "symlink", symlinkTarget.toOSString(), true);
		IPath linkChildLocation = baseLocation.append("symlink/dir2");
		IPath resolvedLinkChildLocation = resolve(linkChildLocation);
		File linkChild = resolvedLinkChildLocation.toFile();
		linkChild.mkdir();
		assertTrue("Could not create link at location: " + linkChild, linkChild.exists());

		IFolder folder = nonExistingFolderInExistingProject;
		try {
			folder.createLink(linkChildLocation, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}
		// Check that the symlink is preserved.
		assertEquals("1.2", resolvedLinkChildLocation, folder.getLocation());
	}

	/**
	 * Tests deleting of the target of a linked folder that itself is a symbolic link.
	 */
	public void testDeleteLinkTarget_Bug507084() throws Exception {
		// Only activate this test if testing of symbolic links is possible.
		if (!canCreateSymLinks()) {
			return;
		}
		IPath baseLocation = getRandomLocation();
		IPath resolvedBaseLocation = resolve(baseLocation);
		deleteOnTearDown(resolvedBaseLocation);
		IPath symlinkTarget = resolvedBaseLocation.append("dir1/A");
		symlinkTarget.append("B/C").toFile().mkdirs();
		IPath linkParentDir = resolvedBaseLocation.append("dir2");
		linkParentDir.toFile().mkdirs();
		createSymLink(linkParentDir.toFile(), "symlink", symlinkTarget.toOSString(), true);

		IFolder folder = nonExistingFolderInExistingProject;
		IPath symLink = linkParentDir.append("symlink");
		folder.createLink(symLink, IResource.NONE, getMonitor());
		assertTrue("1.1", folder.exists());
		assertTrue("1.2", folder.getFolder("B/C").exists());
		assertEquals("1.3", symLink, folder.getLocation());
		// Delete the symlink and the directory that contains it.
		symLink.toFile().delete();
		linkParentDir.toFile().delete();
		// Check that the directory that contained the symlink has been deleted.
		assertFalse("2.1", linkParentDir.toFile().exists());
		// Refresh the project.
		folder.getParent().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		// Check that the linked folder still exists.
		assertTrue("3.1", folder.exists());
		// Check that the contents of the linked folder no longer exist.
		assertFalse("3.2", folder.getFolder("B").exists());
		assertFalse("3.3", folder.getFolder("B/C").exists());
	}
}
