blob: 60f805387141c35d8d2f3cf5d0689e2400af0470 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 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.wst.jsdt.core.tests.model;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import junit.framework.Test;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.jsdt.core.IAccessRule;
import org.eclipse.wst.jsdt.core.IIncludePathAttribute;
import org.eclipse.wst.jsdt.core.IJsGlobalScopeContainer;
import org.eclipse.wst.jsdt.core.IIncludePathEntry;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.IJavaScriptElementDelta;
import org.eclipse.wst.jsdt.core.IJavaScriptModelMarker;
import org.eclipse.wst.jsdt.core.IJavaScriptModelStatus;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IPackageFragment;
import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
import org.eclipse.wst.jsdt.core.JavaScriptConventions;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.tests.util.Util;
import org.eclipse.wst.jsdt.internal.core.ClasspathEntry;
import org.eclipse.wst.jsdt.internal.core.JavaModelManager;
import org.eclipse.wst.jsdt.internal.core.JavaProject;
public class ClasspathTests extends ModifyingResourceTests {
public class TestContainer implements IJsGlobalScopeContainer {
IPath path;
IIncludePathEntry[] entries;
TestContainer(IPath path, IIncludePathEntry[] entries){
this.path = path;
this.entries = entries;
}
public IPath getPath() { return this.path; }
/**
* @deprecated Use {@link #getIncludepathEntries()} instead
*/
public IIncludePathEntry[] getClasspathEntries() {
return getIncludepathEntries();
}
public IIncludePathEntry[] getIncludepathEntries() { return this.entries; }
public String getDescription() { return this.path.toString(); }
public int getKind() { return 0; }
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainer#resolvedLibraryImport(java.lang.String)
*/
public String[] resolvedLibraryImport(String a) {
return new String[] {a};
}
}
public ClasspathTests(String name) {
super(name);
}
// Use this static initializer to specify subset for tests
// All specified tests which do not belong to the class are skipped...
static {
// Names of tests to run: can be "testBugXXXX" or "BugXXXX")
// TESTS_PREFIX = "testClasspathDuplicateExtraAttribute";
// TESTS_NAMES = new String[] {"testClasspathValidation42"};
// TESTS_NUMBERS = new int[] { 23, 28, 38 };
// TESTS_RANGE = new int[] { 21, 38 };
}
public static Test suite() {
return buildModelTestSuite(ClasspathTests.class);
}
public void setUpSuite() throws Exception {
super.setUpSuite();
setupExternalJCL("jclMin");
}
protected void assertCycleMarkers(IJavaScriptProject project, IJavaScriptProject[] p, int[] expectedCycleParticipants) throws CoreException {
waitForAutoBuild();
StringBuffer expected = new StringBuffer("{");
int expectedCount = 0;
StringBuffer computed = new StringBuffer("{");
int computedCount = 0;
for (int j = 0; j < p.length; j++){
int markerCount = this.numberOfCycleMarkers(p[j]);
if (markerCount > 0){
if (computedCount++ > 0) computed.append(", ");
computed.append(p[j].getElementName());
//computed.append(" (" + markerCount + ")");
}
markerCount = expectedCycleParticipants[j];
if (markerCount > 0){
if (expectedCount++ > 0) expected.append(", ");
expected.append(p[j].getElementName());
//expected.append(" (" + markerCount + ")");
}
}
expected.append("}");
computed.append("}");
assertEquals("Invalid cycle detection after setting classpath for: "+project.getElementName(), expected.toString(), computed.toString());
}
private void assertEncodeDecodeEntry(String projectName, String expectedEncoded, IIncludePathEntry entry) {
IJavaScriptProject project = getJavaProject(projectName);
String encoded = project.encodeIncludepathEntry(entry);
assertSourceEquals(
"Unexpected encoded entry",
expectedEncoded,
encoded);
IIncludePathEntry decoded = project.decodeIncludepathEntry(encoded);
assertEquals(
"Unexpected decoded entry",
entry,
decoded);
}
protected File createFile(File parent, String name, String content) throws IOException {
File file = new File(parent, name);
FileOutputStream out = new FileOutputStream(file);
out.write(content.getBytes());
out.close();
/*
* Need to change the time stamp to realize that the file has been modified
*/
file.setLastModified(System.currentTimeMillis() + 2000);
return file;
}
protected File createFolder(File parent, String name) {
File file = new File(parent, name);
file.mkdirs();
return file;
}
protected int numberOfCycleMarkers(IJavaScriptProject javaProject) throws CoreException {
IMarker[] markers = javaProject.getProject().findMarkers(IJavaScriptModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
int result = 0;
for (int i = 0, length = markers.length; i < length; i++) {
IMarker marker = markers[i];
String cycleAttr = (String)marker.getAttribute(IJavaScriptModelMarker.CYCLE_DETECTED);
if (cycleAttr != null && cycleAttr.equals("true")){ //$NON-NLS-1$
result++;
}
}
return result;
}
/**
* Add an entry to the classpath for a non-existent root. Then create
* the root and ensure that it comes alive.
*/
public void testAddRoot1() throws CoreException {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP= project.getRawIncludepath();
try {
IIncludePathEntry newEntry= JavaScriptCore.newSourceEntry(project.getProject().getFullPath().append("extra"));
IIncludePathEntry[] newCP= new IIncludePathEntry[originalCP.length + 1];
System.arraycopy(originalCP, 0 , newCP, 0, originalCP.length);
newCP[originalCP.length]= newEntry;
project.setRawIncludepath(newCP, null);
// now create the actual resource for the root and populate it
project.getProject().getFolder("extra").create(false, true, null);
IPackageFragmentRoot newRoot= getPackageFragmentRoot("P", "extra");
assertTrue("New root should now be visible", newRoot != null);
} finally {
// cleanup
this.deleteProject("P");
}
}
/*
* Adds an entry to the classpath for a non-existent root. Then creates
* the root and ensures that the marker is removed.
* (regression test for bug 161581 Adding a missing folder doesn't remove classpath marker)
*/
public void testAddRoot2() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {}, "bin");
project.setRawIncludepath(createClasspath("P", new String[] {"/P/src", ""}), null);
waitForAutoBuild();
// now create the actual resource for the root
project.getProject().getFolder("src").create(false, true, null);
assertMarkers("Unexpected markers", "", project);
} finally {
// cleanup
this.deleteProject("P");
}
}
/**
* Ensures that the reordering external resources in the classpath
* generates the correct deltas.
*/
public void testClasspathChangeExternalResources() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] newEntries = new IIncludePathEntry[2];
newEntries[0] = JavaScriptCore.newLibraryEntry(getExternalJCLPath(), null, null, false);
newEntries[1] = JavaScriptCore.newLibraryEntry(getExternalJCLSourcePath(), null, null, false);
setClasspath(proj, newEntries);
startDeltas();
IIncludePathEntry[] swappedEntries = new IIncludePathEntry[2];
swappedEntries[0] = newEntries[1];
swappedEntries[1] = newEntries[0];
setClasspath(proj, swappedEntries);
assertDeltas(
"Unexpected delta",
"P[*]: {CHILDREN | CONTENT | CLASSPATH CHANGED}\n" +
" "+ getExternalJCLPathString() +"[*]: {REORDERED}\n" +
" "+ getExternalJCLSourcePathString() +"[*]: {REORDERED}\n" +
" ResourceDelta(/P/.classpath)[*]"
);
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/*
* Test classpath corruption (23977)
*/
public void testClasspathCorruption() throws CoreException {
try {
JavaProject p1 = (JavaProject)this.createJavaProject("P1", new String[]{""}, new String[]{}, new String[]{}, "");
this.createJavaProject("P2", new String[]{""}, new String[]{}, new String[]{}, "");
this.createFile("P2/foo.txt", "not a project");
String newCPContent =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
+"<classpath> \n"
+" <classpathentry kind=\"src\" path=\"\"/> \n"
+" <classpathentry kind=\"src\" path=\"/P2/foo.txt\"/> \n" // corruption here: target isn't a project
+" <classpathentry kind=\"output\" path=\"\"/> \n"
+"</classpath> \n";
IFile fileRsc = p1.getProject().getFile(JavaProject.CLASSPATH_FILENAME);
fileRsc.setContents(new ByteArrayInputStream(newCPContent.getBytes()), true, false, null);
/*
File file = p1.getProject().getFile(JavaProject.CLASSPATH_FILENAME).getLocation().toFile();
if (file.exists()){
char[] classpath = Util.getFileCharContent(file, "UTF-8");
System.out.println(new String(classpath));
}
*/
p1.close();
JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(p1.getProject(), true/*create if missing*/);
perProjectInfo.setClasspath(null, null, null, null, null, null, null);
// shouldn't fail
p1.getExpandedClasspath();
// if could reach that far, then all is fine
} catch(ClassCastException e){
assertTrue("internal ClassCastException on corrupted classpath file", false);
} finally {
// cleanup
this.deleteProject("P1");
this.deleteProject("P2");
}
}
/*
* Test classpath read for non-java project or java project not opened yet (40658)
*/
public void testClasspathFileRead() throws CoreException {
try {
final IProject proj = this.createProject("P1");
String newCPContent =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
+"<classpath> \n"
+" <classpathentry kind=\"src\" path=\"src\"/> \n"
+" <classpathentry kind=\"output\" path=\"bin\"/> \n"
+"</classpath> \n";
this.createFile("/P1/"+JavaProject.CLASSPATH_FILENAME, newCPContent);
final IJavaScriptProject jproj = JavaScriptCore.create(proj);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) {
IIncludePathEntry[] entries = jproj.readRawIncludepath(); // force to read classpath
IIncludePathEntry entry = entries[0];
assertEquals("first classpath entry should have been read", "/P1/src", entry.getPath().toString());
assertEquals("output location should have been read", "/P1/bin", jproj.readOutputLocation().toString());
}
}, null);
} finally {
// cleanup
this.deleteProject("P1");
}
}
/*
* Test classpath forced reload (20931) and new way to read classpath file (40658)
*/
public void testClasspathForceReload() throws CoreException {
try {
final JavaProject p1 = (JavaProject)this.createJavaProject("P1", new String[]{""}, new String[]{}, new String[]{}, "");
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
p1.getRawIncludepath(); // force to read classpath
createFolder("P1/src");
createFolder("P1/bin");
String newCPContent =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
+"<classpath> \n"
+" <classpathentry kind=\"src\" path=\"src\"/> \n"
+" <classpathentry kind=\"output\" path=\"bin\"/> \n"
+"</classpath> \n";
IFile fileRsc = p1.getProject().getFile(JavaProject.CLASSPATH_FILENAME);
fileRsc.setContents(new ByteArrayInputStream(newCPContent.getBytes()), true, false, null);
p1.close();
assertEquals("output location should not have been refreshed", "/P1", p1.getOutputLocation().toString());
p1.setRawIncludepath(p1.readRawIncludepath(), p1.readOutputLocation(), null);
assertEquals("output location should have been refreshed", "/P1/bin", p1.getOutputLocation().toString());
}
}, null);
} finally {
// cleanup
this.deleteProject("P1");
}
}
/**
* Ensures that the setting the classpath with a library entry
* changes the kind of the root from K_SOURCE to K_BINARY.
*/
public void testClasspathCreateLibraryEntry() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
this.createFile("P/src/X.js", "public class X {}");
this.createFile("P/src/X.class", "");
IFolder rootFolder = proj.getProject().getFolder(new Path("src"));
IPackageFragmentRoot root = proj.getPackageFragmentRoot(rootFolder);
assertEquals(
"Unexpected root kind 1",
IPackageFragmentRoot.K_SOURCE,
root.getKind());
IPackageFragment pkg = root.getPackageFragment("");
assertEquals(
"Unexpected numbers of compilation units",
1,
pkg.getJavaScriptUnits().length);
assertEquals(
"Unexpected numbers of .class files",
0,
pkg.getClassFiles().length);
this.setClasspath(
proj,
new IIncludePathEntry[] {
JavaScriptCore.newLibraryEntry(rootFolder.getFullPath(), null, null, false)
});
assertEquals(
"Unexpected root kind 2",
IPackageFragmentRoot.K_BINARY,
root.getKind());
assertEquals(
"Unexpected numbers of compilation units",
0,
pkg.getJavaScriptUnits().length);
assertEquals(
"Unexpected numbers of .class files",
1,
pkg.getClassFiles().length);
//ensure that the new kind has been persisted in the classpath file
proj.close();
assertEquals(
"Unexpected root kind 3",
IPackageFragmentRoot.K_BINARY,
root.getKind());
} finally {
this.deleteProject("P");
}
}
/**
* Ensures that the setting the classpath with a new library entry for a
* local jar works and generates the correct deltas.
*/
public void testClasspathCreateLocalJarLibraryEntry() throws CoreException {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {""}, "");
IPackageFragmentRoot root = getPackageFragmentRoot("P", "");
IIncludePathEntry newEntry= JavaScriptCore.newLibraryEntry(getExternalJCLPath(), null, null, false);
IIncludePathEntry[] newEntries= new IIncludePathEntry[]{newEntry};
IPackageFragmentRoot newRoot= proj.getPackageFragmentRoot(getExternalJCLPathString());
startDeltas();
setClasspath(proj,newEntries);
try {
assertTrue(
"should be one delta with 2 grand-children - removed & added",
this.deltaListener.deltas.length == 1 &&
this.deltaListener.deltas[0].getAffectedChildren().length == 1 &&
this.deltaListener.deltas[0].getAffectedChildren()[0].getAffectedChildren().length == 2);
IJavaScriptElementDelta d= null;
assertTrue("root should be removed from classpath",(d= getDeltaFor(root, true)) != null &&
(d.getFlags() & IJavaScriptElementDelta.F_REMOVED_FROM_CLASSPATH) > 0);
assertTrue("root should be added to classpath", (d= getDeltaFor(newRoot, true)) != null &&
(d.getFlags() & IJavaScriptElementDelta.F_ADDED_TO_CLASSPATH) > 0);
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/**
* Tests the cross project classpath setting
*/
public void testClasspathCrossProject() throws CoreException {
IJavaScriptProject project = this.createJavaProject("P1", new String[] {""}, "");
this.createJavaProject("P2", new String[] {}, "");
try {
startDeltas();
IPackageFragmentRoot oldRoot= getPackageFragmentRoot("P1", "");
IIncludePathEntry projectEntry= JavaScriptCore.newProjectEntry(new Path("/P2"), false);
IIncludePathEntry[] newClasspath= new IIncludePathEntry[]{projectEntry};
project.setRawIncludepath(newClasspath, null);
project.getAllPackageFragmentRoots();
IJavaScriptElementDelta removedDelta= getDeltaFor(oldRoot, true);
assertDeltas(
"Unexpected delta",
"<project root>[*]: {REMOVED FROM CLASSPATH}",
removedDelta);
} finally {
stopDeltas();
this.deleteProjects(new String[] {"P1", "P2"});
}
}
/**
* Delete a root and ensure the classpath is not updated (i.e. entry isn't removed).
*/
public void testClasspathDeleteNestedRoot() throws CoreException {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPathString()}, "bin");
IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src");
IIncludePathEntry[] originalCP= project.getRawIncludepath();
// delete the root
deleteResource(root.getUnderlyingResource());
IIncludePathEntry[] newCP= project.getRawIncludepath();
try {
// should still be an entry for the "src" folder
assertTrue("classpath should not have been updated",
newCP.length == 2 &&
newCP[0].equals(originalCP[0]) &&
newCP[1].equals(originalCP[1]));
} finally {
this.deleteProject("P");
}
}
/*
* Test classpath diamond (23979)
*/
public void testClasspathDiamond() throws CoreException {
try {
this.createJavaProject("P1", new String[]{""}, "");
this.createJavaProject("P2", new String[]{""}, new String[]{}, new String[]{"/P1"}, "");
this.createJavaProject("P3", new String[]{""}, new String[]{}, new String[]{"/P1", "/P2"}, "");
IJavaScriptProject p4 = this.createJavaProject("P4", new String[]{""}, new String[]{}, new String[]{"/P2", "/P3"}, "");
assertTrue("Should not detect cycle", !p4.hasIncludepathCycle(null));
} finally {
// cleanup
this.deleteProjects(new String[] {"P1", "P2", "P3", "P4"});
}
}
/**
* Delete a nested root's parent folder and ensure the classpath is
* not updated (i.e. entry isn't removed).
*/
public void testClasspathDeleteNestedRootParent() throws CoreException {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPathString()}, "bin");
IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src");
IIncludePathEntry[] originalCP= project.getRawIncludepath();
// delete the root's parent folder
IFolder folder= (IFolder)root.getUnderlyingResource().getParent();
deleteResource(folder);
IIncludePathEntry[] newCP= project.getRawIncludepath();
try {
// should still be an entry for the "src" folder
assertTrue("classpath should not have been updated",
newCP.length == 2 &&
newCP[0].equals(originalCP[0]) &&
newCP[1].equals(originalCP[1]));
} finally {
this.deleteProject("P");
}
}
/**
* Test that a classpath entry for an external jar is externalized
* properly.
*/
public void testClasspathExternalize() throws CoreException {
try {
IJavaScriptProject project= this.createJavaProject("P", new String[] {}, new String[] {getExternalJCLPathString()}, "");
IIncludePathEntry[] classpath= project.getRawIncludepath();
IIncludePathEntry jar= null;
for (int i= 0; i < classpath.length; i++) {
if (classpath[i].getEntryKind() == IIncludePathEntry.CPE_LIBRARY) {
jar= classpath[i];
break;
}
}
project.close();
project.open(null);
classpath= project.getRawIncludepath();
for (int i= 0; i < classpath.length; i++) {
if (classpath[i].getEntryKind() == IIncludePathEntry.CPE_LIBRARY) {
assertTrue("Paths must be the same", classpath[i].getPath().equals(jar.getPath()));
break;
}
}
} finally {
this.deleteProject("P");
}
}
/**
* Move a root and ensure the classpath is not updated (i.e. entry not renamed).
*/
public void testClasspathMoveNestedRoot() throws CoreException {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPathString()}, "bin");
IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src");
IIncludePathEntry[] originalCP= project.getRawIncludepath();
// delete the root
IFolder folder= (IFolder)root.getUnderlyingResource();
IPath originalPath= folder.getFullPath();
IPath newPath= originalPath.removeLastSegments(1);
newPath= newPath.append(new Path("newsrc"));
startDeltas();
folder.move(newPath, true, null);
IIncludePathEntry[] newCP= project.getRawIncludepath();
IPackageFragmentRoot newRoot= project.getPackageFragmentRoot(project.getProject().getFolder("nested").getFolder("newsrc"));
try {
// entry for the "src" folder wasn't replaced
assertTrue("classpath not automatically updated", newCP.length == 2 &&
newCP[1].equals(originalCP[1]) &&
newCP[0].equals(originalCP[0]));
IJavaScriptElementDelta rootDelta = getDeltaFor(root, true);
IJavaScriptElementDelta projectDelta = getDeltaFor(newRoot.getParent(), true);
assertTrue("should get delta for moved root", rootDelta != null &&
rootDelta.getKind() == IJavaScriptElementDelta.REMOVED &&
rootDelta.getFlags() == 0);
assertTrue("should get delta indicating content changed for project", this.deltaContentChanged(projectDelta));
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/**
* Move a parent of a nested root and ensure the classpath is not updated (i.e. entry not renamed).
*/
public void testClasspathMoveNestedRootParent() throws CoreException {
try {
IJavaScriptProject project =this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPathString()}, "bin");
IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src");
IIncludePathEntry[] originalCP= project.getRawIncludepath();
// delete the root
IFolder folder= (IFolder)root.getUnderlyingResource().getParent();
IPath originalPath= folder.getFullPath();
IPath newPath= originalPath.removeLastSegments(1);
newPath= newPath.append(new Path("newsrc"));
folder.move(newPath, true, null);
IIncludePathEntry[] newCP= project.getRawIncludepath();
// entry for the "src" folder wasn't replaced
// entry for the "src" folder should not be replaced
assertTrue("classpath should not automatically be updated", newCP.length == 2 &&
newCP[1].equals(originalCP[1]) &&
newCP[0].equals(originalCP[0]));
} finally {
this.deleteProject("P");
}
}
/**
* Tests that nothing occurs when setting to the same classpath
*/
public void testClasspathNoChanges() throws CoreException {
try {
IJavaScriptProject p = this.createJavaProject("P", new String[] {""}, "");
IIncludePathEntry[] oldClasspath= p.getRawIncludepath();
startDeltas();
p.setRawIncludepath(oldClasspath, null);
assertDeltas("Unexpected delta", "");
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/**
* Ensures that the setting the classpath with a reordered classpath generates
* the correct deltas.
*/
public void testClasspathReordering() throws CoreException {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, new String[] {getExternalJCLPathString()}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IPackageFragmentRoot root = getPackageFragmentRoot("P", "src");
try {
IIncludePathEntry[] newEntries = new IIncludePathEntry[originalCP.length];
int index = originalCP.length - 1;
for (int i = 0; i < originalCP.length; i++) {
newEntries[index] = originalCP[i];
index--;
}
startDeltas();
setClasspath(proj, newEntries);
assertTrue("should be one delta - two roots reordered", this.deltaListener.deltas.length == 1);
IJavaScriptElementDelta d = null;
assertTrue("root should be reordered in the classpath", (d = getDeltaFor(root, true)) != null
&& (d.getFlags() & IJavaScriptElementDelta.F_REORDER) > 0);
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/**
* Should detect duplicate entries on the classpath
*/
public void testClasspathValidation01() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = newCP[0];
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have detected duplicate entries on the classpath",
"Build path contains duplicate entry: \'src\' for project P",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should detect nested source folders on the classpath
*/
public void testClasspathValidation02() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have detected nested source folders on the classpath",
"Cannot nest \'P/src\' inside \'P\'. To enable the nesting exclude \'src/\' from \'P\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should detect library folder nested inside source folder on the classpath
*/
public void testClasspathValidation03() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newLibraryEntry(new Path("/P/src/lib"), null, null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have detected library folder nested inside source folder on the classpath",
"Cannot nest \'P/src/lib\' inside \'P/src\'. To enable the nesting exclude \'lib/\' from \'P/src\'",
status);
} finally {
this.deleteProject("P");
}
}
public void testClasspathValidation04() throws CoreException {
IJavaScriptProject[] p = null;
try {
p = new IJavaScriptProject[]{
this.createJavaProject("P0", new String[] {"src0"}, "bin0"),
this.createJavaProject("P1", new String[] {"src1"}, "bin1"),
};
JavaScriptCore.setIncludepathVariable("var", new Path("/P1"), null);
IIncludePathEntry[] newClasspath = new IIncludePathEntry[]{
JavaScriptCore.newSourceEntry(new Path("/P0/src0")),
JavaScriptCore.newVariableEntry(new Path("var/src1"), null, null),
};
// validate classpath
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(p[0], newClasspath, p[0].getOutputLocation());
assertStatus(
"should not detect external source folder through a variable on the classpath",
"OK",
status);
} finally {
this.deleteProjects(new String[] {"P0", "P1"});
}
}
public void testClasspathValidation05() throws CoreException {
IJavaScriptProject[] p = null;
try {
p = new IJavaScriptProject[]{
this.createJavaProject("P0", new String[] {"src0", "src1"}, "bin0"),
this.createJavaProject("P1", new String[] {"src1"}, "bin1"),
};
JavaScriptCore.setJsGlobalScopeContainer(
new Path("container/default"),
new IJavaScriptProject[]{ p[0] },
new IJsGlobalScopeContainer[] {
new TestContainer(new Path("container/default"),
new IIncludePathEntry[]{
JavaScriptCore.newSourceEntry(new Path("/P0/src0")),
JavaScriptCore.newVariableEntry(new Path("var/src1"), null, null) })
},
null);
IIncludePathEntry[] newClasspath = new IIncludePathEntry[]{
JavaScriptCore.newSourceEntry(new Path("/P0/src1")),
JavaScriptCore.newContainerEntry(new Path("container/default")),
};
// validate classpath
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(p[0], newClasspath, p[0].getOutputLocation());
assertStatus(
"should not have detected external source folder through a container on the classpath",
"OK",
status);
// validate classpath entry
status = JavaScriptConventions.validateClasspathEntry(p[0], newClasspath[1], true);
assertStatus(
"should have detected external source folder through a container on the classpath",
"Invalid classpath container: \'container/default\' in project P0",
status);
} finally {
this.deleteProjects(new String[] {"P0", "P1"});
}
}
public void testClasspathValidation06() throws CoreException {
IJavaScriptProject[] p = null;
try {
p = new IJavaScriptProject[]{
this.createJavaProject("P0", new String[] {"src"}, "src"),
};
// validate classpath entry
IIncludePathEntry[] newClasspath = new IIncludePathEntry[]{
JavaScriptCore.newSourceEntry(new Path("/P0")),
JavaScriptCore.newSourceEntry(new Path("/P0/src")),
};
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(p[0], newClasspath, p[0].getOutputLocation());
assertStatus(
"should have detected nested source folder",
"Cannot nest \'P0/src\' inside \'P0\'. To enable the nesting exclude \'src/\' from \'P0\'",
status);
} finally {
this.deleteProject("P0");
}
}
/**
* Should allow nested source folders on the classpath as long as the outer
* folder excludes the inner one.
*/
public void testClasspathValidation07() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[] {new Path("src/")});
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have allowed nested source folders with exclusion on the classpath",
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should allow a nested binary folder in a source folder on the classpath as
* long as the outer folder excludes the inner one.
*/
public void testClasspathValidation08() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, new String[] {"lib"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[] {new Path("lib/")});
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have allowed nested lib folders with exclusion on the classpath",
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow a nested source folder in the project's output folder.
*/
public void testClasspathValidation09() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/bin/src"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should not allow nested source folder in putput folder",
"Cannot nest \'P/bin/src\' inside output folder \'P/bin\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow a nested output folder in a source folder on the classpath.
*/
public void testClasspathValidation10() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, originalCP, new Path("/P/src/bin"));
assertStatus(
"should not allow nested output folder in source folder",
"Cannot nest output folder \'P/src/bin\' inside \'P/src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should allow a nested library folder in the project's output folder if the project's output is not used.
*/
public void testClasspathValidation11() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newLibraryEntry(new Path("/P/lib"), null, null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should allow nested library folder in output folder",
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow a nested source folder in an output folder.
*/
public void testClasspathValidation12() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin1");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] =
JavaScriptCore.newSourceEntry(
new Path("/P/bin2/src"),
new IPath[] {},
new Path("/P/bin2"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should not allow nested source folder in output folder",
"Cannot nest \'P/bin2/src\' inside output folder \'P/bin2\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow a nested output folder in a source folder on the classpath.
*/
public void testClasspathValidation13() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin1");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] =
JavaScriptCore.newSourceEntry(
new Path("/P/src"),
new IPath[] {},
new Path("/P/src/bin2"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should not allow nested output folder in source folder",
"Cannot nest output folder \'P/src/bin2\' inside \'P/src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should allow a nested output folder in a source folder that coincidate with the project.
*/
public void testClasspathValidation14() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] =
JavaScriptCore.newSourceEntry(
new Path("/P"),
new IPath[] {},
new Path("/P/bin"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should allow nested output folder in source folder which is project",
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow nested source folders on the classpath if exclusion filter has no trailing slash.
*/
public void testClasspathValidation15() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[] {new Path("**/src")});
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"End exclusion filter \'src\' with / to fully exclude \'P/src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should allow custom output folder to be nested in default output folder if default output is not used.
* (regression test for bug 28596 Default output folder cause of validation error even if not used)
*/
public void testClasspathValidation16() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[0], new Path("/P/bin"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow source folder to be nested in default output folder if default output is used.
*/
public void testClasspathValidation17() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src1"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/bin/src2"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest \'P/bin/src2\' inside output folder \'P/bin\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow custom output folder to be external to project.
* (regression test for bug 29079 Buildpath validation: No check that output folder is inside project)
*/
public void testClasspathValidation18() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], new Path("/S/bin"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Path \'/S/bin\' must denote location inside project P",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should detect source folder nested inside library folder on the classpath
*/
public void testClasspathValidation19() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, new String[] {"lib"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/lib/src"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have detected library folder nested inside source folder on the classpath",
"Cannot nest \'P/lib/src\' inside library \'P/lib\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow custom output folder if project preference disallow them
*/
public void testClasspathValidation20() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], new Path("/S/bin"));
Map options = new Hashtable(5);
options.put(JavaScriptCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaScriptCore.DISABLED);
proj.setOptions(options);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Multiple output locations are disabled in project P, cannot associate entry: \'src\' with a specific output",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow exclusion patterns if project preference disallow them
*/
public void testClasspathValidation21() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[]{new Path("**/src")}, null);
Map options = new Hashtable(5);
options.put(JavaScriptCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaScriptCore.DISABLED);
proj.setOptions(options);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Inclusion or exclusion patterns are disabled in project P, cannot selectively include or exclude from entry: \'src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* 33207 - Reject output folder that coincidate with distinct source folder
*/
public void testClasspathValidation22() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], new Path("/P/src2"));
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/src2"), new IPath[0], new Path("/P/src"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Source folder \'src\' in project P cannot output to distinct source folder \'src2\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* 33207 - Reject output folder that coincidate with distinct source folder
* but 36465 - Unable to create multiple source folders when not using bin for output
* default output scenarii is still tolerated
*/
public void testClasspathValidation23() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/"), new IPath[]{new Path("src/")}, null);
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"OK",
status);
// assertStatus(
// "Source folder 'P/src' cannot output to distinct source folder 'P/'.",
// status);
} finally {
this.deleteProject("P");
}
}
/**
* Ensure one cannot nest source entry inside default output folder
*/
public void testClasspathValidation24() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest \'P/src\' inside output folder \'P\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Reject output folder that coincidate with library folder
*/
public void testClasspathValidation25() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], new Path("/P/lib2"));
newCP[originalCP.length+1] = JavaScriptCore.newLibraryEntry(new Path("/P/lib2"), null, null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Source folder \'src\' in project P cannot output to library \'lib2\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Reject output folder that coincidate with library folder
* default output scenarii
*/
public void testClasspathValidation26() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newLibraryEntry(new Path("/P/"), null, null);
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest \'P/src\' inside library \'P/\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks diagnosis for incompatible binary versions
*/
public void testClasspathValidation27() throws CoreException {
try {
IJavaScriptProject proj1 = this.createJavaProject("P1", new String[] {}, "");
proj1.setOption(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_4);
IJavaScriptProject proj2 = this.createJavaProject("P2", new String[] {}, "");
proj2.setOption(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_1);
proj2.setOption(JavaScriptCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaScriptCore.WARNING);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspathEntry(proj2, JavaScriptCore.newProjectEntry(new Path("/P1")), false);
assertStatus(
"Incompatible .class files version in required binaries. Project \'P2\' is targeting a 1.1 runtime, but is compiled against \'P1\' which requires a 1.4 runtime",
status);
} finally {
this.deleteProjects(new String[]{"P1", "P2"});
}
}
/**
* @bug 159325: Any idea why ClasspathEntry checks for string object reference instead of equals
* @test Ensure that validation is correctly done even for other strings than JavaScriptCore constants...
* Note that it's needed to change JavaScriptCore options as "ignore" is the default value and set option
* to this value on java project will just remove it instead of putting another string object...
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=159325"
*/
public void testClasspathValidation27_Bug159325_project() throws CoreException {
Hashtable javaCoreOptions = JavaScriptCore.getOptions();
try {
IJavaScriptProject proj1 = this.createJavaProject("P1", new String[] {}, "");
proj1.setOption(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_4);
Hashtable options = JavaScriptCore.getOptions();
options.put(JavaScriptCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaScriptCore.WARNING);
JavaScriptCore.setOptions(options);
IJavaScriptProject proj2 = this.createJavaProject("P2", new String[] {}, "");
proj2.setOption(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_1);
proj2.setOption(JavaScriptCore.CORE_INCOMPATIBLE_JDK_LEVEL, new String("ignore".toCharArray()));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspathEntry(proj2, JavaScriptCore.newProjectEntry(new Path("/P1")), false);
assertStatus("OK", status);
} finally {
JavaScriptCore.setOptions(javaCoreOptions);
this.deleteProjects(new String[]{"P1", "P2"});
}
}
public void testClasspathValidation27_Bug159325_lib() throws CoreException {
Hashtable javaCoreOptions = JavaScriptCore.getOptions();
try {
IJavaScriptProject proj = this.createJavaProject("P1", new String[] {}, "");
proj.setOption(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_1);
Hashtable options = JavaScriptCore.getOptions();
options.put(JavaScriptCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaScriptCore.WARNING);
JavaScriptCore.setOptions(options);
proj.setOption(JavaScriptCore.CORE_INCOMPATIBLE_JDK_LEVEL, new String("ignore".toCharArray()));
IIncludePathEntry library = JavaScriptCore.newLibraryEntry(new Path(getExternalJCLPathString(JavaScriptCore.VERSION_1_5)), null, null, ClasspathEntry.NO_ACCESS_RULES, null, false);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspathEntry(proj, library, false);
assertStatus("OK", status);
} finally {
JavaScriptCore.setOptions(javaCoreOptions);
this.deleteProjects(new String[]{"P1", "P2"});
}
}
/**
* Checks it is legal for an output folder to be an excluded subfolder of some source folder
*/
public void testClasspathValidation28() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[]{ new Path("output/") }, new Path("/P/src/output"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Source folder \'src\' in project P should be allowed to output to excluded source subfolder \'src/output\'",
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks it is illegal for an output folder to be a subfolder of some source folder
*/
public void testClasspathValidation29() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[0], new Path("/P/src/output"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest output folder \'P/src/output\' inside \'P/src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks it is illegal for a nested output folder (sitting inside excluded range of source folder) to be enclosing another source folder
*/
public void testClasspathValidation30() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src1"), new IPath[]{new Path("bin/")}, new Path("/P/src1/bin"));
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/src1/bin/src2"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest \'P/src1/bin/src2\' inside output folder \'P/src1/bin\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks it is illegal for a nested output folder (sitting inside excluded range of source folder) to be nested in another source folder
*/
public void testClasspathValidation31() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src1"), new IPath[]{new Path("src2/")}, new Path("/P/src1/src2/bin"));
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/src1/src2"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest output folder \'P/src1/src2/bin\' inside \'P/src1/src2\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks it is illegal for a nested output folder (sitting inside excluded range of source folder) to be coincidating with another source folder
*/
public void testClasspathValidation32() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src1"), new IPath[]{new Path("src2/")}, new Path("/P/src1/src2"));
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/src1/src2"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Source folder \'src1\' in project P cannot output to distinct source folder \'src1/src2\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks it is illegal for a source folder to be nested in an output folder (42579)
*/
public void testClasspathValidation33() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/dir/src"), new IPath[]{new Path("src2/")}, new Path("/P/dir"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest \'P/dir/src\' inside output folder \'P/dir\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow nested source folders on the classpath if the outer
* folder includes the inner one.
*/
public void testClasspathValidation34() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[] {new Path("src/")}, new IPath[0], null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should not have allowed nested source folders with inclusion on the classpath",
"Cannot nest \'P/src\' inside \'P\'. To enable the nesting exclude \'src/\' from \'P\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow a nested binary folder in a source folder on the classpath
* if the outer folder includes the inner one.
*/
public void testClasspathValidation35() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, new String[] {"lib"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[] {new Path("lib/")}, new Path[0], null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should not have allowed nested lib folders with inclusion on the classpath",
"Cannot nest \'P/lib\' inside \'P\'. To enable the nesting exclude \'lib/\' from \'P\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should allow nested source folders on the classpath if inclusion filter has no trailing slash.
*/
public void testClasspathValidation36() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[] {new Path("**/src")}, new Path[0], null);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"OK",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Should not allow inclusion patterns if project preference disallow them
*/
public void testClasspathValidation37() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[]{new Path("**/src")}, new Path[0], null);
Map options = new Hashtable(5);
options.put(JavaScriptCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaScriptCore.DISABLED);
proj.setOptions(options);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Inclusion or exclusion patterns are disabled in project P, cannot selectively include or exclude from entry: \'src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Checks it is illegal for an output folder to be an included subfolder of some source folder
*/
public void testClasspathValidation38() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[]{ new Path("output/") }, new Path[0], new Path("/P/src/output"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Source folder \'src\' in project P should not be allowed to output to included source subfolder \'src/output\'",
"Cannot nest output folder \'P/src/output\' inside \'P/src\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* 62713 - check nested output folder detection
*/
public void testClasspathValidation39() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[]{new Path("test/")}, new Path("/P/bin/test"));
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/test"), new IPath[]{}, new Path("/P/bin"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest output folder \'P/bin/test\' inside output folder \'P/bin\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* 62713 - variation
*/
public void testClasspathValidation40() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+2];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[]{new Path("test/")}, new Path("/P/bin"));
newCP[originalCP.length+1] = JavaScriptCore.newSourceEntry(new Path("/P/test"), new IPath[]{}, new Path("/P/bin/test"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest output folder \'P/bin/test\' inside output folder \'P/bin\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* 62713 - variation
*/
public void testClasspathValidation41() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "bin");
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P/src"), new IPath[]{}, new Path("/P/"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"Cannot nest \'P/src\' inside output folder \'P/\'",
status);
} finally {
this.deleteProject("P");
}
}
/*
* Should detect nested source folders on the classpath and indicate the preference if disabled
* (regression test for bug 122615 validate classpath propose to exlude a source folder even though exlusion patterns are disabled)
*/
public void testClasspathValidation42() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {"src"}, "bin");
proj.setOption(JavaScriptCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaScriptCore.DISABLED);
IIncludePathEntry[] originalCP = proj.getRawIncludepath();
IIncludePathEntry[] newCP = new IIncludePathEntry[originalCP.length+1];
System.arraycopy(originalCP, 0, newCP, 0, originalCP.length);
newCP[originalCP.length] = JavaScriptCore.newSourceEntry(new Path("/P"));
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspath(proj, newCP, proj.getOutputLocation());
assertStatus(
"should have detected nested source folders on the classpath",
"Cannot nest \'P/src\' inside \'P\'. To allow the nesting enable use of exclusion patterns in the preferences of project \'P\' and exclude \'src/\' from \'P\'",
status);
} finally {
this.deleteProject("P");
}
}
/**
* Setting the classpath with two entries specifying the same path
* should fail.
*/
public void testClasspathWithDuplicateEntries() throws CoreException {
try {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] cp= project.getRawIncludepath();
IIncludePathEntry[] newCp= new IIncludePathEntry[cp.length *2];
System.arraycopy(cp, 0, newCp, 0, cp.length);
System.arraycopy(cp, 0, newCp, cp.length, cp.length);
try {
project.setRawIncludepath(newCp, null);
} catch (JavaScriptModelException jme) {
return;
}
assertTrue("Setting the classpath with two entries specifying the same path should fail", false);
} finally {
this.deleteProject("P");
}
}
/**
* Bug 94404: [model] Disallow classpath attributes with same key
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=94404"
*/
public void testClasspathDuplicateExtraAttribute() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P1", new String[] {}, "bin");
IIncludePathAttribute[] extraAttributes = new IIncludePathAttribute[2];
extraAttributes[0] = JavaScriptCore.newIncludepathAttribute("javadoc_location", "http://www.sample-url.org/doc/");
extraAttributes[1] = JavaScriptCore.newIncludepathAttribute("javadoc_location", "d:/tmp");
// Verify container entry validation
IIncludePathEntry container = JavaScriptCore.newContainerEntry(new Path("JRE_CONTAINER"), ClasspathEntry.NO_ACCESS_RULES, extraAttributes, false);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspathEntry(proj, container, false);
assertStatus(
"Duplicate extra attribute: \'javadoc_location\' in classpath entry \'JRE_CONTAINER\' for project P1",
status);
// Verify library entry validation
IIncludePathEntry library = JavaScriptCore.newLibraryEntry(new Path(getExternalJCLPathString()), null, null, ClasspathEntry.NO_ACCESS_RULES, extraAttributes, false);
status = JavaScriptConventions.validateClasspathEntry(proj, library, false);
assertStatus(
"Duplicate extra attribute: \'javadoc_location\' in classpath entry \'"+getExternalJCLPath()+"\' for project P1",
status);
// Verify project entry validation
createJavaProject("P2");
IIncludePathEntry projectEntry = JavaScriptCore.newProjectEntry(new Path("/P2"), ClasspathEntry.NO_ACCESS_RULES, false, extraAttributes, false);
status = JavaScriptConventions.validateClasspathEntry(proj, projectEntry, false);
assertStatus(
"Duplicate extra attribute: \'javadoc_location\' in classpath entry \'/P2\' for project P1",
status);
// Verify source entry validation
createFolder("/P1/src");
IIncludePathEntry sourceEntry = JavaScriptCore.newSourceEntry(new Path("/P1/src"), new IPath[0], new IPath[0], null, extraAttributes);
status = JavaScriptConventions.validateClasspathEntry(proj, sourceEntry, false);
assertStatus(
"Duplicate extra attribute: \'javadoc_location\' in classpath entry \'src\' for project P1",
status);
// Verify variable entry validation
IIncludePathEntry variable = JavaScriptCore.newVariableEntry(new Path("JCL_LIB"), new Path("JCL_SRC"), null, ClasspathEntry.NO_ACCESS_RULES, extraAttributes, false);
status = JavaScriptConventions.validateClasspathEntry(proj, variable, false);
assertStatus(
"Duplicate extra attribute: \'javadoc_location\' in classpath entry \'"+getExternalJCLPath()+"\' for project P1",
status);
} finally {
this.deleteProject("P1");
this.deleteProject("P2");
}
}
/**
* Adding an entry to the classpath for a library that does not exist
* should not break the model. The classpath should contain the
* entry, but the root should not appear in the children.
*/
public void testClasspathWithNonExistentLibraryEntry() throws CoreException {
try {
IJavaScriptProject project= this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalPath= project.getRawIncludepath();
IPackageFragmentRoot[] originalRoots= project.getPackageFragmentRoots();
IIncludePathEntry[] newPath= new IIncludePathEntry[originalPath.length + 1];
System.arraycopy(originalPath, 0, newPath, 0, originalPath.length);
IIncludePathEntry newEntry= JavaScriptCore.newLibraryEntry(new Path("c:/nothing/nozip.jar").makeAbsolute(), null, null, false);
newPath[originalPath.length]= newEntry;
project.setRawIncludepath(newPath, null);
IIncludePathEntry[] getPath= project.getRawIncludepath();
assertTrue("should be the same length", getPath.length == newPath.length);
for (int i= 0; i < getPath.length; i++) {
assertTrue("entries should be the same", getPath[i].equals(newPath[i]));
}
IPackageFragmentRoot[] newRoots= project.getPackageFragmentRoots();
assertTrue("Should be the same number of roots", originalRoots.length == newRoots.length);
for (int i= 0; i < newRoots.length; i++) {
assertTrue("roots should be the same", originalRoots[i].equals(newRoots[i]));
}
} finally {
this.deleteProject("P");
}
}
/**
* Adding an entry to the classpath for a project that does not exist
* should not break the model. The classpath should contain the
* entry, but the root should not appear in the children.
*/
public void testClasspathWithNonExistentProjectEntry() throws CoreException {
try {
IJavaScriptProject project= this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalPath= project.getRawIncludepath();
IPackageFragmentRoot[] originalRoots= project.getPackageFragmentRoots();
IIncludePathEntry[] newPath= new IIncludePathEntry[originalPath.length + 1];
System.arraycopy(originalPath, 0, newPath, 0, originalPath.length);
IIncludePathEntry newEntry= JavaScriptCore.newProjectEntry(new Path("/NoProject"), false);
newPath[originalPath.length]= newEntry;
project.setRawIncludepath(newPath, null);
IIncludePathEntry[] getPath= project.getRawIncludepath();
assertTrue("should be the same length", getPath.length == newPath.length);
for (int i= 0; i < getPath.length; i++) {
assertTrue("entries should be the same", getPath[i].equals(newPath[i]));
}
IPackageFragmentRoot[] newRoots= project.getPackageFragmentRoots();
assertTrue("Should be the same number of roots", originalRoots.length == newRoots.length);
for (int i= 0; i < newRoots.length; i++) {
assertTrue("roots should be the same", originalRoots[i].equals(newRoots[i]));
}
} finally {
this.deleteProject("P");
}
}
/**
* Adding an entry to the classpath for a folder that does not exist
* should not break the model. The classpath should contain the
* entry, but the root should not appear in the children.
*/
public void testClasspathWithNonExistentSourceEntry() throws CoreException {
try {
IJavaScriptProject project= this.createJavaProject("P", new String[] {"src"}, "bin");
IIncludePathEntry[] originalPath= project.getRawIncludepath();
IPackageFragmentRoot[] originalRoots= project.getPackageFragmentRoots();
IIncludePathEntry[] newPath= new IIncludePathEntry[originalPath.length + 1];
System.arraycopy(originalPath, 0, newPath, 0, originalPath.length);
IIncludePathEntry newEntry= JavaScriptCore.newSourceEntry(new Path("/P/moreSource"));
newPath[originalPath.length]= newEntry;
project.setRawIncludepath(newPath, null);
IIncludePathEntry[] getPath= project.getRawIncludepath();
assertTrue("should be the same length", getPath.length == newPath.length);
for (int i= 0; i < getPath.length; i++) {
assertTrue("entries should be the same", getPath[i].equals(newPath[i]));
}
IPackageFragmentRoot[] newRoots= project.getPackageFragmentRoots();
assertTrue("Should be the same number of roots", originalRoots.length == newRoots.length);
for (int i= 0; i < newRoots.length; i++) {
assertTrue("roots should be the same", originalRoots[i].equals(newRoots[i]));
}
} finally {
this.deleteProject("P");
}
}
/**
* Ensure that cycle are properly reported.
*/
public void testCycleReport() throws CoreException {
try {
IJavaScriptProject p1 = this.createJavaProject("P1", new String[] {""}, "");
IJavaScriptProject p2 = this.createJavaProject("P2", new String[] {""}, "");
IJavaScriptProject p3 = this.createJavaProject("P3", new String[] {""}, new String[] {}, new String[] {"/P2"}, "");
// Ensure no cycle reported
IJavaScriptProject[] projects = { p1, p2, p3 };
int cycleMarkerCount = 0;
for (int i = 0; i < projects.length; i++){
cycleMarkerCount += this.numberOfCycleMarkers(projects[i]);
}
assertTrue("Should have no cycle markers", cycleMarkerCount == 0);
// Add cycle
IIncludePathEntry[] originalP1CP= p1.getRawIncludepath();
IIncludePathEntry[] originalP2CP= p2.getRawIncludepath();
// Add P1 as a prerequesite of P2
int length = originalP2CP.length;
IIncludePathEntry[] newCP= new IIncludePathEntry[length + 1];
System.arraycopy(originalP2CP, 0 , newCP, 0, length);
newCP[length]= JavaScriptCore.newProjectEntry(p1.getProject().getFullPath(), false);
p2.setRawIncludepath(newCP, null);
// Add P3 as a prerequesite of P1
length = originalP1CP.length;
newCP= new IIncludePathEntry[length + 1];
System.arraycopy(originalP1CP, 0 , newCP, 0, length);
newCP[length]= JavaScriptCore.newProjectEntry(p3.getProject().getFullPath(), false);
p1.setRawIncludepath(newCP, null);
waitForAutoBuild(); // wait for cycle markers to be created
cycleMarkerCount = 0;
for (int i = 0; i < projects.length; i++){
cycleMarkerCount += numberOfCycleMarkers(projects[i]);
}
assertEquals("Unexpected number of projects involved in a classpath cycle", 3, cycleMarkerCount);
} finally {
// cleanup
deleteProjects(new String[] {"P1", "P2", "P3"});
}
}
/**
* Ensures that the default classpath and output locations are correct.
* The default classpath should be the root of the project.
* The default output location should be the root of the project.
*/
public void testDefaultClasspathAndOutputLocation() throws CoreException {
try {
IJavaScriptProject project = this.createJavaProject("P", new String[] {""}, "bin");
IIncludePathEntry[] classpath = project.getRawIncludepath();
assertTrue("Incorrect default classpath; to many entries", classpath.length == 1);
assertTrue("Incorrect default classpath: " + classpath[0], classpath[0].getPath().equals(project.getUnderlyingResource().getFullPath()));
IPath output = project.getOutputLocation();
assertTrue("Incorrect default output location: " + output.toOSString(), output.equals(project.getUnderlyingResource().getFullPath().append("bin")));
} finally {
this.deleteProject("P");
}
}
/**
* Setting the classpath to empty should result in no entries,
* and a delta with removed roots.
*/
public void testEmptyClasspath() throws CoreException {
IJavaScriptProject project = this.createJavaProject("P", new String[] {""}, "");
try {
startDeltas();
setClasspath(project, new IIncludePathEntry[] {});
IIncludePathEntry[] cp= project.getRawIncludepath();
assertTrue("classpath should have no entries", cp.length == 0);
// ensure the deltas are correct
assertDeltas(
"Unexpected delta",
"P[*]: {CHILDREN | CONTENT | CLASSPATH CHANGED}\n" +
" <project root>[*]: {REMOVED FROM CLASSPATH}\n" +
" ResourceDelta(/P/.classpath)[*]"
);
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/*
* Ensures that a source folder that contains character that must be encoded can be written.
* (regression test for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=70193)
*/
public void testEncoding() throws CoreException {
try {
createJavaProject("P", new String[] {"src\u3400"}, "bin");
IFile file = getFile("/P/.classpath");
String encodedContents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(file, "UTF-8"));
encodedContents = Util.convertToIndependantLineDelimiter(encodedContents);
assertEquals(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src\u3400\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n",
encodedContents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that a source classpath entry can be encoded and decoded.
*/
public void testEncodeDecodeEntry01() {
assertEncodeDecodeEntry(
"P",
"<classpathentry kind=\"src\" path=\"src\"/>\n",
JavaScriptCore.newSourceEntry(new Path("/P/src"))
);
}
/*
* Ensures that a source classpath entry with all possible attributes can be encoded and decoded.
*/
public void testEncodeDecodeEntry02() {
assertEncodeDecodeEntry(
"P",
"<classpathentry excluding=\"**/X.java\" including=\"**/Y.java\" kind=\"src\" output=\"bin\" path=\"src\">\n" +
" <attributes>\n" +
" <attribute name=\"attrName\" value=\"some value\"/>\n" +
" </attributes>\n" +
"</classpathentry>\n",
JavaScriptCore.newSourceEntry(
new Path("/P/src"),
new IPath[] {new Path("**/Y.js")},
new IPath[] {new Path("**/X.js")},
new Path("/P/bin"),
new IIncludePathAttribute[] {JavaScriptCore.newIncludepathAttribute("attrName", "some value")})
);
}
/*
* Ensures that a project classpath entry can be encoded and decoded.
*/
public void testEncodeDecodeEntry03() {
assertEncodeDecodeEntry(
"P1",
"<classpathentry kind=\"src\" path=\"/P2\"/>\n",
JavaScriptCore.newProjectEntry(new Path("/P2"))
);
}
/*
* Ensures that a library classpath entry can be encoded and decoded.
*/
public void testEncodeDecodeEntry04() {
assertEncodeDecodeEntry(
"P",
"<classpathentry exported=\"true\" kind=\"lib\" path=\"lib.jar\" rootpath=\"root\" sourcepath=\"src.zip\">\n" +
" <attributes>\n" +
" <attribute name=\"attr1\" value=\"val1\"/>\n" +
" </attributes>\n" +
" <accessrules>\n" +
" <accessrule kind=\"accessible\" pattern=\"**/A*.java\"/>\n" +
" </accessrules>\n" +
"</classpathentry>\n",
JavaScriptCore.newLibraryEntry(
new Path("/P/lib.jar"),
new Path("/P/src.zip"),
new Path("root"),
new IAccessRule[] {JavaScriptCore.newAccessRule(new Path("**/A*.js"), IAccessRule.K_ACCESSIBLE)},
new IIncludePathAttribute[] {JavaScriptCore.newIncludepathAttribute("attr1", "val1")},
true)
);
}
/*
* Ensures that a library classpath entry can be encoded and decoded.
*/
public void testEncodeDecodeEntry05() {
assertEncodeDecodeEntry(
"P",
"<classpathentry exported=\"true\" kind=\"lib\" path=\"lib.jar\" rootpath=\"root\" sourcepath=\"src.zip\">\n" +
" <attributes>\n" +
" <attribute name=\"attr1\" value=\"val1\"/>\n" +
" </attributes>\n" +
" <accessrules>\n" +
" <accessrule ignoreifbetter=\"true\" kind=\"accessible\" pattern=\"**/A*.java\"/>\n" +
" </accessrules>\n" +
"</classpathentry>\n",
JavaScriptCore.newLibraryEntry(
new Path("/P/lib.jar"),
new Path("/P/src.zip"),
new Path("root"),
new IAccessRule[] {JavaScriptCore.newAccessRule(new Path("**/A*.js"), IAccessRule.K_ACCESSIBLE | IAccessRule.IGNORE_IF_BETTER)},
new IIncludePathAttribute[] {JavaScriptCore.newIncludepathAttribute("attr1", "val1")},
true)
);
}
/**
* Ensures that adding an empty classpath container
* generates the correct deltas.
*/
public void testEmptyContainer() throws CoreException {
try {
IJavaScriptProject proj = createJavaProject("P", new String[] {}, "bin");
startDeltas();
// create container
JavaScriptCore.setJsGlobalScopeContainer(
new Path("container/default"),
new IJavaScriptProject[]{ proj },
new IJsGlobalScopeContainer[] {
new TestContainer(
new Path("container/default"),
new IIncludePathEntry[] {})
},
null);
// set P's classpath with this container
IIncludePathEntry container = JavaScriptCore.newContainerEntry(new Path("container/default"), true);
proj.setRawIncludepath(new IIncludePathEntry[] {container}, new Path("/P"), null);
assertDeltas(
"Unexpected delta",
"P[*]: {CONTENT | CLASSPATH CHANGED}\n" +
" ResourceDelta(/P/.classpath)[*]"
);
} finally {
stopDeltas();
this.deleteProject("P");
}
}
/*
* Ensure that a .classpath with an empty inclusion pattern is correctly handled
* (regression test for bug 105581 Creating a Java project from existing source fails because of "Unhandled event loop exception":)
*/
public void testEmptyInclusionPattern() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {""}, "bin");
project.open(null);
editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry including=\"X.java|\" kind=\"src\" path=\"\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
project.getProject().close(null);
project.getProject().open(null);
project.getPackageFragmentRoot(project.getProject()).open(null);
IIncludePathEntry[] classpath = project.getRawIncludepath();
assertClasspathEquals(
classpath,
"/P[CPE_SOURCE][K_SOURCE][isExported:false][including:X.java]"
);
} finally {
deleteProject("P");
}
}
/**
* Exporting a container should make it visible to its dependent project.
* (regression test for bug 21749 Exported libraries and source folders)
*/
public void testExportContainer() throws CoreException {
try {
IJavaScriptProject p1 = this.createJavaProject("P1", new String[] {""}, "");
// create container
JavaScriptCore.setJsGlobalScopeContainer(
new Path("container/default"),
new IJavaScriptProject[]{ p1 },
new IJsGlobalScopeContainer[] {
new TestContainer(
new Path("container/default"),
new IIncludePathEntry[] {
JavaScriptCore.newLibraryEntry(getExternalJCLPath(), null, null)
})
},
null);
// set P1's classpath with this container
IIncludePathEntry container = JavaScriptCore.newContainerEntry(new Path("container/default"), true);
p1.setRawIncludepath(new IIncludePathEntry[] {container}, new Path("/P1"), null);
// create dependent project P2
IJavaScriptProject p2 = this.createJavaProject("P2", new String[] {}, new String[] {}, new String[] {"/P1"}, "");
IIncludePathEntry[] classpath = ((JavaProject)p2).getExpandedClasspath();
// ensure container is exported to P2
assertEquals("Unexpected number of classpath entries", 2, classpath.length);
assertEquals("Unexpected first entry", "/P1", classpath[0].getPath().toString());
assertEquals("Unexpected second entry", getExternalJCLPathString(), classpath[1].getPath().toOSString());
} finally {
this.deleteProjects(new String[] {"P1", "P2"});
}
}
/*
* Ensures that setting 0 extra classpath attributes generates the correct .classpath file.
*/
public void testExtraAttributes1() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
IIncludePathEntry entry = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[0], new IPath[0], null, new IIncludePathAttribute[] {});
project.setRawIncludepath(new IIncludePathEntry[] {entry}, null);
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"\"/>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that setting 1 extra classpath attributes generates the correct .classpath file.
*/
public void testExtraAttributes2() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
IIncludePathAttribute attribute = JavaScriptCore.newIncludepathAttribute("foo", "some value");
IIncludePathEntry entry = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[0], new IPath[0], null, new IIncludePathAttribute[] {attribute});
project.setRawIncludepath(new IIncludePathEntry[] {entry}, null);
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"\">\n" +
" <attributes>\n" +
" <attribute name=\"foo\" value=\"some value\"/>\n" +
" </attributes>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that setting 2 extra classpath attributes generates the correct .classpath file.
*/
public void testExtraAttributes3() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
IIncludePathAttribute attribute1 = JavaScriptCore.newIncludepathAttribute("foo", "some value");
IIncludePathAttribute attribute2 = JavaScriptCore.newIncludepathAttribute("bar", "other value");
IIncludePathEntry entry = JavaScriptCore.newSourceEntry(new Path("/P"), new IPath[0], new IPath[0], null, new IIncludePathAttribute[] {attribute1, attribute2});
project.setRawIncludepath(new IIncludePathEntry[] {entry}, null);
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"\">\n" +
" <attributes>\n" +
" <attribute name=\"foo\" value=\"some value\"/>\n" +
" <attribute name=\"bar\" value=\"other value\"/>\n" +
" </attributes>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that extra classpath attributes in a .classpath file are correctly read.
*/
public void testExtraAttributes4() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"\">\n" +
" <attributes>\n" +
" <attribute value=\"some value\" name=\"foo\"/>\n" +
" </attributes>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n"
);
assertClasspathEquals(
project.getRawIncludepath(),
"/P[CPE_SOURCE][K_SOURCE][isExported:false][attributes:foo=some value]"
);
} finally {
deleteProject("P");
}
}
/**
* Test IJavaScriptProject.hasClasspathCycle(IIncludePathEntry[]).
*/
public void testHasClasspathCycle() throws CoreException {
try {
IJavaScriptProject p1 = this.createJavaProject("P1", new String[] {""}, "");
IJavaScriptProject p2 = this.createJavaProject("P2", new String[] {""}, "");
this.createJavaProject("P3", new String[] {""}, new String[] {}, new String[] {"/P1"}, "");
IIncludePathEntry[] originalP1CP= p1.getRawIncludepath();
IIncludePathEntry[] originalP2CP= p2.getRawIncludepath();
// Ensure no cycle reported
assertTrue("P1 should not have a cycle", !p1.hasIncludepathCycle(originalP1CP));
// Ensure that adding NervousTest as a prerequesite of P2 doesn't report a cycle
int length = originalP2CP.length;
IIncludePathEntry[] newCP= new IIncludePathEntry[length + 1];
System.arraycopy(originalP2CP, 0 , newCP, 0, length);
newCP[length]= JavaScriptCore.newProjectEntry(p1.getProject().getFullPath(), false);
assertTrue("P2 should not have a cycle", !p2.hasIncludepathCycle(newCP));
p2.setRawIncludepath(newCP, null);
// Ensure that adding P3 as a prerequesite of P1 reports a cycle
length = originalP1CP.length;
newCP= new IIncludePathEntry[length + 1];
System.arraycopy(originalP1CP, 0 , newCP, 0, length);
newCP[length]= JavaScriptCore.newProjectEntry(p2.getProject().getFullPath(), false);
assertTrue("P3 should have a cycle", p2.hasIncludepathCycle(newCP));
// Ensure a cycle is not reported through markers
IWorkspace workspace = getJavaModel().getWorkspace();
IMarker[] markers = workspace.getRoot().findMarkers(IJavaScriptModelMarker.TRANSIENT_PROBLEM, true, 1);
boolean hasCycleMarker = false;
for (int i = 0; i < markers.length; i++){
if (markers[i].getAttribute(IJavaScriptModelMarker.CYCLE_DETECTED) != null) {
hasCycleMarker = true;
break;
}
}
assertTrue("Should have no cycle markers", !hasCycleMarker);
} finally {
// cleanup
this.deleteProjects(new String[] {"P1", "P2", "P3"});
}
}
/**
* Ensures that a marker is created if editing the .classpath results in an invalid classpath.
*/
public void testInvalidClasspath1() throws CoreException {
try {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"src"}, "bin");
this.editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src\"/\n" + // missing closing >
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
assertMarkers(
"Unexpected markers",
"XML format error in \'.classpath\' file of project P: Bad format",
project);
} finally {
this.deleteProject("P");
}
}
/**
* Ensures that a marker is created if editing the .classpath results in an invalid classpath.
*/
public void testInvalidClasspath2() throws CoreException {
try {
IJavaScriptProject javaProject = this.createJavaProject("P", new String[] {"src"}, "bin");
this.editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src1\" path=\"src\"/>\n" + // invalid kind: src1
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
assertMarkers(
"Unexpected markers",
"Illegal entry in \'.classpath\' of project P file: Unknown kind: \'src1\'",
javaProject);
// Verify that error marker is not removed after build
// (regression test for bug 42366: Classpath validation error message removed while rebuilding a project.)
IProject project = javaProject.getProject();
project.build(IncrementalProjectBuilder.FULL_BUILD, null);
waitForAutoBuild();
assertMarkers(
"Unexpected markers",
"Illegal entry in \'.classpath\' of project P file: Unknown kind: \'src1\'",
javaProject);
} finally {
this.deleteProject("P");
}
}
/*
* Ensures that an external class folder cannot be put on the classpath.
*/
public void testInvalidExternalClassFolder() throws CoreException {
try {
String externalPath = getExternalPath();
// remove trailing slash
if (Path.fromOSString(externalPath).segmentCount() > 0)
externalPath = externalPath.substring(0, externalPath.length()-1);
IJavaScriptProject proj = createJavaProject("P", new String[] {}, new String[] {externalPath}, "bin");
assertMarkers(
"Unexpected markers",
"Required library cannot denote external folder: \'" + externalPath + "\' for project P",
proj);
} finally {
deleteProject("P");
}
}
/*
* Ensures that a non existing external jar cannot be put on the classpath.
*/
public void testInvalidExternalJar() throws CoreException {
try {
String jarPath = getExternalPath() + "nonExisting.jar";
IJavaScriptProject proj = createJavaProject("P", new String[] {}, new String[] {jarPath}, "bin");
assertMarkers(
"Unexpected markers",
"Project P is missing required library: \'" + jarPath + "\'",
proj);
} finally {
deleteProject("P");
}
}
/*
* Ensures that a non existing internal jar cannot be put on the classpath.
*/
public void testInvalidInternalJar1() throws CoreException {
try {
IJavaScriptProject proj = createJavaProject("P", new String[] {}, new String[] {"/P/nonExisting.jar"}, "bin");
assertMarkers(
"Unexpected markers",
"Project P is missing required library: \'nonExisting.jar\'",
proj);
} finally {
deleteProject("P");
}
}
/*
* Ensures that a file not ending with .jar or .zip cannot be put on the classpath.
*/
public void testInvalidInternalJar2() throws CoreException {
try {
createProject("P1");
createFile("/P1/existing.txt", "");
IJavaScriptProject proj = createJavaProject("P2", new String[] {}, new String[] {"/P1/existing.txt"}, "bin");
assertMarkers(
"Unexpected markers",
"Illegal type of archive for required library: \'/P1/existing.txt\' in project P2",
proj);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/*
* Ensures that a non existing source folder cannot be put on the classpath.
* (regression test for bug 66512 Invalid classpath entry not rejected)
*/
public void testInvalidSourceFolder() throws CoreException {
try {
createJavaProject("P1");
IJavaScriptProject proj = createJavaProject("P2", new String[] {}, new String[] {}, new String[] {"/P1/src1/src2"}, "bin");
assertMarkers(
"Unexpected markers",
"Project P2 is missing required source folder: \'/P1/src1/src2\'",
proj);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/**
* Ensures that only one marker is created if building a project that is
* missing its .classpath file multiple times.
* (regression test for bug 39877 Rebuild All generates extra "Unable to read classpath" entry.)
*/
public void testMissingClasspath() throws CoreException {
try {
IJavaScriptProject javaProject = createJavaProject("P");
IProject project = javaProject.getProject();
project.close(null);
deleteFile(new File(project.getLocation().toOSString(), ".classpath"));
waitForAutoBuild();
project.open(null);
waitForAutoBuild();
project.build(IncrementalProjectBuilder.FULL_BUILD, null);
waitForAutoBuild();
project.build(IncrementalProjectBuilder.FULL_BUILD, null);
waitForAutoBuild();
assertMarkers(
"Unexpected markers",
"Unable to read \'.classpath\' file of project P",
javaProject);
} finally {
this.deleteProject("P");
}
}
/**
* Test that a marker is added when a project as a missing project in its classpath.
*/
public void testMissingPrereq1() throws CoreException {
try {
IJavaScriptProject javaProject = this.createJavaProject("A", new String[] {}, "");
IIncludePathEntry[] classpath =
new IIncludePathEntry[] {
JavaScriptCore.newProjectEntry(new Path("/B"))
};
javaProject.setRawIncludepath(classpath, null);
this.assertMarkers(
"Unexpected markers",
"Project A is missing required Java project: \'B\'",
javaProject);
} finally {
this.deleteProject("A");
}
}
/**
* Test that a marker is added when a project as a missing project in its classpath.
*/
public void testMissingPrereq2() throws CoreException {
try {
IJavaScriptProject javaProject =
this.createJavaProject(
"A",
new String[] {}, // source folders
new String[] {}, // lib folders
new String[] {"/B"}, // projects
"");
this.assertMarkers(
"Unexpected markers",
"Project A is missing required Java project: \'B\'",
javaProject);
} finally {
this.deleteProject("A");
}
}
/**
* Test that a marker indicating a missing project is removed when the project is added.
*/
public void testMissingPrereq3() throws CoreException {
try {
IJavaScriptProject javaProject =
this.createJavaProject(
"A",
new String[] {}, // source folders
new String[] {}, // lib folders
new String[] {"/B"}, // projects
"");
this.createJavaProject("B", new String[] {}, "");
this.assertMarkers("Unexpected markers", "", javaProject);
} finally {
this.deleteProjects(new String[] {"A", "B"});
}
}
/**
* Test that a marker indicating a cycle is removed when a project in the cycle is deleted
* and replaced with a missing prereq marker.
* (regression test for bug 15168 circular errors not reported)
*/
public void testMissingPrereq4() throws CoreException {
try {
IJavaScriptProject projectA =
this.createJavaProject(
"A",
new String[] {}, // source folders
new String[] {}, // lib folders
new String[] {"/B"}, // projects
"");
IJavaScriptProject projectB =
this.createJavaProject(
"B",
new String[] {}, // source folders
new String[] {}, // lib folders
new String[] {"/A"}, // projects
"");
this.assertMarkers(
"Unexpected markers for project A",
"A cycle was detected in the build path of project: A",
projectA);
this.assertMarkers(
"Unexpected markers for project B",
"A cycle was detected in the build path of project: B",
projectB);
// delete project B
this.deleteProject("B");
this.assertMarkers(
"Unexpected markers for project A after deleting of project B",
"Project A is missing required Java project: \'B\'",
projectA);
// add project B back
projectB =
this.createJavaProject(
"B",
new String[] {}, // source folders
new String[] {}, // lib folders
new String[] {"/A"}, // projects
"");
this.assertMarkers(
"Unexpected markers for project A after adding project B back",
"A cycle was detected in the build path of project: A",
projectA);
this.assertMarkers(
"Unexpected markers for project B after adding project B back",
"A cycle was detected in the build path of project: B",
projectB);
} finally {
this.deleteProjects(new String[] {"A", "B"});
}
}
/**
* Setting the classpath to null should be the same as using the
* default classpath.
*/
public void testNullClasspath() throws CoreException {
try {
IJavaScriptProject project = this.createJavaProject("P", new String[] {""}, "");
setClasspath(project, null);
IIncludePathEntry[] cp= project.getRawIncludepath();
assertTrue("classpath should have one root entry", cp.length == 1 && cp[0].getPath().equals(project.getUnderlyingResource().getFullPath()));
} finally {
this.deleteProject("P");
}
}
/**
* Ensure that reading an empty custom output from the .classpath returns a non-null output location.
* (regression test for 28531 Classpath Entry: Output folder can not be set to project)
*/
public void testReadEmptyCustomOutput() throws CoreException {
try {
IJavaScriptProject project = this.createJavaProject("P", new String[] {}, "");
this.editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" output=\"\" path=\"\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
IIncludePathEntry[] classpath = project.getRawIncludepath();
assertEquals("Unexpected classpath length", 1, classpath.length);
assertEquals("Unexpected custom output location", new Path("/P"), classpath[0].getOutputLocation());
} finally {
this.deleteProject("P");
}
}
/*
* Ensures that setting the 'combineAccessRules' flag to false on a project entry generates the correct .classpath file.
*/
public void testCombineAccessRules1() throws CoreException {
try {
createJavaProject("P1");
IJavaScriptProject project = createJavaProject("P2");
IIncludePathEntry entry = JavaScriptCore.newProjectEntry(new Path("/P1"), (IAccessRule[]) null, false/*don't combine*/, new IIncludePathAttribute[] {}, false);
project.setRawIncludepath(new IIncludePathEntry[] {entry}, null);
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P2/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry combineaccessrules=\"false\" kind=\"src\" path=\"/P1\"/>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/*
* Ensures that setting the 'combineAccessRules' flag to true on a project entry generates the correct .classpath file.
*/
public void testCombineAccessRules2() throws CoreException {
try {
createJavaProject("P1");
IJavaScriptProject project = createJavaProject("P2");
IIncludePathEntry entry = JavaScriptCore.newProjectEntry(new Path("/P1"), (IAccessRule[]) null, true/*combine*/, new IIncludePathAttribute[] {}, false);
project.setRawIncludepath(new IIncludePathEntry[] {entry}, null);
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P2/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"/P1\"/>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/*
* Ensures that 'combineAccessRules' flag in a .classpath file is correctly read.
*/
public void testCombineAccessRules3() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P2");
editFile(
"/P2/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" combineaccessrules=\"false\" path=\"/P1\"/>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n"
);
assertClasspathEquals(
project.getRawIncludepath(),
"/P1[CPE_PROJECT][K_SOURCE][isExported:false][combine access rules:false]"
);
} finally {
deleteProject("P2");
}
}
/*
* Ensures that the absence of 'combineAccessRules' flag in a .classpath file is correctly handled.
*/
public void testCombineAccessRules4() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P2");
editFile(
"/P2/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"/P1\"/>\n" +
" <classpathentry kind=\"output\" path=\"\"/>\n" +
"</classpath>\n"
);
assertClasspathEquals(
project.getRawIncludepath(),
"/P1[CPE_PROJECT][K_SOURCE][isExported:false][combine access rules:true]"
);
} finally {
deleteProject("P2");
}
}
/*
* Ensures that the absence of 'combineAccessRules' flag in a .classpath file is correctly handled.
*/
public void testCombineAccessRules5() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P2");
editFile(
"/P2/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n"
);
assertClasspathEquals(
project.getRawIncludepath(),
"/P2/src[CPE_SOURCE][K_SOURCE][isExported:false]"
);
} finally {
deleteProject("P2");
}
}
public void testCycleDetection() throws CoreException {
int max = 5;
IJavaScriptProject[] p = new IJavaScriptProject[max];
String[] projectNames = new String[max];
try {
for (int i = 0; i < max; i++) {
projectNames[i] = "P"+i;
p[i] = this.createJavaProject(projectNames[i], new String[] {""}, "");
}
IIncludePathEntry[][] extraEntries = new IIncludePathEntry[][]{
{ JavaScriptCore.newProjectEntry(p[1].getPath()), JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newProjectEntry(p[2].getPath()), JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newProjectEntry(p[1].getPath()) },
{ JavaScriptCore.newProjectEntry(p[4].getPath())},
{ JavaScriptCore.newProjectEntry(p[3].getPath()), JavaScriptCore.newProjectEntry(p[0].getPath()) }
};
int[][] expectedCycleParticipants = new int[][] {
{ 0, 0, 0, 0, 0 }, // after setting CP p[0]
{ 0, 0, 0, 0, 0 }, // after setting CP p[1]
{ 0, 1, 1, 0, 0 }, // after setting CP p[2]
{ 0, 1, 1, 0, 0 }, // after setting CP p[3]
{ 1, 1, 1, 1, 1 }, // after setting CP p[4]
};
for (int i = 0; i < p.length; i++){
// append project references
IIncludePathEntry[] oldClasspath = p[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries[i].length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries[i].length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[i][j];
}
// set classpath
p[i].setRawIncludepath(newClasspath, null);
// check cycle markers
this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]);
}
//this.startDeltas();
} finally {
this.deleteProjects(projectNames);
}
}
public void testCycleDetectionThroughVariables() throws CoreException {
int max = 5;
IJavaScriptProject[] p = new IJavaScriptProject[max];
String[] projectNames = new String[max];
try {
for (int i = 0; i < max; i++) {
projectNames[i] = "P"+i;
p[i] = this.createJavaProject(projectNames[i], new String[] {""}, "");
}
String[] var = new String[]{ "v0", "v1", "v2"};
IIncludePathEntry[][] extraEntries = new IIncludePathEntry[][]{
{ JavaScriptCore.newProjectEntry(p[1].getPath()), JavaScriptCore.newVariableEntry(new Path(var[0]), null, null) },
{ JavaScriptCore.newProjectEntry(p[2].getPath()), JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newVariableEntry(new Path(var[1]), null, null) },
{ JavaScriptCore.newVariableEntry(new Path(var[2]), null, null)},
{ JavaScriptCore.newProjectEntry(p[3].getPath()), JavaScriptCore.newProjectEntry(p[0].getPath()) }
};
int[][] expectedCycleParticipants = new int[][] {
{ 0, 0, 0, 0, 0 }, // after setting CP p[0]
{ 0, 0, 0, 0, 0 }, // after setting CP p[1]
{ 0, 0, 0, 0, 0 }, // after setting CP p[2]
{ 0, 0, 0, 0, 0 }, // after setting CP p[3]
{ 1, 1, 1, 1, 1 }, // after setting CP p[4]
};
IPath[][] variableValues = new IPath[][]{
{ null, null, null },
{ null, null, null },
{ null, null, null },
{ null, null, null },
{ p[3].getPath(), p[1].getPath(), p[4].getPath() },
};
for (int i = 0; i < p.length; i++){
// append project references
IIncludePathEntry[] oldClasspath = p[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries[i].length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries[i].length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[i][j];
}
// set classpath
p[i].setRawIncludepath(newClasspath, null);
// update variable values
JavaScriptCore.setIncludepathVariables(var, variableValues[i], null);
// check cycle markers
this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]);
}
//this.startDeltas();
} finally {
//this.stopDeltas();
this.deleteProjects(projectNames);
}
}
public void testCycleDetectionThroughContainers() throws CoreException {
int max = 5;
IJavaScriptProject[] p = new IJavaScriptProject[max];
String[] projectNames = new String[max];
try {
for (int i = 0; i < max; i++) {
projectNames[i] = "P"+i;
p[i] = this.createJavaProject(projectNames[i], new String[] {""}, "");
}
IJsGlobalScopeContainer[] containers = new IJsGlobalScopeContainer[]{
new TestContainer(
new Path("container0/default"),
new IIncludePathEntry[]{ JavaScriptCore.newProjectEntry(p[3].getPath()) }),
new TestContainer(
new Path("container1/default"),
new IIncludePathEntry[]{ JavaScriptCore.newProjectEntry(p[1].getPath()) }),
new TestContainer(
new Path("container2/default"),
new IIncludePathEntry[]{ JavaScriptCore.newProjectEntry(p[4].getPath()) }),
};
IIncludePathEntry[][] extraEntries = new IIncludePathEntry[][]{
{ JavaScriptCore.newProjectEntry(p[1].getPath()), JavaScriptCore.newContainerEntry(containers[0].getPath()) },
{ JavaScriptCore.newProjectEntry(p[2].getPath()), JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newContainerEntry(containers[1].getPath()) },
{ JavaScriptCore.newContainerEntry(containers[2].getPath())},
{ JavaScriptCore.newProjectEntry(p[3].getPath()), JavaScriptCore.newProjectEntry(p[0].getPath()) }
};
int[][] expectedCycleParticipants = new int[][] {
{ 0, 0, 0, 0, 0 }, // after setting CP p[0]
{ 0, 0, 0, 0, 0 }, // after setting CP p[1]
{ 0, 0, 0, 0, 0 }, // after setting CP p[2]
{ 0, 0, 0, 0, 0 }, // after setting CP p[3]
{ 1, 1, 1, 1, 1 }, // after setting CP p[4]
};
for (int i = 0; i < p.length; i++){
// append project references
IIncludePathEntry[] oldClasspath = p[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries[i].length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries[i].length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[i][j];
}
// set classpath
p[i].setRawIncludepath(newClasspath, null);
// update container paths
if (i == p.length - 1){
JavaScriptCore.setJsGlobalScopeContainer(
containers[0].getPath(),
new IJavaScriptProject[]{ p[0] },
new IJsGlobalScopeContainer[] { containers[0] },
null);
JavaScriptCore.setJsGlobalScopeContainer(
containers[1].getPath(),
new IJavaScriptProject[]{ p[2] },
new IJsGlobalScopeContainer[] { containers[1] },
null);
JavaScriptCore.setJsGlobalScopeContainer(
containers[2].getPath(),
new IJavaScriptProject[]{ p[3] },
new IJsGlobalScopeContainer[] { containers[2] },
null);
}
// check cycle markers
this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]);
}
//this.startDeltas();
} finally {
//this.stopDeltas();
this.deleteProjects(projectNames);
}
}
public void testCycleDetectionThroughContainerVariants() throws CoreException {
int max = 5;
IJavaScriptProject[] p = new IJavaScriptProject[max];
String[] projectNames = new String[max];
try {
for (int i = 0; i < max; i++) {
projectNames[i] = "P"+i;
p[i] = this.createJavaProject(projectNames[i], new String[] {""}, "");
}
class LocalTestContainer implements IJsGlobalScopeContainer {
IPath path;
IIncludePathEntry[] entries;
LocalTestContainer(IPath path, IIncludePathEntry[] entries){
this.path = path;
this.entries = entries;
}
public IPath getPath() { return this.path; }
/**
* @deprecated Use {@link #getIncludepathEntries()} instead
*/
public IIncludePathEntry[] getClasspathEntries() {
return getIncludepathEntries();
}
public IIncludePathEntry[] getIncludepathEntries() { return this.entries; }
public String getDescription() { return null; }
public int getKind() { return 0; }
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainer#resolvedLibraryImport(java.lang.String)
*/
public String[] resolvedLibraryImport(String a) {
return new String[] {a};
}
}
IJsGlobalScopeContainer[] containers = new IJsGlobalScopeContainer[]{
new LocalTestContainer(
new Path("container0/default"),
new IIncludePathEntry[]{ JavaScriptCore.newProjectEntry(p[3].getPath()) }),
new LocalTestContainer(
new Path("container0/default"),
new IIncludePathEntry[]{ JavaScriptCore.newProjectEntry(p[1].getPath()) }),
new LocalTestContainer(
new Path("container0/default"),
new IIncludePathEntry[]{ JavaScriptCore.newProjectEntry(p[4].getPath()) }),
};
IIncludePathEntry[][] extraEntries = new IIncludePathEntry[][]{
{ JavaScriptCore.newProjectEntry(p[1].getPath()), JavaScriptCore.newContainerEntry(containers[0].getPath()) },
{ JavaScriptCore.newProjectEntry(p[2].getPath()), JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newContainerEntry(containers[1].getPath()) },
{ JavaScriptCore.newContainerEntry(containers[2].getPath())},
{ JavaScriptCore.newProjectEntry(p[3].getPath()), JavaScriptCore.newProjectEntry(p[0].getPath()) }
};
int[][] expectedCycleParticipants = new int[][] {
{ 0, 0, 0, 0, 0 }, // after setting CP p[0]
{ 0, 0, 0, 0, 0 }, // after setting CP p[1]
{ 0, 0, 0, 0, 0 }, // after setting CP p[2]
{ 0, 0, 0, 0, 0 }, // after setting CP p[3]
{ 1, 1, 1, 1, 1 }, // after setting CP p[4]
};
for (int i = 0; i < p.length; i++){
// append project references
IIncludePathEntry[] oldClasspath = p[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries[i].length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries[i].length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[i][j];
}
// set classpath
p[i].setRawIncludepath(newClasspath, null);
// update same container path for multiple projects
if (i == p.length - 1){
JavaScriptCore.setJsGlobalScopeContainer(
containers[0].getPath(),
new IJavaScriptProject[]{ p[0], p[2], p[3] },
new IJsGlobalScopeContainer[] { containers[0], containers[1], containers[2] },
null);
}
// check cycle markers
this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]);
}
//this.startDeltas();
} finally {
//this.stopDeltas();
this.deleteProjects(projectNames);
}
}
public void testCycleDetection2() throws CoreException {
int max = 5;
IJavaScriptProject[] p = new IJavaScriptProject[max];
String[] projectNames = new String[max];
try {
for (int i = 0; i < max; i++) {
projectNames[i] = "P"+i;
p[i] = this.createJavaProject(projectNames[i], new String[] {""}, "");
}
IIncludePathEntry[][] extraEntries = new IIncludePathEntry[][]{
{ JavaScriptCore.newProjectEntry(p[1].getPath()), JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newProjectEntry(p[2].getPath()) },
{ JavaScriptCore.newProjectEntry(p[0].getPath()) },
{ JavaScriptCore.newProjectEntry(p[4].getPath())},
{ JavaScriptCore.newProjectEntry(p[0].getPath()) }
};
int[][] expectedCycleParticipants = new int[][] {
{ 0, 0, 0, 0, 0 }, // after setting CP p[0]
{ 0, 0, 0, 0, 0 }, // after setting CP p[1]
{ 1, 1, 1, 0, 0 }, // after setting CP p[2]
{ 1, 1, 1, 0, 0 }, // after setting CP p[3]
{ 1, 1, 1, 1, 1 }, // after setting CP p[4]
};
for (int i = 0; i < p.length; i++){
// append project references
IIncludePathEntry[] oldClasspath = p[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries[i].length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries[i].length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[i][j];
}
// set classpath
p[i].setRawIncludepath(newClasspath, null);
// check cycle markers
this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]);
}
//this.startDeltas();
} finally {
//this.stopDeltas();
this.deleteProjects(projectNames);
}
}
public void testCycleDetection3() throws CoreException {
int max = 6;
IJavaScriptProject[] p = new IJavaScriptProject[max];
String[] projectNames = new String[max];
try {
for (int i = 0; i < max; i++) {
projectNames[i] = "P"+i;
p[i] = this.createJavaProject(projectNames[i], new String[] {""}, "");
}
IIncludePathEntry[][] extraEntries = new IIncludePathEntry[][]{
{ JavaScriptCore.newProjectEntry(p[2].getPath()), JavaScriptCore.newProjectEntry(p[4].getPath()) },
{ JavaScriptCore.newProjectEntry(p[0].getPath()) },
{ JavaScriptCore.newProjectEntry(p[3].getPath()) },
{ JavaScriptCore.newProjectEntry(p[1].getPath())},
{ JavaScriptCore.newProjectEntry(p[5].getPath()) },
{ JavaScriptCore.newProjectEntry(p[1].getPath()) }
};
int[][] expectedCycleParticipants = new int[][] {
{ 0, 0, 0, 0, 0, 0 }, // after setting CP p[0]
{ 0, 0, 0, 0, 0, 0 }, // after setting CP p[1]
{ 0, 0, 0, 0, 0, 0 }, // after setting CP p[2]
{ 1, 1, 1, 1, 0, 0 }, // after setting CP p[3]
{ 1, 1, 1, 1, 0, 0 }, // after setting CP p[4]
{ 1, 1, 1, 1, 1 , 1}, // after setting CP p[5]
};
for (int i = 0; i < p.length; i++){
// append project references
IIncludePathEntry[] oldClasspath = p[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries[i].length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries[i].length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[i][j];
}
// set classpath
p[i].setRawIncludepath(newClasspath, null);
// check cycle markers
this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]);
}
//this.startDeltas();
} finally {
//this.stopDeltas();
this.deleteProjects(projectNames);
}
}
/*
* Ensures that a cycle is detected if introduced during a post-change event.
* (regression test for bug 113051 No classpath marker produced when cycle through PDE container)
*/
public void testCycleDetection4() throws CoreException {
IResourceChangeListener listener = new IResourceChangeListener() {
boolean containerNeedUpdate = true;
public void resourceChanged(IResourceChangeEvent event) {
if (containerNeedUpdate) {
TestContainer container = new TestContainer(
new Path("org.eclipse.wst.jsdt.core.tests.model.container/default"),
new IIncludePathEntry[] { JavaScriptCore.newProjectEntry(new Path("/P1")) });
try {
JavaScriptCore.setJsGlobalScopeContainer(container.getPath(), new IJavaScriptProject[] {getJavaProject("P2")}, new IJsGlobalScopeContainer[] {container}, null);
} catch (JavaScriptModelException e) {
e.printStackTrace();
}
containerNeedUpdate = false;
}
}
};
try {
IJavaScriptProject p1 = createJavaProject("P1", new String[] {}, new String[] {}, new String[] {"/P2"}, "");
TestContainer container = new TestContainer(
new Path("org.eclipse.wst.jsdt.core.tests.model.container/default"),
new IIncludePathEntry[] {});
IJavaScriptProject p2 = createJavaProject("P2", new String[] {}, new String[] {container.getPath().toString()}, "");
JavaScriptCore.setJsGlobalScopeContainer(container.getPath(), new IJavaScriptProject[] {p2}, new IJsGlobalScopeContainer[] {container}, null);
waitForAutoBuild();
getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
createFile("/P1/test.txt", "");
assertCycleMarkers(p1, new IJavaScriptProject[] {p1, p2}, new int[] {1, 1});
} finally {
getWorkspace().removeResourceChangeListener(listener);
deleteProjects(new String[] {"P1", "P2"});
}
}
public void testPerfDenseCycleDetection1() throws CoreException {
// each project prereqs all other projects
denseCycleDetection(5);
}
public void testPerfDenseCycleDetection2() throws CoreException {
// each project prereqs all other projects
denseCycleDetection(10);
}
public void testPerfDenseCycleDetection3() throws CoreException {
// each project prereqs all other projects
denseCycleDetection(20);
}
/*
* Create projects and set classpaths in one batch
*/
public void testNoCycleDetection1() throws CoreException {
// each project prereqs all the previous ones
noCycleDetection(5, false, false);
noCycleDetection(10, false, false);
noCycleDetection(20, false, false);
// each project prereqs all the next ones
noCycleDetection(5, true, false);
noCycleDetection(10, true, false);
noCycleDetection(20, true, false);
}
/*
* Create projects first, then set classpaths
*/
public void testNoCycleDetection2() throws CoreException {
// each project prereqs all the previous ones
noCycleDetection(5, false, true);
noCycleDetection(10, false, true);
noCycleDetection(20, false, true);
// each project prereqs all the next ones
noCycleDetection(5, true, true);
noCycleDetection(10, true, true);
noCycleDetection(20, true, true);
}
/*
* Ensures that the .classpath file is not written to disk when setting the raw classpath with no resource change.
*/
public void testNoResourceChange01() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {"src1"}, "bin");
IIncludePathEntry[] newClasspath = createClasspath("P", new String[] {"/P/src2", ""});
project.setRawIncludepath(newClasspath, false/*cannot modify resources*/, null/*no progress*/);
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src1\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that the in-memory classpath is correct when setting the raw classpath with no resource change.
*/
public void testNoResourceChange02() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {"src1"}, "bin");
IIncludePathEntry[] newClasspath = createClasspath("P", new String[] {"/P/src2", ""});
project.setRawIncludepath(newClasspath, false/*cannot modify resources*/, null/*no progress*/);
assertClasspathEquals(
project.getRawIncludepath(),
"/P/src2[CPE_SOURCE][K_SOURCE][isExported:false]"
);
} finally {
deleteProject("P");
}
}
/*
* Ensures that a compilation unit on the old classpath doesn't exist after setting a new raw classpath with no resource change.
*/
public void testNoResourceChange03() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {"src1"}, "bin");
createFile(
"/P/src1/X.js",
"public class X {\n" +
"}"
);
IJavaScriptUnit cu = getCompilationUnit("/P/src1/X.js");
cu.open(null);
IIncludePathEntry[] newClasspath = createClasspath("P", new String[] {"/P/src2", ""});
project.setRawIncludepath(newClasspath, false/*cannot modify resources*/, null/*no progress*/);
assertFalse("Compilation unit should not exist", cu.exists());
} finally {
deleteProject("P");
}
}
/*
* Ensures that the delta is correct when setting a new raw classpath with no resource change.
*/
public void testNoResourceChange04() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {"src1"}, "bin");
createFolder("/P/src2");
IIncludePathEntry[] newClasspath = createClasspath("P", new String[] {"/P/src2", ""});
startDeltas();
project.setRawIncludepath(newClasspath, false/*cannot modify resources*/, null/*no progress*/);
assertDeltas(
"Unexpected delta",
"P[*]: {CHILDREN | CLASSPATH CHANGED}\n" +
" src1[*]: {REMOVED FROM CLASSPATH}\n" +
" src2[*]: {ADDED TO CLASSPATH}"
);
} finally {
stopDeltas();
deleteProject("P");
}
}
/*
* Ensures that the in-memory output is correct when setting the output with no resource change.
*/
public void testNoResourceChange05() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P", new String[] {"src1"}, "bin");
project.setRawIncludepath(project.getRawIncludepath(), new Path("/P/bin2"), false/*cannot modify resources*/, null/*no progress*/);
assertEquals(
"/P/bin2",
project.getOutputLocation().toString());
} finally {
deleteProject("P");
}
}
/**
* Ensures that a duplicate entry created by editing the .classpath is detected.
* (regression test for bug 24498 Duplicate entries on classpath cause CP marker to no longer refresh)
*/
public void testDuplicateEntries() throws CoreException {
try {
IJavaScriptProject project = this.createJavaProject("P", new String[] {"src"}, "bin");
this.editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src\"/>\n" +
" <classpathentry kind=\"src\" path=\"src\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
assertMarkers(
"Unexpected markers",
"Build path contains duplicate entry: \'src\' for project P",
project);
} finally {
this.deleteProject("P");
}
}
private void denseCycleDetection(final int numberOfParticipants) throws CoreException {
final IJavaScriptProject[] projects = new IJavaScriptProject[numberOfParticipants];
final String[] projectNames = new String[numberOfParticipants];
final int[] allProjectsInCycle = new int[numberOfParticipants];
try {
JavaScriptCore.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
for (int i = 0; i < numberOfParticipants; i++){
projectNames[i] = "P"+i;
projects[i] = createJavaProject(projectNames[i], new String[]{""}, "");
allProjectsInCycle[i] = 1;
}
for (int i = 0; i < numberOfParticipants; i++){
IIncludePathEntry[] extraEntries = new IIncludePathEntry[numberOfParticipants-1];
int index = 0;
for (int j = 0; j < numberOfParticipants; j++){
if (i == j) continue;
extraEntries[index++] = JavaScriptCore.newProjectEntry(projects[j].getPath());
}
// append project references
IIncludePathEntry[] oldClasspath = projects[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries.length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries.length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[j];
}
// set classpath
projects[i].setRawIncludepath(newClasspath, null);
}
}
},
null);
for (int i = 0; i < numberOfParticipants; i++){
// check cycle markers
this.assertCycleMarkers(projects[i], projects, allProjectsInCycle);
}
} finally {
this.deleteProjects(projectNames);
}
}
/*
* When using forward references, all projects prereq all of the ones which have a greater index,
* e.g. P0, P1, P2: P0 prereqs {P1, P2}, P1 prereqs {P2}, P2 prereqs {}
* When no using forward references (i.e. backward refs), all projects prereq projects with smaller index
* e.g. P0, P1, P2: P0 prereqs {}, P1 prereqs {P0}, P2 prereqs {P0, P1}
*/
private void noCycleDetection(final int numberOfParticipants, final boolean useForwardReferences, final boolean createProjectsFirst) throws CoreException {
final IJavaScriptProject[] projects = new IJavaScriptProject[numberOfParticipants];
final String[] projectNames = new String[numberOfParticipants];
final int[] allProjectsInCycle = new int[numberOfParticipants];
final long[] start = new long[1];
final long[] time = new long[1];
try {
if (createProjectsFirst) {
JavaScriptCore.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
for (int i = 0; i < numberOfParticipants; i++){
projectNames[i] = "P"+i;
projects[i] = createJavaProject(projectNames[i], new String[]{""}, "");
allProjectsInCycle[i] = 0;
}
}
},
null);
}
JavaScriptCore.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
if (!createProjectsFirst) {
for (int i = 0; i < numberOfParticipants; i++){
projectNames[i] = "P"+i;
projects[i] = createJavaProject(projectNames[i], new String[]{""}, "");
allProjectsInCycle[i] = 0;
}
}
for (int i = 0; i < numberOfParticipants; i++){
IIncludePathEntry[] extraEntries = new IIncludePathEntry[useForwardReferences ? numberOfParticipants - i -1 : i];
int index = 0;
for (int j = useForwardReferences ? i+1 : 0;
useForwardReferences ? (j < numberOfParticipants) : (j < i);
j++){
extraEntries[index++] = JavaScriptCore.newProjectEntry(projects[j].getPath());
}
// append project references
IIncludePathEntry[] oldClasspath = projects[i].getRawIncludepath();
IIncludePathEntry[] newClasspath = new IIncludePathEntry[oldClasspath.length+extraEntries.length];
System.arraycopy(oldClasspath, 0 , newClasspath, 0, oldClasspath.length);
for (int j = 0; j < extraEntries.length; j++){
newClasspath[oldClasspath.length+j] = extraEntries[j];
}
// set classpath
long innerStart = System.currentTimeMillis(); // time spent in individual CP setting
projects[i].setRawIncludepath(newClasspath, null);
time[0] += System.currentTimeMillis() - innerStart;
}
start[0] = System.currentTimeMillis(); // time spent in delta refresh
}
},
null);
time[0] += System.currentTimeMillis()-start[0];
//System.out.println("No cycle check ("+numberOfParticipants+" participants) : "+ time[0]+" ms, "+ (useForwardReferences ? "forward references" : "backward references") + ", " + (createProjectsFirst ? "two steps (projects created first, then classpaths are set)" : "one step (projects created and classpaths set in one batch)"));
for (int i = 0; i < numberOfParticipants; i++){
// check cycle markers
this.assertCycleMarkers(projects[i], projects, allProjectsInCycle);
}
} finally {
this.deleteProjects(projectNames);
}
}
/*
* test for bug 32690
* simulate checkout of project with invalid classpath
*/
public void testNestedSourceFolders() throws CoreException, IOException {
try {
// create project using Platform/Resources API
final IProject project = getProject("P");
IWorkspaceRunnable create = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
project.create(null, null);
project.open(null);
}
};
getWorkspace().run(create, null);
// create folders src and src/src2 using java.io API
File pro = project.getLocation().toFile();
File src = createFolder(pro, "src");
createFolder(src, "src2");
// create .project using java.io API
createFile(pro, ".project",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<projectDescription>\n" +
" <name>org.eclipse.wst.jsdt.core</name>\n" +
" <comment></comment>\n" +
" <projects>\n" +
" </projects>\n" +
" <buildSpec>\n" +
" <buildCommand>\n" +
" <name>org.eclipse.wst.jsdt.core.javabuilder</name>\n" +
" <arguments>\n" +
" </arguments>\n" +
" </buildCommand>\n" +
" </buildSpec>\n" +
" <natures>\n" +
" <nature>org.eclipse.wst.jsdt.core.javanature</nature>\n" +
" </natures>\n" +
"</projectDescription>");
// create .classpath using java.io API
createFile(pro, ".classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src\"/>\n" +
" <classpathentry kind=\"src\" path=\"src/src2\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
// refresh
project.refreshLocal(IResource.DEPTH_INFINITE, null);
assertMarkers(
"Unexpected markers",
"Cannot nest \'P/src/src2\' inside \'P/src\'. To enable the nesting exclude \'src2/\' from \'P/src\'",
JavaScriptCore.create(project));
} finally {
deleteProject("P");
}
}
/*
* Ensures that no problems are reported for an optional source entry with no corresponding folder.
*/
public void testOptionalEntry1() throws CoreException {
try {
IJavaScriptProject javaProject = this.createJavaProject("A", new String[] {}, "");
IIncludePathAttribute attribute = JavaScriptCore.newIncludepathAttribute(IIncludePathAttribute.OPTIONAL, "true");
IIncludePathEntry[] classpath =
new IIncludePathEntry[] {
JavaScriptCore.newSourceEntry(new Path("/A/src"), new IPath[0], new IPath[0], new Path("/A/bin"), new IIncludePathAttribute[] {attribute})
};
javaProject.setRawIncludepath(classpath, null);
assertMarkers(
"Unexpected markers",
"",
javaProject);
} finally {
this.deleteProject("A");
}
}
/*
* Ensures that no problems are reported for an optional libary entry with no corresponding folder.
*/
public void testOptionalEntry2() throws CoreException {
try {
IJavaScriptProject javaProject = this.createJavaProject("A", new String[] {}, "");
IIncludePathAttribute attribute = JavaScriptCore.newIncludepathAttribute(IIncludePathAttribute.OPTIONAL, "true");
IIncludePathEntry[] classpath =
new IIncludePathEntry[] {
JavaScriptCore.newLibraryEntry(new Path("/A/lib"), null, null, null, new IIncludePathAttribute[] {attribute}, false)
};
javaProject.setRawIncludepath(classpath, null);
assertMarkers(
"Unexpected markers",
"",
javaProject);
} finally {
this.deleteProject("A");
}
}
/*
* Ensures that no problems are reported for an optional project entry with no corresponding project.
*/
public void testOptionalEntry3() throws CoreException {
try {
IJavaScriptProject javaProject = this.createJavaProject("A", new String[] {}, "");
IIncludePathAttribute attribute = JavaScriptCore.newIncludepathAttribute(IIncludePathAttribute.OPTIONAL, "true");
IIncludePathEntry[] classpath =
new IIncludePathEntry[] {
JavaScriptCore.newProjectEntry(new Path("/B"), null/*no access rules*/, false/*don't combine access rule*/, new IIncludePathAttribute[] {attribute}, false/*not exported*/)
};
javaProject.setRawIncludepath(classpath, null);
assertMarkers(
"Unexpected markers",
"",
javaProject);
} finally {
this.deleteProject("A");
}
}
/*
* test for bug 32974
*/
public void testOutputFolder1() throws CoreException, IOException {
try {
// create project using Platform/Resources API
final IProject project = getProject("P");
IWorkspaceRunnable create = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
project.create(null, null);
project.open(null);
}
};
getWorkspace().run(create, null);
// create folders src and src/src2 using java.io API
File pro = project.getLocation().toFile();
File src = createFolder(pro, "src");
createFolder(src, "src2");
// create .project using java.io API
createFile(pro, ".project",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<projectDescription>\n" +
" <name>org.eclipse.wst.jsdt.core</name>\n" +
" <comment></comment>\n" +
" <projects>\n" +
" </projects>\n" +
" <buildSpec>\n" +
" <buildCommand>\n" +
" <name>org.eclipse.wst.jsdt.core.javabuilder</name>\n" +
" <arguments>\n" +
" </arguments>\n" +
" </buildCommand>\n" +
" </buildSpec>\n" +
" <natures>\n" +
" <nature>org.eclipse.wst.jsdt.core.javanature</nature>\n" +
" </natures>\n" +
"</projectDescription>");
// create .classpath using java.io API
createFile(pro, ".classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" output=\"bin2\" path=\"src1\"/>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
// refresh
project.refreshLocal(IResource.DEPTH_INFINITE,null);
assertMarkers(
"Unexpected markers",
"Project P is missing required source folder: \'src1\'\n" +
"Project P is missing required source folder: \'src2\'",
JavaScriptCore.create(project));
} finally {
deleteProject("P");
}
}
/**
* Ensure classpath is refreshed when project is replaced (43670)
*/
public void testReplaceProject() throws CoreException {
try {
final IJavaScriptProject javaProject = createJavaProject("P", new String[] {"src"}, "bin");
ResourcesPlugin.getWorkspace().run(
new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IProjectDescription descr = javaProject.getProject().getDescription();
descr.setComment("dummy"); // ensure it is changed
javaProject.getProject().setDescription(descr, monitor);
editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
}
},
null);
IIncludePathEntry[] classpath = javaProject.getRawIncludepath();
assertEquals("classpath should have been refreshed", new Path("/P/src2"), classpath[0].getPath());
} finally {
deleteProject("P");
}
}
/*
* Ensures that unknown classpath attributes in a .classpath file are not lost when read and rewritten.
* (regression test for bug 101425 Classpath persistence should be resilient with unknown attributes)
*/
public void testUnknownAttributes() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry unknown=\"test\" kind=\"src\" path=\"src1\"/>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n"
);
IIncludePathEntry[] classpath = project.getRawIncludepath();
// swap 2 entries
IIncludePathEntry src1 = classpath[0];
classpath[0] = classpath[1];
classpath[1] = src1;
project.setRawIncludepath(classpath, null);
// check that .classpath has correct content
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"src\" path=\"src1\" unknown=\"test\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that unknown classpath elements in a .classpath file are not lost when read and rewritten.
* (regression test for bug 101425 Classpath persistence should be resilient with unknown attributes)
*/
public void testUnknownElements1() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src1\">\n" +
" <unknown>\n" +
" <test kind=\"\"/>\n" +
" </unknown>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n"
);
IIncludePathEntry[] classpath = project.getRawIncludepath();
// swap 2 entries
IIncludePathEntry src1 = classpath[0];
classpath[0] = classpath[1];
classpath[1] = src1;
project.setRawIncludepath(classpath, null);
// check that .classpath has correct content
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"src\" path=\"src1\">\n" +
" <unknown>\n" +
" <test kind=\"\"/>\n" +
" </unknown>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/*
* Ensures that unknown classpath elements in a .classpath file are not lost when read and rewritten.
* (regression test for bug 101425 Classpath persistence should be resilient with unknown attributes)
*/
public void testUnknownElements2() throws CoreException {
try {
IJavaScriptProject project = createJavaProject("P");
editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" unknownattribute=\"abcde\" path=\"src1\">\n" +
" <unknown1>\n" +
" <test kind=\"1\"/>\n" +
" <test kind=\"2\"/>\n" +
" </unknown1>\n" +
" <unknown2 attribute2=\"\">\n" +
" <test>\n" +
" <other a=\"b\"/>\n" +
" </test>\n" +
" </unknown2>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n"
);
IIncludePathEntry[] classpath = project.getRawIncludepath();
// swap 2 entries
IIncludePathEntry src1 = classpath[0];
classpath[0] = classpath[1];
classpath[1] = src1;
project.setRawIncludepath(classpath, null);
// check that .classpath has correct content
String contents = new String (org.eclipse.wst.jsdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
assertSourceEquals(
"Unexpected content",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src2\"/>\n" +
" <classpathentry kind=\"src\" path=\"src1\" unknownattribute=\"abcde\">\n" +
" <unknown1>\n" +
" <test kind=\"1\"/>\n" +
" <test kind=\"2\"/>\n" +
" </unknown1>\n" +
" <unknown2 attribute2=\"\">\n" +
" <test>\n" +
" <other a=\"b\"/>\n" +
" </test>\n" +
" </unknown2>\n" +
" </classpathentry>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>\n",
contents);
} finally {
deleteProject("P");
}
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
* Check that Assert.AssertionFailedException exception is well catched
* a) when verifying a classpath entry
* b) when verifying whole classpath
*/
public void testBug55992a() throws CoreException {
try {
IJavaScriptProject proj = this.createJavaProject("P", new String[] {}, "");
IPath path = getExternalJCLPath();
IPath sourceAttachmentPath = new Path("jclMin.zip");
JavaScriptCore.setIncludepathVariables(
new String[] {"TEST_LIB", "TEST_SRC"},
new IPath[] {path, sourceAttachmentPath},
null);
ClasspathEntry cp = new ClasspathEntry(
IPackageFragmentRoot.K_SOURCE,
IIncludePathEntry.CPE_VARIABLE,
new Path("TEST_LIB"),
ClasspathEntry.INCLUDE_ALL,
ClasspathEntry.EXCLUDE_NONE,
new Path("TEST_SRC"),
null,
null, // specific output folder
false,
(IAccessRule[]) null,
false,
ClasspathEntry.NO_EXTRA_ATTRIBUTES);
IJavaScriptModelStatus status = JavaScriptConventions.validateClasspathEntry(proj, cp, false);
assertEquals(
"assertion failed: Source attachment path \'jclMin.zip\' for IIncludePathEntry must be absolute",
status.getMessage());
} finally {
this.deleteProject("P");
}
}
public void testBug55992b() throws CoreException {
boolean autoBuild = getWorkspace().isAutoBuilding();
IWorkspaceDescription preferences = getWorkspace().getDescription();
try {
preferences.setAutoBuilding(false);
IJavaScriptProject javaProject = this.createJavaProject("P", new String[] {"src", "lib"}, "bin");
JavaScriptCore.setIncludepathVariables(
new String[] {"TEST_LIB", "TEST_SRC"},
new IPath[] {new Path("/lib/tmp.jar"), new Path("tmp.zip")},
null);
this.editFile(
"/P/.classpath",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
" <classpathentry kind=\"var\" path=\"TEST_LIB\" sourcepath=\"TEST_SRC\"/>\n" +
"</classpath>"
);
assertMarkers(
"Unexpected markers",
"assertion failed: Source attachment path \'tmp.zip\' for IIncludePathEntry must be absolute",
javaProject);
} finally {
this.deleteProject("P");
preferences.setAutoBuilding(autoBuild);
}
}
/*
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=61214
*/
public void testRemoveDuplicates() throws CoreException {
try {
IJavaScriptProject p1 = this.createJavaProject("P1", new String[] {""}, "");
IIncludePathEntry[] p1ClasspathEntries = new IIncludePathEntry[]{JavaScriptCore.newLibraryEntry(getExternalJCLPath(), null, null, true)};
setClasspath(p1, p1ClasspathEntries);
IJavaScriptProject p2 = this.createJavaProject("P2", new String[] {""}, "");
IIncludePathEntry[] p2ClasspathEntries = new IIncludePathEntry[]{
JavaScriptCore.newProjectEntry(new Path("/P1")),
JavaScriptCore.newLibraryEntry(getExternalJCLPath(), null, null, false)
};
setClasspath(p2, p2ClasspathEntries);
IIncludePathEntry[] classpath = ((JavaProject)p2).getExpandedClasspath();
assertEquals("Unexpected number of classpath entries", 2, classpath.length);
assertEquals("Unexpected first entry", "/P1", classpath[0].getPath().toString());
assertEquals("Unexpected second entry", getExternalJCLPathString(), classpath[1].getPath().toOSString());
} finally {
this.deleteProjects(new String[] {"P1", "P2"});
}
}
}