/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     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.*;
import java.net.URI;
import java.util.ArrayList;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.filesystem.*;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
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;

	public LinkedResourceWithPathVariableTest() {
		super();
	}

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

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

	@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, Path.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();
			}
		}
	}

	/**
	 * @see org.eclipse.core.tests.harness.ResourceTest#getRandomLocation()
	 */
	@Override
	public IPath getRandomLocation() {
		IPathVariableManager pathVars = getWorkspace().getPathVariableManager();
		//low order bits are current time, high order bits are static counter
		IPath parent = new Path(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;
	}

	/**
	 * @see org.eclipse.core.tests.harness.ResourceTest#getRandomLocation()
	 */
	public IPath getRandomProjectLocation() {
		IPathVariableManager pathVars = getWorkspace().getPathVariableManager();
		// low order bits are current time, high order bits are static counter
		IPath parent = new Path(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;
	}

	/**
	 * @see org.eclipse.core.tests.harness.ResourceTest#getRandomLocation()
	 */
	public IPath getRandomRelativeProjectLocation() {
		IPathVariableManager pathVars = getWorkspace().getPathVariableManager();
		// low order bits are current time, high order bits are static counter
		IPath parent = new Path(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;
	}

	/**
	 * @see LinkedResourceTest#resolve(org.eclipse.core.runtime.IPath)
	 */
	@Override
	protected IPath resolve(IPath path) {
		return getWorkspace().getPathVariableManager().resolvePath(path);
	}

	/**
	 * @see LinkedResourceTest#resolve(java.net.URI)
	 */
	@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", Path.fromPortableString("${PARENT-3-PROJECT_LOC}"));
			variableBasedLocation = Path.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 = new Path("NOVAR/folder");
		IPath fileLocation = new Path("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);
	}
}
