blob: faa135c27ca97ad9fe47a2c57ebeee0367e244c3 [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
*******************************************************************************/
package org.eclipse.core.tests.resources;
import java.io.*;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.internal.resources.File;
import org.eclipse.core.internal.resources.Project;
import org.eclipse.core.internal.utils.FileUtil;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.tests.internal.resources.SimpleNature;
/**
* Tests all aspects of project natures. These tests only
* exercise API classes and methods. Note that the nature-related
* APIs on IWorkspace are tested by IWorkspaceTest.
*/
public class NatureTest extends ResourceTest {
/**
* Constructor for NatureTest.
*/
public NatureTest() {
super();
}
/**
* Constructor for NatureTest.
* @param name
*/
public NatureTest(String name) {
super(name);
}
public static Test suite() {
return new TestSuite(NatureTest.class);
}
/**
* Sets the given set of natures for the project. If success
* does not match the "shouldFail" argument, an assertion error
* with the given message is thrown.
*/
protected void setNatures(String message, IProject project, String[] natures, boolean shouldFail) {
setNatures(message, project, natures, shouldFail, false);
}
/**
* Sets the given set of natures for the project. If success
* does not match the "shouldFail" argument, an assertion error
* with the given message is thrown.
*/
protected void setNatures(String message, IProject project, String[] natures, boolean shouldFail, boolean silent) {
try {
IProjectDescription desc = project.getDescription();
desc.setNatureIds(natures);
int flags = IResource.KEEP_HISTORY;
if (silent) {
flags |= IResource.AVOID_NATURE_CONFIG;
}
project.setDescription(desc, flags, getMonitor());
if (shouldFail) {
fail(message);
}
} catch (CoreException e) {
if (!shouldFail) {
fail(message, e);
}
}
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, null);
ensureDoesNotExistInWorkspace(getWorkspace().getRoot());
}
/**
* Tests invalid additions to the set of natures for a project.
*/
public void testInvalidAdditions() {
IWorkspace ws = ResourcesPlugin.getWorkspace();
IProject project = ws.getRoot().getProject("Project");
ensureExistsInWorkspace(project, true);
setNatures("1.0", project, new String[] {NATURE_SIMPLE}, false);
//Adding a nature that is not available.
setNatures("2.0", project, new String[] {NATURE_SIMPLE, NATURE_MISSING}, true);
try {
assertTrue("2.1", project.hasNature(NATURE_SIMPLE));
assertTrue("2.2", !project.hasNature(NATURE_MISSING));
assertTrue("2.3", project.isNatureEnabled(NATURE_SIMPLE));
assertTrue("2.4", !project.isNatureEnabled(NATURE_MISSING));
} catch (CoreException e) {
fail("2.99", e);
}
//Adding a nature that has a missing prerequisite.
setNatures("3.0", project, new String[] {NATURE_SIMPLE, NATURE_SNOW}, true);
try {
assertTrue("3.1", project.hasNature(NATURE_SIMPLE));
assertTrue("3.2", !project.hasNature(NATURE_SNOW));
assertTrue("3.3", project.isNatureEnabled(NATURE_SIMPLE));
assertTrue("3.4", !project.isNatureEnabled(NATURE_SNOW));
} catch (CoreException e) {
fail("3.99", e);
}
//Adding a nature that creates a duplicated set member.
setNatures("4.0", project, new String[] {NATURE_EARTH}, false);
setNatures("4.1", project, new String[] {NATURE_EARTH, NATURE_WATER}, true);
try {
assertTrue("3.1", project.hasNature(NATURE_EARTH));
assertTrue("3.2", !project.hasNature(NATURE_WATER));
assertTrue("3.3", project.isNatureEnabled(NATURE_EARTH));
assertTrue("3.4", !project.isNatureEnabled(NATURE_WATER));
} catch (CoreException e) {
fail("3.99", e);
}
}
/**
* Tests invalid removals from the set of natures for a project.
*/
public void testInvalidRemovals() {
IWorkspace ws = ResourcesPlugin.getWorkspace();
IProject project = ws.getRoot().getProject("Project");
ensureExistsInWorkspace(project, true);
//Removing a nature that still has dependents.
setNatures("1.0", project, new String[] {NATURE_WATER, NATURE_SNOW}, false);
setNatures("2.0", project, new String[] {NATURE_SNOW}, true);
try {
assertTrue("2.1", project.hasNature(NATURE_WATER));
assertTrue("2.2", project.hasNature(NATURE_SNOW));
assertTrue("2.3", project.isNatureEnabled(NATURE_WATER));
assertTrue("2.4", project.isNatureEnabled(NATURE_SNOW));
} catch (CoreException e) {
fail("2.99", e);
}
}
public void testNatureLifecyle() {
IWorkspace ws = ResourcesPlugin.getWorkspace();
IProject project = ws.getRoot().getProject("Project");
ensureExistsInWorkspace(project, true);
//add simple nature
setNatures("1.0", project, new String[] {NATURE_SIMPLE}, false);
SimpleNature instance = SimpleNature.getInstance();
assertTrue("1.1", instance.wasConfigured);
assertTrue("1.2", !instance.wasDeconfigured);
instance.reset();
//remove simple nature
setNatures("1.3", project, new String[0], false);
instance = SimpleNature.getInstance();
assertTrue("1.4", !instance.wasConfigured);
assertTrue("1.5", instance.wasDeconfigured);
//add with AVOID_NATURE_CONFIG
instance.reset();
setNatures("2.0", project, new String[] {NATURE_SIMPLE}, false, true);
instance = SimpleNature.getInstance();
assertTrue("2.1", !instance.wasConfigured);
assertTrue("2.2", !instance.wasDeconfigured);
try {
assertTrue("2.3", project.hasNature(NATURE_SIMPLE));
} catch (CoreException e) {
fail("1.99", e);
}
//remove with AVOID_NATURE_CONFIG
instance.reset();
setNatures("2.3", project, new String[0], false, true);
instance = SimpleNature.getInstance();
assertTrue("2.4", !instance.wasConfigured);
assertTrue("2.5", !instance.wasDeconfigured);
try {
assertTrue("2.6", !project.hasNature(NATURE_SIMPLE));
} catch (CoreException e) {
fail("2.99", e);
}
}
/**
* Test simple addition and removal of natures.
*/
public void testSimpleNature() {
IWorkspace ws = ResourcesPlugin.getWorkspace();
IProject project = ws.getRoot().getProject("Project");
ensureExistsInWorkspace(project, true);
String[][] valid = getValidNatureSets();
for (int i = 0; i < valid.length; i++) {
setNatures("valid: " + i, project, valid[i], false);
}
//configure a valid nature before starting invalid tests
String[] currentSet = new String[] {NATURE_SIMPLE};
setNatures("1.0", project, currentSet, false);
//now do invalid tests and ensure simple nature is still configured
String[][] invalid = getInvalidNatureSets();
for (int i = 0; i < invalid.length; i++) {
setNatures("invalid: " + i, project, invalid[i], true);
try {
assertTrue("2.0", project.hasNature(NATURE_SIMPLE));
assertTrue("2.1", !project.hasNature(NATURE_EARTH));
assertTrue("2.2", project.isNatureEnabled(NATURE_SIMPLE));
assertTrue("2.3", !project.isNatureEnabled(NATURE_EARTH));
assertEquals("2.4", project.getDescription().getNatureIds(), currentSet);
} catch (CoreException e) {
fail("2.99", e);
}
}
}
/**
* Test addition of nature that requires the workspace root.
* See bugs 127562 and 128709.
*/
public void testBug127562Nature() {
IWorkspace ws = ResourcesPlugin.getWorkspace();
IProject project = ws.getRoot().getProject("Project");
ensureExistsInWorkspace(project, true);
String[][] valid = getValidNatureSets();
for (int i = 0; i < valid.length; i++) {
setNatures("valid: " + i, project, valid[i], false);
}
// add with AVOID_NATURE_CONFIG
String[] currentSet = new String[] {NATURE_127562};
setNatures("1.0", project, currentSet, false, true);
// configure the nature using a conflicting scheduling rule
IJobManager manager = Job.getJobManager();
try {
manager.beginRule(ws.getRuleFactory().modifyRule(project), null);
project.getNature(NATURE_127562).configure();
fail("2.0");
} catch (CoreException ex) {
fail("2.1");
} catch (IllegalArgumentException ex) {
// should throw this kind of exception
} finally {
manager.endRule(ws.getRuleFactory().modifyRule(project));
}
// configure the nature using a non-conflicting scheduling rule
try {
manager.beginRule(ws.getRoot(), null);
project.getNature(NATURE_127562).configure();
} catch (CoreException ex) {
fail("3.0");
} finally {
manager.endRule(ws.getRoot());
}
}
public void testBug297871() {
IWorkspace ws = ResourcesPlugin.getWorkspace();
Project project = (Project) ws.getRoot().getProject("Project");
ensureExistsInWorkspace(project, true);
java.io.File desc = null;
try {
IFileStore descStore = ((File) project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME)).getStore();
desc = descStore.toLocalFile(EFS.NONE, getMonitor());
} catch (CoreException e) {
fail("1.0");
}
java.io.File descTmp = new java.io.File(desc.getPath() + ".tmp");
try {
copy(desc, descTmp);
} catch (IOException e) {
fail("2.0", e);
}
setNatures("valid ", project, new String[] {NATURE_EARTH}, false);
try {
assertNotNull(project.getNature(NATURE_EARTH));
} catch (CoreException e) {
fail("3.0", e);
}
try {
assertTrue(project.hasNature(NATURE_EARTH));
} catch (CoreException e) {
fail("4.0", e);
}
try {
// Make sure enough time has past to bump file's
// timestamp during the copy
Thread.sleep(1000);
} catch (InterruptedException e) {
fail("5.0", e);
}
try {
copy(descTmp, desc);
} catch (IOException e) {
fail("6.0", e);
}
try {
project.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
} catch (CoreException e) {
fail("7.0", e);
}
try {
assertNull(project.getNature(NATURE_EARTH));
} catch (CoreException e) {
fail("8.0", e);
}
try {
assertFalse(project.hasNature(NATURE_EARTH));
} catch (CoreException e) {
fail("9.0", e);
}
}
private void copy(java.io.File src, java.io.File dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) > 0) {
out.write(buffer, 0, read);
}
in.close();
out.close();
}
/**
* Changes project description and parallel checks {@link IProject#isNatureEnabled(String)},
* to check if natures value is cached properly.
*
* See Bug 338055.
* @throws Exception
*/
public void testBug338055() throws Exception {
final boolean finished[] = new boolean[] {false};
final Project project = (Project) ResourcesPlugin.getWorkspace().getRoot().getProject(getUniqueString());
ensureExistsInWorkspace(project, true);
new Job("CheckNatureJob") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
if (finished[0] == false) {
if (project.exists() && project.isOpen()) {
project.isNatureEnabled(NATURE_SIMPLE);
}
schedule();
}
} catch (CoreException e) {
fail("CheckNatureJob failed", e);
}
return Status.OK_STATUS;
}
}.schedule();
try {
// Make sure enough time has past to bump file's
// timestamp during the copy
Thread.sleep(1000);
} catch (InterruptedException e) {
fail("2.0", e);
}
IFileStore descStore = ((File) project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME)).getStore();
// create a description with many natures, this will make updating description longer
StringBuffer description = new StringBuffer();
description.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><projectDescription><name></name><comment></comment><projects></projects><buildSpec></buildSpec><natures>");
description.append("<nature>" + NATURE_SIMPLE + "</nature>");
for (int i = 0; i < 100; i++) {
description.append("<nature>nature" + i + "</nature>");
}
description.append("</natures></projectDescription>\n");
// write the description
OutputStream output = null;
try {
output = descStore.openOutputStream(EFS.NONE, getMonitor());
output.write(description.toString().getBytes());
} catch (CoreException e) {
fail("1.0");
} finally {
FileUtil.safeClose(output);
}
try {
project.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
} catch (CoreException e) {
fail("3.0", e);
}
finished[0] = true;
assertTrue("4.0", project.hasNature(NATURE_SIMPLE));
assertTrue("5.0", project.isNatureEnabled(NATURE_SIMPLE));
}
}