/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Martin Oberhuber (Wind River) - testImportWrongLineEndings() for bug [210664]
 *     Serge Beauchamp (Freescale Semiconductor) - [229633] Add Project Path Variables
 *******************************************************************************/

package org.eclipse.core.tests.resources;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.tests.harness.FileSystemHelper;

/**
 * This class extends <code>LinkedResourceTest</code> in order to use
 * randomly generated locations that are always variable-based.
 * TODO: add tests specific to linking resources using path variables (then
 * removing the variable, change the variable value, etc)
 */
public class LinkedResourceWithPathVariableTest extends LinkedResourceTest {

	private final static String VARIABLE_NAME = "ROOT";
	private final static String PROJECT_VARIABLE_NAME = "PROOT";
	private final static String PROJECT_RELATIVE_VARIABLE_NAME = "RELATIVE_PROOT";
	private final static String PROJECT_RELATIVE_VARIABLE_VALUE = "${PROOT}";
	private final ArrayList<IPath> toDelete = new ArrayList<>();
	private IFileStore toSetWritable = null;

	@Override
	protected void setUp() throws Exception {
		IPath base = super.getRandomLocation();
		toDelete.add(base);
		getWorkspace().getPathVariableManager().setValue(VARIABLE_NAME, base);
		base = super.getRandomLocation();
		toDelete.add(base);
		super.setUp();
		existingProject.getPathVariableManager().setValue(PROJECT_VARIABLE_NAME, base);
		existingProject.getPathVariableManager().setValue(PROJECT_RELATIVE_VARIABLE_NAME,
				IPath.fromPortableString(PROJECT_RELATIVE_VARIABLE_VALUE));
	}

	@Override
	protected void tearDown() throws Exception {
		if (toSetWritable != null) {
			IFileInfo info = toSetWritable.fetchInfo();
			info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false);
			toSetWritable.putInfo(info, EFS.SET_ATTRIBUTES, getMonitor());
			toSetWritable = null;
		}
		getWorkspace().getPathVariableManager().setValue(VARIABLE_NAME, null);
		IPath[] paths = toDelete.toArray(new IPath[toDelete.size()]);
		toDelete.clear();
		for (IPath path : paths) {
			Workspace.clear(path.toFile());
		}
		super.tearDown();
	}

	/**
	 * Copy file "inStore" into file "outStore", converting line endings as follows:
	 * <ul>
	 *   <li>DOS, or MAC (CR or CRLF) into UNIX (LF)</li>
	 *   <li>UNIX (LF) into DOS (CRLF)</li>
	 * </ul>
	 * @param inStore handle to an existing text file to convert
	 * @param outStore handle to non-existing file which will be written
	 */
	protected void convertLineEndings(IFileStore inStore, IFileStore outStore, IProgressMonitor mon) throws CoreException, IOException {
		InputStream is = null;
		OutputStream os = null;
		try {
			is = inStore.openInputStream(EFS.NONE, mon);
			os = outStore.openOutputStream(EFS.NONE, new NullProgressMonitor());
			int prevb = 0;
			int ib = is.read();
			while (ib >= 0) {
				switch (ib) {
					case '\r' :
						os.write('\n');
						break;
					case '\n' :
						if (prevb != '\r') { /* not converted already */
							os.write('\r');
							os.write('\n');
						}
						break;
					default :
						os.write(ib);
						break;
				}
				prevb = ib;
				ib = is.read();
			}
		} finally {
			if (is != null) {
				is.close();
			}
			if (os != null) {
				os.close();
			}
		}
	}

	@Override
	public IPath getRandomLocation() {
		IPathVariableManager pathVars = getWorkspace().getPathVariableManager();
		//low order bits are current time, high order bits are static counter
		IPath parent = IPath.fromOSString(VARIABLE_NAME);
		IPath path = FileSystemHelper.computeRandomLocation(parent);
		while (pathVars.resolvePath(path).toFile().exists()) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// ignore
			}
			path = FileSystemHelper.computeRandomLocation(parent);
		}
		toDelete.add(pathVars.resolvePath(path));
		return path;
	}

	public IPath getRandomProjectLocation() {
		IPathVariableManager pathVars = getWorkspace().getPathVariableManager();
		// low order bits are current time, high order bits are static counter
		IPath parent = IPath.fromOSString(PROJECT_VARIABLE_NAME);
		IPath path = FileSystemHelper.computeRandomLocation(parent);
		while (pathVars.resolvePath(path).toFile().exists()) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// ignore
			}
			path = FileSystemHelper.computeRandomLocation(parent);
		}
		toDelete.add(pathVars.resolvePath(path));
		return path;
	}

	public IPath getRandomRelativeProjectLocation() {
		IPathVariableManager pathVars = getWorkspace().getPathVariableManager();
		// low order bits are current time, high order bits are static counter
		IPath parent = IPath.fromOSString(PROJECT_RELATIVE_VARIABLE_NAME);
		IPath path = FileSystemHelper.computeRandomLocation(parent);
		while (pathVars.resolvePath(path).toFile().exists()) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// ignore
			}
			path = FileSystemHelper.computeRandomLocation(parent);
		}
		toDelete.add(pathVars.resolvePath(path));
		return path;
	}

	@Override
	protected IPath resolve(IPath path) {
		return getWorkspace().getPathVariableManager().resolvePath(path);
	}

	@Override
	protected URI resolve(URI uri) {
		return getWorkspace().getPathVariableManager().resolveURI(uri);
	}

	public void testProjectResolution() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();
		IPath value = manager.getValue(PROJECT_VARIABLE_NAME);
		IPath relativeValue = manager.getValue(PROJECT_RELATIVE_VARIABLE_NAME);

		assertTrue("1.0", !value.equals(relativeValue));

		IPath resolvedValue = manager.resolvePath(value);
		assertTrue("1.1", value.equals(resolvedValue));

		IPath resolvedRelativeValue = manager.resolvePath(relativeValue);
		assertTrue("1.2", !relativeValue.equals(resolvedRelativeValue));

		assertTrue("1.3", resolvedValue.equals(resolvedRelativeValue));
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * removed.
	 */
	public void testFileVariableRemoved() {
		final IPathVariableManager manager = getWorkspace().getPathVariableManager();

		IFile file = nonExistingFileInExistingProject;
		IPath existingValue = manager.getValue(VARIABLE_NAME);

		// creates a variable-based location
		IPath variableBasedLocation = getRandomLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		// removes the variable - the location will be undefined (null)
		try {
			manager.setValue(VARIABLE_NAME, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", file);

		//refresh local - should not fail or make the link disappear
		try {
			file.refreshLocal(IResource.DEPTH_ONE, getMonitor());
			file.getProject().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("3.2");
		}

		assertExistsInWorkspace("3.3", file);

		// try to change resource's contents
		try {
			file.setContents(getContents("new contents"), IResource.NONE, null);
			// Resource has no-defined location - should fail
			fail("3.4");
		} catch (CoreException re) {
			// success: resource had no defined location
		}

		assertExistsInWorkspace("3.5", file);
		// the location is null
		assertNull("3.6", file.getLocation());

		// try validating another link location while there is a link with null location
		IFile other = existingProject.getFile("OtherVar");
		getWorkspace().validateLinkLocation(other, getRandomLocation());

		// re-creates the variable with its previous value
		try {
			manager.setValue(VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("4.0", e);
		}

		assertExistsInWorkspace("5.0", file);
		assertNotNull("5.1", file.getLocation());
		assertExistsInFileSystem("5.2", file);
		// the contents must be the original ones
		try {
			assertTrue("5.3", compareContent(file.getContents(true), getContents("contents for a file")));
		} catch (CoreException e) {
			fail("5.4", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * removed.
	 */
	public void testFileProjectVariableRemoved() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();

		IFile file = nonExistingFileInExistingProject;
		IPath existingValue = manager.getValue(PROJECT_VARIABLE_NAME);

		// creates a variable-based location
		IPath variableBasedLocation = getRandomProjectLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		// removes the variable - the location will be undefined (null)
		try {
			manager.setValue(PROJECT_VARIABLE_NAME, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", file);

		// refresh local - should not fail or make the link disappear
		try {
			file.refreshLocal(IResource.DEPTH_ONE, getMonitor());
			file.getProject().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("3.2");
		}

		assertExistsInWorkspace("3.3", file);

		// try to change resource's contents
		try {
			file.setContents(getContents("new contents"), IResource.NONE, null);
			// Resource has no-defined location - should fail
			fail("3.4");
		} catch (CoreException re) {
			// success: resource had no defined location
		}

		assertExistsInWorkspace("3.5", file);
		// the location is null
		assertNull("3.6", file.getLocation());

		// try validating another link location while there is a link with null
		// location
		IFile other = existingProject.getFile("OtherVar");
		getWorkspace().validateLinkLocation(other, getRandomLocation());

		// re-creates the variable with its previous value
		try {
			manager.setValue(PROJECT_VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("4.0", e);
		}

		assertExistsInWorkspace("5.0", file);
		assertNotNull("5.1", file.getLocation());
		assertExistsInFileSystem("5.2", file);
		// the contents must be the original ones
		try {
			assertTrue("5.3", compareContent(file.getContents(true), getContents("contents for a file")));
		} catch (CoreException e) {
			fail("5.4", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * moved to a new project.
	 * This is a regression test for bug 266679
	 */
	public void testMoveFileToDifferentProject() {

		IFile file = existingProjectInSubDirectory.getFile("my_link");

		// creates a variable-based location
		IPath variableBasedLocation = null;
		IPath targetPath = existingProjectInSubDirectory.getLocation().removeLastSegments(1).append("outside.txt");
		if (!targetPath.toFile().exists()) {
			try {
				targetPath.toFile().createNewFile();
			} catch (IOException e2) {
				fail("0.4", e2);
			}
		}
		toDelete.add(targetPath);

		try {
			variableBasedLocation = convertToRelative(targetPath, file, true, null);
		} catch (CoreException e1) {
			fail("0.99", e1);
		}

		IPath resolvedPath = URIUtil.toPath(file.getPathVariableManager().resolveURI(URIUtil.toURI(variableBasedLocation)));
		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}

		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		IFile newFile = nonExistingFileInExistingFolder;
		try {
			file.move(newFile.getFullPath(), IResource.SHALLOW, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", newFile);
		assertTrue("3,2", !newFile.getLocation().equals(newFile.getRawLocation()));
		assertEquals("3,3", newFile.getLocation(), resolvedPath);
	}

	private IPath convertToRelative(IPath path, IResource res, boolean force, String variableHint) throws CoreException {
		return URIUtil.toPath(res.getPathVariableManager().convertToRelative(URIUtil.toURI(path), force, variableHint));
	}

	/**
	 * Tests a scenario where a variable used in a linked file location that is
	 * relative to PROJECT_LOC is moved to a different project.
	 * This is a regression test for bug 266679
	 */
	public void testPROJECT_LOC_MoveFileToDifferentProject() {

		String[] existingVariables = nonExistingFileInExistingFolder.getProject().getPathVariableManager().getPathVariableNames();
		for (String existingVariable : existingVariables) {
			try {
				nonExistingFileInExistingFolder.getProject().getPathVariableManager().setValue(existingVariable, null);
			} catch (CoreException e) {
			}
		}
		IFile file = existingProjectInSubDirectory.getFile("my_link2");

		// creates a variable-based location
		IPath variableBasedLocation = null;
		IPath targetPath = existingProjectInSubDirectory.getLocation().removeLastSegments(3).append("outside.txt");
		if (!targetPath.toFile().exists()) {
			try {
				targetPath.toFile().createNewFile();
			} catch (IOException e2) {
				fail("0.4", e2);
			}
		}
		toDelete.add(targetPath);

		try {
			existingProjectInSubDirectory.getPathVariableManager().setValue("P_RELATIVE",
					IPath.fromPortableString("${PARENT-3-PROJECT_LOC}"));
			variableBasedLocation = IPath.fromPortableString("P_RELATIVE/outside.txt");
		} catch (CoreException e1) {
			fail("0.99", e1);
		}

		IPath resolvedPath = existingProjectInSubDirectory.getPathVariableManager().resolvePath(variableBasedLocation);
		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}

		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		IFile newFile = nonExistingFileInExistingFolder;
		try {
			file.move(newFile.getFullPath(), IResource.SHALLOW, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", newFile);
		IPath newLocation = newFile.getLocation();
		assertTrue("3,2", !newLocation.equals(newFile.getRawLocation()));
		IPath newRawLocation = newFile.getRawLocation();
		/* we cannot test the value of the location since the test machines generate an incorrect value
		IPath newValue = newFile.getProject().getPathVariableManager().getValue("P_RELATIVE");
		assertEquals("3,3", Path.fromPortableString("${PARENT-1-PROJECT_LOC}/sub"), newValue);
		*/
		assertTrue("3,4", newRawLocation.equals(variableBasedLocation));
		assertTrue("3,5", newLocation.equals(resolvedPath));
	}

	/**
	 * Tests a scenario where a linked file location is
	 * is moved to a new project.
	 */
	public void testMoveFileProjectVariable() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();

		IFile file = nonExistingFileInExistingProject;

		// creates a variable-based location
		IPath variableBasedLocation = getRandomProjectLocation();

		IPath resolvedPath = manager.resolvePath(variableBasedLocation);
		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		IFile newFile = nonExistingFileInExistingFolder;
		// removes the variable - the location will be undefined (null)
		try {
			file.move(newFile.getFullPath(), IResource.SHALLOW, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", newFile);
		assertTrue("3,2", !newFile.getLocation().equals(newFile.getRawLocation()));
		assertTrue("3,3", newFile.getRawLocation().equals(variableBasedLocation));
		assertTrue("3,4", newFile.getRawLocation().equals(variableBasedLocation));
		assertTrue("3,5", newFile.getLocation().equals(resolvedPath));
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * removed.
	 */
	public void testMoveFileToNewProjectProjectVariable() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();

		IFile file = nonExistingFileInExistingProject;

		// creates a variable-based location
		IPath variableBasedLocation = getRandomRelativeProjectLocation();

		IPath resolvedPath = manager.resolvePath(variableBasedLocation);
		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		IFile newFile = nonExistingFileInOtherExistingProject;
		// moves the variable - the location will be undefined (null)
		try {
			file.move(newFile.getFullPath(), IResource.SHALLOW, getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", newFile);
		assertTrue("3,2", !newFile.getLocation().equals(newFile.getRawLocation()));
		assertTrue("3,3", newFile.getRawLocation().equals(variableBasedLocation));
		assertTrue("3,4", newFile.getLocation().equals(resolvedPath));
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * removed.
	 */
	public void testFileProjectRelativeVariableRemoved() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();

		IFile file = nonExistingFileInExistingProject;
		IPath existingValue = manager.getValue(PROJECT_RELATIVE_VARIABLE_NAME);

		// creates a variable-based location
		IPath variableBasedLocation = getRandomRelativeProjectLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		// removes the variable - the location will be undefined (null)
		try {
			manager.setValue(PROJECT_RELATIVE_VARIABLE_NAME, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3,1", file);

		// refresh local - should not fail or make the link disappear
		try {
			file.refreshLocal(IResource.DEPTH_ONE, getMonitor());
			file.getProject().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("3.2");
		}

		assertExistsInWorkspace("3.3", file);

		// try to change resource's contents
		try {
			file.setContents(getContents("new contents"), IResource.NONE, null);
			// Resource has no-defined location - should fail
			fail("3.4");
		} catch (CoreException re) {
			// success: resource had no defined location
		}

		assertExistsInWorkspace("3.5", file);
		// the location is null
		assertNull("3.6", file.getLocation());

		// try validating another link location while there is a link with null
		// location
		IFile other = existingProject.getFile("OtherVar");
		getWorkspace().validateLinkLocation(other, getRandomLocation());

		// re-creates the variable with its previous value
		try {
			manager.setValue(PROJECT_RELATIVE_VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("4.0", e);
		}

		assertExistsInWorkspace("5.0", file);
		assertNotNull("5.1", file.getLocation());
		assertExistsInFileSystem("5.2", file);
		// the contents must be the original ones
		try {
			assertTrue("5.3", compareContent(file.getContents(true), getContents("contents for a file")));
		} catch (CoreException e) {
			fail("5.4", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked folder location is
	 * removed.
	 */
	public void testFolderVariableRemoved() {
		final IPathVariableManager manager = getWorkspace().getPathVariableManager();

		IFolder folder = nonExistingFolderInExistingProject;
		IFile childFile = folder.getFile(childName);
		IPath existingValue = manager.getValue(VARIABLE_NAME);

		// creates a variable-based location
		IPath variableBasedLocation = getRandomLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", folder);

		try {
			folder.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
			childFile.create(getRandomContents(), IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			childFile.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", folder);
		assertExistsInWorkspace("2.1", childFile);
		assertExistsInFileSystem("2.2", folder);
		assertExistsInFileSystem("2.3", childFile);

		// removes the variable - the location will be undefined (null)
		try {
			manager.setValue(VARIABLE_NAME, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3.1", folder);

		//refresh local - should not fail but should cause link's children to disappear
		try {
			folder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			folder.getProject().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("3.2", e);
		}
		assertExistsInWorkspace("3.3", folder);
		assertDoesNotExistInWorkspace("3.4", childFile);

		//try to copy a file to the folder
		IFile destination = folder.getFile(existingFileInExistingProject.getName());
		try {
			existingFileInExistingProject.copy(destination.getFullPath(), IResource.NONE, getMonitor());
			//should fail
			fail("3.5");
		} catch (CoreException e) {
			//expected
		}
		assertTrue("3.6", !destination.exists());

		//try to create a sub-file
		try {
			destination.create(getRandomContents(), IResource.NONE, getMonitor());
			//should fail
			fail("3.7");
		} catch (CoreException e) {
			//expected
		}

		//try to create a sub-folder
		IFolder subFolder = folder.getFolder("SubFolder");
		try {
			subFolder.create(IResource.NONE, true, getMonitor());
			//should fail
			fail("3.8");
		} catch (CoreException e) {
			//expected
		}

		// try to change resource's contents
		try {
			childFile.setContents(getContents("new contents"), IResource.NONE, null);
			// Resource has no-defined location - should fail
			fail("4.0");
		} catch (CoreException re) {
			// success: resource had no defined location
		}

		assertExistsInWorkspace("4.1", folder);
		// the location is null
		assertNull("4.2", folder.getLocation());

		// re-creates the variable with its previous value
		try {
			manager.setValue(VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("5.0", e);
		}

		assertExistsInWorkspace("6.0", folder);
		assertNotNull("6.1", folder.getLocation());
		assertExistsInFileSystem("6.2", folder);
		assertDoesNotExistInWorkspace("6.3", childFile);
		assertExistsInFileSystem("6.4", childFile);

		// refresh should recreate the child
		try {
			folder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("7.0", e);
		}
		assertExistsInWorkspace("7.1", folder);
		assertExistsInWorkspace("7.2", childFile);
	}

	/**
	 * Tests importing a project with a Linked Resource and Path Variable,
	 * where the line endings in the .project file do not match the local
	 * Platform.
	 * The .project file must not be modified on import, especially if it
	 * is marked read-only.
	 * See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=210664">Bug 210664</a>.
	 */
	public void testImportWrongLineEndings_Bug210664() throws IOException {
		// Choose a project to work on
		IProject proj = existingProject;
		IFileStore projStore = null;
		IPath randomLocationWithPathVariable = getRandomLocation();

		try {
			projStore = EFS.getStore(proj.getLocationURI());
		} catch (CoreException e) {
			fail("1.0", e);
		}

		// Don't run this test if we cannot set a file read-only
		if ((projStore.getFileSystem().attributes() & EFS.ATTRIBUTE_READ_ONLY) == 0) {
			return;
		}

		try {
			// Create a linked resource with a non-existing path variable
			IFolder folder = proj.getFolder("SOME_LINK");
			folder.createLink(randomLocationWithPathVariable, IResource.ALLOW_MISSING_LOCAL, null);

			// Close the project, and convert line endings
			IFileStore projFile = projStore.getChild(".project");
			proj.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, getMonitor());
			IFileStore projNew = projStore.getChild(".project.new");
			convertLineEndings(projFile, projNew, getMonitor());

			// Set the project read-only
			projNew.move(projFile, EFS.OVERWRITE, getMonitor());
			IFileInfo info = projFile.fetchInfo(EFS.NONE, getMonitor());
			info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, true);
			projFile.putInfo(info, EFS.SET_ATTRIBUTES, getMonitor());
			toSetWritable = projFile; /* for cleanup */
		} catch (CoreException e) {
			fail("2.0", e);
		}

		try {
			//Bug 210664: Open project with wrong line endings and non-existing path variable
			proj.create(null);
			proj.open(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked folder location is
	 * removed.
	 */
	public void testFolderProjectVariableRemoved() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();

		IFolder folder = nonExistingFolderInExistingProject;
		IFile childFile = folder.getFile(childName);
		IPath existingValue = manager.getValue(PROJECT_VARIABLE_NAME);

		// creates a variable-based location
		IPath variableBasedLocation = getRandomProjectLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", folder);

		try {
			folder.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, null);
			childFile.create(getRandomContents(), IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			childFile.setContents(getContents("contents for a file"), IResource.FORCE, null);
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", folder);
		assertExistsInWorkspace("2.1", childFile);
		assertExistsInFileSystem("2.2", folder);
		assertExistsInFileSystem("2.3", childFile);

		// removes the variable - the location will be undefined (null)
		try {
			manager.setValue(PROJECT_VARIABLE_NAME, null);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertExistsInWorkspace("3.1", folder);

		// refresh local - should not fail but should cause link's children to
		// disappear
		try {
			folder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			folder.getProject().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("3.2", e);
		}
		assertExistsInWorkspace("3.3", folder);
		assertDoesNotExistInWorkspace("3.4", childFile);

		// try to copy a file to the folder
		IFile destination = folder.getFile(existingFileInExistingProject.getName());
		try {
			existingFileInExistingProject.copy(destination.getFullPath(), IResource.NONE, getMonitor());
			// should fail
			fail("3.5");
		} catch (CoreException e) {
			// expected
		}
		assertTrue("3.6", !destination.exists());

		// try to create a sub-file
		try {
			destination.create(getRandomContents(), IResource.NONE, getMonitor());
			// should fail
			fail("3.7");
		} catch (CoreException e) {
			// expected
		}

		// try to create a sub-folder
		IFolder subFolder = folder.getFolder("SubFolder");
		try {
			subFolder.create(IResource.NONE, true, getMonitor());
			// should fail
			fail("3.8");
		} catch (CoreException e) {
			// expected
		}

		// try to change resource's contents
		try {
			childFile.setContents(getContents("new contents"), IResource.NONE, null);
			// Resource has no-defined location - should fail
			fail("4.0");
		} catch (CoreException re) {
			// success: resource had no defined location
		}

		assertExistsInWorkspace("4.1", folder);
		// the location is null
		assertNull("4.2", folder.getLocation());

		// re-creates the variable with its previous value
		try {
			manager.setValue(PROJECT_VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("5.0", e);
		}

		assertExistsInWorkspace("6.0", folder);
		assertNotNull("6.1", folder.getLocation());
		assertExistsInFileSystem("6.2", folder);
		assertDoesNotExistInWorkspace("6.3", childFile);
		assertExistsInFileSystem("6.4", childFile);

		// refresh should recreate the child
		try {
			folder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
			fail("7.0", e);
		}
		assertExistsInWorkspace("7.1", folder);
		assertExistsInWorkspace("7.2", childFile);
	}

	/**
	 * Tests scenario where links are relative to undefined variables
	 */
	public void testUndefinedVariable() {
		IPath folderLocation = IPath.fromOSString("NOVAR/folder");
		IPath fileLocation = IPath.fromOSString("NOVAR/abc.txt");
		IFile testFile = existingProject.getFile("UndefinedVar.txt");
		IFolder testFolder = existingProject.getFolder("UndefinedVarTest");

		//should fail to create links
		try {
			testFile.createLink(fileLocation, IResource.NONE, getMonitor());
			fail("1.0");
		} catch (CoreException e) {
			//should fail
		}
		try {
			testFolder.createLink(folderLocation, IResource.NONE, getMonitor());
			fail("1.1");
		} catch (CoreException e) {
			//should fail
		}

		//validate method should return warning
		assertTrue("1.2", getWorkspace().validateLinkLocation(testFolder, folderLocation).getSeverity() == IStatus.WARNING);
		assertTrue("1.3", getWorkspace().validateLinkLocation(testFile, fileLocation).getSeverity() == IStatus.WARNING);

		//should succeed with ALLOW_MISSING_LOCAL
		try {
			testFile.createLink(fileLocation, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		try {
			testFolder.createLink(folderLocation, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("2.1", e);
		}

		//copy should fail
		IPath copyFileDestination = existingProject.getFullPath().append("CopyFileDest");
		IPath copyFolderDestination = existingProject.getFullPath().append("CopyFolderDest");

		try {
			testFile.copy(copyFileDestination, IResource.NONE, getMonitor());
			fail("3.0");
		} catch (CoreException e) {
			//should fail
		}
		try {
			testFolder.copy(copyFolderDestination, IResource.NONE, getMonitor());
			fail("3.1");
		} catch (CoreException e) {
			//should fail
		}

		//move should fail
		IPath moveFileDestination = existingProject.getFullPath().append("MoveFileDest");
		IPath moveFolderDestination = existingProject.getFullPath().append("MoveFolderDest");

		try {
			testFile.move(moveFileDestination, IResource.NONE, getMonitor());
			fail("4.0");
		} catch (CoreException e) {
			//should fail
		}
		try {
			testFolder.move(moveFolderDestination, IResource.NONE, getMonitor());
			fail("4.1");
		} catch (CoreException e) {
			//should fail
		}

		//refresh local should succeed
		try {
			testFile.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			testFolder.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			testFile.refreshLocal(IResource.DEPTH_ZERO, getMonitor());
			testFolder.refreshLocal(IResource.DEPTH_ZERO, getMonitor());
			existingProject.refreshLocal(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("5.0", e);
		}

		//renaming the project shallow is ok
		try {
			IProject project = testFolder.getProject();
			IProjectDescription desc = project.getDescription();
			desc.setName("moveDest");
			project.move(desc, IResource.SHALLOW | IResource.FORCE, getMonitor());
		} catch (CoreException e) {
			fail("6.0");
		}

		//delete should succeed
		try {
			testFile.delete(IResource.NONE, getMonitor());
			testFolder.delete(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("9.0", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * changed.
	 */
	public void testVariableChanged() {
		final IPathVariableManager manager = getWorkspace().getPathVariableManager();

		IPath existingValue = manager.getValue(VARIABLE_NAME);

		IFile file = nonExistingFileInExistingProject;

		// creates a variable-based location
		IPath variableBasedLocation = getRandomLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, getMonitor());
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		// changes the variable value - the file location will change
		try {
			IPath newLocation = super.getRandomLocation();
			toDelete.add(newLocation);
			manager.setValue(VARIABLE_NAME, newLocation);
		} catch (CoreException e) {
			fail("2.2", e);
		}

		// try to change resource's contents
		try {
			file.setContents(getContents("new contents"), IResource.NONE, getMonitor());
			// Resource was out of sync - should not be able to change
			fail("3.0");
		} catch (CoreException e) {
			assertEquals("3.1", IResourceStatus.OUT_OF_SYNC_LOCAL, e.getStatus().getCode());
		}

		assertExistsInWorkspace("3.2", file);
		// the location is different - does not exist anymore
		assertDoesNotExistInFileSystem("3.3", file);

		// successfully changes resource's contents (using IResource.FORCE)
		try {
			file.setContents(getContents("contents in different location"), IResource.FORCE, getMonitor());
		} catch (CoreException e) {
			fail("4.0", e);
		}

		// now the file exists in a different location
		assertExistsInFileSystem("4.1", file);

		// its location must have changed reflecting the variable change
		IPath expectedNewLocation = manager.resolvePath(variableBasedLocation);
		IPath actualNewLocation = file.getLocation();
		assertEquals("4.2", expectedNewLocation, actualNewLocation);

		// its contents are as just set
		try {
			assertTrue("4.3", compareContent(file.getContents(), getContents("contents in different location")));
		} catch (CoreException e) {
			fail("4.4", e);
		}

		// clean-up
		ensureDoesNotExistInFileSystem(file);

		// restore the previous value
		try {
			manager.setValue(VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("5.0", e);
		}

		assertExistsInWorkspace("5.1", file);
		assertExistsInFileSystem("5.2", file);
		// the contents must be the original ones
		try {
			assertTrue("5.3", compareContent(file.getContents(true), getContents("contents for a file")));
		} catch (CoreException e) {
			fail("5.4", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * changed.
	 */
	public void testProjectVariableChanged() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();

		IPath existingValue = manager.getValue(PROJECT_VARIABLE_NAME);

		IFile file = nonExistingFileInExistingProject;

		// creates a variable-based location
		IPath variableBasedLocation = getRandomProjectLocation();

		// the file should not exist yet
		assertDoesNotExistInWorkspace("1.0", file);

		try {
			file.createLink(variableBasedLocation, IResource.ALLOW_MISSING_LOCAL, getMonitor());
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			file.setContents(getContents("contents for a file"), IResource.FORCE, getMonitor());
		} catch (CoreException e) {
			fail("1.2", e);
		}

		// now the file exists in both workspace and file system
		assertExistsInWorkspace("2.0", file);
		assertExistsInFileSystem("2.1", file);

		// changes the variable value - the file location will change
		try {
			IPath newLocation = super.getRandomLocation();
			toDelete.add(newLocation);
			manager.setValue(PROJECT_VARIABLE_NAME, newLocation);
		} catch (CoreException e) {
			fail("2.2", e);
		}

		// try to change resource's contents
		try {
			file.setContents(getContents("new contents"), IResource.NONE, getMonitor());
			// Resource was out of sync - should not be able to change
			fail("3.0");
		} catch (CoreException e) {
			assertEquals("3.1", IResourceStatus.OUT_OF_SYNC_LOCAL, e.getStatus().getCode());
		}

		assertExistsInWorkspace("3.2", file);
		// the location is different - does not exist anymore
		assertDoesNotExistInFileSystem("3.3", file);

		// successfully changes resource's contents (using IResource.FORCE)
		try {
			file.setContents(getContents("contents in different location"), IResource.FORCE, getMonitor());
		} catch (CoreException e) {
			fail("4.0", e);
		}

		// now the file exists in a different location
		assertExistsInFileSystem("4.1", file);

		// its location must have changed reflecting the variable change
		IPath expectedNewLocation = manager.resolvePath(variableBasedLocation);
		IPath actualNewLocation = file.getLocation();
		assertEquals("4.2", expectedNewLocation, actualNewLocation);

		// its contents are as just set
		try {
			assertTrue("4.3", compareContent(file.getContents(), getContents("contents in different location")));
		} catch (CoreException e) {
			fail("4.4", e);
		}

		// clean-up
		ensureDoesNotExistInFileSystem(file);

		// restore the previous value
		try {
			manager.setValue(PROJECT_VARIABLE_NAME, existingValue);
		} catch (CoreException e) {
			fail("5.0", e);
		}

		assertExistsInWorkspace("5.1", file);
		assertExistsInFileSystem("5.2", file);
		// the contents must be the original ones
		try {
			assertTrue("5.3", compareContent(file.getContents(true), getContents("contents for a file")));
		} catch (CoreException e) {
			fail("5.4", e);
		}
	}

	/**
	 * Tests a scenario where a variable used in a linked file location is
	 * changed.
	 */
	//	public void testGetPathVariable() {
	//		final IPathVariableManager manager = existingProject.getPathVariableManager();
	//		IPathVariable variable = manager.getPathVariable("PROJECT_LOC");
	//		assertTrue("1.0", variable != null);
	//		assertTrue("1.1", variable.isReadOnly());
	//		assertEquals("1.2", null, variable.getVariableHints());
	//
	//		variable = manager.getPathVariable("PROJECT_LOC_does_not_exist");
	//		assertTrue("2.0", variable == null);
	//
	//		variable = manager.getPathVariable("PARENT");
	//		assertTrue("3.0", variable != null);
	//		assertTrue("3.1", variable.isReadOnly());
	//		Object[] extensions = variable.getVariableHints();
	//		assertTrue("3.2", extensions == null);
	//
	//		try {
	//			IPath newLocation = super.getRandomLocation();
	//			toDelete.add(newLocation);
	//			manager.setValue(PROJECT_VARIABLE_NAME, newLocation);
	//		} catch (CoreException e) {
	//			fail("4.1", e);
	//		}
	//		variable = manager.getPathVariable(PROJECT_VARIABLE_NAME);
	//		assertTrue("4.0", variable != null);
	//		assertTrue("4.1", !variable.isReadOnly());
	//		assertEquals("4.2", null, variable.getVariableHints());
	//	}

	/**
	 * Test Bug 288880 - Redundant path variables generated when converting some linked resources to path variable-relative
	 */
	public void testNonRedundentPathVariablesGenerated() {
		IFile file = existingProjectInSubDirectory.getFile("my_link");

		IPathVariableManager pathVariableManager = existingProjectInSubDirectory.getPathVariableManager();

		// creates a variable-based location
		IPath variableBasedLocation = null;
		IPath targetPath = existingProjectInSubDirectory.getLocation().removeLastSegments(1).append("outside.txt");
		if (!targetPath.toFile().exists()) {
			try {
				targetPath.toFile().createNewFile();
			} catch (IOException e2) {
				fail("1.0", e2);
			}
		}
		toDelete.add(targetPath);

		try {
			variableBasedLocation = convertToRelative(targetPath, file, true, null);
		} catch (CoreException e1) {
			fail("2.0", e1);
		}
		IPath resolvedPath = URIUtil.toPath(pathVariableManager.resolveURI(URIUtil.toURI(variableBasedLocation)));
		// the file should not exist yet
		assertDoesNotExistInWorkspace("3.0", file);
		assertEquals("3.1", targetPath, resolvedPath);

		try {
			variableBasedLocation = convertToRelative(targetPath, file, true, null);
		} catch (CoreException e1) {
			fail("4.0", e1);
		}

		resolvedPath = URIUtil.toPath(pathVariableManager.resolveURI(URIUtil.toURI(variableBasedLocation)));
		// the file should not exist yet
		assertDoesNotExistInWorkspace("5.0", file);
		assertEquals("5.1", targetPath, resolvedPath);
	}

	public void testConvertToUserEditableFormat() {
		IPathVariableManager pathVariableManager = existingProject.getPathVariableManager();

		String[][] table = { // format: {internal-format, user-editable-format [, internal-format-reconverted]
				{"C:\\foo\\bar", "C:\\foo\\bar", "C:/foo/bar"}, //
				{"C:/foo/bar", "C:/foo/bar"}, //
				{"VAR/foo/bar", "VAR/foo/bar"}, //
				{"${VAR}/foo/bar", "${VAR}/foo/bar"}, //
				{"${VAR}/../foo/bar", "${VAR}/../foo/bar", "${PARENT-1-VAR}/foo/bar"}, //
				{"${PARENT-1-VAR}/foo/bar", "${VAR}/../foo/bar"}, //
				{"${PARENT-0-VAR}/foo/bar", "${VAR}/foo/bar", "${VAR}/foo/bar"}, //
				{"${PARENT-VAR}/foo/bar", "${PARENT-VAR}/foo/bar"}, //
				{"${PARENT-2}/foo/bar", "${PARENT-2}/foo/bar"}, //
				{"${PARENT}/foo/bar", "${PARENT}/foo/bar"}, //
				{"${PARENT-2-VAR}/foo/bar", "${VAR}/../../foo/bar"}, //
				{"${PARENT-2-VAR}/foo/${PARENT-4-BAR}", "${VAR}/../../foo/${BAR}/../../../.."}, //
				{"${PARENT-2-VAR}/foo${PARENT-4-BAR}", "${VAR}/../../foo${BAR}/../../../.."}, //
				{"${PARENT-2-VAR}/${PARENT-4-BAR}/foo", "${VAR}/../../${BAR}/../../../../foo"}, //
				{"${PARENT-2-VAR}/f${PARENT-4-BAR}/oo", "${VAR}/../../f${BAR}/../../../../oo"} //
		};

		for (int i = 0; i < table.length; i++) {
			String result = pathVariableManager.convertToUserEditableFormat(toOS(table[i][0]), false);
			assertEquals("1." + i, toOS(table[i][1]), result);
			String original = pathVariableManager.convertFromUserEditableFormat(result, false);
			assertEquals("2." + i, toOS(table[i].length == 2 ? table[i][0] : table[i][2]), original);
		}

		String[][] tableLocationFormat = { // format: {internal-format, user-editable-format [, internal-format-reconverted]
				{"C:\\foo\\bar", "C:\\foo\\bar", "C:/foo/bar"}, //
				{"C:/foo/bar", "C:/foo/bar"}, //
				{"VAR/foo/bar", "VAR/foo/bar"}, //
				{"${VAR}/../foo/bar", "${VAR}/../foo/bar", "PARENT-1-VAR/foo/bar"}, //
				{"PARENT-1-VAR/foo/bar", "VAR/../foo/bar"}, //
				{"PARENT-0-VAR/foo/bar", "VAR/foo/bar", "VAR/foo/bar"}, //
				{"PARENT-VAR/foo/bar", "PARENT-VAR/foo/bar"}, //
				{"PARENT-2/foo/bar", "PARENT-2/foo/bar"}, //
				{"PARENT/foo/bar", "PARENT/foo/bar"}, //
				{"PARENT-2-VAR/foo/bar", "VAR/../../foo/bar"}, //
				{"PARENT-2-VAR/foo/PARENT-4-BAR", "VAR/../../foo/PARENT-4-BAR"}, //
				{"PARENT-2-VAR/fooPARENT-4-BAR", "VAR/../../fooPARENT-4-BAR"}, //
				{"PARENT-2-VAR/PARENT-4-BAR/foo", "VAR/../../PARENT-4-BAR/foo"}, //
				{"PARENT-2-VAR/fPARENT-4-BAR/oo", "VAR/../../fPARENT-4-BAR/oo"}, //
				{"/foo/bar", "/foo/bar"}, //
		};

		for (int i = 0; i < table.length; i++) {
			String result = pathVariableManager.convertToUserEditableFormat(toOS(tableLocationFormat[i][0]), true);
			assertEquals("3." + i, toOS(tableLocationFormat[i][1]), result);
			String original = pathVariableManager.convertFromUserEditableFormat(result, true);
			assertEquals("4." + i, toOS(tableLocationFormat[i].length == 2 ? tableLocationFormat[i][0] : tableLocationFormat[i][2]), original);
		}
	}

	private String toOS(String path) {
		return path.replace('/', File.separatorChar);
	}

	/**
	 * Regression for Bug 305676 - Selecting PARENT_LOC as the relative path variable in the ImportTypeDialog causes an error
	 */
	public void testPrefixVariablesAreNotConfused() {
		URI uri = nonExistingFileInExistingFolder.getPathVariableManager().getURIValue("PARENT");
		assertEquals("1.0", uri, null);
		uri = nonExistingFileInExistingFolder.getPathVariableManager().getURIValue("PARENT_LOC");
		assertNotNull("1.1", uri);
	}

	/**
	* Regression test for Bug 338185 - Core Resource Variable Resolvers that do not specify the 'class' attribute are not displayed
	*/
	public void test338185() {
		final IPathVariableManager manager = existingProject.getPathVariableManager();
		String[] variables = manager.getPathVariableNames();
		boolean found = false;

		for (String variable : variables) {
			if (variable.equals("Test338185")) {
				found = true;
			}
		}
		assertTrue(found);
	}
}
