blob: 6f6e626045c9e4cc7a88da1434ad27190741a556 [file] [log] [blame]
/*******************************************************************************
* 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
* Alexander Kurtakov <akurtako@redhat.com> - Bug 459343
*******************************************************************************/
package org.eclipse.core.tests.resources;
import java.io.*;
import java.net.URI;
import java.util.*;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.utils.FileUtil;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
/**
* Tests path variables.
*/
public class IPathVariableTest extends ResourceTest {
IPathVariableManager manager = null;
IProject project = null;
@Override
protected void setUp() throws Exception {
super.setUp();
project = getWorkspace().getRoot().getProject("MyProject");
try {
project.create(getMonitor());
project.open(getMonitor());
} catch (CoreException e) {
fail("1.3", e);
}
assertTrue("1.4", project.exists());
manager = project.getPathVariableManager();
}
class PathVariableChangeVerifier implements IPathVariableChangeListener {
class VerificationFailedException extends Exception {
/**
* All serializable objects should have a stable serialVersionUID
*/
private static final long serialVersionUID = 1L;
VerificationFailedException(String message) {
super(message);
}
}
class Event {
int type;
String name;
IPath value;
Event(int type, String name, IPath value) {
this.type = type;
this.name = name;
this.value = value;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Event)) {
return false;
}
Event that = (Event) obj;
if (this.type != that.type || !this.name.equals(that.name)) {
return false;
}
return this.value == null ? that.value == null : this.value.equals(that.value);
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("Event(");
buffer.append("type: ");
buffer.append(stringForType(type));
buffer.append(" name: ");
buffer.append(name);
buffer.append(" value: ");
buffer.append(value);
buffer.append(")");
return buffer.toString();
}
String stringForType(int typeValue) {
switch (typeValue) {
case IPathVariableChangeEvent.VARIABLE_CREATED :
return "CREATED";
case IPathVariableChangeEvent.VARIABLE_CHANGED :
return "CHANGED";
case IPathVariableChangeEvent.VARIABLE_DELETED :
return "DELETED";
default :
return "UNKNOWN";
}
}
}
List<Event> expected = new ArrayList<>();
List<Event> actual = new ArrayList<>();
void addExpectedEvent(int type, String name, IPath value) {
expected.add(new Event(type, name, value));
}
void verify() throws VerificationFailedException {
String message;
if (expected.size() != actual.size()) {
message = "Expected size: " + expected.size() + " does not equal actual size: " + actual.size() + "\n";
message += dump();
throw new VerificationFailedException(message);
}
for (Event event : expected) {
if (!actual.contains(event)) {
message = "Expected and actual results differ.\n";
message += dump();
throw new VerificationFailedException(message);
}
}
}
void reset() {
expected = new ArrayList<>();
actual = new ArrayList<>();
}
@Override
public void pathVariableChanged(IPathVariableChangeEvent event) {
actual.add(new Event(event.getType(), event.getVariableName(), event.getValue()));
}
String dump() {
StringBuffer buffer = new StringBuffer();
buffer.append("Expected:\n");
for (Event event : expected) {
buffer.append("\t" + event + "\n");
}
buffer.append("Actual:\n");
for (Event event : actual) {
buffer.append("\t" + event + "\n");
}
return buffer.toString();
}
}
/**
* Default constructor for this class.
*/
public IPathVariableTest() {
super();
}
/**
* Constructor for the class.
*/
public IPathVariableTest(String name) {
super(name);
}
/**
* Return the tests to run.
*
* @see org.eclipse.core.tests.harness.ResourceTest#suite()
*/
public static Test suite() {
return new TestSuite(IPathVariableTest.class);
}
/**
* Test IPathVariableManager#getPathVariableNames
*/
public void testGetPathVariableNames() {
String[] names = null;
// add one
try {
manager.setValue("one", getRandomLocation());
} catch (CoreException e) {
fail("1.0", e);
}
names = manager.getPathVariableNames();
List<String> list = Arrays.asList(names);
assertTrue("1.2", list.contains("one"));
// add another
try {
manager.setValue("two", Path.ROOT);
} catch (CoreException e) {
fail("2.0", e);
}
names = manager.getPathVariableNames();
list = Arrays.asList(names);
assertTrue("2.2", list.contains("one"));
assertTrue("2.3", list.contains("two"));
// remove one
try {
manager.setValue("one", (IPath) null);
} catch (CoreException e) {
fail("3.0", e);
}
names = manager.getPathVariableNames();
list = Arrays.asList(names);
assertTrue("3.2", list.contains("two"));
assertTrue("3.3", !list.contains("one"));
// remove the last one
try {
manager.setValue("two", (IPath) null);
} catch (CoreException e) {
fail("4.0", e);
}
names = manager.getPathVariableNames();
list = Arrays.asList(names);
assertTrue("4.2", !list.contains("two"));
assertTrue("4.3", !list.contains("one"));
}
/**
* Test IPathVariableManager#getValue and IPathVariableManager#setValue
*/
public void testGetSetValue() {
boolean WINDOWS = java.io.File.separatorChar == '\\';
IPath pathOne = WINDOWS ? new Path("C:\\testGetSetValue") : new Path("/testGetSetValue");
IPath pathTwo = new Path("/blort/backup");
//add device if necessary
pathTwo = new Path(pathTwo.toFile().getAbsolutePath());
IPath pathOneEdit = WINDOWS ? new Path("D:/foobar") : new Path("/foobar");
// nothing to begin with
assertNull("0.0", manager.getValue("one"));
// add a value to the table
try {
manager.setValue("one", pathOne);
} catch (CoreException e) {
fail("1.0", e);
}
IPath value = manager.getValue("one");
assertNotNull("1.1", value);
assertEquals("1.2", pathOne, value);
// add another value
try {
manager.setValue("two", pathTwo);
} catch (CoreException e) {
fail("2.0", e);
}
value = manager.getValue("two");
assertNotNull("2.1", value);
assertEquals("2.2", pathTwo, value);
// edit the first value
try {
manager.setValue("one", pathOneEdit);
} catch (CoreException e) {
fail("3.0", e);
}
value = manager.getValue("one");
assertNotNull("3.1", value);
assertTrue("3.2", pathOneEdit.equals(value));
// setting with value == null will remove
try {
manager.setValue("one", (IPath) null);
} catch (CoreException e) {
fail("4.0", e);
}
assertNull("4.1", manager.getValue("one"));
// set values with bogus names
try {
manager.setValue("ECLIPSE$HOME", Path.ROOT);
fail("5.0 Accepted invalid variable name in setValue()");
} catch (CoreException ce) {
// success
}
// set value with relative path
try {
manager.setValue("one", new Path("foo/bar"));
} catch (CoreException ce) {
fail("5.0 Did not Accepted invalid variable value in setValue()");
}
// set invalid value (with invalid segment)
if (WINDOWS) {
String invalidPathString = "C:/a/\\::/b";
IPath invalidPath = Path.fromPortableString(invalidPathString);
assertTrue("6.0", invalidPath.isAbsolute());
assertTrue("6.1", !Path.EMPTY.isValidPath(invalidPathString));
assertTrue("6.2", manager.validateValue(invalidPath).isOK());
try {
manager.setValue("one", invalidPath);
} catch (CoreException ce) {
fail("6.3 Fail to accept invalid variable value in setValue()");
}
}
}
/**
* Test IPathVariableManager#isDefined
*/
public void testIsDefined() {
assertTrue("0.0", !manager.isDefined("one"));
try {
manager.setValue("one", Path.ROOT);
} catch (CoreException e) {
fail("1.0", e);
}
assertTrue("1.1", manager.isDefined("one"));
try {
manager.setValue("one", (IPath) null);
} catch (CoreException e) {
fail("2.0", e);
}
assertTrue("2.1", !manager.isDefined("one"));
}
/**
* Test IPathVariableManager#resolvePath
*/
public void testResolvePathWithMacro() {
final boolean WINDOWS = java.io.File.separatorChar == '\\';
IPath pathOne = WINDOWS ? new Path("c:/testGetSetValue/foo") : new Path("/testGetSetValue/foo");
IPath pathTwo = WINDOWS ? new Path("c:/tmp/backup") : new Path("/tmp/backup");
// add device if neccessary
pathTwo = new Path(pathTwo.toFile().getAbsolutePath());
try {
manager.setValue("one", pathOne);
} catch (CoreException e) {
fail("0.1", e);
}
try {
manager.setValue("two", pathTwo);
} catch (CoreException e) {
fail("0.2", e);
}
try {
manager.setValue("three", Path.fromOSString("${two}/extra"));
} catch (CoreException e) {
fail("0.3", e);
}
IPath path = new Path("three/bar");
IPath expected = new Path("/tmp/backup/extra/bar").setDevice(WINDOWS ? "c:" : null);
IPath actual = manager.resolvePath(path);
assertEquals("1.0", expected, actual);
}
/**
*/
public void testProjectLoc() {
IPath path = new Path("${PROJECT_LOC}/bar");
IPath projectLocation = project.getLocation();
IPath expected = projectLocation.append("bar");
IPath actual = manager.resolvePath(path);
assertEquals("1.0", expected, actual);
}
/**
*/
public void testEclipseHome() {
IPath path = new Path("${ECLIPSE_HOME}/bar");
IPath expected = new Path(Platform.getInstallLocation().getURL().getPath()).append("bar");
IPath actual = manager.resolvePath(path);
assertEquals("1.0", expected, actual);
}
/**
*/
public void testWorkspaceLocation() {
IPath path = new Path("${WORKSPACE_LOC}/bar");
IPath expected = project.getWorkspace().getRoot().getLocation().append("bar");
IPath actual = manager.resolvePath(path);
assertEquals("1.0", expected, actual);
}
/**
* Test IgetVariableRelativePathLocation(project, IPath)
*/
public void testGetVariableRelativePathLocation() {
IPath path = project.getWorkspace().getRoot().getLocation().append("bar");
IPath actual;
IPath expected;
/* Does not work on the test machine because ECLIPSE_HOME and WORKSPACE is the same location
actual = getVariableRelativePathLocation(project, path);
expected = new Path("WORKSPACE_LOC/bar");
assertEquals("1.0", expected, actual);
*/
path = new Path(Platform.getInstallLocation().getURL().getPath()).append("bar");
expected = new Path("ECLIPSE_HOME/bar");
actual = getVariableRelativePathLocation(project, path);
assertEquals("2.0", expected, actual);
path = project.getLocation().append("bar");
expected = new Path("PROJECT_LOC/bar");
actual = getVariableRelativePathLocation(project, path);
assertEquals("3.0", expected, actual);
actual = getVariableRelativePathLocation(project, new Path("/nonExistentPath/foo"));
assertEquals("4.0", null, actual);
}
private IPath getVariableRelativePathLocation(IProject project, IPath location) {
URI variableRelativePathLocation = project.getPathVariableManager().getVariableRelativePathLocation(URIUtil.toURI(location));
if (variableRelativePathLocation != null) {
return URIUtil.toPath(variableRelativePathLocation);
}
return null;
}
/**
* Test IPathVariableManager#resolvePath
*/
public void testResolvePath() {
final boolean WINDOWS = java.io.File.separatorChar == '\\';
IPath pathOne = WINDOWS ? new Path("C:/testGetSetValue/foo") : new Path("/testGetSetValue/foo");
IPath pathTwo = new Path("/blort/backup");
//add device if necessary
pathTwo = new Path(pathTwo.toFile().getAbsolutePath());
try {
// for WINDOWS - the device id for windows will be changed to upper case
// in the variable stored in the manager
manager.setValue("one", pathOne);
} catch (CoreException e) {
fail("0.1", e);
}
try {
manager.setValue("two", pathTwo);
} catch (CoreException e) {
fail("0.2", e);
}
// one substitution
IPath path = new Path("one/bar");
IPath expected = new Path("/testGetSetValue/foo/bar").setDevice(WINDOWS ? "C:" : null);
IPath actual = manager.resolvePath(path);
assertEquals("1.0", expected, actual);
// another substitution
path = new Path("two/myworld");
expected = new Path("/blort/backup/myworld");
expected = new Path(expected.toFile().getAbsolutePath());
actual = manager.resolvePath(path);
assertEquals("2.0", expected, actual);
// variable not defined
path = new Path("three/nothere");
expected = path;
actual = manager.resolvePath(path);
assertEquals("3.0", expected, actual);
// device
path = new Path("/one").setDevice(WINDOWS ? "C:" : null);
expected = path;
actual = manager.resolvePath(path);
assertEquals("4.0", expected, actual);
// device2
if (WINDOWS) {
path = new Path("C:two");
expected = path;
actual = manager.resolvePath(path);
assertEquals("5.0", expected, actual);
}
// absolute
path = new Path("/one");
expected = path;
actual = manager.resolvePath(path);
assertEquals("6.0", expected, actual);
// just resolving, check if the variable stored in the manager is canonicalized
if (WINDOWS) {
path = new Path("one");
expected = FileUtil.canonicalPath(pathOne);
actual = manager.resolvePath(path);
// the path stored in the manager is canonicalized, so the device id of actual will be upper case
assertEquals("7.0", expected, actual);
}
// null
path = null;
assertNull("7.0", manager.resolvePath(path));
}
private IPath convertToRelative(IPathVariableManager manager, IPath path, boolean force, String variableHint) throws CoreException {
return URIUtil.toPath(manager.convertToRelative(URIUtil.toURI(path), force, variableHint));
}
/**
* Test IPathVariableManager#convertToRelative()
*/
public void testConvertToRelative() {
final boolean WINDOWS = java.io.File.separatorChar == '\\';
IPath pathOne = WINDOWS ? new Path("c:/foo/bar") : new Path("/foo/bar");
IPath pathTwo = WINDOWS ? new Path("c:/foo/other") : new Path("/foo/other");
IPath pathThree = WINDOWS ? new Path("c:/random/other/subpath") : new Path("/random/other/subpath");
IPath file = WINDOWS ? new Path("c:/foo/other/file.txt") : new Path("/foo/other/file.txt");
try {
manager.setValue("ONE", pathOne);
manager.setValue("THREE", pathThree);
} catch (CoreException e) {
fail("0.1", e);
}
IPath actual = null;
try {
actual = convertToRelative(manager, file, false, "ONE");
} catch (CoreException e) {
fail("0.2", e);
}
IPath expected = file;
assertEquals("1.0", expected, actual);
try {
manager.setValue("TWO", pathTwo);
} catch (CoreException e) {
fail("1.1", e);
}
try {
actual = convertToRelative(manager, file, false, "ONE");
} catch (CoreException e) {
fail("1.2", e);
}
expected = file;
assertEquals("2.0", expected, actual);
try {
actual = convertToRelative(manager, file, false, "TWO");
} catch (CoreException e) {
fail("2.1", e);
}
expected = new Path("TWO/file.txt");
assertEquals("3.0", expected, actual);
// force the path to be relative to "ONE"
try {
actual = convertToRelative(manager, file, true, "ONE");
} catch (CoreException e) {
fail("3.1", e);
}
expected = new Path("PARENT-1-ONE/other/file.txt");
assertEquals("4.0", expected, actual);
// the second time should be re-using "FOO"
try {
actual = convertToRelative(manager, file, true, "ONE");
} catch (CoreException e) {
fail("4.3", e);
}
expected = new Path("PARENT-1-ONE/other/file.txt");
assertEquals("5.0", expected, actual);
try {
actual = convertToRelative(manager, file, true, "TWO");
} catch (CoreException e) {
fail("5.4", e);
}
expected = new Path("TWO/file.txt");
assertEquals("6.0", expected, actual);
try {
actual = convertToRelative(manager, file, true, "TWO");
} catch (CoreException e) {
fail("6.1", e);
}
expected = new Path("TWO/file.txt");
assertEquals("7.0", expected, actual);
try {
actual = convertToRelative(manager, file, false, null);
} catch (CoreException e) {
fail("7.1", e);
}
expected = new Path("TWO/file.txt");
assertEquals("8.0", expected, actual);
try {
manager.setValue("TWO", (IPath) null);
} catch (CoreException e) {
fail("8.1", e);
}
// now without any direct reference
try {
actual = convertToRelative(manager, file, false, null);
} catch (CoreException e) {
fail("8.2", e);
}
expected = file;
assertEquals("9.0", expected, actual);
try {
actual = convertToRelative(manager, file, true, null);
} catch (CoreException e) {
fail("9.1", e);
}
expected = new Path("PARENT-1-ONE/other/file.txt");
assertEquals("10.0", expected, actual);
}
/**
* Test IPathVariableManager#testValidateName
*/
public void testValidateName() {
// valid names
assertTrue("0.0", manager.validateName("ECLIPSEHOME").isOK());
assertTrue("0.1", manager.validateName("ECLIPSE_HOME").isOK());
assertTrue("0.2", manager.validateName("ECLIPSE_HOME_1").isOK());
assertTrue("0.3", manager.validateName("_").isOK());
// invalid names
assertTrue("1.0", !manager.validateName("1FOO").isOK());
assertTrue("1.1", !manager.validateName("FOO%BAR").isOK());
assertTrue("1.2", !manager.validateName("FOO$BAR").isOK());
assertTrue("1.3", !manager.validateName(" FOO").isOK());
assertTrue("1.4", !manager.validateName("FOO ").isOK());
}
/**
* Regression test for Bug 304195
*/
public void testEmptyURIResolution() {
IPath path = new Path(new String());
URI uri = URIUtil.toURI(path);
try {
manager.resolveURI(uri);
} catch (Throwable e) {
fail("1.2", e);
}
try {
getWorkspace().getPathVariableManager().resolveURI(uri);
} catch (Throwable e) {
fail("1.2", e);
}
}
/**
* Test IPathVariableManager#addChangeListener and IPathVariableManager#removeChangeListener
*/
public void testListeners() {
PathVariableChangeVerifier listener = new PathVariableChangeVerifier();
manager.addChangeListener(listener);
IPath pathOne = new Path("/blort/foobar");
//add device if necessary
pathOne = new Path(pathOne.toFile().getAbsolutePath());
IPath pathOneEdit = pathOne.append("myworld");
try {
// add a variable
try {
manager.setValue("one", pathOne);
} catch (CoreException e) {
fail("1.0", e);
}
listener.addExpectedEvent(IPathVariableChangeEvent.VARIABLE_CREATED, "one", pathOne);
try {
listener.verify();
} catch (PathVariableChangeVerifier.VerificationFailedException e) {
fail("1.1", e);
}
// change a variable
listener.reset();
try {
manager.setValue("one", pathOneEdit);
} catch (CoreException e) {
fail("2.0", e);
}
listener.addExpectedEvent(IPathVariableChangeEvent.VARIABLE_CHANGED, "one", pathOneEdit);
try {
listener.verify();
} catch (PathVariableChangeVerifier.VerificationFailedException e) {
fail("2.1", e);
}
// remove a variable
listener.reset();
try {
manager.setValue("one", (IPath) null);
} catch (CoreException e) {
fail("3.0", e);
}
listener.addExpectedEvent(IPathVariableChangeEvent.VARIABLE_DELETED, "one", null);
try {
listener.verify();
} catch (PathVariableChangeVerifier.VerificationFailedException e) {
fail("3.1", e);
}
} finally {
manager.removeChangeListener(listener);
}
}
boolean contains(Object[] array, Object obj) {
for (Object element : array) {
if (element.equals(obj)) {
return true;
}
}
return false;
}
/**
* Ensure there are no path variables in the workspace.
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
String[] names = manager.getPathVariableNames();
for (String name : names) {
manager.setValue(name, (IPath) null);
}
}
@Override
protected void cleanup() throws CoreException {
project.delete(true, getMonitor());
super.cleanup();
}
/**
* Regression for Bug 308975 - Can't recover from 'invalid' path variable
*/
public void testLinkExistInProjectDescriptionButNotInWorkspace() {
String dorProjectContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
"<projectDescription>" + //
"<name>ExistingProject</name>" + //
"<comment></comment>" + //
"<projects>" + //
"</projects>" + //
"<buildSpec>" + //
"</buildSpec>" + //
"<natures>" + //
"</natures>" + //
"<variableList>" + //
"<variable>" + //
" <name>PROJ_UP</name>" + //
" <value>$%7BPARENT-1-PROJECT_LOC%7D</value>" + //
" </variable>" + //
" </variableList>" + //
"</projectDescription>";
IProject existingProject = getWorkspace().getRoot().getProject("ExistingProject");
ensureExistsInWorkspace(new IResource[] {existingProject}, true);
try {
existingProject.close(getMonitor());
ProjectInfo info = (ProjectInfo) ((Project) existingProject).getResourceInfo(false, false);
info.clear(ICoreConstants.M_USED);
String dotProjectPath = existingProject.getLocation().append(".project").toOSString();
FileWriter fstream = new FileWriter(dotProjectPath);
BufferedWriter out = new BufferedWriter(fstream);
out.write(dorProjectContent);
out.close();
existingProject.open(getMonitor());
} catch (CoreException e) {
fail("1.99", e);
} catch (IOException e) {
fail("1.99", e);
}
IPathVariableManager pathVariableManager = existingProject.getPathVariableManager();
String[] varNames = pathVariableManager.getPathVariableNames();
for (String varName : varNames) {
try {
pathVariableManager.getURIValue(varName);
} catch (Exception e) {
fail("3.99", e);
}
}
}
/**
* Regression test for Bug 328045 where a class cast exception is thrown when
* attempting to get the location of a resource that would live under an
* existing IFile.
*/
public void testDiscoverLocationOfInvalidFile() {
IPath filep = new Path("someFile");
IPath invalidChild = filep.append("invalidChild");
// Create filep
IFile f = project.getFile(filep);
ensureExistsInWorkspace(f, true);
// Get a reference to a child
IFile invalidFile = project.getFile(invalidChild);
// Don't care about the result, just care there's no exception.
invalidFile.getLocationURI();
}
}